tilelink: add PatternPusher, a device to inject a fixed traffic pattern (#950)
This commit is contained in:
parent
a3358f34a0
commit
baf769f924
74
src/main/scala/tilelink/PatternPusher.scala
Normal file
74
src/main/scala/tilelink/PatternPusher.scala
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user