support memory transaction aborts
This commit is contained in:
parent
950b5cd900
commit
5f12990dfb
@ -4,62 +4,74 @@ import Chisel._;
|
|||||||
import Node._;
|
import Node._;
|
||||||
import Constants._;
|
import Constants._;
|
||||||
|
|
||||||
|
class ioUncachedRequestor extends Bundle {
|
||||||
|
val xact_init = (new ioDecoupled) { new TransactionInit() }
|
||||||
|
val xact_abort = (new ioDecoupled) { new TransactionAbort() }.flip
|
||||||
|
val xact_rep = (new ioPipe) { new TransactionReply() }.flip
|
||||||
|
val xact_finish = (new ioDecoupled) { new TransactionFinish() }
|
||||||
|
}
|
||||||
|
|
||||||
class rocketMemArbiter(n: Int) extends Component {
|
class rocketMemArbiter(n: Int) extends Component {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val mem = new ioTileLink
|
val mem = new ioUncachedRequestor
|
||||||
val requestor = Vec(n) { new ioTileLink().flip }
|
val requestor = Vec(n) { new ioUncachedRequestor().flip }
|
||||||
}
|
}
|
||||||
|
|
||||||
var req_val = Bool(false)
|
var xi_val = Bool(false)
|
||||||
var req_rdy = io.mem.xact_init.ready
|
var xi_rdy = io.mem.xact_init.ready
|
||||||
for (i <- 0 until n)
|
for (i <- 0 until n)
|
||||||
{
|
{
|
||||||
io.requestor(i).xact_init.ready := req_rdy
|
io.requestor(i).xact_init.ready := xi_rdy
|
||||||
req_val = req_val || io.requestor(i).xact_init.valid
|
xi_val = xi_val || io.requestor(i).xact_init.valid
|
||||||
req_rdy = req_rdy && !io.requestor(i).xact_init.valid
|
xi_rdy = xi_rdy && !io.requestor(i).xact_init.valid
|
||||||
}
|
}
|
||||||
|
|
||||||
// if more than one requestor at a time can write back, the data
|
var xi_bits = Wire() { new TransactionInit }
|
||||||
// arbiter needs to be made stateful: one xact's write data must
|
xi_bits := io.requestor(n-1).xact_init.bits
|
||||||
// be sent to the memory system contiguously.
|
xi_bits.tile_xact_id := Cat(io.requestor(n-1).xact_init.bits.tile_xact_id, UFix(n-1, log2up(n)))
|
||||||
var req_data_val = Bool(false)
|
for (i <- n-2 to 0 by -1)
|
||||||
var req_data_rdy = io.mem.xact_init_data.ready
|
{
|
||||||
|
var my_xi_bits = Wire() { new TransactionInit }
|
||||||
|
my_xi_bits := io.requestor(i).xact_init.bits
|
||||||
|
my_xi_bits.tile_xact_id := Cat(io.requestor(i).xact_init.bits.tile_xact_id, UFix(i, log2up(n)))
|
||||||
|
|
||||||
|
xi_bits = Mux(io.requestor(i).xact_init.valid, my_xi_bits, xi_bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.mem.xact_init.valid := xi_val
|
||||||
|
io.mem.xact_init.bits := xi_bits
|
||||||
|
|
||||||
|
var xf_val = Bool(false)
|
||||||
|
var xf_rdy = io.mem.xact_finish.ready
|
||||||
for (i <- 0 until n)
|
for (i <- 0 until n)
|
||||||
{
|
{
|
||||||
io.requestor(i).xact_init_data.ready := req_data_rdy
|
io.requestor(i).xact_finish.ready := xf_rdy
|
||||||
req_data_val = req_data_val || io.requestor(i).xact_init_data.valid
|
xf_val = xf_val || io.requestor(i).xact_finish.valid
|
||||||
req_data_rdy = req_data_rdy && !io.requestor(i).xact_init_data.valid
|
xf_rdy = xf_rdy && !io.requestor(i).xact_finish.valid
|
||||||
}
|
}
|
||||||
|
|
||||||
var req_bits = Wire() { new TransactionInit }
|
var xf_bits = io.requestor(n-1).xact_finish.bits
|
||||||
req_bits := io.requestor(n-1).xact_init.bits
|
|
||||||
req_bits.tile_xact_id := Cat(io.requestor(n-1).xact_init.bits.tile_xact_id, UFix(n-1, log2up(n)))
|
|
||||||
for (i <- n-2 to 0 by -1)
|
for (i <- n-2 to 0 by -1)
|
||||||
{
|
xf_bits = Mux(io.requestor(i).xact_finish.valid, io.requestor(i).xact_finish.bits, xf_bits)
|
||||||
var my_req_bits = Wire() { new TransactionInit }
|
|
||||||
my_req_bits := io.requestor(i).xact_init.bits
|
|
||||||
my_req_bits.tile_xact_id := Cat(io.requestor(i).xact_init.bits.tile_xact_id, UFix(i, log2up(n)))
|
|
||||||
|
|
||||||
req_bits = Mux(io.requestor(i).xact_init.valid, my_req_bits, req_bits)
|
io.mem.xact_finish.valid := xf_val
|
||||||
}
|
io.mem.xact_finish.bits := xf_bits
|
||||||
|
|
||||||
var req_data_bits = io.requestor(n-1).xact_init_data.bits
|
|
||||||
for (i <- n-2 to 0 by -1)
|
|
||||||
req_data_bits = Mux(io.requestor(i).xact_init_data.valid, io.requestor(i).xact_init_data.bits, req_data_bits)
|
|
||||||
|
|
||||||
io.mem.xact_init.valid := req_val
|
|
||||||
io.mem.xact_init.bits := req_bits
|
|
||||||
|
|
||||||
io.mem.xact_init_data.valid := req_data_val
|
|
||||||
io.mem.xact_init_data.bits := req_data_bits
|
|
||||||
|
|
||||||
for (i <- 0 until n)
|
for (i <- 0 until n)
|
||||||
{
|
{
|
||||||
val tag = io.mem.xact_rep.bits.tile_xact_id
|
val tag = io.mem.xact_rep.bits.tile_xact_id
|
||||||
io.requestor(i).xact_rep.valid := io.mem.xact_rep.valid && tag(log2up(n)-1,0) === UFix(i)
|
io.requestor(i).xact_rep.valid := io.mem.xact_rep.valid && tag(log2up(n)-1,0) === UFix(i)
|
||||||
io.requestor(i).xact_rep.bits.data := io.mem.xact_rep.bits.data
|
io.requestor(i).xact_rep.bits := io.mem.xact_rep.bits
|
||||||
io.requestor(i).xact_rep.bits.t_type := io.mem.xact_rep.bits.t_type
|
|
||||||
io.requestor(i).xact_rep.bits.tile_xact_id := tag >> UFix(log2up(n))
|
io.requestor(i).xact_rep.bits.tile_xact_id := tag >> UFix(log2up(n))
|
||||||
io.requestor(i).xact_rep.bits.global_xact_id := io.mem.xact_rep.bits.global_xact_id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i <- 0 until n)
|
||||||
|
{
|
||||||
|
val tag = io.mem.xact_abort.bits.tile_xact_id
|
||||||
|
io.requestor(i).xact_abort.valid := io.mem.xact_abort.valid && tag(log2up(n)-1,0) === UFix(i)
|
||||||
|
io.requestor(i).xact_abort.bits := io.mem.xact_abort.bits
|
||||||
|
io.requestor(i).xact_abort.bits.tile_xact_id := tag >> UFix(log2up(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
io.mem.xact_abort.ready := Bool(true)
|
||||||
}
|
}
|
||||||
|
@ -395,6 +395,8 @@ class CoherenceHubNull extends CoherenceHub {
|
|||||||
x_rep.bits.global_xact_id := UFix(0) // don't care
|
x_rep.bits.global_xact_id := UFix(0) // don't care
|
||||||
x_rep.bits.data := io.mem.resp.bits.data
|
x_rep.bits.data := io.mem.resp.bits.data
|
||||||
x_rep.valid := io.mem.resp.valid || x_init.valid && is_write
|
x_rep.valid := io.mem.resp.valid || x_init.valid && is_write
|
||||||
|
|
||||||
|
io.tiles(0).xact_abort.valid := Bool(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ object Constants
|
|||||||
val NTILES = 1
|
val NTILES = 1
|
||||||
val COHERENCE_DATA_BITS = (1 << OFFSET_BITS)*8
|
val COHERENCE_DATA_BITS = (1 << OFFSET_BITS)*8
|
||||||
val TILE_ID_BITS = 1
|
val TILE_ID_BITS = 1
|
||||||
val TILE_XACT_ID_BITS = log2up(NMSHR)+2
|
val TILE_XACT_ID_BITS = log2up(NMSHR)+3
|
||||||
val GLOBAL_XACT_ID_BITS = 4
|
val GLOBAL_XACT_ID_BITS = 4
|
||||||
val NGLOBAL_XACTS = 1 << GLOBAL_XACT_ID_BITS
|
val NGLOBAL_XACTS = 1 << GLOBAL_XACT_ID_BITS
|
||||||
|
|
||||||
|
@ -78,7 +78,12 @@ class rocketHTIF(w: Int, ncores: Int) extends Component
|
|||||||
Mux(!nack && cmd === cmd_readcr, UFix(1), UFix(0)))
|
Mux(!nack && cmd === cmd_readcr, UFix(1), UFix(0)))
|
||||||
val tx_done = packet_ram_raddr - UFix(1) === tx_size
|
val tx_done = packet_ram_raddr - UFix(1) === tx_size
|
||||||
|
|
||||||
val state_rx :: state_pcr :: state_mem_req :: state_mem_wdata :: state_mem_rdata :: state_tx :: Nil = Enum(6) { UFix() }
|
val mem_acked = Reg(resetVal = Bool(false))
|
||||||
|
val mem_nacked = Reg(resetVal = Bool(false))
|
||||||
|
when (io.mem.xact_rep.valid) { mem_acked := Bool(true) }
|
||||||
|
when (io.mem.xact_abort.valid) { mem_nacked := Bool(true) }
|
||||||
|
|
||||||
|
val state_rx :: state_pcr :: state_mem_req :: state_mem_wdata :: state_mem_wresp :: state_mem_rdata :: state_tx :: Nil = Enum(7) { UFix() }
|
||||||
val state = Reg(resetVal = state_rx)
|
val state = Reg(resetVal = state_rx)
|
||||||
|
|
||||||
when (state === state_rx && rx_done) {
|
when (state === state_rx && rx_done) {
|
||||||
@ -96,13 +101,35 @@ class rocketHTIF(w: Int, ncores: Int) extends Component
|
|||||||
when (state === state_mem_req && io.mem.xact_init.ready) {
|
when (state === state_mem_req && io.mem.xact_init.ready) {
|
||||||
state := Mux(cmd === cmd_writemem, state_mem_wdata, state_mem_rdata)
|
state := Mux(cmd === cmd_writemem, state_mem_wdata, state_mem_rdata)
|
||||||
}
|
}
|
||||||
when (state === state_mem_wdata && io.mem.xact_init_data.ready ||
|
when (state === state_mem_wdata && io.mem.xact_init_data.ready) {
|
||||||
state === state_mem_rdata && io.mem.xact_rep.valid) {
|
|
||||||
when (mem_cnt.andR) {
|
when (mem_cnt.andR) {
|
||||||
state := state_tx
|
state := state_mem_wresp
|
||||||
}
|
}
|
||||||
mem_cnt := mem_cnt + UFix(1)
|
mem_cnt := mem_cnt + UFix(1)
|
||||||
}
|
}
|
||||||
|
when (state === state_mem_wresp) {
|
||||||
|
when (mem_nacked) {
|
||||||
|
state := state_mem_req
|
||||||
|
mem_nacked := Bool(false)
|
||||||
|
}
|
||||||
|
when (mem_acked) {
|
||||||
|
state := state_tx
|
||||||
|
mem_acked := Bool(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when (state === state_mem_rdata) {
|
||||||
|
when (mem_nacked) {
|
||||||
|
state := state_mem_req
|
||||||
|
mem_nacked := Bool(false)
|
||||||
|
}
|
||||||
|
when (io.mem.xact_rep.valid) {
|
||||||
|
when (mem_cnt.andR) {
|
||||||
|
state := state_tx
|
||||||
|
}
|
||||||
|
mem_cnt := mem_cnt + UFix(1)
|
||||||
|
}
|
||||||
|
mem_acked := Bool(false)
|
||||||
|
}
|
||||||
when (state === state_tx && tx_done) {
|
when (state === state_tx && tx_done) {
|
||||||
rx_count := UFix(0)
|
rx_count := UFix(0)
|
||||||
tx_count := UFix(0)
|
tx_count := UFix(0)
|
||||||
|
@ -20,7 +20,7 @@ class ioImem(view: List[String] = null) extends Bundle (view)
|
|||||||
class ioRocketICache extends Bundle()
|
class ioRocketICache extends Bundle()
|
||||||
{
|
{
|
||||||
val cpu = new ioImem();
|
val cpu = new ioImem();
|
||||||
val mem = new ioTileLink
|
val mem = new ioUncachedRequestor
|
||||||
}
|
}
|
||||||
|
|
||||||
// basic direct mapped instruction cache
|
// basic direct mapped instruction cache
|
||||||
@ -49,6 +49,7 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
|||||||
|
|
||||||
val s_reset :: s_ready :: s_request :: s_refill_wait :: s_refill :: Nil = Enum(5) { UFix() };
|
val s_reset :: s_ready :: s_request :: s_refill_wait :: s_refill :: Nil = Enum(5) { UFix() };
|
||||||
val state = Reg(resetVal = s_reset);
|
val state = Reg(resetVal = s_reset);
|
||||||
|
val invalidated = Reg() { Bool() }
|
||||||
|
|
||||||
val r_cpu_req_idx = Reg { Bits() }
|
val r_cpu_req_idx = Reg { Bits() }
|
||||||
val r_cpu_req_ppn = Reg { Bits() }
|
val r_cpu_req_ppn = Reg { Bits() }
|
||||||
@ -78,13 +79,14 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
|||||||
when (io.mem.xact_rep.valid) {
|
when (io.mem.xact_rep.valid) {
|
||||||
refill_count := refill_count + UFix(1);
|
refill_count := refill_count + UFix(1);
|
||||||
}
|
}
|
||||||
|
val refill_done = io.mem.xact_rep.valid && refill_count.andR
|
||||||
|
|
||||||
val repl_way = LFSR16(state === s_ready && r_cpu_req_val && !io.cpu.itlb_miss && !tag_hit)(log2up(assoc)-1,0)
|
val repl_way = LFSR16(state === s_ready && r_cpu_req_val && !io.cpu.itlb_miss && !tag_hit)(log2up(assoc)-1,0)
|
||||||
val word_shift = Cat(r_cpu_req_idx(offsetmsb-rf_cnt_bits,offsetlsb), UFix(0, log2up(databits))).toUFix
|
val word_shift = Cat(r_cpu_req_idx(offsetmsb-rf_cnt_bits,offsetlsb), UFix(0, log2up(databits))).toUFix
|
||||||
|
val tag_we = (state === s_refill) && refill_done
|
||||||
val tag_addr =
|
val tag_addr =
|
||||||
Mux((state === s_refill_wait), r_cpu_req_idx(indexmsb,indexlsb),
|
Mux((state === s_refill), r_cpu_req_idx(indexmsb,indexlsb),
|
||||||
io.cpu.req_idx(indexmsb,indexlsb)).toUFix;
|
io.cpu.req_idx(indexmsb,indexlsb)).toUFix;
|
||||||
val tag_we = (state === s_refill_wait) && io.mem.xact_rep.valid;
|
|
||||||
val data_addr =
|
val data_addr =
|
||||||
Mux((state === s_refill_wait) || (state === s_refill), Cat(r_cpu_req_idx(indexmsb,offsetbits), refill_count),
|
Mux((state === s_refill_wait) || (state === s_refill), Cat(r_cpu_req_idx(indexmsb,offsetbits), refill_count),
|
||||||
io.cpu.req_idx(indexmsb, offsetbits-rf_cnt_bits)).toUFix;
|
io.cpu.req_idx(indexmsb, offsetbits-rf_cnt_bits)).toUFix;
|
||||||
@ -102,10 +104,10 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
|||||||
// valid bit array
|
// valid bit array
|
||||||
val vb_array = Reg(resetVal = Bits(0, sets));
|
val vb_array = Reg(resetVal = Bits(0, sets));
|
||||||
when (io.cpu.invalidate) {
|
when (io.cpu.invalidate) {
|
||||||
vb_array := Bits(0,sets);
|
vb_array := Bits(0)
|
||||||
}
|
}
|
||||||
.elsewhen (tag_we && repl_me) {
|
.elsewhen (tag_we && repl_me) {
|
||||||
vb_array := vb_array.bitSet(r_cpu_req_idx(indexmsb,indexlsb).toUFix, UFix(1,1));
|
vb_array := vb_array.bitSet(r_cpu_req_idx(indexmsb,indexlsb).toUFix, !invalidated)
|
||||||
}
|
}
|
||||||
|
|
||||||
val valid = vb_array(r_cpu_req_idx(indexmsb,indexlsb)).toBool;
|
val valid = vb_array(r_cpu_req_idx(indexmsb,indexlsb)).toBool;
|
||||||
@ -131,20 +133,20 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
|||||||
io.mem.xact_init.valid := (state === s_request)
|
io.mem.xact_init.valid := (state === s_request)
|
||||||
io.mem.xact_init.bits.t_type := X_INIT_READ_UNCACHED
|
io.mem.xact_init.bits.t_type := X_INIT_READ_UNCACHED
|
||||||
io.mem.xact_init.bits.address := r_cpu_miss_addr(tagmsb,indexlsb).toUFix
|
io.mem.xact_init.bits.address := r_cpu_miss_addr(tagmsb,indexlsb).toUFix
|
||||||
io.mem.xact_init_data.valid := Bool(false)
|
|
||||||
|
|
||||||
// control state machine
|
// control state machine
|
||||||
|
when (io.cpu.invalidate) {
|
||||||
|
invalidated := Bool(true)
|
||||||
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
is (s_reset) {
|
is (s_reset) {
|
||||||
state := s_ready;
|
state := s_ready;
|
||||||
}
|
}
|
||||||
is (s_ready) {
|
is (s_ready) {
|
||||||
when (io.cpu.itlb_miss) {
|
when (r_cpu_req_val && !tag_hit && !io.cpu.itlb_miss) {
|
||||||
state := s_ready;
|
|
||||||
}
|
|
||||||
.elsewhen (r_cpu_req_val && !tag_hit) {
|
|
||||||
state := s_request;
|
state := s_request;
|
||||||
}
|
}
|
||||||
|
invalidated := Bool(false)
|
||||||
}
|
}
|
||||||
is (s_request)
|
is (s_request)
|
||||||
{
|
{
|
||||||
@ -153,12 +155,15 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is (s_refill_wait) {
|
is (s_refill_wait) {
|
||||||
|
when (io.mem.xact_abort.valid) {
|
||||||
|
state := s_request
|
||||||
|
}
|
||||||
when (io.mem.xact_rep.valid) {
|
when (io.mem.xact_rep.valid) {
|
||||||
state := s_refill;
|
state := s_refill;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is (s_refill) {
|
is (s_refill) {
|
||||||
when (io.mem.xact_rep.valid && refill_count.andR) {
|
when (refill_done) {
|
||||||
state := s_ready;
|
state := s_ready;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,22 +18,23 @@ class rocketIPrefetcher extends Component() {
|
|||||||
val s_invalid :: s_valid :: s_refilling :: s_req_wait :: s_resp_wait :: s_bad_resp_wait :: Nil = Enum(6) { UFix() };
|
val s_invalid :: s_valid :: s_refilling :: s_req_wait :: s_resp_wait :: s_bad_resp_wait :: Nil = Enum(6) { UFix() };
|
||||||
val state = Reg(resetVal = s_invalid);
|
val state = Reg(resetVal = s_invalid);
|
||||||
|
|
||||||
|
val ip_mem_resp_abort = io.mem.xact_abort.valid && io.mem.xact_abort.bits.tile_xact_id(0)
|
||||||
val demand_miss = io.icache.xact_init.valid && io.icache.xact_init.ready
|
val demand_miss = io.icache.xact_init.valid && io.icache.xact_init.ready
|
||||||
val prefetch_addr = Reg() { UFix(width = io.icache.xact_init.bits.address.width) };
|
val prefetch_addr = Reg() { UFix(width = io.icache.xact_init.bits.address.width) };
|
||||||
val addr_match = (prefetch_addr === io.icache.xact_init.bits.address);
|
val addr_match = (prefetch_addr === io.icache.xact_init.bits.address);
|
||||||
val hit = (state != s_invalid) & (state != s_req_wait) & addr_match;
|
val hit = (state != s_invalid) && (state != s_req_wait) && addr_match && !ip_mem_resp_abort
|
||||||
val prefetch_miss = io.icache.xact_init.valid && !hit
|
val prefetch_miss = io.icache.xact_init.valid && !hit
|
||||||
when (demand_miss) { prefetch_addr := io.icache.xact_init.bits.address + UFix(1); }
|
when (demand_miss) { prefetch_addr := io.icache.xact_init.bits.address + UFix(1); }
|
||||||
|
|
||||||
io.icache.xact_init.ready := io.mem.xact_init.ready
|
io.icache.xact_init.ready := io.mem.xact_init.ready
|
||||||
val ip_mem_req_rdy = io.mem.xact_init.ready && !prefetch_miss
|
|
||||||
val ip_mem_resp_val = io.mem.xact_rep.valid && io.mem.xact_rep.bits.tile_xact_id(0)
|
val ip_mem_resp_val = io.mem.xact_rep.valid && io.mem.xact_rep.bits.tile_xact_id(0)
|
||||||
|
val ip_mem_req_rdy = io.mem.xact_init.ready && !prefetch_miss
|
||||||
|
|
||||||
|
io.mem.xact_abort.ready := Bool(true)
|
||||||
io.mem.xact_init.valid := prefetch_miss || (state === s_req_wait)
|
io.mem.xact_init.valid := prefetch_miss || (state === s_req_wait)
|
||||||
io.mem.xact_init.bits.t_type := X_INIT_READ_UNCACHED
|
io.mem.xact_init.bits.t_type := X_INIT_READ_UNCACHED
|
||||||
io.mem.xact_init.bits.tile_xact_id := Mux(prefetch_miss, UFix(0), UFix(1))
|
io.mem.xact_init.bits.tile_xact_id := Mux(prefetch_miss, UFix(0), UFix(1))
|
||||||
io.mem.xact_init.bits.address := Mux(prefetch_miss, io.icache.xact_init.bits.address, prefetch_addr);
|
io.mem.xact_init.bits.address := Mux(prefetch_miss, io.icache.xact_init.bits.address, prefetch_addr);
|
||||||
io.mem.xact_init_data.valid := Bool(false)
|
|
||||||
|
|
||||||
val fill_cnt = Reg(resetVal = UFix(0, ceil(log(REFILL_CYCLES)/log(2)).toInt));
|
val fill_cnt = Reg(resetVal = UFix(0, ceil(log(REFILL_CYCLES)/log(2)).toInt));
|
||||||
when (ip_mem_resp_val.toBool) { fill_cnt := fill_cnt + UFix(1); }
|
when (ip_mem_resp_val.toBool) { fill_cnt := fill_cnt + UFix(1); }
|
||||||
@ -43,8 +44,10 @@ class rocketIPrefetcher extends Component() {
|
|||||||
val forward_cnt = Reg(resetVal = UFix(0, ceil(log(REFILL_CYCLES)/log(2)).toInt));
|
val forward_cnt = Reg(resetVal = UFix(0, ceil(log(REFILL_CYCLES)/log(2)).toInt));
|
||||||
when (forward & pdq.io.deq.valid) { forward_cnt := forward_cnt + UFix(1); }
|
when (forward & pdq.io.deq.valid) { forward_cnt := forward_cnt + UFix(1); }
|
||||||
val forward_done = (~forward_cnt === UFix(0)) & pdq.io.deq.valid;
|
val forward_done = (~forward_cnt === UFix(0)) & pdq.io.deq.valid;
|
||||||
forward := (demand_miss & hit | forward & ~forward_done);
|
forward := demand_miss && hit || forward && !forward_done
|
||||||
|
|
||||||
|
io.icache.xact_abort.valid := io.mem.xact_abort.valid && !io.mem.xact_abort.bits.tile_xact_id(0) ||
|
||||||
|
forward && ip_mem_resp_abort
|
||||||
io.icache.xact_rep.valid := io.mem.xact_rep.valid && !io.mem.xact_rep.bits.tile_xact_id(0) || (forward && pdq.io.deq.valid)
|
io.icache.xact_rep.valid := io.mem.xact_rep.valid && !io.mem.xact_rep.bits.tile_xact_id(0) || (forward && pdq.io.deq.valid)
|
||||||
io.icache.xact_rep.bits.data := Mux(forward, pdq.io.deq.bits, io.mem.xact_rep.bits.data)
|
io.icache.xact_rep.bits.data := Mux(forward, pdq.io.deq.bits, io.mem.xact_rep.bits.data)
|
||||||
|
|
||||||
@ -69,11 +72,14 @@ class rocketIPrefetcher extends Component() {
|
|||||||
when (ip_mem_req_rdy) { state := s_resp_wait; }
|
when (ip_mem_req_rdy) { state := s_resp_wait; }
|
||||||
}
|
}
|
||||||
is (s_resp_wait) {
|
is (s_resp_wait) {
|
||||||
when (demand_miss & ~addr_match) { state := s_bad_resp_wait; }
|
when (ip_mem_resp_abort) {
|
||||||
.elsewhen (ip_mem_resp_val.toBool) { state := s_refilling; }
|
state := s_invalid
|
||||||
|
}
|
||||||
|
.elsewhen (demand_miss && !addr_match) { state := s_bad_resp_wait }
|
||||||
|
.elsewhen (ip_mem_resp_val) { state := s_refilling }
|
||||||
}
|
}
|
||||||
is (s_bad_resp_wait) {
|
is (s_bad_resp_wait) {
|
||||||
when (fill_done.toBool & ip_mem_resp_val.toBool) { state := s_req_wait; }
|
when (fill_done || ip_mem_resp_abort) { state := s_req_wait }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +178,7 @@ class MSHR(id: Int) extends Component with ThreeStateIncoherence {
|
|||||||
val way_oh = Bits(NWAYS, OUTPUT)
|
val way_oh = Bits(NWAYS, OUTPUT)
|
||||||
|
|
||||||
val mem_resp_val = Bool(INPUT)
|
val mem_resp_val = Bool(INPUT)
|
||||||
|
val mem_abort_val = Bool(INPUT)
|
||||||
val mem_req = (new ioDecoupled) { new TransactionInit }
|
val mem_req = (new ioDecoupled) { new TransactionInit }
|
||||||
val meta_req = (new ioDecoupled) { new MetaArrayArrayReq() }
|
val meta_req = (new ioDecoupled) { new MetaArrayArrayReq() }
|
||||||
val replay = (new ioDecoupled) { new Replay() }
|
val replay = (new ioDecoupled) { new Replay() }
|
||||||
@ -216,6 +217,9 @@ class MSHR(id: Int) extends Component with ThreeStateIncoherence {
|
|||||||
when (io.mem_req.valid && io.mem_req.ready) {
|
when (io.mem_req.valid && io.mem_req.ready) {
|
||||||
requested := Bool(true)
|
requested := Bool(true)
|
||||||
}
|
}
|
||||||
|
when (io.mem_abort_val) {
|
||||||
|
requested := Bool(false)
|
||||||
|
}
|
||||||
when (io.mem_resp_val) {
|
when (io.mem_resp_val) {
|
||||||
refilled := Bool(true)
|
refilled := Bool(true)
|
||||||
}
|
}
|
||||||
@ -264,6 +268,7 @@ class MSHRFile extends Component {
|
|||||||
val mem_req = (new ioDecoupled) { new TransactionInit }
|
val mem_req = (new ioDecoupled) { new TransactionInit }
|
||||||
val meta_req = (new ioDecoupled) { new MetaArrayArrayReq() }
|
val meta_req = (new ioDecoupled) { new MetaArrayArrayReq() }
|
||||||
val data_req = (new ioDecoupled) { new DataReq() }
|
val data_req = (new ioDecoupled) { new DataReq() }
|
||||||
|
val mem_abort = (new ioPipe) { new TransactionAbort }.flip
|
||||||
|
|
||||||
val cpu_resp_val = Bool(OUTPUT)
|
val cpu_resp_val = Bool(OUTPUT)
|
||||||
val cpu_resp_tag = Bits(DCACHE_TAG_BITS, OUTPUT)
|
val cpu_resp_tag = Bits(DCACHE_TAG_BITS, OUTPUT)
|
||||||
@ -310,8 +315,8 @@ class MSHRFile extends Component {
|
|||||||
mshr.io.mem_req <> mem_req_arb.io.in(i)
|
mshr.io.mem_req <> mem_req_arb.io.in(i)
|
||||||
mshr.io.replay <> replay_arb.io.in(i)
|
mshr.io.replay <> replay_arb.io.in(i)
|
||||||
|
|
||||||
val mem_resp_val = io.mem_resp_val && (UFix(i) === io.mem_resp_tag)
|
mshr.io.mem_resp_val := io.mem_resp_val && (UFix(i) === io.mem_resp_tag)
|
||||||
mshr.io.mem_resp_val := mem_resp_val
|
mshr.io.mem_abort_val := io.mem_abort.valid && (UFix(i) === io.mem_abort.bits.tile_xact_id)
|
||||||
mem_resp_idx_mux.io.sel(i) := (UFix(i) === io.mem_resp_tag)
|
mem_resp_idx_mux.io.sel(i) := (UFix(i) === io.mem_resp_tag)
|
||||||
mem_resp_idx_mux.io.in(i) := mshr.io.idx
|
mem_resp_idx_mux.io.in(i) := mshr.io.idx
|
||||||
mem_resp_way_oh_mux.io.sel(i) := (UFix(i) === io.mem_resp_tag)
|
mem_resp_way_oh_mux.io.sel(i) := (UFix(i) === io.mem_resp_tag)
|
||||||
@ -352,22 +357,55 @@ class WritebackUnit extends Component {
|
|||||||
val data_req = (new ioDecoupled) { new DataArrayArrayReq() }
|
val data_req = (new ioDecoupled) { new DataArrayArrayReq() }
|
||||||
val data_resp = Bits(MEM_DATA_BITS, INPUT)
|
val data_resp = Bits(MEM_DATA_BITS, INPUT)
|
||||||
val refill_req = (new ioDecoupled) { new TransactionInit }.flip
|
val refill_req = (new ioDecoupled) { new TransactionInit }.flip
|
||||||
val mem_req = (new ioDecoupled) { new TransactionInit }
|
val mem_req = (new ioDecoupled) { new TransactionInit }
|
||||||
val mem_req_data = (new ioDecoupled) { new TransactionInitData }
|
val mem_req_data = (new ioDecoupled) { new TransactionInitData }
|
||||||
|
val mem_abort = (new ioPipe) { new TransactionAbort }.flip
|
||||||
|
val mem_rep = (new ioPipe) { new TransactionReply }.flip
|
||||||
}
|
}
|
||||||
|
|
||||||
val valid = Reg(resetVal = Bool(false))
|
val valid = Reg(resetVal = Bool(false))
|
||||||
val data_req_fired = Reg(resetVal = Bool(false))
|
val data_req_fired = Reg(resetVal = Bool(false))
|
||||||
|
val cmd_sent = Reg() { Bool() }
|
||||||
val cnt = Reg() { UFix(width = log2up(REFILL_CYCLES+1)) }
|
val cnt = Reg() { UFix(width = log2up(REFILL_CYCLES+1)) }
|
||||||
val addr = Reg() { new WritebackReq() }
|
val addr = Reg() { new WritebackReq() }
|
||||||
|
|
||||||
data_req_fired := Bool(false)
|
val acked = Reg() { Bool() }
|
||||||
when (io.data_req.valid && io.data_req.ready) { data_req_fired := Bool(true); cnt := cnt + UFix(1) }
|
val nacked = Reg() { Bool() }
|
||||||
when (data_req_fired && !io.mem_req_data.ready) { data_req_fired := Bool(false); cnt := cnt - UFix(1) }
|
when (io.mem_rep.valid && io.mem_rep.bits.tile_xact_id === UFix(NMSHR)) { acked := Bool(true) }
|
||||||
when ((cnt === UFix(REFILL_CYCLES)) && io.mem_req_data.ready) { valid := Bool(false) }
|
when (io.mem_abort.valid && io.mem_abort.bits.tile_xact_id === UFix(NMSHR)) { nacked := Bool(true) }
|
||||||
when (io.req.valid && io.req.ready) { valid := Bool(true); cnt := UFix(0); addr := io.req.bits }
|
|
||||||
|
|
||||||
io.req.ready := !valid && io.mem_req.ready
|
data_req_fired := Bool(false)
|
||||||
|
when (valid && io.mem_req.ready) {
|
||||||
|
cmd_sent := Bool(true)
|
||||||
|
}
|
||||||
|
when (io.data_req.valid && io.data_req.ready) {
|
||||||
|
data_req_fired := Bool(true)
|
||||||
|
cnt := cnt + UFix(1)
|
||||||
|
}
|
||||||
|
when (data_req_fired && !io.mem_req_data.ready) {
|
||||||
|
data_req_fired := Bool(false)
|
||||||
|
cnt := cnt - UFix(1)
|
||||||
|
}
|
||||||
|
when ((cnt === UFix(REFILL_CYCLES)) && (!data_req_fired || io.mem_req_data.ready)) {
|
||||||
|
when (acked) {
|
||||||
|
valid := Bool(false)
|
||||||
|
}
|
||||||
|
when (nacked) {
|
||||||
|
cmd_sent := Bool(false)
|
||||||
|
nacked := Bool(false)
|
||||||
|
cnt := UFix(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when (io.req.valid && io.req.ready) {
|
||||||
|
valid := Bool(true)
|
||||||
|
acked := Bool(false)
|
||||||
|
nacked := Bool(false)
|
||||||
|
cmd_sent := Bool(false)
|
||||||
|
cnt := UFix(0)
|
||||||
|
addr := io.req.bits
|
||||||
|
}
|
||||||
|
|
||||||
|
io.req.ready := !valid
|
||||||
io.data_req.valid := valid && (cnt < UFix(REFILL_CYCLES))
|
io.data_req.valid := valid && (cnt < UFix(REFILL_CYCLES))
|
||||||
io.data_req.bits.way_en := addr.way_oh
|
io.data_req.bits.way_en := addr.way_oh
|
||||||
io.data_req.bits.inner_req.idx := addr.idx
|
io.data_req.bits.inner_req.idx := addr.idx
|
||||||
@ -376,11 +414,12 @@ class WritebackUnit extends Component {
|
|||||||
io.data_req.bits.inner_req.wmask := Bits(0)
|
io.data_req.bits.inner_req.wmask := Bits(0)
|
||||||
io.data_req.bits.inner_req.data := Bits(0)
|
io.data_req.bits.inner_req.data := Bits(0)
|
||||||
|
|
||||||
val wb_req_val = io.req.valid && !valid
|
val wb_req_val = valid && !cmd_sent
|
||||||
io.refill_req.ready := io.mem_req.ready && !wb_req_val
|
io.refill_req.ready := io.mem_req.ready && !(valid && !acked)
|
||||||
io.mem_req.valid := io.refill_req.valid || wb_req_val
|
io.mem_req.valid := io.refill_req.valid && !(valid && !acked) || wb_req_val
|
||||||
io.mem_req.bits.t_type := Mux(wb_req_val, X_INIT_WRITE_UNCACHED, io.refill_req.bits.t_type)
|
io.mem_req.bits.t_type := Mux(wb_req_val, X_INIT_WRITE_UNCACHED, io.refill_req.bits.t_type)
|
||||||
io.mem_req.bits.address := Mux(wb_req_val, Cat(io.req.bits.ppn, io.req.bits.idx).toUFix, io.refill_req.bits.address)
|
io.mem_req.bits.has_data := wb_req_val
|
||||||
|
io.mem_req.bits.address := Mux(wb_req_val, Cat(addr.ppn, addr.idx).toUFix, io.refill_req.bits.address)
|
||||||
io.mem_req.bits.tile_xact_id := Mux(wb_req_val, Bits(NMSHR), io.refill_req.bits.tile_xact_id)
|
io.mem_req.bits.tile_xact_id := Mux(wb_req_val, Bits(NMSHR), io.refill_req.bits.tile_xact_id)
|
||||||
|
|
||||||
io.mem_req_data.valid := data_req_fired
|
io.mem_req_data.valid := data_req_fired
|
||||||
@ -676,8 +715,12 @@ class HellaCacheUniproc extends HellaCache with ThreeStateIncoherence {
|
|||||||
val cpu_req_data = Mux(r_replay_amo, r_amo_replay_data, io.cpu.req_data)
|
val cpu_req_data = Mux(r_replay_amo, r_amo_replay_data, io.cpu.req_data)
|
||||||
|
|
||||||
// refill counter
|
// refill counter
|
||||||
|
<<<<<<< HEAD
|
||||||
val mem_resp_type = io.mem.xact_rep.bits.t_type
|
val mem_resp_type = io.mem.xact_rep.bits.t_type
|
||||||
val refill_val = io.mem.xact_rep.valid && (mem_resp_type === X_REP_READ_SHARED || mem_resp_type === X_REP_READ_EXCLUSIVE)
|
val refill_val = io.mem.xact_rep.valid && (mem_resp_type === X_REP_READ_SHARED || mem_resp_type === X_REP_READ_EXCLUSIVE)
|
||||||
|
=======
|
||||||
|
val refill_val = io.mem.xact_rep.valid && io.mem.xact_rep.bits.tile_xact_id < UFix(NMSHR)
|
||||||
|
>>>>>>> support memory transaction aborts
|
||||||
val rr_count = Reg(resetVal = UFix(0, log2up(REFILL_CYCLES)))
|
val rr_count = Reg(resetVal = UFix(0, log2up(REFILL_CYCLES)))
|
||||||
val rr_count_next = rr_count + UFix(1)
|
val rr_count_next = rr_count + UFix(1)
|
||||||
when (refill_val) { rr_count := rr_count_next }
|
when (refill_val) { rr_count := rr_count_next }
|
||||||
@ -725,6 +768,9 @@ class HellaCacheUniproc extends HellaCache with ThreeStateIncoherence {
|
|||||||
wb_arb.io.out <> wb.io.req
|
wb_arb.io.out <> wb.io.req
|
||||||
wb.io.data_req <> data_arb.io.in(3)
|
wb.io.data_req <> data_arb.io.in(3)
|
||||||
wb.io.data_resp <> data_resp_mux
|
wb.io.data_resp <> data_resp_mux
|
||||||
|
wb.io.mem_rep <> io.mem.xact_rep
|
||||||
|
wb.io.mem_abort.valid := io.mem.xact_abort.valid
|
||||||
|
wb.io.mem_abort.bits := io.mem.xact_abort.bits
|
||||||
|
|
||||||
// replacement policy
|
// replacement policy
|
||||||
val replacer = new RandomReplacementWayGen()
|
val replacer = new RandomReplacementWayGen()
|
||||||
@ -737,9 +783,11 @@ class HellaCacheUniproc extends HellaCache with ThreeStateIncoherence {
|
|||||||
// refill response
|
// refill response
|
||||||
val block_during_refill = !refill_val && (rr_count != UFix(0))
|
val block_during_refill = !refill_val && (rr_count != UFix(0))
|
||||||
data_arb.io.in(0).bits.inner_req.offset := rr_count
|
data_arb.io.in(0).bits.inner_req.offset := rr_count
|
||||||
|
data_arb.io.in(0).bits.inner_req.idx := mshr.io.mem_resp_idx
|
||||||
data_arb.io.in(0).bits.inner_req.rw := !block_during_refill
|
data_arb.io.in(0).bits.inner_req.rw := !block_during_refill
|
||||||
data_arb.io.in(0).bits.inner_req.wmask := ~UFix(0, MEM_DATA_BITS/8)
|
data_arb.io.in(0).bits.inner_req.wmask := ~UFix(0, MEM_DATA_BITS/8)
|
||||||
data_arb.io.in(0).bits.inner_req.data := io.mem.xact_rep.bits.data
|
data_arb.io.in(0).bits.inner_req.data := io.mem.xact_rep.bits.data
|
||||||
|
data_arb.io.in(0).bits.way_en := mshr.io.mem_resp_way_oh
|
||||||
data_arb.io.in(0).valid := refill_val || block_during_refill
|
data_arb.io.in(0).valid := refill_val || block_during_refill
|
||||||
|
|
||||||
// load hits
|
// load hits
|
||||||
@ -815,10 +863,10 @@ class HellaCacheUniproc extends HellaCache with ThreeStateIncoherence {
|
|||||||
|
|
||||||
mshr.io.mem_resp_val := refill_val && (~rr_count === UFix(0))
|
mshr.io.mem_resp_val := refill_val && (~rr_count === UFix(0))
|
||||||
mshr.io.mem_resp_tag := io.mem.xact_rep.bits.tile_xact_id
|
mshr.io.mem_resp_tag := io.mem.xact_rep.bits.tile_xact_id
|
||||||
|
mshr.io.mem_abort.valid := io.mem.xact_abort.valid
|
||||||
|
mshr.io.mem_abort.bits := io.mem.xact_abort.bits
|
||||||
mshr.io.mem_req <> wb.io.refill_req
|
mshr.io.mem_req <> wb.io.refill_req
|
||||||
mshr.io.meta_req <> meta_arb.io.in(1)
|
mshr.io.meta_req <> meta_arb.io.in(1)
|
||||||
data_arb.io.in(0).bits.inner_req.idx := mshr.io.mem_resp_idx
|
|
||||||
data_arb.io.in(0).bits.way_en := mshr.io.mem_resp_way_oh
|
|
||||||
replacer.io.pick_new_way := mshr.io.req.valid && mshr.io.req.ready
|
replacer.io.pick_new_way := mshr.io.req.valid && mshr.io.req.ready
|
||||||
|
|
||||||
// replays
|
// replays
|
||||||
|
@ -29,13 +29,18 @@ class Top() extends Component {
|
|||||||
val hub = new CoherenceHubNull
|
val hub = new CoherenceHubNull
|
||||||
// connect tile to hub
|
// connect tile to hub
|
||||||
hub.io.tiles(0).xact_init <> Queue(arbiter.io.mem.xact_init)
|
hub.io.tiles(0).xact_init <> Queue(arbiter.io.mem.xact_init)
|
||||||
hub.io.tiles(0).xact_init_data <> Queue(arbiter.io.mem.xact_init_data)
|
arbiter.io.mem.xact_abort <> Queue(hub.io.tiles(0).xact_abort)
|
||||||
arbiter.io.mem.xact_rep <> Pipe(hub.io.tiles(0).xact_rep)
|
arbiter.io.mem.xact_rep <> Pipe(hub.io.tiles(0).xact_rep)
|
||||||
// connect hub to memory
|
// connect hub to memory
|
||||||
io.mem.req_cmd <> Queue(hub.io.mem.req_cmd)
|
io.mem.req_cmd <> Queue(hub.io.mem.req_cmd)
|
||||||
io.mem.req_data <> Queue(hub.io.mem.req_data)
|
io.mem.req_data <> Queue(hub.io.mem.req_data)
|
||||||
hub.io.mem.resp <> Pipe(io.mem.resp)
|
hub.io.mem.resp <> Pipe(io.mem.resp)
|
||||||
|
|
||||||
|
// temporary HTIF data connection
|
||||||
|
val data_arb = (new Arbiter(2)) { new TransactionInitData }
|
||||||
|
data_arb.io.in(0) <> Queue(dcache.io.mem.xact_init_data)
|
||||||
|
data_arb.io.in(1) <> Queue(htif.io.mem.xact_init_data)
|
||||||
|
hub.io.tiles(0).xact_init_data <> data_arb.io.out
|
||||||
|
|
||||||
if (HAVE_VEC)
|
if (HAVE_VEC)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user