dtlb now arbitrates between cpu, vec, and vec pf
This commit is contained in:
parent
94ba32bbd3
commit
569698b824
@ -238,4 +238,8 @@ object Constants
|
|||||||
val VIMM_VLEN = UFix(0, 1)
|
val VIMM_VLEN = UFix(0, 1)
|
||||||
val VIMM_ALU = UFix(1, 1)
|
val VIMM_ALU = UFix(1, 1)
|
||||||
val VIMM_X = UFix(0, 1)
|
val VIMM_X = UFix(0, 1)
|
||||||
|
|
||||||
|
val DTLB_VEC = 0
|
||||||
|
val DTLB_VPF = 1
|
||||||
|
val DTLB_CPU = 2
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,80 @@ class rocketProc(resetSignal: Bool = null) extends Component(resetSignal)
|
|||||||
val ptw = new rocketPTW();
|
val ptw = new rocketPTW();
|
||||||
val arb = new rocketDmemArbiter();
|
val arb = new rocketDmemArbiter();
|
||||||
|
|
||||||
|
var vu: vu = null
|
||||||
|
if (HAVE_VEC)
|
||||||
|
{
|
||||||
|
vu = new vu()
|
||||||
|
// cpu, vector prefetch, and vector use the DTLB
|
||||||
|
val dtlbarb = new cArbiter(3)({new ioDTLB_CPU_req()})
|
||||||
|
val dtlbchosen = Reg(resetVal=Bits(DTLB_CPU,log2up(3)))
|
||||||
|
when( dtlb.io.cpu_req.ready && dtlbarb.io.out.valid ) { dtlbchosen := dtlbarb.io.chosen }
|
||||||
|
|
||||||
|
val chosen_vec = dtlbchosen === Bits(DTLB_VEC)
|
||||||
|
val chosen_pf = dtlbchosen === Bits(DTLB_VPF)
|
||||||
|
val chosen_cpu = dtlbchosen === Bits(DTLB_CPU)
|
||||||
|
|
||||||
|
// vector prefetch doesn't care about exceptions
|
||||||
|
// and shouldn't cause any anyways
|
||||||
|
vu.io.vec_tlb_resp.xcpt_ld := chosen_vec && dtlb.io.cpu_resp.xcpt_ld
|
||||||
|
vu.io.vec_tlb_resp.xcpt_st := chosen_vec && dtlb.io.cpu_resp.xcpt_st
|
||||||
|
vu.io.vec_tlb_resp.miss := chosen_vec && dtlb.io.cpu_resp.miss
|
||||||
|
vu.io.vec_tlb_resp.ppn := dtlb.io.cpu_resp.ppn
|
||||||
|
|
||||||
|
vu.io.vec_pftlb_resp.xcpt_ld := Bool(false)
|
||||||
|
vu.io.vec_pftlb_resp.xcpt_st := Bool(false)
|
||||||
|
vu.io.vec_pftlb_resp.miss := chosen_pf && dtlb.io.cpu_resp.miss
|
||||||
|
vu.io.vec_pftlb_resp.ppn := dtlb.io.cpu_resp.ppn
|
||||||
|
|
||||||
|
// connect DTLB to ctrl+dpath
|
||||||
|
dtlbarb.io.in(DTLB_CPU).valid := ctrl.io.dtlb_val
|
||||||
|
dtlbarb.io.in(DTLB_CPU).bits.kill := ctrl.io.dtlb_kill
|
||||||
|
dtlbarb.io.in(DTLB_CPU).bits.cmd := ctrl.io.dmem.req_cmd
|
||||||
|
dtlbarb.io.in(DTLB_CPU).bits.asid := Bits(0,ASID_BITS); // FIXME: connect to PCR
|
||||||
|
dtlbarb.io.in(DTLB_CPU).bits.vpn := dpath.io.dmem.req_addr(VADDR_BITS,PGIDX_BITS)
|
||||||
|
ctrl.io.dtlb_rdy := dtlbarb.io.in(DTLB_CPU).ready
|
||||||
|
|
||||||
|
ctrl.io.xcpt_dtlb_ld := chosen_cpu && dtlb.io.cpu_resp.xcpt_ld
|
||||||
|
ctrl.io.xcpt_dtlb_st := chosen_cpu && dtlb.io.cpu_resp.xcpt_st
|
||||||
|
ctrl.io.dtlb_miss := chosen_cpu && dtlb.io.cpu_resp.miss
|
||||||
|
|
||||||
|
dtlbarb.io.in(DTLB_VEC) <> vu.io.vec_tlb_req
|
||||||
|
dtlbarb.io.in(DTLB_VPF) <> vu.io.vec_pftlb_req
|
||||||
|
|
||||||
|
|
||||||
|
dtlb.io.cpu_req <> dtlbarb.io.out
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// connect DTLB to ctrl+dpath
|
||||||
|
dtlb.io.cpu_req.valid := ctrl.io.dtlb_val
|
||||||
|
dtlb.io.cpu_req.bits.kill := ctrl.io.dtlb_kill
|
||||||
|
dtlb.io.cpu_req.bits.cmd := ctrl.io.dmem.req_cmd
|
||||||
|
dtlb.io.cpu_req.bits.asid := Bits(0,ASID_BITS); // FIXME: connect to PCR
|
||||||
|
dtlb.io.cpu_req.bits.vpn := dpath.io.dmem.req_addr(VADDR_BITS,PGIDX_BITS)
|
||||||
|
ctrl.io.xcpt_dtlb_ld := dtlb.io.cpu_resp.xcpt_ld
|
||||||
|
ctrl.io.xcpt_dtlb_st := dtlb.io.cpu_resp.xcpt_st
|
||||||
|
ctrl.io.dtlb_rdy := dtlb.io.cpu_req.ready
|
||||||
|
ctrl.io.dtlb_miss := dtlb.io.cpu_resp.miss
|
||||||
|
}
|
||||||
|
|
||||||
|
dtlb.io.invalidate := dpath.io.ptbr_wen
|
||||||
|
dtlb.io.status := dpath.io.ctrl.status
|
||||||
|
|
||||||
|
arb.io.cpu.req_ppn := dtlb.io.cpu_resp.ppn;
|
||||||
|
ctrl.io.dmem.req_rdy := dtlb.io.cpu_req.ready && arb.io.cpu.req_rdy;
|
||||||
|
|
||||||
|
// connect DTLB to D$ arbiter
|
||||||
|
ctrl.io.xcpt_ma_ld := io.dmem.xcpt_ma_ld
|
||||||
|
ctrl.io.xcpt_ma_st := io.dmem.xcpt_ma_st
|
||||||
|
// 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;
|
||||||
|
arb.io.mem <> io.dmem
|
||||||
|
|
||||||
ctrl.io.dpath <> dpath.io.ctrl;
|
ctrl.io.dpath <> dpath.io.ctrl;
|
||||||
dpath.io.host <> io.host;
|
dpath.io.host <> io.host;
|
||||||
dpath.io.debug <> io.debug;
|
dpath.io.debug <> io.debug;
|
||||||
@ -53,39 +127,14 @@ class rocketProc(resetSignal: Bool = null) extends Component(resetSignal)
|
|||||||
ctrl.io.xcpt_itlb := itlb.io.cpu.exception;
|
ctrl.io.xcpt_itlb := itlb.io.cpu.exception;
|
||||||
io.imem.itlb_miss := itlb.io.cpu.resp_miss;
|
io.imem.itlb_miss := itlb.io.cpu.resp_miss;
|
||||||
|
|
||||||
// connect DTLB to D$ arbiter, ctrl+dpath
|
|
||||||
dtlb.io.cpu.invalidate := dpath.io.ptbr_wen;
|
|
||||||
dtlb.io.cpu.status := dpath.io.ctrl.status;
|
|
||||||
dtlb.io.cpu.req_val := ctrl.io.dtlb_val;
|
|
||||||
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,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;
|
|
||||||
ctrl.io.dtlb_miss := dtlb.io.cpu.resp_miss;
|
|
||||||
ctrl.io.xcpt_ma_ld := io.dmem.xcpt_ma_ld;
|
|
||||||
ctrl.io.xcpt_ma_st := io.dmem.xcpt_ma_st;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
arb.io.mem <> io.dmem
|
|
||||||
|
|
||||||
// connect arbiter to ctrl+dpath+DTLB
|
// connect arbiter to ctrl+dpath+DTLB
|
||||||
arb.io.cpu.req_val := ctrl.io.dmem.req_val;
|
arb.io.cpu.req_val := ctrl.io.dmem.req_val;
|
||||||
arb.io.cpu.req_cmd := ctrl.io.dmem.req_cmd;
|
arb.io.cpu.req_cmd := ctrl.io.dmem.req_cmd;
|
||||||
arb.io.cpu.req_type := ctrl.io.dmem.req_type;
|
arb.io.cpu.req_type := ctrl.io.dmem.req_type;
|
||||||
arb.io.cpu.req_kill := ctrl.io.dmem.req_kill;
|
arb.io.cpu.req_kill := ctrl.io.dmem.req_kill;
|
||||||
arb.io.cpu.req_idx := dpath.io.dmem.req_addr(PGIDX_BITS-1,0);
|
arb.io.cpu.req_idx := dpath.io.dmem.req_addr(PGIDX_BITS-1,0);
|
||||||
arb.io.cpu.req_ppn := dtlb.io.cpu.resp_ppn;
|
|
||||||
arb.io.cpu.req_data := dpath.io.dmem.req_data;
|
arb.io.cpu.req_data := dpath.io.dmem.req_data;
|
||||||
arb.io.cpu.req_tag := dpath.io.dmem.req_tag;
|
arb.io.cpu.req_tag := dpath.io.dmem.req_tag;
|
||||||
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_miss := arb.io.cpu.resp_miss;
|
||||||
ctrl.io.dmem.resp_replay:= arb.io.cpu.resp_replay;
|
ctrl.io.dmem.resp_replay:= arb.io.cpu.resp_replay;
|
||||||
ctrl.io.dmem.resp_nack := arb.io.cpu.resp_nack;
|
ctrl.io.dmem.resp_nack := arb.io.cpu.resp_nack;
|
||||||
@ -111,8 +160,6 @@ class rocketProc(resetSignal: Bool = null) extends Component(resetSignal)
|
|||||||
{
|
{
|
||||||
dpath.io.vec_ctrl <> ctrl.io.vec_dpath
|
dpath.io.vec_ctrl <> ctrl.io.vec_dpath
|
||||||
|
|
||||||
val vu = new vu()
|
|
||||||
|
|
||||||
// hooking up vector I$
|
// hooking up vector I$
|
||||||
vitlb.io.cpu.invalidate := dpath.io.ptbr_wen
|
vitlb.io.cpu.invalidate := dpath.io.ptbr_wen
|
||||||
vitlb.io.cpu.status := dpath.io.ctrl.status
|
vitlb.io.cpu.status := dpath.io.ctrl.status
|
||||||
|
@ -4,33 +4,39 @@ import Chisel._;
|
|||||||
import Node._;
|
import Node._;
|
||||||
import Constants._;
|
import Constants._;
|
||||||
import scala.math._;
|
import scala.math._;
|
||||||
|
import hwacha._
|
||||||
|
|
||||||
// interface between DTLB and pipeline
|
// ioDTLB_CPU also located in hwacha/src/vuVXU-Interface.scala
|
||||||
class ioDTLB_CPU(view: List[String] = null) extends Bundle(view)
|
// should keep them in sync
|
||||||
|
|
||||||
|
class ioDTLB_CPU_req_bundle extends Bundle
|
||||||
{
|
{
|
||||||
// status bits (from PCR), to check current permission and whether VM is enabled
|
|
||||||
val status = Bits(17, INPUT);
|
|
||||||
// invalidate all TLB entries
|
|
||||||
val invalidate = Bool(INPUT);
|
|
||||||
// lookup requests
|
// lookup requests
|
||||||
val req_val = Bool(INPUT);
|
val kill = Bool()
|
||||||
val req_kill = Bool(INPUT);
|
val cmd = Bits(width=4) // load/store/amo
|
||||||
val req_cmd = Bits(4, INPUT); // load/store/amo
|
val asid = Bits(width=ASID_BITS)
|
||||||
val req_rdy = Bool(OUTPUT);
|
val vpn = UFix(width=VPN_BITS+1)
|
||||||
val req_asid = Bits(ASID_BITS, INPUT);
|
}
|
||||||
val req_vpn = UFix(VPN_BITS+1, INPUT);
|
class ioDTLB_CPU_req extends io_ready_valid()( { new ioDTLB_CPU_req_bundle() } )
|
||||||
|
|
||||||
|
class ioDTLB_CPU_resp extends Bundle
|
||||||
|
{
|
||||||
// lookup responses
|
// lookup responses
|
||||||
val resp_miss = Bool(OUTPUT);
|
val miss = Bool(OUTPUT)
|
||||||
// val resp_val = Bool(OUTPUT);
|
val ppn = UFix(PPN_BITS, OUTPUT)
|
||||||
val resp_ppn = UFix(PPN_BITS, OUTPUT);
|
val xcpt_ld = Bool(OUTPUT)
|
||||||
val xcpt_ld = Bool(OUTPUT);
|
val xcpt_st = Bool(OUTPUT)
|
||||||
val xcpt_st = Bool(OUTPUT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ioDTLB extends Bundle
|
class ioDTLB extends Bundle
|
||||||
{
|
{
|
||||||
val cpu = new ioDTLB_CPU();
|
// status bits (from PCR), to check current permission and whether VM is enabled
|
||||||
val ptw = new ioTLB_PTW();
|
val status = Bits(17,INPUT)
|
||||||
|
// invalidate all TLB entries
|
||||||
|
val invalidate = Bool(INPUT)
|
||||||
|
val cpu_req = new ioDTLB_CPU_req().flip()
|
||||||
|
val cpu_resp = new ioDTLB_CPU_resp()
|
||||||
|
val ptw = new ioTLB_PTW()
|
||||||
}
|
}
|
||||||
|
|
||||||
class rocketDTLB(entries: Int) extends Component
|
class rocketDTLB(entries: Int) extends Component
|
||||||
@ -50,10 +56,10 @@ class rocketDTLB(entries: Int) extends Component
|
|||||||
val r_refill_waddr = Reg() { UFix() }
|
val r_refill_waddr = Reg() { UFix() }
|
||||||
val repl_count = Reg(resetVal = UFix(0,addr_bits));
|
val repl_count = Reg(resetVal = UFix(0,addr_bits));
|
||||||
|
|
||||||
when (io.cpu.req_val && io.cpu.req_rdy) {
|
when (io.cpu_req.valid && io.cpu_req.ready) {
|
||||||
r_cpu_req_vpn := io.cpu.req_vpn;
|
r_cpu_req_vpn := io.cpu_req.bits.vpn;
|
||||||
r_cpu_req_cmd := io.cpu.req_cmd;
|
r_cpu_req_cmd := io.cpu_req.bits.cmd;
|
||||||
r_cpu_req_asid := io.cpu.req_asid;
|
r_cpu_req_asid := io.cpu_req.bits.asid;
|
||||||
r_cpu_req_val := Bool(true);
|
r_cpu_req_val := Bool(true);
|
||||||
}
|
}
|
||||||
.otherwise {
|
.otherwise {
|
||||||
@ -63,6 +69,7 @@ class rocketDTLB(entries: Int) extends Component
|
|||||||
val req_load = (r_cpu_req_cmd === M_XRD);
|
val req_load = (r_cpu_req_cmd === M_XRD);
|
||||||
val req_store = (r_cpu_req_cmd === M_XWR);
|
val req_store = (r_cpu_req_cmd === M_XWR);
|
||||||
val req_amo = r_cpu_req_cmd(3).toBool;
|
val req_amo = r_cpu_req_cmd(3).toBool;
|
||||||
|
val req_pf = (r_cpu_req_cmd === M_PFR) || (r_cpu_req_cmd === M_PFW)
|
||||||
|
|
||||||
val bad_va = r_cpu_req_vpn(VPN_BITS) != r_cpu_req_vpn(VPN_BITS-1);
|
val bad_va = r_cpu_req_vpn(VPN_BITS) != r_cpu_req_vpn(VPN_BITS-1);
|
||||||
|
|
||||||
@ -70,7 +77,7 @@ class rocketDTLB(entries: Int) extends Component
|
|||||||
val tag_ram = Mem(entries, io.ptw.resp_val, r_refill_waddr.toUFix, io.ptw.resp_ppn);
|
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);
|
val lookup_tag = Cat(r_cpu_req_asid, r_cpu_req_vpn);
|
||||||
tag_cam.io.clear := io.cpu.invalidate;
|
tag_cam.io.clear := io.invalidate;
|
||||||
tag_cam.io.tag := lookup_tag;
|
tag_cam.io.tag := lookup_tag;
|
||||||
tag_cam.io.write := io.ptw.resp_val || io.ptw.resp_err;
|
tag_cam.io.write := io.ptw.resp_val || io.ptw.resp_err;
|
||||||
tag_cam.io.write_tag := r_refill_tag;
|
tag_cam.io.write_tag := r_refill_tag;
|
||||||
@ -79,9 +86,9 @@ class rocketDTLB(entries: Int) extends Component
|
|||||||
val tag_hit_addr = tag_cam.io.hit_addr;
|
val tag_hit_addr = tag_cam.io.hit_addr;
|
||||||
|
|
||||||
// extract fields from status register
|
// extract fields from status register
|
||||||
val status_s = io.cpu.status(SR_S).toBool; // user/supervisor mode
|
val status_s = io.status(SR_S).toBool; // user/supervisor mode
|
||||||
val status_u = !status_s;
|
val status_u = !status_s;
|
||||||
val status_vm = io.cpu.status(SR_VM).toBool // virtual memory enable
|
val status_vm = io.status(SR_VM).toBool // virtual memory enable
|
||||||
|
|
||||||
// extract fields from PT permission bits
|
// extract fields from PT permission bits
|
||||||
val ptw_perm_ur = io.ptw.resp_perm(2);
|
val ptw_perm_ur = io.ptw.resp_perm(2);
|
||||||
@ -118,7 +125,7 @@ class rocketDTLB(entries: Int) extends Component
|
|||||||
|
|
||||||
val repl_waddr = Mux(invalid_entry, ie_addr, repl_count).toUFix;
|
val repl_waddr = Mux(invalid_entry, ie_addr, repl_count).toUFix;
|
||||||
|
|
||||||
val lookup = (state === s_ready) && r_cpu_req_val && !io.cpu.req_kill && (req_load || req_store || req_amo);
|
val lookup = (state === s_ready) && r_cpu_req_val && !io.cpu_req.bits.kill && (req_load || req_store || req_amo || req_pf);
|
||||||
val lookup_hit = lookup && tag_hit;
|
val lookup_hit = lookup && tag_hit;
|
||||||
val lookup_miss = lookup && !tag_hit;
|
val lookup_miss = lookup && !tag_hit;
|
||||||
val tlb_hit = status_vm && lookup_hit;
|
val tlb_hit = status_vm && lookup_hit;
|
||||||
@ -135,7 +142,7 @@ class rocketDTLB(entries: Int) extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
// exception check
|
// exception check
|
||||||
val outofrange = !tlb_miss && (io.cpu.resp_ppn > UFix(MEMSIZE_PAGES, PPN_BITS));
|
val outofrange = !tlb_miss && (io.cpu_resp.ppn > UFix(MEMSIZE_PAGES, PPN_BITS));
|
||||||
|
|
||||||
val access_fault_ld =
|
val access_fault_ld =
|
||||||
tlb_hit && (req_load || req_amo) &&
|
tlb_hit && (req_load || req_amo) &&
|
||||||
@ -143,7 +150,7 @@ class rocketDTLB(entries: Int) extends Component
|
|||||||
(status_u && !ur_array(tag_hit_addr).toBool) ||
|
(status_u && !ur_array(tag_hit_addr).toBool) ||
|
||||||
bad_va);
|
bad_va);
|
||||||
|
|
||||||
io.cpu.xcpt_ld := access_fault_ld;
|
io.cpu_resp.xcpt_ld := access_fault_ld;
|
||||||
|
|
||||||
val access_fault_st =
|
val access_fault_st =
|
||||||
tlb_hit && (req_store || req_amo) &&
|
tlb_hit && (req_store || req_amo) &&
|
||||||
@ -151,11 +158,11 @@ class rocketDTLB(entries: Int) extends Component
|
|||||||
(status_u && !uw_array(tag_hit_addr).toBool) ||
|
(status_u && !uw_array(tag_hit_addr).toBool) ||
|
||||||
bad_va);
|
bad_va);
|
||||||
|
|
||||||
io.cpu.xcpt_st := access_fault_st;
|
io.cpu_resp.xcpt_st := access_fault_st;
|
||||||
|
|
||||||
io.cpu.req_rdy := (state === s_ready) && !tlb_miss;
|
io.cpu_req.ready := (state === s_ready) && !tlb_miss;
|
||||||
io.cpu.resp_miss := tlb_miss;
|
io.cpu_resp.miss := tlb_miss;
|
||||||
io.cpu.resp_ppn :=
|
io.cpu_resp.ppn :=
|
||||||
Mux(status_vm, tag_ram(tag_hit_addr), r_cpu_req_vpn(PPN_BITS-1,0)).toUFix;
|
Mux(status_vm, tag_ram(tag_hit_addr), r_cpu_req_vpn(PPN_BITS-1,0)).toUFix;
|
||||||
|
|
||||||
io.ptw.req_val := (state === s_request);
|
io.ptw.req_val := (state === s_request);
|
||||||
|
Loading…
Reference in New Issue
Block a user