diff --git a/rocket/src/main/scala/cpu.scala b/rocket/src/main/scala/cpu.scala index b68a9316..f2c993ca 100644 --- a/rocket/src/main/scala/cpu.scala +++ b/rocket/src/main/scala/cpu.scala @@ -45,16 +45,15 @@ class rocketProc extends Component val ctrl = new rocketCtrl(); val dpath = new rocketDpath(); - val dtlb = new rocketDTLB(ITLB_ENTRIES); + val dtlb = new rocketDTLB(DTLB_ENTRIES); val itlb = new rocketITLB(ITLB_ENTRIES); val ptw = new rocketPTW(); val arb = new rocketDmemArbiter(); ctrl.io.dpath <> dpath.io.ctrl; -// ctrl.io.dmem ^^ io.dmem; ctrl.io.host.start ^^ io.host.start; +// ctrl.io.dmem ^^ io.dmem; // ctrl.io.imem ^^ io.imem; - // dpath.io.dmem ^^ io.dmem; // dpath.io.imem.req_addr ^^ io.imem.req_addr; dpath.io.imem.resp_data ^^ io.imem.resp_data; @@ -63,7 +62,7 @@ class rocketProc extends Component // FIXME: make this less verbose // connect ITLB to I$, ctrl, dpath - itlb.io.cpu.invalidate := Bool(false); + itlb.io.cpu.invalidate := Bool(false); // FIXME 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 @@ -74,9 +73,18 @@ class rocketProc extends Component ctrl.io.imem.resp_val := io.imem.resp_val; ctrl.io.itlb_xcpt := itlb.io.cpu.exception; + // connect DTLB to D$ arbiter, ctrl+dpath + dtlb.io.cpu.invalidate := Bool(false); // FIXME + dtlb.io.cpu.status := dpath.io.ctrl.status; + dtlb.io.cpu.req_val := ctrl.io.dmem.req_val; + 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_addr := dpath.io.dmem.req_addr; + ctrl.io.dtlb_xcpt := dtlb.io.cpu.exception; + // connect page table walker to TLBs, page table base register (from PCR) // and D$ arbiter (selects between requests from pipeline and PTW, PTW has priority) - + ptw.io.dtlb <> dtlb.io.ptw; ptw.io.itlb <> itlb.io.ptw; ptw.io.ptbr := dpath.io.ptbr; arb.io.ptw <> ptw.io.dmem; @@ -84,18 +92,30 @@ class rocketProc extends Component // FIXME: make this less verbose // connect arbiter to ctrl+dpath - arb.io.cpu.req_val := ctrl.io.dmem.req_val; + arb.io.cpu.req_val := dtlb.io.cpu.resp_val; arb.io.cpu.req_cmd := ctrl.io.dmem.req_cmd; arb.io.cpu.req_type := ctrl.io.dmem.req_type; - arb.io.cpu.req_addr := dpath.io.dmem.req_addr; + arb.io.cpu.req_addr := dtlb.io.cpu.resp_addr; arb.io.cpu.req_data := dpath.io.dmem.req_data; arb.io.cpu.req_tag := dpath.io.dmem.req_tag; - ctrl.io.dmem.req_rdy := arb.io.cpu.req_rdy; + ctrl.io.dmem.req_rdy := dtlb.io.cpu.req_rdy && arb.io.cpu.req_rdy; ctrl.io.dmem.resp_miss := arb.io.cpu.resp_miss; - ctrl.io.dmem.resp_val := arb.io.cpu.resp_val; dpath.io.dmem.resp_val := arb.io.cpu.resp_val; dpath.io.dmem.resp_tag := arb.io.cpu.resp_tag; - dpath.io.dmem.resp_data := arb.io.cpu.resp_data; + dpath.io.dmem.resp_data := arb.io.cpu.resp_data; + +// arb.io.cpu.req_val := ctrl.io.dmem.req_val; +// arb.io.cpu.req_cmd := ctrl.io.dmem.req_cmd; +// arb.io.cpu.req_type := ctrl.io.dmem.req_type; +// arb.io.cpu.req_addr := dpath.io.dmem.req_addr; +// arb.io.cpu.req_data := dpath.io.dmem.req_data; +// arb.io.cpu.req_tag := dpath.io.dmem.req_tag; +// ctrl.io.dmem.req_rdy := arb.io.cpu.req_rdy; +// ctrl.io.dmem.resp_miss := arb.io.cpu.resp_miss; +// ctrl.io.dmem.resp_val := arb.io.cpu.resp_val; +// dpath.io.dmem.resp_val := arb.io.cpu.resp_val; +// dpath.io.dmem.resp_tag := arb.io.cpu.resp_tag; +// dpath.io.dmem.resp_data := arb.io.cpu.resp_data; // FIXME: console disconnected // io.console.bits := dpath.io.dpath.rs1(7,0); diff --git a/rocket/src/main/scala/ctrl.scala b/rocket/src/main/scala/ctrl.scala index cef554f7..b1eea3d0 100644 --- a/rocket/src/main/scala/ctrl.scala +++ b/rocket/src/main/scala/ctrl.scala @@ -33,10 +33,13 @@ class ioCtrlDpath extends Bundle() val sel_wb = UFix(3, 'output); val ren_pcr = Bool('output); val wen_pcr = Bool('output); + // FIXME: move exception handling stuff (generating cause value, etc) + // from EX stage of dpath to MEM stage of control val xcpt_illegal = Bool('output); val xcpt_privileged = Bool('output); val xcpt_fpu = Bool('output); val xcpt_syscall = Bool('output); +// val xcpt_dtlb = Bool('output); val xcpt_itlb = Bool('output); val eret = Bool('output); val mem_load = Bool('output); @@ -68,6 +71,7 @@ class ioCtrlAll extends Bundle() val imem = new ioImem(List("req_val", "req_rdy", "resp_val")).flip(); val dmem = new ioDmem(List("req_val", "req_rdy", "req_cmd", "req_type", "resp_miss")).flip(); val host = new ioHost(List("start")); + val dtlb_xcpt = Bool('input); val itlb_xcpt = Bool('input); } @@ -237,7 +241,7 @@ class rocketCtrl extends Component val ex_reg_mem_type = Reg(){UFix(width = 3)}; val ex_reg_eret = Reg(resetVal = Bool(false)); val ex_reg_privileged = Reg(resetVal = Bool(false)); -// val id_reg_itlb_xcpt = Reg(resetVal = Bool(false)); +// val ex_reg_itlb_xcpt = Reg(resetVal = Bool(false)); when (!io.dpath.stalld) { when (io.dpath.killf) { @@ -343,8 +347,10 @@ class rocketCtrl extends Component io.dpath.mem_load := mem_cmd_load; + // FIXME: dtlb exception handling broken, need to move cause value generation + // to mem stage. also should probably move it from dpath to ctrl io.dpath.sel_pc := - Mux(io.dpath.exception || mem_reg_eret, PC_PCR, + Mux(io.dpath.exception || io.dtlb_xcpt, PC_PCR, Mux(replay_ex || replay_mem || mem_reg_privileged, PC_EX, Mux(!ex_reg_btb_hit && br_taken, PC_BR, Mux(ex_reg_btb_hit && !br_taken, PC_EX4, diff --git a/rocket/src/main/scala/dpath.scala b/rocket/src/main/scala/dpath.scala index e9218261..825c3897 100644 --- a/rocket/src/main/scala/dpath.scala +++ b/rocket/src/main/scala/dpath.scala @@ -5,6 +5,16 @@ import Node._; import Constants._ import Instructions._ +class ioDpathDmem extends Bundle() +{ + val req_addr = UFix(VADDR_BITS, 'output); + val req_tag = UFix(5, 'output); + val req_data = Bits(64, 'output); + val resp_val = Bool('input); + val resp_tag = Bits(13, 'input); // FIXME: MSB is ignored + val resp_data = Bits(64, 'input); +} + class ioDpathImem extends Bundle() { val req_addr = UFix(VADDR_BITS, 'output); @@ -16,7 +26,8 @@ class ioDpathAll extends Bundle() val host = new ioHost(); val ctrl = new ioCtrlDpath().flip(); val debug = new ioDebug(); - val dmem = new ioDmem(List("req_addr", "req_data", "req_tag", "resp_val", "resp_tag", "resp_data")).flip(); +// val dmem = new ioDmem(List("req_addr", "req_data", "req_tag", "resp_val", "resp_tag", "resp_data")).flip(); + val dmem = new ioDpathDmem(); val imem = new ioDpathImem(); val ptbr = UFix(PADDR_BITS, 'output); } diff --git a/rocket/src/main/scala/dtlb.scala b/rocket/src/main/scala/dtlb.scala index 961e6041..e0cdfe6f 100644 --- a/rocket/src/main/scala/dtlb.scala +++ b/rocket/src/main/scala/dtlb.scala @@ -43,8 +43,8 @@ class rocketDTLB(entries: Int) extends Component val req_vpn = io.cpu.req_addr(VADDR_BITS-1,PGIDX_BITS); val req_idx = io.cpu.req_addr(PGIDX_BITS-1,0); - val req_load = (io.cpu.req_cmd === M_XRD); - val req_store = (io.cpu.req_cmd === M_XWR); + val req_load = io.cpu.req_val && (io.cpu.req_cmd === M_XRD); + val req_store = io.cpu.req_val && (io.cpu.req_cmd === M_XWR); // val req_amo = io.cpu.req_cmd(3).toBool; val lookup_tag = Cat(io.cpu.req_asid, req_vpn); @@ -65,10 +65,8 @@ class rocketDTLB(entries: Int) extends Component val status_vm = io.cpu.status(16).toBool // virtual memory enable // extract fields from PT permission bits -// val ptw_perm_ux = io.ptw.resp_perm(0); val ptw_perm_ur = io.ptw.resp_perm(1); val ptw_perm_uw = io.ptw.resp_perm(2); -// val ptw_perm_sx = io.ptw.resp_perm(3); val ptw_perm_sr = io.ptw.resp_perm(4); val ptw_perm_sw = io.ptw.resp_perm(5); @@ -135,11 +133,10 @@ class rocketDTLB(entries: Int) extends Component io.cpu.req_rdy := (state === s_ready); io.cpu.resp_val := Mux(status_vm, tag_hit, io.cpu.req_val); -// io.cpu.resp_ppn := Mux(status_vm, io.cpu.req_vpn(PPN_BITS-1, 0), tag_ram(tag_hit_addr)); io.cpu.resp_addr := Mux(status_vm, Cat(tag_ram(tag_hit_addr), req_idx), io.cpu.req_addr(PADDR_BITS-1,0)).toUFix; - io.cpu.exception := dtlb_exception; + io.cpu.exception := status_vm && dtlb_exception; io.ptw.req_val := (state === s_request); io.ptw.req_vpn := r_refill_tag(VPN_BITS-1,0); diff --git a/rocket/src/main/scala/itlb.scala b/rocket/src/main/scala/itlb.scala index 5d80c4cb..cf9532c2 100644 --- a/rocket/src/main/scala/itlb.scala +++ b/rocket/src/main/scala/itlb.scala @@ -62,11 +62,9 @@ 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 = Bits(VPN_BITS, 'input); val req_addr = UFix(VADDR_BITS, 'input); // lookup responses val resp_val = Bool('output); -// val resp_ppn = Bits(PPN_BITS, 'output); val resp_addr = UFix(PADDR_BITS, 'output); val exception = Bool('output); } @@ -155,13 +153,12 @@ class rocketITLB(entries: Int) extends Component } val itlb_exception = - tag_hit && + io.cpu.req_val && tag_hit && ((status_mode && !sx_array(tag_hit_addr).toBool) || (!status_mode && !ux_array(tag_hit_addr).toBool)); io.cpu.req_rdy := (state === s_ready); io.cpu.resp_val := Mux(status_vm, tag_hit, io.cpu.req_val); -// io.cpu.resp_ppn := Mux(status_vm, io.cpu.req_vpn(PPN_BITS-1, 0), tag_ram(tag_hit_addr)); io.cpu.resp_addr := Mux(status_vm, Cat(tag_ram(tag_hit_addr), req_idx), io.cpu.req_addr(PADDR_BITS-1,0)).toUFix; diff --git a/rocket/src/main/scala/ptw.scala b/rocket/src/main/scala/ptw.scala index 89170884..596f3e43 100644 --- a/rocket/src/main/scala/ptw.scala +++ b/rocket/src/main/scala/ptw.scala @@ -32,14 +32,15 @@ class rocketDmemArbiter extends Component io.ptw.resp_data := io.mem.resp_data; io.cpu.resp_data := io.mem.resp_data; - io.cpu.resp_tag := io.mem.resp_tag; +// io.cpu.resp_tag := io.mem.resp_tag(11,0); + io.cpu.resp_tag := io.mem.resp_tag; // to get rid of warning, MSB of tag is ignored in dpath } class ioPTW extends Bundle { val itlb = new ioTLB_PTW().flip(); -// val dtlb = new ioTLB_PTW.flip(); + val dtlb = new ioTLB_PTW().flip(); val dmem = new ioDmem(List("req_val", "req_rdy", "req_cmd", "req_type", "req_addr", "resp_data", "resp_val")).flip(); val ptbr = UFix(PADDR_BITS, 'input); } @@ -52,17 +53,31 @@ class rocketPTW extends Component val state = Reg(resetVal = s_ready); val r_req_vpn = Reg(resetVal = Bits(0,VPN_BITS)); + val r_req_dest = Reg(resetVal = Bool(false)); // 0 = ITLB, 1 = DTLB val req_addr = Reg(resetVal = UFix(0,PPN_BITS+PGIDX_BITS)); val r_resp_ppn = Reg(resetVal = Bits(0,PPN_BITS)); val r_resp_perm = Reg(resetVal = Bits(0,PERM_BITS)); val vpn_idx = Mux(state === s_l2_wait, r_req_vpn(9,0), r_req_vpn(19,10)); + val req_val = io.itlb.req_val || io.dtlb.req_val; - when ((state === s_ready) && io.itlb.req_val) { + // give ITLB requests priority over DTLB requests + 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)).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)).toUFix; + } + when (io.dmem.resp_val) { req_addr <== Cat(io.dmem.resp_data(PADDR_BITS-1, PGIDX_BITS), vpn_idx).toUFix; r_resp_perm <== io.dmem.resp_data(9,4); @@ -78,22 +93,33 @@ class rocketPTW extends Component io.dmem.req_type := MT_D; io.dmem.req_addr := req_addr; - io.itlb.req_rdy := (state === s_ready); - io.itlb.resp_val := (state === s_done) || (state === s_l1_fake) || (state === s_l2_fake); - io.itlb.resp_err := (state === s_error); - io.itlb.resp_perm := r_resp_perm; - io.itlb.resp_ppn := - Mux(state === s_l1_fake, Cat(r_resp_ppn(PPN_BITS-1, PPN_BITS-7), r_req_vpn(VPN_BITS-11, 0)), - Mux(state === s_l2_fake, Cat(r_resp_ppn(PPN_BITS-1, PPN_BITS-17), r_req_vpn(VPN_BITS-21, 0)), - r_resp_ppn)); - + val resp_val = (state === s_done) || (state === s_l1_fake) || (state === s_l2_fake); + val resp_err = (state === s_error); + val resp_ptd = (io.dmem.resp_data(1,0) === Bits(1,2)); val resp_pte = (io.dmem.resp_data(1,0) === Bits(2,2)); + io.dtlb.req_rdy := (state === s_ready) && !io.itlb.req_val; + io.itlb.req_rdy := (state === s_ready); + io.dtlb.resp_val := r_req_dest && resp_val; + io.itlb.resp_val := !r_req_dest && resp_val; + io.dtlb.resp_err := r_req_dest && resp_err; + io.itlb.resp_err := !r_req_dest && resp_err; + io.dtlb.resp_perm := r_resp_perm; + io.itlb.resp_perm := r_resp_perm; + + val resp_ppn = + Mux(state === s_l1_fake, Cat(r_resp_ppn(PPN_BITS-1, PPN_BITS-7), r_req_vpn(VPN_BITS-11, 0)), + Mux(state === s_l2_fake, Cat(r_resp_ppn(PPN_BITS-1, PPN_BITS-17), r_req_vpn(VPN_BITS-21, 0)), + r_resp_ppn)); + + io.dtlb.resp_ppn := resp_ppn; + io.itlb.resp_ppn := resp_ppn; + // control state machine switch (state) { is (s_ready) { - when (io.itlb.req_val) { + when (req_val) { state <== s_l1_req; } }