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:
		
				
					committed by
					
						
						Andrew Waterman
					
				
			
			
				
	
			
			
			
						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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user