Skip to content

Commit

Permalink
Support parseArgs for GatewayConfig (#301)
Browse files Browse the repository at this point in the history
We add an parseArgs interface of difftest for style and GatewayConfig.
User can pass DifftestArgs from top module which extends App trait, and
it will return filter args for subsequent parsing.

Now, we support use "--difftest-config ..." to specify GatewayConfig, each
letter represents an optimization measure. Corresponding change for NutShell/XiangShan will be added with next time bump difftest.
  • Loading branch information
klin02 authored Mar 6, 2024
1 parent 1b3c3aa commit 666a1ec
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 63 deletions.
45 changes: 8 additions & 37 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,8 @@ jobs:
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
sed -i 's/isBatch: Boolean = false/isBatch: Boolean = true/' difftest/src/main/scala/Gateway.scala
make emu -j2
make emu MILL_ARGS="--difftest-config B" -j2
./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
- name: Difftest with Global DPI-C Enable
run: |
Expand All @@ -181,10 +179,8 @@ jobs:
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
sed -i 's/hasGlobalEnable: Boolean = false/hasGlobalEnable: Boolean = true/' difftest/src/main/scala/Gateway.scala
make emu -j2
make emu MILL_ARGS="--difftest-config E" -j2
./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
- name: Difftest with Squash and Global Enable
run: |
Expand All @@ -193,11 +189,8 @@ jobs:
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
sed -i 's/hasGlobalEnable: Boolean = false/hasGlobalEnable: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/isSquash: Boolean = false/isSquash: Boolean = true/' difftest/src/main/scala/Gateway.scala
make emu -j2
make emu MILL_ARGS="--difftest-config ES" -j2
./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
- name: Difftest with Squash Batch and Global Enable
run: |
Expand All @@ -206,12 +199,8 @@ jobs:
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
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 -j2
make emu MILL_ARGS="--difftest-config ESB" -j2
./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
test-difftest-fuzzing:
# This test runs on ubuntu-20.04 for two reasons:
Expand Down Expand Up @@ -315,11 +304,9 @@ jobs:
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
sed -i 's/hasDutZone: Boolean = false/hasDutZone: Boolean = true/' difftest/src/main/scala/Gateway.scala
make simv DIFFTEST_PERFCNT=1 VCS=verilator -j2
make simv MILL_ARGS="--difftest-config Z" DIFFTEST_PERFCNT=1 VCS=verilator -j2
./build/simv +workload=./ready-to-run/microbench.bin +e=0 +no-diff +max-cycles=100000
./build/simv +workload=./ready-to-run/microbench.bin +e=0 +diff=./ready-to-run/riscv64-nemu-interpreter-so
cd difftest && git restore src
- name: Verilator Build with VCS Top (with Batch InternalStep PerfCnt)
run: |
Expand All @@ -328,12 +315,9 @@ jobs:
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
sed -i 's/isBatch: Boolean = false/isBatch: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/hasInternalStep: Boolean = false/hasInternalStep: Boolean = true/' difftest/src/main/scala/Gateway.scala
make simv DIFFTEST_PERFCNT=1 VCS=verilator -j2
make simv MILL_ARGS="--difftest-config BI" DIFFTEST_PERFCNT=1 VCS=verilator -j2
./build/simv +workload=./ready-to-run/microbench.bin +e=0 +no-diff +max-cycles=100000
./build/simv +workload=./ready-to-run/microbench.bin +e=0 +diff=./ready-to-run/riscv64-nemu-interpreter-so
cd difftest && git restore src
- name: Verilator Build with VCS Top (with DutZone GlobalEnable Squash SquashReplay Batch PerfCnt)
run: |
Expand All @@ -342,15 +326,9 @@ jobs:
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
sed -i 's/hasDutZone: Boolean = false/hasDutZone: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/hasGlobalEnable: Boolean = false/hasGlobalEnable: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/isSquash: Boolean = false/isSquash: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/squashReplay: Boolean = false/squashReplay: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/isBatch: Boolean = false/isBatch: Boolean = true/' difftest/src/main/scala/Gateway.scala
make simv DIFFTEST_PERFCNT=1 VCS=verilator -j2
make simv MILL_ARGS="--difftest-config ZESRB" DIFFTEST_PERFCNT=1 VCS=verilator -j2
./build/simv +workload=./ready-to-run/microbench.bin +e=0 +no-diff +max-cycles=100000
./build/simv +workload=./ready-to-run/microbench.bin +e=0 +diff=./ready-to-run/riscv64-nemu-interpreter-so
cd difftest && git restore src
- name: Verilator Build with VCS Top (with GlobalEnable Squash SquashReplay Batch InternalStep NonBlock PerfCnt)
run: |
Expand All @@ -359,16 +337,9 @@ jobs:
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
sed -i 's/hasGlobalEnable: Boolean = false/hasGlobalEnable: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/isSquash: Boolean = false/isSquash: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/squashReplay: Boolean = false/squashReplay: 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/hasInternalStep: Boolean = false/hasInternalStep: Boolean = true/' difftest/src/main/scala/Gateway.scala
sed -i 's/isNonBlock: Boolean = false/isNonBlock: Boolean = true/' difftest/src/main/scala/Gateway.scala
make simv DIFFTEST_PERFCNT=1 VCS=verilator -j2
make simv MILL_ARGS="--difftest-config ESRBIN" DIFFTEST_PERFCNT=1 VCS=verilator -j2
./build/simv +workload=./ready-to-run/microbench.bin +e=0 +no-diff +max-cycles=100000
./build/simv +workload=./ready-to-run/microbench.bin +e=0 +diff=./ready-to-run/riscv64-nemu-interpreter-so
cd difftest && git restore src
- name: Verilator Build with VCS Top (with workload-list)
run : |
Expand Down
48 changes: 28 additions & 20 deletions src/main/scala/Difftest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import difftest.gateway.{Gateway, GatewayConfig}

import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Paths}
import scala.annotation.tailrec
import scala.collection.mutable.ListBuffer

