From 94d5f8b265d0c4029a2e8417abdc32b21e6d6516 Mon Sep 17 00:00:00 2001 From: klin02 Date: Fri, 8 Dec 2023 16:00:10 +0800 Subject: [PATCH] Squash: move into Gateway, get Scope from initial * To simplify squash logic and support replay,we move Squash into Gateway. * Redundant fly-lines and wb_int fix has been implemented in Gateway, so we remove it from Squash. * We get svScope from initial rather than name string for better portability --- .github/workflows/main.yml | 6 +-- src/main/scala/Difftest.scala | 4 +- src/main/scala/Gateway.scala | 40 ++++++++++++------- src/main/scala/Squash.scala | 61 +++++------------------------ src/test/csrc/difftest/difftest.cpp | 20 ++++++---- src/test/csrc/difftest/difftest.h | 3 +- 6 files changed, 53 insertions(+), 81 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 58a889c48..839b1e757 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -183,7 +183,7 @@ jobs: source ./env.sh make clean sed -i 's/hasGlobalEnable: Boolean = false/hasGlobalEnable: Boolean = true/' difftest/src/main/scala/Gateway.scala - sed -i 's/isEffective: Boolean = false/isEffective: Boolean = true/' difftest/src/main/scala/Squash.scala + sed -i 's/isSquash : Boolean = false/isSquash : Boolean = true/' difftest/src/main/scala/Gateway.scala make emu ./build/emu -b 0 -e 0 -i ./ready-to-run/microbench.bin --diff ./ready-to-run/riscv64-nemu-interpreter-so cd difftest && git restore src @@ -195,7 +195,7 @@ jobs: cd $GITHUB_WORKSPACE/../xs-env/NutShell source ./env.sh make clean - sed -i 's/isEffective: Boolean = false/isEffective: Boolean = true/' difftest/src/main/scala/Squash.scala + sed -i 's/isSquash : Boolean = false/isSquash : Boolean = true/' difftest/src/main/scala/Gateway.scala sed -i 's/isBatch : Boolean = false/isBatch : Boolean = true/' difftest/src/main/scala/Gateway.scala sed -i 's/hasGlobalEnable: Boolean = false/hasGlobalEnable: Boolean = true/' difftest/src/main/scala/Gateway.scala make emu @@ -265,7 +265,7 @@ jobs: cd $GITHUB_WORKSPACE/../xs-env/NutShell source ./env.sh make clean - sed -i 's/isEffective: Boolean = false/isEffective: Boolean = true/' difftest/src/main/scala/Squash.scala + sed -i 's/isSquash : Boolean = false/isSquash : Boolean = true/' difftest/src/main/scala/Gateway.scala sed -i 's/isBatch : Boolean = false/isBatch : Boolean = true/' difftest/src/main/scala/Gateway.scala sed -i 's/hasGlobalEnable: Boolean = false/hasGlobalEnable: Boolean = true/' difftest/src/main/scala/Gateway.scala make simv VCS=verilator diff --git a/src/main/scala/Difftest.scala b/src/main/scala/Difftest.scala index c3144479e..3d254a8a3 100644 --- a/src/main/scala/Difftest.scala +++ b/src/main/scala/Difftest.scala @@ -18,7 +18,6 @@ package difftest import chisel3._ import difftest.gateway.Gateway -import difftest.squash.Squash import java.nio.charset.StandardCharsets import java.nio.file.{Files, Paths} @@ -287,7 +286,7 @@ object DifftestModule { if (enabled) { val id = register(gen, style) val sink = Gateway(gen, style) - sink := Squash(Delayer(difftest, delay)) + sink := Delayer(difftest, delay) sink.coreid := difftest.coreid } if (dontCare) { @@ -312,7 +311,6 @@ object DifftestModule { macros ++= gateway_tuple._1 difftest.step := gateway_tuple._2 - macros ++= Squash.collect() if (cppHeader.isDefined) { generateCppHeader(cpu, cppHeader.get) } diff --git a/src/main/scala/Gateway.scala b/src/main/scala/Gateway.scala index 3c1af7fd5..294dbf3c6 100644 --- a/src/main/scala/Gateway.scala +++ b/src/main/scala/Gateway.scala @@ -20,12 +20,14 @@ import chisel3.util._ import chisel3.util.experimental.BoringUtils import difftest._ import difftest.dpic.DPIC +import difftest.squash.Squash import scala.collection.mutable.ListBuffer case class GatewayConfig( style : String = "dpic", hasGlobalEnable: Boolean = false, + isSquash : Boolean = false, diffStateSelect: Boolean = false, isBatch : Boolean = false, batchSize : Int = 32 @@ -80,10 +82,9 @@ class GatewayEndpoint(signals: Seq[DifftestBundle], config: GatewayConfig) exten BoringUtils.addSink(data, s"gateway_$id") in(id) := data.asTypeOf(in(id).cloneType) } - val out = WireInit(in) - val out_pack = WireInit(in_pack) - if (config.hasDutPos) { + val share_wbint = WireInit(in) + if (config.hasDutPos || config.isSquash) { // Special fix for int writeback. Work for single-core only if (in.exists(_.desiredCppName == "wb_int")) { require(in.count(_.isUniqueIdentifier) == 1, "only single-core is supported yet") @@ -99,7 +100,7 @@ class GatewayEndpoint(signals: Seq[DifftestBundle], config: GatewayConfig) exten val commits = in.filter(_.desiredCppName == "commit").map(_.asInstanceOf[DiffInstrCommit]) val num_skip = PopCount(commits.map(c => c.valid && c.skip)) assert(num_skip <= 1.U, p"num_skip $num_skip is larger than one. Squash not supported yet") - val wb_for_skip = out.filter(_.desiredCppName == "wb_int").head.asInstanceOf[DiffIntWriteback] + val wb_for_skip = share_wbint.filter(_.desiredCppName == "wb_int").head.asInstanceOf[DiffIntWriteback] for (c <- commits) { when(c.valid && c.skip) { wb_for_skip.valid := true.B @@ -112,22 +113,30 @@ class GatewayEndpoint(signals: Seq[DifftestBundle], config: GatewayConfig) exten } } } - - for ((data, id) <- out_pack.zipWithIndex) { - data := out(id).asUInt - } } } + val out = WireInit(share_wbint) + if (config.isSquash) { + val squash = Squash(share_wbint.toSeq.map(_.cloneType)) + squash.in := share_wbint + out := squash.out + } + + val out_pack = WireInit(in_pack) + for ((data, id) <- out_pack.zipWithIndex) { + data := out(id).asUInt + } + val port_num = if (config.isBatch) config.batchSize else 1 val ports = Seq.fill(port_num)(Wire(new GatewayBundle(config))) val global_enable = WireInit(true.B) if(config.hasGlobalEnable) { - global_enable := VecInit(in.filter(_.needUpdate.isDefined).map(_.needUpdate.get).toSeq).asUInt.orR + global_enable := VecInit(out.filter(_.needUpdate.isDefined).map(_.needUpdate.get).toSeq).asUInt.orR } - val batch_data = Option.when(config.isBatch)(Mem(config.batchSize, in_pack.cloneType)) + val batch_data = Option.when(config.isBatch)(Mem(config.batchSize, out_pack.cloneType)) val enable = WireInit(false.B) if(config.isBatch) { val batch_ptr = RegInit(0.U(log2Ceil(config.batchSize).W)) @@ -162,14 +171,14 @@ class GatewayEndpoint(signals: Seq[DifftestBundle], config: GatewayConfig) exten if (config.isBatch) { for (ptr <- 0 until config.batchSize) { ports(ptr).dut_pos.get := ptr.asUInt - for(id <- 0 until in.length) { - GatewaySink(in(id).cloneType, config, ports(ptr)) := batch_data.get(ptr)(id) + for(id <- 0 until out.length) { + GatewaySink(out(id).cloneType, config, ports(ptr)) := batch_data.get(ptr)(id) } } } else { - for(id <- 0 until in.length){ - GatewaySink(in(id).cloneType, config, ports.head) := out_pack(id) + for(id <- 0 until out.length){ + GatewaySink(out(id).cloneType, config, ports.head) := out_pack(id) } } @@ -177,6 +186,9 @@ class GatewayEndpoint(signals: Seq[DifftestBundle], config: GatewayConfig) exten if (config.isBatch) { macros ++= Seq("CONFIG_DIFFTEST_BATCH", s"DIFFTEST_BATCH_SIZE ${config.batchSize}") } + if (config.isSquash) { + macros ++= Squash.collect() + } } diff --git a/src/main/scala/Squash.scala b/src/main/scala/Squash.scala index e85d0ee27..f52b906a6 100644 --- a/src/main/scala/Squash.scala +++ b/src/main/scala/Squash.scala @@ -24,43 +24,21 @@ import difftest._ import scala.collection.mutable.ListBuffer object Squash { - private val isEffective: Boolean = false private val instances = ListBuffer.empty[DifftestBundle] - def apply[T <: DifftestBundle](gen: T): T = { - if (isEffective) register(gen, WireInit(0.U.asTypeOf(gen))) else gen - } - - def register[T <: DifftestBundle](original: T, squashed: T): T = { - // There seems to be a bug in WiringUtils when original is some IO of Module. - // We manually add a Wire for the source to avoid the WiringException. - BoringUtils.addSource(WireInit(original), s"squash_in_${instances.length}") - BoringUtils.addSink(squashed, s"squash_out_${instances.length}") - instances += original.cloneType - squashed + def apply[T <: Seq[DifftestBundle]](bundles: T): SquashEndpoint = { + val module = Module(new SquashEndpoint(bundles)) + module } def collect(): Seq[String] = { - if (isEffective) { - Module(new SquashEndpoint(instances.toSeq)) - Seq("CONFIG_DIFFTEST_SQUASH") - } - else { - Seq() - } + Seq("CONFIG_DIFFTEST_SQUASH") } } class SquashEndpoint(bundles: Seq[DifftestBundle]) extends Module { - val in = WireInit(0.U.asTypeOf(MixedVec(bundles))) - for ((data, i) <- in.zipWithIndex) { - BoringUtils.addSink(data, s"squash_in_$i") - } - - val out = Wire(MixedVec(bundles)) - for ((data, i) <- out.zipWithIndex) { - BoringUtils.addSource(data, s"squash_out_$i") - } + val in = IO(Input(MixedVec(bundles))) + val out = IO(Output(MixedVec(bundles))) val state = RegInit(0.U.asTypeOf(MixedVec(bundles))) @@ -106,30 +84,6 @@ class SquashEndpoint(bundles: Seq[DifftestBundle]) extends Module { s := i.squash(s) } } - - // Special fix for int writeback. Work for single-core only. - if (bundles.exists(_.desiredCppName == "wb_int")) { - require(bundles.count(_.isUniqueIdentifier) == 1, "only single-core is supported yet") - val writebacks = in.filter(_.desiredCppName == "wb_int").map(_.asInstanceOf[DiffIntWriteback]) - val numPhyRegs = writebacks.head.numElements - val wb_int = Reg(Vec(numPhyRegs, UInt(64.W))) - for (wb <- writebacks) { - when (wb.valid) { - wb_int(wb.address) := wb.data - } - } - val commits = out.filter(_.desiredCppName == "commit").map(_.asInstanceOf[DiffInstrCommit]) - val num_skip = PopCount(commits.map(c => c.valid && c.skip)) - assert(num_skip <= 1.U, p"num_skip $num_skip is larger than one. Squash not supported yet") - val wb_for_skip = out.filter(_.desiredCppName == "wb_int").head.asInstanceOf[DiffIntWriteback] - for (c <- commits) { - when (c.valid && c.skip) { - wb_for_skip.valid := true.B - wb_for_skip.address := c.wpdest - wb_for_skip.data := wb_int(c.wpdest) - } - } - } } class SquashControl extends ExtModule with HasExtModuleInline { @@ -145,7 +99,10 @@ class SquashControl extends ExtModule with HasExtModuleInline { | output reg enable |); | + |import "DPI-C" context function void set_squash_scope(); + | |initial begin + | set_squash_scope(); | enable = 1'b1; |end | diff --git a/src/test/csrc/difftest/difftest.cpp b/src/test/csrc/difftest/difftest.cpp index 11e64e159..c6ead3024 100644 --- a/src/test/csrc/difftest/difftest.cpp +++ b/src/test/csrc/difftest/difftest.cpp @@ -103,15 +103,19 @@ void difftest_finish() { } #ifdef CONFIG_DIFFTEST_SQUASH +svScope squashScope; +void set_squash_scope() { + squashScope = svGetScope(); +} + extern "C" void set_squash_enable(int enable); -void difftest_squash_set(int enable, const char *scope_name = "TOP.SimTop.SquashEndpoint.control") { - auto scope = svGetScopeFromName(scope_name); - if (scope == NULL) { - printf("Error: Could not retrieve scope with name '%s'\n", scope_name); - assert(scope); - } - svSetScope(scope); - set_squash_enable(rand()); +void difftest_squash_enable(int enable) { + if (squashScope == NULL) { + printf("Error: Could not retrieve squash scope, set first\n"); + assert(squashScope); + } + svSetScope(squashScope); + set_squash_enable(enable); } #endif // CONFIG_DIFFTEST_SQUASH diff --git a/src/test/csrc/difftest/difftest.h b/src/test/csrc/difftest/difftest.h index a38f767e1..714a1e73c 100644 --- a/src/test/csrc/difftest/difftest.h +++ b/src/test/csrc/difftest/difftest.h @@ -369,7 +369,8 @@ void difftest_trace_write(int step); int init_nemuproxy(size_t); #ifdef CONFIG_DIFFTEST_SQUASH -extern "C" void difftest_squash_set(int enable, const char *scope_name); +extern "C" void set_squash_scope(); +extern "C" void difftest_squash_enable(int enable); #endif // CONFIG_DIFFTEST_SQUASH #endif