1
0

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:
Andrew Waterman 2012-11-16 02:37:56 -08:00
parent 0cd0f8a9db
commit 3e6dc35809
3 changed files with 31 additions and 23 deletions

View File

@ -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)

View File

@ -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

View File

@ -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) {