diff --git a/build.sbt b/build.sbt index d353a497..8e09a6ab 100644 --- a/build.sbt +++ b/build.sbt @@ -109,6 +109,10 @@ lazy val example = conditionalDependsOn(project in file("generators/example")) .dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities) .settings(commonSettings) +lazy val tracegen = conditionalDependsOn(project in file("generators/tracegen")) + .dependsOn(rocketchip, sifive_cache) + .settings(commonSettings) + lazy val utilities = conditionalDependsOn(project in file("generators/utilities")) .dependsOn(rocketchip, boom) .settings(commonSettings) @@ -166,7 +170,7 @@ lazy val midas = ProjectRef(firesimDir, "midas") lazy val firesimLib = ProjectRef(firesimDir, "firesimLib") lazy val firechip = (project in file("generators/firechip")) - .dependsOn(boom, icenet, testchipip, sifive_blocks, sifive_cache, utilities, midasTargetUtils, midas, firesimLib % "test->test;compile->compile") + .dependsOn(boom, icenet, testchipip, sifive_blocks, sifive_cache, utilities, tracegen, midasTargetUtils, midas, firesimLib % "test->test;compile->compile") .settings( commonSettings, testGrouping in Test := isolateAllTests( (definedTests in Test).value ) diff --git a/common.mk b/common.mk index 16208e82..764495f3 100644 --- a/common.mk +++ b/common.mk @@ -6,11 +6,10 @@ SHELL=/bin/bash ######################################################################################### # variables to get all *.scala files ######################################################################################### -lookup_scala_srcs = $(shell find -L $(1)/ -iname "*.scala" 2> /dev/null) +lookup_scala_srcs = $(shell find -L $(1)/ -name target -prune -o -iname "*.scala" -print 2> /dev/null) -PACKAGES=$(addprefix generators/, rocket-chip testchipip boom hwacha sifive-blocks sifive-cache example) \ - $(addprefix sims/firesim/sim/, . firesim-lib midas midas/targetutils) -SCALA_SOURCES=$(foreach pkg,$(PACKAGES),$(call lookup_scala_srcs,$(base_dir)/$(pkg)/src/main/scala)) +SOURCE_DIRS=$(addprefix $(base_dir)/,generators sims/firesim/sim) +SCALA_SOURCES=$(call lookup_scala_srcs,$(SOURCE_DIRS)) ######################################################################################### # rocket and testchipip classes diff --git a/docs/Customization/Adding-An-Accelerator.rst b/docs/Customization/Adding-An-Accelerator.rst index 0b688ea6..90a74733 100644 --- a/docs/Customization/Adding-An-Accelerator.rst +++ b/docs/Customization/Adding-An-Accelerator.rst @@ -61,15 +61,6 @@ the ``example`` project, change the final line in build.sbt to the following. lazy val example = (project in file(".")).settings(commonSettings).dependsOn(testchipip, yourproject) -Finally, add ``yourproject`` to the ``PACKAGES`` variable in the ``common.mk`` file in the Chipyard top level. -This will allow make to detect that your source files have changed when building the Verilog/FIRRTL files. - -.. code-block:: shell - - PACKAGES=$(addprefix generators/, rocket-chip testchipip boom hwacha sifive-blocks sifive-cache example yourproject) \ - $(addprefix sims/firesim/sim/, . firesim-lib midas midas/targetutils) - - MMIO Peripheral ------------------ diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 85c82753..ddfb2548 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -4,14 +4,18 @@ import java.io.File import chisel3.util.{log2Up} import freechips.rocketchip.config.{Parameters, Config} +import freechips.rocketchip.groundtest.TraceGenParams import freechips.rocketchip.tile._ import freechips.rocketchip.tilelink._ +import freechips.rocketchip.rocket.DCacheParams import freechips.rocketchip.subsystem._ import freechips.rocketchip.devices.tilelink.BootROMParams import freechips.rocketchip.devices.debug.DebugModuleParams import boom.common.BoomTilesKey import testchipip.{WithBlockDevice, BlockDeviceKey, BlockDeviceConfig} import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams} +import scala.math.{min, max} +import tracegen.TraceGenKey import icenet._ class WithBootROM extends Config((site, here, up) => { @@ -205,3 +209,69 @@ class SupernodeFireSimRocketChipOctaCoreConfig extends Config( new WithExtMemSize(0x200000000L) ++ // 8GB new FireSimRocketChipOctaCoreConfig) +class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) + extends Config((site, here, up) => { + case TraceGenKey => params.map { dcp => TraceGenParams( + dcache = Some(dcp), + wordBits = site(XLen), + addrBits = 48, + addrBag = { + val nSets = dcp.nSets + val nWays = dcp.nWays + val blockOffset = site(SystemBusKey).blockOffset + val nBeats = min(2, site(SystemBusKey).blockBeats) + val beatBytes = site(SystemBusKey).beatBytes + List.tabulate(2 * nWays) { i => + Seq.tabulate(nBeats) { j => + BigInt((j * beatBytes) + ((i * nSets) << blockOffset)) + } + }.flatten + }, + maxRequests = nReqs, + memStart = site(ExtMem).get.master.base, + numGens = params.size) + } + case MaxHartIdBits => log2Up(params.size) +}) + +class FireSimTraceGenConfig extends Config( + new WithTraceGen( + List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++ + new FireSimRocketChipConfig) + +class WithL2TraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) + extends Config((site, here, up) => { + case TraceGenKey => params.map { dcp => TraceGenParams( + dcache = Some(dcp), + wordBits = site(XLen), + addrBits = 48, + addrBag = { + val sbp = site(SystemBusKey) + val l2p = site(InclusiveCacheKey) + val nSets = max(l2p.sets, dcp.nSets) + val nWays = max(l2p.ways, dcp.nWays) + val nBanks = site(BankedL2Key).nBanks + val blockOffset = sbp.blockOffset + val nBeats = min(2, sbp.blockBeats) + val beatBytes = sbp.beatBytes + List.tabulate(2 * nWays) { i => + Seq.tabulate(nBeats) { j => + BigInt((j * beatBytes) + ((i * nSets * nBanks) << blockOffset)) + } + }.flatten + }, + maxRequests = nReqs, + memStart = site(ExtMem).get.master.base, + numGens = params.size) + } + case MaxHartIdBits => log2Up(params.size) +}) + +class FireSimTraceGenL2Config extends Config( + new WithL2TraceGen( + List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++ + new WithInclusiveCache( + nBanks = 4, + capacityKB = 1024, + outerLatencyCycles = 50) ++ + new FireSimRocketChipConfig) diff --git a/generators/firechip/src/main/scala/TargetMixins.scala b/generators/firechip/src/main/scala/TargetMixins.scala index 7b4d5d4f..199a22cc 100644 --- a/generators/firechip/src/main/scala/TargetMixins.scala +++ b/generators/firechip/src/main/scala/TargetMixins.scala @@ -103,4 +103,3 @@ trait HasTraceIOImp extends LazyModuleImp { trait ExcludeInvalidBoomAssertions extends LazyModuleImp { ExcludeInstanceAsserts(("NonBlockingDCache", "dtlb")) } - diff --git a/generators/firechip/src/main/scala/Targets.scala b/generators/firechip/src/main/scala/Targets.scala index 7b6ea95c..ba966fac 100644 --- a/generators/firechip/src/main/scala/Targets.scala +++ b/generators/firechip/src/main/scala/Targets.scala @@ -15,6 +15,7 @@ import utilities.{Subsystem, SubsystemModuleImp} import icenet._ import testchipip._ import testchipip.SerialAdapter.SERIAL_IF_WIDTH +import tracegen.{HasTraceGenTiles, HasTraceGenTilesModuleImp} import sifive.blocks.devices.uart._ import midas.models.AXI4BundleWithEdge import java.io.File @@ -174,3 +175,14 @@ class FireSimSupernode(implicit p: Parameters) extends Module { } } } +class FireSimTraceGen(implicit p: Parameters) extends BaseSubsystem + with HasHierarchicalBusTopology + with HasTraceGenTiles + with CanHaveFASEDOptimizedMasterAXI4MemPort { + override lazy val module = new FireSimTraceGenModuleImp(this) +} + +class FireSimTraceGenModuleImp(outer: FireSimTraceGen) + extends BaseSubsystemModuleImp(outer) + with HasTraceGenTilesModuleImp + with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp diff --git a/generators/tracegen/src/main/scala/Configs.scala b/generators/tracegen/src/main/scala/Configs.scala new file mode 100644 index 00000000..e3536e6a --- /dev/null +++ b/generators/tracegen/src/main/scala/Configs.scala @@ -0,0 +1,76 @@ +package tracegen + +import chisel3._ +import chisel3.util.log2Ceil +import freechips.rocketchip.config.{Config, Parameters} +import freechips.rocketchip.groundtest.{TraceGenParams} +import freechips.rocketchip.subsystem.{ExtMem, SystemBusKey, WithInclusiveCache, InclusiveCacheKey} +import freechips.rocketchip.system.BaseConfig +import freechips.rocketchip.rocket.DCacheParams +import freechips.rocketchip.tile.{MaxHartIdBits, XLen} +import scala.math.{max, min} + +class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) + extends Config((site, here, up) => { + case TraceGenKey => params.map { dcp => TraceGenParams( + dcache = Some(dcp), + wordBits = site(XLen), + addrBits = 48, + addrBag = { + val nSets = dcp.nSets + val nWays = dcp.nWays + val blockOffset = site(SystemBusKey).blockOffset + val nBeats = min(2, site(SystemBusKey).blockBeats) + val beatBytes = site(SystemBusKey).beatBytes + List.tabulate(2 * nWays) { i => + Seq.tabulate(nBeats) { j => + BigInt((j * beatBytes) + ((i * nSets) << blockOffset)) + } + }.flatten + }, + maxRequests = nReqs, + memStart = site(ExtMem).get.master.base, + numGens = params.size) + } + case MaxHartIdBits => if (params.size == 1) 1 else log2Ceil(params.size) +}) + +class TraceGenConfig extends Config( + new WithTraceGen(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++ + new BaseConfig) + +class NonBlockingTraceGenConfig extends Config( + new WithTraceGen(List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++ + new BaseConfig) + +class WithL2TraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) + extends Config((site, here, up) => { + case TraceGenKey => params.map { dcp => TraceGenParams( + dcache = Some(dcp), + wordBits = site(XLen), + addrBits = 48, + addrBag = { + val sbp = site(SystemBusKey) + val l2p = site(InclusiveCacheKey) + val nSets = max(l2p.sets, dcp.nSets) + val nWays = max(l2p.ways, dcp.nWays) + val blockOffset = sbp.blockOffset + val nBeats = min(2, sbp.blockBeats) + val beatBytes = sbp.beatBytes + List.tabulate(2 * nWays) { i => + Seq.tabulate(nBeats) { j => + BigInt((j * beatBytes) + ((i * nSets) << blockOffset)) + } + }.flatten + }, + maxRequests = nReqs, + memStart = site(ExtMem).get.master.base, + numGens = params.size) + } + case MaxHartIdBits => if (params.size == 1) 1 else log2Ceil(params.size) +}) + +class NonBlockingTraceGenL2Config extends Config( + new WithL2TraceGen(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++ + new WithInclusiveCache ++ + new BaseConfig) diff --git a/generators/tracegen/src/main/scala/System.scala b/generators/tracegen/src/main/scala/System.scala new file mode 100644 index 00000000..57d048a3 --- /dev/null +++ b/generators/tracegen/src/main/scala/System.scala @@ -0,0 +1,43 @@ +package tracegen + +import chisel3._ +import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, BufferParams} +import freechips.rocketchip.groundtest.{DebugCombiner, TraceGenParams} +import freechips.rocketchip.subsystem._ + +case object TraceGenKey extends Field[Seq[TraceGenParams]] + +trait HasTraceGenTiles { this: BaseSubsystem => + val tiles = p(TraceGenKey).zipWithIndex.map { case (params, i) => + LazyModule(new TraceGenTile(i, params, p)) + } + + tiles.foreach { t => + sbus.fromTile(None, buffer = BufferParams.default) { t.masterNode } + } +} + +trait HasTraceGenTilesModuleImp extends LazyModuleImp { + val outer: HasTraceGenTiles + val success = IO(Output(Bool())) + + outer.tiles.zipWithIndex.map { case(t, i) => + t.module.constants.hartid := i.U + } + + val status = DebugCombiner(outer.tiles.map(_.module.status)) + success := status.finished +} + +class TraceGenSystem(implicit p: Parameters) extends BaseSubsystem + with HasTraceGenTiles + with HasHierarchicalBusTopology + with CanHaveMasterAXI4MemPort { + override lazy val module = new TraceGenSystemModuleImp(this) +} + +class TraceGenSystemModuleImp(outer: TraceGenSystem) + extends BaseSubsystemModuleImp(outer) + with HasTraceGenTilesModuleImp + with CanHaveMasterAXI4MemPortModuleImp diff --git a/generators/tracegen/src/main/scala/TestHarness.scala b/generators/tracegen/src/main/scala/TestHarness.scala new file mode 100644 index 00000000..93da430b --- /dev/null +++ b/generators/tracegen/src/main/scala/TestHarness.scala @@ -0,0 +1,27 @@ +package tracegen + +import chisel3._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy.LazyModule +import freechips.rocketchip.util.GeneratorApp + +class TestHarness(implicit p: Parameters) extends Module { + val io = IO(new Bundle { + val success = Output(Bool()) + }) + + val dut = Module(LazyModule(new TraceGenSystem).module) + io.success := dut.success + dut.connectSimAXIMem() +} + +object Generator extends GeneratorApp { + // specify the name that the generator outputs files as + val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs + + // generate files + generateFirrtl + generateAnno + generateTestSuiteMakefrags + generateArtefacts +} diff --git a/generators/tracegen/src/main/scala/Tile.scala b/generators/tracegen/src/main/scala/Tile.scala new file mode 100644 index 00000000..1897224d --- /dev/null +++ b/generators/tracegen/src/main/scala/Tile.scala @@ -0,0 +1,53 @@ +package tracegen + +import chisel3._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy.{LazyModule, SynchronousCrossing} +import freechips.rocketchip.groundtest.{TraceGenerator, TraceGenParams, DummyPTW, GroundTestStatus} +import freechips.rocketchip.rocket.{DCache, NonBlockingDCache, SimpleHellaCacheIF} +import freechips.rocketchip.tile.{BaseTile, BaseTileModuleImp, HartsWontDeduplicate} +import freechips.rocketchip.tilelink.{TLInwardNode, TLIdentityNode} +import freechips.rocketchip.interrupts._ + +class TraceGenTile(val id: Int, val params: TraceGenParams, q: Parameters) + extends BaseTile(params, SynchronousCrossing(), HartsWontDeduplicate(params), q) { + val dcache = params.dcache.map { dc => LazyModule( + if (dc.nMSHRs == 0) new DCache(hartId, crossing) + else new NonBlockingDCache(hartId)) + }.get + + val intInwardNode: IntInwardNode = IntIdentityNode() + val intOutwardNode: IntOutwardNode = IntIdentityNode() + val slaveNode: TLInwardNode = TLIdentityNode() + val ceaseNode: IntOutwardNode = IntIdentityNode() + val haltNode: IntOutwardNode = IntIdentityNode() + val wfiNode: IntOutwardNode = IntIdentityNode() + + val masterNode = visibilityNode + masterNode := dcache.node + + override lazy val module = new TraceGenTileModuleImp(this) +} + +class TraceGenTileModuleImp(outer: TraceGenTile) + extends BaseTileModuleImp(outer) { + val status = IO(new GroundTestStatus) + val halt_and_catch_fire = None + + val ptw = Module(new DummyPTW(1)) + ptw.io.requestors.head <> outer.dcache.module.io.ptw + + val tracegen = Module(new TraceGenerator(outer.params)) + tracegen.io.hartid := constants.hartid + + val dcacheIF = Module(new SimpleHellaCacheIF()) + dcacheIF.io.requestor <> tracegen.io.mem + outer.dcache.module.io.cpu <> dcacheIF.io.cache + + status.finished := tracegen.io.finished + status.timeout.valid := tracegen.io.timeout + status.timeout.bits := 0.U + status.error.valid := false.B + + assert(!tracegen.io.timeout, s"TraceGen tile ${outer.id}: request timed out") +} diff --git a/scripts/check-tracegen.sh b/scripts/check-tracegen.sh new file mode 100755 index 00000000..6462613c --- /dev/null +++ b/scripts/check-tracegen.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR=$(dirname $0) +AXE_DIR=$(realpath ${SCRIPT_DIR}/../../axe) +ROCKET_DIR=$(realpath ${SCRIPT_DIR}/../generators/rocket-chip) + +TO_AXE=${ROCKET_DIR}/scripts/toaxe.py +AXE=${AXE_DIR}/src/axe +AXE_SHRINK=${AXE_DIR}/src/axe-shrink.py + +PATH=$PATH:${AXE_DIR}/src + +grep '.*:.*#.*@' $1 > /tmp/clean-trace.txt +$TO_AXE /tmp/clean-trace.txt > /tmp/trace.axe +result=$($AXE check wmo /tmp/trace.axe) + +if [ $result != "OK" ]; then + $AXE_SHRINK wmo /tmp/trace.axe +else + echo "OK" +fi diff --git a/variables.mk b/variables.mk index 48c4ace0..b7ea0f7b 100644 --- a/variables.mk +++ b/variables.mk @@ -38,6 +38,17 @@ ifeq ($(SUB_PROJECT),example) TB ?= TestDriver TOP ?= Top endif +ifeq ($(SUB_PROJECT),tracegen) + SBT_PROJECT ?= tracegen + MODEL ?= TestHarness + VLOG_MODEL ?= $(MODEL) + MODEL_PACKAGE ?= $(SBT_PROJECT) + CONFIG ?= TraceGenConfig + CONFIG_PACKAGE ?= $(SBT_PROJECT) + GENERATOR_PACKAGE ?= $(SBT_PROJECT) + TB ?= TestDriver + TOP ?= TraceGenSystem +endif # for Rocket-chip developers ifeq ($(SUB_PROJECT),rocketchip) SBT_PROJECT ?= rocketchip