diff --git a/.circleci/config.yml b/.circleci/config.yml index bb5b3a509a..07222b7103 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -317,6 +317,35 @@ jobs: key: tracegen-{{ .Branch }}-{{ .Revision }} paths: - "/home/riscvuser/project" + prepare-tracegen-boom: + docker: + - image: riscvboom/riscvboom-images:0.0.12 + environment: + JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit + TERM: dumb + steps: + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" + - checkout + - run: + name: Create hash of toolchains + command: | + .circleci/create-hash.sh + - restore_cache: + keys: + - riscv-tools-installed-v2-{{ checksum "../riscv-tools.hash" }} + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} + - run: + name: Building the tracegen-boom subproject using Verilator + command: .circleci/do-rtl-build.sh tracegen-boom + no_output_timeout: 120m + - save_cache: + key: tracegen-boom-{{ .Branch }}-{{ .Revision }} + paths: + - "/home/riscvuser/project" prepare-firesim: docker: - image: riscvboom/riscvboom-images:0.0.12 @@ -540,6 +569,30 @@ jobs: - run: name: Run tracegen tests command: .circleci/run-tests.sh tracegen + tracegen-boom-run-tests: + docker: + - image: riscvboom/riscvboom-images:0.0.12 + environment: + JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit + TERM: dumb + steps: + - checkout + - run: + name: Create hash of toolchains + command: | + .circleci/create-hash.sh + - restore_cache: + keys: + - riscv-tools-installed-v2-{{ checksum "../riscv-tools.hash" }} + - restore_cache: + keys: + - tracegen-boom-{{ .Branch }}-{{ .Revision }} + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} + - run: + name: Run tracegen-boom tests + command: .circleci/run-tests.sh tracegen-boom firesim-run-tests: docker: - image: riscvboom/riscvboom-images:0.0.12 @@ -665,6 +718,11 @@ workflows: - install-riscv-toolchain - install-verilator + - prepare-tracegen-boom: + requires: + - install-riscv-toolchain + - install-verilator + - prepare-firesim: requires: - install-riscv-toolchain @@ -708,6 +766,10 @@ workflows: requires: - prepare-tracegen + - tracegen-boom-run-tests: + requires: + - prepare-tracegen-boom + # Run the firesim tests - firesim-run-tests: requires: diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh index ffd45ffb6b..0c0457bf41 100755 --- a/.circleci/defaults.sh +++ b/.circleci/defaults.sh @@ -48,5 +48,6 @@ mapping["rocketchip"]="SUB_PROJECT=rocketchip" mapping["blockdevrocketchip"]="SUB_PROJECT=example CONFIG=SimBlockDeviceRocketConfig TOP=TopWithBlockDevice" mapping["hwacha"]="SUB_PROJECT=example CONFIG=HwachaRocketConfig" mapping["tracegen"]="SUB_PROJECT=tracegen CONFIG=NonBlockingTraceGenL2Config" +mapping["tracegen-boom"]="SUB_PROJECT=tracegen CONFIG=BoomTraceGenConfig" mapping["firesim"]="DESIGN=FireSim TARGET_CONFIG=DDR3FRFCFSLLC4MB_FireSimRocketChipConfig PLATFORM_CONFIG=BaseF1Config" mapping["fireboom"]="DESIGN=FireSim TARGET_CONFIG=DDR3FRFCFSLLC4MB_FireSimBoomConfig PLATFORM_CONFIG=BaseF1Config" diff --git a/.circleci/run-tests.sh b/.circleci/run-tests.sh index 138e27855a..46806d83b9 100755 --- a/.circleci/run-tests.sh +++ b/.circleci/run-tests.sh @@ -53,6 +53,9 @@ case $1 in tracegen) run_tracegen ${mapping[$1]} ;; + tracegen-boom) + run_tracegen ${mapping[$1]} + ;; *) echo "No set of tests for $1. Did you spell it right?" exit 1 diff --git a/build.sbt b/build.sbt index e252cfa912..14f9d9b4cd 100644 --- a/build.sbt +++ b/build.sbt @@ -127,7 +127,7 @@ lazy val example = conditionalDependsOn(project in file("generators/example")) .settings(commonSettings) lazy val tracegen = conditionalDependsOn(project in file("generators/tracegen")) - .dependsOn(rocketchip, sifive_cache) + .dependsOn(rocketchip, sifive_cache, boom) .settings(commonSettings) lazy val utilities = conditionalDependsOn(project in file("generators/utilities")) diff --git a/generators/tracegen/src/main/scala/Configs.scala b/generators/tracegen/src/main/scala/Configs.scala index e3536e6ada..536412c12c 100644 --- a/generators/tracegen/src/main/scala/Configs.scala +++ b/generators/tracegen/src/main/scala/Configs.scala @@ -10,7 +10,7 @@ import freechips.rocketchip.rocket.DCacheParams import freechips.rocketchip.tile.{MaxHartIdBits, XLen} import scala.math.{max, min} -class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) +class WithTraceGen(params: Seq[DCacheParams], boom_params: Seq[DCacheParams] = Nil, nReqs: Int = 8192) extends Config((site, here, up) => { case TraceGenKey => params.map { dcp => TraceGenParams( dcache = Some(dcp), @@ -32,7 +32,28 @@ class WithTraceGen(params: Seq[DCacheParams], nReqs: Int = 8192) memStart = site(ExtMem).get.master.base, numGens = params.size) } - case MaxHartIdBits => if (params.size == 1) 1 else log2Ceil(params.size) + case BoomTraceGenKey => boom_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 + boom_params.size == 1) 1 + else log2Ceil(params.size + boom_params.size) }) class TraceGenConfig extends Config( @@ -43,6 +64,10 @@ class NonBlockingTraceGenConfig extends Config( new WithTraceGen(List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++ new BaseConfig) +class BoomTraceGenConfig extends Config( + new WithTraceGen(Nil, List.fill(2) { DCacheParams(nMSHRs = 8, 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( diff --git a/generators/tracegen/src/main/scala/System.scala b/generators/tracegen/src/main/scala/System.scala index 57d048a3c5..1830767874 100644 --- a/generators/tracegen/src/main/scala/System.scala +++ b/generators/tracegen/src/main/scala/System.scala @@ -6,12 +6,18 @@ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, BufferParams} import freechips.rocketchip.groundtest.{DebugCombiner, TraceGenParams} import freechips.rocketchip.subsystem._ -case object TraceGenKey extends Field[Seq[TraceGenParams]] +case object BoomTraceGenKey extends Field[Seq[TraceGenParams]](Nil) +case object TraceGenKey extends Field[Seq[TraceGenParams]](Nil) trait HasTraceGenTiles { this: BaseSubsystem => - val tiles = p(TraceGenKey).zipWithIndex.map { case (params, i) => + val rocket_tiles = p(TraceGenKey).zipWithIndex.map { case (params, i) => LazyModule(new TraceGenTile(i, params, p)) } + val boom_tiles = p(BoomTraceGenKey).zipWithIndex.map { case (params, i) => + LazyModule(new BoomTraceGenTile(i, params, p)) + } + + val tiles = rocket_tiles ++ boom_tiles tiles.foreach { t => sbus.fromTile(None, buffer = BufferParams.default) { t.masterNode } @@ -26,7 +32,10 @@ trait HasTraceGenTilesModuleImp extends LazyModuleImp { t.module.constants.hartid := i.U } - val status = DebugCombiner(outer.tiles.map(_.module.status)) + val status = DebugCombiner( + outer.rocket_tiles.map(_.module.status) ++ + outer.boom_tiles.map(_.module.status) + ) success := status.finished } diff --git a/generators/tracegen/src/main/scala/Tile.scala b/generators/tracegen/src/main/scala/Tile.scala index 1897224de3..1ac931706d 100644 --- a/generators/tracegen/src/main/scala/Tile.scala +++ b/generators/tracegen/src/main/scala/Tile.scala @@ -1,14 +1,19 @@ package tracegen import chisel3._ +import chisel3.util._ 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.rocket.{DCache, NonBlockingDCache, SimpleHellaCacheIF, HellaCacheExceptions, HellaCacheReq} +import freechips.rocketchip.rocket.constants.{MemoryOpConstants} +import freechips.rocketchip.tile.{BaseTile, BaseTileModuleImp, HartsWontDeduplicate, TileKey} import freechips.rocketchip.tilelink.{TLInwardNode, TLIdentityNode} import freechips.rocketchip.interrupts._ +import boom.lsu.{BoomNonBlockingDCache, LSU} +import boom.common.{BoomTileParams, MicroOp, BoomCoreParams} + class TraceGenTile(val id: Int, val params: TraceGenParams, q: Parameters) extends BaseTile(params, SynchronousCrossing(), HartsWontDeduplicate(params), q) { val dcache = params.dcache.map { dc => LazyModule( @@ -29,6 +34,180 @@ class TraceGenTile(val id: Int, val params: TraceGenParams, q: Parameters) override lazy val module = new TraceGenTileModuleImp(this) } +class BoomTraceGenTile(val id: Int, val params: TraceGenParams, q: Parameters) + extends BaseTile(params, SynchronousCrossing(), HartsWontDeduplicate(params), q) { + val boom_params = p.alterMap(Map(TileKey -> BoomTileParams( + dcache=params.dcache, + core=BoomCoreParams(nPMPs=0, numLdqEntries=32, numStqEntries=32, useVM=false)))) + val dcache = params.dcache.map { + dc => LazyModule(new BoomNonBlockingDCache(hartId)(boom_params)) + }.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 BoomTraceGenTileModuleImp(this) +} + +class BoomTraceGenTileModuleImp(outer: BoomTraceGenTile) + extends BaseTileModuleImp(outer) with MemoryOpConstants { + + val status = IO(new GroundTestStatus) + + val tracegen = Module(new TraceGenerator(outer.params)) + tracegen.io.mem := DontCare + tracegen.io.hartid := constants.hartid + + val ptw = Module(new DummyPTW(1)) + + val lsu = Module(new LSU()(outer.boom_params, outer.dcache.module.edge)) + lsu.io.core.tsc_reg := 0.U(1.W) + ptw.io.requestors.head <> lsu.io.ptw + outer.dcache.module.io.lsu <> lsu.io.dmem + + + val rob_sz = outer.boom_params(TileKey).core.asInstanceOf[BoomCoreParams].numRobEntries + val rob = Reg(Vec(rob_sz, new HellaCacheReq)) + val rob_respd = RegInit(VecInit((~(0.U(rob_sz.W))).asBools)) + val rob_uop = Reg(Vec(rob_sz, new MicroOp()(outer.boom_params))) + val rob_bsy = RegInit(VecInit(0.U(rob_sz.W).asBools)) + val rob_head = RegInit(0.U(log2Up(rob_sz).W)) + val rob_tail = RegInit(0.U(log2Up(rob_sz).W)) + val rob_wait_till_empty = RegInit(false.B) + val ready_for_amo = rob_tail === rob_head && lsu.io.core.fencei_rdy + when (ready_for_amo) { + rob_wait_till_empty := false.B + } + + def WrapInc(idx: UInt, max: Int): UInt = { + Mux(idx === (max-1).U, 0.U, idx + 1.U) + } + + + tracegen.io.mem.req.ready := (!rob_bsy(rob_tail) && + !rob_wait_till_empty && + (ready_for_amo || !(isAMO(tracegen.io.mem.req.bits.cmd) || tracegen.io.mem.req.bits.cmd === M_XLR || tracegen.io.mem.req.bits.cmd === M_XSC)) && + (WrapInc(rob_tail, rob_sz) =/= rob_head) && + !(lsu.io.core.ldq_full(0) && isRead(tracegen.io.mem.req.bits.cmd)) && + !(lsu.io.core.stq_full(0) && isWrite(tracegen.io.mem.req.bits.cmd)) + ) + + val tracegen_uop = WireInit((0.U).asTypeOf(new MicroOp()(outer.boom_params))) + tracegen_uop.uses_ldq := isRead(tracegen.io.mem.req.bits.cmd) && !isWrite(tracegen.io.mem.req.bits.cmd) + tracegen_uop.uses_stq := isWrite(tracegen.io.mem.req.bits.cmd) + tracegen_uop.rob_idx := rob_tail + tracegen_uop.uopc := tracegen.io.mem.req.bits.tag + tracegen_uop.mem_size := tracegen.io.mem.req.bits.size + tracegen_uop.mem_cmd := tracegen.io.mem.req.bits.cmd + tracegen_uop.mem_signed := tracegen.io.mem.req.bits.signed + tracegen_uop.ldq_idx := lsu.io.core.dis_ldq_idx(0) + tracegen_uop.stq_idx := lsu.io.core.dis_stq_idx(0) + tracegen_uop.is_amo := isAMO(tracegen.io.mem.req.bits.cmd) || tracegen.io.mem.req.bits.cmd === M_XSC + tracegen_uop.ctrl.is_load := isRead(tracegen.io.mem.req.bits.cmd) && !isWrite(tracegen.io.mem.req.bits.cmd) + tracegen_uop.ctrl.is_sta := isWrite(tracegen.io.mem.req.bits.cmd) + tracegen_uop.ctrl.is_std := isWrite(tracegen.io.mem.req.bits.cmd) + + lsu.io.core.dis_uops(0).valid := tracegen.io.mem.req.fire() + lsu.io.core.dis_uops(0).bits := tracegen_uop + + when (tracegen.io.mem.req.fire()) { + rob_tail := WrapInc(rob_tail, rob_sz) + rob_bsy(rob_tail) := true.B + rob_uop(rob_tail) := tracegen_uop + rob_respd(rob_tail) := false.B + rob(rob_tail) := tracegen.io.mem.req.bits + when ( + isAMO(tracegen.io.mem.req.bits.cmd) || + tracegen.io.mem.req.bits.cmd === M_XLR || + tracegen.io.mem.req.bits.cmd === M_XSC + ) { + rob_wait_till_empty := true.B + } + } + + lsu.io.core.fp_stdata.valid := false.B + lsu.io.core.fp_stdata.bits := DontCare + + + + lsu.io.core.commit.valids(0) := (!rob_bsy(rob_head) && rob_head =/= rob_tail && rob_respd(rob_head)) + lsu.io.core.commit.uops(0) := rob_uop(rob_head) + lsu.io.core.commit.rbk_valids(0) := false.B + lsu.io.core.commit.rollback := false.B + lsu.io.core.commit.fflags := DontCare + when (lsu.io.core.commit.valids(0)) { + rob_head := WrapInc(rob_head, rob_sz) + } + + when (lsu.io.core.clr_bsy(0).valid) { + rob_bsy(lsu.io.core.clr_bsy(0).bits) := false.B + } + when (lsu.io.core.clr_unsafe(0).valid && rob(lsu.io.core.clr_unsafe(0).bits).cmd =/= M_XLR) { + rob_bsy(lsu.io.core.clr_unsafe(0).bits) := false.B + } + when (lsu.io.core.exe(0).iresp.valid) { + rob_bsy(lsu.io.core.exe(0).iresp.bits.uop.rob_idx) := false.B + } + + + assert(!lsu.io.core.lxcpt.valid) + + lsu.io.core.exe(0).req.valid := RegNext(tracegen.io.mem.req.fire()) + lsu.io.core.exe(0).req.bits := DontCare + lsu.io.core.exe(0).req.bits.uop := RegNext(tracegen_uop) + lsu.io.core.exe(0).req.bits.addr := RegNext(tracegen.io.mem.req.bits.addr) + lsu.io.core.exe(0).req.bits.data := RegNext(tracegen.io.mem.req.bits.data) + + tracegen.io.mem.resp.valid := lsu.io.core.exe(0).iresp.valid + tracegen.io.mem.resp.bits := DontCare + tracegen.io.mem.resp.bits.tag := lsu.io.core.exe(0).iresp.bits.uop.uopc + tracegen.io.mem.resp.bits.size := lsu.io.core.exe(0).iresp.bits.uop.mem_size + tracegen.io.mem.resp.bits.data := lsu.io.core.exe(0).iresp.bits.data + + val store_resp_idx = PriorityEncoder((0 until rob_sz) map {i => + !rob_respd(i) && isWrite(rob(i).cmd) + }) + val can_do_store_resp = ~rob_respd(store_resp_idx) && isWrite(rob(store_resp_idx).cmd) && !isRead(rob(store_resp_idx).cmd) + when (can_do_store_resp && !lsu.io.core.exe(0).iresp.valid) { + rob_respd(store_resp_idx) := true.B + tracegen.io.mem.resp.valid := true.B + tracegen.io.mem.resp.bits.tag := rob(store_resp_idx).tag + } + + when (lsu.io.core.exe(0).iresp.valid) { + rob_respd(lsu.io.core.exe(0).iresp.bits.uop.rob_idx) := true.B + } + + lsu.io.core.exe(0).fresp.ready := true.B + lsu.io.core.exe(0).iresp.ready := true.B + + + lsu.io.core.exception := false.B + lsu.io.core.fence_dmem := false.B + + lsu.io.hellacache := DontCare + lsu.io.hellacache.req.valid := false.B + + lsu.io.core.rob_pnr_idx := rob_tail + lsu.io.core.commit_load_at_rob_head := false.B + + lsu.io.core.brinfo := DontCare + lsu.io.core.brinfo.valid := false.B + lsu.io.core.rob_head_idx := rob_head + + status.finished := tracegen.io.finished + status.timeout.valid := tracegen.io.timeout + status.timeout.bits := 0.U + status.error.valid := false.B +} + class TraceGenTileModuleImp(outer: TraceGenTile) extends BaseTileModuleImp(outer) { val status = IO(new GroundTestStatus)