refactor ioMem and associcated constants. merge Aqcuire and AcquireData
This commit is contained in:
parent
a228dbfa0d
commit
fbca7c6bb3
@ -48,7 +48,6 @@ abstract class CoherencePolicy {
|
|||||||
def needsOuterRead(a_type: UInt, global_state: UInt): Bool
|
def needsOuterRead(a_type: UInt, global_state: UInt): Bool
|
||||||
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool
|
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool
|
||||||
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool
|
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool
|
||||||
def requiresDatalessGrant(a_type: UInt, global_state: UInt): Bool
|
|
||||||
def requiresSelfProbe(a_type: UInt): Bool
|
def requiresSelfProbe(a_type: UInt): Bool
|
||||||
def requiresAckForGrant(g_type: UInt): Bool
|
def requiresAckForGrant(g_type: UInt): Bool
|
||||||
def requiresAckForRelease(r_type: UInt): Bool
|
def requiresAckForRelease(r_type: UInt): Bool
|
||||||
@ -79,7 +78,6 @@ abstract class IncoherentPolicy extends CoherencePolicy {
|
|||||||
def needsOuterRead(a_type: UInt, global_state: UInt): Bool = Bool(false)
|
def needsOuterRead(a_type: UInt, global_state: UInt): Bool = Bool(false)
|
||||||
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool = Bool(false)
|
def needsOuterWrite(a_type: UInt, global_state: UInt): Bool = Bool(false)
|
||||||
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = Bool(false)
|
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = Bool(false)
|
||||||
def requiresDatalessGrant(a_type: UInt, global_state: UInt): Bool = Bool(false)
|
|
||||||
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
||||||
def requiresAckForGrant(g_type: UInt) = Bool(true)
|
def requiresAckForGrant(g_type: UInt) = Bool(true)
|
||||||
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
||||||
@ -282,9 +280,6 @@ class MICoherence extends CoherencePolicyWithUncached {
|
|||||||
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = {
|
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = {
|
||||||
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
||||||
}
|
}
|
||||||
def requiresDatalessGrant(a_type: UInt, global_state: UInt): Bool = {
|
|
||||||
(a_type === acquireWriteUncached)
|
|
||||||
}
|
|
||||||
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
||||||
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
||||||
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
||||||
@ -442,9 +437,6 @@ class MEICoherence extends CoherencePolicyWithUncached {
|
|||||||
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = {
|
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = {
|
||||||
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
||||||
}
|
}
|
||||||
def requiresDatalessGrant(a_type: UInt, global_state: UInt): Bool = {
|
|
||||||
(a_type === acquireWriteUncached)
|
|
||||||
}
|
|
||||||
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
||||||
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
||||||
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
||||||
@ -606,9 +598,6 @@ class MSICoherence extends CoherencePolicyWithUncached {
|
|||||||
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = {
|
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = {
|
||||||
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
||||||
}
|
}
|
||||||
def requiresDatalessGrant(a_type: UInt, global_state: UInt): Bool = {
|
|
||||||
(a_type === acquireWriteUncached)
|
|
||||||
}
|
|
||||||
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
||||||
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
||||||
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
||||||
@ -773,9 +762,6 @@ class MESICoherence extends CoherencePolicyWithUncached {
|
|||||||
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = {
|
def requiresOuterAcquire(a_type: UInt, global_state: UInt): Bool = {
|
||||||
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
||||||
}
|
}
|
||||||
def requiresDatalessGrant(a_type: UInt, global_state: UInt): Bool = {
|
|
||||||
(a_type === acquireWriteUncached)
|
|
||||||
}
|
|
||||||
|
|
||||||
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
||||||
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
||||||
@ -958,9 +944,6 @@ class MigratoryCoherence extends CoherencePolicyWithUncached {
|
|||||||
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
needsOuterRead(a_type, global_state) || needsOuterWrite(a_type, global_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
def requiresDatalessGrant(a_type: UInt, global_state: UInt): Bool = {
|
|
||||||
(a_type === acquireWriteUncached || a_type === acquireWriteWordUncached ||a_type === acquireInvalidateOthers)
|
|
||||||
}
|
|
||||||
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
def requiresAckForGrant(g_type: UInt) = g_type != grantVoluntaryAck
|
||||||
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
def requiresAckForRelease(r_type: UInt) = Bool(false)
|
||||||
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
def requiresSelfProbe(a_type: UInt) = Bool(false)
|
||||||
|
@ -70,9 +70,3 @@ trait TileLinkSizeConstants {
|
|||||||
trait MemoryInterfaceConstants extends
|
trait MemoryInterfaceConstants extends
|
||||||
CacheConstants with
|
CacheConstants with
|
||||||
AddressConstants
|
AddressConstants
|
||||||
{
|
|
||||||
val MEM_TAG_BITS = 5
|
|
||||||
val MEM_DATA_BITS = 128
|
|
||||||
val REFILL_CYCLES = CACHE_DATA_SIZE_IN_BYTES*8/MEM_DATA_BITS
|
|
||||||
val MEM_ADDR_BITS = PADDR_BITS - OFFSET_BITS
|
|
||||||
}
|
|
||||||
|
@ -56,7 +56,7 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int)(implicit conf: TileLinkConfigurati
|
|||||||
// system is 'interesting' if any tile is 'interesting'
|
// system is 'interesting' if any tile is 'interesting'
|
||||||
|
|
||||||
val short_request_bits = 64
|
val short_request_bits = 64
|
||||||
val long_request_bits = short_request_bits + MEM_DATA_BITS*REFILL_CYCLES
|
val long_request_bits = short_request_bits + conf.dataBits
|
||||||
require(short_request_bits % w == 0)
|
require(short_request_bits % w == 0)
|
||||||
|
|
||||||
val rx_count_w = 13 + log2Up(64) - log2Up(w) // data size field is 12 bits
|
val rx_count_w = 13 + log2Up(64) - log2Up(w) // data size field is 12 bits
|
||||||
@ -124,26 +124,23 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int)(implicit conf: TileLinkConfigurati
|
|||||||
}
|
}
|
||||||
io.mem.grant.ready := Bool(true)
|
io.mem.grant.ready := Bool(true)
|
||||||
|
|
||||||
val state_rx :: state_pcr_req :: state_pcr_resp :: state_mem_req :: state_mem_wdata :: state_mem_wresp :: state_mem_rdata :: state_mem_finish :: state_tx :: Nil = Enum(UInt(), 9)
|
val state_rx :: state_pcr_req :: state_pcr_resp :: state_mem_rreq :: state_mem_wreq :: state_mem_rresp :: state_mem_wresp :: state_mem_finish :: state_tx :: Nil = Enum(UInt(), 9)
|
||||||
val state = Reg(init=state_rx)
|
val state = Reg(init=state_rx)
|
||||||
|
|
||||||
val rx_cmd = Mux(rx_word_count === UInt(0), next_cmd, cmd)
|
val rx_cmd = Mux(rx_word_count === UInt(0), next_cmd, cmd)
|
||||||
when (state === state_rx && rx_done) {
|
when (state === state_rx && rx_done) {
|
||||||
state := Mux(rx_cmd === cmd_readmem || rx_cmd === cmd_writemem, state_mem_req,
|
state := Mux(rx_cmd === cmd_readmem, state_mem_rreq,
|
||||||
|
Mux(rx_cmd === cmd_writemem, state_mem_wreq,
|
||||||
Mux(rx_cmd === cmd_readcr || rx_cmd === cmd_writecr, state_pcr_req,
|
Mux(rx_cmd === cmd_readcr || rx_cmd === cmd_writecr, state_pcr_req,
|
||||||
state_tx))
|
state_tx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
val mem_cnt = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
|
val acq_q = Module(new Queue(new Acquire, 1))
|
||||||
val x_init = Module(new Queue(new Acquire, 1))
|
when (state === state_mem_wreq && acq_q.io.enq.ready) {
|
||||||
when (state === state_mem_req && x_init.io.enq.ready) {
|
state := state_mem_wresp
|
||||||
state := Mux(cmd === cmd_writemem, state_mem_wdata, state_mem_rdata)
|
|
||||||
}
|
}
|
||||||
when (state === state_mem_wdata && io.mem.acquire.data.ready) {
|
when (state === state_mem_rreq && acq_q.io.enq.ready) {
|
||||||
when (mem_cnt.andR) {
|
state := state_mem_rresp
|
||||||
state := state_mem_wresp
|
|
||||||
}
|
|
||||||
mem_cnt := mem_cnt + UInt(1)
|
|
||||||
}
|
}
|
||||||
when (state === state_mem_wresp) {
|
when (state === state_mem_wresp) {
|
||||||
when (mem_acked) {
|
when (mem_acked) {
|
||||||
@ -151,12 +148,9 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int)(implicit conf: TileLinkConfigurati
|
|||||||
mem_acked := Bool(false)
|
mem_acked := Bool(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when (state === state_mem_rdata) {
|
when (state === state_mem_rresp) {
|
||||||
when (io.mem.grant.valid) {
|
when (io.mem.grant.valid) {
|
||||||
when (mem_cnt.andR) {
|
state := state_mem_finish
|
||||||
state := state_mem_finish
|
|
||||||
}
|
|
||||||
mem_cnt := mem_cnt + UInt(1)
|
|
||||||
}
|
}
|
||||||
mem_acked := Bool(false)
|
mem_acked := Bool(false)
|
||||||
}
|
}
|
||||||
@ -170,31 +164,33 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int)(implicit conf: TileLinkConfigurati
|
|||||||
rx_count := UInt(0)
|
rx_count := UInt(0)
|
||||||
tx_count := UInt(0)
|
tx_count := UInt(0)
|
||||||
}
|
}
|
||||||
state := Mux(cmd === cmd_readmem && pos != UInt(0), state_mem_req, state_rx)
|
state := Mux(cmd === cmd_readmem && pos != UInt(0), state_mem_rreq, state_rx)
|
||||||
}
|
}
|
||||||
|
|
||||||
var mem_req_data: Bits = null
|
var mem_req_data: Bits = null
|
||||||
for (i <- 0 until MEM_DATA_BITS/short_request_bits) {
|
for (i <- 0 until conf.dataBits/short_request_bits) {
|
||||||
val idx = Cat(mem_cnt, UInt(i, log2Up(MEM_DATA_BITS/short_request_bits)))
|
val idx = UInt(i, log2Up(conf.dataBits/short_request_bits))
|
||||||
when (state === state_mem_rdata && io.mem.grant.valid) {
|
when (state === state_mem_rresp && io.mem.grant.valid) {
|
||||||
packet_ram(idx) := io.mem.grant.bits.payload.data((i+1)*short_request_bits-1, i*short_request_bits)
|
packet_ram(idx) := io.mem.grant.bits.payload.data((i+1)*short_request_bits-1, i*short_request_bits)
|
||||||
}
|
}
|
||||||
mem_req_data = Cat(packet_ram(idx), mem_req_data)
|
mem_req_data = Cat(packet_ram(idx), mem_req_data)
|
||||||
}
|
}
|
||||||
x_init.io.enq.valid := state === state_mem_req
|
acq_q.io.enq.valid := state === state_mem_rreq || state === state_mem_wreq
|
||||||
val init_addr = addr.toUInt >> UInt(OFFSET_BITS-3)
|
val init_addr = addr.toUInt >> UInt(OFFSET_BITS-3)
|
||||||
x_init.io.enq.bits := Mux(cmd === cmd_writemem,
|
acq_q.io.enq.bits := Mux(cmd === cmd_writemem,
|
||||||
Acquire(co.getUncachedWriteAcquireType, init_addr, UInt(0)),
|
Acquire(co.getUncachedWriteAcquireType, init_addr, UInt(0)),
|
||||||
Acquire(co.getUncachedReadAcquireType, init_addr, UInt(0)))
|
Acquire(co.getUncachedReadAcquireType, init_addr, UInt(0)))
|
||||||
io.mem.acquire.meta <> FIFOedLogicalNetworkIOWrapper(x_init.io.deq, UInt(conf.ln.nClients), UInt(0)) // By convention HTIF is the client with the largest id
|
io.mem.acquire.valid := acq_q.io.deq.valid
|
||||||
io.mem.acquire.data.valid := state === state_mem_wdata
|
acq_q.io.deq.ready := io.mem.acquire.ready
|
||||||
io.mem.acquire.data.bits.payload.data := mem_req_data
|
io.mem.acquire.bits.payload := acq_q.io.deq.bits
|
||||||
|
io.mem.acquire.bits.payload.data := mem_req_data
|
||||||
|
io.mem.acquire.bits.header.src := UInt(conf.ln.nClients) // By convention HTIF is the client with the largest id
|
||||||
|
io.mem.acquire.bits.header.dst := UInt(0) // DNC; Overwritten outside module
|
||||||
io.mem.grant_ack.valid := (state === state_mem_finish) && mem_needs_ack
|
io.mem.grant_ack.valid := (state === state_mem_finish) && mem_needs_ack
|
||||||
io.mem.grant_ack.bits.payload.master_xact_id := mem_gxid
|
io.mem.grant_ack.bits.payload.master_xact_id := mem_gxid
|
||||||
io.mem.grant_ack.bits.header.dst := mem_gsrc
|
io.mem.grant_ack.bits.header.dst := mem_gsrc
|
||||||
io.mem.probe.ready := Bool(false)
|
io.mem.probe.ready := Bool(false)
|
||||||
io.mem.release.meta.valid := Bool(false)
|
io.mem.release.valid := Bool(false)
|
||||||
io.mem.release.data.valid := Bool(false)
|
|
||||||
|
|
||||||
val pcr_reset = UInt(pcr_RESET)(pcr_addr.getWidth-1,0)
|
val pcr_reset = UInt(pcr_RESET)(pcr_addr.getWidth-1,0)
|
||||||
val pcrReadData = Reg(Bits(width = io.cpu(0).pcr_rep.bits.getWidth))
|
val pcrReadData = Reg(Bits(width = io.cpu(0).pcr_rep.bits.getWidth))
|
||||||
@ -244,7 +240,7 @@ class HTIF(w: Int, pcr_RESET: Int, nSCR: Int)(implicit conf: TileLinkConfigurati
|
|||||||
for (i <- 0 until scr_rdata.size)
|
for (i <- 0 until scr_rdata.size)
|
||||||
scr_rdata(i) := io.scr.rdata(i)
|
scr_rdata(i) := io.scr.rdata(i)
|
||||||
scr_rdata(0) := UInt(nTiles)
|
scr_rdata(0) := UInt(nTiles)
|
||||||
scr_rdata(1) := UInt((BigInt(REFILL_CYCLES*MEM_DATA_BITS/8) << x_init.io.enq.bits.addr.getWidth) >> 20)
|
scr_rdata(1) := UInt((BigInt(conf.dataBits/8) << acq_q.io.enq.bits.addr.getWidth) >> 20)
|
||||||
|
|
||||||
io.scr.wen := Bool(false)
|
io.scr.wen := Bool(false)
|
||||||
io.scr.wdata := pcr_wdata
|
io.scr.wdata := pcr_wdata
|
||||||
|
@ -72,42 +72,42 @@ class BigMem[T <: Data](n: Int, preLatency: Int, postLatency: Int, leaf: Mem[UIn
|
|||||||
io.rdata := Mux1H(rdataSel, rdataDeep)
|
io.rdata := Mux1H(rdataSel, rdataDeep)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LLCDataReq(ways: Int) extends MemReqCmd
|
class LLCDataReq(ways: Int)(implicit conf: MemoryIFConfiguration) extends MemReqCmd
|
||||||
{
|
{
|
||||||
val way = UInt(width = log2Up(ways))
|
val way = UInt(width = log2Up(ways))
|
||||||
val isWriteback = Bool()
|
val isWriteback = Bool()
|
||||||
override def clone = new LLCDataReq(ways).asInstanceOf[this.type]
|
override def clone = new LLCDataReq(ways)(conf).asInstanceOf[this.type]
|
||||||
}
|
}
|
||||||
|
|
||||||
class LLCTagReq(ways: Int) extends HasMemAddr
|
class LLCTagReq(ways: Int)(implicit val conf: MemoryIFConfiguration) extends HasMemAddr
|
||||||
{
|
{
|
||||||
val way = UInt(width = log2Up(ways))
|
val way = UInt(width = log2Up(ways))
|
||||||
override def clone = new LLCTagReq(ways).asInstanceOf[this.type]
|
override def clone = new LLCTagReq(ways)(conf).asInstanceOf[this.type]
|
||||||
}
|
}
|
||||||
|
|
||||||
class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int) extends Module
|
class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int, refill_cycles: Int)(implicit conf: MemoryIFConfiguration) extends Module
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val cpu = Decoupled(new MemReqCmd).flip
|
val cpu = Decoupled(new MemReqCmd).flip
|
||||||
val repl_way = UInt(INPUT, log2Up(ways))
|
val repl_way = UInt(INPUT, log2Up(ways))
|
||||||
val repl_dirty = Bool(INPUT)
|
val repl_dirty = Bool(INPUT)
|
||||||
val repl_tag = UInt(INPUT, MEM_ADDR_BITS - log2Up(sets))
|
val repl_tag = UInt(INPUT, conf.addrBits - log2Up(sets))
|
||||||
val data = Decoupled(new LLCDataReq(ways))
|
val data = Decoupled(new LLCDataReq(ways))
|
||||||
val tag = Decoupled(new LLCTagReq(ways))
|
val tag = Decoupled(new LLCTagReq(ways))
|
||||||
val mem = new ioMemPipe
|
val mem = new MemPipeIO
|
||||||
val mem_resp_set = UInt(OUTPUT, log2Up(sets))
|
val mem_resp_set = UInt(OUTPUT, log2Up(sets))
|
||||||
val mem_resp_way = UInt(OUTPUT, log2Up(ways))
|
val mem_resp_way = UInt(OUTPUT, log2Up(ways))
|
||||||
}
|
}
|
||||||
|
|
||||||
class MSHR extends Bundle {
|
class MSHR extends Bundle {
|
||||||
val addr = UInt(width = PADDR_BITS - OFFSET_BITS)
|
val addr = UInt(width = conf.addrBits)
|
||||||
val way = UInt(width = log2Up(ways))
|
val way = UInt(width = log2Up(ways))
|
||||||
val tag = io.cpu.bits.tag.clone
|
val tag = io.cpu.bits.tag.clone
|
||||||
val refilled = Bool()
|
val refilled = Bool()
|
||||||
val refillCount = UInt(width = log2Up(REFILL_CYCLES))
|
val refillCount = UInt(width = log2Up(refill_cycles))
|
||||||
val requested = Bool()
|
val requested = Bool()
|
||||||
val old_dirty = Bool()
|
val old_dirty = Bool()
|
||||||
val old_tag = UInt(width = MEM_ADDR_BITS - log2Up(sets))
|
val old_tag = UInt(width = conf.addrBits - log2Up(sets))
|
||||||
val wb_busy = Bool()
|
val wb_busy = Bool()
|
||||||
|
|
||||||
override def clone = new MSHR().asInstanceOf[this.type]
|
override def clone = new MSHR().asInstanceOf[this.type]
|
||||||
@ -139,7 +139,7 @@ class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int) extends Module
|
|||||||
val refillCount = mshr(refillId).refillCount
|
val refillCount = mshr(refillId).refillCount
|
||||||
when (io.mem.resp.valid) {
|
when (io.mem.resp.valid) {
|
||||||
mshr(refillId).refillCount := refillCount + UInt(1)
|
mshr(refillId).refillCount := refillCount + UInt(1)
|
||||||
when (refillCount === UInt(REFILL_CYCLES-1)) { mshr(refillId).refilled := Bool(true) }
|
when (refillCount === UInt(refill_cycles-1)) { mshr(refillId).refilled := Bool(true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val replays = Cat(Bits(0), (outstanding-1 to 0 by -1).map(i => valid(i) && mshr(i).refilled):_*)
|
val replays = Cat(Bits(0), (outstanding-1 to 0 by -1).map(i => valid(i) && mshr(i).refilled):_*)
|
||||||
@ -183,12 +183,12 @@ class LLCMSHRFile(sets: Int, ways: Int, outstanding: Int) extends Module
|
|||||||
io.mem_resp_way := mshr(refillId).way
|
io.mem_resp_way := mshr(refillId).way
|
||||||
}
|
}
|
||||||
|
|
||||||
class LLCWriteback(requestors: Int) extends Module
|
class LLCWriteback(requestors: Int, refill_cycles: Int)(implicit conf: MemoryIFConfiguration) extends Module
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val req = Vec.fill(requestors){Decoupled(UInt(width = MEM_ADDR_BITS)).flip }
|
val req = Vec.fill(requestors){Decoupled(UInt(width = conf.addrBits)).flip }
|
||||||
val data = Vec.fill(requestors){Decoupled(new MemData).flip }
|
val data = Vec.fill(requestors){Decoupled(new MemData).flip }
|
||||||
val mem = new ioMemPipe
|
val mem = new MemPipeIO
|
||||||
}
|
}
|
||||||
|
|
||||||
val valid = Reg(init=Bool(false))
|
val valid = Reg(init=Bool(false))
|
||||||
@ -196,7 +196,7 @@ class LLCWriteback(requestors: Int) extends Module
|
|||||||
val addr = Reg(UInt())
|
val addr = Reg(UInt())
|
||||||
val cmd_sent = Reg(Bool())
|
val cmd_sent = Reg(Bool())
|
||||||
val data_sent = Reg(Bool())
|
val data_sent = Reg(Bool())
|
||||||
val count = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
|
val count = Reg(init=UInt(0, log2Up(refill_cycles)))
|
||||||
|
|
||||||
var anyReq = Bool(false)
|
var anyReq = Bool(false)
|
||||||
for (i <- 0 until requestors) {
|
for (i <- 0 until requestors) {
|
||||||
@ -216,7 +216,7 @@ class LLCWriteback(requestors: Int) extends Module
|
|||||||
|
|
||||||
when (io.mem.req_data.valid && io.mem.req_data.ready) {
|
when (io.mem.req_data.valid && io.mem.req_data.ready) {
|
||||||
count := count + UInt(1)
|
count := count + UInt(1)
|
||||||
when (count === UInt(REFILL_CYCLES-1)) {
|
when (count === UInt(refill_cycles-1)) {
|
||||||
data_sent := Bool(true)
|
data_sent := Bool(true)
|
||||||
when (cmd_sent) { valid := Bool(false) }
|
when (cmd_sent) { valid := Bool(false) }
|
||||||
}
|
}
|
||||||
@ -232,12 +232,12 @@ class LLCWriteback(requestors: Int) extends Module
|
|||||||
io.mem.req_data.bits := io.data(who).bits
|
io.mem.req_data.bits := io.data(who).bits
|
||||||
}
|
}
|
||||||
|
|
||||||
class LLCData(latency: Int, sets: Int, ways: Int, leaf: Mem[UInt]) extends Module
|
class LLCData(latency: Int, sets: Int, ways: Int, refill_cycles: Int, leaf: Mem[UInt])(implicit conf: MemoryIFConfiguration) extends Module
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val req = Decoupled(new LLCDataReq(ways)).flip
|
val req = Decoupled(new LLCDataReq(ways)).flip
|
||||||
val req_data = Decoupled(new MemData).flip
|
val req_data = Decoupled(new MemData).flip
|
||||||
val writeback = Decoupled(UInt(width = MEM_ADDR_BITS))
|
val writeback = Decoupled(UInt(width = conf.addrBits))
|
||||||
val writeback_data = Decoupled(new MemData)
|
val writeback_data = Decoupled(new MemData)
|
||||||
val resp = Decoupled(new MemResp)
|
val resp = Decoupled(new MemResp)
|
||||||
val mem_resp = Valid(new MemResp).flip
|
val mem_resp = Valid(new MemResp).flip
|
||||||
@ -245,7 +245,7 @@ class LLCData(latency: Int, sets: Int, ways: Int, leaf: Mem[UInt]) extends Modul
|
|||||||
val mem_resp_way = UInt(INPUT, log2Up(ways))
|
val mem_resp_way = UInt(INPUT, log2Up(ways))
|
||||||
}
|
}
|
||||||
|
|
||||||
val data = Module(new BigMem(sets*ways*REFILL_CYCLES, 1, latency-1, leaf)(Bits(width = MEM_DATA_BITS)))
|
val data = Module(new BigMem(sets*ways*refill_cycles, 1, latency-1, leaf)(Bits(width = conf.dataBits)))
|
||||||
class QEntry extends MemResp {
|
class QEntry extends MemResp {
|
||||||
val isWriteback = Bool()
|
val isWriteback = Bool()
|
||||||
override def clone = new QEntry().asInstanceOf[this.type]
|
override def clone = new QEntry().asInstanceOf[this.type]
|
||||||
@ -254,12 +254,12 @@ class LLCData(latency: Int, sets: Int, ways: Int, leaf: Mem[UInt]) extends Modul
|
|||||||
val qReady = q.io.count <= UInt(q.entries-latency-1)
|
val qReady = q.io.count <= UInt(q.entries-latency-1)
|
||||||
val valid = Reg(init=Bool(false))
|
val valid = Reg(init=Bool(false))
|
||||||
val req = Reg(io.req.bits.clone)
|
val req = Reg(io.req.bits.clone)
|
||||||
val count = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
|
val count = Reg(init=UInt(0, log2Up(refill_cycles)))
|
||||||
val refillCount = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
|
val refillCount = Reg(init=UInt(0, log2Up(refill_cycles)))
|
||||||
|
|
||||||
when (data.io.in.valid && !io.mem_resp.valid) {
|
when (data.io.in.valid && !io.mem_resp.valid) {
|
||||||
count := count + UInt(1)
|
count := count + UInt(1)
|
||||||
when (valid && count === UInt(REFILL_CYCLES-1)) { valid := Bool(false) }
|
when (valid && count === UInt(refill_cycles-1)) { valid := Bool(false) }
|
||||||
}
|
}
|
||||||
when (io.req.valid && io.req.ready) { valid := Bool(true); req := io.req.bits }
|
when (io.req.valid && io.req.ready) { valid := Bool(true); req := io.req.bits }
|
||||||
when (io.mem_resp.valid) { refillCount := refillCount + UInt(1) }
|
when (io.mem_resp.valid) { refillCount := refillCount + UInt(1) }
|
||||||
@ -300,11 +300,11 @@ class LLCData(latency: Int, sets: Int, ways: Int, leaf: Mem[UInt]) extends Modul
|
|||||||
io.writeback_data.bits := q.io.deq.bits
|
io.writeback_data.bits := q.io.deq.bits
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemReqArb(n: Int) extends Module // UNTESTED
|
class MemReqArb(n: Int, refill_cycles: Int)(implicit conf: MemoryIFConfiguration) extends Module
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val cpu = Vec.fill(n){new ioMem().flip}
|
val cpu = Vec.fill(n){new MemIO().flip}
|
||||||
val mem = new ioMem
|
val mem = new MemIO
|
||||||
}
|
}
|
||||||
|
|
||||||
val lock = Reg(init=Bool(false))
|
val lock = Reg(init=Bool(false))
|
||||||
@ -339,26 +339,26 @@ class MemReqArb(n: Int) extends Module // UNTESTED
|
|||||||
}
|
}
|
||||||
io.mem.resp.ready := io.cpu(respWho).resp.ready
|
io.mem.resp.ready := io.cpu(respWho).resp.ready
|
||||||
|
|
||||||
val unlock = Counter(io.mem.req_data.fire(), REFILL_CYCLES)._2
|
val unlock = Counter(io.mem.req_data.fire(), refill_cycles)._2
|
||||||
when (unlock) { lock := Bool(false) }
|
when (unlock) { lock := Bool(false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class DRAMSideLLC(sets: Int, ways: Int, outstanding: Int, tagLeaf: Mem[UInt], dataLeaf: Mem[UInt]) extends Module
|
class DRAMSideLLC(sets: Int, ways: Int, outstanding: Int, refill_cycles: Int, tagLeaf: Mem[UInt], dataLeaf: Mem[UInt])(implicit conf: MemoryIFConfiguration) extends Module
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val cpu = new ioMem().flip
|
val cpu = new MemIO().flip
|
||||||
val mem = new ioMemPipe
|
val mem = new MemPipeIO
|
||||||
}
|
}
|
||||||
|
|
||||||
val tagWidth = MEM_ADDR_BITS - log2Up(sets)
|
val tagWidth = conf.addrBits - log2Up(sets)
|
||||||
val metaWidth = tagWidth + 2 // valid + dirty
|
val metaWidth = tagWidth + 2 // valid + dirty
|
||||||
|
|
||||||
val memCmdArb = Module(new Arbiter(new MemReqCmd, 2))
|
val memCmdArb = Module(new Arbiter(new MemReqCmd, 2))
|
||||||
val dataArb = Module(new Arbiter(new LLCDataReq(ways), 2))
|
val dataArb = Module(new Arbiter(new LLCDataReq(ways), 2))
|
||||||
val mshr = Module(new LLCMSHRFile(sets, ways, outstanding))
|
val mshr = Module(new LLCMSHRFile(sets, ways, outstanding, refill_cycles))
|
||||||
val tags = Module(new BigMem(sets, 0, 1, tagLeaf)(Bits(width = metaWidth*ways)))
|
val tags = Module(new BigMem(sets, 0, 1, tagLeaf)(Bits(width = metaWidth*ways)))
|
||||||
val data = Module(new LLCData(4, sets, ways, dataLeaf))
|
val data = Module(new LLCData(4, sets, ways, refill_cycles, dataLeaf))
|
||||||
val writeback = Module(new LLCWriteback(2))
|
val writeback = Module(new LLCWriteback(2, refill_cycles))
|
||||||
|
|
||||||
val initCount = Reg(init=UInt(0, log2Up(sets+1)))
|
val initCount = Reg(init=UInt(0, log2Up(sets+1)))
|
||||||
val initialize = !initCount(log2Up(sets))
|
val initialize = !initCount(log2Up(sets))
|
||||||
@ -497,11 +497,11 @@ object HellaQueue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DRAMSideLLCNull(numRequests: Int, refillCycles: Int) extends Module
|
class DRAMSideLLCNull(numRequests: Int, refillCycles: Int)(implicit conf: MemoryIFConfiguration) extends Module
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val cpu = new ioMem().flip
|
val cpu = new MemIO().flip
|
||||||
val mem = new ioMemPipe
|
val mem = new MemPipeIO
|
||||||
}
|
}
|
||||||
|
|
||||||
val numEntries = numRequests * refillCycles
|
val numEntries = numRequests * refillCycles
|
||||||
|
@ -2,49 +2,56 @@ package uncore
|
|||||||
import Chisel._
|
import Chisel._
|
||||||
import scala.math._
|
import scala.math._
|
||||||
|
|
||||||
trait HasMemData extends Bundle {
|
case class MemoryIFConfiguration(addrBits: Int, dataBits: Int, tagBits: Int, dataBeats: Int)
|
||||||
val data = Bits(width = MEM_DATA_BITS)
|
|
||||||
|
abstract trait MemoryIFSubBundle extends Bundle {
|
||||||
|
implicit val conf: MemoryIFConfiguration
|
||||||
|
override def clone = this.getClass.getConstructors.head.newInstance(conf).asInstanceOf[this.type]
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasMemAddr extends Bundle {
|
trait HasMemData extends MemoryIFSubBundle {
|
||||||
val addr = UInt(width = MEM_ADDR_BITS)
|
val data = Bits(width = conf.dataBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasMemTag extends Bundle {
|
trait HasMemAddr extends MemoryIFSubBundle {
|
||||||
val tag = UInt(width = MEM_TAG_BITS)
|
val addr = UInt(width = conf.addrBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemReqCmd extends HasMemAddr with HasMemTag {
|
trait HasMemTag extends MemoryIFSubBundle {
|
||||||
|
val tag = UInt(width = conf.tagBits)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MemReqCmd(implicit val conf: MemoryIFConfiguration) extends HasMemAddr with HasMemTag {
|
||||||
val rw = Bool()
|
val rw = Bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemResp extends HasMemData with HasMemTag
|
class MemResp(implicit val conf: MemoryIFConfiguration) extends HasMemData with HasMemTag
|
||||||
|
|
||||||
class MemData extends HasMemData
|
class MemData(implicit val conf: MemoryIFConfiguration) extends HasMemData
|
||||||
|
|
||||||
class ioMem extends Bundle {
|
class MemIO(implicit val conf: MemoryIFConfiguration) extends Bundle {
|
||||||
val req_cmd = Decoupled(new MemReqCmd)
|
val req_cmd = Decoupled(new MemReqCmd)
|
||||||
val req_data = Decoupled(new MemData)
|
val req_data = Decoupled(new MemData)
|
||||||
val resp = Decoupled(new MemResp).flip
|
val resp = Decoupled(new MemResp).flip
|
||||||
}
|
}
|
||||||
|
|
||||||
class ioMemPipe extends Bundle {
|
class MemPipeIO(implicit val conf: MemoryIFConfiguration) extends Bundle {
|
||||||
val req_cmd = Decoupled(new MemReqCmd)
|
val req_cmd = Decoupled(new MemReqCmd)
|
||||||
val req_data = Decoupled(new MemData)
|
val req_data = Decoupled(new MemData)
|
||||||
val resp = Valid(new MemResp).flip
|
val resp = Valid(new MemResp).flip
|
||||||
}
|
}
|
||||||
|
|
||||||
class ioMemSerialized(w: Int) extends Bundle
|
class MemSerializedIO(w: Int)(implicit val conf: MemoryIFConfiguration) extends Bundle
|
||||||
{
|
{
|
||||||
val req = Decoupled(Bits(width = w))
|
val req = Decoupled(Bits(width = w))
|
||||||
val resp = Valid(Bits(width = w)).flip
|
val resp = Valid(Bits(width = w)).flip
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemSerdes(w: Int) extends Module
|
class MemSerdes(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module
|
||||||
{
|
{
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val wide = new ioMem().flip
|
val wide = new MemIO().flip
|
||||||
val narrow = new ioMemSerialized(w)
|
val narrow = new MemSerializedIO(w)
|
||||||
}
|
}
|
||||||
val abits = io.wide.req_cmd.bits.toBits.getWidth
|
val abits = io.wide.req_cmd.bits.toBits.getWidth
|
||||||
val dbits = io.wide.req_data.bits.toBits.getWidth
|
val dbits = io.wide.req_data.bits.toBits.getWidth
|
||||||
@ -56,7 +63,7 @@ class MemSerdes(w: Int) extends Module
|
|||||||
val s_idle :: s_read_addr :: s_write_addr :: s_write_idle :: s_write_data :: Nil = Enum(UInt(), 5)
|
val s_idle :: s_read_addr :: s_write_addr :: s_write_idle :: s_write_data :: Nil = Enum(UInt(), 5)
|
||||||
val state = Reg(init=s_idle)
|
val state = Reg(init=s_idle)
|
||||||
val send_cnt = Reg(init=UInt(0, log2Up((max(abits, dbits)+w-1)/w)))
|
val send_cnt = Reg(init=UInt(0, log2Up((max(abits, dbits)+w-1)/w)))
|
||||||
val data_send_cnt = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
|
val data_send_cnt = Reg(init=UInt(0, log2Up(conf.dataBeats)))
|
||||||
val adone = io.narrow.req.ready && send_cnt === UInt((abits-1)/w)
|
val adone = io.narrow.req.ready && send_cnt === UInt((abits-1)/w)
|
||||||
val ddone = io.narrow.req.ready && send_cnt === UInt((dbits-1)/w)
|
val ddone = io.narrow.req.ready && send_cnt === UInt((dbits-1)/w)
|
||||||
|
|
||||||
@ -92,12 +99,12 @@ class MemSerdes(w: Int) extends Module
|
|||||||
}
|
}
|
||||||
when (state === s_write_data && ddone) {
|
when (state === s_write_data && ddone) {
|
||||||
data_send_cnt := data_send_cnt + UInt(1)
|
data_send_cnt := data_send_cnt + UInt(1)
|
||||||
state := Mux(data_send_cnt === UInt(REFILL_CYCLES-1), s_idle, s_write_idle)
|
state := Mux(data_send_cnt === UInt(conf.dataBeats-1), s_idle, s_write_idle)
|
||||||
send_cnt := UInt(0)
|
send_cnt := UInt(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
|
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
|
||||||
val data_recv_cnt = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
|
val data_recv_cnt = Reg(init=UInt(0, log2Up(conf.dataBeats)))
|
||||||
val resp_val = Reg(init=Bool(false))
|
val resp_val = Reg(init=Bool(false))
|
||||||
|
|
||||||
resp_val := Bool(false)
|
resp_val := Bool(false)
|
||||||
@ -115,12 +122,12 @@ class MemSerdes(w: Int) extends Module
|
|||||||
io.wide.resp.bits := io.wide.resp.bits.fromBits(in_buf)
|
io.wide.resp.bits := io.wide.resp.bits.fromBits(in_buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemDesserIO(w: Int) extends Bundle {
|
class MemDesserIO(w: Int)(implicit val conf: MemoryIFConfiguration) extends Bundle {
|
||||||
val narrow = new ioMemSerialized(w).flip
|
val narrow = new MemSerializedIO(w).flip
|
||||||
val wide = new ioMem
|
val wide = new MemIO
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemDesser(w: Int) extends Module // test rig side
|
class MemDesser(w: Int)(implicit val conf: MemoryIFConfiguration) extends Module // test rig side
|
||||||
{
|
{
|
||||||
val io = new MemDesserIO(w)
|
val io = new MemDesserIO(w)
|
||||||
val abits = io.wide.req_cmd.bits.toBits.getWidth
|
val abits = io.wide.req_cmd.bits.toBits.getWidth
|
||||||
@ -129,7 +136,7 @@ class MemDesser(w: Int) extends Module // test rig side
|
|||||||
|
|
||||||
require(dbits >= abits && rbits >= dbits)
|
require(dbits >= abits && rbits >= dbits)
|
||||||
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
|
val recv_cnt = Reg(init=UInt(0, log2Up((rbits+w-1)/w)))
|
||||||
val data_recv_cnt = Reg(init=UInt(0, log2Up(REFILL_CYCLES)))
|
val data_recv_cnt = Reg(init=UInt(0, log2Up(conf.dataBeats)))
|
||||||
val adone = io.narrow.req.valid && recv_cnt === UInt((abits-1)/w)
|
val adone = io.narrow.req.valid && recv_cnt === UInt((abits-1)/w)
|
||||||
val ddone = io.narrow.req.valid && recv_cnt === UInt((dbits-1)/w)
|
val ddone = io.narrow.req.valid && recv_cnt === UInt((dbits-1)/w)
|
||||||
val rdone = io.narrow.resp.valid && recv_cnt === UInt((rbits-1)/w)
|
val rdone = io.narrow.resp.valid && recv_cnt === UInt((rbits-1)/w)
|
||||||
@ -157,13 +164,13 @@ class MemDesser(w: Int) extends Module // test rig side
|
|||||||
}
|
}
|
||||||
when (state === s_data && io.wide.req_data.ready) {
|
when (state === s_data && io.wide.req_data.ready) {
|
||||||
state := s_data_recv
|
state := s_data_recv
|
||||||
when (data_recv_cnt === UInt(REFILL_CYCLES-1)) {
|
when (data_recv_cnt === UInt(conf.dataBeats-1)) {
|
||||||
state := s_cmd_recv
|
state := s_cmd_recv
|
||||||
}
|
}
|
||||||
data_recv_cnt := data_recv_cnt + UInt(1)
|
data_recv_cnt := data_recv_cnt + UInt(1)
|
||||||
}
|
}
|
||||||
when (rdone) { // state === s_reply
|
when (rdone) { // state === s_reply
|
||||||
when (data_recv_cnt === UInt(REFILL_CYCLES-1)) {
|
when (data_recv_cnt === UInt(conf.dataBeats-1)) {
|
||||||
state := s_cmd_recv
|
state := s_cmd_recv
|
||||||
}
|
}
|
||||||
recv_cnt := UInt(0)
|
recv_cnt := UInt(0)
|
||||||
@ -177,10 +184,92 @@ class MemDesser(w: Int) extends Module // test rig side
|
|||||||
io.wide.req_data.valid := state === s_data
|
io.wide.req_data.valid := state === s_data
|
||||||
io.wide.req_data.bits.data := in_buf >> UInt(((rbits+w-1)/w - (dbits+w-1)/w)*w)
|
io.wide.req_data.bits.data := in_buf >> UInt(((rbits+w-1)/w - (dbits+w-1)/w)*w)
|
||||||
|
|
||||||
val dataq = Module(new Queue(new MemResp, REFILL_CYCLES))
|
val dataq = Module(new Queue(new MemResp, conf.dataBeats))
|
||||||
dataq.io.enq <> io.wide.resp
|
dataq.io.enq <> io.wide.resp
|
||||||
dataq.io.deq.ready := recv_cnt === UInt((rbits-1)/w)
|
dataq.io.deq.ready := recv_cnt === UInt((rbits-1)/w)
|
||||||
|
|
||||||
io.narrow.resp.valid := dataq.io.deq.valid
|
io.narrow.resp.valid := dataq.io.deq.valid
|
||||||
io.narrow.resp.bits := dataq.io.deq.bits.toBits >> (recv_cnt * UInt(w))
|
io.narrow.resp.bits := dataq.io.deq.bits.toBits >> (recv_cnt * UInt(w))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Adapter betweewn an UncachedTileLinkIO and a mem controller MemIO
|
||||||
|
class MemIOUncachedTileLinkIOConverter(qDepth: Int)(implicit tlconf: TileLinkConfiguration, mifconf: MemoryIFConfiguration) extends Module {
|
||||||
|
val io = new Bundle {
|
||||||
|
val uncached = new UncachedTileLinkIO().flip
|
||||||
|
val mem = new MemIO
|
||||||
|
}
|
||||||
|
|
||||||
|
require(tlconf.dataBits == mifconf.dataBits*mifconf.dataBeats)
|
||||||
|
//require(tlconf.clientXactIdBits <= mifconf.tagBits)
|
||||||
|
|
||||||
|
val mem_cmd_q = Module(new Queue(new MemReqCmd, qDepth))
|
||||||
|
val mem_data_q = Module(new Queue(new MemData, qDepth))
|
||||||
|
val cnt_max = mifconf.dataBeats
|
||||||
|
|
||||||
|
val cnt_out = Reg(UInt(width = log2Up(cnt_max+1)))
|
||||||
|
val active_out = Reg(init=Bool(false))
|
||||||
|
val cmd_sent_out = Reg(init=Bool(false))
|
||||||
|
val buf_out = Reg(Bits())
|
||||||
|
val tag_out = Reg(Bits())
|
||||||
|
val addr_out = Reg(Bits())
|
||||||
|
val has_data = Reg(init=Bool(false))
|
||||||
|
|
||||||
|
val cnt_in = Reg(UInt(width = log2Up(cnt_max+1)))
|
||||||
|
val active_in = Reg(init=Bool(false))
|
||||||
|
val buf_in = Reg(Bits())
|
||||||
|
val tag_in = Reg(UInt(width = mifconf.tagBits))
|
||||||
|
|
||||||
|
// Decompose outgoing TL Acquires into MemIO cmd and data
|
||||||
|
when(!active_out && io.uncached.acquire.valid) {
|
||||||
|
active_out := Bool(true)
|
||||||
|
cmd_sent_out := Bool(false)
|
||||||
|
cnt_out := UInt(0)
|
||||||
|
buf_out := io.uncached.acquire.bits.payload.data
|
||||||
|
tag_out := io.uncached.acquire.bits.payload.client_xact_id
|
||||||
|
addr_out := io.uncached.acquire.bits.payload.addr
|
||||||
|
has_data := tlconf.co.needsOuterWrite(io.uncached.acquire.bits.payload.a_type, UInt(0))
|
||||||
|
}
|
||||||
|
when(active_out) {
|
||||||
|
when(mem_cmd_q.io.enq.fire()) {
|
||||||
|
cmd_sent_out := Bool(true)
|
||||||
|
}
|
||||||
|
when(mem_data_q.io.enq.fire()) {
|
||||||
|
cnt_out := cnt_out + UInt(1)
|
||||||
|
buf_out := buf_out >> UInt(mifconf.dataBits)
|
||||||
|
}
|
||||||
|
when(cmd_sent_out && (!has_data || cnt_out === UInt(cnt_max))) {
|
||||||
|
active_out := Bool(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
io.uncached.acquire.ready := !active_out
|
||||||
|
mem_cmd_q.io.enq.valid := active_out && !cmd_sent_out
|
||||||
|
mem_cmd_q.io.enq.bits.rw := has_data
|
||||||
|
mem_cmd_q.io.enq.bits.tag := tag_out
|
||||||
|
mem_cmd_q.io.enq.bits.addr := addr_out
|
||||||
|
mem_data_q.io.enq.valid := active_out && has_data && cnt_out < UInt(cnt_max)
|
||||||
|
mem_data_q.io.enq.bits.data := buf_out
|
||||||
|
io.mem.req_cmd <> mem_cmd_q.io.deq
|
||||||
|
io.mem.req_data <> mem_data_q.io.deq
|
||||||
|
|
||||||
|
// Aggregate incoming MemIO responses into TL Grants
|
||||||
|
io.mem.resp.ready := !active_in || cnt_in < UInt(cnt_max)
|
||||||
|
io.uncached.grant.valid := active_in && (cnt_in === UInt(cnt_max))
|
||||||
|
io.uncached.grant.bits.payload := Grant(UInt(0), tag_in, UInt(0), buf_in)
|
||||||
|
when(!active_in && io.mem.resp.valid) {
|
||||||
|
active_in := Bool(true)
|
||||||
|
cnt_in := UInt(1)
|
||||||
|
buf_in := io.mem.resp.bits.data << UInt(mifconf.dataBits*(cnt_max-1))
|
||||||
|
tag_in := io.mem.resp.bits.tag
|
||||||
|
}
|
||||||
|
when(active_in) {
|
||||||
|
when(io.uncached.grant.fire()) {
|
||||||
|
active_in := Bool(false)
|
||||||
|
}
|
||||||
|
when(io.mem.resp.fire()) {
|
||||||
|
buf_in := Cat(io.mem.resp.bits.data, buf_in(cnt_max*mifconf.dataBits-1,mifconf.dataBits))
|
||||||
|
cnt_in := cnt_in + UInt(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,102 +1,5 @@
|
|||||||
package uncore
|
package uncore
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import scala.collection.mutable.Stack
|
|
||||||
|
|
||||||
class PairedDataIO[M <: Data, D <: Data](mType: M, dType: D) extends Bundle {
|
|
||||||
val meta = Decoupled(mType)
|
|
||||||
val data = Decoupled(dType)
|
|
||||||
override def clone = { new PairedDataIO(mType, dType).asInstanceOf[this.type] }
|
|
||||||
}
|
|
||||||
|
|
||||||
class PairedArbiterIO[M <: Data, D <: Data](mType: M, dType: D, n: Int) extends Bundle {
|
|
||||||
val in = Vec.fill(n){new PairedDataIO(mType, dType)}.flip
|
|
||||||
val out = new PairedDataIO(mType, dType)
|
|
||||||
val meta_chosen = UInt(OUTPUT, log2Up(n))
|
|
||||||
val data_chosen = UInt(OUTPUT, log2Up(n))
|
|
||||||
override def clone = { new PairedArbiterIO(mType, dType, n).asInstanceOf[this.type] }
|
|
||||||
}
|
|
||||||
|
|
||||||
class PairedLockingRRArbiter[M <: Data, D <: Data](mType: M, dType: D, n: Int, count: Int, needsLock: Option[M => Bool] = None) extends Module {
|
|
||||||
require(isPow2(count))
|
|
||||||
val io = new PairedArbiterIO(mType, dType, n)
|
|
||||||
val locked = if(count > 1) Reg(init=Bool(false)) else Bool(false)
|
|
||||||
val lockIdx = if(count > 1) Reg(init=UInt(n-1)) else UInt(n-1)
|
|
||||||
val grant = List.fill(n)(Bool())
|
|
||||||
val meta_chosen = Bits(width = log2Up(n))
|
|
||||||
|
|
||||||
val chosen_meta_has_data = needsLock.map(_(io.in(meta_chosen).meta.bits)).getOrElse(Bool(true))
|
|
||||||
val valid_meta_has_data = io.in(meta_chosen).meta.valid && chosen_meta_has_data
|
|
||||||
val grant_chosen_meta = !(locked && chosen_meta_has_data)
|
|
||||||
(0 until n).map(i => io.in(i).meta.ready := grant(i) && grant_chosen_meta && io.out.meta.ready)
|
|
||||||
(0 until n).map(i => io.in(i).data.ready := Mux(locked, lockIdx === UInt(i), grant(i) && valid_meta_has_data) && io.out.data.ready)
|
|
||||||
io.out.meta.valid := io.in(meta_chosen).meta.valid && grant_chosen_meta
|
|
||||||
io.out.data.valid := Mux(locked, io.in(lockIdx).data.valid, io.in(meta_chosen).data.valid && valid_meta_has_data)
|
|
||||||
io.out.meta.bits := io.in(meta_chosen).meta.bits
|
|
||||||
io.out.data.bits := Mux(locked, io.in(lockIdx).data.bits, io.in(meta_chosen).data.bits)
|
|
||||||
io.meta_chosen := meta_chosen
|
|
||||||
io.data_chosen := Mux(locked, lockIdx, meta_chosen)
|
|
||||||
|
|
||||||
if(count > 1){
|
|
||||||
val cnt = Reg(init=UInt(0, width = log2Up(count)))
|
|
||||||
val cnt_next = cnt + UInt(1)
|
|
||||||
when(io.out.data.fire()){
|
|
||||||
cnt := cnt_next
|
|
||||||
when(cnt_next === UInt(0)) {
|
|
||||||
locked := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
when(io.out.meta.fire()) {
|
|
||||||
when(needsLock.map(_(io.out.meta.bits)).getOrElse(Bool(true))) {
|
|
||||||
when(!locked) {
|
|
||||||
locked := Bool(true)
|
|
||||||
lockIdx := Vec(io.in.map{in => in.meta.fire()}).indexWhere{i: Bool => i}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val last_grant = Reg(init=Bits(0, log2Up(n)))
|
|
||||||
val ctrl = ArbiterCtrl((0 until n).map(i => io.in(i).meta.valid && UInt(i) > last_grant) ++ io.in.map(_.meta.valid))
|
|
||||||
(0 until n).map(i => grant(i) := ctrl(i) && UInt(i) > last_grant || ctrl(i + n))
|
|
||||||
|
|
||||||
var choose = Bits(n-1)
|
|
||||||
for (i <- n-2 to 0 by -1)
|
|
||||||
choose = Mux(io.in(i).meta.valid, Bits(i), choose)
|
|
||||||
for (i <- n-1 to 1 by -1)
|
|
||||||
choose = Mux(io.in(i).meta.valid && UInt(i) > last_grant, Bits(i), choose)
|
|
||||||
meta_chosen := choose
|
|
||||||
|
|
||||||
when (io.out.meta.fire()) { last_grant := meta_chosen }
|
|
||||||
}
|
|
||||||
|
|
||||||
class PairedCrossbarIO[M <: Data, D <: Data](mType: M, dType: D)(implicit conf: PhysicalNetworkConfiguration) extends Bundle {
|
|
||||||
val in = Vec.fill(conf.nEndpoints){new PairedDataIO(new PhysicalNetworkIO(mType),new PhysicalNetworkIO(dType))}.flip
|
|
||||||
val out = Vec.fill(conf.nEndpoints){new PairedDataIO(new PhysicalNetworkIO(mType),new PhysicalNetworkIO(dType))}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PairedCrossbar[M <: Data, D <: Data](mType: M, dType: D, count: Int, needsLock: Option[PhysicalNetworkIO[M] => Bool] = None)(implicit conf: PhysicalNetworkConfiguration) extends PhysicalNetwork(conf) {
|
|
||||||
val io = new PairedCrossbarIO(mType, dType)
|
|
||||||
|
|
||||||
val metaRdyVecs = List.fill(conf.nEndpoints)(Vec.fill(conf.nEndpoints){Bool()})
|
|
||||||
val dataRdyVecs = List.fill(conf.nEndpoints)(Vec.fill(conf.nEndpoints){Bool()})
|
|
||||||
val rdyVecs = metaRdyVecs zip dataRdyVecs
|
|
||||||
|
|
||||||
io.out.zip(rdyVecs).zipWithIndex.map{ case ((out, rdys), i) => {
|
|
||||||
val rrarb = Module(new PairedLockingRRArbiter(io.in(0).meta.bits.clone, io.in(0).data.bits.clone, conf.nEndpoints, count, needsLock))
|
|
||||||
rrarb.io.in zip io.in zip rdys._1 zip rdys._2 map { case (((arb, in), meta_rdy), data_rdy) => {
|
|
||||||
arb.meta.valid := in.meta.valid && (in.meta.bits.header.dst === UInt(i))
|
|
||||||
arb.meta.bits := in.meta.bits
|
|
||||||
meta_rdy := arb.meta.ready && (in.meta.bits.header.dst === UInt(i))
|
|
||||||
arb.data.valid := in.data.valid && (in.data.bits.header.dst === UInt(i))
|
|
||||||
arb.data.bits := in.data.bits
|
|
||||||
data_rdy := arb.data.ready && (in.data.bits.header.dst === UInt(i))
|
|
||||||
}}
|
|
||||||
out <> rrarb.io.out
|
|
||||||
}}
|
|
||||||
for(i <- 0 until conf.nEndpoints) {
|
|
||||||
io.in(i).meta.ready := rdyVecs.map(r => r._1(i)).reduceLeft(_||_)
|
|
||||||
io.in(i).data.ready := rdyVecs.map(r => r._2(i)).reduceLeft(_||_)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case class PhysicalNetworkConfiguration(nEndpoints: Int, idBits: Int)
|
case class PhysicalNetworkConfiguration(nEndpoints: Int, idBits: Int)
|
||||||
|
|
||||||
@ -147,7 +50,13 @@ class LogicalHeader(implicit conf: LogicalNetworkConfiguration) extends Bundle {
|
|||||||
val dst = UInt(width = conf.idBits)
|
val dst = UInt(width = conf.idBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
object FIFOedLogicalNetworkIOWrapper {
|
class LogicalNetworkIO[T <: Data](dType: T)(implicit conf: LogicalNetworkConfiguration) extends Bundle {
|
||||||
|
val header = new LogicalHeader
|
||||||
|
val payload = dType.clone
|
||||||
|
override def clone = { new LogicalNetworkIO(dType).asInstanceOf[this.type] }
|
||||||
|
}
|
||||||
|
|
||||||
|
object DecoupledLogicalNetworkIOWrapper {
|
||||||
def apply[T <: Data](in: DecoupledIO[T], src: UInt = UInt(0), dst: UInt = UInt(0))(implicit conf: LogicalNetworkConfiguration) = {
|
def apply[T <: Data](in: DecoupledIO[T], src: UInt = UInt(0), dst: UInt = UInt(0))(implicit conf: LogicalNetworkConfiguration) = {
|
||||||
val out = Decoupled(new LogicalNetworkIO(in.bits.clone)).asDirectionless
|
val out = Decoupled(new LogicalNetworkIO(in.bits.clone)).asDirectionless
|
||||||
out.valid := in.valid
|
out.valid := in.valid
|
||||||
@ -159,7 +68,7 @@ object FIFOedLogicalNetworkIOWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object FIFOedLogicalNetworkIOUnwrapper {
|
object DecoupledLogicalNetworkIOUnwrapper {
|
||||||
def apply[T <: Data](in: DecoupledIO[LogicalNetworkIO[T]])(implicit conf: LogicalNetworkConfiguration) = {
|
def apply[T <: Data](in: DecoupledIO[LogicalNetworkIO[T]])(implicit conf: LogicalNetworkConfiguration) = {
|
||||||
val out = Decoupled(in.bits.payload.clone).asDirectionless
|
val out = Decoupled(in.bits.payload.clone).asDirectionless
|
||||||
out.valid := in.valid
|
out.valid := in.valid
|
||||||
@ -168,9 +77,3 @@ object FIFOedLogicalNetworkIOUnwrapper {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LogicalNetworkIO[T <: Data](dType: T)(implicit conf: LogicalNetworkConfiguration) extends Bundle {
|
|
||||||
val header = new LogicalHeader
|
|
||||||
val payload = dType.clone
|
|
||||||
override def clone = { new LogicalNetworkIO(dType).asInstanceOf[this.type] }
|
|
||||||
}
|
|
||||||
|
@ -35,18 +35,24 @@ object Acquire
|
|||||||
acq.a_type := a_type
|
acq.a_type := a_type
|
||||||
acq.addr := addr
|
acq.addr := addr
|
||||||
acq.client_xact_id := client_xact_id
|
acq.client_xact_id := client_xact_id
|
||||||
|
acq.data := Bits(0)
|
||||||
acq.write_mask := Bits(0)
|
acq.write_mask := Bits(0)
|
||||||
acq.subword_addr := Bits(0)
|
acq.subword_addr := Bits(0)
|
||||||
acq.atomic_opcode := Bits(0)
|
acq.atomic_opcode := Bits(0)
|
||||||
acq
|
acq
|
||||||
}
|
}
|
||||||
def apply(a_type: UInt, addr: UInt, client_xact_id: UInt, write_mask: Bits)(implicit conf: TileLinkConfiguration): Acquire = {
|
def apply(a_type: Bits, addr: UInt, client_xact_id: UInt, data: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
|
||||||
val acq = apply(a_type, addr, client_xact_id)
|
val acq = apply(a_type, addr, client_xact_id)
|
||||||
|
acq.data := data
|
||||||
|
acq
|
||||||
|
}
|
||||||
|
def apply(a_type: UInt, addr: UInt, client_xact_id: UInt, write_mask: Bits, data: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
|
||||||
|
val acq = apply(a_type, addr, client_xact_id, data)
|
||||||
acq.write_mask := write_mask
|
acq.write_mask := write_mask
|
||||||
acq
|
acq
|
||||||
}
|
}
|
||||||
def apply(a_type: UInt, addr: UInt, client_xact_id: UInt, subword_addr: UInt, atomic_opcode: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
|
def apply(a_type: UInt, addr: UInt, client_xact_id: UInt, subword_addr: UInt, atomic_opcode: UInt, data: UInt)(implicit conf: TileLinkConfiguration): Acquire = {
|
||||||
val acq = apply(a_type, addr, client_xact_id)
|
val acq = apply(a_type, addr, client_xact_id, data)
|
||||||
acq.subword_addr := subword_addr
|
acq.subword_addr := subword_addr
|
||||||
acq.atomic_opcode := atomic_opcode
|
acq.atomic_opcode := atomic_opcode
|
||||||
acq
|
acq
|
||||||
@ -57,15 +63,17 @@ object Acquire
|
|||||||
acq
|
acq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Acquire(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasPhysicalAddress with HasClientTransactionId {
|
|
||||||
|
class Acquire(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage
|
||||||
|
with HasPhysicalAddress
|
||||||
|
with HasClientTransactionId
|
||||||
|
with HasTileLinkData {
|
||||||
val a_type = UInt(width = conf.co.acquireTypeWidth)
|
val a_type = UInt(width = conf.co.acquireTypeWidth)
|
||||||
val write_mask = Bits(width = ACQUIRE_WRITE_MASK_BITS)
|
val write_mask = Bits(width = ACQUIRE_WRITE_MASK_BITS)
|
||||||
val subword_addr = Bits(width = ACQUIRE_SUBWORD_ADDR_BITS)
|
val subword_addr = Bits(width = ACQUIRE_SUBWORD_ADDR_BITS)
|
||||||
val atomic_opcode = Bits(width = ACQUIRE_ATOMIC_OP_BITS)
|
val atomic_opcode = Bits(width = ACQUIRE_ATOMIC_OP_BITS)
|
||||||
}
|
}
|
||||||
|
|
||||||
class AcquireData(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasTileLinkData
|
|
||||||
|
|
||||||
object Probe
|
object Probe
|
||||||
{
|
{
|
||||||
def apply(p_type: UInt, addr: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
|
def apply(p_type: UInt, addr: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
|
||||||
@ -76,16 +84,20 @@ object Probe
|
|||||||
prb
|
prb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Probe(implicit val conf: TileLinkConfiguration) extends MasterSourcedMessage with HasPhysicalAddress with HasMasterTransactionId {
|
|
||||||
|
class Probe(implicit val conf: TileLinkConfiguration) extends MasterSourcedMessage
|
||||||
|
with HasPhysicalAddress
|
||||||
|
with HasMasterTransactionId {
|
||||||
val p_type = UInt(width = conf.co.probeTypeWidth)
|
val p_type = UInt(width = conf.co.probeTypeWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
object Release
|
object Release
|
||||||
{
|
{
|
||||||
def apply(r_type: UInt, addr: UInt)(implicit conf: TileLinkConfiguration) = {
|
def apply(r_type: UInt, addr: UInt, data: UInt)(implicit conf: TileLinkConfiguration) = {
|
||||||
val rel = new Release
|
val rel = new Release
|
||||||
rel.r_type := r_type
|
rel.r_type := r_type
|
||||||
rel.addr := addr
|
rel.addr := addr
|
||||||
|
rel.data := data
|
||||||
rel
|
rel
|
||||||
}
|
}
|
||||||
def apply(r_type: UInt, addr: UInt, client_xact_id: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
|
def apply(r_type: UInt, addr: UInt, client_xact_id: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
|
||||||
@ -94,16 +106,45 @@ object Release
|
|||||||
rel.addr := addr
|
rel.addr := addr
|
||||||
rel.client_xact_id := client_xact_id
|
rel.client_xact_id := client_xact_id
|
||||||
rel.master_xact_id := master_xact_id
|
rel.master_xact_id := master_xact_id
|
||||||
|
rel.data := UInt(0)
|
||||||
|
rel
|
||||||
|
}
|
||||||
|
def apply(r_type: UInt, addr: UInt, client_xact_id: UInt, master_xact_id: UInt, data: UInt)(implicit conf: TileLinkConfiguration): Release = {
|
||||||
|
val rel = apply(r_type, addr, client_xact_id, master_xact_id)
|
||||||
|
rel.data := data
|
||||||
rel
|
rel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Release(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasPhysicalAddress with HasClientTransactionId with HasMasterTransactionId {
|
|
||||||
|
class Release(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage
|
||||||
|
with HasPhysicalAddress
|
||||||
|
with HasClientTransactionId
|
||||||
|
with HasMasterTransactionId
|
||||||
|
with HasTileLinkData {
|
||||||
val r_type = UInt(width = conf.co.releaseTypeWidth)
|
val r_type = UInt(width = conf.co.releaseTypeWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReleaseData(implicit val conf: TileLinkConfiguration) extends ClientSourcedMessage with HasTileLinkData
|
object Grant
|
||||||
|
{
|
||||||
|
def apply(g_type: UInt, client_xact_id: UInt, master_xact_id: UInt)(implicit conf: TileLinkConfiguration) = {
|
||||||
|
val gnt = new Grant
|
||||||
|
gnt.g_type := g_type
|
||||||
|
gnt.client_xact_id := client_xact_id
|
||||||
|
gnt.master_xact_id := master_xact_id
|
||||||
|
gnt.data := UInt(0)
|
||||||
|
gnt
|
||||||
|
}
|
||||||
|
def apply(g_type: UInt, client_xact_id: UInt, master_xact_id: UInt, data: UInt)(implicit conf: TileLinkConfiguration): Grant = {
|
||||||
|
val gnt = apply(g_type, client_xact_id, master_xact_id)
|
||||||
|
gnt.data := data
|
||||||
|
gnt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Grant(implicit val conf: TileLinkConfiguration) extends MasterSourcedMessage with HasTileLinkData with HasClientTransactionId with HasMasterTransactionId {
|
class Grant(implicit val conf: TileLinkConfiguration) extends MasterSourcedMessage
|
||||||
|
with HasTileLinkData
|
||||||
|
with HasClientTransactionId
|
||||||
|
with HasMasterTransactionId {
|
||||||
val g_type = UInt(width = conf.co.grantTypeWidth)
|
val g_type = UInt(width = conf.co.grantTypeWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +153,7 @@ class GrantAck(implicit val conf: TileLinkConfiguration) extends ClientSourcedMe
|
|||||||
|
|
||||||
class UncachedTileLinkIO(implicit conf: TileLinkConfiguration) extends Bundle {
|
class UncachedTileLinkIO(implicit conf: TileLinkConfiguration) extends Bundle {
|
||||||
implicit val ln = conf.ln
|
implicit val ln = conf.ln
|
||||||
val acquire = new PairedDataIO(new LogicalNetworkIO(new Acquire), new LogicalNetworkIO(new AcquireData))
|
val acquire = new DecoupledIO(new LogicalNetworkIO(new Acquire))
|
||||||
val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip
|
val grant = new DecoupledIO(new LogicalNetworkIO(new Grant)).flip
|
||||||
val grant_ack = new DecoupledIO(new LogicalNetworkIO(new GrantAck))
|
val grant_ack = new DecoupledIO(new LogicalNetworkIO(new GrantAck))
|
||||||
override def clone = { new UncachedTileLinkIO().asInstanceOf[this.type] }
|
override def clone = { new UncachedTileLinkIO().asInstanceOf[this.type] }
|
||||||
@ -120,7 +161,7 @@ class UncachedTileLinkIO(implicit conf: TileLinkConfiguration) extends Bundle {
|
|||||||
|
|
||||||
class TileLinkIO(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIO()(conf) {
|
class TileLinkIO(implicit conf: TileLinkConfiguration) extends UncachedTileLinkIO()(conf) {
|
||||||
val probe = new DecoupledIO(new LogicalNetworkIO(new Probe)).flip
|
val probe = new DecoupledIO(new LogicalNetworkIO(new Probe)).flip
|
||||||
val release = new PairedDataIO(new LogicalNetworkIO(new Release), new LogicalNetworkIO(new ReleaseData))
|
val release = new DecoupledIO(new LogicalNetworkIO(new Release))
|
||||||
override def clone = { new TileLinkIO().asInstanceOf[this.type] }
|
override def clone = { new TileLinkIO().asInstanceOf[this.type] }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,32 +170,28 @@ abstract class TileLinkArbiterLike(val arbN: Int)(implicit conf: TileLinkConfigu
|
|||||||
|
|
||||||
type MasterSourcedWithId = MasterSourcedMessage with HasClientTransactionId
|
type MasterSourcedWithId = MasterSourcedMessage with HasClientTransactionId
|
||||||
type ClientSourcedWithId = ClientSourcedMessage with HasClientTransactionId
|
type ClientSourcedWithId = ClientSourcedMessage with HasClientTransactionId
|
||||||
type ClientSourcedWithData = ClientSourcedMessage with HasTileLinkData
|
|
||||||
|
|
||||||
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int): Bits
|
def clientSourcedClientXactId(in: ClientSourcedWithId, id: Int): Bits
|
||||||
def masterSourcedClientXactId(in: MasterSourcedWithId): Bits
|
def masterSourcedClientXactId(in: MasterSourcedWithId): Bits
|
||||||
def arbIdx(in: MasterSourcedWithId): UInt
|
def arbIdx(in: MasterSourcedWithId): UInt
|
||||||
|
|
||||||
def hookupClientSource[M <: ClientSourcedWithId, D <: ClientSourcedWithData]
|
def hookupClientSource[M <: ClientSourcedWithId]
|
||||||
(ins: Seq[PairedDataIO[LogicalNetworkIO[M],LogicalNetworkIO[D]]],
|
(ins: Seq[DecoupledIO[LogicalNetworkIO[M]]],
|
||||||
out: PairedDataIO[LogicalNetworkIO[M],LogicalNetworkIO[D]]) {
|
out: DecoupledIO[LogicalNetworkIO[M]]) {
|
||||||
def hasData(m: LogicalNetworkIO[M]) = co.messageHasData(m.payload)
|
def hasData(m: LogicalNetworkIO[M]) = co.messageHasData(m.payload)
|
||||||
val arb = Module(new PairedLockingRRArbiter(out.meta.bits.clone, out.data.bits.clone,
|
val arb = Module(new RRArbiter(out.bits.clone, arbN))
|
||||||
arbN, REFILL_CYCLES, hasData _))
|
|
||||||
out <> arb.io.out
|
out <> arb.io.out
|
||||||
ins.zipWithIndex.zip(arb.io.in).map{ case ((req,id), arb) => {
|
ins.zipWithIndex.zip(arb.io.in).map{ case ((req,id), arb) => {
|
||||||
arb.data <> req.data
|
arb.valid := req.valid
|
||||||
arb.meta.valid := req.meta.valid
|
arb.bits := req.bits
|
||||||
arb.meta.bits := req.meta.bits
|
arb.bits.payload.client_xact_id := clientSourcedClientXactId(req.bits.payload, id)
|
||||||
arb.meta.bits.payload := req.meta.bits.payload
|
req.ready := arb.ready
|
||||||
arb.meta.bits.payload.client_xact_id := clientSourcedClientXactId(req.meta.bits.payload, id)
|
|
||||||
req.meta.ready := arb.meta.ready
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
def hookupMasterSource[M <: MasterSourcedWithId]
|
def hookupMasterSource[M <: MasterSourcedWithId]
|
||||||
(ins: Seq[DecoupledIO[LogicalNetworkIO[M]]],
|
(ins: Seq[DecoupledIO[LogicalNetworkIO[M]]],
|
||||||
out: DecoupledIO[LogicalNetworkIO[M]]) {
|
out: DecoupledIO[LogicalNetworkIO[M]]) {
|
||||||
out.ready := Bool(false)
|
out.ready := Bool(false)
|
||||||
for (i <- 0 until arbN) {
|
for (i <- 0 until arbN) {
|
||||||
ins(i).valid := Bool(false)
|
ins(i).valid := Bool(false)
|
||||||
|
@ -31,16 +31,12 @@ class L2CoherenceAgent(bankId: Int)(implicit conf: L2CoherenceAgentConfiguration
|
|||||||
val alloc_arb = Module(new Arbiter(Bool(), trackerList.size))
|
val alloc_arb = Module(new Arbiter(Bool(), trackerList.size))
|
||||||
for( i <- 0 until trackerList.size ) {
|
for( i <- 0 until trackerList.size ) {
|
||||||
val t = trackerList(i).io.client
|
val t = trackerList(i).io.client
|
||||||
alloc_arb.io.in(i).valid := t.acquire.meta.ready
|
alloc_arb.io.in(i).valid := t.acquire.ready
|
||||||
t.acquire.meta.bits := acquire.meta.bits
|
t.acquire.bits := acquire.bits
|
||||||
t.acquire.meta.valid := alloc_arb.io.in(i).ready
|
t.acquire.valid := alloc_arb.io.in(i).ready
|
||||||
|
|
||||||
t.acquire.data.bits := acquire.data.bits
|
|
||||||
t.acquire.data.valid := acquire.data.valid
|
|
||||||
}
|
}
|
||||||
acquire.meta.ready := trackerList.map(_.io.client.acquire.meta.ready).reduce(_||_) && !block_acquires
|
acquire.ready := trackerList.map(_.io.client.acquire.ready).reduce(_||_) && !block_acquires
|
||||||
acquire.data.ready := trackerList.map(_.io.client.acquire.data.ready).reduce(_||_)
|
alloc_arb.io.out.ready := acquire.valid && !block_acquires
|
||||||
alloc_arb.io.out.ready := acquire.meta.valid && !block_acquires
|
|
||||||
|
|
||||||
// Handle probe request generation
|
// Handle probe request generation
|
||||||
val probe_arb = Module(new Arbiter(new LogicalNetworkIO(new Probe), trackerList.size))
|
val probe_arb = Module(new Arbiter(new LogicalNetworkIO(new Probe), trackerList.size))
|
||||||
@ -49,21 +45,18 @@ class L2CoherenceAgent(bankId: Int)(implicit conf: L2CoherenceAgentConfiguration
|
|||||||
|
|
||||||
// Handle releases, which might be voluntary and might have data
|
// Handle releases, which might be voluntary and might have data
|
||||||
val release = io.client.release
|
val release = io.client.release
|
||||||
val voluntary = co.isVoluntary(release.meta.bits.payload)
|
val voluntary = co.isVoluntary(release.bits.payload)
|
||||||
val any_release_conflict = trackerList.tail.map(_.io.has_release_conflict).reduce(_||_)
|
val any_release_conflict = trackerList.tail.map(_.io.has_release_conflict).reduce(_||_)
|
||||||
val block_releases = Bool(false)
|
val block_releases = Bool(false)
|
||||||
val conflict_idx = Vec(trackerList.map(_.io.has_release_conflict)).lastIndexWhere{b: Bool => b}
|
val conflict_idx = Vec(trackerList.map(_.io.has_release_conflict)).lastIndexWhere{b: Bool => b}
|
||||||
//val release_idx = Mux(voluntary, Mux(any_release_conflict, conflict_idx, UInt(0)), release.bits.payload.master_xact_id) // TODO: Add merging logic to allow allocated AcquireTracker to handle conflicts, send all necessary grants, use first sufficient response
|
//val release_idx = Mux(voluntary, Mux(any_release_conflict, conflict_idx, UInt(0)), release.bits.payload.master_xact_id) // TODO: Add merging logic to allow allocated AcquireTracker to handle conflicts, send all necessary grants, use first sufficient response
|
||||||
val release_idx = Mux(voluntary, UInt(0), release.meta.bits.payload.master_xact_id)
|
val release_idx = Mux(voluntary, UInt(0), release.bits.payload.master_xact_id)
|
||||||
for( i <- 0 until trackerList.size ) {
|
for( i <- 0 until trackerList.size ) {
|
||||||
val t = trackerList(i).io.client
|
val t = trackerList(i).io.client
|
||||||
t.release.meta.bits := release.meta.bits
|
t.release.bits := release.bits
|
||||||
t.release.meta.valid := release.meta.valid && (release_idx === UInt(i)) && !block_releases
|
t.release.valid := release.valid && (release_idx === UInt(i)) && !block_releases
|
||||||
t.release.data.bits := release.data.bits
|
|
||||||
t.release.data.valid := release.data.valid
|
|
||||||
}
|
}
|
||||||
release.meta.ready := Vec(trackerList.map(_.io.client.release.meta.ready)).read(release_idx) && !block_releases
|
release.ready := Vec(trackerList.map(_.io.client.release.ready)).read(release_idx) && !block_releases
|
||||||
release.data.ready := trackerList.map(_.io.client.release.data.ready).reduce(_||_)
|
|
||||||
|
|
||||||
// Reply to initial requestor
|
// Reply to initial requestor
|
||||||
val grant_arb = Module(new Arbiter(new LogicalNetworkIO(new Grant), trackerList.size))
|
val grant_arb = Module(new Arbiter(new LogicalNetworkIO(new Grant), trackerList.size))
|
||||||
@ -83,7 +76,7 @@ class L2CoherenceAgent(bankId: Int)(implicit conf: L2CoherenceAgentConfiguration
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
abstract class XactTracker()(implicit conf: L2CoherenceAgentConfiguration) extends Module with OuterRequestGenerator {
|
abstract class XactTracker()(implicit conf: L2CoherenceAgentConfiguration) extends Module {
|
||||||
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
implicit val (tl, ln, co) = (conf.tl, conf.tl.ln, conf.tl.co)
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val client = (new TileLinkIO).flip
|
val client = (new TileLinkIO).flip
|
||||||
@ -92,63 +85,56 @@ abstract class XactTracker()(implicit conf: L2CoherenceAgentConfiguration) exten
|
|||||||
val has_acquire_conflict = Bool(OUTPUT)
|
val has_acquire_conflict = Bool(OUTPUT)
|
||||||
val has_release_conflict = Bool(OUTPUT)
|
val has_release_conflict = Bool(OUTPUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val c_acq = io.client.acquire.bits
|
||||||
|
val c_rel = io.client.release.bits
|
||||||
|
val c_gnt = io.client.grant.bits
|
||||||
|
val c_ack = io.client.grant_ack.bits
|
||||||
|
val m_gnt = io.master.grant.bits
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoluntaryReleaseTracker(trackerId: Int, bankId: Int)(implicit conf: L2CoherenceAgentConfiguration) extends XactTracker()(conf) {
|
class VoluntaryReleaseTracker(trackerId: Int, bankId: Int)(implicit conf: L2CoherenceAgentConfiguration) extends XactTracker()(conf) {
|
||||||
val s_idle :: s_mem :: s_ack :: s_busy :: Nil = Enum(UInt(), 4)
|
val s_idle :: s_mem :: s_ack :: s_busy :: Nil = Enum(UInt(), 4)
|
||||||
val state = Reg(init=s_idle)
|
val state = Reg(init=s_idle)
|
||||||
val xact = Reg{ new Release }
|
val xact = Reg{ new Release }
|
||||||
val init_client_id_ = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
val init_client_id = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||||
val release_data_needs_write = Reg(init=Bool(false))
|
val incoming_rel = io.client.release.bits
|
||||||
val mem_cmd_sent = Reg(init=Bool(false))
|
|
||||||
val cmd_to_write = Acquire(co.getUncachedWriteAcquireType, xact.addr, UInt(trackerId))
|
|
||||||
|
|
||||||
io.has_acquire_conflict := Bool(false)
|
io.has_acquire_conflict := Bool(false)
|
||||||
io.has_release_conflict := co.isCoherenceConflict(xact.addr, io.client.release.meta.bits.payload.addr) && (state != s_idle)
|
io.has_release_conflict := co.isCoherenceConflict(xact.addr, incoming_rel.payload.addr) &&
|
||||||
|
(state != s_idle)
|
||||||
|
|
||||||
io.master.grant.ready := Bool(false)
|
io.master.grant.ready := Bool(false)
|
||||||
io.master.acquire.meta.valid := Bool(false)
|
io.master.acquire.valid := Bool(false)
|
||||||
io.master.acquire.meta.bits.payload := cmd_to_write
|
io.master.acquire.bits.header.src := UInt(bankId)
|
||||||
//TODO io.master.acquire.bits.header.dst
|
//io.master.acquire.bits.header.dst TODO
|
||||||
io.master.acquire.meta.bits.header.src := UInt(bankId)
|
io.master.acquire.bits.payload := Acquire(co.getUncachedWriteAcquireType,
|
||||||
io.master.acquire.data.valid := Bool(false)
|
xact.addr,
|
||||||
io.master.acquire.data.bits.payload.data := UInt(0)
|
UInt(trackerId),
|
||||||
//TODO io.master.acquire_data.bits.header.dst
|
xact.data)
|
||||||
io.master.acquire.data.bits.header.src := UInt(bankId)
|
io.client.acquire.ready := Bool(false)
|
||||||
io.client.acquire.meta.ready := Bool(false)
|
|
||||||
io.client.acquire.data.ready := Bool(false)
|
|
||||||
io.client.probe.valid := Bool(false)
|
io.client.probe.valid := Bool(false)
|
||||||
io.client.release.meta.ready := Bool(false)
|
io.client.release.ready := Bool(false)
|
||||||
io.client.release.data.ready := Bool(false) // DNC
|
|
||||||
io.client.grant.valid := Bool(false)
|
io.client.grant.valid := Bool(false)
|
||||||
io.client.grant.bits.payload.g_type := co.getGrantType(xact, UInt(0))
|
|
||||||
io.client.grant.bits.payload.client_xact_id := xact.client_xact_id
|
|
||||||
io.client.grant.bits.payload.master_xact_id := UInt(trackerId)
|
|
||||||
io.client.grant.bits.payload.data := UInt(0)
|
|
||||||
io.client.grant.bits.header.dst := init_client_id_
|
|
||||||
io.client.grant.bits.header.src := UInt(bankId)
|
io.client.grant.bits.header.src := UInt(bankId)
|
||||||
|
io.client.grant.bits.header.dst := init_client_id
|
||||||
|
io.client.grant.bits.payload := Grant(co.getGrantType(xact, UInt(0)),
|
||||||
|
xact.client_xact_id,
|
||||||
|
UInt(trackerId))
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
is(s_idle) {
|
is(s_idle) {
|
||||||
io.client.release.meta.ready := Bool(true)
|
io.client.release.ready := Bool(true)
|
||||||
when( io.client.release.meta.valid ) {
|
when( io.client.release.valid ) {
|
||||||
xact := io.client.release.meta.bits.payload
|
xact := incoming_rel.payload
|
||||||
init_client_id_ := io.client.release.meta.bits.header.src
|
init_client_id := incoming_rel.header.src
|
||||||
release_data_needs_write := co.messageHasData(io.client.release.meta.bits.payload)
|
state := Mux(co.messageHasData(incoming_rel.payload), s_mem, s_ack)
|
||||||
mem_cnt := UInt(0)
|
|
||||||
mem_cmd_sent := Bool(false)
|
|
||||||
state := s_mem
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(s_mem) {
|
is(s_mem) {
|
||||||
when (release_data_needs_write) {
|
io.master.acquire.valid := Bool(true)
|
||||||
doOuterReqWrite(io.master.acquire,
|
when(io.master.acquire.ready) { state := s_ack }
|
||||||
io.client.release.data,
|
|
||||||
cmd_to_write,
|
|
||||||
release_data_needs_write,
|
|
||||||
mem_cmd_sent,
|
|
||||||
init_client_id_)
|
|
||||||
} . otherwise { state := s_ack }
|
|
||||||
}
|
}
|
||||||
is(s_ack) {
|
is(s_ack) {
|
||||||
io.client.grant.valid := Bool(true)
|
io.client.grant.valid := Bool(true)
|
||||||
@ -158,172 +144,138 @@ class VoluntaryReleaseTracker(trackerId: Int, bankId: Int)(implicit conf: L2Cohe
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CoherenceAgentConfiguration) extends XactTracker()(conf) {
|
class AcquireTracker(trackerId: Int, bankId: Int)(implicit conf: L2CoherenceAgentConfiguration) extends XactTracker()(conf) {
|
||||||
val s_idle :: s_ack :: s_mem :: s_probe :: s_busy :: Nil = Enum(UInt(), 5)
|
val s_idle :: s_probe :: s_mem_read :: s_mem_write :: s_make_grant :: s_busy :: Nil = Enum(UInt(), 6)
|
||||||
val state = Reg(init=s_idle)
|
val state = Reg(init=s_idle)
|
||||||
val xact = Reg{ new Acquire }
|
val xact = Reg{ new Acquire }
|
||||||
val init_client_id_ = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
val init_client_id = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||||
val release_data_client_id = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
|
||||||
//TODO: Will need id reg for merged release xacts
|
//TODO: Will need id reg for merged release xacts
|
||||||
val init_sharer_cnt_ = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
|
||||||
val grant_type = co.getGrantType(xact.a_type, init_sharer_cnt_)
|
val init_sharer_cnt = Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||||
val release_count = if (ln.nClients == 1) UInt(0) else Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
val release_count = if (ln.nClients == 1) UInt(0) else Reg(init=UInt(0, width = log2Up(ln.nClients)))
|
||||||
val probe_flags = Reg(init=Bits(0, width = ln.nClients))
|
val probe_flags = Reg(init=Bits(0, width = ln.nClients))
|
||||||
val curr_p_id = PriorityEncoder(probe_flags)
|
val curr_p_id = PriorityEncoder(probe_flags)
|
||||||
val x_needs_read = Reg(init=Bool(false))
|
|
||||||
val acquire_data_needs_write = Reg(init=Bool(false))
|
val pending_outer_write = co.messageHasData(xact)
|
||||||
val release_data_needs_write = Reg(init=Bool(false))
|
val pending_outer_read = co.needsOuterRead(xact.a_type, UInt(0))
|
||||||
val cmd_to_write = Acquire(co.getUncachedWriteAcquireType, xact.addr, UInt(trackerId))
|
val outer_write_acq = Acquire(co.getUncachedWriteAcquireType,
|
||||||
val cmd_to_read = Acquire(co.getUncachedReadAcquireType, xact.addr, UInt(trackerId))
|
xact.addr, UInt(trackerId), xact.data)
|
||||||
val a_w_mem_cmd_sent = Reg(init=Bool(false))
|
val outer_write_rel = Acquire(co.getUncachedWriteAcquireType,
|
||||||
val r_w_mem_cmd_sent = Reg(init=Bool(false))
|
xact.addr, UInt(trackerId), c_rel.payload.data)
|
||||||
|
val outer_read = Acquire(co.getUncachedReadAcquireType, xact.addr, UInt(trackerId))
|
||||||
|
|
||||||
val probe_initial_flags = Bits(width = ln.nClients)
|
val probe_initial_flags = Bits(width = ln.nClients)
|
||||||
probe_initial_flags := Bits(0)
|
probe_initial_flags := Bits(0)
|
||||||
if (ln.nClients > 1) {
|
if (ln.nClients > 1) {
|
||||||
// issue self-probes for uncached read xacts to facilitate I$ coherence
|
// issue self-probes for uncached read xacts to facilitate I$ coherence
|
||||||
val probe_self = Bool(true) //co.needsSelfProbe(io.client.acquire.bits.payload)
|
val probe_self = Bool(true) //co.needsSelfProbe(io.client.acquire.bits.payload)
|
||||||
val myflag = Mux(probe_self, Bits(0), UIntToOH(io.client.acquire.meta.bits.header.src(log2Up(ln.nClients)-1,0)))
|
val myflag = Mux(probe_self, Bits(0), UIntToOH(c_acq.header.src(log2Up(ln.nClients)-1,0)))
|
||||||
probe_initial_flags := ~(io.tile_incoherent | myflag)
|
probe_initial_flags := ~(io.tile_incoherent | myflag)
|
||||||
}
|
}
|
||||||
|
|
||||||
io.has_acquire_conflict := co.isCoherenceConflict(xact.addr, io.client.acquire.meta.bits.payload.addr) && (state != s_idle)
|
io.has_acquire_conflict := co.isCoherenceConflict(xact.addr, c_acq.payload.addr) && (state != s_idle)
|
||||||
io.has_release_conflict := co.isCoherenceConflict(xact.addr, io.client.release.meta.bits.payload.addr) && (state != s_idle)
|
io.has_release_conflict := co.isCoherenceConflict(xact.addr, c_rel.payload.addr) && (state != s_idle)
|
||||||
io.master.acquire.meta.valid := Bool(false)
|
|
||||||
io.master.acquire.meta.bits.payload := Acquire(co.getUncachedReadAcquireType, xact.addr, UInt(trackerId))
|
io.master.acquire.valid := Bool(false)
|
||||||
io.master.acquire.meta.bits.header.src := UInt(bankId)
|
io.master.acquire.bits.header.src := UInt(bankId)
|
||||||
io.master.acquire.data.valid := Bool(false)
|
//io.master.acquire.bits.header.dst TODO
|
||||||
io.master.acquire.data.bits.payload.data := UInt(0)
|
io.master.acquire.bits.payload := outer_read
|
||||||
io.master.acquire.data.bits.header.src := UInt(bankId)
|
|
||||||
io.client.probe.valid := Bool(false)
|
|
||||||
io.client.probe.bits.payload.p_type := co.getProbeType(xact.a_type, UInt(0))
|
|
||||||
io.client.probe.bits.payload.master_xact_id := UInt(trackerId)
|
|
||||||
io.client.probe.bits.payload.addr := xact.addr
|
|
||||||
io.client.probe.bits.header.dst := UInt(0)
|
|
||||||
io.client.probe.bits.header.src := UInt(bankId)
|
|
||||||
io.client.grant.bits.payload.data := io.master.grant.bits.payload.data
|
|
||||||
io.client.grant.bits.payload.g_type := grant_type
|
|
||||||
io.client.grant.bits.payload.client_xact_id := xact.client_xact_id
|
|
||||||
io.client.grant.bits.payload.master_xact_id := UInt(trackerId)
|
|
||||||
io.client.grant.bits.header.dst := init_client_id_
|
|
||||||
io.client.grant.bits.header.src := UInt(bankId)
|
|
||||||
io.client.grant.valid := (io.master.grant.valid && (UInt(trackerId) === io.master.grant.bits.payload.client_xact_id))
|
|
||||||
io.client.acquire.meta.ready := Bool(false)
|
|
||||||
io.client.acquire.data.ready := Bool(false)
|
|
||||||
io.client.release.meta.ready := Bool(false)
|
|
||||||
io.client.release.data.ready := Bool(false)
|
|
||||||
io.master.grant.ready := io.client.grant.ready
|
io.master.grant.ready := io.client.grant.ready
|
||||||
|
|
||||||
|
io.client.probe.valid := Bool(false)
|
||||||
|
io.client.probe.bits.header.src := UInt(bankId)
|
||||||
|
io.client.probe.bits.header.dst := curr_p_id
|
||||||
|
io.client.probe.bits.payload := Probe(co.getProbeType(xact.a_type, UInt(0)),
|
||||||
|
xact.addr,
|
||||||
|
UInt(trackerId))
|
||||||
|
|
||||||
|
val grant_type = co.getGrantType(xact.a_type, init_sharer_cnt)
|
||||||
|
io.client.grant.valid := Bool(false)
|
||||||
|
io.client.grant.bits.header.src := UInt(bankId)
|
||||||
|
io.client.grant.bits.header.dst := init_client_id
|
||||||
|
io.client.grant.bits.payload := Grant(grant_type,
|
||||||
|
xact.client_xact_id,
|
||||||
|
UInt(trackerId),
|
||||||
|
m_gnt.payload.data)
|
||||||
|
|
||||||
|
io.client.acquire.ready := Bool(false)
|
||||||
|
io.client.release.ready := Bool(false)
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
is(s_idle) {
|
is(s_idle) {
|
||||||
io.client.acquire.meta.ready := Bool(true)
|
io.client.acquire.ready := Bool(true)
|
||||||
when( io.client.acquire.meta.valid ) {
|
val needs_outer_write = co.messageHasData(c_acq.payload)
|
||||||
xact := io.client.acquire.meta.bits.payload
|
val needs_outer_read = co.needsOuterRead(c_acq.payload.a_type, UInt(0))
|
||||||
init_client_id_ := io.client.acquire.meta.bits.header.src
|
when( io.client.acquire.valid ) {
|
||||||
init_sharer_cnt_ := UInt(ln.nClients) // TODO: Broadcast only
|
xact := c_acq.payload
|
||||||
acquire_data_needs_write := co.messageHasData(io.client.acquire.meta.bits.payload)
|
init_client_id := c_acq.header.src
|
||||||
x_needs_read := co.needsOuterRead(io.client.acquire.meta.bits.payload.a_type, UInt(0))
|
init_sharer_cnt := UInt(ln.nClients) // TODO: Broadcast only
|
||||||
probe_flags := probe_initial_flags
|
probe_flags := probe_initial_flags
|
||||||
mem_cnt := UInt(0)
|
|
||||||
r_w_mem_cmd_sent := Bool(false)
|
|
||||||
a_w_mem_cmd_sent := Bool(false)
|
|
||||||
if(ln.nClients > 1) {
|
if(ln.nClients > 1) {
|
||||||
release_count := PopCount(probe_initial_flags)
|
release_count := PopCount(probe_initial_flags)
|
||||||
state := Mux(probe_initial_flags.orR, s_probe, s_mem)
|
state := Mux(probe_initial_flags.orR, s_probe,
|
||||||
} else state := s_mem
|
Mux(needs_outer_write, s_mem_write,
|
||||||
|
Mux(needs_outer_read, s_mem_read, s_make_grant)))
|
||||||
|
} else state := Mux(needs_outer_write, s_mem_write,
|
||||||
|
Mux(needs_outer_read, s_mem_read, s_make_grant))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(s_probe) {
|
is(s_probe) {
|
||||||
when(probe_flags.orR) {
|
// Generate probes
|
||||||
io.client.probe.valid := Bool(true)
|
io.client.probe.valid := probe_flags.orR
|
||||||
io.client.probe.bits.header.dst := curr_p_id
|
|
||||||
}
|
|
||||||
when(io.client.probe.ready) {
|
when(io.client.probe.ready) {
|
||||||
probe_flags := probe_flags & ~(UIntToOH(curr_p_id))
|
probe_flags := probe_flags & ~(UIntToOH(curr_p_id))
|
||||||
}
|
}
|
||||||
io.client.release.meta.ready := Bool(true)
|
|
||||||
when(io.client.release.meta.valid) {
|
// Handle releases, which may have data to be written back
|
||||||
if(ln.nClients > 1) release_count := release_count - UInt(1)
|
when(io.client.release.valid) {
|
||||||
when(release_count === UInt(1)) {
|
when(co.messageHasData(c_rel.payload)) {
|
||||||
state := s_mem
|
io.master.acquire.valid := Bool(true)
|
||||||
}
|
io.master.acquire.bits.payload := outer_write_rel
|
||||||
when( co.messageHasData(io.client.release.meta.bits.payload)) {
|
when(io.master.acquire.ready) {
|
||||||
release_data_needs_write := Bool(true)
|
io.client.release.ready := Bool(true)
|
||||||
release_data_client_id := io.client.release.meta.bits.header.src
|
if(ln.nClients > 1) release_count := release_count - UInt(1)
|
||||||
|
when(release_count === UInt(1)) {
|
||||||
|
state := Mux(pending_outer_write, s_mem_write,
|
||||||
|
Mux(pending_outer_read, s_mem_read, s_make_grant))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} .otherwise {
|
||||||
|
io.client.release.ready := Bool(true)
|
||||||
|
if(ln.nClients > 1) release_count := release_count - UInt(1)
|
||||||
|
when(release_count === UInt(1)) {
|
||||||
|
state := Mux(pending_outer_write, s_mem_write,
|
||||||
|
Mux(pending_outer_read, s_mem_read, s_make_grant))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when (release_data_needs_write) {
|
}
|
||||||
doOuterReqWrite(io.master.acquire,
|
is(s_mem_read) {
|
||||||
io.client.release.data,
|
io.master.acquire.valid := Bool(true)
|
||||||
cmd_to_write,
|
io.master.acquire.bits.payload := outer_read
|
||||||
release_data_needs_write,
|
when(io.master.acquire.ready) {
|
||||||
r_w_mem_cmd_sent,
|
state := Mux(co.requiresAckForGrant(grant_type), s_busy, s_idle)
|
||||||
release_data_client_id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(s_mem) {
|
is(s_mem_write) {
|
||||||
when (release_data_needs_write) {
|
io.master.acquire.valid := Bool(true)
|
||||||
doOuterReqWrite(io.master.acquire,
|
io.master.acquire.bits.payload := outer_write_acq
|
||||||
io.client.release.data,
|
when(io.master.acquire.ready) {
|
||||||
cmd_to_write,
|
state := Mux(pending_outer_read, s_mem_read, s_make_grant)
|
||||||
release_data_needs_write,
|
|
||||||
r_w_mem_cmd_sent,
|
|
||||||
release_data_client_id)
|
|
||||||
} . elsewhen(acquire_data_needs_write) {
|
|
||||||
doOuterReqWrite(io.master.acquire,
|
|
||||||
io.client.acquire.data,
|
|
||||||
cmd_to_write,
|
|
||||||
acquire_data_needs_write,
|
|
||||||
a_w_mem_cmd_sent,
|
|
||||||
init_client_id_)
|
|
||||||
} . elsewhen (x_needs_read) {
|
|
||||||
doOuterReqRead(io.master.acquire, cmd_to_read, x_needs_read)
|
|
||||||
} . otherwise {
|
|
||||||
state := Mux(co.requiresDatalessGrant(xact.a_type, UInt(0)), s_ack,
|
|
||||||
Mux(co.requiresAckForGrant(io.client.grant.bits.payload.g_type), s_busy, s_idle))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(s_ack) {
|
is(s_make_grant) {
|
||||||
io.client.grant.valid := Bool(true)
|
io.client.grant.valid := Bool(true)
|
||||||
when(io.client.grant.ready) { state := Mux(co.requiresAckForGrant(io.client.grant.bits.payload.g_type), s_busy, s_idle) }
|
when(io.client.grant.ready) {
|
||||||
|
state := Mux(co.requiresAckForGrant(grant_type), s_busy, s_idle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is(s_busy) { // Nothing left to do but wait for transaction to complete
|
is(s_busy) { // Nothing left to do but wait for transaction to complete
|
||||||
when (io.client.grant_ack.valid && io.client.grant_ack.bits.payload.master_xact_id === UInt(trackerId)) {
|
when(io.master.grant.valid && m_gnt.payload.client_xact_id === UInt(trackerId)) {
|
||||||
|
io.client.grant.valid := Bool(true)
|
||||||
|
}
|
||||||
|
when(io.client.grant_ack.valid && c_ack.payload.master_xact_id === UInt(trackerId)) {
|
||||||
state := s_idle
|
state := s_idle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract trait OuterRequestGenerator {
|
|
||||||
val mem_cnt = Reg(init=UInt(0, width = log2Up(REFILL_CYCLES)))
|
|
||||||
val mem_cnt_next = mem_cnt + UInt(1)
|
|
||||||
|
|
||||||
def doOuterReqWrite[T <: HasTileLinkData](master_acq: PairedDataIO[LogicalNetworkIO[Acquire],LogicalNetworkIO[AcquireData]], client_data: DecoupledIO[LogicalNetworkIO[T]], cmd: Acquire, trigger: Bool, cmd_sent: Bool, desired_client_data_src_id: UInt) {
|
|
||||||
val do_write = client_data.valid && (client_data.bits.header.src === desired_client_data_src_id)
|
|
||||||
master_acq.meta.bits.payload := cmd
|
|
||||||
master_acq.data.bits.payload := client_data.bits.payload
|
|
||||||
when(master_acq.meta.fire()) {
|
|
||||||
cmd_sent := Bool(true)
|
|
||||||
}
|
|
||||||
when (do_write) {
|
|
||||||
master_acq.meta.valid := !cmd_sent
|
|
||||||
when (master_acq.meta.ready || cmd_sent) {
|
|
||||||
master_acq.data.valid := client_data.valid
|
|
||||||
when(master_acq.data.ready) {
|
|
||||||
client_data.ready:= Bool(true)
|
|
||||||
mem_cnt := mem_cnt_next
|
|
||||||
when(mem_cnt === UInt(REFILL_CYCLES-1)) {
|
|
||||||
trigger := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def doOuterReqRead(master_acq: PairedDataIO[LogicalNetworkIO[Acquire],LogicalNetworkIO[AcquireData]], cmd: Acquire, trigger: Bool) {
|
|
||||||
master_acq.meta.valid := Bool(true)
|
|
||||||
master_acq.meta.bits.payload := cmd
|
|
||||||
when(master_acq.meta.ready) {
|
|
||||||
trigger := Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user