Merge pull request #942 from freechipsproject/bus-blocker-lock
Bus blocker lock
This commit is contained in:
commit
49ba31ac34
@ -16,6 +16,7 @@ case class BusBlockerParams(
|
|||||||
pmpRegisters: Int)
|
pmpRegisters: Int)
|
||||||
{
|
{
|
||||||
val page = 4096
|
val page = 4096
|
||||||
|
val pageBits = log2Ceil(page)
|
||||||
val size = (((pmpRegisters * 8) + page - 1) / page) * page
|
val size = (((pmpRegisters * 8) + page - 1) / page) * page
|
||||||
|
|
||||||
require (pmpRegisters > 0)
|
require (pmpRegisters > 0)
|
||||||
@ -25,28 +26,29 @@ case class BusBlockerParams(
|
|||||||
require (deviceBeatBytes > 0 && isPow2(deviceBeatBytes))
|
require (deviceBeatBytes > 0 && isPow2(deviceBeatBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
case class DevicePMPParams(addressBits: Int)
|
case class DevicePMPParams(addressBits: Int, pageBits: Int)
|
||||||
class DevicePMP(params: DevicePMPParams) extends GenericParameterizedBundle(params)
|
class DevicePMP(params: DevicePMPParams) extends GenericParameterizedBundle(params)
|
||||||
{
|
{
|
||||||
require (params.addressBits > 12)
|
require (params.addressBits > params.pageBits)
|
||||||
|
|
||||||
val l = UInt(width = 1) // locked
|
val l = UInt(width = 1) // locked
|
||||||
val a = UInt(width = 1) // LSB of A (0=disabled, 1=TOR)
|
val a = UInt(width = 1) // LSB of A (0=disabled, 1=TOR)
|
||||||
val r = UInt(width = 1)
|
val r = UInt(width = 1)
|
||||||
val w = UInt(width = 1)
|
val w = UInt(width = 1)
|
||||||
|
|
||||||
val addr_hi = UInt(width = params.addressBits-12)
|
val addr_hi = UInt(width = params.addressBits-params.pageBits)
|
||||||
def address = Cat(addr_hi, UInt(0, width=12))
|
def address = Cat(addr_hi, UInt(0, width=params.pageBits))
|
||||||
|
def blockPriorAddress = l(0) && a(0)
|
||||||
|
|
||||||
def fields(locked: Bool): Seq[RegField] = {
|
def fields(blockAddress: Bool): Seq[RegField] = {
|
||||||
def field(bits: Int, reg: UInt) =
|
def field(bits: Int, reg: UInt, lock: Bool = l(0)) =
|
||||||
RegField(bits, RegReadFn(reg), RegWriteFn((wen, data) => {
|
RegField(bits, RegReadFn(reg), RegWriteFn((wen, data) => {
|
||||||
when (wen && !locked) { reg := data }
|
when (wen && !lock) { reg := data }
|
||||||
Bool(true)
|
Bool(true)
|
||||||
}))
|
}))
|
||||||
Seq(
|
Seq(
|
||||||
RegField(10),
|
RegField(10),
|
||||||
field(params.addressBits-12, addr_hi),
|
field(params.addressBits-params.pageBits, addr_hi, l(0) || blockAddress),
|
||||||
RegField(56 - (params.addressBits-2)),
|
RegField(56 - (params.addressBits-2)),
|
||||||
field(1, r),
|
field(1, r),
|
||||||
field(1, w),
|
field(1, w),
|
||||||
@ -59,8 +61,8 @@ class DevicePMP(params: DevicePMPParams) extends GenericParameterizedBundle(para
|
|||||||
|
|
||||||
object DevicePMP
|
object DevicePMP
|
||||||
{
|
{
|
||||||
def apply(addressBits: Int) = {
|
def apply(addressBits: Int, pageBits: Int) = {
|
||||||
val out = Wire(new DevicePMP(DevicePMPParams(addressBits)))
|
val out = Wire(new DevicePMP(DevicePMPParams(addressBits, pageBits)))
|
||||||
out.l := UInt(0)
|
out.l := UInt(0)
|
||||||
out.a := UInt(0)
|
out.a := UInt(0)
|
||||||
out.r := UInt(0)
|
out.r := UInt(0)
|
||||||
@ -87,9 +89,9 @@ class BusBlocker(params: BusBlockerParams)(implicit p: Parameters) extends TLBus
|
|||||||
|
|
||||||
// We need to be able to represent +1 larger than the largest populated address
|
// We need to be able to represent +1 larger than the largest populated address
|
||||||
val addressBits = log2Ceil(nodeOut.edgesOut(0).manager.maxAddress+1+1)
|
val addressBits = log2Ceil(nodeOut.edgesOut(0).manager.maxAddress+1+1)
|
||||||
val pmps = RegInit(Vec.fill(params.pmpRegisters) { DevicePMP(addressBits) })
|
val pmps = RegInit(Vec.fill(params.pmpRegisters) { DevicePMP(addressBits, params.pageBits) })
|
||||||
val locks = (pmps.map(_.l) zip (UInt(0) +: pmps.map(_.l))) map { case (x, n) => x | n }
|
val blocks = pmps.tail.map(_.blockPriorAddress) :+ Bool(false)
|
||||||
controlNode.regmap(0 -> (pmps zip locks).map { case (p, l) => p.fields(l(0)) }.toList.flatten)
|
controlNode.regmap(0 -> (pmps zip blocks).map { case (p, b) => p.fields(b) }.toList.flatten)
|
||||||
|
|
||||||
val in = io.in(0)
|
val in = io.in(0)
|
||||||
val edge = nodeIn.edgesIn(0)
|
val edge = nodeIn.edgesIn(0)
|
||||||
@ -97,8 +99,8 @@ class BusBlocker(params: BusBlockerParams)(implicit p: Parameters) extends TLBus
|
|||||||
// Determine if a request is allowed
|
// Determine if a request is allowed
|
||||||
val needW = in.a.bits.opcode =/= TLMessages.Get
|
val needW = in.a.bits.opcode =/= TLMessages.Get
|
||||||
val needR = in.a.bits.opcode =/= TLMessages.PutFullData && in.a.bits.opcode =/= TLMessages.PutPartialData
|
val needR = in.a.bits.opcode =/= TLMessages.PutFullData && in.a.bits.opcode =/= TLMessages.PutPartialData
|
||||||
val lte = Bool(false) +: pmps.map(in.a.bits.address < _.address)
|
val lt = Bool(false) +: pmps.map(in.a.bits.address < _.address)
|
||||||
val sel = (pmps.map(_.a) zip (lte.init zip lte.tail)) map { case (a, (l, r)) => a(0) && !l && r }
|
val sel = (pmps.map(_.a) zip (lt.init zip lt.tail)) map { case (a, (l, r)) => a(0) && !l && r }
|
||||||
val ok = pmps.map(p => (p.r(0) || !needR) && (p.w(0) || !needW))
|
val ok = pmps.map(p => (p.r(0) || !needR) && (p.w(0) || !needW))
|
||||||
val allow = PriorityMux(sel :+ Bool(true), ok :+ Bool(false)) // no match => deny
|
val allow = PriorityMux(sel :+ Bool(true), ok :+ Bool(false)) // no match => deny
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user