tilelink: generalize ErrorEvaluator to more than just address patterns
This commit is contained in:
parent
25ea7fa852
commit
88234ead0d
@ -7,34 +7,50 @@ import freechips.rocketchip.config.Parameters
|
|||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
// Check if a request satisfies some interesting property
|
||||||
|
class RequestPattern(test: TLBundleA => Bool)
|
||||||
|
{
|
||||||
|
def apply(a: TLBundleA) = test(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
object RequestPattern
|
||||||
|
{
|
||||||
|
// Does the request address range overlap a particular pattern of addresses?
|
||||||
|
def overlaps(pattern: Seq[AddressSet])(a: TLBundleA) = {
|
||||||
|
val amask = UIntToOH1(a.size, a.params.addressBits)
|
||||||
|
val abase = a.address
|
||||||
|
pattern.map { case p =>
|
||||||
|
val pbase = UInt(p.base)
|
||||||
|
val pmask = UInt(p.mask & ((BigInt(1) << a.params.addressBits) - 1))
|
||||||
|
(amask | pmask | ~(abase ^ pbase)).andR
|
||||||
|
}.reduce(_ || _)
|
||||||
|
}
|
||||||
|
|
||||||
|
implicit def apply(pattern: Seq[AddressSet]): RequestPattern = new RequestPattern(overlaps(pattern) _)
|
||||||
|
}
|
||||||
|
|
||||||
// An ErrorEvaluator is used for test harnesses.
|
// An ErrorEvaluator is used for test harnesses.
|
||||||
// It creates errors in transactions which overlap an address in pattern.
|
// It creates errors in transactions which match the provided test function.
|
||||||
// If testOn is true, it will assert fail if these transactions do not already error.
|
// If testOn is true, it will assert fail if these transactions do not already error.
|
||||||
// If testOff is true, it will assert fail if these transactions otherwise error.
|
// If testOff is true, it will assert fail if these transactions otherwise error.
|
||||||
// This helps when building unit tests to confirm that errors are propagated correctly.
|
// This helps when building unit tests to confirm that errors are propagated correctly.
|
||||||
class TLErrorEvaluator(pattern: Seq[AddressSet], testOn: Boolean, testOff: Boolean)(implicit p: Parameters) extends LazyModule
|
class TLErrorEvaluator(test: RequestPattern, testOn: Boolean, testOff: Boolean)(implicit p: Parameters) extends LazyModule
|
||||||
{
|
{
|
||||||
val node = TLAdapterNode()
|
val node = TLAdapterNode()
|
||||||
lazy val module = new LazyModuleImp(this) {
|
lazy val module = new LazyModuleImp(this) {
|
||||||
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
|
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
|
||||||
out <> in
|
out <> in
|
||||||
|
|
||||||
// Does the request overlap the pattern ?
|
// Should the request receive an error ?
|
||||||
val abase = in.a.bits.address
|
val inject_map = Mem(edgeIn.client.endSourceId, Bool())
|
||||||
val amask = UIntToOH1(in.a.bits.size, log2Up(edgeIn.maxTransfer))
|
val inject_now = test(in.a.bits)
|
||||||
val overlaps = pattern.map { case a =>
|
|
||||||
val pbase = UInt(a.base)
|
|
||||||
val pmask = UInt(a.mask & ((BigInt(1) << edgeIn.bundle.addressBits) - 1))
|
|
||||||
(amask | pmask | ~(abase ^ pbase)).andR
|
|
||||||
}.reduce(_ || _)
|
|
||||||
|
|
||||||
val (d_first, d_last, _) = edgeOut.firstlast(out.d)
|
val (d_first, d_last, _) = edgeOut.firstlast(out.d)
|
||||||
|
|
||||||
val inject = Mem(edgeIn.client.endSourceId, Bool())
|
when (in.a.fire()) { inject_map.write(in.a.bits.source, inject_now) }
|
||||||
when (in.a.fire()) { inject.write(in.a.bits.source, overlaps) }
|
|
||||||
|
|
||||||
val bypass = in.a.fire() && in.a.bits.source === in.d.bits.source
|
val bypass = in.a.fire() && in.a.bits.source === in.d.bits.source
|
||||||
val d_inject = Mux(bypass, overlaps, inject.read(in.d.bits.source)) holdUnless d_first
|
val d_inject = Mux(bypass, inject_now, inject_map.read(in.d.bits.source)) holdUnless d_first
|
||||||
in.d.bits.error := out.d.bits.error || (d_last && d_inject)
|
in.d.bits.error := out.d.bits.error || (d_last && d_inject)
|
||||||
|
|
||||||
assert (Bool(!testOn) || !out.d.fire() || !d_last || !d_inject || out.d.bits.error, "Error flag was not set!")
|
assert (Bool(!testOn) || !out.d.fire() || !d_last || !d_inject || out.d.bits.error, "Error flag was not set!")
|
||||||
@ -45,6 +61,6 @@ class TLErrorEvaluator(pattern: Seq[AddressSet], testOn: Boolean, testOff: Boole
|
|||||||
|
|
||||||
object TLErrorEvaluator
|
object TLErrorEvaluator
|
||||||
{
|
{
|
||||||
def apply(pattern: Seq[AddressSet], testOn: Boolean = false, testOff: Boolean = false)(implicit p: Parameters): TLNode =
|
def apply(test: RequestPattern, testOn: Boolean = false, testOff: Boolean = false)(implicit p: Parameters): TLNode =
|
||||||
LazyModule(new TLErrorEvaluator(pattern, testOn, testOff)).node
|
LazyModule(new TLErrorEvaluator(test, testOn, testOff)).node
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user