I have seen more excitement and community around these kinds of projects there than here.
phendrenad2 12 hours ago [-]
Doing OOO in a one-person project is impressive.
IshKebab 12 hours ago [-]
Maybe 6 months ago. Today anyone vaguely familiar with CPU design can do it.
ltbarcly3 11 hours ago [-]
Lol it's always cute to see the amount of confidence that people have for AI when they can't tell if the work it did is actually good.
IshKebab 11 hours ago [-]
I don't think that's quite fair - this guy is clearly quite familiar with CPU design, it's very easy to run coremark, dhrystone, etc. to get a decent idea of performance, and for verification there's a reference model written in Sail you can compare against (though tbf it sounds like he didn't). AI is good at writing large test corpuses these days too.
So I would say it is relatively easy to tell if a vibe coded RISC-V CPU is actually good today. It's not like non-vibe coded RISC-V CPUs were amazingly well verified before anyway (except Ibex anyway). Even CVA6 has had some embarrassing bugs.
I expect this is a decent RISC-V core, but I also expect I could make one just as easily.
sanxiyn 4 hours ago [-]
> for verification there's a reference model written in Sail you can compare against (though tbf it sounds like he didn't)
Can you elaborate on "it sounds like he didn't" because he clearly did? There is a Sail testbench at verification/s1_sail_cosim_tb.cpp.
ltbarcly3 10 hours ago [-]
I don't think chip design comes down to knocking out a theoretically correct design. Then you fab it and it can't run at more than 37mhz LOL.
I think you don't know what you don't know here.
beng-nl 10 hours ago [-]
I wish you’d use your knowledge to add to the discussion rather than discourage others.
IshKebab 10 hours ago [-]
I do know about physical design too. Just because somebody doesn't explain every single thing in a comment doesn't mean you win the argument by highlighting something they didn't mention.
ltbarcly3 6 hours ago [-]
I'm sorry, I didn't mean this to be personally critical of you. I'm talking generally about saying to an AI "make a chip don't make any mistakes" and then thinking there is any chance of getting something that isn't trash in return, and being confident of that even though one doesn't have the domain knowledge to know if it's trash or not.
Specifically, for an advanced superscalar chip design, it is unlikely this guy single handedly, with claude or whatever, produced something highly valuable where hundreds of professional chip designers have failed.
remexre 8 hours ago [-]
you might even note that the author posted here that they closed timing at 500MHz on nangate45...
varispeed 11 hours ago [-]
and a bit of cloude:
"Make me an OOO RISC-V core in SystemVerilog. No mistakes."
I am somewhat of vaguely familiar with CPU design myself.
PowerElectronix 8 hours ago [-]
This is really cool. Any chance you'll try to make a few with tiny tap or some service like that?
fursoy 8 hours ago [-]
Thanks! Slice-1 is a bit too big for Tiny Tapeout right now.
fursoy 15 hours ago [-]
I built Fursoy Slice-1, a 64-bit out-of-order superscalar RISC-V core (RV64IMAFDV + Zba/Zbb/Zicsr/Zifencei) in SystemVerilog, along with a minimal SoC (5-master crossbar, CLINT, PLIC, 16550 UART, and custom SBI v2.0 firmware).
At a high level, the core is 2-wide fetch/decode/rename/retire with a 128-entry ROB, 160-entry integer PRF, 8 branch checkpoints for single-cycle speculative RAT rollback, and separate Int/Mem/FP/Vec issue queues. On the memory side, it has a dual-port Sv39 DTLB (64-entry 4-way Tree-PLRU + 8-entry 2 MiB/1 GiB superpage CAM), ITLB, and a 16 KiB 8-bank non-blocking L1D. Instead of flushing dirty lines on every page-table walk, the hardware PTW snoops dirty L1D sets non-destructively so Linux page-table updates are visible directly, paired with store-queue drain on SFENCE.VMA.
In Verilator, it boots mainline Linux 6.6.50 and BusyBox userspace in ~89.8M cycles (~76.2M retired instructions, 2,255 page faults handled) while checking an 8-bucket single-owner CPI conservation invariant every cycle with 0 cycle leakage. Synthesizing the 8 main core logic blocks standalone with sv2v + Yosys + OpenSTA on Nangate 45nm (SRAMs/PRFs black-boxed, pre-P&R) meets 500 MHz across all 8/8 blocks at ~219 kGE, after rebuilding the ALU and branch unit as Kogge-Stone prefix trees and balancing high-fanout CSR/TLB paths.
I used an AI-agent-assisted workflow for RTL iteration and verification scaffolding while driving the microarchitecture, timing closure, and debugging myself. The nastiest late bug was a Linux boot livelock around ~90M cycles: per RISC-V Priv Spec §3.1.9, CSR read-modify-write instructions on `mip` have to operate on the software-writable `mip_q[9]` bit rather than the live `irq_seip_i` wire—our CSR block was feeding `mip_val` back into RMW, so whenever SBI cleared `STIP` while a PLIC IRQ was high, it permanently latched `SEIP` and trapped the kernel in `plic_handle_irq`.
For folks who have built Sv39 cores or open-source ASIC flows: do you prefer letting the PTW snoop dirty L1D lines directly like this, or forcing a clean/drain path? Also curious what people would tackle next on a single-core tree like this—an inclusive L2 cache or jumping straight to dual-core coherency.
peterfirefly 4 hours ago [-]
> the hardware PTW snoops dirty L1D sets non-destructively so Linux page-table updates are visible directly
Neat! Andy Glew has talked about wanting the TLB hardware to snoop on page table updates for a long time. I don't think he ever got to implement it in a shipping CPU, though.
Have you considered doing TLB invalidation on other cores without needing IPIs? Perhaps by extending an MOESI-style cache protocol a bit?
krupan 10 hours ago [-]
Very cool. Any plans to have this fabbed? Or built into a bitstream for an FPGA?
fursoy 8 hours ago [-]
Thanks! I'm planning to do an FPGA bring-up, though I don't have a suitable board on hand right now. Fabbing is much further down the road.
peterfirefly 2 hours ago [-]
Do you know how balanced your design is or are those choices mostly based on napkin estimates and guesses?
The ROB and PRF are bigger than what the K8 had. If I understand you correctly, Slice-1 can decode two instructions per cycle (and they don't expand to multiple internal instructions) and it can retire two per cycle. If I do, then that's less than the K8 (and K7, K6, and P6).
You are not clear about the ALU/AGU/branch resources that the OOO engine has. If it can execute two instructions per cycle then it's less than the K8. It doesn't say what limitations there are -- can it handle more than 1 branch per cycle? Can it handle more than 1 load/store per cycle?
I'm asking because I'm really curious, both about your choices and about how practical it is to estimate these things as an amateur. Do you have a performance model for your architecture or is the Verilog code everything, including the performance model? Do you have the ability to execute instruction traces to compare different microarchitectural choices?
Do you know if conflict misses are much of a problem? And if so, if a small victim cache would help enough to be worth it?
Do you know why the CSR block is so slow? Too much fanout because it needs to handle access to many CSRs? Would it make sense to make it a two-cycle block instead? Or split it into a single-cycle block for common CSRs and a two-cycle block for the rest (if you are really ambitious)?
Do you know why the AGU block is so slow? Isn't it just at most two numbers that need to be added together? Your ALU block can do it twice as fast. Is it sign extension for offsets? If so, can't you sign extend them before that block (parallel with register reads, perhaps)? Or because it doesn't use the fancy adder?
Why are the TLBs so slow? Is it partly because they are single-cycle? I mean, they are only 4-way so I'm a bit surprised.
I should make clear that I am not complaining, I'm just surprised at the relative estimated speeds of the blocks you have synthesized.
A block diagram in the style of chips and cheese would help a lot, btw. It doesn't need to have the fancy pastel colours, black and white is fine.
---
There are some pages you forgot to have the AI translate from Turkish:
> Do you know why the AGU block is so slow? Isn't it just at most two numbers that need to be added together? Your ALU block can do it twice as fast. Is it sign extension for offsets? If so, can't you sign extend them before that block (parallel with register reads, perhaps)? Or because it doesn't use the fancy adder?
It doesn't use the fancy adder. I also noticed that there are two implementations of the fancy adder (they are different) and they are inlined into rtl/core/fursoy_s1_alu.sv and rtl/core/fursoy_s1_branch_unit.sv
That one was easy!
> Do you have a performance model for your architecture or is the Verilog code everything, including the performance model?
The Verilog code is indeed everything, including the performance model. There's a module that handles performance counters: rtl/core/fursoy_s1_hpm.sv
The Verilator test bench(es) dump(s) the performance counters at the end of a run.
> Do you have the ability to execute instruction traces to compare different microarchitectural choices?
Seemingly not. There's only real execution using real memory/IO access and real interrupts from real devices.
---
If anybody else is following along at home: there are apparently two RISC-V implementations: Slice-0 and Slice-1. Slice-0 is a dead simple single-scalar in-order CPU with two stages (fetch and execute). It does have TLB(s?) and caches so it's not entirely simple. Slice-1 is the OOO CPU (fetch/decode/execute/retire widths: 2/2/3/2, 10 stages). They are sometimes abbreviated as s0 and s1.
There are Verilator test benches but there's no model checking.
It looks like Slice-1 is still quite early in its development. I bet the code will be cleaned up (with the two Kogge-Stone adders merged into one and moved to a separate module, for example, or the ITLB being in a module of its own but the DTLB dumped inside the load-store unit module) and optimized further. Also tested further, of course. It doesn't seem like floating-point and vectors have received much testing love yet, for example.
The code seems very straightforward and readable (as much as Verilog can be readable -- I have seen far worse code do far less) but not well-commented. The doc files for each module are a bit too short and assume too much knowledge about the microarchitecture to be known already. Perfectly fine for a solo project, too cryptic for others to read.
This is the place to look for anybody wanting to know more about the microarchitecture. It's out of sync with the README but it has a lot more meat (details).
iberator 13 hours ago [-]
[flagged]
krupan 9 hours ago [-]
True, just writing some SystemVerilog that can be simulated does not guarantee working hardware. The OP does point out that he took it all the way to a netlist targeting a real hardware library. Place and route and actual fabrication, or building it for an FPGA and testing there are still needed to fully prove the design, but if the synthesis tools he used are reliable then there's not a lot of room for it to fail at this point. The clock speed is based on the netlist only, so it'll probably not be that fast after actual place and route, so it'll probably have to be clocked a little slower than 500 MHz, but it should work
thijson 12 hours ago [-]
I'm not sure what you consider real. Verilog or System Verilog is used industry wide to describe hardware that then becomes chips.
13 hours ago [-]
fedpost 9 hours ago [-]
YoU wOuLdN'T dOwNlOaD a CpU!1!!
pezezin 6 hours ago [-]
My MiSTer thinks otherwise...
(yes, I know that your comment is sarcasm)
matthewfcarlson 13 hours ago [-]
Who hurt you? This is a fantastic project with effort put into simulating the RTL against a PDK. I don’t understand why you would gate your approval. If someone showed off a game on HN would you say it wasn’t a real game until you could buy it at your local Best Buy or GameStop?
I have seen more excitement and community around these kinds of projects there than here.
So I would say it is relatively easy to tell if a vibe coded RISC-V CPU is actually good today. It's not like non-vibe coded RISC-V CPUs were amazingly well verified before anyway (except Ibex anyway). Even CVA6 has had some embarrassing bugs.
I expect this is a decent RISC-V core, but I also expect I could make one just as easily.
Can you elaborate on "it sounds like he didn't" because he clearly did? There is a Sail testbench at verification/s1_sail_cosim_tb.cpp.
I think you don't know what you don't know here.
Specifically, for an advanced superscalar chip design, it is unlikely this guy single handedly, with claude or whatever, produced something highly valuable where hundreds of professional chip designers have failed.
"Make me an OOO RISC-V core in SystemVerilog. No mistakes."
I am somewhat of vaguely familiar with CPU design myself.
At a high level, the core is 2-wide fetch/decode/rename/retire with a 128-entry ROB, 160-entry integer PRF, 8 branch checkpoints for single-cycle speculative RAT rollback, and separate Int/Mem/FP/Vec issue queues. On the memory side, it has a dual-port Sv39 DTLB (64-entry 4-way Tree-PLRU + 8-entry 2 MiB/1 GiB superpage CAM), ITLB, and a 16 KiB 8-bank non-blocking L1D. Instead of flushing dirty lines on every page-table walk, the hardware PTW snoops dirty L1D sets non-destructively so Linux page-table updates are visible directly, paired with store-queue drain on SFENCE.VMA.
In Verilator, it boots mainline Linux 6.6.50 and BusyBox userspace in ~89.8M cycles (~76.2M retired instructions, 2,255 page faults handled) while checking an 8-bucket single-owner CPI conservation invariant every cycle with 0 cycle leakage. Synthesizing the 8 main core logic blocks standalone with sv2v + Yosys + OpenSTA on Nangate 45nm (SRAMs/PRFs black-boxed, pre-P&R) meets 500 MHz across all 8/8 blocks at ~219 kGE, after rebuilding the ALU and branch unit as Kogge-Stone prefix trees and balancing high-fanout CSR/TLB paths.
I used an AI-agent-assisted workflow for RTL iteration and verification scaffolding while driving the microarchitecture, timing closure, and debugging myself. The nastiest late bug was a Linux boot livelock around ~90M cycles: per RISC-V Priv Spec §3.1.9, CSR read-modify-write instructions on `mip` have to operate on the software-writable `mip_q[9]` bit rather than the live `irq_seip_i` wire—our CSR block was feeding `mip_val` back into RMW, so whenever SBI cleared `STIP` while a PLIC IRQ was high, it permanently latched `SEIP` and trapped the kernel in `plic_handle_irq`.
For folks who have built Sv39 cores or open-source ASIC flows: do you prefer letting the PTW snoop dirty L1D lines directly like this, or forcing a clean/drain path? Also curious what people would tackle next on a single-core tree like this—an inclusive L2 cache or jumping straight to dual-core coherency.
Neat! Andy Glew has talked about wanting the TLB hardware to snoop on page table updates for a long time. I don't think he ever got to implement it in a shipping CPU, though.
Have you considered doing TLB invalidation on other cores without needing IPIs? Perhaps by extending an MOESI-style cache protocol a bit?
The ROB and PRF are bigger than what the K8 had. If I understand you correctly, Slice-1 can decode two instructions per cycle (and they don't expand to multiple internal instructions) and it can retire two per cycle. If I do, then that's less than the K8 (and K7, K6, and P6).
You are not clear about the ALU/AGU/branch resources that the OOO engine has. If it can execute two instructions per cycle then it's less than the K8. It doesn't say what limitations there are -- can it handle more than 1 branch per cycle? Can it handle more than 1 load/store per cycle?
I'm asking because I'm really curious, both about your choices and about how practical it is to estimate these things as an amateur. Do you have a performance model for your architecture or is the Verilog code everything, including the performance model? Do you have the ability to execute instruction traces to compare different microarchitectural choices?
Do you know if conflict misses are much of a problem? And if so, if a small victim cache would help enough to be worth it?
Do you know why the CSR block is so slow? Too much fanout because it needs to handle access to many CSRs? Would it make sense to make it a two-cycle block instead? Or split it into a single-cycle block for common CSRs and a two-cycle block for the rest (if you are really ambitious)?
Do you know why the AGU block is so slow? Isn't it just at most two numbers that need to be added together? Your ALU block can do it twice as fast. Is it sign extension for offsets? If so, can't you sign extend them before that block (parallel with register reads, perhaps)? Or because it doesn't use the fancy adder?
Why are the TLBs so slow? Is it partly because they are single-cycle? I mean, they are only 4-way so I'm a bit surprised.
I should make clear that I am not complaining, I'm just surprised at the relative estimated speeds of the blocks you have synthesized.
A block diagram in the style of chips and cheese would help a lot, btw. It doesn't need to have the fancy pastel colours, black and white is fine.
There are some pages you forgot to have the AI translate from Turkish:https://github.com/FURSOY/fursoy-cpu/blob/main/docs/architec...
https://github.com/FURSOY/fursoy-cpu/blob/main/docs/architec...
(probably more)
This one has an error (at least when shown in github) in section 3.3:
https://github.com/FURSOY/fursoy-cpu/blob/main/docs/architec...
And this one in section 2.2.3:https://github.com/FURSOY/fursoy-cpu/blob/main/docs/architec...
It doesn't use the fancy adder. I also noticed that there are two implementations of the fancy adder (they are different) and they are inlined into rtl/core/fursoy_s1_alu.sv and rtl/core/fursoy_s1_branch_unit.sv
That one was easy!
> Do you have a performance model for your architecture or is the Verilog code everything, including the performance model?
The Verilog code is indeed everything, including the performance model. There's a module that handles performance counters: rtl/core/fursoy_s1_hpm.sv
The Verilator test bench(es) dump(s) the performance counters at the end of a run.
> Do you have the ability to execute instruction traces to compare different microarchitectural choices?
Seemingly not. There's only real execution using real memory/IO access and real interrupts from real devices.
If anybody else is following along at home: there are apparently two RISC-V implementations: Slice-0 and Slice-1. Slice-0 is a dead simple single-scalar in-order CPU with two stages (fetch and execute). It does have TLB(s?) and caches so it's not entirely simple. Slice-1 is the OOO CPU (fetch/decode/execute/retire widths: 2/2/3/2, 10 stages). They are sometimes abbreviated as s0 and s1. There are Verilator test benches but there's no model checking.It looks like Slice-1 is still quite early in its development. I bet the code will be cleaned up (with the two Kogge-Stone adders merged into one and moved to a separate module, for example, or the ITLB being in a module of its own but the DTLB dumped inside the load-store unit module) and optimized further. Also tested further, of course. It doesn't seem like floating-point and vectors have received much testing love yet, for example.
The code seems very straightforward and readable (as much as Verilog can be readable -- I have seen far worse code do far less) but not well-commented. The doc files for each module are a bit too short and assume too much knowledge about the microarchitecture to be known already. Perfectly fine for a solo project, too cryptic for others to read.
https://github.com/FURSOY/fursoy-cpu/blob/main/docs/architec...
This is the place to look for anybody wanting to know more about the microarchitecture. It's out of sync with the README but it has a lot more meat (details).
(yes, I know that your comment is sarcasm)