From 82ac61e590c3ecbf3fbc0f036b4044c252f47a22 Mon Sep 17 00:00:00 2001 From: liuyic00 Date: Wed, 10 Jul 2024 21:46:49 +0800 Subject: [PATCH] Support fake extensions in RVConfig (#19) --- src/main/scala/rvspeccore/core/RVConfig.scala | 55 ++++++++++++------- .../scala/rvspeccore/core/RiscvCore.scala | 6 +- .../rvspeccore/checker/CheckerSpec.scala | 4 +- .../checker/ConnectHelperSpec.scala | 2 +- .../scala/rvspeccore/core/RiscvCoreSpec.scala | 16 +++--- 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/main/scala/rvspeccore/core/RVConfig.scala b/src/main/scala/rvspeccore/core/RVConfig.scala index 0e726f4..4c5fd5d 100644 --- a/src/main/scala/rvspeccore/core/RVConfig.scala +++ b/src/main/scala/rvspeccore/core/RVConfig.scala @@ -3,13 +3,18 @@ package rvspeccore.core import chisel3._ import chisel3.util._ -sealed abstract class RVConfig(extensions: String) { - - /** - riscv-spec-20191213 - * - We use the term XLEN to refer to the width of an integer register in - * bits. - */ - val XLEN: Int +/** @param XLEN + * The width of an integer register in bits + * @param extensions + * Supported extensions + * @param fakeExtensions + * RiscvCore does not support these extensions, but they will appear in misa + */ +class RVConfig(val XLEN: Int, extensions: String, fakeExtensions: String) { + // - riscv-spec-20191213 + // - We use the term XLEN to refer to the width of an integer register in + // bits. + require(XLEN == 32 || XLEN == 64, "RiscvCore only support 32 or 64 bits now") // ISA Extensions val M: Boolean = extensions.indexOf("M") != -1 @@ -20,18 +25,30 @@ sealed abstract class RVConfig(extensions: String) { // CSRs Config // Misa - var CSRMisaExtList = Seq( - Some('I'), - if (M) Some('M') else None, - if (C) Some('C') else None, - if (S) Some('S') else None, - if (U || S) Some('U') else None - ).flatten + val CSRMisaExtList = (fakeExtensions.toSeq ++ + Seq( + Some('I'), + if (M) Some('M') else None, + if (C) Some('C') else None, + if (S) Some('S') else None, + if (U || S) Some('U') else None + ).flatten).distinct } -case class RV32Config(extensions: String = "") extends RVConfig(extensions) { - val XLEN = 32 -} -case class RV64Config(extensions: String = "") extends RVConfig(extensions) { - val XLEN = 64 +object RVConfig { + + /** Create a RVConfig + * @param XLEN + * The width of an integer register in bits + * @param extensions + * Supported extensions + * @param fakeExtensions + * RiscvCore do not support this extensions, but will be appear in Misa + */ + def apply( + XLEN: Int, + extensions: String = "", + fakeExtensions: String = "" + ): RVConfig = + new RVConfig(XLEN, extensions, fakeExtensions) } diff --git a/src/main/scala/rvspeccore/core/RiscvCore.scala b/src/main/scala/rvspeccore/core/RiscvCore.scala index bdb0c2a..0ab94c6 100644 --- a/src/main/scala/rvspeccore/core/RiscvCore.scala +++ b/src/main/scala/rvspeccore/core/RiscvCore.scala @@ -122,13 +122,13 @@ class RiscvCore()(implicit config: RVConfig) extends BaseCore with RVInstSet { iFetchpc := resultPC // Decode and Excute - config match { - case RV32Config(_) => { + config.XLEN match { + case 32 => { doRV32I if (config.M) { doRV32M } if (config.C) { doRV32C } } - case RV64Config(_) => { + case 64 => { doRV64I if (config.M) { doRV64M } if (config.C) { doRV64C } diff --git a/src/test/scala/rvspeccore/checker/CheckerSpec.scala b/src/test/scala/rvspeccore/checker/CheckerSpec.scala index de547ad..6bf3ac1 100644 --- a/src/test/scala/rvspeccore/checker/CheckerSpec.scala +++ b/src/test/scala/rvspeccore/checker/CheckerSpec.scala @@ -10,7 +10,7 @@ import rvspeccore.core._ class CheckerWithResultSpec extends AnyFlatSpec with ChiselScalatestTester { behavior of "CheckerWithResult" - implicit val config = RV64Config() + implicit val config = RVConfig(64) class TestCore(checkMem: Boolean = true) extends RiscvCore { val checker = Module(new CheckerWithResult(checkMem)) @@ -71,7 +71,7 @@ class CheckerWithResultSpec extends AnyFlatSpec with ChiselScalatestTester { class CheckerWithWBSpec extends AnyFlatSpec with ChiselScalatestTester { behavior of "CheckerWithWB" - implicit val config = RV64Config() + implicit val config = RVConfig(64) class TestCore(checkMem: Boolean = true) extends RiscvCore { val wb = Wire(new WriteBack) diff --git a/src/test/scala/rvspeccore/checker/ConnectHelperSpec.scala b/src/test/scala/rvspeccore/checker/ConnectHelperSpec.scala index eb0521c..9f0198c 100644 --- a/src/test/scala/rvspeccore/checker/ConnectHelperSpec.scala +++ b/src/test/scala/rvspeccore/checker/ConnectHelperSpec.scala @@ -10,7 +10,7 @@ import rvspeccore.core._ class ConnectHelperSpec extends AnyFlatSpec with ChiselScalatestTester { behavior of "ConnectHelper" - implicit val config = RV64Config() + implicit val config = RVConfig(64) class TestCore extends RiscvCore { val checker = Module(new CheckerWithResult(false)) diff --git a/src/test/scala/rvspeccore/core/RiscvCoreSpec.scala b/src/test/scala/rvspeccore/core/RiscvCoreSpec.scala index bffb2b3..ecbb763 100644 --- a/src/test/scala/rvspeccore/core/RiscvCoreSpec.scala +++ b/src/test/scala/rvspeccore/core/RiscvCoreSpec.scala @@ -37,8 +37,8 @@ class CoreTester(genCore: => RiscvCore, memFile: String)(implicit config: RVConf // printf("[Debug] InstMEM: %x %x\n", fetchAddr, fetchAddr2) // inst core.io.valid := !reset.asBool - config match { - case RV32Config(_) => { + config.XLEN match { + case 32 => { val instMem = fetchAddr inst := MuxLookup( @@ -50,7 +50,7 @@ class CoreTester(genCore: => RiscvCore, memFile: String)(implicit config: RVConf ) ) } - case RV64Config(_) => { + case 64 => { val instMem = Cat(mem.read((pc >> 3) + 1.U), mem.read(pc >> 3)) inst := MuxLookup( pc(2, 1), @@ -208,10 +208,10 @@ class RiscvCoreSpec extends AnyFlatSpec with ChiselScalatestTester { it should "pass RV64Config firrtl emit" in { // generate Firrtl Code (new chisel3.stage.ChiselStage) - .emitFirrtl(new RiscvCore()(RV64Config()), Array("--target-dir", "test_run_dir/" + getTestName)) + .emitFirrtl(new RiscvCore()(RVConfig(64)), Array("--target-dir", "test_run_dir/" + getTestName)) } it should "pass manual test" in { - test(new RiscvCore()(RV64Config("MC"))).withAnnotations(Seq(WriteVcdAnnotation)) { c => + test(new RiscvCore()(RVConfig(64, "MC"))).withAnnotations(Seq(WriteVcdAnnotation)) { c => c.io.valid.poke(true.B) c.io.inst.poke("h8391_4441".U) c.clock.step() @@ -220,7 +220,7 @@ class RiscvCoreSpec extends AnyFlatSpec with ChiselScalatestTester { c.io.inst.poke("h0000_0000".U) c.clock.step() } - implicit val config = RV64Config("MC") + implicit val config = RVConfig(64, "MC") test(new CoreTester(new RiscvCore, "./testcase/riscv-tests-hex/rv64uc/rv64uc-rvc.hex")) .withAnnotations(Seq(WriteVcdAnnotation)) { c => RiscvTests.stepTest(c, RiscvTests.maxStep) @@ -230,7 +230,7 @@ class RiscvCoreSpec extends AnyFlatSpec with ChiselScalatestTester { } class RiscvCore64Spec extends AnyFlatSpec with ChiselScalatestTester { - implicit val config = RV64Config("MCS") + implicit val config = RVConfig(64, "MCS") val tests = Seq("rv64ui", "rv64um", "rv64uc") @@ -251,7 +251,7 @@ class RiscvCore64Spec extends AnyFlatSpec with ChiselScalatestTester { } class RiscvCore32Spec extends AnyFlatSpec with ChiselScalatestTester { - implicit val config = RV32Config("MC") + implicit val config = RVConfig(32, "MC") val tests = Seq("rv32ui", "rv32um", "rv32uc") // val tests = Seq("tempcsr32")