Merge pull request #1039 from freechipsproject/tile-crossing-params
Improvements wrt connecting RocketTiles to SystemBus
This commit is contained in:
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
import scala.math.min
|
||||
|
||||
abstract class TLBusBypassBase(beatBytes: Int)(implicit p: Parameters) extends LazyModule
|
||||
abstract class TLBusBypassBase(beatBytes: Int, deadlock: Boolean = false)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
protected val nodeIn = TLIdentityNode()
|
||||
protected val nodeOut = TLIdentityNode()
|
||||
@ -18,7 +18,8 @@ abstract class TLBusBypassBase(beatBytes: Int)(implicit p: Parameters) extends L
|
||||
|
||||
protected val bar = LazyModule(new TLBusBypassBar)
|
||||
protected val everything = Seq(AddressSet(0, BigInt("ffffffffffffffffffffffffffffffff", 16))) // 128-bit
|
||||
protected val error = LazyModule(new TLError(ErrorParams(everything), beatBytes))
|
||||
protected val error = if (deadlock) LazyModule(new DeadlockDevice(ErrorParams(everything), beatBytes))
|
||||
else LazyModule(new TLError(ErrorParams(everything), beatBytes))
|
||||
|
||||
// order matters
|
||||
bar.node := nodeIn
|
||||
@ -48,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)
|
||||
@ -59,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)
|
||||
|
@ -13,17 +13,13 @@ import scala.math.min
|
||||
case class ErrorParams(address: Seq[AddressSet], maxTransfer: Int = 4096)
|
||||
case object ErrorParams extends Field[ErrorParams]
|
||||
|
||||
/** Adds a /dev/null slave that generates TL error response messages */
|
||||
class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val address = params.address
|
||||
|
||||
val device = new SimpleDevice("error-device", Seq("sifive,error0"))
|
||||
|
||||
abstract class DevNullDevice(params: ErrorParams, beatBytes: Int = 4)
|
||||
(device: SimpleDevice)
|
||||
(implicit p: Parameters) extends LazyModule {
|
||||
val xfer = TransferSizes(1, params.maxTransfer)
|
||||
val node = TLManagerNode(Seq(TLManagerPortParameters(
|
||||
Seq(TLManagerParameters(
|
||||
address = address,
|
||||
address = params.address,
|
||||
resources = device.reg("mem"),
|
||||
regionType = RegionType.UNCACHED,
|
||||
supportsAcquireT = xfer,
|
||||
@ -38,7 +34,12 @@ class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters) e
|
||||
beatBytes = beatBytes,
|
||||
endSinkId = 1, // can receive GrantAck
|
||||
minLatency = 1))) // no bypass needed for this device
|
||||
}
|
||||
|
||||
/** Adds a /dev/null slave that generates TL error response messages */
|
||||
class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters)
|
||||
extends DevNullDevice(params, beatBytes)(new SimpleDevice("error-device", Seq("sifive,error0")))
|
||||
{
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
import TLMessages._
|
||||
import TLPermissions._
|
||||
@ -88,6 +89,23 @@ class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters) e
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a /dev/null slave that does not raise ready for any incoming traffic.
|
||||
* !!! WARNING: This device WILL cause your bus to deadlock for as long as you
|
||||
* continue to send traffic to it !!!
|
||||
*/
|
||||
class DeadlockDevice(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters)
|
||||
extends DevNullDevice(params, beatBytes)(new SimpleDevice("deadlock-device", Seq("sifive,deadlock0")))
|
||||
{
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val (in, _) = node.in(0)
|
||||
in.a.ready := Bool(false)
|
||||
in.b.valid := Bool(false)
|
||||
in.c.ready := Bool(false)
|
||||
in.d.valid := Bool(false)
|
||||
in.e.ready := Bool(false)
|
||||
}
|
||||
}
|
||||
|
||||
trait HasSystemErrorSlave extends HasSystemBus {
|
||||
private val params = p(ErrorParams)
|
||||
val error = LazyModule(new TLError(params, sbus.beatBytes))
|
||||
|
Reference in New Issue
Block a user