issue self-probes for uncached read transactions
this facilitates I$ coherence. but it seems like a hack and perhaps the mechanism should be rethought.
This commit is contained in:
parent
0cd0f8a9db
commit
3e6dc35809
@ -4,14 +4,7 @@ import Chisel._
|
|||||||
import Constants._
|
import Constants._
|
||||||
|
|
||||||
object cpuCmdToRW {
|
object cpuCmdToRW {
|
||||||
def apply(cmd: Bits): (Bool, Bool) = {
|
def apply(cmd: Bits): (Bool, Bool) = (isRead(cmd), isWrite(cmd))
|
||||||
val store = (cmd === M_XWR)
|
|
||||||
val load = (cmd === M_XRD)
|
|
||||||
val amo = cmd(3).toBool
|
|
||||||
val read = load || amo || (cmd === M_PFR) || (cmd === M_PFW)
|
|
||||||
val write = store || amo
|
|
||||||
(read, write)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class CoherencePolicy {
|
abstract class CoherencePolicy {
|
||||||
@ -56,6 +49,7 @@ trait UncachedTransactions {
|
|||||||
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix): TransactionInit
|
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix): TransactionInit
|
||||||
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits): TransactionInit
|
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits): TransactionInit
|
||||||
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix): TransactionInit
|
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix): TransactionInit
|
||||||
|
def isUncachedReadTransaction(xinit: TransactionInit): Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class CoherencePolicyWithUncached extends CoherencePolicy with UncachedTransactions
|
abstract class CoherencePolicyWithUncached extends CoherencePolicy with UncachedTransactions
|
||||||
@ -182,6 +176,7 @@ class MICoherence extends CoherencePolicyWithUncached {
|
|||||||
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
||||||
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
||||||
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
||||||
|
def isUncachedReadTransaction(xinit: TransactionInit) = xinit.x_type === xactInitReadUncached
|
||||||
|
|
||||||
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = xactInitReadExclusive
|
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = xactInitReadExclusive
|
||||||
def getTransactionInitTypeOnSecondaryMiss(cmd: Bits, state: UFix, outstanding: TransactionInit): UFix = xactInitReadExclusive
|
def getTransactionInitTypeOnSecondaryMiss(cmd: Bits, state: UFix, outstanding: TransactionInit): UFix = xactInitReadExclusive
|
||||||
@ -317,6 +312,7 @@ class MEICoherence extends CoherencePolicyWithUncached {
|
|||||||
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
||||||
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
||||||
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
||||||
|
def isUncachedReadTransaction(xinit: TransactionInit) = xinit.x_type === xactInitReadUncached
|
||||||
|
|
||||||
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = {
|
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = {
|
||||||
val (read, write) = cpuCmdToRW(cmd)
|
val (read, write) = cpuCmdToRW(cmd)
|
||||||
@ -470,6 +466,7 @@ class MSICoherence extends CoherencePolicyWithUncached {
|
|||||||
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
||||||
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
||||||
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
||||||
|
def isUncachedReadTransaction(xinit: TransactionInit) = xinit.x_type === xactInitReadUncached
|
||||||
|
|
||||||
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = {
|
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = {
|
||||||
val (read, write) = cpuCmdToRW(cmd)
|
val (read, write) = cpuCmdToRW(cmd)
|
||||||
@ -620,6 +617,7 @@ class MESICoherence extends CoherencePolicyWithUncached {
|
|||||||
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
||||||
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
||||||
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
||||||
|
def isUncachedReadTransaction(xinit: TransactionInit) = xinit.x_type === xactInitReadUncached
|
||||||
|
|
||||||
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = {
|
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = {
|
||||||
val (read, write) = cpuCmdToRW(cmd)
|
val (read, write) = cpuCmdToRW(cmd)
|
||||||
@ -787,6 +785,7 @@ class MigratoryCoherence extends CoherencePolicyWithUncached {
|
|||||||
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
def getUncachedReadWordTransactionInit(addr: UFix, id: UFix) = TransactionInit(xactInitReadWordUncached, addr, id)
|
||||||
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
def getUncachedWriteWordTransactionInit(addr: UFix, id: UFix, write_mask: Bits) = TransactionInit(xactInitWriteWordUncached, addr, id, write_mask)
|
||||||
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
def getUncachedAtomicTransactionInit(addr: UFix, id: UFix, subword_addr: UFix, atomic_op: UFix) = TransactionInit(xactInitAtomicUncached, addr, id, subword_addr, atomic_op)
|
||||||
|
def isUncachedReadTransaction(xinit: TransactionInit) = xinit.x_type === xactInitReadUncached
|
||||||
|
|
||||||
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = {
|
def getTransactionInitTypeOnPrimaryMiss(cmd: Bits, state: UFix): UFix = {
|
||||||
val (read, write) = cpuCmdToRW(cmd)
|
val (read, write) = cpuCmdToRW(cmd)
|
||||||
|
@ -50,7 +50,6 @@ trait MemoryOpConstants {
|
|||||||
val M_XWR = Bits("b0001", 4); // int store
|
val M_XWR = Bits("b0001", 4); // int store
|
||||||
val M_PFR = Bits("b0010", 4); // prefetch with intent to read
|
val M_PFR = Bits("b0010", 4); // prefetch with intent to read
|
||||||
val M_PFW = Bits("b0011", 4); // prefetch with intent to write
|
val M_PFW = Bits("b0011", 4); // prefetch with intent to write
|
||||||
val M_FLA = Bits("b0100", 4); // write back and invlaidate all lines
|
|
||||||
val M_FENCE = Bits("b0101", 4); // memory fence
|
val M_FENCE = Bits("b0101", 4); // memory fence
|
||||||
val M_INV = Bits("b0110", 4); // write back and invalidate line
|
val M_INV = Bits("b0110", 4); // write back and invalidate line
|
||||||
val M_CLN = Bits("b0111", 4); // write back line
|
val M_CLN = Bits("b0111", 4); // write back line
|
||||||
@ -62,6 +61,10 @@ trait MemoryOpConstants {
|
|||||||
val M_XA_MAX = Bits("b1101", 4);
|
val M_XA_MAX = Bits("b1101", 4);
|
||||||
val M_XA_MINU = Bits("b1110", 4);
|
val M_XA_MINU = Bits("b1110", 4);
|
||||||
val M_XA_MAXU = Bits("b1111", 4);
|
val M_XA_MAXU = Bits("b1111", 4);
|
||||||
|
|
||||||
|
def isAMO(cmd: Bits) = cmd(3)
|
||||||
|
def isRead(cmd: Bits) = cmd === M_XRD || cmd === M_PFR || cmd === M_PFW || isAMO(cmd)
|
||||||
|
def isWrite(cmd: Bits) = cmd === M_XWR || isAMO(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait MemoryInterfaceConstants extends
|
trait MemoryInterfaceConstants extends
|
||||||
|
@ -89,10 +89,8 @@ class XactTracker(id: Int)(implicit conf: UncoreConfiguration) extends Component
|
|||||||
|
|
||||||
val s_idle :: s_ack :: s_mem :: s_probe :: s_busy :: Nil = Enum(5){ UFix() }
|
val s_idle :: s_ack :: s_mem :: s_probe :: s_busy :: Nil = Enum(5){ UFix() }
|
||||||
val state = Reg(resetVal = s_idle)
|
val state = Reg(resetVal = s_idle)
|
||||||
val addr_ = Reg{ UFix() }
|
val xact = Reg{ new TransactionInit }
|
||||||
val x_type_ = Reg{ Bits() }
|
|
||||||
val init_tile_id_ = Reg{ Bits() }
|
val init_tile_id_ = Reg{ Bits() }
|
||||||
val tile_xact_id_ = Reg{ Bits() }
|
|
||||||
val p_rep_count = if (conf.ntiles == 1) UFix(0) else Reg(resetVal = UFix(0, width = log2Up(conf.ntiles)))
|
val p_rep_count = if (conf.ntiles == 1) UFix(0) else Reg(resetVal = UFix(0, width = log2Up(conf.ntiles)))
|
||||||
val p_req_flags = Reg(resetVal = Bits(0, width = conf.ntiles))
|
val p_req_flags = Reg(resetVal = Bits(0, width = conf.ntiles))
|
||||||
val p_rep_tile_id_ = Reg{ Bits() }
|
val p_rep_tile_id_ = Reg{ Bits() }
|
||||||
@ -105,27 +103,37 @@ class XactTracker(id: Int)(implicit conf: UncoreConfiguration) extends Component
|
|||||||
val mem_cnt_next = mem_cnt + UFix(1)
|
val mem_cnt_next = mem_cnt + UFix(1)
|
||||||
val mem_cnt_max = ~UFix(0, width = log2Up(REFILL_CYCLES))
|
val mem_cnt_max = ~UFix(0, width = log2Up(REFILL_CYCLES))
|
||||||
val p_req_initial_flags = Bits(width = conf.ntiles)
|
val p_req_initial_flags = Bits(width = conf.ntiles)
|
||||||
p_req_initial_flags := (if (conf.ntiles == 1) Bits(0) else ~(io.tile_incoherent | UFixToOH(io.alloc_req.bits.tile_id(log2Up(conf.ntiles)-1,0)))) //TODO: Broadcast only
|
p_req_initial_flags := Bits(0)
|
||||||
|
if (conf.ntiles > 1) {
|
||||||
|
// issue self-probes for uncached read xacts to facilitate I$ coherence
|
||||||
|
// TODO: this is hackish; figure out how to do it more systematically
|
||||||
|
val probe_self = co match {
|
||||||
|
case u: CoherencePolicyWithUncached => u.isUncachedReadTransaction(io.alloc_req.bits.xact_init)
|
||||||
|
case _ => Bool(false)
|
||||||
|
}
|
||||||
|
val myflag = Mux(probe_self, Bits(0), UFixToOH(io.alloc_req.bits.tile_id(log2Up(conf.ntiles)-1,0)))
|
||||||
|
p_req_initial_flags := ~(io.tile_incoherent | myflag)
|
||||||
|
}
|
||||||
|
|
||||||
io.busy := state != s_idle
|
io.busy := state != s_idle
|
||||||
io.addr := addr_
|
io.addr := xact.addr
|
||||||
io.init_tile_id := init_tile_id_
|
io.init_tile_id := init_tile_id_
|
||||||
io.p_rep_tile_id := p_rep_tile_id_
|
io.p_rep_tile_id := p_rep_tile_id_
|
||||||
io.tile_xact_id := tile_xact_id_
|
io.tile_xact_id := xact.tile_xact_id
|
||||||
io.sharer_count := UFix(conf.ntiles) // TODO: Broadcast only
|
io.sharer_count := UFix(conf.ntiles) // TODO: Broadcast only
|
||||||
io.x_type := x_type_
|
io.x_type := xact.x_type
|
||||||
|
|
||||||
io.mem_req_cmd.valid := Bool(false)
|
io.mem_req_cmd.valid := Bool(false)
|
||||||
io.mem_req_cmd.bits.rw := Bool(false)
|
io.mem_req_cmd.bits.rw := Bool(false)
|
||||||
io.mem_req_cmd.bits.addr := addr_
|
io.mem_req_cmd.bits.addr := xact.addr
|
||||||
io.mem_req_cmd.bits.tag := UFix(id)
|
io.mem_req_cmd.bits.tag := UFix(id)
|
||||||
io.mem_req_data.valid := Bool(false)
|
io.mem_req_data.valid := Bool(false)
|
||||||
io.mem_req_data.bits.data := UFix(0)
|
io.mem_req_data.bits.data := UFix(0)
|
||||||
io.mem_req_lock := Bool(false)
|
io.mem_req_lock := Bool(false)
|
||||||
io.probe_req.valid := Bool(false)
|
io.probe_req.valid := Bool(false)
|
||||||
io.probe_req.bits.p_type := co.getProbeRequestType(x_type_, UFix(0))
|
io.probe_req.bits.p_type := co.getProbeRequestType(xact.x_type, UFix(0))
|
||||||
io.probe_req.bits.global_xact_id := UFix(id)
|
io.probe_req.bits.global_xact_id := UFix(id)
|
||||||
io.probe_req.bits.addr := addr_
|
io.probe_req.bits.addr := xact.addr
|
||||||
io.push_p_req := Bits(0, width = conf.ntiles)
|
io.push_p_req := Bits(0, width = conf.ntiles)
|
||||||
io.pop_p_rep := Bits(0, width = conf.ntiles)
|
io.pop_p_rep := Bits(0, width = conf.ntiles)
|
||||||
io.pop_p_rep_data := Bits(0, width = conf.ntiles)
|
io.pop_p_rep_data := Bits(0, width = conf.ntiles)
|
||||||
@ -138,10 +146,8 @@ class XactTracker(id: Int)(implicit conf: UncoreConfiguration) extends Component
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
is(s_idle) {
|
is(s_idle) {
|
||||||
when( io.alloc_req.valid && io.can_alloc ) {
|
when( io.alloc_req.valid && io.can_alloc ) {
|
||||||
addr_ := io.alloc_req.bits.xact_init.addr
|
xact := io.alloc_req.bits.xact_init
|
||||||
x_type_ := io.alloc_req.bits.xact_init.x_type
|
|
||||||
init_tile_id_ := io.alloc_req.bits.tile_id
|
init_tile_id_ := io.alloc_req.bits.tile_id
|
||||||
tile_xact_id_ := io.alloc_req.bits.xact_init.tile_xact_id
|
|
||||||
x_init_data_needs_write := co.messageHasData(io.alloc_req.bits.xact_init)
|
x_init_data_needs_write := co.messageHasData(io.alloc_req.bits.xact_init)
|
||||||
x_needs_read := co.needsMemRead(io.alloc_req.bits.xact_init.x_type, UFix(0))
|
x_needs_read := co.needsMemRead(io.alloc_req.bits.xact_init.x_type, UFix(0))
|
||||||
p_req_flags := p_req_initial_flags
|
p_req_flags := p_req_initial_flags
|
||||||
@ -202,7 +208,7 @@ class XactTracker(id: Int)(implicit conf: UncoreConfiguration) extends Component
|
|||||||
} . elsewhen (x_needs_read) {
|
} . elsewhen (x_needs_read) {
|
||||||
doMemReqRead(io.mem_req_cmd, x_needs_read)
|
doMemReqRead(io.mem_req_cmd, x_needs_read)
|
||||||
} . otherwise {
|
} . otherwise {
|
||||||
state := Mux(co.needsAckReply(x_type_, UFix(0)), s_ack, s_busy)
|
state := Mux(co.needsAckReply(xact.x_type, UFix(0)), s_ack, s_busy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(s_ack) {
|
is(s_ack) {
|
||||||
|
Loading…
Reference in New Issue
Block a user