Along the same lines of minimizing the amount of logic used at the cost of cycles, there's SERV which uses a bit-serial implementation with a 1-bit data path: https://github.com/olofk/serv
From time to time, I have been tempted to design a RISC-V implementation out of discrete 74xx components. Sure, there are plenty of projects out there to build your own processor from scratch like that, but most of them aren't LLVM targets!
The 32-bit datapaths and need for so many registers makes it a bit daunting to approach directly. That approach would probably end up similar in scale to a MIPS implementation I once saw done like that. (Can't find the link, but it was about half a dozen A4-sized PCBs).
Retreating to an 8-bit microcoded approach and lifting all the registers and complexity into RAM and software is a very attractive idea. Might even fit on a single Eurocard. It's not like a discrete TTL RISC-V implementation would ever be a speed demon, either way.
My last rough sketch came out to about 400 gates, excluding the flip-flops.
If one cuts even more corners, that number could come down much further. For example, an adder isn't actually necessary and can be replaced with lookup tables and bit-twiddling, again at the cost of cycles and more microcode.
That design consists of: one 4 bit counter, four 8-bit flip-flops, one quad OR gate, one dual 2-to-4 demux, and one 128 KB Flash ROM.
Including the flip-flops (and obviously excluding the Flash memory) that comes out to about 200 or so gates by my count, and the microcode/emulation program implements a fairly typical CISC 16 bit processor. It's not even all that inefficient, with under 100 cycles per instruction on average.
If you don't know of it already, you might like the book Bit-Slice Microprocessor Design written by Mick and Brick. It's written to be very AM2900 specific, but a lot of the techniques would apply to microcoded TTL processors with just a little more work on your end. And it really does a good job of exploring the space of microcoded minicomputer design in an interesting way.
I'm surprised that there aren't any specialised instructions or hardware resources to handle the RISC-V instruction decoding/dispatching. [1]
Like, sure, it's not meant to be a fast implementation, but even just a "mask byte with 0x7C and set PC to that value times 8" instruction (which in an FPGA implementation is just rearranging the wires) could save 5-6 cycles per instruction.
Is it really "microcoded" when all you're doing is writing a RISC-V emulator that runs on what looks to be a fairly standard 8 bit CPU?
The MicroChip "PolarFire SoC" FPGA chips have five 64 bit RISC-V cores (SiFive U54-MC) currently running at 600 to 667 MHz (depending on speed grade) inside. So far the only available device has 250k logic elements (LUT4 + FF) for $340 qty 1, but there are part numbers in the data sheet for other sizes in future.
I have an "Icicle" board based on this chip. The FPGA comes preconfigured to boot Linux from the included pre=programmed SD card, so you can just use it to run Linux if you don't care about FPGAs. Or you can replace or enhance the default FPGA programming.
> Is it really "microcoded" when all you're doing is writing a RISC-V emulator that runs on what looks to be a fairly standard 8 bit CPU?
Don't know, but the amount of "microcode" or emulation code required is itself a reasonable measure of an ISA's complexity. Doing an x86 that way would surely take tons more code.
Yes, an interpreter is exactly what microcoding is. See Maurice Wilkes' original paper, or the initial IBM 360 models (the lower end of which had an 8 bit CPU running the microcode), or the various VAX models etc.
In those days the microcode ROM and ALU etc was substantially faster than RAM (core). At some point SRAM became as fast as or faster than ROM and machines copied the microcode into SRAM on startup. Some machines such as the Burroughs 1700 series loaded different microcode into SRAM depending on whether you wanted to run FORTRAN or COBOL programs.
Then companies started allowing users to write their own custom instructions in microcode. See for example the VAX "Writeable Control Store" which on the 11/780 (as an option) gave users 1024 words (12 KB) for custom microcode and a microcode assembler and debugger. Some people even wrote compilers targeting this for languages such as Pascal (see for example https://apps.dtic.mil/dtic/tr/fulltext/u2/a089424.pdf)
The next step was to turn the SRAM into a cache, and make a slightly more user-friendly microcode the actual instruction set used by all compilers, and thus RISC was born.
Of course you are correct that specialised instructions to make instruction decoding easier are helpful in an ISA emulator. It would not surprise me to see RISC-V itself get an extension along those lines in the near future, to help M-mode software emulate unaligned loads and stores and other unimplemented instructions, but maybe also to help emulate other instruction sets.
> Yes, an interpreter is exactly what microcoding is.
In a sense, yes, it is indeed!
But when I think "microcode" then I think something like the 8086's horizontal microcode [1], where each line of microcode is wired directly to the various functional units and the microcode jumps and branches are (in some sense) determined based off (some of) the bits in the instruction register.
Characteristics of microcode include: wide instructions (20-40 bits) that perform multiple operations in parallel (e.g. ALU operation and register-register copy) and hardware dispatch to the appropriate microcode to handle each microcoded instruction via zero-overhead multiway branches.
I wouldn't call a 6502-like assembly language microcode, even if it implements an interpreter for a user-level instruction set, because it lacks the relevant characteristics of true CPU microcode.
I never understood the hype around RISC-V. It is an ISA on the level of a mediocre early 90s design and does not address any of the problems we have today such as the memory latency bottleneck and the resulting topology challenges. Several completely open source designs are available that are vastly superior and real world battle tested such as OpenSPARC-T2.
So why do we need RISC-V? Is it another case of NIHS?
1. RISC-V is completely unencumbered from an IP perspective. There is no possibility of a rightsholder reasserting rights on IP they had previously released (like what happened with MIPS in 2019).
2. RISC-V is legacy-free. It's an extremely "clean" design, free of weird quirks like the MIPS branch delay slot or SPARC register windows.
3. There are subsets of the RISC-V architecture defined for different sizes of systems, e.g. 32/64 bit versions, an embedded subset with fewer registers, etc. They all share an instruction set and a general architecture, and most compilers can target any subset. Some of the smaller subsets are well within the realm of what a single student can be taught to implement within a semester.
4. Numerous real implementations of RISC-V exist -- both as hardware and HDL -- are being maintained, and the hardware is available on the open market.
I'm not the one who called it that, it's nice in many ways, but being unable to trap integer overflow seems 90s to me. Integer overflow (like buffer overflow) is now recognized as a common source of bugs, but it takes several instructions to detect with risc-v. So your compiler has to generate those extra instructions after almost every integer operation to implement trapping (-ftrapv in GCC and maybe LLVM parlance). This is sort of like a cpu architecture where dereferencing a null pointer is required to return 0 rather than trap. So either you have to either generate a bunch of extra checking code, or let software bugs go undetected for much longer than necessary.
I think MIPS had a similar issue but eventually fixed it. Maybe RISCV can do similar.
RISC-V is not "unable" to trap integer overflow. They made a deliberate decision not to. And divide by zero as well.
Instructions that can trap -- but almost never do unless you have a program bug -- cause a large complication in pipelines, and especially in OoO implementations. Even a single-issue pipeline can run faster and be smaller without conditionally-trapping instructions, and as soon as you have even 2-wide execution it's just much better in every way to use explicit checks that use the same conditional branching facilities as the rest of the code.
As I remember it takes 3 extra instructions to check for arithmetic overflow after, say, an ADD instruction. Spewing those extra instructions all over the place sounds like severe code bloat to me, though I'll try to get around to checking examples sometime (gcc trapv vs wrapv). Yes, Risc-V is unable to trap on overflow and yes that was an intentional design decision. It can trap on invalid memory references and various other things, it can set flags on floating point overflow if it implements IEEE FP properly, but integer overflow is unchecked. Whether that limitation is wise or unwise is a matter of opinion, but that it is part of the architecture is just a fact.
By using a CISC instead of RISC. But this time instead of designing it for easy human assembly programming like the VAX use instructions that drastically improve memory density, make the life of the branch predictor easier and promote memory locality. Also introduce branchless instructions like cmov.
RISC-V has the C extension (compressed opcodes, similar to Thumb-2) and code density then is comparable to x86 which is the main CISC in use these days.
Well ok, I'd be interested in seeing a code density comparison between Riscv-IMC and whatever you want to compare it with. Vax density wasn't that great either, though maybe compilers back then weren't as good as now.
RISC-V doesn't even match ARM's levels when pulling extra tricks and extensions designed to improved code density. Other ISA's like AVR32 beat ARM by 50% which means it is more than possible to beat ARM. As I said, RISC-V is designed like a typical early 90s ISA when memory latency was not a concern. It will never be used in high performance general computing for that reason alone.
32 bit RISC-V code density is slightly worse than Thumb2, but better than any other 32 bit ISA I'm aware of with similar performance. I don't know much about AVR32 except that it is very dead. Some ISAs designed explicitly for microcontroller use have denser code than RISC-V and Thumb2 on things such as manipulating GPIOs, but not on algorithmic code which makes up the vast majority of any application over a few KB in size.
64 bit RISC-V code density is far better than 64 bit ARM code density, which is similar to AMD64 (i.e. quite a bit bigger than i386)
Other than a few extra instructions to zero-extend 32 bit values to 64 bits at times, 64 bit RISC-V and 32 bit RISC-V code are identical in size.
High performance general computing these days means 64 bit, and RISC-V has by far the highest code density of any 64 bit ISA.
edit I missed duskwuff's answer, which is better informed than mine. I'll leave this here anyway.
How open is OpenSPARC? Are there patent concerns?
RISC-V isn't aiming to revolutionise CPU architecture with a radical new design, it's aiming to offer a Free and Open, patent-unencumbered, fairly conventional RISC ISA. They're quite open about their emphasis on openness. [0]
For a project that aims to turn CPU design on its head, there's the Mill processor, although it's broadly thought to be vaporware.
A mediocre early 90s design that is totally unencumbered is a lot better than a mediocre late 70s design hacked beyond the limits of sanity.
Or would be.
The fact is RISC-V is a distinct improvement on early 90s designs such as MIPS III and has also learned lessons from Alpha, PowerPC, Itanium, and AMD64.
In many ways RISC-V and Aarch64 (which were being designed in parallel unknown to each other) learned the same lessons from those earlier ISAs, though they made several trade-offs differently.
The RISC approach to microprocessor design has been around since the 1980s, but the specific instruction set called "RISC-V" has only been around since 2010.
It takes years for tooling to improve and for industry designs to start making it out into the world. As more designs make it into end-users' hands, the tooling has even more motivation to improve.
I feel like that slow evolution can make it appear "suddenly popular" despite being around for a few years. =)
Design work was started on RISC-V in 2010 and an initial frozen spec was released to the public in 2015. The first proper 32 bit chip and board (HiFive1/FE310) shipped in December 2016, and the first Linux-capable 64 bit chip and board (HiFive Unleashed/FU540) in April 2018.
Glacial was one of the entries for the 2018 RISC-V SoftCPU Contest, but I think it wasn't ready by the deadline.
If you look at the winners there was another 8-bit CPU with a RISC-V interpreter, SERV, VexRiscv but also Reindeer which seems like a more balanced implementation:
https://riscv.org/blog/2018/12/risc-v-softcpu-contest-highli...
How big is your CPU. I develop on Microsemi and the PolarFire range should do it. 12G transcievers and a decent amount of logic. At about €200+. And considering Microsemi are usually behind the curve, Xilinx and Altera must have similar https://www.microsemi.com/product-directory/fpgas/3854-polar...
What do you intend to do with the 5GHz IO? Assuming it's for peripheral connectivity, then maybe the Ultra96 would work. It does not have general purpose transceivers availbals, but it has a PS (processing subsystem) that has lots of connectivity. The PL is pmenty big for many applications.
I was thinking of hooking it up to GDDR6. I've programmed an FPGA before (a couple of school projects), but never interfaced with anything serious like modern high-bandwidth memory.
That would be the ECP5UM-5G parts. The 5G variants are somewhat more exotic but the base ECP5 is supported by Yosys and readily available on Mouser for $15-20 or so
51 comments
[ 3.0 ms ] story [ 113 ms ] threadFrom time to time, I have been tempted to design a RISC-V implementation out of discrete 74xx components. Sure, there are plenty of projects out there to build your own processor from scratch like that, but most of them aren't LLVM targets!
The 32-bit datapaths and need for so many registers makes it a bit daunting to approach directly. That approach would probably end up similar in scale to a MIPS implementation I once saw done like that. (Can't find the link, but it was about half a dozen A4-sized PCBs).
Retreating to an 8-bit microcoded approach and lifting all the registers and complexity into RAM and software is a very attractive idea. Might even fit on a single Eurocard. It's not like a discrete TTL RISC-V implementation would ever be a speed demon, either way.
If one cuts even more corners, that number could come down much further. For example, an adder isn't actually necessary and can be replaced with lookup tables and bit-twiddling, again at the cost of cycles and more microcode.
See https://hackaday.io/project/161251-1-square-inch-ttl-cpu -- while not RISC-V it demonstrates some of these principles in action, taken to the extreme.
That design consists of: one 4 bit counter, four 8-bit flip-flops, one quad OR gate, one dual 2-to-4 demux, and one 128 KB Flash ROM.
Including the flip-flops (and obviously excluding the Flash memory) that comes out to about 200 or so gates by my count, and the microcode/emulation program implements a fairly typical CISC 16 bit processor. It's not even all that inefficient, with under 100 cycles per instruction on average.
I haven't synthesized it though, so I can't say for sure.
Like, sure, it's not meant to be a fast implementation, but even just a "mask byte with 0x7C and set PC to that value times 8" instruction (which in an FPGA implementation is just rearranging the wires) could save 5-6 cycles per instruction.
Is it really "microcoded" when all you're doing is writing a RISC-V emulator that runs on what looks to be a fairly standard 8 bit CPU?
[1] https://github.com/brouhaha/glacial/blob/master/ucode/ucode....
I understand that there are some FPGAs now that essentially have RISC-V ALU hard blocks, so use of them might be a speed and area improvements.
I have an "Icicle" board based on this chip. The FPGA comes preconfigured to boot Linux from the included pre=programmed SD card, so you can just use it to run Linux if you don't care about FPGAs. Or you can replace or enhance the default FPGA programming.
Don't know, but the amount of "microcode" or emulation code required is itself a reasonable measure of an ISA's complexity. Doing an x86 that way would surely take tons more code.
In those days the microcode ROM and ALU etc was substantially faster than RAM (core). At some point SRAM became as fast as or faster than ROM and machines copied the microcode into SRAM on startup. Some machines such as the Burroughs 1700 series loaded different microcode into SRAM depending on whether you wanted to run FORTRAN or COBOL programs.
Then companies started allowing users to write their own custom instructions in microcode. See for example the VAX "Writeable Control Store" which on the 11/780 (as an option) gave users 1024 words (12 KB) for custom microcode and a microcode assembler and debugger. Some people even wrote compilers targeting this for languages such as Pascal (see for example https://apps.dtic.mil/dtic/tr/fulltext/u2/a089424.pdf)
The next step was to turn the SRAM into a cache, and make a slightly more user-friendly microcode the actual instruction set used by all compilers, and thus RISC was born.
Of course you are correct that specialised instructions to make instruction decoding easier are helpful in an ISA emulator. It would not surprise me to see RISC-V itself get an extension along those lines in the near future, to help M-mode software emulate unaligned loads and stores and other unimplemented instructions, but maybe also to help emulate other instruction sets.
In a sense, yes, it is indeed!
But when I think "microcode" then I think something like the 8086's horizontal microcode [1], where each line of microcode is wired directly to the various functional units and the microcode jumps and branches are (in some sense) determined based off (some of) the bits in the instruction register.
Characteristics of microcode include: wide instructions (20-40 bits) that perform multiple operations in parallel (e.g. ALU operation and register-register copy) and hardware dispatch to the appropriate microcode to handle each microcoded instruction via zero-overhead multiway branches.
I wouldn't call a 6502-like assembly language microcode, even if it implements an interpreter for a user-level instruction set, because it lacks the relevant characteristics of true CPU microcode.
[1] https://www.reenigne.org/blog/8086-microcode-disassembled/
So why do we need RISC-V? Is it another case of NIHS?
1. RISC-V is completely unencumbered from an IP perspective. There is no possibility of a rightsholder reasserting rights on IP they had previously released (like what happened with MIPS in 2019).
2. RISC-V is legacy-free. It's an extremely "clean" design, free of weird quirks like the MIPS branch delay slot or SPARC register windows.
3. There are subsets of the RISC-V architecture defined for different sizes of systems, e.g. 32/64 bit versions, an embedded subset with fewer registers, etc. They all share an instruction set and a general architecture, and most compilers can target any subset. Some of the smaller subsets are well within the realm of what a single student can be taught to implement within a semester.
4. Numerous real implementations of RISC-V exist -- both as hardware and HDL -- are being maintained, and the hardware is available on the open market.
What happened with MIPS in 2019?
Shouldn't that kind of thing be impossible, the way it's impossible to revoke the GPL licence on software?
https://www.hackster.io/news/wave-computing-closes-its-mips-...
Astonishing.
Also saying it's like "a mediocre 90s design" is pure bias. It's a nice modern design.
I think MIPS had a similar issue but eventually fixed it. Maybe RISCV can do similar.
Yeah, that's RISC.
Instructions that can trap -- but almost never do unless you have a program bug -- cause a large complication in pipelines, and especially in OoO implementations. Even a single-issue pipeline can run faster and be smaller without conditionally-trapping instructions, and as soon as you have even 2-wide execution it's just much better in every way to use explicit checks that use the same conditional branching facilities as the rest of the code.
The code size penalty is very minor in practice.
64 bit RISC-V code density is far better than 64 bit ARM code density, which is similar to AMD64 (i.e. quite a bit bigger than i386)
Other than a few extra instructions to zero-extend 32 bit values to 64 bits at times, 64 bit RISC-V and 32 bit RISC-V code are identical in size.
High performance general computing these days means 64 bit, and RISC-V has by far the highest code density of any 64 bit ISA.
How open is OpenSPARC? Are there patent concerns?
RISC-V isn't aiming to revolutionise CPU architecture with a radical new design, it's aiming to offer a Free and Open, patent-unencumbered, fairly conventional RISC ISA. They're quite open about their emphasis on openness. [0]
For a project that aims to turn CPU design on its head, there's the Mill processor, although it's broadly thought to be vaporware.
[0] https://riscv.org/why-risc-v/
Or would be.
The fact is RISC-V is a distinct improvement on early 90s designs such as MIPS III and has also learned lessons from Alpha, PowerPC, Itanium, and AMD64.
In many ways RISC-V and Aarch64 (which were being designed in parallel unknown to each other) learned the same lessons from those earlier ISAs, though they made several trade-offs differently.
I feel like that slow evolution can make it appear "suddenly popular" despite being around for a few years. =)
It's pretty new.
In my quick searches, I found that high speed FPGAs are around $10k+, and have much more fabric than I really need or want.