From 0280a1f21811918d5bd0754387f254508c43eb3f Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 30 Oct 2017 17:05:09 -0700 Subject: [PATCH] tilelink: add the ErrorEvaluator, a test bench error helper --- src/main/scala/tilelink/ErrorEvaluator.scala | 50 ++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/scala/tilelink/ErrorEvaluator.scala diff --git a/src/main/scala/tilelink/ErrorEvaluator.scala b/src/main/scala/tilelink/ErrorEvaluator.scala new file mode 100644 index 00000000..2a1bdb4b --- /dev/null +++ b/src/main/scala/tilelink/ErrorEvaluator.scala @@ -0,0 +1,50 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.tilelink + +import Chisel._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.util._ + +// An ErrorEvaluator is used for test harnesses. +// It creates errors in transactions which overlap an address in pattern. +// 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. +// 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 +{ + val node = TLAdapterNode() + lazy val module = new LazyModuleImp(this) { + (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => + out <> in + + // Does the request overlap the pattern ? + val abase = in.a.bits.address + val amask = UIntToOH1(in.a.bits.size, log2Up(edgeIn.maxTransfer)) + 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 inject = Mem(edgeIn.client.endSourceId, Bool()) + 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 d_inject = Mux(bypass, overlaps, inject.read(in.d.bits.source)) holdUnless d_first + 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(!testOff) || !out.d.fire() || !d_last || d_inject || !out.d.bits.error, "Error flag was set!") + } + } +} + +object TLErrorEvaluator +{ + def apply(pattern: Seq[AddressSet], testOn: Boolean = false, testOff: Boolean = false)(implicit p: Parameters): TLNode = + LazyModule(new TLErrorEvaluator(pattern, testOn, testOff)).node +}