support memory transaction aborts
This commit is contained in:
		| @@ -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)  { | ||||||
|  |       state := state_mem_wresp | ||||||
|  |     } | ||||||
|  |     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)  { |       when (mem_cnt.andR)  { | ||||||
|         state := state_tx |         state := state_tx | ||||||
|       } |       } | ||||||
|       mem_cnt := mem_cnt + UFix(1) |       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) | ||||||
| @@ -354,20 +359,53 @@ class WritebackUnit extends Component { | |||||||
|     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) | ||||||
|   { |   { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user