From 6a636f867574f1e0180b8e5afdd5425411da33a2 Mon Sep 17 00:00:00 2001 From: kinzafatim Date: Fri, 19 Sep 2025 15:42:02 +0500 Subject: [PATCH 01/12] add AtomicDecoder and AMO signals to decode stage --- src/main/scala/components/AtomicDecoder.scala | 67 +++++++++++++++++++ .../scala/components/InstructionDecode.scala | 15 +++++ 2 files changed, 82 insertions(+) create mode 100644 src/main/scala/components/AtomicDecoder.scala diff --git a/src/main/scala/components/AtomicDecoder.scala b/src/main/scala/components/AtomicDecoder.scala new file mode 100644 index 000000000..46c68074e --- /dev/null +++ b/src/main/scala/components/AtomicDecoder.scala @@ -0,0 +1,67 @@ +package nucleusrv.components +import chisel3._ +import chisel3.util._ + + +class AtomicDecodeOut extends Bundle { + val isLR = Bool() + val isSC = Bool() + val isAMO = Bool() + val amoOp = UInt(4.W) // Encoded value for AMO operation type +} + +class AtomicDecoder extends Module { + val io = IO(new Bundle { + val instr = Input(UInt(32.W)) + val out = Output(new AtomicDecodeOut) + }) + + io.out.isLR := false.B + io.out.isSC := false.B + io.out.isAMO := false.B + io.out.amoOp := 0.U + + val opcode = io.instr(6,0) + val funct5 = io.instr(31,27) + val funct3 = io.instr(14,12) + + // opcode for atomic instructions + val OPCODE_ATOMIC = "b0101111".U + + when(opcode === OPCODE_ATOMIC && funct3 === "b010".U) { + switch(funct5) { + is("b00010".U) { + io.out.isLR := true.B } // LR.W + is("b00011".U) { + io.out.isSC := true.B } // SC.W + + is("b00000".U) { + io.out.isAMO := true.B; + io.out.amoOp := 1.U } // AMOADD + is("b00001".U) { + io.out.isAMO := true.B; + io.out.amoOp := 2.U } // AMOSWAP + is("b00100".U) { + io.out.isAMO := true.B; + io.out.amoOp := 3.U } // AMOXOR + is("b01100".U) { + io.out.isAMO := true.B; + io.out.amoOp := 4.U } // AMOAND + is("b01000".U) { + io.out.isAMO := true.B; + io.out.amoOp := 5.U } // AMOOR + is("b10000".U) { + io.out.isAMO := true.B; + io.out.amoOp := 6.U } // AMOMIN + is("b10100".U) { + io.out.isAMO := true.B; + io.out.amoOp := 7.U } // AMOMAX + is("b11000".U) { + io.out.isAMO := true.B; + io.out.amoOp := 8.U } // AMOMINU + is("b11100".U) { + io.out.isAMO := true.B; + io.out.amoOp := 9.U } // AMOMAXU + } + } +} diff --git a/src/main/scala/components/InstructionDecode.scala b/src/main/scala/components/InstructionDecode.scala index a87e902cd..1f73492b9 100755 --- a/src/main/scala/components/InstructionDecode.scala +++ b/src/main/scala/components/InstructionDecode.scala @@ -83,6 +83,12 @@ class InstructionDecode( // RVFI pins val raddr = if (TRACE) Some(Output(Vec(3, UInt(5.W)))) else None val rd_wdata = if (TRACE) Some(Output(UInt(32.W))) else None + + // Atomic Outputpins + val isAMO = Bool() + val isLR = Bool() + val isSC = Bool() + val amoOp = UInt(4.W) }) val is_f = if (F) Some(WireInit(0.B)) else None @@ -98,6 +104,15 @@ class InstructionDecode( ).map(io.id_instruction(6, 0) === _.U).reduce(_ || _) io.is_f.get := is_f.get } + // Atomic Decoder + val atomicDecoder = Module(new AtomicDecoder) + atomicDecoder.io.instr := io.id_instruction + + io.out.isAMO := atomicDecoder.io.out.isAMO + io.out.isLR := atomicDecoder.io.out.isLR + io.out.isSC := atomicDecoder.io.out.isSC + io.out.amoOp := atomicDecoder.io.out.amoOp + // CSR val csr = if (Zicsr) Some(Module(new CSR())) else None From c3fc2dc88f4d27e52e62a0faa475281b5fe8fac7 Mon Sep 17 00:00:00 2001 From: kinzafatim Date: Fri, 19 Sep 2025 16:22:01 +0500 Subject: [PATCH 02/12] add ID-EX registers --- src/main/scala/components/Core.scala | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/scala/components/Core.scala b/src/main/scala/components/Core.scala index a548fcff2..d69aa25bf 100644 --- a/src/main/scala/components/Core.scala +++ b/src/main/scala/components/Core.scala @@ -57,6 +57,13 @@ class Core(implicit val config:Configs) extends Module{ val id_reg_fcsr_o_data = if (F) Some(RegInit(0.U(32.W))) else None val id_reg_is_f = if (F) Some(RegInit(0.B)) else None + // Atomic signals ID-EX + val id_reg_isAMO = RegInit(false.B) + val id_reg_isLR = RegInit(false.B) + val id_reg_isSC = RegInit(false.B) + val id_reg_amoOp = RegInit(0.U(4.W)) + + // EX-MEM Registers val ex_reg_branch = RegInit(0.U(32.W)) val ex_reg_zero = RegInit(0.U(32.W)) From 2c503f82e62993d3ba836d171cf9358e3ebcf2ad Mon Sep 17 00:00:00 2001 From: kinzafatim Date: Fri, 19 Sep 2025 22:20:48 +0500 Subject: [PATCH 03/12] add Atomic ALU --- src/main/scala/components/AtomicAlu.scala | 49 +++++++++++++++++++++++ src/main/scala/components/Core.scala | 7 +++- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/components/AtomicAlu.scala diff --git a/src/main/scala/components/AtomicAlu.scala b/src/main/scala/components/AtomicAlu.scala new file mode 100644 index 000000000..9de7b7930 --- /dev/null +++ b/src/main/scala/components/AtomicAlu.scala @@ -0,0 +1,49 @@ +package nucleusrv.components +import chisel3._ +import chisel3.util._ + +class AMOALU extends Module { + val io = IO(new Bundle { + val memData = Input(UInt(32.W)) // Data loaded from memory (old value at rs1 address) + val src2 = Input(UInt(32.W)) // Value from rs2 register + val amoOp = Input(UInt(4.W)) // Operation code from decoder + val result = Output(UInt(32.W)) // Computed result to write back + }) + io.result := 0.U + + // AMOoperation encodin + val AMO_ADD = 1.U + val AMO_SWAP = 2.U + val AMO_XOR = 3.U + val AMO_AND = 4.U + val AMO_OR = 5.U + val AMO_MIN = 6.U + val AMO_MAX = 7.U + val AMO_MINU = 8.U + val AMO_MAXU = 9.U + + // Signed for comparisons + val s_memData = io.memData.asSInt + val s_src2 = io.src2.asSInt + + switch(io.amoOp) { + is(AMO_ADD) { + io.result := io.memData + io.src2 } + is(AMO_SWAP) { + io.result := io.src2 } // Swap old with new + is(AMO_XOR) { + io.result := io.memData ^ io.src2 } + is(AMO_AND) { + io.result := io.memData & io.src2 } + is(AMO_OR) { + io.result := io.memData | io.src2 } + is(AMO_MIN) { + io.result := Mux(s_memData < s_src2, io.memData, io.src2) } + is(AMO_MAX) { + io.result := Mux(s_memData > s_src2, io.memData, io.src2) } + is(AMO_MINU) { + io.result := Mux(io.memData < io.src2, io.memData, io.src2) } + is(AMO_MAXU) { + io.result := Mux(io.memData > io.src2, io.memData, io.src2) } + } +} diff --git a/src/main/scala/components/Core.scala b/src/main/scala/components/Core.scala index d69aa25bf..4db940a3c 100644 --- a/src/main/scala/components/Core.scala +++ b/src/main/scala/components/Core.scala @@ -187,7 +187,7 @@ class Core(implicit val config:Configs) extends Module{ when(ID.ifid_flush) { if_reg_ins := 0.U } - + /**************** * Decode Stage * @@ -237,6 +237,11 @@ class Core(implicit val config:Configs) extends Module{ ID.f_read_reg.get(2)(i) := mem_reg_f_read.get(i) } } + // ID-EX A + id_reg_isAMO := ID.isAMO + id_reg_isLR := ID.isLR + id_reg_isSC := ID.isSC + id_reg_amoOp := ID.amoOp /***************** * Execute Stage * From 5cc64f7cb20fbc7532c998a74736af85edbb26ee Mon Sep 17 00:00:00 2001 From: kinzafatim Date: Sat, 20 Sep 2025 00:11:21 +0500 Subject: [PATCH 04/12] add pipeline register for amoOp --- src/main/scala/components/Core.scala | 54 +++++++++++++++---- .../scala/components/InstructionDecode.scala | 9 ++-- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/main/scala/components/Core.scala b/src/main/scala/components/Core.scala index 4db940a3c..cbd169a91 100644 --- a/src/main/scala/components/Core.scala +++ b/src/main/scala/components/Core.scala @@ -83,7 +83,10 @@ class Core(implicit val config:Configs) extends Module{ val ex_reg_f_read = if (F) Some(Reg(Vec(3, Bool()))) else None val ex_reg_f_except = if (F) Some(RegInit(VecInit(Vector.fill(5)(0.B)))) else None val ex_reg_is_f = if (F) Some(RegInit(0.B)) else None - + // Atomic signals EX-MEM + val ex_reg_isAMO = RegInit(false.B) + val ex_reg_amoOp = RegInit(0.U(4.W)) + // MEM-WB Registers val mem_reg_rd = RegInit(0.U(32.W)) val mem_reg_ins = RegInit(0.U(32.W)) @@ -238,10 +241,10 @@ class Core(implicit val config:Configs) extends Module{ } } // ID-EX A - id_reg_isAMO := ID.isAMO - id_reg_isLR := ID.isLR - id_reg_isSC := ID.isSC - id_reg_amoOp := ID.amoOp + id_reg_isAMO := ID.isAMO + id_reg_isLR := ID.isLR + id_reg_isSC := ID.isSC + id_reg_amoOp := ID.amoOp /***************** * Execute Stage * @@ -295,6 +298,18 @@ class Core(implicit val config:Configs) extends Module{ ex_reg_is_f.get := EX.is_f_o.get ID.f_except.get(0) <> EX.exceptions.get } + // forward atomic control from ID->EX to EX->MEM + ex_reg_isAMO := id_reg_isAMO + ex_reg_amoOp := id_reg_amoOp + + // AMO ALU instance (use in MEM stage) + val amoALU = Module(new AMOALU) + + // ----- AMO wiring in Memory stage ----- + // Connect AMOALU inputs to data read from memory.. rs2 (ex_reg_wd) + amoALU.io.memData := MEM.io.readData + amoALU.io.src2 := ex_reg_wd + amoALU.io.amoOp := ex_reg_amoOp /**************** * Memory Stage * @@ -314,7 +329,12 @@ class Core(implicit val config:Configs) extends Module{ // // } otherwise{ mem_reg_rd := MEM.io.readData - mem_reg_result := ex_reg_result + // mem_reg_result := ex_reg_result + + // If this is an AMO, WB should receive the original memory value (MEM.io.readData). + // For other cases keep previous behavior. + mem_reg_result := Mux(ex_reg_isAMO, MEM.io.readData, ex_reg_result) + // mem_reg_ctl_memToReg := ex_reg_ctl_memToReg mem_reg_ctl_regWrite <> ex_reg_ctl_regWrite mem_reg_ins := ex_reg_ins @@ -325,14 +345,28 @@ class Core(implicit val config:Configs) extends Module{ ex_reg_result := EX.ALUresult // } mem_reg_wra := ex_reg_wra - mem_reg_ctl_memToReg := ex_reg_ctl_memToReg + // mem_reg_ctl_memToReg := ex_reg_ctl_memToReg + + // Force the memToReg selector to choose memory result for AMO + // (assuming memToReg==1 means load -> uses MEM.io.readData in WB) + mem_reg_ctl_memToReg := Mux(ex_reg_isAMO, 1.U, ex_reg_ctl_memToReg) + mem_reg_is_csr := ex_reg_is_csr mem_reg_csr_data := ex_reg_csr_data EX.ex_mem_regWrite <> ex_reg_ctl_regWrite MEM.io.aluResultIn := ex_reg_result - MEM.io.writeData := ex_reg_wd - MEM.io.readEnable := ex_reg_ctl_memRead - MEM.io.writeEnable := ex_reg_ctl_memWrite + // MEM.io.writeData := ex_reg_wd +// If ex_reg_isAMO: writeData should be amoALU result; otherwise normal ex_reg_wd + MEM.io.writeData := Mux(ex_reg_isAMO, amoALU.io.result, ex_reg_wd) + + // MEM.io.readEnable := ex_reg_ctl_memRead + // For readEnable we keep original control (AMO still needs a read) + MEM.io.readEnable := ex_reg_ctl_memRead || ex_reg_isAMO + + //MEM.io.writeEnable := ex_reg_ctl_memWrite + // Ensure we assert writeEnable for AMO (RMW needs write back) + MEM.io.writeEnable := ex_reg_ctl_memWrite || ex_reg_isAMO + MEM.io.f3 := ex_reg_ins(14,12) EX.mem_result := ex_reg_result ID.csr_Mem := ex_reg_is_csr diff --git a/src/main/scala/components/InstructionDecode.scala b/src/main/scala/components/InstructionDecode.scala index 1f73492b9..991658601 100755 --- a/src/main/scala/components/InstructionDecode.scala +++ b/src/main/scala/components/InstructionDecode.scala @@ -108,10 +108,11 @@ class InstructionDecode( val atomicDecoder = Module(new AtomicDecoder) atomicDecoder.io.instr := io.id_instruction - io.out.isAMO := atomicDecoder.io.out.isAMO - io.out.isLR := atomicDecoder.io.out.isLR - io.out.isSC := atomicDecoder.io.out.isSC - io.out.amoOp := atomicDecoder.io.out.amoOp + io.isAMO := atomicDecoder.io.out.isAMO + io.isLR := atomicDecoder.io.out.isLR + io.isSC := atomicDecoder.io.out.isSC + io.amoOp := atomicDecoder.io.out.amoOp + // CSR From a78bfe0a1e3f4bab80f8a060df3a34a4ad127c9c Mon Sep 17 00:00:00 2001 From: kinzafatim Date: Sun, 5 Oct 2025 00:40:07 +0500 Subject: [PATCH 05/12] simple bus for communication added --- src/main/scala/components/Bus.scala | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/main/scala/components/Bus.scala diff --git a/src/main/scala/components/Bus.scala b/src/main/scala/components/Bus.scala new file mode 100644 index 000000000..1ec31dc33 --- /dev/null +++ b/src/main/scala/components/Bus.scala @@ -0,0 +1,40 @@ +package nucleusrv.components + +import chisel3._ +import chisel3.util._ + +class BusIO(addrWidth: Int, dataWidth: Int) extends Bundle { + val addr = Input(UInt(addrWidth.W)) + val wdata = Input(UInt(dataWidth.W)) + val rdata = Output(UInt(dataWidth.W)) + val wen = Input(Bool()) + val ren = Input(Bool()) +} + +class Bus(addrWidth: Int = 32, dataWidth: Int = 32) extends Module { + val io = IO(new Bundle { + val cpu = Flipped(new BusIO(addrWidth, dataWidth)) + val imem = new BusIO(addrWidth, dataWidth) + val dmem = new BusIO(addrWidth, dataWidth) + }) + + // Default signals + io.imem := 0.U.asTypeOf(io.imem) + io.dmem := 0.U.asTypeOf(io.dmem) + io.cpu.rdata := 0.U + + // Address decode: <0x1000_0000 -> imem, else -> dmem + when(io.cpu.addr < "h10000000".U) { + io.imem.addr := io.cpu.addr + io.imem.wdata := io.cpu.wdata + io.imem.wen := io.cpu.wen + io.imem.ren := io.cpu.ren + io.cpu.rdata := io.imem.rdata + }.otherwise { + io.dmem.addr := io.cpu.addr + io.dmem.wdata := io.cpu.wdata + io.dmem.wen := io.cpu.wen + io.dmem.ren := io.cpu.ren + io.cpu.rdata := io.dmem.rdata + } +} From 774d8efed7fba0891727dbebc7e971f7783f8cf5 Mon Sep 17 00:00:00 2001 From: kinzafatim Date: Sun, 5 Oct 2025 00:41:49 +0500 Subject: [PATCH 06/12] Implement dualcore NRV system with cache and simple bus integration --- src/main/scala/components/top_new.scala | 115 ++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/main/scala/components/top_new.scala diff --git a/src/main/scala/components/top_new.scala b/src/main/scala/components/top_new.scala new file mode 100644 index 000000000..541908c00 --- /dev/null +++ b/src/main/scala/components/top_new.scala @@ -0,0 +1,115 @@ +package nucleusrv.components + +import chisel3._ +import chisel3.stage.ChiselStage +import nucleusrv.tracer._ + +class Top(programFile: Option[String], dataFile: Option[String]) extends Module { + + val io = IO(new Bundle { + val pin = Output(UInt(32.W)) + val rvfi = new TracerO + }) + + // Core configuration + implicit val config: Configs = Configs( + XLEN = 32, + M = true, + F = true, + C = false, + Zicsr = true, + TRACE = true + ) + + // 2 NucleusRV core + val core0 = Module(new Core()) + val core1 = Module(new Core()) + core0.io.stall := false.B + core1.io.stall := false.B + + // caches (16KB each 64B line) + val icache0 = Module(new Cache(16384, 64, CacheAccessType.ReadOnly)) // icache for Core0 + val dcache0 = Module(new Cache(16384, 64, CacheAccessType.ReadWrite)) // dcache for Core0 + + val icache1 = Module(new Cache(16384, 64, CacheAccessType.ReadOnly)) // icache for Core1 + val dcache1 = Module(new Cache(16384, 64, CacheAccessType.ReadWrite)) // dcache for Core1 + + // Shared Bus + Memory system + val bus0 = Module(new Bus()) // Core0 bus to imem,dmem + val bus1 = Module(new Bus()) // Core1 bus to imem,dmem + + val imem = Module(new SRamTop(programFile)) + val dmem = Module(new SRamTop(dataFile)) + + // Connect Core0 to dcaches, icache + core0.io.imemReq.addr := icache0.io.addr + core0.io.imemRsp.data := icache0.io.rdata + core0.io.imemRsp.valid := icache0.io.valid + + core0.io.dmemReq.addr := dcache0.io.addr + core0.io.dmemReq.wdata := dcache0.io.wdata + core0.io.dmemReq.wen := dcache0.io.wen + core0.io.dmemRsp.data := dcache0.io.rdata + core0.io.dmemRsp.valid := dcache0.io.valid + + // Connect Core1 to dcaches, icache + + core1.io.imemReq.addr := icache1.io.addr + core1.io.imemRsp.data := icache1.io.rdata + core1.io.imemRsp.valid := icache1.io.valid + + core1.io.dmemReq.addr := dcache1.io.addr + core1.io.dmemReq.wdata := dcache1.io.wdata + core1.io.dmemReq.wen := dcache1.io.wen + core1.io.dmemRsp.data := dcache1.io.rdata + core1.io.dmemRsp.valid := dcache1.io.valid + + + // Connect caches to bus + + // Core0 cache to Bus0 + bus0.io.cpu.addr := Mux(icache0.io.valid, icache0.io.addr, dcache0.io.addr) + bus0.io.cpu.wdata := dcache0.io.wdata + bus0.io.cpu.wen := dcache0.io.wen + bus0.io.cpu.ren := !dcache0.io.wen + dcache0.io.rdata := bus0.io.cpu.rdata + icache0.io.rdata := bus0.io.cpu.rdata + + // Core1 caches to Bus1 + bus1.io.cpu.addr := Mux(icache1.io.valid, icache1.io.addr, dcache1.io.addr) + bus1.io.cpu.wdata := dcache1.io.wdata + bus1.io.cpu.wen := dcache1.io.wen + bus1.io.cpu.ren := !dcache1.io.wen + dcache1.io.rdata := bus1.io.cpu.rdata + icache1.io.rdata := bus1.io.cpu.rdata + + + // Shared Memory connection + bus0.io.imem <> imem.io + bus0.io.dmem <> dmem.io + + bus1.io.imem <> imem.io + bus1.io.dmem <> dmem.io + + io.pin := core0.io.pin | core1.io.pin + + if (config.TRACE) { + val tracer = Module(new Tracer) + tracer.rvfi_i <> core0.io.rvfi.get + io.rvfi <> tracer.rvfi_o + } +} + +object NRVDriver { + def main(args: Array[String]): Unit = { + val IMem = if (args.contains("--imem")) Some(args(args.indexOf("--imem") + 1)) else None + val DMem = if (args.contains("--dmem")) Some(args(args.indexOf("--dmem") + 1)) else None + new ChiselStage().emitVerilog( + new Top(IMem, DMem), + if (args.contains("--target-dir")) args.slice( + args.indexOf("--target-dir"), + args.indexOf("--target-dir") + 2 + ) else Array() + ) + } +} From 8dc1112f313acea0423173251a3e4e79870a347e Mon Sep 17 00:00:00 2001 From: Kinza Fatima <123647485+kinzafatim@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:21:34 +0000 Subject: [PATCH 07/12] Add files via upload --- NucleusRV_B.png | Bin 0 -> 5143 bytes NucleusRV_w.png | Bin 0 -> 6144 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 NucleusRV_B.png create mode 100644 NucleusRV_w.png diff --git a/NucleusRV_B.png b/NucleusRV_B.png new file mode 100644 index 0000000000000000000000000000000000000000..9b9b78b1fb1942293d1c69ac8003bb25a0a16d81 GIT binary patch literal 5143 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 R2q5W$ED+YF1Y@_P{{v2TAp-ya literal 0 HcmV?d00001 From ed77813156873989ea162534796c5baaf839cba3 Mon Sep 17 00:00:00 2001 From: Kinza Fatima <123647485+kinzafatim@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:26:18 +0000 Subject: [PATCH 08/12] Add files via upload --- nrv_B.png | Bin 0 -> 8303 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 nrv_B.png diff --git a/nrv_B.png b/nrv_B.png new file mode 100644 index 0000000000000000000000000000000000000000..2f19f7f85e169ccca084b8285f5def9df202cd00 GIT binary patch literal 8303 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 Date: Fri, 16 Jan 2026 17:05:18 +0500 Subject: [PATCH 09/12] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cff73210b..13fa99551 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -# NucleusRV + + + + NucleusRV Logo + [![Join the chat at https://gitter.im/merledu/nucleusrv](https://badges.gitter.im/merledu/nucleusrv.svg)](https://gitter.im/merledu/nucleusrv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From 171a51f42b980d63ab491833569d820e72a2cf15 Mon Sep 17 00:00:00 2001 From: Kinza Fatima <123647485+kinzafatim@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:33:17 +0500 Subject: [PATCH 10/12] Update README.md --- README.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 13fa99551..f820c88d6 100644 --- a/README.md +++ b/README.md @@ -32,16 +32,43 @@ python3 gen_verilog.py ### Running RISC-V assembly ```sh -python3 simulate.py --sbt_args "--imem " nucleusrv.components.NRVDriver Top +python3 simulate.py --sbt_args "--imem " nucleusrv.components.NRVDriver Top + ``` ### Running RISC-V Architectural Tests * Make sure to have the RISC-V GNU Toolchain and Verilator in your `PATH`. -* Create a python virtual environment and follow the `README.md` in `riscof/riscv-arch-test/`. +* Create a python virtual environment. +```sh +python3 -m venv .venv +source .venv/bin/activate +``` +* Install Python Dependencies for RISCoF +```sh +pip install --upgrade pip +pip install git+https://github.com/riscv/riscof.git +``` * Run `run_riscv_arch_tests.py` in root directory. ```sh python3 run_riscv_arch_tests.py ``` +* RISCoF Architecture Tests: +```sh +cd riscof/riscv-arch-test/riscv-ctg +pip install -e . +``` +```sh +cd ../riscv-isac +pip install -e . +cd ../../.. +``` +* Verify Installation +```sh +riscof --help +spike --help +``` +You should see RISCoF and Spike help options displayed. + ### Building C Programs * In `tools/tests` directory, create a folder and write c program in the `main.c` file From b93322f93e37cc8cc8cd5378944c220910059365 Mon Sep 17 00:00:00 2001 From: Kinza Fatima <123647485+kinzafatim@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:41:57 +0500 Subject: [PATCH 11/12] Add contributing guidelines to Contributing.md --- Contributing.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Contributing.md diff --git a/Contributing.md b/Contributing.md new file mode 100644 index 000000000..f44d3c877 --- /dev/null +++ b/Contributing.md @@ -0,0 +1,9 @@ +# Contributing + +Contributions are welcome! You can help by: +- Adding new RISC-V instructions or extensions +- Improving the pipeline or memory modules +- Adding more RISCoF test cases +- Fixing bugs in existing modules + +Please fork the repository, create a feature branch, and submit a pull request. From b299c45c396ba33ae485d29b3e13e7dbb69393ff Mon Sep 17 00:00:00 2001 From: Kinza Fatima <123647485+kinzafatim@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:52:29 +0500 Subject: [PATCH 12/12] Update README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index f820c88d6..b2d91e29c 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,17 @@ A chisel based riscv 5-stage pipelined cpu design, implementing 32-bit version of the ISA (incomplete). +## Supported Extensions + +| Extension | Description | +|-----------|-------------| +| I | Base Integer Instructions | +| M | Integer Multiplication & Division | +| F | Single-Precision Floating Point | +| C | Compressed Instructions | +| A | Atomic Instructions | + + ## Dependencies