Attach MemTracer to SBus , all physical addr hashed between 0X80000000->0X90000000
This commit is contained in:
@@ -75,8 +75,8 @@ MemTraceLine MemTraceReader::read_trace_at(const long cycle,
|
|||||||
// read it right now.
|
// read it right now.
|
||||||
return MemTraceLine{};
|
return MemTraceLine{};
|
||||||
} else if (line.cycle == cycle && line.lane_id == lane_id) {
|
} else if (line.cycle == cycle && line.lane_id == lane_id) {
|
||||||
printf("fire! cycle=%ld, valid=%d, %s \n", cycle, line.valid,
|
printf("fire! cycle=%ld, valid=%d, %s addr=%x \n", cycle, line.valid,
|
||||||
line.loadstore);
|
line.loadstore, line.address);
|
||||||
|
|
||||||
// FIXME! Currently lane_id is assumed to be in round-robin order, e.g.
|
// FIXME! Currently lane_id is assumed to be in round-robin order, e.g.
|
||||||
// 0->1->2->3->0->..., both in the trace file and the order the caller calls
|
// 0->1->2->3->0->..., both in the trace file and the order the caller calls
|
||||||
|
|||||||
@@ -570,13 +570,14 @@ class CoalShiftQueue[T <: Data](
|
|||||||
io.count := PopCount(io.mask)
|
io.count := PopCount(io.mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemTraceDriver(numLanes: Int = 1)(implicit p: Parameters) extends LazyModule {
|
class MemTraceDriver(numLanes: Int = 4, traceFile : String = "vecadd.core1.thread4.trace")(implicit p: Parameters) extends LazyModule {
|
||||||
|
|
||||||
// Create N client nodes together
|
// Create N client nodes together
|
||||||
val laneNodes = Seq.tabulate(numLanes) { i =>
|
val laneNodes = Seq.tabulate(numLanes) { i =>
|
||||||
val clientParam = Seq(
|
val clientParam = Seq(
|
||||||
TLMasterParameters.v1(
|
TLMasterParameters.v1(
|
||||||
name = "MemTraceDriver" + i.toString,
|
name = "MemTraceDriver" + i.toString,
|
||||||
sourceId = IdRange(0, 0x10)
|
sourceId = IdRange(0, 0x1000)
|
||||||
// visibility = Seq(AddressSet(0x0000, 0xffffff))
|
// visibility = Seq(AddressSet(0x0000, 0xffffff))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -588,7 +589,7 @@ class MemTraceDriver(numLanes: Int = 1)(implicit p: Parameters) extends LazyModu
|
|||||||
val node = TLIdentityNode()
|
val node = TLIdentityNode()
|
||||||
laneNodes.foreach { l => node := l }
|
laneNodes.foreach { l => node := l }
|
||||||
|
|
||||||
lazy val module = new MemTraceDriverImp(this, numLanes)
|
lazy val module = new MemTraceDriverImp(this, numLanes, traceFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
class TraceReq extends Bundle {
|
class TraceReq extends Bundle {
|
||||||
@@ -599,11 +600,11 @@ class TraceReq extends Bundle {
|
|||||||
val data = UInt(64.W)
|
val data = UInt(64.W)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int)
|
class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int, traceFile : String)
|
||||||
extends LazyModuleImp(outer)
|
extends LazyModuleImp(outer)
|
||||||
with UnitTestModule {
|
with UnitTestModule {
|
||||||
val sim = Module(
|
val sim = Module(
|
||||||
new SimMemTrace(filename = "vecadd.core1.thread4.trace", numLanes)
|
new SimMemTrace(traceFile, numLanes)
|
||||||
)
|
)
|
||||||
sim.io.clock := clock
|
sim.io.clock := clock
|
||||||
sim.io.reset := reset.asBool
|
sim.io.reset := reset.asBool
|
||||||
@@ -629,26 +630,31 @@ class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int)
|
|||||||
val sourceIdCounter = RegInit(0.U(64.W))
|
val sourceIdCounter = RegInit(0.U(64.W))
|
||||||
sourceIdCounter := sourceIdCounter + 1.U
|
sourceIdCounter := sourceIdCounter + 1.U
|
||||||
|
|
||||||
|
//Issue here is that Vortex mem range is not within Chipyard Mem range
|
||||||
|
//In default setting, all mem-req for program data must be within 0X80000000 -> 0X90000000
|
||||||
|
//
|
||||||
|
def hashToValidPhyAddr(addr : UInt) : UInt = {
|
||||||
|
Cat(8.U(4.W), addr(27, 3), 0.U(3.W) )
|
||||||
|
}
|
||||||
|
|
||||||
// Connect each lane to its respective TL node.
|
// Connect each lane to its respective TL node.
|
||||||
(outer.laneNodes zip laneReqs).foreach { case (node, req) =>
|
(outer.laneNodes zip laneReqs).foreach { case (node, req) =>
|
||||||
val (tlOut, edge) = node.out(0)
|
val (tlOut, edge) = node.out(0)
|
||||||
|
|
||||||
val (plegal, pbits) = edge.Put(
|
val (plegal, pbits) = edge.Put(
|
||||||
fromSource = sourceIdCounter,
|
fromSource = sourceIdCounter,
|
||||||
toAddress = req.address,
|
toAddress = hashToValidPhyAddr(req.address),
|
||||||
// Memory trace addresses are not necessarily aligned to word boundaries
|
lgSize = 3.U,
|
||||||
// so leave lgSize to 0
|
|
||||||
// NOTE: this is in bytes not bits
|
|
||||||
lgSize = 0.U,
|
|
||||||
data = req.data
|
data = req.data
|
||||||
)
|
)
|
||||||
val (glegal, gbits) = edge.Get(
|
val (glegal, gbits) = edge.Get(
|
||||||
fromSource = sourceIdCounter,
|
fromSource = sourceIdCounter,
|
||||||
toAddress = req.address,
|
toAddress = hashToValidPhyAddr(req.address),
|
||||||
lgSize = 0.U
|
lgSize = 3.U
|
||||||
)
|
)
|
||||||
val legal = Mux(req.is_store, plegal, glegal)
|
val legal = Mux(req.is_store, plegal, glegal)
|
||||||
val bits = Mux(req.is_store, pbits, gbits)
|
val bits = Mux(req.is_store, pbits, gbits)
|
||||||
|
|
||||||
assert(legal, "illegal TL req gen")
|
assert(legal, "illegal TL req gen")
|
||||||
tlOut.a.valid := req.valid
|
tlOut.a.valid := req.valid
|
||||||
tlOut.a.bits := bits
|
tlOut.a.bits := bits
|
||||||
@@ -658,9 +664,13 @@ class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int)
|
|||||||
tlOut.e.valid := false.B
|
tlOut.e.valid := false.B
|
||||||
|
|
||||||
dontTouch(tlOut.a)
|
dontTouch(tlOut.a)
|
||||||
|
dontTouch(tlOut.d)
|
||||||
}
|
}
|
||||||
|
|
||||||
io.finished := sim.io.trace_read.finished
|
io.finished := sim.io.trace_read.finished
|
||||||
|
when(io.finished){
|
||||||
|
assert(false.B, "\n\n\nsimulation Successfully finished\n\n\n (this assertion intentional fail upon MemTracer termination)")
|
||||||
|
}
|
||||||
|
|
||||||
// Clock Counter, for debugging purpose
|
// Clock Counter, for debugging purpose
|
||||||
val clkcount = RegInit(0.U(64.W))
|
val clkcount = RegInit(0.U(64.W))
|
||||||
@@ -668,7 +678,7 @@ class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int)
|
|||||||
dontTouch(clkcount)
|
dontTouch(clkcount)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimMemTrace(val filename: String, numLanes: Int)
|
class SimMemTrace(filename: String, numLanes: Int)
|
||||||
extends BlackBox(
|
extends BlackBox(
|
||||||
Map("FILENAME" -> filename, "NUM_LANES" -> numLanes)
|
Map("FILENAME" -> filename, "NUM_LANES" -> numLanes)
|
||||||
)
|
)
|
||||||
|
|||||||
45
src/main/scala/tilelink/TracerSystemMem.scala
Normal file
45
src/main/scala/tilelink/TracerSystemMem.scala
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
package freechips.rocketchip.tilelink
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util._
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.subsystem.{BaseSubsystem, CacheBlockBytes}
|
||||||
|
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||||
|
|
||||||
|
// class class, consumed by WithGPUTacer config and GPUTracerKey
|
||||||
|
|
||||||
|
case class GPUTracerConfig(numLanes: Int, traceFile : String) // FIXME, add lane number and file name
|
||||||
|
|
||||||
|
case object GPUTracerKey extends Field[Option[GPUTracerConfig]](None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Both LazyModule of Tracer and Impl are both in Coalescing.scala
|
||||||
|
|
||||||
|
|
||||||
|
//The trait is attached to DigitalTop of Chipyard system, informing it indeed has the ability
|
||||||
|
//to attach GPU tracer node onto the system bus
|
||||||
|
trait CanHaveGPUTracer { this: BaseSubsystem =>
|
||||||
|
implicit val p: Parameters
|
||||||
|
|
||||||
|
//p(GPUTracerKey) is the mechnimism to pass Config's parameter down to lazymodule
|
||||||
|
p(GPUTracerKey) .map { k =>
|
||||||
|
val config = p(GPUTracerKey).get
|
||||||
|
val tracer = LazyModule(new MemTraceDriver(config.numLanes, config.traceFile)(p))
|
||||||
|
// Must use :=* to ensure the N edges from Tracer doesn't get merged into 1 when connecting to SBus
|
||||||
|
sbus.fromPort(Some("gpu-tracer"))() :=* tracer.node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//This is used by Chip Level Config, the config which creates the SoC
|
||||||
|
class WithGPUTracer(numLanes: Int, traceFile : String) extends Config((site, here, up) => {
|
||||||
|
case GPUTracerKey => Some( GPUTracerConfig(numLanes, traceFile) )
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user