Skip to content

Commit

Permalink
Squash: move into Gateway, get Scope from initial
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
klin02 committed Dec 8, 2023
1 parent c9eaaff commit 94d5f8b
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 81 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/Difftest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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) {
Expand All @@ -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)
}
Expand Down
40 changes: 26 additions & 14 deletions src/main/scala/Gateway.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand All @@ -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
Expand All @@ -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))
Expand Down Expand Up @@ -162,21 +171,24 @@ 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)
}
}

var macros = GatewaySink.collect(config)
if (config.isBatch) {
macros ++= Seq("CONFIG_DIFFTEST_BATCH", s"DIFFTEST_BATCH_SIZE ${config.batchSize}")
}
if (config.isSquash) {
macros ++= Squash.collect()
}
}


Expand Down
61 changes: 9 additions & 52 deletions src/main/scala/Squash.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)))

Expand Down Expand Up @@ -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 {
Expand All @@ -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
|
Expand Down
20 changes: 12 additions & 8 deletions src/test/csrc/difftest/difftest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion src/test/csrc/difftest/difftest.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 94d5f8b

Please sign in to comment.