trait DifftestWithCoreid {
Expand Down Expand Up @@ -259,20 +260,33 @@ trait DifftestModule[T <: DifftestBundle] {

object DifftestModule {
private val enabled = true
private val instances = ListBuffer.empty[(DifftestBundle, String)]
private val instances = ListBuffer.empty[DifftestBundle]
private val cppMacros = ListBuffer.empty[String]
private val vMacros = ListBuffer.empty[String]

def parseArgs(args: Array[String]): Array[String] = {
@tailrec
def nextOption(args: Array[String], list: List[String]): Array[String] = {
list match {
case Nil => args
case "--difftest-config" :: config :: tail =>
Gateway.setConfig(config)
nextOption(args.patch(args.indexOf("--difftest-config"), Nil, 2), tail)
case option :: tail => nextOption(args, tail)
}
}
nextOption(args, args.toList)
}

def apply[T <: DifftestBundle](
gen: T,
style: String = "dpic",
dontCare: Boolean = false,
delay: Int = 0,
): T = {
val difftest: T = Wire(gen)
if (enabled) {
register(gen, style)
val sink = Gateway(gen, style)
register(gen)
val sink = Gateway(gen)
sink := Delayer(difftest, delay)
sink.coreid := difftest.coreid
}
Expand All @@ -282,22 +296,19 @@ object DifftestModule {
difftest
}

def register[T <: DifftestBundle](gen: T, style: String): Int = {
def register[T <: DifftestBundle](gen: T): Int = {
val id = instances.length
val element = (gen, style)
instances += element
instances += gen
id
}

def finish(cpu: String, cppHeader: Option[String] = Some("dpic")): DifftestTopIO = {
def finish(cpu: String): DifftestTopIO = {
val gateway = Gateway.collect()
cppMacros ++= gateway.cppMacros
vMacros ++= gateway.vMacros
instances ++= gateway.instances

if (cppHeader.isDefined) {
generateCppHeader(cpu, cppHeader.get, gateway.structPacked.getOrElse(false))
}
generateCppHeader(cpu, gateway.structPacked.getOrElse(false))
generateVeriogHeader()

if (enabled) {
Expand Down Expand Up @@ -326,7 +337,7 @@ object DifftestModule {
difftest
}

def generateCppHeader(cpu: String, style: String, structPacked: Boolean): Unit = {
def generateCppHeader(cpu: String, structPacked: Boolean): Unit = {
val difftestCpp = ListBuffer.empty[String]
difftestCpp += "#ifndef __DIFFSTATE_H__"
difftestCpp += "#define __DIFFSTATE_H__"
Expand All @@ -341,18 +352,15 @@ object DifftestModule {
difftestCpp += s"#define CPU_$cpu_s"
difftestCpp += ""

val headerInstances = instances.filter(_._2 == style)

val numCores = headerInstances.count(_._1.isUniqueIdentifier)
if (headerInstances.nonEmpty) {
val numCores = instances.count(_.isUniqueIdentifier)
if (instances.nonEmpty) {
difftestCpp += s"#define NUM_CORES $numCores"
difftestCpp += ""
}

val uniqBundles = headerInstances.groupBy(_._1.desiredModuleName)
val uniqBundles = instances.groupBy(_.desiredModuleName)
// Create cpp declaration for each bundle type
uniqBundles.values
.map(_.map(_._1))
.foreach(bundles => {
val bundleType = bundles.head
difftestCpp += bundleType.toCppDeclMacro
Expand All @@ -372,8 +380,8 @@ object DifftestModule {

// create top-level difftest struct
difftestCpp += "typedef struct {"
for ((className, cppInstances) <- uniqBundles.toSeq.sortBy(_._2.head._1.order)) {
val bundleType = cppInstances.head._1
for ((className, cppInstances) <- uniqBundles.toSeq.sortBy(_._2.head.order)) {
val bundleType = cppInstances.head
val instanceName = bundleType.desiredCppName
val cppIsArray = bundleType.isInstanceOf[DifftestWithIndex] || bundleType.isFlatten
val nInstances = cppInstances.length
Expand Down
27 changes: 21 additions & 6 deletions src/main/scala/Gateway.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ case class GatewayConfig(
hasInternalStep: Boolean = false,
isNonBlock: Boolean = false,
) {
if (squashReplay) require(isSquash)
if (hasInternalStep) require(isBatch)
def dutZoneSize: Int = if (hasDutZone) 2 else 1
def dutZoneWidth: Int = log2Ceil(dutZoneSize)
def dutBufLen: Int = if (isBatch) batchSize else 1
Expand Down Expand Up @@ -70,12 +68,16 @@ case class GatewayConfig(
if (hasInternalStep) macros += "CONFIG_DIFFTEST_INTERNAL_STEP"
macros.toSeq
}
def check(): Unit = {
if (squashReplay) require(isSquash)
if (hasInternalStep) require(isBatch)
}
}

case class GatewayResult(
cppMacros: Seq[String] = Seq(),
vMacros: Seq[String] = Seq(),
instances: Seq[(DifftestBundle, String)] = Seq(),
instances: Seq[DifftestBundle] = Seq(),
structPacked: Option[Boolean] = None,
step: Option[UInt] = None,
) {
Expand All @@ -94,8 +96,21 @@ object Gateway {
private val instances = ListBuffer.empty[DifftestBundle]
private var config = GatewayConfig()

def apply[T <: DifftestBundle](gen: T, style: String): T = {
config = GatewayConfig(style = style)
def setConfig(cfg: String): Unit = {
cfg.foreach {
case 'E' => config = config.copy(hasGlobalEnable = true)
case 'S' => config = config.copy(isSquash = true)
case 'R' => config = config.copy(squashReplay = true)
case 'Z' => config = config.copy(hasDutZone = true)
case 'B' => config = config.copy(isBatch = true)
case 'I' => config = config.copy(hasInternalStep = true)
case 'N' => config = config.copy(isNonBlock = true)
case x => println(s"Unknown Gateway Config $x")
}
config.check()
}

def apply[T <: DifftestBundle](gen: T): T = {
if (config.needEndpoint) {
register(WireInit(0.U.asTypeOf(gen)))
} else {
Expand Down Expand Up @@ -133,7 +148,7 @@ object Gateway {
}

class GatewayEndpoint(signals: Seq[DifftestBundle], config: GatewayConfig) extends Module {
val instances = if (config.needTraceInfo) Seq((new DiffTraceInfo(config), config.style)) else Seq()
val instances = if (config.needTraceInfo) Seq(new DiffTraceInfo(config)) else Seq()
val in = WireInit(0.U.asTypeOf(MixedVec(signals.map(_.cloneType))))
val in_pack = WireInit(0.U.asTypeOf(MixedVec(signals.map(gen => UInt(gen.getWidth.W)))))
for ((data, id) <- in_pack.zipWithIndex) {
Expand Down

0 comments on commit 666a1ec

Please sign in to comment.