Ahb tweaks (#50)
* ahb: handle tlDataBytes==1 and tlDataBeats==1 gracefully I only now learned that chisel does not handle 0-width wires properly and that log2Up and log2Ceil differ on 1. Fix-up code to handle this. * ahb: optionally disable atomics => optimize to nothing Trust the compiler the compiler to optimize away unused logic.
This commit is contained in:
parent
740a6073f6
commit
11b3cee07a
@ -30,7 +30,7 @@ class AHBRequestIO(implicit p: Parameters) extends HastiMasterIO
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AHB stage1: translate TileLink Acquires into AHBRequests
|
// AHB stage1: translate TileLink Acquires into AHBRequests
|
||||||
class AHBTileLinkIn(implicit val p: Parameters) extends Module
|
class AHBTileLinkIn(supportAtomics: Boolean = false)(implicit val p: Parameters) extends Module
|
||||||
with HasHastiParameters
|
with HasHastiParameters
|
||||||
with HasTileLinkParameters
|
with HasTileLinkParameters
|
||||||
with HasAddrMapParameters {
|
with HasAddrMapParameters {
|
||||||
@ -50,13 +50,13 @@ class AHBTileLinkIn(implicit val p: Parameters) extends Module
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bursts start at 0 and wrap-around back to 0
|
// Bursts start at 0 and wrap-around back to 0
|
||||||
val finalBurst = SInt(-1, width = log2Up(tlDataBeats)).asUInt
|
val finalBurst = UInt(tlDataBeats-1, width = log2Up(tlDataBeats)).asUInt
|
||||||
val firstBurst = UInt(0, width = log2Up(tlDataBeats))
|
val firstBurst = UInt(0, width = log2Up(tlDataBeats))
|
||||||
val next_wmask = Wire(UInt(width = tlDataBytes)) // calculated below
|
val next_wmask = Wire(UInt(width = tlDataBytes)) // calculated below
|
||||||
|
|
||||||
// State variables for processing more complicated TileLink Acquires
|
// State variables for processing more complicated TileLink Acquires
|
||||||
val s_atom_r :: s_atom_idle1 :: s_atom_w :: s_atom_idle2 :: Nil = Enum(UInt(), 4)
|
val s_atom_r :: s_atom_idle1 :: s_atom_w :: s_atom_idle2 :: Nil = Enum(UInt(), 4)
|
||||||
val atom_state = Reg(init = s_atom_r)
|
val atom_state = Reg(init = s_atom_r) // never changes if !supportAtomics
|
||||||
val done_wmask = Reg(init = UInt(0, width = tlDataBytes))
|
val done_wmask = Reg(init = UInt(0, width = tlDataBytes))
|
||||||
val burst = Reg(init = firstBurst)
|
val burst = Reg(init = firstBurst)
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ class AHBTileLinkIn(implicit val p: Parameters) extends Module
|
|||||||
val isReadBurst = io.acquire.bits.is(Acquire.getBlockType)
|
val isReadBurst = io.acquire.bits.is(Acquire.getBlockType)
|
||||||
val isWriteBurst = io.acquire.bits.is(Acquire.putBlockType)
|
val isWriteBurst = io.acquire.bits.is(Acquire.putBlockType)
|
||||||
val isBurst = isWriteBurst || isReadBurst
|
val isBurst = isWriteBurst || isReadBurst
|
||||||
val isAtomic = io.acquire.bits.is(Acquire.putAtomicType)
|
val isAtomic = io.acquire.bits.is(Acquire.putAtomicType) && Bool(supportAtomics)
|
||||||
val isPut = io.acquire.bits.is(Acquire.putType)
|
val isPut = io.acquire.bits.is(Acquire.putType)
|
||||||
|
|
||||||
// Final states?
|
// Final states?
|
||||||
@ -97,7 +97,11 @@ class AHBTileLinkIn(implicit val p: Parameters) extends Module
|
|||||||
// Advance the burst state
|
// Advance the burst state
|
||||||
// We assume here that TileLink gives us all putBlock beats with nothing between them
|
// We assume here that TileLink gives us all putBlock beats with nothing between them
|
||||||
when (io.request.ready && io.acquire.valid && isBurst) {
|
when (io.request.ready && io.acquire.valid && isBurst) {
|
||||||
burst := burst + UInt(1) // overflow => wraps around to 0
|
when (last_burst) {
|
||||||
|
burst := UInt(0)
|
||||||
|
} .otherwise {
|
||||||
|
burst := burst + UInt(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance the atomic state machine
|
// Advance the atomic state machine
|
||||||
@ -140,7 +144,7 @@ class AHBTileLinkIn(implicit val p: Parameters) extends Module
|
|||||||
val addr_burst = Mux(isReadBurst, addr_beat + burst, addr_beat)
|
val addr_burst = Mux(isReadBurst, addr_beat + burst, addr_beat)
|
||||||
val addr_byte = Mux(isPut, put_addr, io.acquire.bits.addr_byte())
|
val addr_byte = Mux(isPut, put_addr, io.acquire.bits.addr_byte())
|
||||||
val ahbAddr = Cat(addr_block, addr_burst, addr_byte)
|
val ahbAddr = Cat(addr_block, addr_burst, addr_byte)
|
||||||
val ahbSize = Mux(isPut, put_size, Mux(isBurst, UInt(log2Up(tlDataBytes)), io.acquire.bits.op_size()))
|
val ahbSize = Mux(isPut, put_size, Mux(isBurst, UInt(log2Ceil(tlDataBytes)), io.acquire.bits.op_size()))
|
||||||
|
|
||||||
val ahbBurst = MuxLookup(io.acquire.bits.a_type, HBURST_SINGLE, Array(
|
val ahbBurst = MuxLookup(io.acquire.bits.a_type, HBURST_SINGLE, Array(
|
||||||
Acquire.getType -> HBURST_SINGLE,
|
Acquire.getType -> HBURST_SINGLE,
|
||||||
@ -221,10 +225,12 @@ class AHBTileLinkIn(implicit val p: Parameters) extends Module
|
|||||||
assert(!io.acquire.valid || !isBurst || burst === firstBurst || debugBurst === addr_burst - burst, "TileLink putBlock beats not sequential")
|
assert(!io.acquire.valid || !isBurst || burst === firstBurst || debugBurst === addr_burst - burst, "TileLink putBlock beats not sequential")
|
||||||
// We better not get an incomplete TileLink acquire
|
// We better not get an incomplete TileLink acquire
|
||||||
assert(!io.acquire.valid || isBurst || burst === firstBurst, "TileLink never completed a putBlock")
|
assert(!io.acquire.valid || isBurst || burst === firstBurst, "TileLink never completed a putBlock")
|
||||||
|
// If we disabled atomic support, we better not see a request
|
||||||
|
assert(!io.acquire.bits.is(Acquire.putAtomicType) || Bool(supportAtomics))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AHB stage2: execute AHBRequests
|
// AHB stage2: execute AHBRequests
|
||||||
class AHBBusMaster(implicit val p: Parameters) extends Module
|
class AHBBusMaster(supportAtomics: Boolean = false)(implicit val p: Parameters) extends Module
|
||||||
with HasHastiParameters
|
with HasHastiParameters
|
||||||
with HasTileLinkParameters
|
with HasTileLinkParameters
|
||||||
with HasAddrMapParameters {
|
with HasAddrMapParameters {
|
||||||
@ -325,7 +331,7 @@ class AHBBusMaster(implicit val p: Parameters) extends Module
|
|||||||
addr_beat0 := io.request.bits.addr_beat
|
addr_beat0 := io.request.bits.addr_beat
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute Atomic ops
|
// Execute Atomic ops; unused and optimized away if !supportAtomics
|
||||||
val amo_p = p.alterPartial({
|
val amo_p = p.alterPartial({
|
||||||
case CacheBlockOffsetBits => hastiAddrBits
|
case CacheBlockOffsetBits => hastiAddrBits
|
||||||
case AmoAluOperandBits => hastiDataBits
|
case AmoAluOperandBits => hastiDataBits
|
||||||
@ -340,7 +346,7 @@ class AHBBusMaster(implicit val p: Parameters) extends Module
|
|||||||
// Transfer bulk data phase
|
// Transfer bulk data phase
|
||||||
// NOTE: this introduces no bubbles because addrReady is a superset of dataReady
|
// NOTE: this introduces no bubbles because addrReady is a superset of dataReady
|
||||||
when (dataReady) {
|
when (dataReady) {
|
||||||
hwdata1 := alu.io.out // hwdata1 := hwdata0
|
hwdata1 := Mux(Bool(supportAtomics), alu.io.out, hwdata0)
|
||||||
respondTL1 := respondTL0
|
respondTL1 := respondTL0
|
||||||
latchAtom1 := latchAtom0
|
latchAtom1 := latchAtom0
|
||||||
g_type1 := g_type0
|
g_type1 := g_type0
|
||||||
@ -367,7 +373,7 @@ class AHBBusMaster(implicit val p: Parameters) extends Module
|
|||||||
assert(!io.ahb.hresp, "AHB hresp error detected and cannot be reported via TileLink")
|
assert(!io.ahb.hresp, "AHB hresp error detected and cannot be reported via TileLink")
|
||||||
}
|
}
|
||||||
|
|
||||||
class AHBBridge(implicit val p: Parameters) extends Module
|
class AHBBridge(supportAtomics: Boolean = true)(implicit val p: Parameters) extends Module
|
||||||
with HasHastiParameters
|
with HasHastiParameters
|
||||||
with HasTileLinkParameters
|
with HasTileLinkParameters
|
||||||
with HasAddrMapParameters {
|
with HasAddrMapParameters {
|
||||||
@ -383,11 +389,11 @@ class AHBBridge(implicit val p: Parameters) extends Module
|
|||||||
// AHB does not permit bursts to cross a 1KB boundary
|
// AHB does not permit bursts to cross a 1KB boundary
|
||||||
require (tlDataBits * tlDataBeats <= 1024*8)
|
require (tlDataBits * tlDataBeats <= 1024*8)
|
||||||
// tlDataBytes must be a power of 2
|
// tlDataBytes must be a power of 2
|
||||||
require (1 << log2Up(tlDataBytes) == tlDataBytes)
|
require (1 << log2Ceil(tlDataBytes) == tlDataBytes)
|
||||||
|
|
||||||
// Create the sub-blocks
|
// Create the sub-blocks
|
||||||
val fsm = Module(new AHBTileLinkIn)
|
val fsm = Module(new AHBTileLinkIn(supportAtomics))
|
||||||
val bus = Module(new AHBBusMaster)
|
val bus = Module(new AHBBusMaster(supportAtomics))
|
||||||
val pad = Module(new Queue(new Grant, 4))
|
val pad = Module(new Queue(new Grant, 4))
|
||||||
|
|
||||||
fsm.io.acquire <> Queue(io.tl.acquire, 2) // Pipe is also acceptable
|
fsm.io.acquire <> Queue(io.tl.acquire, 2) // Pipe is also acceptable
|
||||||
|
Loading…
Reference in New Issue
Block a user