From 2dbe882e58ce281e7bc790879b9f3ae6aba881c5 Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Wed, 11 Oct 2017 13:16:50 -0700 Subject: [PATCH] tilelink: add BasicBusBlocker device --- .../scala/devices/tilelink/BusBlocker.scala | 73 ++++++++++++++----- .../scala/devices/tilelink/BusBypass.scala | 3 + 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/main/scala/devices/tilelink/BusBlocker.scala b/src/main/scala/devices/tilelink/BusBlocker.scala index b057ab8d..3ff76d19 100644 --- a/src/main/scala/devices/tilelink/BusBlocker.scala +++ b/src/main/scala/devices/tilelink/BusBlocker.scala @@ -9,23 +9,6 @@ import freechips.rocketchip.regmapper._ import freechips.rocketchip.tilelink._ import freechips.rocketchip.util._ -case class BusBlockerParams( - controlAddress: BigInt, - controlBeatBytes: Int, - deviceBeatBytes: Int, - pmpRegisters: Int) -{ - val page = 4096 - val pageBits = log2Ceil(page) - val size = (((pmpRegisters * 8) + page - 1) / page) * page - - require (pmpRegisters > 0) - require (controlAddress > 0) - require (controlAddress % size == 0) - require (controlBeatBytes > 0 && isPow2(controlBeatBytes)) - require (deviceBeatBytes > 0 && isPow2(deviceBeatBytes)) -} - case class DevicePMPParams(addressBits: Int, pageBits: Int) class DevicePMP(params: DevicePMPParams) extends GenericParameterizedBundle(params) { @@ -71,6 +54,28 @@ object DevicePMP } } +/** BusBlocker uses a set of DevicePMP registers to control whether + * accesses of certain types are allowed to proceed or bypassed to + * a /dev/null device. + */ + +case class BusBlockerParams( + controlAddress: BigInt, + controlBeatBytes: Int, + deviceBeatBytes: Int, + pmpRegisters: Int) +{ + val page = 4096 + val pageBits = log2Ceil(page) + val size = (((pmpRegisters * 8) + page - 1) / page) * page + + require (pmpRegisters > 0) + require (controlAddress > 0) + require (controlAddress % size == 0) + require (controlBeatBytes > 0 && isPow2(controlBeatBytes)) + require (deviceBeatBytes > 0 && isPow2(deviceBeatBytes)) +} + class BusBlocker(params: BusBlockerParams)(implicit p: Parameters) extends TLBusBypassBase(params.deviceBeatBytes) { val device = new SimpleDevice("bus-blocker", Seq("sifive,bus-blocker0")) @@ -100,3 +105,37 @@ class BusBlocker(params: BusBlockerParams)(implicit p: Parameters) extends TLBus bar.module.io.bypass := !allow } } + +/** BasicBusBlocker uses a single bit register to control whether + * accesses of all types are allowed to proceed or bypassed to + * a /dev/null device. It has a second bit register to report + * whether any requests are pending on either path. + */ + +case class BasicBusBlockerParams( + controlAddress: BigInt, + controlBeatBytes: Int, + deviceBeatBytes: Int, + deadlock: Boolean = false) + +class BasicBusBlocker(params: BasicBusBlockerParams)(implicit p: Parameters) + extends TLBusBypassBase(params.deviceBeatBytes, params.deadlock) +{ + val device = new SimpleDevice("basic-bus-blocker", Seq("sifive,basic-bus-blocker0")) + + val controlNode = TLRegisterNode( + address = Seq(AddressSet(params.controlAddress, 0xFFF)), + device = device, + beatBytes = params.controlBeatBytes) + + lazy val module = new LazyModuleImp(this) { + val allow = RegInit(true.B) + val pending = RegNext(bar.module.io.pending) + + controlNode.regmap( + 0 -> Seq(RegField (32, allow)), + 4 -> Seq(RegField.r(32, pending))) + + bar.module.io.bypass := !allow + } +} diff --git a/src/main/scala/devices/tilelink/BusBypass.scala b/src/main/scala/devices/tilelink/BusBypass.scala index 38c378a3..08d61418 100644 --- a/src/main/scala/devices/tilelink/BusBypass.scala +++ b/src/main/scala/devices/tilelink/BusBypass.scala @@ -49,6 +49,7 @@ class TLBusBypassBar(implicit p: Parameters) extends LazyModule lazy val module = new LazyModuleImp(this) { val io = IO(new Bundle { val bypass = Bool(INPUT) + val pending = Bool(OUTPUT) }) val (in, edge) = node.in(0) @@ -60,6 +61,8 @@ class TLBusBypassBar(implicit p: Parameters) extends LazyModule val flight = RegInit(UInt(0, width = log2Ceil(3*edge.client.endSourceId+1))) val bypass = RegInit(io.bypass) // synchronous reset required + io.pending := (flight > 0.U) + val (a_first, a_last, _) = edge.firstlast(in.a) val (b_first, b_last, _) = edge.firstlast(in.b) val (c_first, c_last, _) = edge.firstlast(in.c)