update to new chisel
This commit is contained in:
parent
f8b937d590
commit
725190d0ee
@ -339,17 +339,17 @@ class rocketCtrl extends Component
|
||||
|
||||
when (!io.dpath.stalld) {
|
||||
when (io.dpath.killf) {
|
||||
id_reg_btb_hit <== Bool(false);
|
||||
id_reg_xcpt_ma_inst <== Bool(false);
|
||||
id_reg_xcpt_itlb <== Bool(false);
|
||||
id_reg_btb_hit := Bool(false);
|
||||
id_reg_xcpt_ma_inst := Bool(false);
|
||||
id_reg_xcpt_itlb := Bool(false);
|
||||
}
|
||||
otherwise{
|
||||
id_reg_btb_hit <== io.dpath.btb_hit;
|
||||
id_reg_xcpt_ma_inst <== if_reg_xcpt_ma_inst;
|
||||
id_reg_xcpt_itlb <== io.xcpt_itlb;
|
||||
.otherwise{
|
||||
id_reg_btb_hit := io.dpath.btb_hit;
|
||||
id_reg_xcpt_ma_inst := if_reg_xcpt_ma_inst;
|
||||
id_reg_xcpt_itlb := io.xcpt_itlb;
|
||||
}
|
||||
id_reg_icmiss <== !io.imem.resp_val;
|
||||
id_reg_replay <== !take_pc && !io.imem.resp_val;
|
||||
id_reg_icmiss := !io.imem.resp_val;
|
||||
id_reg_replay := !take_pc && !io.imem.resp_val;
|
||||
}
|
||||
|
||||
// executing ERET when traps are enabled causes an illegal instruction exception (as per ISA sim)
|
||||
@ -358,54 +358,54 @@ class rocketCtrl extends Component
|
||||
(id_eret.toBool && io.dpath.status(SR_ET).toBool);
|
||||
|
||||
when (reset.toBool || io.dpath.killd) {
|
||||
ex_reg_br_type <== BR_N;
|
||||
ex_reg_btb_hit <== Bool(false);
|
||||
ex_reg_div_val <== Bool(false);
|
||||
ex_reg_mul_val <== Bool(false);
|
||||
ex_reg_mem_val <== Bool(false);
|
||||
ex_reg_wen <== Bool(false);
|
||||
ex_reg_fp_wen <== Bool(false);
|
||||
ex_reg_eret <== Bool(false);
|
||||
ex_reg_replay_next <== Bool(false);
|
||||
ex_reg_inst_di <== Bool(false);
|
||||
ex_reg_inst_ei <== Bool(false);
|
||||
ex_reg_flush_inst <== Bool(false);
|
||||
ex_reg_xcpt_ma_inst <== Bool(false);
|
||||
ex_reg_xcpt_itlb <== Bool(false);
|
||||
ex_reg_xcpt_illegal <== Bool(false);
|
||||
ex_reg_xcpt_privileged <== Bool(false);
|
||||
ex_reg_xcpt_syscall <== Bool(false);
|
||||
ex_reg_fp_val <== Bool(false);
|
||||
ex_reg_vec_val <== Bool(false);
|
||||
ex_reg_replay <== Bool(false);
|
||||
ex_reg_load_use <== Bool(false);
|
||||
ex_reg_br_type := BR_N;
|
||||
ex_reg_btb_hit := Bool(false);
|
||||
ex_reg_div_val := Bool(false);
|
||||
ex_reg_mul_val := Bool(false);
|
||||
ex_reg_mem_val := Bool(false);
|
||||
ex_reg_wen := Bool(false);
|
||||
ex_reg_fp_wen := Bool(false);
|
||||
ex_reg_eret := Bool(false);
|
||||
ex_reg_replay_next := Bool(false);
|
||||
ex_reg_inst_di := Bool(false);
|
||||
ex_reg_inst_ei := Bool(false);
|
||||
ex_reg_flush_inst := Bool(false);
|
||||
ex_reg_xcpt_ma_inst := Bool(false);
|
||||
ex_reg_xcpt_itlb := Bool(false);
|
||||
ex_reg_xcpt_illegal := Bool(false);
|
||||
ex_reg_xcpt_privileged := Bool(false);
|
||||
ex_reg_xcpt_syscall := Bool(false);
|
||||
ex_reg_fp_val := Bool(false);
|
||||
ex_reg_vec_val := Bool(false);
|
||||
ex_reg_replay := Bool(false);
|
||||
ex_reg_load_use := Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
ex_reg_br_type <== id_br_type;
|
||||
ex_reg_btb_hit <== id_reg_btb_hit;
|
||||
ex_reg_div_val <== id_div_val.toBool && id_waddr != UFix(0);
|
||||
ex_reg_mul_val <== id_mul_val.toBool && id_waddr != UFix(0);
|
||||
ex_reg_mem_val <== id_mem_val.toBool;
|
||||
ex_reg_wen <== id_wen.toBool && id_waddr != UFix(0);
|
||||
ex_reg_fp_wen <== fpdec.io.wen;
|
||||
ex_reg_eret <== id_eret.toBool;
|
||||
ex_reg_replay_next <== id_replay_next.toBool;
|
||||
ex_reg_inst_di <== (id_irq === I_DI);
|
||||
ex_reg_inst_ei <== (id_irq === I_EI);
|
||||
ex_reg_flush_inst <== (id_sync === SYNC_I);
|
||||
ex_reg_xcpt_ma_inst <== id_reg_xcpt_ma_inst;
|
||||
ex_reg_xcpt_itlb <== id_reg_xcpt_itlb;
|
||||
ex_reg_xcpt_illegal <== illegal_inst;
|
||||
ex_reg_xcpt_privileged <== (id_privileged & ~io.dpath.status(SR_S)).toBool;
|
||||
ex_reg_xcpt_syscall <== id_syscall.toBool;
|
||||
ex_reg_fp_val <== fpdec.io.valid;
|
||||
ex_reg_vec_val <== id_vec_val.toBool
|
||||
ex_reg_replay <== id_reg_replay || ex_reg_replay_next;
|
||||
ex_reg_load_use <== id_load_use;
|
||||
.otherwise {
|
||||
ex_reg_br_type := id_br_type;
|
||||
ex_reg_btb_hit := id_reg_btb_hit;
|
||||
ex_reg_div_val := id_div_val.toBool && id_waddr != UFix(0);
|
||||
ex_reg_mul_val := id_mul_val.toBool && id_waddr != UFix(0);
|
||||
ex_reg_mem_val := id_mem_val.toBool;
|
||||
ex_reg_wen := id_wen.toBool && id_waddr != UFix(0);
|
||||
ex_reg_fp_wen := fpdec.io.wen;
|
||||
ex_reg_eret := id_eret.toBool;
|
||||
ex_reg_replay_next := id_replay_next.toBool;
|
||||
ex_reg_inst_di := (id_irq === I_DI);
|
||||
ex_reg_inst_ei := (id_irq === I_EI);
|
||||
ex_reg_flush_inst := (id_sync === SYNC_I);
|
||||
ex_reg_xcpt_ma_inst := id_reg_xcpt_ma_inst;
|
||||
ex_reg_xcpt_itlb := id_reg_xcpt_itlb;
|
||||
ex_reg_xcpt_illegal := illegal_inst;
|
||||
ex_reg_xcpt_privileged := (id_privileged & ~io.dpath.status(SR_S)).toBool;
|
||||
ex_reg_xcpt_syscall := id_syscall.toBool;
|
||||
ex_reg_fp_val := fpdec.io.valid;
|
||||
ex_reg_vec_val := id_vec_val.toBool
|
||||
ex_reg_replay := id_reg_replay || ex_reg_replay_next;
|
||||
ex_reg_load_use := id_load_use;
|
||||
}
|
||||
ex_reg_ext_mem_val <== io.ext_mem.req_val
|
||||
ex_reg_mem_cmd <== Mux(io.ext_mem.req_val, io.ext_mem.req_cmd, id_mem_cmd).toUFix
|
||||
ex_reg_mem_type <== Mux(io.ext_mem.req_val, io.ext_mem.req_type, id_mem_type).toUFix
|
||||
ex_reg_ext_mem_val := io.ext_mem.req_val
|
||||
ex_reg_mem_cmd := Mux(io.ext_mem.req_val, io.ext_mem.req_cmd, id_mem_cmd).toUFix
|
||||
ex_reg_mem_type := Mux(io.ext_mem.req_val, io.ext_mem.req_type, id_mem_type).toUFix
|
||||
|
||||
val beq = io.dpath.br_eq;
|
||||
val bne = ~io.dpath.br_eq;
|
||||
@ -431,60 +431,60 @@ class rocketCtrl extends Component
|
||||
val mem_reg_mem_type = Reg(){UFix(width = 3)};
|
||||
|
||||
when (reset.toBool || io.dpath.killx) {
|
||||
mem_reg_div_mul_val <== Bool(false);
|
||||
mem_reg_wen <== Bool(false);
|
||||
mem_reg_fp_wen <== Bool(false);
|
||||
mem_reg_eret <== Bool(false);
|
||||
mem_reg_mem_val <== Bool(false);
|
||||
mem_reg_inst_di <== Bool(false);
|
||||
mem_reg_inst_ei <== Bool(false);
|
||||
mem_reg_flush_inst <== Bool(false);
|
||||
mem_reg_xcpt_ma_inst <== Bool(false);
|
||||
mem_reg_xcpt_itlb <== Bool(false);
|
||||
mem_reg_xcpt_illegal <== Bool(false);
|
||||
mem_reg_xcpt_privileged <== Bool(false);
|
||||
mem_reg_xcpt_fpu <== Bool(false);
|
||||
mem_reg_xcpt_vec <== Bool(false);
|
||||
mem_reg_xcpt_syscall <== Bool(false);
|
||||
mem_reg_div_mul_val := Bool(false);
|
||||
mem_reg_wen := Bool(false);
|
||||
mem_reg_fp_wen := Bool(false);
|
||||
mem_reg_eret := Bool(false);
|
||||
mem_reg_mem_val := Bool(false);
|
||||
mem_reg_inst_di := Bool(false);
|
||||
mem_reg_inst_ei := Bool(false);
|
||||
mem_reg_flush_inst := Bool(false);
|
||||
mem_reg_xcpt_ma_inst := Bool(false);
|
||||
mem_reg_xcpt_itlb := Bool(false);
|
||||
mem_reg_xcpt_illegal := Bool(false);
|
||||
mem_reg_xcpt_privileged := Bool(false);
|
||||
mem_reg_xcpt_fpu := Bool(false);
|
||||
mem_reg_xcpt_vec := Bool(false);
|
||||
mem_reg_xcpt_syscall := Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
mem_reg_div_mul_val <== ex_reg_div_val || ex_reg_mul_val;
|
||||
mem_reg_wen <== ex_reg_wen;
|
||||
mem_reg_fp_wen <== ex_reg_fp_wen;
|
||||
mem_reg_eret <== ex_reg_eret;
|
||||
mem_reg_mem_val <== ex_reg_mem_val;
|
||||
mem_reg_inst_di <== ex_reg_inst_di;
|
||||
mem_reg_inst_ei <== ex_reg_inst_ei;
|
||||
mem_reg_flush_inst <== ex_reg_flush_inst;
|
||||
mem_reg_xcpt_ma_inst <== ex_reg_xcpt_ma_inst;
|
||||
mem_reg_xcpt_itlb <== ex_reg_xcpt_itlb;
|
||||
mem_reg_xcpt_illegal <== ex_reg_xcpt_illegal;
|
||||
mem_reg_xcpt_privileged <== ex_reg_xcpt_privileged;
|
||||
mem_reg_xcpt_fpu <== ex_reg_fp_val && !io.dpath.status(SR_EF).toBool;
|
||||
mem_reg_xcpt_vec <== ex_reg_vec_val && !io.dpath.status(SR_EV).toBool;
|
||||
mem_reg_xcpt_syscall <== ex_reg_xcpt_syscall;
|
||||
.otherwise {
|
||||
mem_reg_div_mul_val := ex_reg_div_val || ex_reg_mul_val;
|
||||
mem_reg_wen := ex_reg_wen;
|
||||
mem_reg_fp_wen := ex_reg_fp_wen;
|
||||
mem_reg_eret := ex_reg_eret;
|
||||
mem_reg_mem_val := ex_reg_mem_val;
|
||||
mem_reg_inst_di := ex_reg_inst_di;
|
||||
mem_reg_inst_ei := ex_reg_inst_ei;
|
||||
mem_reg_flush_inst := ex_reg_flush_inst;
|
||||
mem_reg_xcpt_ma_inst := ex_reg_xcpt_ma_inst;
|
||||
mem_reg_xcpt_itlb := ex_reg_xcpt_itlb;
|
||||
mem_reg_xcpt_illegal := ex_reg_xcpt_illegal;
|
||||
mem_reg_xcpt_privileged := ex_reg_xcpt_privileged;
|
||||
mem_reg_xcpt_fpu := ex_reg_fp_val && !io.dpath.status(SR_EF).toBool;
|
||||
mem_reg_xcpt_vec := ex_reg_vec_val && !io.dpath.status(SR_EV).toBool;
|
||||
mem_reg_xcpt_syscall := ex_reg_xcpt_syscall;
|
||||
}
|
||||
mem_reg_ext_mem_val <== ex_reg_ext_mem_val;
|
||||
mem_reg_mem_cmd <== ex_reg_mem_cmd;
|
||||
mem_reg_mem_type <== ex_reg_mem_type;
|
||||
mem_reg_ext_mem_val := ex_reg_ext_mem_val;
|
||||
mem_reg_mem_cmd := ex_reg_mem_cmd;
|
||||
mem_reg_mem_type := ex_reg_mem_type;
|
||||
|
||||
when (io.dpath.killm) {
|
||||
wb_reg_wen <== Bool(false);
|
||||
wb_reg_fp_wen <== Bool(false);
|
||||
wb_reg_eret <== Bool(false);
|
||||
wb_reg_inst_di <== Bool(false);
|
||||
wb_reg_inst_ei <== Bool(false);
|
||||
wb_reg_flush_inst <== Bool(false);
|
||||
wb_reg_div_mul_val <== Bool(false);
|
||||
wb_reg_wen := Bool(false);
|
||||
wb_reg_fp_wen := Bool(false);
|
||||
wb_reg_eret := Bool(false);
|
||||
wb_reg_inst_di := Bool(false);
|
||||
wb_reg_inst_ei := Bool(false);
|
||||
wb_reg_flush_inst := Bool(false);
|
||||
wb_reg_div_mul_val := Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
wb_reg_wen <== mem_reg_wen;
|
||||
wb_reg_fp_wen <== mem_reg_fp_wen;
|
||||
wb_reg_eret <== mem_reg_eret;
|
||||
wb_reg_inst_di <== mem_reg_inst_di;
|
||||
wb_reg_inst_ei <== mem_reg_inst_ei;
|
||||
wb_reg_flush_inst <== mem_reg_flush_inst;
|
||||
wb_reg_div_mul_val <== mem_reg_div_mul_val;
|
||||
.otherwise {
|
||||
wb_reg_wen := mem_reg_wen;
|
||||
wb_reg_fp_wen := mem_reg_fp_wen;
|
||||
wb_reg_eret := mem_reg_eret;
|
||||
wb_reg_inst_di := mem_reg_inst_di;
|
||||
wb_reg_inst_ei := mem_reg_inst_ei;
|
||||
wb_reg_flush_inst := mem_reg_flush_inst;
|
||||
wb_reg_div_mul_val := mem_reg_div_mul_val;
|
||||
}
|
||||
|
||||
val sboard = new rocketCtrlSboard();
|
||||
@ -591,12 +591,12 @@ class rocketCtrl extends Component
|
||||
ex_reg_mul_val && !io.dpath.mul_rdy
|
||||
val kill_ex = take_pc_wb || replay_ex
|
||||
|
||||
mem_reg_replay <== replay_ex && !take_pc_wb;
|
||||
mem_reg_kill <== kill_ex;
|
||||
mem_reg_replay := replay_ex && !take_pc_wb;
|
||||
mem_reg_kill := kill_ex;
|
||||
|
||||
wb_reg_replay <== replay_mem && !take_pc_wb;
|
||||
wb_reg_exception <== mem_exception && !take_pc_wb;
|
||||
wb_reg_cause <== mem_cause;
|
||||
wb_reg_replay := replay_mem && !take_pc_wb;
|
||||
wb_reg_exception := mem_exception && !take_pc_wb;
|
||||
wb_reg_cause := mem_cause;
|
||||
|
||||
val wb_badvaddr_wen = wb_reg_exception && ((wb_reg_cause === UFix(10)) || (wb_reg_cause === UFix(11)))
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
package Top
|
||||
{
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
@ -23,38 +23,14 @@ class ioCtrlSboard extends Bundle()
|
||||
class rocketCtrlSboard extends Component
|
||||
{
|
||||
override val io = new ioCtrlSboard();
|
||||
val reg_busy = Reg(width = 32, resetVal = Bits(0, 32));
|
||||
val reg_busy = Reg(resetVal = Bits(0, 32));
|
||||
|
||||
val set_mask = io.set.toUFix << io.seta;
|
||||
val clr_mask = ~(io.clr.toUFix << io.clra);
|
||||
reg_busy <== (reg_busy | set_mask) & clr_mask
|
||||
reg_busy := (reg_busy | set_mask) & clr_mask
|
||||
|
||||
io.stalla := reg_busy(io.raddra).toBool;
|
||||
io.stallb := reg_busy(io.raddrb).toBool;
|
||||
io.stallc := reg_busy(io.raddrc).toBool;
|
||||
io.stalld := reg_busy(io.raddrd).toBool;
|
||||
}
|
||||
|
||||
class ioCtrlCnt extends Bundle()
|
||||
{
|
||||
val enq = Bool(INPUT);
|
||||
val deq = Bool(INPUT);
|
||||
val empty = Bool(OUTPUT);
|
||||
val full = Bool(OUTPUT);
|
||||
}
|
||||
|
||||
class rocketCtrlCnt(n_bits: Int, limit: Int) extends Component
|
||||
{
|
||||
override val io = new ioCtrlCnt();
|
||||
val counter = Reg(width = n_bits, resetVal = UFix(0, n_bits));
|
||||
when (io.enq && !io.deq) {
|
||||
counter <== counter + UFix(1, n_bits);
|
||||
}
|
||||
when (!io.enq && io.deq) {
|
||||
counter <== counter - UFix(1, n_bits);
|
||||
}
|
||||
io.empty := counter === UFix(0, n_bits);
|
||||
io.full := counter === UFix(limit, n_bits);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -137,23 +137,23 @@ class rocketDCacheDM_flush(lines: Int) extends Component {
|
||||
|
||||
when (io.cpu.req_val && io.cpu.req_rdy && (io.cpu.req_cmd === M_FLA))
|
||||
{
|
||||
r_cpu_req_tag <== io.cpu.req_tag;
|
||||
flushing <== Bool(true);
|
||||
flush_waiting <== Bool(true);
|
||||
r_cpu_req_tag := io.cpu.req_tag;
|
||||
flushing := Bool(true);
|
||||
flush_waiting := Bool(true);
|
||||
}
|
||||
|
||||
when (dcache.io.cpu.req_rdy && (flush_count === ~Bits(0, indexbits))) {
|
||||
flushing <== Bool(false);
|
||||
flushing := Bool(false);
|
||||
}
|
||||
when (dcache.io.cpu.resp_val && (dcache.io.cpu.resp_tag === r_cpu_req_tag) && (flush_resp_count === ~Bits(0, indexbits))) {
|
||||
flush_waiting <== Bool(false);
|
||||
flush_waiting := Bool(false);
|
||||
}
|
||||
|
||||
when (flushing && dcache.io.cpu.req_rdy) {
|
||||
flush_count <== flush_count + UFix(1,1);
|
||||
flush_count := flush_count + UFix(1,1);
|
||||
}
|
||||
when (flush_waiting && dcache.io.cpu.resp_val && (dcache.io.cpu.resp_tag === r_cpu_req_tag)) {
|
||||
flush_resp_count <== flush_resp_count + UFix(1,1);
|
||||
flush_resp_count := flush_resp_count + UFix(1,1);
|
||||
}
|
||||
|
||||
dcache.io.cpu.req_val := (io.cpu.req_val && (io.cpu.req_cmd != M_FLA) && !flush_waiting) || flushing;
|
||||
@ -220,33 +220,33 @@ class rocketDCacheDM(lines: Int) extends Component {
|
||||
val r_req_amo = r_cpu_req_cmd(3).toBool;
|
||||
|
||||
when (io.cpu.req_val && io.cpu.req_rdy) {
|
||||
r_cpu_req_idx <== io.cpu.req_idx;
|
||||
r_cpu_req_cmd <== io.cpu.req_cmd;
|
||||
r_cpu_req_type <== io.cpu.req_type;
|
||||
r_cpu_req_tag <== io.cpu.req_tag;
|
||||
r_cpu_req_idx := io.cpu.req_idx;
|
||||
r_cpu_req_cmd := io.cpu.req_cmd;
|
||||
r_cpu_req_type := io.cpu.req_type;
|
||||
r_cpu_req_tag := io.cpu.req_tag;
|
||||
}
|
||||
|
||||
when ((state === s_ready) && r_cpu_req_val && !io.cpu.req_kill) {
|
||||
r_cpu_req_ppn <== io.cpu.req_ppn;
|
||||
r_cpu_req_ppn := io.cpu.req_ppn;
|
||||
}
|
||||
when (io.cpu.req_rdy) {
|
||||
r_cpu_req_val <== io.cpu.req_val;
|
||||
r_cpu_req_val := io.cpu.req_val;
|
||||
}
|
||||
otherwise {
|
||||
r_cpu_req_val <== Bool(false);
|
||||
r_cpu_req_val := Bool(false);
|
||||
}
|
||||
when (((state === s_resolve_miss) && (r_req_load || r_req_amo)) || (state === s_replay_load)) {
|
||||
r_cpu_resp_val <== Bool(true);
|
||||
r_cpu_resp_val := Bool(true);
|
||||
}
|
||||
otherwise {
|
||||
r_cpu_resp_val <== Bool(false);
|
||||
r_cpu_resp_val := Bool(false);
|
||||
}
|
||||
|
||||
// refill counter
|
||||
val rr_count = Reg(resetVal = UFix(0,2));
|
||||
val rr_count_next = rr_count + UFix(1);
|
||||
when (((state === s_refill) && io.mem.resp_val) || ((state === s_writeback) && io.mem.req_rdy)) {
|
||||
rr_count <== rr_count_next;
|
||||
rr_count := rr_count_next;
|
||||
}
|
||||
|
||||
// tag array
|
||||
@ -257,7 +257,7 @@ class rocketDCacheDM(lines: Int) extends Component {
|
||||
((state === s_refill) && io.mem.resp_val && (rr_count === UFix(3,2))) ||
|
||||
((state === s_resolve_miss) && r_req_flush);
|
||||
|
||||
val tag_array = Mem4(lines, r_cpu_req_ppn);
|
||||
val tag_array = Mem(lines, r_cpu_req_ppn);
|
||||
tag_array.setReadLatency(1);
|
||||
tag_array.setTarget('inst);
|
||||
val tag_rdata = tag_array.rw(tag_addr, r_cpu_req_ppn, tag_we);
|
||||
@ -265,10 +265,10 @@ class rocketDCacheDM(lines: Int) extends Component {
|
||||
// valid bit array
|
||||
val vb_array = Reg(resetVal = Bits(0, lines));
|
||||
when (tag_we && !r_req_flush) {
|
||||
vb_array <== vb_array.bitSet(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(1,1));
|
||||
vb_array := vb_array.bitSet(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(1,1));
|
||||
}
|
||||
when (tag_we && r_req_flush) {
|
||||
vb_array <== vb_array.bitSet(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(0,1));
|
||||
vb_array := vb_array.bitSet(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(0,1));
|
||||
}
|
||||
val vb_rdata = vb_array(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix).toBool;
|
||||
val tag_valid = r_cpu_req_val && vb_rdata;
|
||||
@ -294,33 +294,33 @@ class rocketDCacheDM(lines: Int) extends Component {
|
||||
|
||||
// pending store data
|
||||
when (io.cpu.req_val && io.cpu.req_rdy && req_store) {
|
||||
p_store_idx <== io.cpu.req_idx;
|
||||
p_store_data <== io.cpu.req_data;
|
||||
p_store_type <== io.cpu.req_type;
|
||||
p_store_idx := io.cpu.req_idx;
|
||||
p_store_data := io.cpu.req_data;
|
||||
p_store_type := io.cpu.req_type;
|
||||
}
|
||||
when (store_hit && !drain_store) {
|
||||
p_store_valid <== Bool(true);
|
||||
p_store_valid := Bool(true);
|
||||
}
|
||||
when (drain_store) {
|
||||
p_store_valid <== Bool(false);
|
||||
p_store_valid := Bool(false);
|
||||
}
|
||||
|
||||
// AMO operand
|
||||
when (io.cpu.req_val && io.cpu.req_rdy && req_amo) {
|
||||
r_amo_data <== io.cpu.req_data;
|
||||
r_amo_data := io.cpu.req_data;
|
||||
}
|
||||
|
||||
// dirty bit array
|
||||
val db_array = Reg(resetVal = Bits(0, lines));
|
||||
val tag_dirty = db_array(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix).toBool;
|
||||
when ((r_cpu_req_val && !io.cpu.req_kill && tag_hit && r_req_store) || resolve_store) {
|
||||
db_array <== db_array.bitSet(p_store_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(1,1));
|
||||
db_array := db_array.bitSet(p_store_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(1,1));
|
||||
}
|
||||
when (state === s_write_amo) {
|
||||
db_array <== db_array.bitSet(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(1,1));
|
||||
db_array := db_array.bitSet(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(1,1));
|
||||
}
|
||||
when (tag_we) {
|
||||
db_array <== db_array.bitSet(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(0,1));
|
||||
db_array := db_array.bitSet(r_cpu_req_idx(PGIDX_BITS-1,offsetbits).toUFix, UFix(0,1));
|
||||
}
|
||||
|
||||
// generate write mask and data signals for stores and amos
|
||||
@ -374,7 +374,7 @@ class rocketDCacheDM(lines: Int) extends Component {
|
||||
Mux((state === s_write_amo), amo_store_wmask,
|
||||
store_wmask));
|
||||
|
||||
val data_array = Mem4(lines*4, data_wdata);
|
||||
val data_array = Mem(lines*4, data_wdata);
|
||||
data_array.setReadLatency(1);
|
||||
data_array.setTarget('inst);
|
||||
val data_array_rdata = data_array.rw(data_addr, data_wdata, data_we, data_wmask);
|
||||
@ -424,62 +424,62 @@ class rocketDCacheDM(lines: Int) extends Component {
|
||||
// control state machine
|
||||
switch (state) {
|
||||
is (s_reset) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
is (s_ready) {
|
||||
when (io.cpu.req_kill) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
when (ldst_conflict) {
|
||||
state <== s_replay_load;
|
||||
state := s_replay_load;
|
||||
}
|
||||
when (!r_cpu_req_val || (tag_hit && !(r_req_flush || r_req_amo))) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
when (tag_hit && r_req_amo) {
|
||||
state <== s_write_amo;
|
||||
state := s_write_amo;
|
||||
}
|
||||
when (tag_valid & tag_dirty) {
|
||||
state <== s_start_writeback;
|
||||
state := s_start_writeback;
|
||||
}
|
||||
when (r_req_flush) {
|
||||
state <== s_resolve_miss;
|
||||
state := s_resolve_miss;
|
||||
}
|
||||
otherwise {
|
||||
state <== s_req_refill;
|
||||
state := s_req_refill;
|
||||
}
|
||||
}
|
||||
is (s_replay_load) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
is (s_write_amo) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
is (s_start_writeback) {
|
||||
state <== s_writeback;
|
||||
state := s_writeback;
|
||||
}
|
||||
is (s_writeback) {
|
||||
when (io.mem.req_rdy && (rr_count === UFix(3,2))) {
|
||||
when (r_req_flush) {
|
||||
state <== s_resolve_miss;
|
||||
state := s_resolve_miss;
|
||||
}
|
||||
otherwise {
|
||||
state <== s_req_refill;
|
||||
state := s_req_refill;
|
||||
}
|
||||
}
|
||||
}
|
||||
is (s_req_refill)
|
||||
{
|
||||
when (io.mem.req_rdy) { state <== s_refill; }
|
||||
when (io.mem.req_rdy) { state := s_refill; }
|
||||
}
|
||||
is (s_refill) {
|
||||
when (io.mem.resp_val && (rr_count === UFix(3,2))) { state <== s_resolve_miss; }
|
||||
when (io.mem.resp_val && (rr_count === UFix(3,2))) { state := s_resolve_miss; }
|
||||
}
|
||||
is (s_resolve_miss) {
|
||||
when (r_req_amo) {
|
||||
state <== s_write_amo;
|
||||
state := s_write_amo;
|
||||
}
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -505,12 +505,12 @@ class rocketDCacheAmoALU extends Component {
|
||||
val adder_out = adder_lhs + adder_rhs;
|
||||
val alu_out = Wire() { UFix() };
|
||||
switch (io.cmd) {
|
||||
// is (M_XA_ADD) { alu_out <== adder_out; }
|
||||
is (M_XA_SWAP) { alu_out <== io.rhs; }
|
||||
is (M_XA_AND) { alu_out <== io.lhs & io.rhs; }
|
||||
is (M_XA_OR) { alu_out <== io.lhs | io.rhs; }
|
||||
// is (M_XA_ADD) { alu_out := adder_out; }
|
||||
is (M_XA_SWAP) { alu_out := io.rhs; }
|
||||
is (M_XA_AND) { alu_out := io.lhs & io.rhs; }
|
||||
is (M_XA_OR) { alu_out := io.lhs | io.rhs; }
|
||||
}
|
||||
alu_out <== adder_out;
|
||||
alu_out := adder_out;
|
||||
io.result := alu_out;
|
||||
}
|
||||
|
||||
|
@ -21,20 +21,6 @@ class ioDivider(width: Int) extends Bundle {
|
||||
val result_rdy = Bool(INPUT);
|
||||
}
|
||||
|
||||
// class ioDivider extends Bundle {
|
||||
// // requests
|
||||
// val req_val = Bool(INPUT);
|
||||
// val req_rdy = Bool(OUTPUT);
|
||||
// val req_fn = UFix(3, INPUT);
|
||||
// val req_tag = UFix(5, INPUT);
|
||||
// val req_rs1 = Bits(64, INPUT);
|
||||
// val req_rs2 = Bits(64, INPUT);
|
||||
// // responses
|
||||
// val resp_val = Bool(OUTPUT);
|
||||
// val resp_data = Bits(64, OUTPUT);
|
||||
// val resp_tag = UFix(5, OUTPUT);
|
||||
// }
|
||||
|
||||
class rocketDivider(width : Int) extends Component {
|
||||
val io = new ioDivider(width);
|
||||
|
||||
@ -55,28 +41,36 @@ class rocketDivider(width : Int) extends Component {
|
||||
|
||||
val tc = (io.div_fn === DIV_D) || (io.div_fn === DIV_R);
|
||||
|
||||
when (io.div_kill && Reg(state === s_ready)) { // can only kill on first cycle
|
||||
state <== s_ready;
|
||||
val do_kill = io.div_kill && Reg(io.div_rdy) // kill on 1st cycle only
|
||||
|
||||
switch (state) {
|
||||
is (s_ready) {
|
||||
when (io.div_val) {
|
||||
state := Mux(tc, s_neg_inputs, s_busy)
|
||||
}
|
||||
}
|
||||
is (s_neg_inputs) {
|
||||
state := Mux(do_kill, s_ready, s_busy)
|
||||
}
|
||||
is (s_busy) {
|
||||
when (do_kill) {
|
||||
state := s_ready
|
||||
}
|
||||
.elsewhen (count === UFix(width)) {
|
||||
state := Mux(neg_quo || neg_rem, s_neg_outputs, s_done)
|
||||
}
|
||||
}
|
||||
is (s_neg_outputs) {
|
||||
state := s_done
|
||||
}
|
||||
is (s_done) {
|
||||
when (io.result_rdy) {
|
||||
state := s_ready
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// state machine
|
||||
switch (state) {
|
||||
is (s_ready) {
|
||||
when (!io.div_val) { state <== s_ready; }
|
||||
when (tc) { state <== s_neg_inputs };
|
||||
otherwise { state <== s_busy; }
|
||||
}
|
||||
is (s_neg_inputs) { state <== s_busy; }
|
||||
is (s_busy) {
|
||||
when (count != UFix(width)) { state <== s_busy; }
|
||||
when (!(neg_quo || neg_rem)) { state <== s_done; }
|
||||
otherwise { state <== s_neg_outputs; }
|
||||
}
|
||||
is (s_neg_outputs) { state <== s_done; }
|
||||
is (s_done) {
|
||||
when (io.result_rdy) { state <== s_ready; }
|
||||
}
|
||||
}
|
||||
|
||||
val lhs_sign = tc && Mux(io.dw === DW_64, io.in0(width-1), io.in0(width/2-1)).toBool
|
||||
val lhs_hi = Mux(io.dw === DW_64, io.in0(width-1,width/2), Fill(width/2, lhs_sign))
|
||||
@ -87,45 +81,45 @@ class rocketDivider(width : Int) extends Component {
|
||||
val rhs_in = Cat(rhs_hi, io.in1(width/2-1,0))
|
||||
|
||||
when ((state === s_ready) && io.div_val) {
|
||||
count <== UFix(0, log2up(width+1));
|
||||
half <== (io.dw === DW_32);
|
||||
neg_quo <== Bool(false);
|
||||
neg_rem <== Bool(false);
|
||||
rem <== (io.div_fn === DIV_R) || (io.div_fn === DIV_RU);
|
||||
reg_tag <== io.div_tag;
|
||||
divby0 <== Bool(true);
|
||||
divisor <== rhs_in.toUFix;
|
||||
remainder <== Cat(UFix(0,width+1), lhs_in).toUFix;
|
||||
count := UFix(0, log2up(width+1));
|
||||
half := (io.dw === DW_32);
|
||||
neg_quo := Bool(false);
|
||||
neg_rem := Bool(false);
|
||||
rem := (io.div_fn === DIV_R) || (io.div_fn === DIV_RU);
|
||||
reg_tag := io.div_tag;
|
||||
divby0 := Bool(true);
|
||||
divisor := rhs_in.toUFix;
|
||||
remainder := Cat(UFix(0,width+1), lhs_in).toUFix;
|
||||
}
|
||||
|
||||
when (state === s_neg_inputs) {
|
||||
neg_rem <== remainder(width-1).toBool;
|
||||
neg_quo <== (remainder(width-1) != divisor(width-1));
|
||||
neg_rem := remainder(width-1).toBool;
|
||||
neg_quo := (remainder(width-1) != divisor(width-1));
|
||||
when (remainder(width-1).toBool) {
|
||||
remainder <== Cat(remainder(2*width, width), -remainder(width-1,0)).toUFix;
|
||||
remainder := Cat(remainder(2*width, width), -remainder(width-1,0)).toUFix;
|
||||
}
|
||||
when (divisor(width-1).toBool) {
|
||||
divisor <== subtractor(width-1,0);
|
||||
divisor := subtractor(width-1,0);
|
||||
}
|
||||
}
|
||||
when (state === s_neg_outputs) {
|
||||
when (neg_rem && neg_quo && !divby0) {
|
||||
remainder <== Cat(-remainder(2*width, width+1), remainder(width), -remainder(width-1,0)).toUFix;
|
||||
remainder := Cat(-remainder(2*width, width+1), remainder(width), -remainder(width-1,0)).toUFix;
|
||||
}
|
||||
when (neg_quo && !divby0) {
|
||||
remainder <== Cat(remainder(2*width, width), -remainder(width-1,0)).toUFix;
|
||||
.elsewhen (neg_quo && !divby0) {
|
||||
remainder := Cat(remainder(2*width, width), -remainder(width-1,0)).toUFix;
|
||||
}
|
||||
when (neg_rem) {
|
||||
remainder <== Cat(-remainder(2*width, width+1), remainder(width,0)).toUFix;
|
||||
.elsewhen (neg_rem) {
|
||||
remainder := Cat(-remainder(2*width, width+1), remainder(width,0)).toUFix;
|
||||
}
|
||||
|
||||
when (divisor(width-1).toBool) {
|
||||
divisor <== subtractor(width-1,0);
|
||||
divisor := subtractor(width-1,0);
|
||||
}
|
||||
}
|
||||
when (state === s_busy) {
|
||||
count <== count + UFix(1);
|
||||
divby0 <== divby0 && !subtractor(width).toBool;
|
||||
remainder <== Mux(subtractor(width).toBool,
|
||||
count := count + UFix(1);
|
||||
divby0 := divby0 && !subtractor(width).toBool;
|
||||
remainder := Mux(subtractor(width).toBool,
|
||||
Cat(remainder(2*width-1, width), remainder(width-1,0), ~subtractor(width)),
|
||||
Cat(subtractor(width-1, 0), remainder(width-1,0), ~subtractor(width))).toUFix;
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ class rocketDpath extends Component
|
||||
if_pc_plus4))))))); // PC_4
|
||||
|
||||
when (!io.ctrl.stallf) {
|
||||
if_reg_pc <== if_next_pc.toUFix;
|
||||
if_reg_pc := if_next_pc.toUFix;
|
||||
}
|
||||
|
||||
io.ctrl.xcpt_ma_inst := if_next_pc(1,0) != Bits(0)
|
||||
@ -171,14 +171,14 @@ class rocketDpath extends Component
|
||||
|
||||
// instruction decode stage
|
||||
when (!io.ctrl.stalld) {
|
||||
id_reg_pc <== if_reg_pc;
|
||||
id_reg_pc := if_reg_pc;
|
||||
when(io.ctrl.killf) {
|
||||
id_reg_inst <== NOP;
|
||||
id_reg_valid <== Bool(false);
|
||||
id_reg_inst := NOP;
|
||||
id_reg_valid := Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
id_reg_inst <== io.imem.resp_data;
|
||||
id_reg_valid <== Bool(true);
|
||||
.otherwise {
|
||||
id_reg_inst := io.imem.resp_data;
|
||||
id_reg_valid := Bool(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,34 +235,34 @@ class rocketDpath extends Component
|
||||
io.ctrl.inst := id_reg_inst;
|
||||
|
||||
// execute stage
|
||||
ex_reg_pc <== id_reg_pc;
|
||||
ex_reg_inst <== id_reg_inst
|
||||
ex_reg_raddr1 <== id_raddr1
|
||||
ex_reg_raddr2 <== id_raddr2;
|
||||
ex_reg_op2 <== id_op2;
|
||||
ex_reg_rs2 <== id_rs2;
|
||||
ex_reg_rs1 <== id_rs1;
|
||||
ex_reg_waddr <== id_waddr;
|
||||
ex_reg_ctrl_fn_dw <== io.ctrl.fn_dw.toUFix;
|
||||
ex_reg_ctrl_fn_alu <== io.ctrl.fn_alu;
|
||||
ex_reg_ctrl_mul_fn <== io.ctrl.mul_fn;
|
||||
ex_reg_ctrl_div_fn <== io.ctrl.div_fn;
|
||||
ex_reg_ctrl_sel_wb <== io.ctrl.sel_wb;
|
||||
ex_reg_ctrl_ren_pcr <== io.ctrl.ren_pcr;
|
||||
ex_reg_pc := id_reg_pc;
|
||||
ex_reg_inst := id_reg_inst
|
||||
ex_reg_raddr1 := id_raddr1
|
||||
ex_reg_raddr2 := id_raddr2;
|
||||
ex_reg_op2 := id_op2;
|
||||
ex_reg_rs2 := id_rs2;
|
||||
ex_reg_rs1 := id_rs1;
|
||||
ex_reg_waddr := id_waddr;
|
||||
ex_reg_ctrl_fn_dw := io.ctrl.fn_dw.toUFix;
|
||||
ex_reg_ctrl_fn_alu := io.ctrl.fn_alu;
|
||||
ex_reg_ctrl_mul_fn := io.ctrl.mul_fn;
|
||||
ex_reg_ctrl_div_fn := io.ctrl.div_fn;
|
||||
ex_reg_ctrl_sel_wb := io.ctrl.sel_wb;
|
||||
ex_reg_ctrl_ren_pcr := io.ctrl.ren_pcr;
|
||||
|
||||
when(io.ctrl.killd) {
|
||||
ex_reg_valid <== Bool(false);
|
||||
ex_reg_ctrl_div_val <== Bool(false);
|
||||
ex_reg_ctrl_mul_val <== Bool(false);
|
||||
ex_reg_ctrl_wen_pcr <== Bool(false);
|
||||
ex_reg_ctrl_eret <== Bool(false);
|
||||
ex_reg_valid := Bool(false);
|
||||
ex_reg_ctrl_div_val := Bool(false);
|
||||
ex_reg_ctrl_mul_val := Bool(false);
|
||||
ex_reg_ctrl_wen_pcr := Bool(false);
|
||||
ex_reg_ctrl_eret := Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
ex_reg_valid <== id_reg_valid;
|
||||
ex_reg_ctrl_div_val <== io.ctrl.div_val;
|
||||
ex_reg_ctrl_mul_val <== io.ctrl.mul_val;
|
||||
ex_reg_ctrl_wen_pcr <== io.ctrl.wen_pcr;
|
||||
ex_reg_ctrl_eret <== io.ctrl.id_eret;
|
||||
.otherwise {
|
||||
ex_reg_valid := id_reg_valid;
|
||||
ex_reg_ctrl_div_val := io.ctrl.div_val;
|
||||
ex_reg_ctrl_mul_val := io.ctrl.mul_val;
|
||||
ex_reg_ctrl_wen_pcr := io.ctrl.wen_pcr;
|
||||
ex_reg_ctrl_eret := io.ctrl.id_eret;
|
||||
}
|
||||
|
||||
alu.io.dw := ex_reg_ctrl_fn_dw;
|
||||
@ -330,10 +330,10 @@ class rocketDpath extends Component
|
||||
|
||||
// time stamp counter
|
||||
val tsc_reg = Reg(resetVal = UFix(0,64));
|
||||
tsc_reg <== tsc_reg + UFix(1);
|
||||
tsc_reg := tsc_reg + UFix(1);
|
||||
// instructions retired counter
|
||||
val irt_reg = Reg(resetVal = UFix(0,64));
|
||||
when (wb_reg_valid) { irt_reg <== irt_reg + UFix(1); }
|
||||
when (wb_reg_valid) { irt_reg := irt_reg + UFix(1); }
|
||||
|
||||
// writeback select mux
|
||||
ex_wdata :=
|
||||
@ -344,21 +344,21 @@ class rocketDpath extends Component
|
||||
ex_alu_out)))).toBits; // WB_ALU
|
||||
|
||||
// memory stage
|
||||
mem_reg_pc <== ex_reg_pc;
|
||||
mem_reg_inst <== ex_reg_inst
|
||||
mem_reg_rs2 <== ex_reg_rs2
|
||||
mem_reg_waddr <== ex_reg_waddr;
|
||||
mem_reg_wdata <== ex_wdata;
|
||||
mem_reg_raddr1 <== ex_reg_raddr1
|
||||
mem_reg_raddr2 <== ex_reg_raddr2;
|
||||
mem_reg_pc := ex_reg_pc;
|
||||
mem_reg_inst := ex_reg_inst
|
||||
mem_reg_rs2 := ex_reg_rs2
|
||||
mem_reg_waddr := ex_reg_waddr;
|
||||
mem_reg_wdata := ex_wdata;
|
||||
mem_reg_raddr1 := ex_reg_raddr1
|
||||
mem_reg_raddr2 := ex_reg_raddr2;
|
||||
|
||||
when (io.ctrl.killx) {
|
||||
mem_reg_valid <== Bool(false);
|
||||
mem_reg_ctrl_wen_pcr <== Bool(false);
|
||||
mem_reg_valid := Bool(false);
|
||||
mem_reg_ctrl_wen_pcr := Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
mem_reg_valid <== ex_reg_valid;
|
||||
mem_reg_ctrl_wen_pcr <== ex_reg_ctrl_wen_pcr;
|
||||
.otherwise {
|
||||
mem_reg_valid := ex_reg_valid;
|
||||
mem_reg_ctrl_wen_pcr := ex_reg_ctrl_wen_pcr;
|
||||
}
|
||||
|
||||
// for load/use hazard detection (load byte/halfword)
|
||||
@ -376,9 +376,9 @@ class rocketDpath extends Component
|
||||
val dmem_resp_waddr = io.dmem.resp_tag.toUFix >> UFix(2)
|
||||
val dmem_resp_ext_tag = io.dmem.resp_tag.toUFix >> UFix(1)
|
||||
dmem_resp_replay := io.dmem.resp_replay && dmem_resp_xpu;
|
||||
r_dmem_resp_replay <== dmem_resp_replay
|
||||
r_dmem_resp_waddr <== dmem_resp_waddr
|
||||
r_dmem_fp_replay <== io.dmem.resp_replay && dmem_resp_fpu;
|
||||
r_dmem_resp_replay := dmem_resp_replay
|
||||
r_dmem_resp_waddr := dmem_resp_waddr
|
||||
r_dmem_fp_replay := io.dmem.resp_replay && dmem_resp_fpu;
|
||||
|
||||
val mem_ll_waddr = Mux(dmem_resp_replay, dmem_resp_waddr,
|
||||
Mux(div_result_val, div_result_tag,
|
||||
@ -389,22 +389,22 @@ class rocketDpath extends Component
|
||||
mem_reg_wdata))
|
||||
val mem_ll_wb = dmem_resp_replay || div_result_val || mul_result_val
|
||||
|
||||
wb_reg_pc <== mem_reg_pc;
|
||||
wb_reg_inst <== mem_reg_inst
|
||||
wb_reg_ll_wb <== mem_ll_wb
|
||||
wb_reg_rs2 <== mem_reg_rs2
|
||||
wb_reg_waddr <== mem_ll_waddr
|
||||
wb_reg_wdata <== mem_ll_wdata
|
||||
wb_reg_raddr1 <== mem_reg_raddr1
|
||||
wb_reg_raddr2 <== mem_reg_raddr2;
|
||||
wb_reg_pc := mem_reg_pc;
|
||||
wb_reg_inst := mem_reg_inst
|
||||
wb_reg_ll_wb := mem_ll_wb
|
||||
wb_reg_rs2 := mem_reg_rs2
|
||||
wb_reg_waddr := mem_ll_waddr
|
||||
wb_reg_wdata := mem_ll_wdata
|
||||
wb_reg_raddr1 := mem_reg_raddr1
|
||||
wb_reg_raddr2 := mem_reg_raddr2;
|
||||
|
||||
when (io.ctrl.killm) {
|
||||
wb_reg_valid <== Bool(false);
|
||||
wb_reg_ctrl_wen_pcr <== Bool(false);
|
||||
wb_reg_valid := Bool(false);
|
||||
wb_reg_ctrl_wen_pcr := Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
wb_reg_valid <== mem_reg_valid;
|
||||
wb_reg_ctrl_wen_pcr <== mem_reg_ctrl_wen_pcr;
|
||||
.otherwise {
|
||||
wb_reg_valid := mem_reg_valid;
|
||||
wb_reg_ctrl_wen_pcr := mem_reg_ctrl_wen_pcr;
|
||||
}
|
||||
|
||||
// vector datapath
|
||||
|
@ -40,13 +40,10 @@ class rocketDpathBTB(entries: Int) extends Component
|
||||
val my_clr = io.clr && my_hit || io.invalidate
|
||||
val my_wen = io.wen && (my_hit || !hit && UFix(i) === repl_way)
|
||||
|
||||
when (my_clr) {
|
||||
valid <== Bool(false)
|
||||
}
|
||||
valid := !my_clr && (valid || my_wen)
|
||||
when (my_wen) {
|
||||
valid <== Bool(true)
|
||||
tag <== io.correct_pc
|
||||
target <== io.correct_target
|
||||
tag := io.correct_pc
|
||||
target := io.correct_target
|
||||
}
|
||||
|
||||
hit_reduction = hit_reduction || my_hit
|
||||
@ -66,14 +63,14 @@ class ioDpathPCR extends Bundle()
|
||||
val r = new ioReadPort();
|
||||
val w = new ioWritePort();
|
||||
|
||||
val status = Bits(17, OUTPUT);
|
||||
val status = Bits(17, OUTPUT);
|
||||
val ptbr = UFix(PADDR_BITS, OUTPUT);
|
||||
val evec = UFix(VADDR_BITS, OUTPUT);
|
||||
val exception = Bool(INPUT);
|
||||
val cause = UFix(5, INPUT);
|
||||
val cause = UFix(5, INPUT);
|
||||
val badvaddr_wen = Bool(INPUT);
|
||||
val pc = UFix(VADDR_BITS+1, INPUT);
|
||||
val eret = Bool(INPUT);
|
||||
val pc = UFix(VADDR_BITS+1, INPUT);
|
||||
val eret = Bool(INPUT);
|
||||
val ei = Bool(INPUT);
|
||||
val di = Bool(INPUT);
|
||||
val ptbr_wen = Bool(OUTPUT);
|
||||
@ -120,12 +117,12 @@ class rocketDpathPCR extends Component
|
||||
val reg_status = Cat(reg_status_sx, reg_status_ux, reg_status_s, reg_status_ps, reg_status_ec, reg_status_ev, reg_status_ef, reg_status_et);
|
||||
val rdata = Wire() { Bits() };
|
||||
|
||||
io.ptbr_wen := reg_status_vm.toBool && !io.exception && io.w.en && (io.w.addr === PCR_PTBR);
|
||||
io.status := Cat(reg_status_vm, reg_status_im, reg_status);
|
||||
io.ptbr_wen := reg_status_vm.toBool && io.w.en && (io.w.addr === PCR_PTBR);
|
||||
io.status := Cat(reg_status_vm, reg_status_im, reg_status);
|
||||
io.evec := reg_ebase;
|
||||
io.ptbr := reg_ptbr;
|
||||
io.host.to := Mux(io.host.from_wen, Bits(0), reg_tohost);
|
||||
io.debug.error_mode := reg_error_mode;
|
||||
io.host.to := Mux(io.host.from_wen, Bits(0), reg_tohost);
|
||||
io.debug.error_mode := reg_error_mode;
|
||||
io.r.data := rdata;
|
||||
|
||||
io.vecbank := reg_vecbank
|
||||
@ -139,100 +136,99 @@ class rocketDpathPCR extends Component
|
||||
io.console_val := console_wen;
|
||||
|
||||
when (io.host.from_wen) {
|
||||
reg_tohost <== Bits(0);
|
||||
reg_fromhost <== io.host.from;
|
||||
}
|
||||
otherwise {
|
||||
when (!io.exception && io.w.en && (io.w.addr === PCR_TOHOST)) {
|
||||
reg_tohost <== io.w.data;
|
||||
reg_fromhost <== Bits(0);
|
||||
}
|
||||
reg_tohost := Bits(0);
|
||||
reg_fromhost := io.host.from;
|
||||
}
|
||||
.elsewhen (io.w.en && (io.w.addr === PCR_TOHOST)) {
|
||||
reg_tohost := io.w.data;
|
||||
reg_fromhost := Bits(0);
|
||||
}
|
||||
|
||||
val badvaddr_sign = Mux(io.w.data(VADDR_BITS-1), ~io.w.data(63,VADDR_BITS) === UFix(0), io.w.data(63,VADDR_BITS) != UFix(0))
|
||||
when (io.badvaddr_wen) {
|
||||
reg_badvaddr <== Cat(badvaddr_sign, io.w.data(VADDR_BITS-1,0)).toUFix;
|
||||
}
|
||||
|
||||
when (io.exception && !reg_status_et) {
|
||||
reg_error_mode <== Bool(true);
|
||||
}
|
||||
|
||||
when (io.exception && reg_status_et) {
|
||||
reg_status_s <== Bool(true);
|
||||
reg_status_ps <== reg_status_s;
|
||||
reg_status_et <== Bool(false);
|
||||
reg_epc <== io.pc;
|
||||
reg_cause <== io.cause;
|
||||
}
|
||||
|
||||
when (!io.exception && io.di) {
|
||||
reg_status_et <== Bool(false);
|
||||
}
|
||||
|
||||
when (!io.exception && io.ei) {
|
||||
reg_status_et <== Bool(true);
|
||||
}
|
||||
|
||||
when (!io.exception && io.eret) {
|
||||
reg_status_s <== reg_status_ps;
|
||||
reg_status_et <== Bool(true);
|
||||
reg_badvaddr := Cat(badvaddr_sign, io.w.data(VADDR_BITS-1,0)).toUFix;
|
||||
}
|
||||
|
||||
when (!io.exception && !io.eret && io.w.en) {
|
||||
when (io.w.addr === PCR_STATUS) {
|
||||
reg_status_vm <== io.w.data(SR_VM).toBool;
|
||||
reg_status_im <== io.w.data(15,8);
|
||||
reg_status_sx <== io.w.data(SR_SX).toBool;
|
||||
reg_status_ux <== io.w.data(SR_UX).toBool;
|
||||
reg_status_s <== io.w.data(SR_S).toBool;
|
||||
reg_status_ps <== io.w.data(SR_PS).toBool;
|
||||
reg_status_ev <== Bool(HAVE_VEC) && io.w.data(SR_EV).toBool;
|
||||
reg_status_ef <== Bool(HAVE_FPU) && io.w.data(SR_EF).toBool;
|
||||
reg_status_ec <== Bool(HAVE_RVC) && io.w.data(SR_EC).toBool;
|
||||
reg_status_et <== io.w.data(SR_ET).toBool;
|
||||
}
|
||||
when (io.w.addr === PCR_EPC) { reg_epc <== io.w.data(VADDR_BITS,0).toUFix; }
|
||||
when (io.w.addr === PCR_BADVADDR) { reg_badvaddr <== io.w.data(VADDR_BITS,0).toUFix; }
|
||||
when (io.w.addr === PCR_EVEC) { reg_ebase <== io.w.data(VADDR_BITS-1,0).toUFix; }
|
||||
when (io.w.addr === PCR_COUNT) { reg_count <== io.w.data(31,0).toUFix; }
|
||||
when (io.w.addr === PCR_COMPARE) { reg_compare <== io.w.data(31,0).toUFix; r_irq_timer <== Bool(false); }
|
||||
when (io.w.addr === PCR_CAUSE) { reg_cause <== io.w.data(4,0); }
|
||||
when (io.w.addr === PCR_FROMHOST) { reg_fromhost <== io.w.data; }
|
||||
when (io.w.addr === PCR_SEND_IPI) { r_irq_ipi <== Bool(true); }
|
||||
when (io.w.addr === PCR_CLR_IPI) { r_irq_ipi <== Bool(false); }
|
||||
when (io.w.addr === PCR_K0) { reg_k0 <== io.w.data; }
|
||||
when (io.w.addr === PCR_K1) { reg_k1 <== io.w.data; }
|
||||
when (io.w.addr === PCR_PTBR) { reg_ptbr <== Cat(io.w.data(PADDR_BITS-1, PGIDX_BITS), Bits(0, PGIDX_BITS)).toUFix; }
|
||||
when (io.w.addr === PCR_VECBANK) { reg_vecbank <== io.w.data(7,0) }
|
||||
when (io.exception) {
|
||||
when (!reg_status_et) {
|
||||
reg_error_mode := Bool(true)
|
||||
}
|
||||
.otherwise {
|
||||
reg_status_s := Bool(true);
|
||||
reg_status_ps := reg_status_s;
|
||||
reg_status_et := Bool(false);
|
||||
reg_epc := io.pc;
|
||||
reg_cause := io.cause;
|
||||
}
|
||||
}
|
||||
|
||||
otherwise {
|
||||
reg_count <== reg_count + UFix(1);
|
||||
|
||||
when (io.di) {
|
||||
reg_status_et := Bool(false);
|
||||
}
|
||||
|
||||
when (io.ei) {
|
||||
reg_status_et := Bool(true);
|
||||
}
|
||||
|
||||
when (io.eret) {
|
||||
reg_status_s := reg_status_ps;
|
||||
reg_status_et := Bool(true);
|
||||
}
|
||||
|
||||
when (reg_count === reg_compare) {
|
||||
r_irq_timer <== Bool(true);
|
||||
r_irq_timer := Bool(true);
|
||||
}
|
||||
reg_count := reg_count + UFix(1);
|
||||
|
||||
io.irq_timer := r_irq_timer;
|
||||
io.irq_ipi := r_irq_ipi;
|
||||
|
||||
when (!io.r.en) { rdata <== Bits(0,64); }
|
||||
switch (io.r.addr) {
|
||||
is (PCR_STATUS) { rdata <== Cat(Bits(0,47), reg_status_vm, reg_status_im, reg_status); }
|
||||
is (PCR_EPC) { rdata <== Cat(Fill(64-VADDR_BITS-1, reg_epc(VADDR_BITS)), reg_epc); }
|
||||
is (PCR_BADVADDR) { rdata <== Cat(Fill(64-VADDR_BITS-1, reg_badvaddr(VADDR_BITS)), reg_badvaddr); }
|
||||
is (PCR_EVEC) { rdata <== Cat(Fill(64-VADDR_BITS, reg_ebase(VADDR_BITS-1)), reg_ebase); }
|
||||
is (PCR_COUNT) { rdata <== Cat(Fill(32, reg_count(31)), reg_count); }
|
||||
is (PCR_COMPARE) { rdata <== Cat(Fill(32, reg_compare(31)), reg_compare); }
|
||||
is (PCR_CAUSE) { rdata <== Cat(Bits(0,59), reg_cause); }
|
||||
is (PCR_COREID) { rdata <== Bits(COREID,64); }
|
||||
is (PCR_FROMHOST) { rdata <== reg_fromhost; }
|
||||
is (PCR_TOHOST) { rdata <== reg_tohost; }
|
||||
is (PCR_K0) { rdata <== reg_k0; }
|
||||
is (PCR_K1) { rdata <== reg_k1; }
|
||||
is (PCR_PTBR) { rdata <== Cat(Bits(0,64-PADDR_BITS), reg_ptbr); }
|
||||
is (PCR_VECBANK) { rdata <== Cat(Bits(0, 56), reg_vecbank) }
|
||||
otherwise { rdata <== Bits(0,64); }
|
||||
when (io.w.en) {
|
||||
when (io.w.addr === PCR_STATUS) {
|
||||
reg_status_vm := io.w.data(SR_VM).toBool;
|
||||
reg_status_im := io.w.data(15,8);
|
||||
reg_status_sx := io.w.data(SR_SX).toBool;
|
||||
reg_status_ux := io.w.data(SR_UX).toBool;
|
||||
reg_status_s := io.w.data(SR_S).toBool;
|
||||
reg_status_ps := io.w.data(SR_PS).toBool;
|
||||
reg_status_ev := Bool(HAVE_VEC) && io.w.data(SR_EV).toBool;
|
||||
reg_status_ef := Bool(HAVE_FPU) && io.w.data(SR_EF).toBool;
|
||||
reg_status_ec := Bool(HAVE_RVC) && io.w.data(SR_EC).toBool;
|
||||
reg_status_et := io.w.data(SR_ET).toBool;
|
||||
}
|
||||
when (io.w.addr === PCR_EPC) { reg_epc := io.w.data(VADDR_BITS,0).toUFix; }
|
||||
when (io.w.addr === PCR_BADVADDR) { reg_badvaddr := io.w.data(VADDR_BITS,0).toUFix; }
|
||||
when (io.w.addr === PCR_EVEC) { reg_ebase := io.w.data(VADDR_BITS-1,0).toUFix; }
|
||||
when (io.w.addr === PCR_COUNT) { reg_count := io.w.data(31,0).toUFix; }
|
||||
when (io.w.addr === PCR_COMPARE) { reg_compare := io.w.data(31,0).toUFix; r_irq_timer := Bool(false); }
|
||||
when (io.w.addr === PCR_CAUSE) { reg_cause := io.w.data(4,0); }
|
||||
when (io.w.addr === PCR_FROMHOST) { reg_fromhost := io.w.data; }
|
||||
when (io.w.addr === PCR_SEND_IPI) { r_irq_ipi := Bool(true); }
|
||||
when (io.w.addr === PCR_CLR_IPI) { r_irq_ipi := Bool(false); }
|
||||
when (io.w.addr === PCR_K0) { reg_k0 := io.w.data; }
|
||||
when (io.w.addr === PCR_K1) { reg_k1 := io.w.data; }
|
||||
when (io.w.addr === PCR_PTBR) { reg_ptbr := Cat(io.w.data(PADDR_BITS-1, PGIDX_BITS), Bits(0, PGIDX_BITS)).toUFix; }
|
||||
when (io.w.addr === PCR_VECBANK) { reg_vecbank := io.w.data(7,0) }
|
||||
}
|
||||
|
||||
rdata := Bits(0, 64)
|
||||
when (io.r.en) {
|
||||
switch (io.r.addr) {
|
||||
is (PCR_STATUS) { rdata := Cat(Bits(0,47), reg_status_vm, reg_status_im, reg_status); }
|
||||
is (PCR_EPC) { rdata := Cat(Fill(64-VADDR_BITS-1, reg_epc(VADDR_BITS)), reg_epc); }
|
||||
is (PCR_BADVADDR) { rdata := Cat(Fill(64-VADDR_BITS-1, reg_badvaddr(VADDR_BITS)), reg_badvaddr); }
|
||||
is (PCR_EVEC) { rdata := Cat(Fill(64-VADDR_BITS, reg_ebase(VADDR_BITS-1)), reg_ebase); }
|
||||
is (PCR_COUNT) { rdata := Cat(Fill(32, reg_count(31)), reg_count); }
|
||||
is (PCR_COMPARE) { rdata := Cat(Fill(32, reg_compare(31)), reg_compare); }
|
||||
is (PCR_CAUSE) { rdata := Cat(Bits(0,59), reg_cause); }
|
||||
is (PCR_COREID) { rdata := Bits(COREID,64); }
|
||||
is (PCR_FROMHOST) { rdata := reg_fromhost; }
|
||||
is (PCR_TOHOST) { rdata := reg_tohost; }
|
||||
is (PCR_K0) { rdata := reg_k0; }
|
||||
is (PCR_K1) { rdata := reg_k1; }
|
||||
is (PCR_PTBR) { rdata := Cat(Bits(0,64-PADDR_BITS), reg_ptbr); }
|
||||
is (PCR_VECBANK) { rdata := Cat(Bits(0, 56), reg_vecbank) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +257,7 @@ class rocketDpathRegfile extends Component
|
||||
{
|
||||
override val io = new ioRegfile();
|
||||
|
||||
val regfile = Mem4(32, io.w0.data);
|
||||
val regfile = Mem(32, io.w0.data);
|
||||
regfile.setReadLatency(0);
|
||||
regfile.setTarget('inst);
|
||||
regfile.write(io.w0.addr, io.w0.data, io.w0.en);
|
||||
|
@ -150,8 +150,8 @@ class rocketDpathVec extends Component
|
||||
|
||||
when (io.valid && wb_vec_wen.toBool && wb_vec_fn.toBool)
|
||||
{
|
||||
reg_hwvl <== hwvl_vcfg
|
||||
reg_appvl0 <== !(appvl.orR())
|
||||
reg_hwvl := hwvl_vcfg
|
||||
reg_appvl0 := !(appvl.orR())
|
||||
}
|
||||
|
||||
io.wen := io.valid && wb_vec_wen.toBool
|
||||
|
@ -52,13 +52,13 @@ class rocketDTLB(entries: Int) extends Component
|
||||
val repl_count = Reg(resetVal = UFix(0,addr_bits));
|
||||
|
||||
when (io.cpu.req_val && io.cpu.req_rdy) {
|
||||
r_cpu_req_vpn <== io.cpu.req_vpn;
|
||||
r_cpu_req_cmd <== io.cpu.req_cmd;
|
||||
r_cpu_req_asid <== io.cpu.req_asid;
|
||||
r_cpu_req_val <== Bool(true);
|
||||
r_cpu_req_vpn := io.cpu.req_vpn;
|
||||
r_cpu_req_cmd := io.cpu.req_cmd;
|
||||
r_cpu_req_asid := io.cpu.req_asid;
|
||||
r_cpu_req_val := Bool(true);
|
||||
}
|
||||
otherwise {
|
||||
r_cpu_req_val <== Bool(false);
|
||||
.otherwise {
|
||||
r_cpu_req_val := Bool(false);
|
||||
}
|
||||
|
||||
val req_load = (r_cpu_req_cmd === M_XRD);
|
||||
@ -96,19 +96,19 @@ class rocketDTLB(entries: Int) extends Component
|
||||
val sr_array = Reg(resetVal = Bits(0, entries)); // supervisor read permission
|
||||
val sw_array = Reg(resetVal = Bits(0, entries)); // supervisor write permission
|
||||
when (io.ptw.resp_val) {
|
||||
ur_array <== ur_array.bitSet(r_refill_waddr, ptw_perm_ur);
|
||||
uw_array <== uw_array.bitSet(r_refill_waddr, ptw_perm_uw);
|
||||
sr_array <== sr_array.bitSet(r_refill_waddr, ptw_perm_sr);
|
||||
sw_array <== sw_array.bitSet(r_refill_waddr, ptw_perm_sw);
|
||||
ur_array := ur_array.bitSet(r_refill_waddr, ptw_perm_ur);
|
||||
uw_array := uw_array.bitSet(r_refill_waddr, ptw_perm_uw);
|
||||
sr_array := sr_array.bitSet(r_refill_waddr, ptw_perm_sr);
|
||||
sw_array := sw_array.bitSet(r_refill_waddr, ptw_perm_sw);
|
||||
}
|
||||
|
||||
// when the page table lookup reports an error, set all permission
|
||||
// bits to 0 so the next access will cause an exception
|
||||
when (io.ptw.resp_err) {
|
||||
ur_array <== ur_array.bitSet(r_refill_waddr, Bool(false));
|
||||
uw_array <== uw_array.bitSet(r_refill_waddr, Bool(false));
|
||||
sr_array <== sr_array.bitSet(r_refill_waddr, Bool(false));
|
||||
sw_array <== sw_array.bitSet(r_refill_waddr, Bool(false));
|
||||
ur_array := ur_array.bitSet(r_refill_waddr, Bool(false));
|
||||
uw_array := uw_array.bitSet(r_refill_waddr, Bool(false));
|
||||
sr_array := sr_array.bitSet(r_refill_waddr, Bool(false));
|
||||
sw_array := sw_array.bitSet(r_refill_waddr, Bool(false));
|
||||
}
|
||||
|
||||
// high if there are any unused (invalid) entries in the TLB
|
||||
@ -128,10 +128,10 @@ class rocketDTLB(entries: Int) extends Component
|
||||
// currently replace TLB entries in LIFO order
|
||||
// TODO: implement LRU replacement policy
|
||||
when (tlb_miss) {
|
||||
r_refill_tag <== lookup_tag;
|
||||
r_refill_waddr <== repl_waddr;
|
||||
r_refill_tag := lookup_tag;
|
||||
r_refill_waddr := repl_waddr;
|
||||
when (!invalid_entry) {
|
||||
repl_count <== repl_count + UFix(1);
|
||||
repl_count := repl_count + UFix(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,17 +166,17 @@ class rocketDTLB(entries: Int) extends Component
|
||||
switch (state) {
|
||||
is (s_ready) {
|
||||
when (tlb_miss) {
|
||||
state <== s_request;
|
||||
state := s_request;
|
||||
}
|
||||
}
|
||||
is (s_request) {
|
||||
when (io.ptw.req_rdy) {
|
||||
state <== s_wait;
|
||||
state := s_wait;
|
||||
}
|
||||
}
|
||||
is (s_wait) {
|
||||
when (io.ptw.resp_val || io.ptw.resp_err) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ class rocketFPU extends Component
|
||||
|
||||
val ex_reg_inst = Reg() { Bits() }
|
||||
when (io.req_valid) {
|
||||
ex_reg_inst <== io.req_inst
|
||||
ex_reg_inst := io.req_inst
|
||||
}
|
||||
|
||||
// load response
|
||||
@ -135,12 +135,12 @@ class rocketFPU extends Component
|
||||
val load_wb_data = Reg() { Bits() }
|
||||
val load_wb_tag = Reg() { UFix() }
|
||||
when (dmem_resp_val_fpu) {
|
||||
load_wb_data <== io.dmem.resp_data
|
||||
load_wb_tag <== io.dmem.resp_tag.toUFix >> UFix(1)
|
||||
load_wb_data := io.dmem.resp_data
|
||||
load_wb_tag := io.dmem.resp_tag.toUFix >> UFix(1)
|
||||
}
|
||||
|
||||
// regfile
|
||||
val regfile = Mem4(32, load_wb_data);
|
||||
val regfile = Mem(32, load_wb_data);
|
||||
regfile.setReadLatency(0);
|
||||
regfile.setTarget('inst);
|
||||
regfile.write(load_wb_tag, load_wb_data, load_wb);
|
||||
|
@ -68,14 +68,14 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
||||
val tag_hit = Wire() { Bool() }
|
||||
|
||||
when (io.cpu.req_val && rdy) {
|
||||
r_cpu_req_val <== Bool(true)
|
||||
r_cpu_req_idx <== io.cpu.req_idx
|
||||
r_cpu_req_val := Bool(true)
|
||||
r_cpu_req_idx := io.cpu.req_idx
|
||||
}
|
||||
otherwise {
|
||||
r_cpu_req_val <== Bool(false)
|
||||
.otherwise {
|
||||
r_cpu_req_val := Bool(false)
|
||||
}
|
||||
when (state === s_ready && r_cpu_req_val && !io.cpu.itlb_miss) {
|
||||
r_cpu_req_ppn <== io.cpu.req_ppn
|
||||
r_cpu_req_ppn := io.cpu.req_ppn
|
||||
}
|
||||
|
||||
val r_cpu_hit_addr = Cat(io.cpu.req_ppn, r_cpu_req_idx)
|
||||
@ -86,7 +86,7 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
||||
// refill counter
|
||||
val refill_count = Reg(resetVal = UFix(0, rf_cnt_bits));
|
||||
when (io.mem.resp_val) {
|
||||
refill_count <== refill_count + UFix(1);
|
||||
refill_count := refill_count + UFix(1);
|
||||
}
|
||||
|
||||
val repl_way = LFSR16(state === s_ready && r_cpu_req_val && !io.cpu.itlb_miss && !tag_hit)(log2up(assoc)-1,0)
|
||||
@ -104,7 +104,7 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
||||
for (i <- 0 until assoc)
|
||||
{
|
||||
val repl_me = (repl_way === UFix(i))
|
||||
val tag_array = Mem4(lines, r_cpu_miss_tag);
|
||||
val tag_array = Mem(lines, r_cpu_miss_tag);
|
||||
tag_array.setReadLatency(1);
|
||||
tag_array.setTarget('inst);
|
||||
val tag_rdata = tag_array.rw(tag_addr, r_cpu_miss_tag, tag_we && repl_me);
|
||||
@ -112,17 +112,17 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
||||
// valid bit array
|
||||
val vb_array = Reg(resetVal = Bits(0, lines));
|
||||
when (io.cpu.invalidate) {
|
||||
vb_array <== Bits(0,lines);
|
||||
vb_array := Bits(0,lines);
|
||||
}
|
||||
when (tag_we && repl_me) {
|
||||
vb_array <== vb_array.bitSet(r_cpu_req_idx(indexmsb,indexlsb).toUFix, UFix(1,1));
|
||||
.elsewhen (tag_we && repl_me) {
|
||||
vb_array := vb_array.bitSet(r_cpu_req_idx(indexmsb,indexlsb).toUFix, UFix(1,1));
|
||||
}
|
||||
|
||||
val valid = vb_array(r_cpu_req_idx(indexmsb,indexlsb)).toBool;
|
||||
val hit = valid && (tag_rdata === r_cpu_hit_addr(tagmsb,taglsb))
|
||||
|
||||
// data array
|
||||
val data_array = Mem4(lines*REFILL_CYCLES, io.mem.resp_data);
|
||||
val data_array = Mem(lines*REFILL_CYCLES, io.mem.resp_data);
|
||||
data_array.setReadLatency(1);
|
||||
data_array.setTarget('inst);
|
||||
val data_out = data_array.rw(data_addr, io.mem.resp_data, io.mem.resp_val && repl_me)
|
||||
@ -144,30 +144,30 @@ class rocketICache(sets: Int, assoc: Int) extends Component {
|
||||
// control state machine
|
||||
switch (state) {
|
||||
is (s_reset) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
is (s_ready) {
|
||||
when (io.cpu.itlb_miss) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
when (r_cpu_req_val && !tag_hit) {
|
||||
state <== s_request;
|
||||
.elsewhen (r_cpu_req_val && !tag_hit) {
|
||||
state := s_request;
|
||||
}
|
||||
}
|
||||
is (s_request)
|
||||
{
|
||||
when (io.mem.req_rdy) {
|
||||
state <== s_refill_wait;
|
||||
state := s_refill_wait;
|
||||
}
|
||||
}
|
||||
is (s_refill_wait) {
|
||||
when (io.mem.resp_val) {
|
||||
state <== s_refill;
|
||||
state := s_refill;
|
||||
}
|
||||
}
|
||||
is (s_refill) {
|
||||
when (io.mem.resp_val && (~refill_count === UFix(0))) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ class rocketIPrefetcher extends Component() {
|
||||
|
||||
val demand_miss = io.icache.req_val & io.icache.req_rdy;
|
||||
val prefetch_addr = Reg() { UFix(width = io.icache.req_addr.width) };
|
||||
when (demand_miss) { prefetch_addr <== io.icache.req_addr + UFix(1); }
|
||||
when (demand_miss) { prefetch_addr := io.icache.req_addr + UFix(1); }
|
||||
|
||||
val addr_match = (prefetch_addr === io.icache.req_addr);
|
||||
val hit = (state != s_invalid) & (state != s_req_wait) & addr_match;
|
||||
@ -44,14 +44,14 @@ class rocketIPrefetcher extends Component() {
|
||||
io.mem.req_addr := Mux(io.mem.req_tag(0).toBool, prefetch_addr, io.icache.req_addr);
|
||||
|
||||
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); }
|
||||
val fill_done = (~fill_cnt === UFix(0)) & ip_mem_resp_val;
|
||||
|
||||
val forward = Reg(resetVal = Bool(false));
|
||||
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;
|
||||
forward <== (demand_miss & hit | forward & ~forward_done);
|
||||
forward := (demand_miss & hit | forward & ~forward_done);
|
||||
|
||||
io.icache.resp_val := (io.mem.resp_val && !io.mem.resp_tag(0).toBool) || (forward && pdq.io.deq.valid);
|
||||
io.icache.resp_data := Mux(forward, pdq.io.deq.bits, io.mem.resp_data);
|
||||
@ -63,25 +63,25 @@ class rocketIPrefetcher extends Component() {
|
||||
|
||||
switch (state) {
|
||||
is (s_invalid) {
|
||||
when (demand_miss) { state <== s_req_wait; }
|
||||
when (demand_miss) { state := s_req_wait; }
|
||||
}
|
||||
is (s_valid) {
|
||||
when (demand_miss | (forward & forward_done)) { state <== s_req_wait; }
|
||||
when (demand_miss | (forward & forward_done)) { state := s_req_wait; }
|
||||
}
|
||||
is (s_refilling) {
|
||||
when (demand_miss & ~addr_match & fill_done.toBool) { state <== s_req_wait; }
|
||||
when (demand_miss & ~addr_match) { state <== s_bad_resp_wait; }
|
||||
when (fill_done.toBool) { state <== s_valid; }
|
||||
when (demand_miss & ~addr_match & fill_done.toBool) { state := s_req_wait; }
|
||||
.elsewhen (demand_miss & ~addr_match) { state := s_bad_resp_wait; }
|
||||
.elsewhen (fill_done.toBool) { state := s_valid; }
|
||||
}
|
||||
is (s_req_wait) {
|
||||
when (ip_mem_req_rdy) { state <== s_resp_wait; }
|
||||
when (ip_mem_req_rdy) { state := s_resp_wait; }
|
||||
}
|
||||
is (s_resp_wait) {
|
||||
when (demand_miss & ~addr_match) { state <== s_bad_resp_wait; }
|
||||
when (ip_mem_resp_val.toBool) { state <== s_refilling; }
|
||||
when (demand_miss & ~addr_match) { state := s_bad_resp_wait; }
|
||||
.elsewhen (ip_mem_resp_val.toBool) { state := s_refilling; }
|
||||
}
|
||||
is (s_bad_resp_wait) {
|
||||
when (fill_done.toBool & ip_mem_resp_val.toBool) { state <== s_req_wait; }
|
||||
when (fill_done.toBool & ip_mem_resp_val.toBool) { state := s_req_wait; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,30 +23,26 @@ class rocketCAM(entries: Int, tag_bits: Int) extends Component {
|
||||
val io = new ioCAM(entries, addr_bits, tag_bits);
|
||||
val cam_tags = Mem(entries, io.write, io.write_addr, io.write_tag);
|
||||
|
||||
val l_hit = Wire() { Bool() };
|
||||
val l_hit_addr = Wire() { UFix() };
|
||||
|
||||
val vb_array = Reg(resetVal = Bits(0, entries));
|
||||
when (io.clear) {
|
||||
vb_array <== Bits(0, entries);
|
||||
vb_array := Bits(0, entries);
|
||||
}
|
||||
when (io.write) {
|
||||
vb_array <== vb_array.bitSet(io.write_addr, Bool(true));
|
||||
}
|
||||
|
||||
for (i <- 0 to entries-1) {
|
||||
when (vb_array(UFix(i)).toBool && (cam_tags(UFix(i)) === io.tag)) {
|
||||
l_hit <== Bool(true);
|
||||
l_hit_addr <== UFix(i,addr_bits);
|
||||
}
|
||||
.elsewhen (io.write) {
|
||||
vb_array := vb_array.bitSet(io.write_addr, Bool(true));
|
||||
}
|
||||
|
||||
l_hit <== Bool(false);
|
||||
l_hit_addr <== UFix(0, addr_bits);
|
||||
var l_hit = Bool(false)
|
||||
val mux = (new Mux1H(entries)) { Bits(width = addr_bits) }
|
||||
for (i <- 0 to entries-1) {
|
||||
val my_hit = vb_array(UFix(i)).toBool && (cam_tags(UFix(i)) === io.tag)
|
||||
l_hit = l_hit || my_hit
|
||||
mux.io.in(i) := Bits(i)
|
||||
mux.io.sel(i) := my_hit
|
||||
}
|
||||
|
||||
io.valid_bits := vb_array;
|
||||
io.hit := l_hit;
|
||||
io.hit_addr := l_hit_addr;
|
||||
io.hit_addr := mux.io.out.toUFix;
|
||||
}
|
||||
|
||||
// interface between TLB and PTW
|
||||
@ -104,12 +100,12 @@ class rocketITLB(entries: Int) extends Component
|
||||
val repl_count = Reg(resetVal = UFix(0, addr_bits));
|
||||
|
||||
when (io.cpu.req_val && io.cpu.req_rdy) {
|
||||
r_cpu_req_vpn <== io.cpu.req_vpn;
|
||||
r_cpu_req_asid <== io.cpu.req_asid;
|
||||
r_cpu_req_val <== Bool(true);
|
||||
r_cpu_req_vpn := io.cpu.req_vpn;
|
||||
r_cpu_req_asid := io.cpu.req_asid;
|
||||
r_cpu_req_val := Bool(true);
|
||||
}
|
||||
otherwise {
|
||||
r_cpu_req_val <== Bool(false);
|
||||
.otherwise {
|
||||
r_cpu_req_val := Bool(false);
|
||||
}
|
||||
|
||||
val bad_va = r_cpu_req_vpn(VPN_BITS) != r_cpu_req_vpn(VPN_BITS-1);
|
||||
@ -139,15 +135,15 @@ class rocketITLB(entries: Int) extends Component
|
||||
val ux_array = Reg(resetVal = Bits(0, entries)); // user execute permission
|
||||
val sx_array = Reg(resetVal = Bits(0, entries)); // supervisor execute permission
|
||||
when (io.ptw.resp_val) {
|
||||
ux_array <== ux_array.bitSet(r_refill_waddr, ptw_perm_ux);
|
||||
sx_array <== sx_array.bitSet(r_refill_waddr, ptw_perm_sx);
|
||||
ux_array := ux_array.bitSet(r_refill_waddr, ptw_perm_ux);
|
||||
sx_array := sx_array.bitSet(r_refill_waddr, ptw_perm_sx);
|
||||
}
|
||||
|
||||
// when the page table lookup reports an error, set both execute permission
|
||||
// bits to 0 so the next access will cause an exceptions
|
||||
when (io.ptw.resp_err) {
|
||||
ux_array <== ux_array.bitSet(r_refill_waddr, Bool(false));
|
||||
sx_array <== sx_array.bitSet(r_refill_waddr, Bool(false));
|
||||
ux_array := ux_array.bitSet(r_refill_waddr, Bool(false));
|
||||
sx_array := sx_array.bitSet(r_refill_waddr, Bool(false));
|
||||
}
|
||||
|
||||
// high if there are any unused entries in the ITLB
|
||||
@ -165,10 +161,10 @@ class rocketITLB(entries: Int) extends Component
|
||||
val tlb_miss = status_vm && lookup_miss;
|
||||
|
||||
when (tlb_miss) {
|
||||
r_refill_tag <== lookup_tag;
|
||||
r_refill_waddr <== repl_waddr;
|
||||
r_refill_tag := lookup_tag;
|
||||
r_refill_waddr := repl_waddr;
|
||||
when (!invalid_entry) {
|
||||
repl_count <== repl_count + UFix(1);
|
||||
repl_count := repl_count + UFix(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,17 +186,17 @@ class rocketITLB(entries: Int) extends Component
|
||||
switch (state) {
|
||||
is (s_ready) {
|
||||
when (tlb_miss) {
|
||||
state <== s_request;
|
||||
state := s_request;
|
||||
}
|
||||
}
|
||||
is (s_request) {
|
||||
when (io.ptw.req_rdy) {
|
||||
state <== s_wait;
|
||||
state := s_wait;
|
||||
}
|
||||
}
|
||||
is (s_wait) {
|
||||
when (io.ptw.resp_val || io.ptw.resp_err) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,19 +51,21 @@ class rocketMultiplier extends Component {
|
||||
val rhs_sign = (io.mul_fn === MUL_HS) && rhs_msb
|
||||
val rhs_hi = Mux(io.dw === DW_64, io.in1(63,32), Fill(32, rhs_sign))
|
||||
val rhs_in = Cat(rhs_sign, rhs_sign, rhs_hi, io.in1(31,0))
|
||||
|
||||
val do_kill = io.mul_kill && r_cnt === UFix(0) // can only kill on 1st cycle
|
||||
|
||||
when (io.mul_val && io.mul_rdy) {
|
||||
r_val <== Bool(true)
|
||||
r_cnt <== UFix(0, log2up(cycles+1))
|
||||
r_dw <== io.dw
|
||||
r_fn <== io.mul_fn
|
||||
r_tag <== io.mul_tag
|
||||
r_lhs <== lhs_in
|
||||
r_prod<== rhs_in
|
||||
r_lsb <== Bool(false)
|
||||
r_val := Bool(true)
|
||||
r_cnt := UFix(0, log2up(cycles+1))
|
||||
r_dw := io.dw
|
||||
r_fn := io.mul_fn
|
||||
r_tag := io.mul_tag
|
||||
r_lhs := lhs_in
|
||||
r_prod:= rhs_in
|
||||
r_lsb := Bool(false)
|
||||
}
|
||||
when (io.result_val && io.result_rdy || io.mul_kill && r_cnt === UFix(0)) { // can only kill on first cycle
|
||||
r_val <== Bool(false)
|
||||
.elsewhen (io.result_val && io.result_rdy || do_kill) { // can only kill on first cycle
|
||||
r_val := Bool(false)
|
||||
}
|
||||
|
||||
val lhs_sext = Cat(r_lhs(width-2), r_lhs(width-2), r_lhs).toUFix
|
||||
@ -86,9 +88,9 @@ class rocketMultiplier extends Component {
|
||||
}
|
||||
|
||||
when (r_val && (r_cnt != UFix(cycles))) {
|
||||
r_lsb <== lsb
|
||||
r_prod <== prod
|
||||
r_cnt <== r_cnt + UFix(1)
|
||||
r_lsb := lsb
|
||||
r_prod := prod
|
||||
r_cnt := r_cnt + UFix(1)
|
||||
}
|
||||
|
||||
val mul_output64 = Mux(r_fn === MUL_LO, r_prod(63,0), r_prod(127,64))
|
||||
|
@ -197,35 +197,46 @@ class MSHR(id: Int) extends Component {
|
||||
val next_dirty = dirty || io.req_sec_val && io.req_sec_rdy && !req_load
|
||||
val sec_rdy = io.idx_match && !refilled && (dirty || !requested || req_load)
|
||||
|
||||
val rpq = (new queue(NRPQ)) { new RPQEntry() }
|
||||
// XXX why doesn't this work?
|
||||
// val rpq = (new queue(NRPQ)) { new RPQEntry() }
|
||||
val rpq_enq_bits = Cat(io.req_offset, io.req_cmd, io.req_type, io.req_sdq_id, io.req_tag)
|
||||
val rpq = (new queue(NRPQ)) { Bits(width = rpq_enq_bits.getWidth) }
|
||||
rpq.io.enq.valid := (io.req_pri_val && io.req_pri_rdy || io.req_sec_val && sec_rdy) && req_use_rpq
|
||||
rpq.io.enq.bits.offset := io.req_offset
|
||||
rpq.io.enq.bits.cmd := io.req_cmd
|
||||
rpq.io.enq.bits.typ := io.req_type
|
||||
rpq.io.enq.bits.sdq_id := io.req_sdq_id
|
||||
rpq.io.enq.bits.tag := io.req_tag
|
||||
rpq.io.enq.bits := rpq_enq_bits
|
||||
rpq.io.deq.ready := io.replay.ready && refilled
|
||||
|
||||
var rpq_deq_bits = rpq.io.deq.bits
|
||||
io.replay.bits.tag := rpq_deq_bits
|
||||
rpq_deq_bits = rpq_deq_bits >> UFix(io.req_tag.width)
|
||||
io.replay.bits.sdq_id := rpq_deq_bits.toUFix
|
||||
rpq_deq_bits = rpq_deq_bits >> UFix(io.req_sdq_id.width)
|
||||
io.replay.bits.typ := rpq_deq_bits
|
||||
rpq_deq_bits = rpq_deq_bits >> UFix(io.req_type.width)
|
||||
io.replay.bits.cmd := rpq_deq_bits
|
||||
rpq_deq_bits = rpq_deq_bits >> UFix(io.req_cmd.width)
|
||||
io.replay.bits.offset := rpq_deq_bits
|
||||
rpq_deq_bits = rpq_deq_bits >> UFix(io.req_offset.width)
|
||||
|
||||
when (io.req_pri_val && io.req_pri_rdy) {
|
||||
valid <== Bool(true)
|
||||
dirty <== !req_load
|
||||
requested <== Bool(false)
|
||||
refilled <== Bool(false)
|
||||
ppn <== io.req_ppn
|
||||
idx_ <== io.req_idx
|
||||
way_oh_ <== io.req_way_oh
|
||||
valid := Bool(true)
|
||||
dirty := !req_load
|
||||
requested := Bool(false)
|
||||
refilled := Bool(false)
|
||||
ppn := io.req_ppn
|
||||
idx_ := io.req_idx
|
||||
way_oh_ := io.req_way_oh
|
||||
}
|
||||
when (io.mem_req.valid && io.mem_req.ready) {
|
||||
requested <== Bool(true)
|
||||
}
|
||||
when (io.mem_resp_val) {
|
||||
refilled <== Bool(true)
|
||||
}
|
||||
when (io.meta_req.valid && io.meta_req.ready) {
|
||||
valid <== Bool(false)
|
||||
}
|
||||
otherwise {
|
||||
dirty <== next_dirty
|
||||
.otherwise {
|
||||
when (io.mem_req.valid && io.mem_req.ready) {
|
||||
requested := Bool(true)
|
||||
}
|
||||
when (io.mem_resp_val) {
|
||||
refilled := Bool(true)
|
||||
}
|
||||
when (io.meta_req.valid && io.meta_req.ready) {
|
||||
valid := Bool(false)
|
||||
}
|
||||
dirty := next_dirty
|
||||
}
|
||||
|
||||
io.idx_match := valid && (idx_ === io.req_idx)
|
||||
@ -251,11 +262,6 @@ class MSHR(id: Int) extends Component {
|
||||
|
||||
io.replay.valid := rpq.io.deq.valid && refilled
|
||||
io.replay.bits.idx := idx_
|
||||
io.replay.bits.tag := rpq.io.deq.bits.tag
|
||||
io.replay.bits.offset := rpq.io.deq.bits.offset
|
||||
io.replay.bits.cmd := rpq.io.deq.bits.cmd
|
||||
io.replay.bits.typ := rpq.io.deq.bits.typ
|
||||
io.replay.bits.sdq_id := rpq.io.deq.bits.sdq_id
|
||||
io.replay.bits.way_oh := way_oh_
|
||||
}
|
||||
|
||||
@ -366,10 +372,10 @@ class ReplayUnit extends Component {
|
||||
|
||||
val replay_val = Reg(resetVal = Bool(false))
|
||||
val replay_retry = replay_val && !io.data_req.ready
|
||||
replay_val <== io.replay.valid || replay_retry
|
||||
replay_val := io.replay.valid || replay_retry
|
||||
|
||||
val rp = Reg { new Replay() }
|
||||
when (io.replay.valid && io.replay.ready) { rp <== io.replay.bits }
|
||||
when (io.replay.valid && io.replay.ready) { rp := io.replay.bits }
|
||||
|
||||
val rp_amo = rp.cmd(3).toBool
|
||||
val rp_store = (rp.cmd === M_XWR)
|
||||
@ -383,13 +389,13 @@ class ReplayUnit extends Component {
|
||||
val sdq_wen = io.sdq_enq.valid && io.sdq_enq.ready
|
||||
val sdq_addr = Mux(sdq_ren_retry, rp.sdq_id, Mux(sdq_ren_new, io.replay.bits.sdq_id, sdq_alloc_id))
|
||||
|
||||
val sdq = Mem4(NSDQ, io.sdq_enq.bits)
|
||||
val sdq = Mem(NSDQ, io.sdq_enq.bits)
|
||||
sdq.setReadLatency(1);
|
||||
sdq.setTarget('inst)
|
||||
val sdq_dout = sdq.rw(sdq_addr, io.sdq_enq.bits, sdq_wen, cs = sdq_ren || sdq_wen)
|
||||
|
||||
val sdq_free = replay_val && !replay_retry && rp_write
|
||||
sdq_val <== sdq_val & ~(sdq_free.toUFix << rp.sdq_id) | (sdq_wen.toUFix << sdq_alloc_id)
|
||||
sdq_val := sdq_val & ~(sdq_free.toUFix << rp.sdq_id) | (sdq_wen.toUFix << sdq_alloc_id)
|
||||
|
||||
io.sdq_enq.ready := (~sdq_val != UFix(0)) && !sdq_ren
|
||||
io.sdq_id := sdq_alloc_id
|
||||
@ -433,9 +439,9 @@ class WritebackUnit extends Component {
|
||||
wbq.io.enq.bits := io.data_resp
|
||||
wbq.io.deq.ready := io.mem_req.ready && !refill_val && (cnt === UFix(REFILL_CYCLES))
|
||||
|
||||
when (io.req.valid && io.req.ready) { valid <== Bool(true); cnt <== UFix(0); addr <== io.req.bits }
|
||||
when (io.data_req.valid && io.data_req.ready) { cnt <== cnt + UFix(1) }
|
||||
when ((cnt === UFix(REFILL_CYCLES)) && !wbq.io.deq.valid) { valid <== Bool(false) }
|
||||
when (io.data_req.valid && io.data_req.ready) { cnt := cnt + UFix(1) }
|
||||
when ((cnt === UFix(REFILL_CYCLES)) && !wbq.io.deq.valid) { valid := Bool(false) }
|
||||
when (io.req.valid && io.req.ready) { valid := Bool(true); cnt := UFix(0); addr := io.req.bits }
|
||||
|
||||
io.req.ready := !valid
|
||||
io.data_req.valid := valid && (cnt < UFix(REFILL_CYCLES))
|
||||
@ -474,22 +480,22 @@ class FlushUnit(lines: Int) extends Component {
|
||||
switch (state) {
|
||||
is(s_reset) {
|
||||
when (io.meta_req.ready) {
|
||||
state <== Mux(~way_cnt === UFix(0) && ~idx_cnt === UFix(0), s_ready, s_reset);
|
||||
when (~way_cnt === UFix(0)) { idx_cnt <== next_idx_cnt };
|
||||
way_cnt <== next_way_cnt;
|
||||
state := Mux(~way_cnt === UFix(0) && ~idx_cnt === UFix(0), s_ready, s_reset);
|
||||
when (~way_cnt === UFix(0)) { idx_cnt := next_idx_cnt };
|
||||
way_cnt := next_way_cnt;
|
||||
}
|
||||
}
|
||||
is(s_ready) { when (io.req.valid) { state <== s_meta_read; tag <== io.req.bits } }
|
||||
is(s_meta_read) { when (io.meta_req.ready) { state <== s_meta_wait } }
|
||||
is(s_meta_wait) { state <== Mux(io.meta_resp.valid && io.meta_resp.dirty && !io.wb_req.ready, s_meta_read, s_meta_write) }
|
||||
is(s_ready) { when (io.req.valid) { state := s_meta_read; tag := io.req.bits } }
|
||||
is(s_meta_read) { when (io.meta_req.ready) { state := s_meta_wait } }
|
||||
is(s_meta_wait) { state := Mux(io.meta_resp.valid && io.meta_resp.dirty && !io.wb_req.ready, s_meta_read, s_meta_write) }
|
||||
is(s_meta_write) {
|
||||
when (io.meta_req.ready) {
|
||||
state <== Mux(~way_cnt === UFix(0) && ~idx_cnt === UFix(0), s_done, s_meta_read);
|
||||
when (~way_cnt === UFix(0)) { idx_cnt <== next_idx_cnt };
|
||||
way_cnt <== next_way_cnt;
|
||||
state := Mux(~way_cnt === UFix(0) && ~idx_cnt === UFix(0), s_done, s_meta_read);
|
||||
when (~way_cnt === UFix(0)) { idx_cnt := next_idx_cnt };
|
||||
way_cnt := next_way_cnt;
|
||||
}
|
||||
}
|
||||
is(s_done) { when (io.resp.ready) { state <== s_ready } }
|
||||
is(s_done) { when (io.resp.ready) { state := s_ready } }
|
||||
}
|
||||
|
||||
io.req.ready := state === s_ready
|
||||
@ -515,7 +521,7 @@ class MetaDataArray(lines: Int) extends Component {
|
||||
val state_req = (new ioDecoupled) { new MetaArrayReq() }
|
||||
}
|
||||
|
||||
val vd_array = Mem4(lines, Bits(width = 2))
|
||||
val vd_array = Mem(lines, Bits(width = 2))
|
||||
vd_array.setReadLatency(1);
|
||||
val vd_wdata2 = Cat(io.state_req.bits.data.valid, io.state_req.bits.data.dirty)
|
||||
vd_array.write(io.state_req.bits.idx, vd_wdata2, io.state_req.valid && io.state_req.bits.rw)
|
||||
@ -526,7 +532,7 @@ class MetaDataArray(lines: Int) extends Component {
|
||||
// this could be eliminated if the read port were combinational.
|
||||
val vd_conflict = io.state_req.valid && (io.req.bits.idx === io.state_req.bits.idx)
|
||||
|
||||
val tag_array = Mem4(lines, io.resp.tag)
|
||||
val tag_array = Mem(lines, io.resp.tag)
|
||||
tag_array.setReadLatency(1);
|
||||
tag_array.setTarget('inst)
|
||||
val tag_rdata = tag_array.rw(io.req.bits.idx, io.req.bits.data.tag, io.req.valid && io.req.bits.rw, cs = io.req.valid)
|
||||
@ -547,7 +553,7 @@ class MetaDataArrayArray(lines: Int) extends Component {
|
||||
|
||||
val way_en_ = Reg { Bits(width=NWAYS) }
|
||||
when (io.req.valid && io.req.ready) {
|
||||
way_en_ <== io.req.bits.way_en
|
||||
way_en_ := io.req.bits.way_en
|
||||
}
|
||||
|
||||
var tag_ready = Bool(true)
|
||||
@ -576,7 +582,7 @@ class DataArray(lines: Int) extends Component {
|
||||
|
||||
val wmask = FillInterleaved(8, io.req.bits.wmask)
|
||||
|
||||
val array = Mem4(lines*REFILL_CYCLES, io.resp)
|
||||
val array = Mem(lines*REFILL_CYCLES, io.resp)
|
||||
array.setReadLatency(1);
|
||||
array.setTarget('inst)
|
||||
val addr = Cat(io.req.bits.idx, io.req.bits.offset)
|
||||
@ -594,7 +600,7 @@ class DataArrayArray(lines: Int) extends Component {
|
||||
|
||||
val way_en_ = Reg { Bits(width=NWAYS) }
|
||||
when (io.req.valid && io.req.ready) {
|
||||
way_en_ <== io.req.bits.way_en
|
||||
way_en_ := io.req.bits.way_en
|
||||
}
|
||||
|
||||
//val data_ready_arr = Vec(NWAYS){ Bool() }
|
||||
@ -694,26 +700,26 @@ class HellaCacheDM extends Component {
|
||||
val replayer = new ReplayUnit()
|
||||
val replay_amo_val = replayer.io.data_req.valid && replayer.io.data_req.bits.cmd(3).toBool
|
||||
|
||||
when (replay_amo_val) {
|
||||
r_cpu_req_idx <== Cat(replayer.io.data_req.bits.idx, replayer.io.data_req.bits.offset)
|
||||
r_cpu_req_cmd <== replayer.io.data_req.bits.cmd
|
||||
r_cpu_req_type <== replayer.io.data_req.bits.typ
|
||||
r_cpu_req_data <== replayer.io.data_req.bits.data
|
||||
}
|
||||
when (io.cpu.req_val) {
|
||||
r_cpu_req_idx <== io.cpu.req_idx
|
||||
r_cpu_req_cmd <== io.cpu.req_cmd
|
||||
r_cpu_req_type <== io.cpu.req_type
|
||||
r_cpu_req_tag <== io.cpu.req_tag
|
||||
r_cpu_req_idx := io.cpu.req_idx
|
||||
r_cpu_req_cmd := io.cpu.req_cmd
|
||||
r_cpu_req_type := io.cpu.req_type
|
||||
r_cpu_req_tag := io.cpu.req_tag
|
||||
when (req_write) {
|
||||
r_cpu_req_data <== io.cpu.req_data
|
||||
r_cpu_req_data := io.cpu.req_data
|
||||
}
|
||||
}
|
||||
when (replay_amo_val) {
|
||||
r_cpu_req_idx := Cat(replayer.io.data_req.bits.idx, replayer.io.data_req.bits.offset)
|
||||
r_cpu_req_cmd := replayer.io.data_req.bits.cmd
|
||||
r_cpu_req_type := replayer.io.data_req.bits.typ
|
||||
r_cpu_req_data := replayer.io.data_req.bits.data
|
||||
}
|
||||
|
||||
// refill counter
|
||||
val rr_count = Reg(resetVal = UFix(0, log2up(REFILL_CYCLES)))
|
||||
val rr_count_next = rr_count + UFix(1)
|
||||
when (io.mem.resp_val) { rr_count <== rr_count_next }
|
||||
when (io.mem.resp_val) { rr_count := rr_count_next }
|
||||
|
||||
val misaligned =
|
||||
(((r_cpu_req_type === MT_H) || (r_cpu_req_type === MT_HU)) && (r_cpu_req_idx(0) != Bits(0))) ||
|
||||
@ -788,7 +794,7 @@ class HellaCacheDM extends Component {
|
||||
val drain_store = drain_store_val && data_arb.io.in(2).ready
|
||||
val p_store_rdy = !p_store_valid || drain_store
|
||||
val p_amo = Reg(tag_hit && r_req_amo && p_store_rdy && !p_store_match || r_replay_amo, resetVal = Bool(false))
|
||||
p_store_valid <== !p_store_rdy || (tag_hit && r_req_store) || p_amo
|
||||
p_store_valid := !p_store_rdy || (tag_hit && r_req_store) || p_amo
|
||||
|
||||
// writeback
|
||||
val wb_rdy = wb_arb.io.in(1).ready && !p_store_idx_match
|
||||
@ -811,14 +817,14 @@ class HellaCacheDM extends Component {
|
||||
val amoalu = new AMOALU
|
||||
storegen.io.typ := r_cpu_req_type
|
||||
storegen.io.din := r_cpu_req_data
|
||||
when (p_amo) {
|
||||
p_store_data <== amoalu.io.out
|
||||
}
|
||||
when (tag_hit && r_req_write && p_store_rdy || r_replay_amo) {
|
||||
p_store_idx <== r_cpu_req_idx
|
||||
p_store_type <== r_cpu_req_type
|
||||
p_store_cmd <== r_cpu_req_cmd
|
||||
p_store_data <== storegen.io.dout
|
||||
p_store_idx := r_cpu_req_idx
|
||||
p_store_type := r_cpu_req_type
|
||||
p_store_cmd := r_cpu_req_cmd
|
||||
p_store_data := storegen.io.dout
|
||||
}
|
||||
when (p_amo) {
|
||||
p_store_data := amoalu.io.out
|
||||
}
|
||||
|
||||
// miss handling
|
||||
@ -852,7 +858,7 @@ class HellaCacheDM extends Component {
|
||||
data_arb.io.in(1).bits.rw := replay.cmd === M_XWR
|
||||
data_arb.io.in(1).valid := replay_val
|
||||
replayer.io.data_req.ready := replay_rdy && !stall_replay
|
||||
r_replay_amo <== replay_amo_val && replay_rdy && !stall_replay
|
||||
r_replay_amo := replay_amo_val && replay_rdy && !stall_replay
|
||||
|
||||
// store write mask generation.
|
||||
// assumes store replays are higher-priority than pending stores.
|
||||
@ -881,13 +887,13 @@ class HellaCacheDM extends Component {
|
||||
amoalu.io.lhs := loadgen.io.r_dout.toUFix
|
||||
amoalu.io.rhs := p_store_data.toUFix
|
||||
|
||||
early_nack <== early_tag_nack || early_load_nack || r_cpu_req_val && r_req_amo || replay_amo_val || r_replay_amo
|
||||
early_nack := early_tag_nack || early_load_nack || r_cpu_req_val && r_req_amo || replay_amo_val || r_replay_amo
|
||||
|
||||
// reset and flush unit
|
||||
val flusher = new FlushUnit(lines)
|
||||
val flushed = Reg(resetVal = Bool(true))
|
||||
val flush_rdy = mshr.io.fence_rdy && wb_rdy && !p_store_valid
|
||||
flushed <== flushed && !r_cpu_req_val || r_cpu_req_val && r_req_flush && flush_rdy && flusher.io.req.ready
|
||||
flushed := flushed && !r_cpu_req_val || r_cpu_req_val && r_req_flush && flush_rdy && flusher.io.req.ready
|
||||
flusher.io.req.valid := r_cpu_req_val && r_req_flush && flush_rdy && !flushed
|
||||
flusher.io.wb_req <> wb_arb.io.in(0)
|
||||
flusher.io.meta_req.bits.inner_req <> meta_arb.io.in(0).bits
|
||||
@ -899,7 +905,7 @@ class HellaCacheDM extends Component {
|
||||
// we usually nack rather than reporting that the cache is not ready.
|
||||
// fences and flushes are the exceptions.
|
||||
val pending_fence = Reg(resetVal = Bool(false))
|
||||
pending_fence <== (r_cpu_req_val && r_req_fence || pending_fence) && !flush_rdy
|
||||
pending_fence := (r_cpu_req_val && r_req_fence || pending_fence) && !flush_rdy
|
||||
val nack_hit = p_store_match || r_req_write && !p_store_rdy
|
||||
val nack_miss = dirty && !wb_rdy || !mshr.io.req_rdy || r_req_write && !replayer.io.sdq_enq.ready
|
||||
val nack_flush = !flush_rdy && (r_req_fence || r_req_flush) ||
|
||||
@ -974,26 +980,26 @@ class HellaCacheAssoc extends Component {
|
||||
val replayer = new ReplayUnit()
|
||||
val replay_amo_val = replayer.io.data_req.valid && replayer.io.data_req.bits.cmd(3).toBool
|
||||
|
||||
when (replay_amo_val) {
|
||||
r_cpu_req_idx <== Cat(replayer.io.data_req.bits.idx, replayer.io.data_req.bits.offset)
|
||||
r_cpu_req_cmd <== replayer.io.data_req.bits.cmd
|
||||
r_cpu_req_type <== replayer.io.data_req.bits.typ
|
||||
r_cpu_req_data <== replayer.io.data_req.bits.data
|
||||
}
|
||||
when (io.cpu.req_val) {
|
||||
r_cpu_req_idx <== io.cpu.req_idx
|
||||
r_cpu_req_cmd <== io.cpu.req_cmd
|
||||
r_cpu_req_type <== io.cpu.req_type
|
||||
r_cpu_req_tag <== io.cpu.req_tag
|
||||
r_cpu_req_idx := io.cpu.req_idx
|
||||
r_cpu_req_cmd := io.cpu.req_cmd
|
||||
r_cpu_req_type := io.cpu.req_type
|
||||
r_cpu_req_tag := io.cpu.req_tag
|
||||
when (req_write) {
|
||||
r_cpu_req_data <== io.cpu.req_data
|
||||
r_cpu_req_data := io.cpu.req_data
|
||||
}
|
||||
}
|
||||
when (replay_amo_val) {
|
||||
r_cpu_req_idx := Cat(replayer.io.data_req.bits.idx, replayer.io.data_req.bits.offset)
|
||||
r_cpu_req_cmd := replayer.io.data_req.bits.cmd
|
||||
r_cpu_req_type := replayer.io.data_req.bits.typ
|
||||
r_cpu_req_data := replayer.io.data_req.bits.data
|
||||
}
|
||||
|
||||
// refill counter
|
||||
val rr_count = Reg(resetVal = UFix(0, log2up(REFILL_CYCLES)))
|
||||
val rr_count_next = rr_count + UFix(1)
|
||||
when (io.mem.resp_val) { rr_count <== rr_count_next }
|
||||
when (io.mem.resp_val) { rr_count := rr_count_next }
|
||||
|
||||
val misaligned =
|
||||
(((r_cpu_req_type === MT_H) || (r_cpu_req_type === MT_HU)) && (r_cpu_req_idx(0) != Bits(0))) ||
|
||||
@ -1081,7 +1087,7 @@ class HellaCacheAssoc extends Component {
|
||||
val drain_store = drain_store_val && data_arb.io.in(2).ready
|
||||
val p_store_rdy = !p_store_valid || drain_store
|
||||
val p_amo = Reg(tag_hit && r_req_amo && p_store_rdy && !p_store_match || r_replay_amo, resetVal = Bool(false))
|
||||
p_store_valid <== !p_store_rdy || (tag_hit && r_req_store) || p_amo
|
||||
p_store_valid := !p_store_rdy || (tag_hit && r_req_store) || p_amo
|
||||
|
||||
// writeback
|
||||
val wb_rdy = wb_arb.io.in(1).ready && !p_store_idx_match
|
||||
@ -1105,15 +1111,15 @@ class HellaCacheAssoc extends Component {
|
||||
val amoalu = new AMOALU
|
||||
storegen.io.typ := r_cpu_req_type
|
||||
storegen.io.din := r_cpu_req_data
|
||||
when (p_amo) {
|
||||
p_store_data <== amoalu.io.out
|
||||
}
|
||||
when (tag_hit && r_req_write && p_store_rdy || r_replay_amo) {
|
||||
p_store_idx <== r_cpu_req_idx
|
||||
p_store_type <== r_cpu_req_type
|
||||
p_store_cmd <== r_cpu_req_cmd
|
||||
p_store_way_oh <== Mux(r_replay_amo, replayer.io.way_oh, hit_way_oh)
|
||||
p_store_data <== storegen.io.dout
|
||||
p_store_idx := r_cpu_req_idx
|
||||
p_store_type := r_cpu_req_type
|
||||
p_store_cmd := r_cpu_req_cmd
|
||||
p_store_way_oh := Mux(r_replay_amo, replayer.io.way_oh, hit_way_oh)
|
||||
p_store_data := storegen.io.dout
|
||||
}
|
||||
when (p_amo) {
|
||||
p_store_data := amoalu.io.out
|
||||
}
|
||||
|
||||
// miss handling
|
||||
@ -1149,7 +1155,7 @@ class HellaCacheAssoc extends Component {
|
||||
data_arb.io.in(1).valid := replay_val
|
||||
data_arb.io.in(1).bits.way_en := replayer.io.way_oh
|
||||
replayer.io.data_req.ready := replay_rdy && !stall_replay
|
||||
r_replay_amo <== replay_amo_val && replay_rdy && !stall_replay
|
||||
r_replay_amo := replay_amo_val && replay_rdy && !stall_replay
|
||||
|
||||
// store write mask generation.
|
||||
// assumes store replays are higher-priority than pending stores.
|
||||
@ -1178,13 +1184,13 @@ class HellaCacheAssoc extends Component {
|
||||
amoalu.io.lhs := loadgen.io.r_dout.toUFix
|
||||
amoalu.io.rhs := p_store_data.toUFix
|
||||
|
||||
early_nack <== early_tag_nack || early_load_nack || r_cpu_req_val && r_req_amo || replay_amo_val || r_replay_amo
|
||||
early_nack := early_tag_nack || early_load_nack || r_cpu_req_val && r_req_amo || replay_amo_val || r_replay_amo
|
||||
|
||||
// reset and flush unit
|
||||
val flusher = new FlushUnit(lines)
|
||||
val flushed = Reg(resetVal = Bool(true))
|
||||
val flush_rdy = mshr.io.fence_rdy && wb_rdy && !p_store_valid
|
||||
flushed <== flushed && !r_cpu_req_val || r_cpu_req_val && r_req_flush && flush_rdy && flusher.io.req.ready
|
||||
flushed := flushed && !r_cpu_req_val || r_cpu_req_val && r_req_flush && flush_rdy && flusher.io.req.ready
|
||||
flusher.io.req.valid := r_cpu_req_val && r_req_flush && flush_rdy && !flushed
|
||||
flusher.io.wb_req <> wb_arb.io.in(0)
|
||||
flusher.io.meta_req <> meta_arb.io.in(0)
|
||||
@ -1194,7 +1200,7 @@ class HellaCacheAssoc extends Component {
|
||||
// we usually nack rather than reporting that the cache is not ready.
|
||||
// fences and flushes are the exceptions.
|
||||
val pending_fence = Reg(resetVal = Bool(false))
|
||||
pending_fence <== (r_cpu_req_val && r_req_fence || pending_fence) && !flush_rdy
|
||||
pending_fence := (r_cpu_req_val && r_req_fence || pending_fence) && !flush_rdy
|
||||
val nack_hit = p_store_match || r_req_write && !p_store_rdy
|
||||
val nack_miss = dirty && !wb_rdy || !mshr.io.req_rdy || r_req_write && !replayer.io.sdq_enq.ready
|
||||
val nack_flush = !flush_rdy && (r_req_fence || r_req_flush) ||
|
||||
|
@ -77,22 +77,22 @@ class rocketPTW extends Component
|
||||
val req_itlb_val = io.itlb.req_val;
|
||||
val req_dtlb_val = io.dtlb.req_val && !io.itlb.req_val;
|
||||
|
||||
when ((state === s_ready) && req_itlb_val) {
|
||||
r_req_vpn <== io.itlb.req_vpn;
|
||||
r_req_dest <== Bool(false);
|
||||
req_addr <== Cat(io.ptbr(PADDR_BITS-1,PGIDX_BITS), io.itlb.req_vpn(VPN_BITS-1,VPN_BITS-10), Bits(0,3)).toUFix;
|
||||
when ((state === s_ready) && req_dtlb_val) {
|
||||
r_req_vpn := io.dtlb.req_vpn;
|
||||
r_req_dest := Bool(true);
|
||||
req_addr := Cat(io.ptbr(PADDR_BITS-1,PGIDX_BITS), io.dtlb.req_vpn(VPN_BITS-1,VPN_BITS-10), Bits(0,3)).toUFix;
|
||||
}
|
||||
|
||||
when ((state === s_ready) && req_dtlb_val) {
|
||||
r_req_vpn <== io.dtlb.req_vpn;
|
||||
r_req_dest <== Bool(true);
|
||||
req_addr <== Cat(io.ptbr(PADDR_BITS-1,PGIDX_BITS), io.dtlb.req_vpn(VPN_BITS-1,VPN_BITS-10), Bits(0,3)).toUFix;
|
||||
when ((state === s_ready) && req_itlb_val) {
|
||||
r_req_vpn := io.itlb.req_vpn;
|
||||
r_req_dest := Bool(false);
|
||||
req_addr := Cat(io.ptbr(PADDR_BITS-1,PGIDX_BITS), io.itlb.req_vpn(VPN_BITS-1,VPN_BITS-10), Bits(0,3)).toUFix;
|
||||
}
|
||||
|
||||
when (io.dmem.resp_val) {
|
||||
req_addr <== Cat(io.dmem.resp_data(PADDR_BITS-1, PGIDX_BITS), vpn_idx, Bits(0,3)).toUFix;
|
||||
r_resp_perm <== io.dmem.resp_data(9,4);
|
||||
r_resp_ppn <== io.dmem.resp_data(PADDR_BITS-1, PGIDX_BITS);
|
||||
req_addr := Cat(io.dmem.resp_data(PADDR_BITS-1, PGIDX_BITS), vpn_idx, Bits(0,3)).toUFix;
|
||||
r_resp_perm := io.dmem.resp_data(9,4);
|
||||
r_resp_ppn := io.dmem.resp_data(PADDR_BITS-1, PGIDX_BITS);
|
||||
}
|
||||
|
||||
io.dmem.req_val :=
|
||||
@ -133,83 +133,83 @@ class rocketPTW extends Component
|
||||
switch (state) {
|
||||
is (s_ready) {
|
||||
when (req_val) {
|
||||
state <== s_l1_req;
|
||||
state := s_l1_req;
|
||||
}
|
||||
}
|
||||
// level 1
|
||||
is (s_l1_req) {
|
||||
when (io.dmem.req_rdy) {
|
||||
state <== s_l1_wait;
|
||||
state := s_l1_wait;
|
||||
}
|
||||
}
|
||||
is (s_l1_wait) {
|
||||
when (io.dmem.resp_nack) {
|
||||
state <== s_l1_req
|
||||
state := s_l1_req
|
||||
}
|
||||
when (io.dmem.resp_val) {
|
||||
when (resp_ptd) { // page table descriptor
|
||||
state <== s_l2_req;
|
||||
state := s_l2_req;
|
||||
}
|
||||
when (resp_pte) { // page table entry
|
||||
state <== s_l1_fake;
|
||||
.elsewhen (resp_pte) { // page table entry
|
||||
state := s_l1_fake;
|
||||
}
|
||||
otherwise {
|
||||
state <== s_error;
|
||||
.otherwise {
|
||||
state := s_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
is (s_l1_fake) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
// level 2
|
||||
is (s_l2_req) {
|
||||
when (io.dmem.req_rdy) {
|
||||
state <== s_l2_wait;
|
||||
state := s_l2_wait;
|
||||
}
|
||||
}
|
||||
is (s_l2_wait) {
|
||||
when (io.dmem.resp_nack) {
|
||||
state <== s_l2_req
|
||||
state := s_l2_req
|
||||
}
|
||||
when (io.dmem.resp_val) {
|
||||
when (resp_ptd) { // page table descriptor
|
||||
state <== s_l3_req;
|
||||
state := s_l3_req;
|
||||
}
|
||||
when (resp_pte) { // page table entry
|
||||
state <== s_l2_fake;
|
||||
.elsewhen (resp_pte) { // page table entry
|
||||
state := s_l2_fake;
|
||||
}
|
||||
otherwise {
|
||||
state <== s_error;
|
||||
.otherwise {
|
||||
state := s_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
is (s_l2_fake) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
// level 3
|
||||
is (s_l3_req) {
|
||||
when (io.dmem.req_rdy) {
|
||||
state <== s_l3_wait;
|
||||
state := s_l3_wait;
|
||||
}
|
||||
}
|
||||
is (s_l3_wait) {
|
||||
when (io.dmem.resp_nack) {
|
||||
state <== s_l3_req
|
||||
state := s_l3_req
|
||||
}
|
||||
when (io.dmem.resp_val) {
|
||||
when (resp_pte) { // page table entry
|
||||
state <== s_done;
|
||||
state := s_done;
|
||||
}
|
||||
otherwise {
|
||||
state <== s_error;
|
||||
.otherwise {
|
||||
state := s_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
is (s_done) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
is (s_error) {
|
||||
state <== s_ready;
|
||||
state := s_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,22 +24,22 @@ class queue[T <: Data](entries: Int, flushable: Boolean = false)(data: => T) ext
|
||||
val do_enq = io.enq.ready && io.enq.valid
|
||||
val do_deq = io.deq.ready && io.deq.valid
|
||||
|
||||
if (flushable) {
|
||||
when (io.flush) {
|
||||
deq_ptr <== UFix(0)
|
||||
enq_ptr <== UFix(0)
|
||||
maybe_full <== Bool(false)
|
||||
}
|
||||
}
|
||||
when (do_deq) {
|
||||
deq_ptr <== deq_ptr + UFix(1)
|
||||
deq_ptr := deq_ptr + UFix(1)
|
||||
}
|
||||
when (do_enq) {
|
||||
enq_ptr <== enq_ptr + UFix(1)
|
||||
enq_ptr := enq_ptr + UFix(1)
|
||||
}
|
||||
when (do_enq != do_deq) {
|
||||
maybe_full <== do_enq
|
||||
maybe_full := do_enq
|
||||
}
|
||||
if (flushable) {
|
||||
when (io.flush) {
|
||||
deq_ptr := UFix(0)
|
||||
enq_ptr := UFix(0)
|
||||
maybe_full := Bool(false)
|
||||
}
|
||||
}
|
||||
|
||||
Mem(entries, do_enq, enq_ptr, io.enq.bits).read(deq_ptr) <> io.deq.bits
|
||||
io.deq.bits <> Mem(entries, do_enq, enq_ptr, io.enq.bits).read(deq_ptr)
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ object LFSR16
|
||||
{
|
||||
val width = 16
|
||||
val lfsr = Reg(resetVal = UFix(1, width))
|
||||
when (increment) { lfsr <== Cat(lfsr(0)^lfsr(2)^lfsr(3)^lfsr(5), lfsr(width-1,1)).toUFix }
|
||||
when (increment) { lfsr := Cat(lfsr(0)^lfsr(2)^lfsr(3)^lfsr(5), lfsr(width-1,1)).toUFix }
|
||||
lfsr
|
||||
}
|
||||
}
|
||||
@ -176,13 +176,13 @@ class priorityDecoder(width: Int) extends Component
|
||||
val io = new ioPriorityEncoder(in_width, width);
|
||||
val l_out = Wire() { Bits() };
|
||||
|
||||
for (i <- 0 to width-1) {
|
||||
l_out := Bits(0, width);
|
||||
for (i <- width-1 to 0 by -1) {
|
||||
when (io.in === UFix(i, in_width)) {
|
||||
l_out <== Bits(1,1) << UFix(i);
|
||||
l_out := Bits(1,1) << UFix(i);
|
||||
}
|
||||
}
|
||||
|
||||
l_out <== Bits(0, width);
|
||||
io.out := l_out;
|
||||
}
|
||||
|
||||
@ -198,13 +198,13 @@ class priorityEncoder(width: Int) extends Component
|
||||
val io = new ioPriorityDecoder(width, out_width);
|
||||
val l_out = Wire() { UFix() };
|
||||
|
||||
for (i <- 0 to width-1) {
|
||||
l_out := UFix(0, out_width);
|
||||
for (i <- width-1 to 1 by -1) {
|
||||
when (io.in(i).toBool) {
|
||||
l_out <== UFix(i, out_width);
|
||||
l_out := UFix(i, out_width);
|
||||
}
|
||||
}
|
||||
|
||||
l_out <== UFix(0, out_width);
|
||||
io.out := l_out;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user