From 38d906c36fc2caa62ac4c7b0c8af33c150b9e0cd Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 15 May 2022 22:42:03 -0700 Subject: [PATCH 1/2] Add PTWProber --- src/main/scala/Configs.scala | 10 ++++++- src/main/scala/PTWProber.scala | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/PTWProber.scala diff --git a/src/main/scala/Configs.scala b/src/main/scala/Configs.scala index d7508d8a..b775b842 100644 --- a/src/main/scala/Configs.scala +++ b/src/main/scala/Configs.scala @@ -4,8 +4,9 @@ import chisel3._ import freechips.rocketchip.system.BaseConfig import freechips.rocketchip.config.{Parameters, Config} import freechips.rocketchip.tilelink._ +import freechips.rocketchip.tile._ import freechips.rocketchip.subsystem._ -import freechips.rocketchip.diplomacy.{AsynchronousCrossing, ClockCrossingType} +import freechips.rocketchip.diplomacy._ import freechips.rocketchip.unittest.UnitTests class WithRingSystemBus( @@ -117,3 +118,10 @@ class WithSerialTLROMFile(file: String) extends Config((site, here, up) => { class WithTilesStartInReset(harts: Int*) extends Config((site, here, up) => { case TileResetCtrlKey => up(TileResetCtrlKey, site).copy(initResetHarts = up(TileResetCtrlKey, site).initResetHarts ++ harts) }) + +class WithRoCCPTWProber(opcode: OpcodeSet = OpcodeSet.custom0) extends Config((site, here, up) => { + case BuildRoCC => up(BuildRoCC) ++ Seq((p: Parameters) => { + val ptw_prober = LazyModule(new PTWProber(opcode)(p)) + ptw_prober + }) +}) diff --git a/src/main/scala/PTWProber.scala b/src/main/scala/PTWProber.scala new file mode 100644 index 00000000..32dc3044 --- /dev/null +++ b/src/main/scala/PTWProber.scala @@ -0,0 +1,55 @@ +package testchipip + +import chisel3._ +import chisel3.util._ + +import freechips.rocketchip.tile._ +import freechips.rocketchip.rocket._ +import freechips.rocketchip.config.{Parameters} + +/* + * RoCC "accelerator" which translates a virtual address + * Useful for giving user programs info about physical addresses + */ +class PTWProber(opcodes: OpcodeSet)(implicit p: Parameters) extends LazyRoCC(opcodes, 1) { + override lazy val module = new LazyRoCCModuleImp(this) with HasCoreParameters { + val in_q = Queue(io.cmd) + val in_flight = RegInit(false.B) + val resp_q = Module(new Queue(new RoCCResponse, 2)) + + val vm_enabled = usingVM.B && io.ptw(0).ptbr.mode(io.ptw(0).ptbr.mode.getWidth-1) && in_q.bits.status.dprv <= PRV.S.U + + io.ptw(0).req.valid := in_q.valid && resp_q.io.enq.ready && !in_flight && vm_enabled + io.ptw(0).req.bits.valid := in_q.valid + io.ptw(0).req.bits.bits.addr := in_q.bits.rs1(vaddrBits-1, pgIdxBits) + io.ptw(0).req.bits.bits.vstage1 := false.B + io.ptw(0).req.bits.bits.stage2 := false.B + io.ptw(0).req.bits.bits.need_gpa := false.B + + when (io.ptw(0).req.fire()) { + in_flight := true.B + } .elsewhen (io.ptw(0).resp.valid) { + in_flight := false.B + } + in_q.ready := Mux(in_flight, io.ptw(0).resp.valid, !vm_enabled && resp_q.io.enq.ready) + + + resp_q.io.enq.valid := Mux(in_flight, io.ptw(0).resp.valid, !vm_enabled && in_q.valid) + resp_q.io.enq.bits.rd := in_q.bits.inst.rd + resp_q.io.enq.bits.data := Mux(in_flight, + Mux(io.ptw(0).resp.bits.pf, 0.U, Cat(io.ptw(0).resp.bits.pte.ppn, in_q.bits.rs1(pgIdxBits-1,0))), + in_q.bits.rs1) + + dontTouch(io.ptw(0).resp) + + io.resp <> resp_q.io.deq + + io.fpu_req.valid := false.B + io.fpu_req.bits := DontCare + io.fpu_resp.ready := false.B + io.mem := DontCare + io.mem.req.valid := false.B + io.busy := in_q.valid || resp_q.io.deq.valid + io.interrupt := false.B + } +} From 34f0a8296eebdb6310292bb97d4baf78ae969fa1 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 18 May 2022 14:08:57 -0700 Subject: [PATCH 2/2] Add cache flush functionality --- src/main/scala/PTWProber.scala | 72 ++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/src/main/scala/PTWProber.scala b/src/main/scala/PTWProber.scala index 32dc3044..19bc133f 100644 --- a/src/main/scala/PTWProber.scala +++ b/src/main/scala/PTWProber.scala @@ -5,6 +5,9 @@ import chisel3.util._ import freechips.rocketchip.tile._ import freechips.rocketchip.rocket._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ import freechips.rocketchip.config.{Parameters} /* @@ -12,14 +15,26 @@ import freechips.rocketchip.config.{Parameters} * Useful for giving user programs info about physical addresses */ class PTWProber(opcodes: OpcodeSet)(implicit p: Parameters) extends LazyRoCC(opcodes, 1) { + val nTrackers = 8 + + override val atlNode = TLClientNode(Seq(TLMasterPortParameters.v1( + Seq(TLMasterParameters.v1("PTWProber", sourceId = IdRange(0,nTrackers))) + ))) + override lazy val module = new LazyRoCCModuleImp(this) with HasCoreParameters { val in_q = Queue(io.cmd) - val in_flight = RegInit(false.B) - val resp_q = Module(new Queue(new RoCCResponse, 2)) + val translate_in_flight = RegInit(false.B) + + class RoCCBundle extends Bundle { + val cmd = new RoCCCommand + val data = UInt(64.W) + } + + val resp_q = Module(new Queue(new RoCCBundle, 2)) val vm_enabled = usingVM.B && io.ptw(0).ptbr.mode(io.ptw(0).ptbr.mode.getWidth-1) && in_q.bits.status.dprv <= PRV.S.U - io.ptw(0).req.valid := in_q.valid && resp_q.io.enq.ready && !in_flight && vm_enabled + io.ptw(0).req.valid := in_q.valid && resp_q.io.enq.ready && !translate_in_flight && vm_enabled io.ptw(0).req.bits.valid := in_q.valid io.ptw(0).req.bits.bits.addr := in_q.bits.rs1(vaddrBits-1, pgIdxBits) io.ptw(0).req.bits.bits.vstage1 := false.B @@ -27,29 +42,60 @@ class PTWProber(opcodes: OpcodeSet)(implicit p: Parameters) extends LazyRoCC(opc io.ptw(0).req.bits.bits.need_gpa := false.B when (io.ptw(0).req.fire()) { - in_flight := true.B + translate_in_flight := true.B } .elsewhen (io.ptw(0).resp.valid) { - in_flight := false.B + translate_in_flight := false.B } - in_q.ready := Mux(in_flight, io.ptw(0).resp.valid, !vm_enabled && resp_q.io.enq.ready) + in_q.ready := Mux(translate_in_flight, io.ptw(0).resp.valid, !vm_enabled && resp_q.io.enq.ready) - resp_q.io.enq.valid := Mux(in_flight, io.ptw(0).resp.valid, !vm_enabled && in_q.valid) - resp_q.io.enq.bits.rd := in_q.bits.inst.rd - resp_q.io.enq.bits.data := Mux(in_flight, + resp_q.io.enq.valid := Mux(translate_in_flight, io.ptw(0).resp.valid, !vm_enabled && in_q.valid) + resp_q.io.enq.bits.cmd := in_q.bits + resp_q.io.enq.bits.data := Mux(translate_in_flight, Mux(io.ptw(0).resp.bits.pf, 0.U, Cat(io.ptw(0).resp.bits.pte.ppn, in_q.bits.rs1(pgIdxBits-1,0))), in_q.bits.rs1) dontTouch(io.ptw(0).resp) - io.resp <> resp_q.io.deq + val flush_trackers = RegInit(VecInit(0.U(nTrackers.W).asBools)) + val flush_ready = !flush_trackers.reduce(_&&_) + val (tl_out, edge) = atlNode.out(0) + + io.resp.valid := resp_q.io.deq.valid && resp_q.io.deq.bits.cmd.inst.funct === 0.U + io.resp.bits.rd := resp_q.io.deq.bits.cmd.inst.rd + io.resp.bits.data := resp_q.io.deq.bits.data + resp_q.io.deq.ready := Mux(resp_q.io.deq.bits.cmd.inst.funct === 0.U, + io.resp.ready, + flush_ready && tl_out.a.ready) + + tl_out.a.valid := resp_q.io.deq.valid && resp_q.io.deq.bits.cmd.inst.funct =/= 0.U && flush_ready + tl_out.a.bits := edge.Put( + fromSource = PriorityEncoder(~(flush_trackers.asUInt)), + toAddress = 0x2010200.U, + lgSize = log2Ceil(8).U, + data = resp_q.io.deq.bits.data, + corrupt = false.B + )._2 + when (tl_out.a.fire()) { + flush_trackers(tl_out.a.bits.source) := true.B + } + tl_out.d.ready := true.B + when (tl_out.d.fire()) { + flush_trackers(tl_out.d.bits.source) := false.B + } + tl_out.b.ready := false.B + tl_out.c.valid := false.B + tl_out.c.bits := DontCare + tl_out.e.valid := false.B + tl_out.e.bits := DontCare + + io.mem := DontCare + io.mem.req.valid := false.B io.fpu_req.valid := false.B io.fpu_req.bits := DontCare io.fpu_resp.ready := false.B - io.mem := DontCare - io.mem.req.valid := false.B - io.busy := in_q.valid || resp_q.io.deq.valid + io.busy := in_q.valid || resp_q.io.deq.valid || flush_trackers.reduce(_||_) io.interrupt := false.B } }