cleanup, fixes, initial commit for dtlb.scala
This commit is contained in:
parent
e96430d862
commit
c29d2821b4
@ -4,7 +4,7 @@ import Chisel._;
|
|||||||
import Node._;
|
import Node._;
|
||||||
import Constants._;
|
import Constants._;
|
||||||
|
|
||||||
class ioDebug extends Bundle()
|
class ioDebug(view: List[String] = null) extends Bundle(view)
|
||||||
{
|
{
|
||||||
val error_mode = Bool('output);
|
val error_mode = Bool('output);
|
||||||
val log_control = Bool('output);
|
val log_control = Bool('output);
|
||||||
@ -66,13 +66,14 @@ class rocketProc extends Component
|
|||||||
ctrl.io.imem.req_rdy := itlb.io.cpu.req_rdy && io.imem.req_rdy;
|
ctrl.io.imem.req_rdy := itlb.io.cpu.req_rdy && io.imem.req_rdy;
|
||||||
|
|
||||||
itlb.io.cpu.req_asid := Bits(0,ASID_BITS); // FIXME: connect to PCR
|
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-1,PGIDX_BITS);
|
||||||
|
itlb.io.cpu.req_addr := dpath.io.imem.req_addr;
|
||||||
|
|
||||||
io.imem.req_val := itlb.io.cpu.resp_val;
|
io.imem.req_val := itlb.io.cpu.resp_val;
|
||||||
io.imem.req_addr := Cat(itlb.io.cpu.resp_ppn, dpath.io.imem.req_addr(PGIDX_BITS-1,0)).toUFix;
|
io.imem.req_addr := itlb.io.cpu.resp_addr;
|
||||||
|
|
||||||
ctrl.io.imem.resp_val := io.imem.resp_val;
|
ctrl.io.imem.resp_val := io.imem.resp_val;
|
||||||
dpath.io.itlb_xcpt := itlb.io.cpu.exception;
|
ctrl.io.itlb_xcpt := itlb.io.cpu.exception;
|
||||||
|
|
||||||
ptw.io.itlb <> itlb.io.ptw;
|
ptw.io.itlb <> itlb.io.ptw;
|
||||||
ptw.io.ptbr := dpath.io.ptbr;
|
ptw.io.ptbr := dpath.io.ptbr;
|
||||||
|
@ -37,6 +37,7 @@ class ioCtrlDpath extends Bundle()
|
|||||||
val xcpt_privileged = Bool('output);
|
val xcpt_privileged = Bool('output);
|
||||||
val xcpt_fpu = Bool('output);
|
val xcpt_fpu = Bool('output);
|
||||||
val xcpt_syscall = Bool('output);
|
val xcpt_syscall = Bool('output);
|
||||||
|
val xcpt_itlb = Bool('output);
|
||||||
val eret = Bool('output);
|
val eret = Bool('output);
|
||||||
val mem_load = Bool('output);
|
val mem_load = Bool('output);
|
||||||
val wen = Bool('output);
|
val wen = Bool('output);
|
||||||
@ -65,9 +66,9 @@ class ioCtrlAll extends Bundle()
|
|||||||
val dpath = new ioCtrlDpath();
|
val dpath = new ioCtrlDpath();
|
||||||
val console = new ioConsole(List("rdy", "valid"));
|
val console = new ioConsole(List("rdy", "valid"));
|
||||||
val imem = new ioImem(List("req_val", "req_rdy", "resp_val")).flip();
|
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", "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 host = new ioHost(List("start"));
|
||||||
// val itlb_xcpt = Bool('input);
|
val itlb_xcpt = Bool('input);
|
||||||
}
|
}
|
||||||
|
|
||||||
class rocketCtrl extends Component
|
class rocketCtrl extends Component
|
||||||
@ -226,7 +227,8 @@ class rocketCtrl extends Component
|
|||||||
val id_stall_waddr = sboard.io.stallc;
|
val id_stall_waddr = sboard.io.stallc;
|
||||||
val id_stall_ra = sboard.io.stallra;
|
val id_stall_ra = sboard.io.stallra;
|
||||||
|
|
||||||
val id_reg_btb_hit = Reg(width = 1, resetVal = Bool(false));
|
val id_reg_btb_hit = Reg(resetVal = Bool(false));
|
||||||
|
val id_reg_itlb_xcpt = Reg(resetVal = Bool(false));
|
||||||
val ex_reg_br_type = Reg(){UFix(width = 4)};
|
val ex_reg_br_type = Reg(){UFix(width = 4)};
|
||||||
val ex_reg_btb_hit = Reg(){Bool()};
|
val ex_reg_btb_hit = Reg(){Bool()};
|
||||||
val ex_reg_div_mul_val = Reg(){Bool()};
|
val ex_reg_div_mul_val = Reg(){Bool()};
|
||||||
@ -235,12 +237,15 @@ class rocketCtrl extends Component
|
|||||||
val ex_reg_mem_type = Reg(){UFix(width = 3)};
|
val ex_reg_mem_type = Reg(){UFix(width = 3)};
|
||||||
val ex_reg_eret = Reg(resetVal = Bool(false));
|
val ex_reg_eret = Reg(resetVal = Bool(false));
|
||||||
val ex_reg_privileged = Reg(resetVal = Bool(false));
|
val ex_reg_privileged = Reg(resetVal = Bool(false));
|
||||||
|
// val id_reg_itlb_xcpt = Reg(resetVal = Bool(false));
|
||||||
|
|
||||||
when (!io.dpath.stalld) {
|
when (!io.dpath.stalld) {
|
||||||
when (io.dpath.killf) {
|
when (io.dpath.killf) {
|
||||||
|
id_reg_itlb_xcpt <== Bool(false);
|
||||||
id_reg_btb_hit <== Bool(false);
|
id_reg_btb_hit <== Bool(false);
|
||||||
}
|
}
|
||||||
otherwise{
|
otherwise{
|
||||||
|
id_reg_itlb_xcpt <== io.itlb_xcpt;
|
||||||
id_reg_btb_hit <== io.dpath.btb_hit;
|
id_reg_btb_hit <== io.dpath.btb_hit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,6 +259,7 @@ class rocketCtrl extends Component
|
|||||||
ex_reg_mem_type <== UFix(0, 3);
|
ex_reg_mem_type <== UFix(0, 3);
|
||||||
ex_reg_eret <== Bool(false);
|
ex_reg_eret <== Bool(false);
|
||||||
ex_reg_privileged <== Bool(false);
|
ex_reg_privileged <== Bool(false);
|
||||||
|
// ex_reg_itlb_xcpt <== Bool(false);
|
||||||
}
|
}
|
||||||
otherwise {
|
otherwise {
|
||||||
ex_reg_br_type <== id_br_type;
|
ex_reg_br_type <== id_br_type;
|
||||||
@ -264,6 +270,7 @@ class rocketCtrl extends Component
|
|||||||
ex_reg_mem_type <== id_mem_type;
|
ex_reg_mem_type <== id_mem_type;
|
||||||
ex_reg_eret <== id_eret.toBool;
|
ex_reg_eret <== id_eret.toBool;
|
||||||
ex_reg_privileged <== id_privileged.toBool;
|
ex_reg_privileged <== id_privileged.toBool;
|
||||||
|
// ex_reg_itlb_xcpt <== id_reg_itlb_xcpt;
|
||||||
}
|
}
|
||||||
|
|
||||||
val beq = io.dpath.br_eq;
|
val beq = io.dpath.br_eq;
|
||||||
@ -284,7 +291,7 @@ class rocketCtrl extends Component
|
|||||||
val jr_taken = (ex_reg_br_type === BR_JR);
|
val jr_taken = (ex_reg_br_type === BR_JR);
|
||||||
val j_taken = (ex_reg_br_type === BR_J);
|
val j_taken = (ex_reg_br_type === BR_J);
|
||||||
|
|
||||||
io.imem.req_val := io.host.start;
|
io.imem.req_val := io.host.start; // FIXME
|
||||||
// io.imem.req_val := Bool(true);
|
// io.imem.req_val := Bool(true);
|
||||||
|
|
||||||
io.dmem.req_val := ex_reg_mem_val && ~io.dpath.killx;
|
io.dmem.req_val := ex_reg_mem_val && ~io.dpath.killx;
|
||||||
@ -330,7 +337,7 @@ class rocketCtrl extends Component
|
|||||||
val replay_mem = io.dmem.resp_miss;
|
val replay_mem = io.dmem.resp_miss;
|
||||||
|
|
||||||
val kill_ex = replay_ex | replay_mem | mem_reg_privileged;
|
val kill_ex = replay_ex | replay_mem | mem_reg_privileged;
|
||||||
val kill_mem = io.dpath.exception;
|
val kill_mem = io.dpath.exception; // TODO: add load/store related exceptions
|
||||||
|
|
||||||
dcache_miss <== io.dmem.resp_miss;
|
dcache_miss <== io.dmem.resp_miss;
|
||||||
|
|
||||||
@ -461,6 +468,7 @@ class rocketCtrl extends Component
|
|||||||
io.dpath.xcpt_privileged := (id_privileged & ~io.dpath.status(5)).toBool;
|
io.dpath.xcpt_privileged := (id_privileged & ~io.dpath.status(5)).toBool;
|
||||||
io.dpath.xcpt_fpu := Bool(false);
|
io.dpath.xcpt_fpu := Bool(false);
|
||||||
io.dpath.xcpt_syscall := id_syscall.toBool;
|
io.dpath.xcpt_syscall := id_syscall.toBool;
|
||||||
|
io.dpath.xcpt_itlb := id_reg_itlb_xcpt;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,20 @@ import Node._;
|
|||||||
import Constants._
|
import Constants._
|
||||||
import Instructions._
|
import Instructions._
|
||||||
|
|
||||||
|
class ioDpathImem extends Bundle()
|
||||||
|
{
|
||||||
|
val req_addr = UFix(VADDR_BITS, 'output);
|
||||||
|
val resp_data = Bits(32, 'input);
|
||||||
|
}
|
||||||
|
|
||||||
class ioDpathAll extends Bundle()
|
class ioDpathAll extends Bundle()
|
||||||
{
|
{
|
||||||
val host = new ioHost();
|
val host = new ioHost();
|
||||||
val ctrl = new ioCtrlDpath().flip();
|
val ctrl = new ioCtrlDpath().flip();
|
||||||
val debug = new ioDebug();
|
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 imem = new ioImem(List("req_addr", "resp_data")).flip();
|
// val imem = new ioImem(List("req_addr", "resp_data")).flip();
|
||||||
val itlb_xcpt = Bool('input);
|
val imem = new ioDpathImem();
|
||||||
val ptbr = UFix(PADDR_BITS, 'output);
|
val ptbr = UFix(PADDR_BITS, 'output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,13 +249,14 @@ class rocketDpath extends Component
|
|||||||
id_rdata2)))));
|
id_rdata2)))));
|
||||||
|
|
||||||
// write value to cause register based on exception type
|
// write value to cause register based on exception type
|
||||||
val id_exception = io.ctrl.xcpt_illegal || io.ctrl.xcpt_privileged || io.ctrl.xcpt_fpu || io.ctrl.xcpt_syscall;
|
val id_exception = io.ctrl.xcpt_illegal || io.ctrl.xcpt_privileged || io.ctrl.xcpt_fpu || io.ctrl.xcpt_syscall || io.ctrl.xcpt_itlb;
|
||||||
val id_cause =
|
val id_cause =
|
||||||
|
Mux(io.ctrl.xcpt_itlb, UFix(1,5),
|
||||||
Mux(io.ctrl.xcpt_illegal, UFix(2,5),
|
Mux(io.ctrl.xcpt_illegal, UFix(2,5),
|
||||||
Mux(io.ctrl.xcpt_privileged, UFix(3,5),
|
Mux(io.ctrl.xcpt_privileged, UFix(3,5),
|
||||||
Mux(io.ctrl.xcpt_fpu, UFix(4,5),
|
Mux(io.ctrl.xcpt_fpu, UFix(4,5),
|
||||||
Mux(io.ctrl.xcpt_syscall, UFix(6,5),
|
Mux(io.ctrl.xcpt_syscall, UFix(6,5),
|
||||||
UFix(0,5)))));
|
UFix(0,5))))));
|
||||||
|
|
||||||
io.ctrl.inst := id_reg_inst;
|
io.ctrl.inst := id_reg_inst;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class rocketDpathBTB extends Component
|
|||||||
class ioDpathPCR extends Bundle()
|
class ioDpathPCR extends Bundle()
|
||||||
{
|
{
|
||||||
val host = new ioHost(List("from", "from_wen", "to"));
|
val host = new ioHost(List("from", "from_wen", "to"));
|
||||||
val debug = new ioDebug();
|
val debug = new ioDebug(List("error_mode", "log_control"));
|
||||||
val r = new ioReadPort();
|
val r = new ioReadPort();
|
||||||
val w = new ioWritePort();
|
val w = new ioWritePort();
|
||||||
|
|
||||||
|
166
rocket/src/main/scala/dtlb.scala
Normal file
166
rocket/src/main/scala/dtlb.scala
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package Top
|
||||||
|
{
|
||||||
|
|
||||||
|
import Chisel._;
|
||||||
|
import Node._;
|
||||||
|
import Constants._;
|
||||||
|
import scala.math._;
|
||||||
|
|
||||||
|
// interface between DTLB and fetch stage of pipeline
|
||||||
|
class ioDTLB_CPU(view: List[String] = null) extends Bundle(view)
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
val req_val = Bool('input);
|
||||||
|
val req_cmd = Bits(4, 'input); // load/store/amo
|
||||||
|
val req_rdy = Bool('output);
|
||||||
|
val req_asid = Bits(ASID_BITS, 'input);
|
||||||
|
val req_addr = UFix(VADDR_BITS, 'input);
|
||||||
|
// lookup responses
|
||||||
|
val resp_val = Bool('output);
|
||||||
|
val resp_addr = UFix(PADDR_BITS, 'output);
|
||||||
|
val exception = Bool('output);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ioDTLB extends Bundle
|
||||||
|
{
|
||||||
|
val cpu = new ioDTLB_CPU();
|
||||||
|
val ptw = new ioTLB_PTW();
|
||||||
|
}
|
||||||
|
|
||||||
|
class rocketDTLB(entries: Int) extends Component
|
||||||
|
{
|
||||||
|
val addr_bits = ceil(log10(entries)/log10(2)).toInt;
|
||||||
|
val io = new ioDTLB();
|
||||||
|
|
||||||
|
val s_ready :: s_request :: s_wait :: Nil = Enum(3) { UFix() };
|
||||||
|
val state = Reg(resetVal = s_ready);
|
||||||
|
|
||||||
|
val tag_cam = new rocketCAM(entries, addr_bits, ASID_BITS+VPN_BITS);
|
||||||
|
|
||||||
|
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_amo = io.cpu.req_cmd(3).toBool;
|
||||||
|
|
||||||
|
val lookup_tag = Cat(io.cpu.req_asid, req_vpn);
|
||||||
|
val r_refill_tag = Reg(resetVal = Bits(0, ASID_BITS+VPN_BITS));
|
||||||
|
val r_refill_waddr = Reg(resetVal = UFix(0, addr_bits));
|
||||||
|
val repl_count = Reg(resetVal = UFix(0, addr_bits));
|
||||||
|
|
||||||
|
val tag_ram = Mem(entries, io.ptw.resp_val, r_refill_waddr.toUFix, io.ptw.resp_ppn);
|
||||||
|
|
||||||
|
tag_cam.io.tag := lookup_tag;
|
||||||
|
tag_cam.io.write := io.ptw.resp_val;
|
||||||
|
tag_cam.io.write_tag := r_refill_tag;
|
||||||
|
tag_cam.io.write_addr := r_refill_waddr;
|
||||||
|
val tag_hit_addr = tag_cam.io.hit_addr;
|
||||||
|
|
||||||
|
// extract fields from status register
|
||||||
|
val status_mode = io.cpu.status(6).toBool; // user/supervisor mode
|
||||||
|
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);
|
||||||
|
|
||||||
|
// valid bit array
|
||||||
|
val vb_array = Reg(resetVal = Bits(0, entries));
|
||||||
|
when (io.cpu.invalidate) {
|
||||||
|
vb_array <== Bits(0, entries);
|
||||||
|
}
|
||||||
|
when (io.ptw.resp_val) {
|
||||||
|
vb_array <== vb_array.bitSet(r_refill_waddr, Bool(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// permission bit arrays
|
||||||
|
val ur_array = Reg(resetVal = Bits(0, entries)); // user execute permission
|
||||||
|
val uw_array = Reg(resetVal = Bits(0, entries)); // user execute permission
|
||||||
|
val sr_array = Reg(resetVal = Bits(0, entries)); // supervisor execute permission
|
||||||
|
val sw_array = Reg(resetVal = Bits(0, entries)); // supervisor execute permission
|
||||||
|
when (io.ptw.resp_val) {
|
||||||
|
ur_array <== ur_array.bitSet(r_refill_waddr, ptw_perm_ur);
|
||||||
|
uw_array <== ur_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 <== ur_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
|
||||||
|
val invalid_entry = ~vb_array.toUFix.orR();
|
||||||
|
val ie_enc = new priorityEncoder(entries);
|
||||||
|
ie_enc.io.in := vb_array.toUFix;
|
||||||
|
val ie_addr = ie_enc.io.out;
|
||||||
|
|
||||||
|
val repl_waddr = Mux(invalid_entry, ie_addr, repl_count).toUFix;
|
||||||
|
|
||||||
|
val tag_hit = tag_cam.io.hit && vb_array(tag_hit_addr).toBool;
|
||||||
|
val lookup_miss = (state === s_ready) && status_vm && io.cpu.req_val && !tag_hit;
|
||||||
|
|
||||||
|
when (lookup_miss) {
|
||||||
|
r_refill_tag <== lookup_tag;
|
||||||
|
r_refill_waddr <== repl_waddr;
|
||||||
|
when (!invalid_entry) {
|
||||||
|
repl_count <== repl_count + UFix(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val dtlb_st_xcpt =
|
||||||
|
tag_hit && req_load &&
|
||||||
|
((status_mode && !sw_array(tag_hit_addr).toBool) ||
|
||||||
|
(!status_mode && !uw_array(tag_hit_addr).toBool));
|
||||||
|
|
||||||
|
val dtlb_ld_xcpt =
|
||||||
|
tag_hit && req_store &&
|
||||||
|
((status_mode && !sr_array(tag_hit_addr).toBool) ||
|
||||||
|
(!status_mode && !ur_array(tag_hit_addr).toBool));
|
||||||
|
|
||||||
|
val dtlb_exception = dtlb_st_xcpt || dtlb_ld_xcpt;
|
||||||
|
|
||||||
|
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.ptw.req_val := (state === s_request);
|
||||||
|
io.ptw.req_vpn := r_refill_tag(VPN_BITS-1,0);
|
||||||
|
|
||||||
|
// control state machine
|
||||||
|
switch (state) {
|
||||||
|
is (s_ready) {
|
||||||
|
when (status_vm && io.cpu.req_val && !tag_hit) {
|
||||||
|
state <== s_request;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is (s_request) {
|
||||||
|
when (io.ptw.req_rdy) {
|
||||||
|
state <== s_wait;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is (s_wait) {
|
||||||
|
when (io.ptw.resp_val || io.ptw.resp_err) {
|
||||||
|
state <== s_ready;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,10 +5,10 @@ import Node._;
|
|||||||
import Constants._;
|
import Constants._;
|
||||||
import scala.math._;
|
import scala.math._;
|
||||||
|
|
||||||
// interface between I$ and processor (32 bits wide)
|
// interface between I$ and pipeline/ITLB (32 bits wide)
|
||||||
class ioImem(view: List[String] = null) extends Bundle (view)
|
class ioImem(view: List[String] = null) extends Bundle (view)
|
||||||
{
|
{
|
||||||
val req_addr = UFix(32, 'input);
|
val req_addr = UFix(PADDR_BITS, 'input);
|
||||||
val req_val = Bool('input);
|
val req_val = Bool('input);
|
||||||
val req_rdy = Bool('output);
|
val req_rdy = Bool('output);
|
||||||
val resp_data = Bits(32, 'output);
|
val resp_data = Bits(32, 'output);
|
||||||
|
@ -52,7 +52,7 @@ class ioTLB_PTW extends Bundle
|
|||||||
}
|
}
|
||||||
|
|
||||||
// interface between ITLB and fetch stage of pipeline
|
// interface between ITLB and fetch stage of pipeline
|
||||||
class ioITLB_CPU extends Bundle
|
class ioITLB_CPU(view: List[String] = null) extends Bundle(view)
|
||||||
{
|
{
|
||||||
// status bits (from PCR), to check current permission and whether VM is enabled
|
// status bits (from PCR), to check current permission and whether VM is enabled
|
||||||
val status = Bits(17, 'input);
|
val status = Bits(17, 'input);
|
||||||
@ -62,10 +62,12 @@ class ioITLB_CPU extends Bundle
|
|||||||
val req_val = Bool('input);
|
val req_val = Bool('input);
|
||||||
val req_rdy = Bool('output);
|
val req_rdy = Bool('output);
|
||||||
val req_asid = Bits(ASID_BITS, 'input);
|
val req_asid = Bits(ASID_BITS, 'input);
|
||||||
val req_vpn = Bits(VPN_BITS, 'input);
|
// val req_vpn = Bits(VPN_BITS, 'input);
|
||||||
|
val req_addr = UFix(VADDR_BITS, 'input);
|
||||||
// lookup responses
|
// lookup responses
|
||||||
val resp_val = Bool('output);
|
val resp_val = Bool('output);
|
||||||
val resp_ppn = Bits(PPN_BITS, 'output);
|
// val resp_ppn = Bits(PPN_BITS, 'output);
|
||||||
|
val resp_addr = UFix(PADDR_BITS, 'output);
|
||||||
val exception = Bool('output);
|
val exception = Bool('output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +87,9 @@ class rocketITLB(entries: Int) extends Component
|
|||||||
|
|
||||||
val tag_cam = new rocketCAM(entries, addr_bits, ASID_BITS+VPN_BITS);
|
val tag_cam = new rocketCAM(entries, addr_bits, ASID_BITS+VPN_BITS);
|
||||||
|
|
||||||
val lookup_tag = Cat(io.cpu.req_asid, io.cpu.req_vpn);
|
val req_vpn = io.cpu.req_addr(VADDR_BITS-1,PGIDX_BITS);
|
||||||
|
val req_idx = io.cpu.req_addr(PGIDX_BITS-1,0);
|
||||||
|
val lookup_tag = Cat(io.cpu.req_asid, req_vpn);
|
||||||
val r_refill_tag = Reg(resetVal = Bits(0, ASID_BITS+VPN_BITS));
|
val r_refill_tag = Reg(resetVal = Bits(0, ASID_BITS+VPN_BITS));
|
||||||
val r_refill_waddr = Reg(resetVal = UFix(0, addr_bits));
|
val r_refill_waddr = Reg(resetVal = UFix(0, addr_bits));
|
||||||
val repl_count = Reg(resetVal = UFix(0, addr_bits));
|
val repl_count = Reg(resetVal = UFix(0, addr_bits));
|
||||||
@ -99,12 +103,12 @@ class rocketITLB(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_mode = io.cpu.status(6).toBool;
|
val status_mode = io.cpu.status(6).toBool; // user/supervisor mode
|
||||||
val status_vm = io.cpu.status(16).toBool
|
val status_vm = io.cpu.status(16).toBool // virtual memory enable
|
||||||
|
|
||||||
// extract fields from PT permission bits
|
// extract fields from PT permission bits
|
||||||
val ptw_perm_ux = io.ptw.resp_perm(4);
|
val ptw_perm_ux = io.ptw.resp_perm(0);
|
||||||
val ptw_perm_sx = io.ptw.resp_perm(7);
|
val ptw_perm_sx = io.ptw.resp_perm(3);
|
||||||
|
|
||||||
// valid bit array
|
// valid bit array
|
||||||
val vb_array = Reg(resetVal = Bits(0, entries));
|
val vb_array = Reg(resetVal = Bits(0, entries));
|
||||||
@ -120,7 +124,14 @@ class rocketITLB(entries: Int) extends Component
|
|||||||
val sx_array = Reg(resetVal = Bits(0, entries)); // supervisor execute permission
|
val sx_array = Reg(resetVal = Bits(0, entries)); // supervisor execute permission
|
||||||
when (io.ptw.resp_val) {
|
when (io.ptw.resp_val) {
|
||||||
ux_array <== ux_array.bitSet(r_refill_waddr, ptw_perm_ux);
|
ux_array <== ux_array.bitSet(r_refill_waddr, ptw_perm_ux);
|
||||||
sx_array <== ux_array.bitSet(r_refill_waddr, ptw_perm_sx);
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// high if there are any unused (invalid) entries in the ITLB
|
// high if there are any unused (invalid) entries in the ITLB
|
||||||
@ -150,11 +161,14 @@ class rocketITLB(entries: Int) extends Component
|
|||||||
|
|
||||||
io.cpu.req_rdy := (state === s_ready);
|
io.cpu.req_rdy := (state === s_ready);
|
||||||
io.cpu.resp_val := Mux(status_vm, tag_hit, io.cpu.req_val);
|
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_ppn := Mux(status_vm, io.cpu.req_vpn(PPN_BITS-1, 0), tag_ram(tag_hit_addr));
|
||||||
io.cpu.exception := itlb_exception;
|
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 := status_vm && itlb_exception;
|
||||||
|
|
||||||
io.ptw.req_val := (state === s_request);
|
io.ptw.req_val := (state === s_request);
|
||||||
io.ptw.req_vpn := r_refill_tag;
|
io.ptw.req_vpn := r_refill_tag(VPN_BITS-1,0);
|
||||||
|
|
||||||
// control state machine
|
// control state machine
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -169,7 +183,7 @@ class rocketITLB(entries: Int) extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is (s_wait) {
|
is (s_wait) {
|
||||||
when (io.ptw.resp_val) {
|
when (io.ptw.resp_val || io.ptw.resp_err) {
|
||||||
state <== s_ready;
|
state <== s_ready;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class rocketPTW extends Component
|
|||||||
when (io.dmem.resp_val) {
|
when (io.dmem.resp_val) {
|
||||||
req_addr <== Cat(io.dmem.resp_data(PADDR_BITS-1, PGIDX_BITS), vpn_idx).toUFix;
|
req_addr <== Cat(io.dmem.resp_data(PADDR_BITS-1, PGIDX_BITS), vpn_idx).toUFix;
|
||||||
r_resp_perm <== io.dmem.resp_data(9,4);
|
r_resp_perm <== io.dmem.resp_data(9,4);
|
||||||
r_resp_ppn <== io.dmem.resp_data(PPN_BITS-1, PGIDX_BITS);
|
r_resp_ppn <== io.dmem.resp_data(PADDR_BITS-1, PGIDX_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
io.dmem.req_val :=
|
io.dmem.req_val :=
|
||||||
@ -78,12 +78,13 @@ class rocketPTW extends Component
|
|||||||
io.dmem.req_type := MT_D;
|
io.dmem.req_type := MT_D;
|
||||||
io.dmem.req_addr := req_addr;
|
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_val := (state === s_done) || (state === s_l1_fake) || (state === s_l2_fake);
|
||||||
io.itlb.resp_err := (state === s_error);
|
io.itlb.resp_err := (state === s_error);
|
||||||
io.itlb.resp_perm := r_resp_perm;
|
io.itlb.resp_perm := r_resp_perm;
|
||||||
io.itlb.resp_ppn :=
|
io.itlb.resp_ppn :=
|
||||||
Mux(state === s_l1_fake, Cat(r_resp_ppn(PADDR_BITS-1, PADDR_BITS-7), r_req_vpn(VPN_BITS-8, 0)),
|
Mux(state === s_l1_fake, Cat(r_resp_ppn(PPN_BITS-1, PPN_BITS-7), r_req_vpn(VPN_BITS-8, 0)),
|
||||||
Mux(state === s_l2_fake, Cat(r_resp_ppn(PADDR_BITS-1, PADDR_BITS-17), r_req_vpn(VPN_BITS-18, 0)),
|
Mux(state === s_l2_fake, Cat(r_resp_ppn(PPN_BITS-1, PPN_BITS-17), r_req_vpn(VPN_BITS-18, 0)),
|
||||||
r_resp_ppn));
|
r_resp_ppn));
|
||||||
|
|
||||||
val resp_ptd = (io.dmem.resp_data(1,0) === Bits(1,2));
|
val resp_ptd = (io.dmem.resp_data(1,0) === Bits(1,2));
|
||||||
|
Loading…
Reference in New Issue
Block a user