From f1c355e3cdcda715cd1bf26caa213498484977e1 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 24 Jan 2012 00:15:17 -0800 Subject: [PATCH] check pc/effective address sign extension --- rocket/src/main/scala/cpu.scala | 4 +-- rocket/src/main/scala/dpath.scala | 36 +++++++++++++------------- rocket/src/main/scala/dpath_util.scala | 13 +++++----- rocket/src/main/scala/dtlb.scala | 13 ++++++---- rocket/src/main/scala/itlb.scala | 17 ++++++------ 5 files changed, 43 insertions(+), 40 deletions(-) diff --git a/rocket/src/main/scala/cpu.scala b/rocket/src/main/scala/cpu.scala index e8a99954..70fd9b56 100644 --- a/rocket/src/main/scala/cpu.scala +++ b/rocket/src/main/scala/cpu.scala @@ -55,7 +55,7 @@ class rocketProc extends Component itlb.io.cpu.status := dpath.io.ctrl.status; itlb.io.cpu.req_val := ctrl.io.imem.req_val; itlb.io.cpu.req_asid := Bits(0,ASID_BITS); // FIXME: connect to PCR - itlb.io.cpu.req_vpn := dpath.io.imem.req_addr(VADDR_BITS-1,PGIDX_BITS); + itlb.io.cpu.req_vpn := dpath.io.imem.req_addr(VADDR_BITS,PGIDX_BITS); io.imem.req_idx := dpath.io.imem.req_addr(PGIDX_BITS-1,0); io.imem.req_ppn := itlb.io.cpu.resp_ppn; io.imem.req_val := ctrl.io.imem.req_val; @@ -72,7 +72,7 @@ class rocketProc extends Component dtlb.io.cpu.req_kill := ctrl.io.dtlb_kill; dtlb.io.cpu.req_cmd := ctrl.io.dmem.req_cmd; dtlb.io.cpu.req_asid := Bits(0,ASID_BITS); // FIXME: connect to PCR - dtlb.io.cpu.req_vpn := dpath.io.dmem.req_addr(VADDR_BITS-1,PGIDX_BITS); + dtlb.io.cpu.req_vpn := dpath.io.dmem.req_addr(VADDR_BITS,PGIDX_BITS); ctrl.io.xcpt_dtlb_ld := dtlb.io.cpu.xcpt_ld; ctrl.io.xcpt_dtlb_st := dtlb.io.cpu.xcpt_st; ctrl.io.dtlb_rdy := dtlb.io.cpu.req_rdy; diff --git a/rocket/src/main/scala/dpath.scala b/rocket/src/main/scala/dpath.scala index 06b38a0d..a19d0fd7 100644 --- a/rocket/src/main/scala/dpath.scala +++ b/rocket/src/main/scala/dpath.scala @@ -7,7 +7,7 @@ import Instructions._ class ioDpathDmem extends Bundle() { - val req_addr = UFix(VADDR_BITS, OUTPUT); + val req_addr = UFix(VADDR_BITS+1, OUTPUT); val req_tag = UFix(CPU_TAG_BITS, OUTPUT); val req_data = Bits(64, OUTPUT); val resp_val = Bool(INPUT); @@ -20,7 +20,7 @@ class ioDpathDmem extends Bundle() class ioDpathImem extends Bundle() { - val req_addr = UFix(VADDR_BITS, OUTPUT); + val req_addr = UFix(VADDR_BITS+1, OUTPUT); val resp_data = Bits(32, INPUT); } @@ -50,7 +50,6 @@ class rocketDpath extends Component val alu = new rocketDpathALU(); val ex_alu_out = alu.io.out; val ex_alu_adder_out = alu.io.adder_out; - val ex_jr_target = ex_alu_adder_out(VADDR_BITS-1,0); val div = new rocketDivider(64); val div_result = div.io.div_result_bits; @@ -65,13 +64,13 @@ class rocketDpath extends Component val rfile = new rocketDpathRegfile(); // instruction fetch definitions - val if_reg_pc = Reg(resetVal = UFix(START_ADDR,VADDR_BITS)); + val if_reg_pc = Reg(resetVal = UFix(START_ADDR,VADDR_BITS+1)); // instruction decode definitions val id_reg_valid = Reg(resetVal = Bool(false)); val id_reg_inst = Reg(resetVal = NOP); - val id_reg_pc = Reg() { UFix() }; - val id_reg_pc_plus4 = Reg() { UFix() }; + val id_reg_pc = Reg() { UFix(width = VADDR_BITS+1) }; + val id_reg_pc_plus4 = Reg() { UFix(width = VADDR_BITS+1) }; // execute definitions val ex_reg_valid = Reg(resetVal = Bool(false)); @@ -133,21 +132,23 @@ class rocketDpath extends Component Cat(Fill(52, ex_reg_inst(31)), ex_reg_inst(31,27), ex_reg_inst(16,10)); val branch_adder_rhs = - Mux(io.ctrl.ex_jmp, Cat(Fill(VADDR_BITS-26, ex_reg_inst(31)), ex_reg_inst(31,7), UFix(0,1)), - Cat(ex_sign_extend_split(VADDR_BITS-2,0), UFix(0, 1))); - + Mux(io.ctrl.ex_jmp, Cat(Fill(VADDR_BITS-25, ex_reg_inst(31)), ex_reg_inst(31,7), UFix(0,1)), + Cat(ex_sign_extend_split(VADDR_BITS-1,0), UFix(0, 1))); val ex_branch_target = ex_reg_pc + branch_adder_rhs.toUFix; - val jr_br_target = Mux(io.ctrl.ex_jr, ex_jr_target, ex_branch_target); + val ex_jr_target_sign = Mux(ex_alu_adder_out(VADDR_BITS-1), ~ex_alu_adder_out(63,VADDR_BITS) === UFix(0), ex_alu_adder_out(63,VADDR_BITS) != UFix(0)) + val ex_jr_target_extended = Cat(ex_jr_target_sign, ex_alu_adder_out(VADDR_BITS-1,0)).toUFix + + val jr_br_target = Mux(io.ctrl.ex_jr, ex_jr_target_extended, ex_branch_target); btb.io.correct_target := jr_br_target val if_next_pc = - Mux(io.ctrl.sel_pc === PC_BTB, if_btb_target, + Mux(io.ctrl.sel_pc === PC_BTB, Cat(if_btb_target(VADDR_BITS-1), if_btb_target), Mux(io.ctrl.sel_pc === PC_EX4, ex_reg_pc_plus4, Mux(io.ctrl.sel_pc === PC_BR, ex_branch_target, - Mux(io.ctrl.sel_pc === PC_JR, ex_jr_target.toUFix, - Mux(io.ctrl.sel_pc === PC_PCR, wb_reg_wdata(VADDR_BITS-1,0), // only used for ERET - Mux(io.ctrl.sel_pc === PC_EVEC, pcr.io.evec, + Mux(io.ctrl.sel_pc === PC_JR, ex_jr_target_extended, + Mux(io.ctrl.sel_pc === PC_PCR, wb_reg_wdata(VADDR_BITS,0), // only used for ERET + Mux(io.ctrl.sel_pc === PC_EVEC, Cat(pcr.io.evec(VADDR_BITS-1), pcr.io.evec), Mux(io.ctrl.sel_pc === PC_WB, wb_reg_pc, if_pc_plus4))))))); // PC_4 @@ -155,8 +156,7 @@ class rocketDpath extends Component if_reg_pc <== if_next_pc.toUFix; } - // FIXME: make sure PCs are properly sign extended - io.ctrl.xcpt_ma_inst := if_next_pc(1,0) != Bits(0,2) + io.ctrl.xcpt_ma_inst := if_next_pc(1,0) != Bits(0) io.imem.req_addr := Mux(io.ctrl.stallf, if_reg_pc, @@ -172,7 +172,7 @@ class rocketDpath extends Component // instruction decode stage when (!io.ctrl.stalld) { id_reg_pc <== if_reg_pc; - id_reg_pc_plus4 <== if_pc_plus4; + id_reg_pc_plus4 <== if_pc_plus4; when(io.ctrl.killf) { id_reg_inst <== NOP; id_reg_valid <== Bool(false); @@ -314,7 +314,7 @@ class rocketDpath extends Component // D$ request interface (registered inside D$ module) // other signals (req_val, req_rdy) connect to control module - io.dmem.req_addr := ex_alu_adder_out(VADDR_BITS-1,0); + io.dmem.req_addr := ex_jr_target_extended.toUFix; io.dmem.req_data := ex_reg_rs2; io.dmem.req_tag := ex_reg_waddr; diff --git a/rocket/src/main/scala/dpath_util.scala b/rocket/src/main/scala/dpath_util.scala index 17a8b39f..e12d6d5d 100644 --- a/rocket/src/main/scala/dpath_util.scala +++ b/rocket/src/main/scala/dpath_util.scala @@ -53,7 +53,7 @@ class ioDpathPCR extends Bundle() val exception = Bool(INPUT); val cause = UFix(5, INPUT); val badvaddr_wen = Bool(INPUT); - val pc = UFix(VADDR_BITS, INPUT); + val pc = UFix(VADDR_BITS+1, INPUT); val eret = Bool(INPUT); val ei = Bool(INPUT); val di = Bool(INPUT); @@ -121,8 +121,9 @@ class rocketDpathPCR extends Component } } + 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 <== io.w.data.toUFix; + reg_badvaddr <== Cat(badvaddr_sign, io.w.data(VADDR_BITS-1,0)).toUFix; } when (io.exception && !reg_status_et) { @@ -163,8 +164,8 @@ class rocketDpathPCR extends Component reg_status_ec <== 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-1,0).toUFix; } - when (io.w.addr === PCR_BADVADDR) { reg_badvaddr <== io.w.data(VADDR_BITS-1,0).toUFix; } + 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); } @@ -187,8 +188,8 @@ class rocketDpathPCR extends Component 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, reg_epc(VADDR_BITS-1)), reg_epc); } - is (PCR_BADVADDR) { rdata <== Cat(Fill(64-VADDR_BITS, reg_badvaddr(VADDR_BITS-1)), reg_badvaddr); } + 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); } diff --git a/rocket/src/main/scala/dtlb.scala b/rocket/src/main/scala/dtlb.scala index 214f05df..de1098eb 100644 --- a/rocket/src/main/scala/dtlb.scala +++ b/rocket/src/main/scala/dtlb.scala @@ -19,7 +19,7 @@ class ioDTLB_CPU(view: List[String] = null) extends Bundle(view) val req_cmd = Bits(4, INPUT); // load/store/amo val req_rdy = Bool(OUTPUT); val req_asid = Bits(ASID_BITS, INPUT); - val req_vpn = UFix(VPN_BITS, INPUT); + val req_vpn = UFix(VPN_BITS+1, INPUT); // lookup responses val resp_miss = Bool(OUTPUT); // val resp_val = Bool(OUTPUT); @@ -65,17 +65,18 @@ class rocketDTLB(entries: Int) extends Component val req_store = (r_cpu_req_cmd === M_XWR); val req_amo = r_cpu_req_cmd(3).toBool; - val lookup_tag = Cat(r_cpu_req_asid, r_cpu_req_vpn); + val bad_va = r_cpu_req_vpn(VPN_BITS) != r_cpu_req_vpn(VPN_BITS-1); val tag_cam = new rocketCAM(entries, ASID_BITS+VPN_BITS); val tag_ram = Mem(entries, io.ptw.resp_val, r_refill_waddr.toUFix, io.ptw.resp_ppn); + val lookup_tag = Cat(r_cpu_req_asid, r_cpu_req_vpn); tag_cam.io.clear := io.cpu.invalidate; tag_cam.io.tag := lookup_tag; tag_cam.io.write := io.ptw.resp_val || io.ptw.resp_err; tag_cam.io.write_tag := r_refill_tag; tag_cam.io.write_addr := r_refill_waddr; - val tag_hit = tag_cam.io.hit; + val tag_hit = tag_cam.io.hit || bad_va; val tag_hit_addr = tag_cam.io.hit_addr; // extract fields from status register @@ -140,14 +141,16 @@ class rocketDTLB(entries: Int) extends Component val access_fault_ld = tlb_hit && (req_load || req_amo) && ((status_s && !sr_array(tag_hit_addr).toBool) || - (status_u && !ur_array(tag_hit_addr).toBool)); + (status_u && !ur_array(tag_hit_addr).toBool) || + bad_va); io.cpu.xcpt_ld := access_fault_ld; val access_fault_st = tlb_hit && (req_store || req_amo) && ((status_s && !sw_array(tag_hit_addr).toBool) || - (status_u && !uw_array(tag_hit_addr).toBool)); + (status_u && !uw_array(tag_hit_addr).toBool) || + bad_va); io.cpu.xcpt_st := access_fault_st; diff --git a/rocket/src/main/scala/itlb.scala b/rocket/src/main/scala/itlb.scala index 73f63b00..1b6aa7ed 100644 --- a/rocket/src/main/scala/itlb.scala +++ b/rocket/src/main/scala/itlb.scala @@ -74,7 +74,7 @@ class ioITLB_CPU(view: List[String] = null) extends Bundle(view) val req_val = Bool(INPUT); val req_rdy = Bool(OUTPUT); val req_asid = Bits(ASID_BITS, INPUT); - val req_vpn = UFix(VPN_BITS, INPUT); + val req_vpn = UFix(VPN_BITS+1, INPUT); // lookup responses val resp_miss = Bool(OUTPUT); // val resp_val = Bool(OUTPUT); @@ -111,18 +111,19 @@ class rocketITLB(entries: Int) extends Component otherwise { r_cpu_req_val <== Bool(false); } - - val lookup_tag = Cat(r_cpu_req_asid, r_cpu_req_vpn); + + val bad_va = r_cpu_req_vpn(VPN_BITS) != r_cpu_req_vpn(VPN_BITS-1); val tag_cam = new rocketCAM(entries, ASID_BITS+VPN_BITS); val tag_ram = Mem(entries, io.ptw.resp_val, r_refill_waddr.toUFix, io.ptw.resp_ppn); + val lookup_tag = Cat(r_cpu_req_asid, r_cpu_req_vpn); tag_cam.io.clear := io.cpu.invalidate; tag_cam.io.tag := lookup_tag; tag_cam.io.write := io.ptw.resp_val || io.ptw.resp_err; tag_cam.io.write_tag := r_refill_tag; tag_cam.io.write_addr := r_refill_waddr; - val tag_hit = tag_cam.io.hit; + val tag_hit = tag_cam.io.hit || bad_va; val tag_hit_addr = tag_cam.io.hit_addr; // extract fields from status register @@ -171,15 +172,13 @@ class rocketITLB(entries: Int) extends Component } } - // exception check - val outofrange = !tlb_miss && (io.cpu.resp_ppn > UFix(MEMSIZE_PAGES, PPN_BITS)); - val access_fault = tlb_hit && ((status_s && !sx_array(tag_hit_addr).toBool) || - (status_u && !ux_array(tag_hit_addr).toBool)); + (status_u && !ux_array(tag_hit_addr).toBool) || + bad_va); - io.cpu.exception := access_fault; //|| outofrange; + io.cpu.exception := access_fault; io.cpu.req_rdy := Mux(status_vm, (state === s_ready) && (!r_cpu_req_val || tag_hit), Bool(true)); io.cpu.resp_miss := tlb_miss || (state != s_ready); io.cpu.resp_ppn := Mux(status_vm, tag_ram(tag_hit_addr), r_cpu_req_vpn(PPN_BITS-1,0)).toUFix;