Ik ben bezig een RISC-V cpu emulator te schrijven in gcc die niet afhankelijk is van de CPU architectuur waar de emulator op draait.
Doel is om een RV32I CPU met G en C extensies te maken en het op een 8-bit AVR te draaien. Een RV32I voor een bejaarde AT90S8535 CPU neemt 4620 bytes (van 8K) flash in beslag. Alle extensies die ik nu gemaakt heb (RV32IMACZicsr_Zifencei_Zba_Zbb_Zbc_Zbs) kost 14398 bytes flash in een minder bejaarde ATmega1284P.
Een half jaar geleden had ik een testje gedaan en van de 20MHz klok op de AVR bleef ongeveer 80kHz over in de ge-emuleerde 32 bit risc-v CPU. De emulator is nu complexer met meer instructies dus ik vermoed dat er nog minder van die 80kHz over blijft. Ik had ook een test gedaan met een 32-bit ATSAMD21@48MHz, daar draaide de emulator ook op. Wat mij bij staat is dat die verrassend genoeg niet heel veel sneller was dan de AVR ondanks hogere kloksnelheid en het feit dat die 32-bit is.
Er bestaat een test framework genaamd riscv-arch-test die ik gebruik om mijn emulator te valideren. Het test framework vergelijkt een golden model emulator met die van mij. Daarvoor heb ik mijn emulator op Linux werkend gemaakt. 2 dagen terug waren het golden model en mijn emulator het niet eens met elkaar, bleek dat ik een klein logging bugje had ontdekt in de golden model emulator.
Wat nu? Volgende stappen zijn single en double precision floating point instructies toe te voegen.
Nog later… wellicht een toepassing verzinnen. Ik had het idee een soort zelda meets borderlands achtige gameboy game te maken op een 128x64 z/w lcd die dan draait op de eerdergenoemde bejaarde AT90S8535. Wellicht ga ik ontdekken dat de ge-emuleerde cpu daarvoor niet snel genoeg voor is.
Plaatje van de logging output van de emulator onder linux:
Plaatje van het testframework:
4 Likes
Nope, nee, poging gedaan. IEEE 754 is niet het konijnengat waar ik blijkbaar in wilde duiken.
Bij deze verklaar ik mijn risc-v emulator gereed. Het is goed genoeg en alle geïmplementeerde extensies slagen ook nog eens met de officiële tests: GitHub - riscv/riscv-arch-test: The RISC-V Architectural Certification Tests (ACTs) are a set of assembly language tests designed to certify that a design faithfully implements the RISC-V specification. · GitHub
Wat nog niet op mijn github staat, maar op een interne repository in Forgejo is een implementatie van de RISC-V emulator die op 10 verschillende maar pin-compatibele AVR microcontrollers kan draaien. Van de bejaarde at90s8535 tot en met de grootste ATmega1284P. Bij de varianten met meer dan 32kB flash kan het ook nog eens een 8MB SPI flash, 8MB SPI PSRAM, SPI SD-kaart en een 128x160 SPI TFT aansturen. Voorlopig is die randapparatuur nog allemaal met losse testjes gedaan. Maar er gaat vast ooit iets leuks uit komen.
wat een leuk project!
ik had ooit het plan om IEEE754 te implementeren via church encoding, dat is ook op een gegeven moment gestrand 
1 Like
Het risc-v test framework (GitHub - riscv/riscv-arch-test: The RISC-V Architectural Certification Tests (ACTs) are a set of assembly language tests designed to certify that a design faithfully implements the RISC-V specification. · GitHub) is aangepast van RISCOF naar ACT. Bij RISCOF werden geheugen dumps vergeleken van een risc-v golden model en je DUT (mijn emulator). ACT heeft dat versimpeld naar een .elf uitvoerbaar bestand die 1 instructie test en vervolgens PASS/FAIL via de UART output op de DUT zelf.
Ik heb mijn emulatortester (GitHub - atoomnetmarc/RISC-V-emulator-ACT: Running the riscv-arch-test against my RISC-V emulator. · GitHub) daarop aangepast. Het nieuwe test framework had gelijk een fout gevonden in mijn emulator, ik miste de Fence instructie, dat was blijkbaar onderdeel van de RV32I basis instructieset.
Ik kan nu alle permutaties van RISC-V extenties testen. Dat zijn er vandaag 2040 stuks en duurt een paar uur op mijn laptop. Echter, 100% pass.
Je kan ook een smoke-test uitvoeren, die doet een subset van de tests die al een goed beeld geven. Dat zijn er vandaag 78:
Ik heb simavr gebruikt om mijn risc-v emulator code verder te testen. simavr doet Atmega AVR microcontroller simuleren waarin weer mijn emulator draait (insert: we must go deeper quote).
Dat had resultaat, want het ACT testframework had fouten gevonden in de B-extentie, maar alleen op AVR, niet op x86_64.
Het probleem was een impliciete cast naar int. Op x86_64 is die blijkbaar 4 byte, maar op AVR is die 2 byte groot. Dan mislukken berekeningen. Een expliciete cast naar uint32_t lossen die problemen op.