From baf769f9241a9093fc422c08a56bd29f7be51279 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 11 Aug 2017 15:07:10 -0700 Subject: [PATCH] tilelink: add PatternPusher, a device to inject a fixed traffic pattern (#950) --- src/main/scala/tilelink/PatternPusher.scala | 74 +++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/scala/tilelink/PatternPusher.scala diff --git a/src/main/scala/tilelink/PatternPusher.scala b/src/main/scala/tilelink/PatternPusher.scala new file mode 100644 index 00000000..1858c925 --- /dev/null +++ b/src/main/scala/tilelink/PatternPusher.scala @@ -0,0 +1,74 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.tilelink + +import Chisel._ +import chisel3.internal.sourceinfo.SourceInfo +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ + +sealed trait Pattern { + def address: BigInt + def size: Int + def bits(edge: TLEdgeOut): (Bool, TLBundleA) + require ((address & ((BigInt(1) << size) - 1)) == 0) +} + +case class WritePattern(address: BigInt, size: Int, data: BigInt) extends Pattern +{ + require (log2Floor(data) < (BigInt(8) << size)) + def bits(edge: TLEdgeOut) = edge.Put(UInt(0), UInt(address), UInt(size), UInt(data)) +} + +case class ReadPattern(address: BigInt, size: Int) extends Pattern +{ + def bits(edge: TLEdgeOut) = edge.Get(UInt(0), UInt(address), UInt(size)) +} + +class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameters) extends LazyModule +{ + val node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(name = name))))) + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val tl_out = node.bundleOut + val run = Bool(INPUT) + val done = Bool(OUTPUT) + } + + val edgeOut = node.edgesOut(0) + pattern.foreach { p => + require (p.size <= log2Ceil(edgeOut.manager.beatBytes), "Patterns must fit in a single beat") + } + + val step = RegInit(UInt(0, width = log2Ceil(pattern.size+1))) + val flight = RegInit(Bool(false)) + val ready = RegNext(Bool(true), Bool(false)) + + val end = step === UInt(pattern.size) + io.done := end && !flight + + val a = io.tl_out(0).a + val d = io.tl_out(0).d + + when (a.fire()) { + flight := Bool(true) + step := step + UInt(1) + } + when (d.fire()) { + flight := Bool(false) + } + + val (plegal, pbits) = pattern.map(_.bits(edgeOut)).unzip + assert (end || Vec(plegal)(step), s"Pattern pusher ${name} tried to push an illegal request") + + a.valid := io.run && ready && !end && !flight + a.bits := Vec(pbits)(step) + d.ready := Bool(true) + + // Tie off unused channels + io.tl_out(0).b.ready := Bool(true) + io.tl_out(0).c.valid := Bool(false) + io.tl_out(0).e.valid := Bool(false) + } +}