1
0

ahb: support hmastlock acquistion of crossbar

This commit is contained in:
Wesley W. Terpstra 2016-05-24 13:28:06 -07:00
parent e1e8eda419
commit 200c69c106

View File

@ -171,7 +171,6 @@ class HastiXbar(nMasters: Int, addressMap: Seq[UInt=>Bool])(implicit p: Paramete
}
val nSlaves = addressMap.size
// !!! handle hmastlock
// Setup diversions infront of each master
val diversions = Seq.tabulate(nMasters) { m => Module(new MasterDiversion) }
@ -181,6 +180,10 @@ class HastiXbar(nMasters: Int, addressMap: Seq[UInt=>Bool])(implicit p: Paramete
val masters = diversions map (_.io.out)
val slaves = io.slaves
// Lock status of the crossbar
val lockedM = Reg(init = Vec.fill(nMasters)(Bool(false)))
val isLocked = lockedM.reduce(_ || _)
// This matrix governs the master-slave connections in the address phase
// It is indexed by addressPhaseGrantSM(slave)(master)
// It is guaranteed to have at most one 'true' per column and per row
@ -247,11 +250,12 @@ class HastiXbar(nMasters: Int, addressMap: Seq[UInt=>Bool])(implicit p: Paramete
.reduce(_ || _) }
// Requested access to slaves from masters (pre-arbitration)
// NOTE: quash any request that requires bus ownership or conflicts with isLocked
// NOTE: isNSeq does NOT include SEQ; thus, masters who are midburst do not
// request access to a new slave. They stay tied to the old and do not get two.
// NOTE: if a master was waited, it must repeat the same request as last cycle;
// thus, it will request the same slave and not end up with two (unless buggy).
val NSeq = Vec(masters.map(_.isNSeq()))
val NSeq = Vec((lockedM zip masters) map { case(l, m) => m.isNSeq() && ((!isLocked && !m.hmastlock) || l) })
val requestSM = Vec.tabulate(nSlaves) { s => Vec.tabulate(nMasters) { m => matchMS(m)(s) && NSeq(m) && !bubbleM(m) } }
// Select at most one master request per slave (lowest index = highest priority)
@ -281,7 +285,7 @@ class HastiXbar(nMasters: Int, addressMap: Seq[UInt=>Bool])(implicit p: Paramete
(slaves zip addressPhaseGrantSM) foreach { case (s, g) => {
s.htrans := Mux1H(g, masters.map(_.htrans)) // defaults to HTRANS_IDLE (0)
s.haddr := Mux1H(g, masters.map(_.haddr))
s.hmastlock := Mux1H(g, masters.map(_.hmastlock)) // !!! use global crossbar lock state
s.hmastlock := isLocked
s.hwrite := Mux1H(g, masters.map(_.hwrite))
s.hsize := Mux1H(g, masters.map(_.hsize))
s.hburst := Mux1H(g, masters.map(_.hburst))
@ -293,6 +297,20 @@ class HastiXbar(nMasters: Int, addressMap: Seq[UInt=>Bool])(implicit p: Paramete
(slaves zip dataPhaseGrantSM) foreach { case (s, g) => {
s.hwdata := Mux1H(g, masters.map(_.hwdata))
} }
// When no master-slave connections are active, a master can take-over the bus
val canLock = !addressPhaseGrantSM.map({ v => v.reduce(_ || _) }).reduce(_ || _)
// Lowest index highest priority for lock arbitration
val reqLock = masters.map(_.hmastlock)
val winLock = PriorityEncoderOH(reqLock)
// Lock arbitration
when (isLocked) {
lockedM := (lockedM zip reqLock) map { case (a,b) => a && b }
} .elsewhen (canLock) {
lockedM := winLock
}
}
class HastiBus(amap: Seq[UInt=>Bool])(implicit p: Parameters) extends HastiModule()(p) {