integrating ITLB & PTW
This commit is contained in:
		@@ -128,6 +128,7 @@ object Constants
 | 
			
		||||
  val M_FRD     = Bits("b0010", 4); // fp load
 | 
			
		||||
  val M_FWR     = Bits("b0011", 4); // fp store
 | 
			
		||||
  val M_FLA     = Bits("b0100", 4); // flush cache
 | 
			
		||||
  val M_PRD     = Bits("b0101", 4); // PTW load
 | 
			
		||||
  val M_XA_ADD  = Bits("b1000", 4);
 | 
			
		||||
  val M_XA_SWAP = Bits("b1001", 4);
 | 
			
		||||
  val M_XA_AND  = Bits("b1010", 4);
 | 
			
		||||
@@ -145,12 +146,26 @@ object Constants
 | 
			
		||||
  val PCR_COMPARE  = UFix( 5, 5);
 | 
			
		||||
  val PCR_CAUSE    = UFix( 6, 5);
 | 
			
		||||
  val PCR_MEMSIZE  = UFix( 8, 5);
 | 
			
		||||
  val PCR_PTBR     = UFix( 9, 5);
 | 
			
		||||
  val PCR_LOG      = UFix(10, 5);
 | 
			
		||||
  val PCR_TOHOST   = UFix(16, 5);
 | 
			
		||||
  val PCR_FROMHOST = UFix(17, 5);
 | 
			
		||||
  val PCR_CONSOLE  = UFix(18, 5);
 | 
			
		||||
  val PCR_K0       = UFix(24, 5);
 | 
			
		||||
  val PCR_K1       = UFix(25, 5);
 | 
			
		||||
  
 | 
			
		||||
  val PADDR_BITS = 40;
 | 
			
		||||
  val VADDR_BITS = 43;
 | 
			
		||||
  val PGIDX_BITS = 13;
 | 
			
		||||
  val PPN_BITS = PADDR_BITS-PGIDX_BITS;
 | 
			
		||||
  val VPN_BITS = VADDR_BITS-PGIDX_BITS;
 | 
			
		||||
  val ASID_BITS = 7;
 | 
			
		||||
  val PERM_BITS = 6;
 | 
			
		||||
  
 | 
			
		||||
  val ITLB_ENTRIES = 8;
 | 
			
		||||
  
 | 
			
		||||
  val HAVE_FPU = Bool(false);
 | 
			
		||||
  val HAVE_VEC = Bool(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
package Top {
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import Chisel._;
 | 
			
		||||
import Node._;
 | 
			
		||||
import Constants._;
 | 
			
		||||
 | 
			
		||||
@@ -45,17 +45,56 @@ class rocketProc extends Component
 | 
			
		||||
  val ctrl  = new rocketCtrl();      
 | 
			
		||||
  val dpath = new rocketDpath();
 | 
			
		||||
 | 
			
		||||
  ctrl.io.dpath             <> dpath.io.ctrl;
 | 
			
		||||
  ctrl.io.dmem              ^^ io.dmem;
 | 
			
		||||
  ctrl.io.host.start        ^^ io.host.start;
 | 
			
		||||
  ctrl.io.imem              ^^ io.imem;
 | 
			
		||||
  val itlb  = new rocketITLB(ITLB_ENTRIES);
 | 
			
		||||
  val ptw   = new rocketPTW();
 | 
			
		||||
  val arb   = new rocketDmemArbiter();
 | 
			
		||||
 | 
			
		||||
  dpath.io.dmem             ^^ io.dmem;
 | 
			
		||||
  dpath.io.imem.req_addr    ^^ io.imem.req_addr;
 | 
			
		||||
  ctrl.io.dpath             <> dpath.io.ctrl;
 | 
			
		||||
//  ctrl.io.dmem              ^^ io.dmem;
 | 
			
		||||
  ctrl.io.host.start        ^^ io.host.start;
 | 
			
		||||
//  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;
 | 
			
		||||
  dpath.io.host             ^^ io.host;
 | 
			
		||||
  dpath.io.debug            ^^ io.debug;
 | 
			
		||||
 | 
			
		||||
  itlb.io.cpu.invalidate  := Bool(false);
 | 
			
		||||
  itlb.io.cpu.status      := dpath.io.ctrl.status;
 | 
			
		||||
  itlb.io.cpu.req_val     := ctrl.io.imem.req_val;
 | 
			
		||||
  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_vpn     := dpath.io.imem.req_addr(VADDR_BITS-1,PGIDX_BITS);
 | 
			
		||||
  
 | 
			
		||||
  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;
 | 
			
		||||
  
 | 
			
		||||
  ctrl.io.imem.resp_val   := io.imem.resp_val;
 | 
			
		||||
  dpath.io.itlb_xcpt      := itlb.io.cpu.exception;
 | 
			
		||||
  
 | 
			
		||||
  ptw.io.itlb             <> itlb.io.ptw;
 | 
			
		||||
  ptw.io.ptbr             := dpath.io.ptbr;
 | 
			
		||||
  
 | 
			
		||||
  arb.io.ptw              <> ptw.io.dmem;
 | 
			
		||||
  arb.io.mem              ^^ io.dmem
 | 
			
		||||
  
 | 
			
		||||
  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);
 | 
			
		||||
  io.console.bits     := Bits(0,8);
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@ class ioCtrlDpath extends Bundle()
 | 
			
		||||
  val mem_waddr = UFix(5,'input); // write addr from memory stage
 | 
			
		||||
  val wb_waddr = UFix(5,'input); // write addr from writeback stage
 | 
			
		||||
  val exception = Bool('input);
 | 
			
		||||
  val status  = Bits(8, 'input);
 | 
			
		||||
  val status  = Bits(17, 'input);
 | 
			
		||||
  val sboard_clr0  = Bool('input);
 | 
			
		||||
  val sboard_clr0a = UFix(5, 'input);
 | 
			
		||||
  val sboard_clr1  = Bool('input);
 | 
			
		||||
@@ -67,6 +67,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", "resp_val")).flip();
 | 
			
		||||
  val host    = new ioHost(List("start"));
 | 
			
		||||
//   val itlb_xcpt = Bool('input);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketCtrl extends Component
 | 
			
		||||
 
 | 
			
		||||
@@ -5,24 +5,24 @@ import Node._;
 | 
			
		||||
import Constants._;
 | 
			
		||||
import scala.math._;
 | 
			
		||||
 | 
			
		||||
// interface between D$ and processor
 | 
			
		||||
// interface between D$ and processor pipeline
 | 
			
		||||
class ioDmem(view: List[String] = null) extends Bundle(view) {
 | 
			
		||||
  val req_val   = Bool('input);
 | 
			
		||||
  val req_rdy   = Bool('output);
 | 
			
		||||
  val req_cmd   = Bits(4, 'input);
 | 
			
		||||
  val req_type  = Bits(3, 'input);
 | 
			
		||||
  val req_addr  = UFix(32, 'input);
 | 
			
		||||
  val req_addr  = UFix(PADDR_BITS, 'input);
 | 
			
		||||
  val req_data  = Bits(64, 'input);
 | 
			
		||||
  val req_tag   = Bits(5, 'input);
 | 
			
		||||
  val resp_miss = Bool('output);
 | 
			
		||||
  val resp_val  = Bool('output);
 | 
			
		||||
  val resp_data = Bits(64, 'output);
 | 
			
		||||
  val resp_tag  = Bits(12, 'output);
 | 
			
		||||
  val resp_tag  = Bits(13, 'output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// interface between D$ and memory
 | 
			
		||||
// interface between D$ and next level in memory hierarchy
 | 
			
		||||
class ioDcache(view: List[String] = null) extends Bundle(view) {
 | 
			
		||||
  val req_addr  = UFix(32, 'input);
 | 
			
		||||
  val req_addr  = UFix(PADDR_BITS, 'input);
 | 
			
		||||
  val req_tag   = UFix(3, 'input);
 | 
			
		||||
  val req_val   = Bool('input);
 | 
			
		||||
  val req_rdy   = Bool('output);
 | 
			
		||||
@@ -39,10 +39,11 @@ class ioDCacheDM extends Bundle() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// state machine to flush (write back dirty lines, invalidate clean ones) the D$
 | 
			
		||||
class rocketDCacheDM_flush(lines: Int, addrbits: Int) extends Component {
 | 
			
		||||
class rocketDCacheDM_flush(lines: Int) extends Component {
 | 
			
		||||
  val io = new ioDCacheDM();
 | 
			
		||||
  val dcache = new rocketDCacheDM(lines, addrbits);
 | 
			
		||||
  val dcache = new rocketDCacheDM(lines);
 | 
			
		||||
  
 | 
			
		||||
  val addrbits = PADDR_BITS;
 | 
			
		||||
  val indexbits = ceil(log10(lines)/log10(2)).toInt;
 | 
			
		||||
  val offsetbits = 6;
 | 
			
		||||
  val tagmsb    = addrbits - 1;
 | 
			
		||||
@@ -65,15 +66,19 @@ class rocketDCacheDM_flush(lines: Int, addrbits: Int) extends Component {
 | 
			
		||||
    flush_waiting <== Bool(true);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  when (dcache.io.cpu.req_rdy && 
 | 
			
		||||
        (flush_count === ~Bits(0, indexbits))) { 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); }
 | 
			
		||||
  when (dcache.io.cpu.req_rdy && (flush_count === ~Bits(0, indexbits))) {
 | 
			
		||||
    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);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  when (flushing && dcache.io.cpu.req_rdy) { 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); }
 | 
			
		||||
  when (flushing && dcache.io.cpu.req_rdy) {
 | 
			
		||||
    flush_count <== flush_count + UFix(1,1);
 | 
			
		||||
  }
 | 
			
		||||
  when (flush_waiting && dcache.io.cpu.resp_val && (dcache.io.cpu.resp_tag(5,0) === r_cpu_req_tag)) {
 | 
			
		||||
    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;
 | 
			
		||||
  dcache.io.cpu.req_cmd   := Mux(flushing, M_FLA, io.cpu.req_cmd);
 | 
			
		||||
@@ -92,9 +97,10 @@ class rocketDCacheDM_flush(lines: Int, addrbits: Int) extends Component {
 | 
			
		||||
  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketDCacheDM(lines: Int, addrbits: Int) extends Component {
 | 
			
		||||
class rocketDCacheDM(lines: Int) extends Component {
 | 
			
		||||
  val io = new ioDCacheDM();
 | 
			
		||||
  
 | 
			
		||||
  val addrbits = PADDR_BITS;
 | 
			
		||||
  val indexbits = ceil(log10(lines)/log10(2)).toInt;
 | 
			
		||||
  val offsetbits = 6;
 | 
			
		||||
  val tagmsb    = addrbits - 1;
 | 
			
		||||
@@ -119,9 +125,10 @@ class rocketDCacheDM(lines: Int, addrbits: Int) extends Component {
 | 
			
		||||
  val p_store_type   = Reg(resetVal = Bits(0,3));
 | 
			
		||||
  val p_store_valid  = Reg(resetVal = Bool(false));
 | 
			
		||||
 | 
			
		||||
  val req_load  = (r_cpu_req_cmd === M_XRD);
 | 
			
		||||
  val req_load  = (r_cpu_req_cmd === M_XRD) || (r_cpu_req_cmd === M_PRD);
 | 
			
		||||
  val req_store = (r_cpu_req_cmd === M_XWR);
 | 
			
		||||
  val req_flush = (r_cpu_req_cmd === M_FLA);
 | 
			
		||||
  val req_ptw_load = (r_cpu_req_cmd === M_PRD);
 | 
			
		||||
 | 
			
		||||
  when (io.cpu.req_val && io.cpu.req_rdy) { 
 | 
			
		||||
    r_cpu_req_addr  <== io.cpu.req_addr;
 | 
			
		||||
@@ -288,7 +295,8 @@ class rocketDCacheDM(lines: Int, addrbits: Int) extends Component {
 | 
			
		||||
                      ((state === s_resolve_miss) && req_flush);
 | 
			
		||||
                      
 | 
			
		||||
  io.cpu.resp_miss := miss;
 | 
			
		||||
  io.cpu.resp_tag  := Cat(Bits(0,1), r_cpu_req_type, r_cpu_req_addr(2,0), r_cpu_req_tag);
 | 
			
		||||
//   io.cpu.resp_tag  := Cat(Bits(0,1), r_cpu_req_type, r_cpu_req_addr(2,0), r_cpu_req_tag);
 | 
			
		||||
  io.cpu.resp_tag  := Cat(req_ptw_load, r_cpu_req_type, r_cpu_req_addr(2,0), r_cpu_req_tag);
 | 
			
		||||
  io.cpu.resp_data := 
 | 
			
		||||
    Mux(r_cpu_req_addr(offsetlsb).toBool, data_array_rdata(127, 64), 
 | 
			
		||||
      data_array_rdata(63,0));
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,8 @@ class ioDpathAll extends Bundle()
 | 
			
		||||
  val debug = new ioDebug();
 | 
			
		||||
  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 itlb_xcpt = Bool('input);
 | 
			
		||||
  val ptbr = UFix(PADDR_BITS, 'output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketDpath extends Component
 | 
			
		||||
@@ -45,14 +47,14 @@ class rocketDpath extends Component
 | 
			
		||||
 | 
			
		||||
  // instruction decode definitions
 | 
			
		||||
  val id_reg_valid     = Reg(resetVal = Bool(false));
 | 
			
		||||
  val id_reg_pc        = Reg(resetVal = UFix(0,32));
 | 
			
		||||
  val id_reg_pc_plus4  = Reg(resetVal = UFix(0,32));
 | 
			
		||||
  val id_reg_pc        = Reg(resetVal = UFix(0,VADDR_BITS));
 | 
			
		||||
  val id_reg_pc_plus4  = Reg(resetVal = UFix(0,VADDR_BITS));
 | 
			
		||||
  val id_reg_inst      = Reg(resetVal = NOP);
 | 
			
		||||
 | 
			
		||||
  // execute definitions
 | 
			
		||||
  val ex_reg_valid          = Reg(resetVal = Bool(false));
 | 
			
		||||
  val ex_reg_pc             = Reg(resetVal = UFix(0,32));
 | 
			
		||||
  val ex_reg_pc_plus4       = Reg(resetVal = UFix(0,32));
 | 
			
		||||
  val ex_reg_pc             = Reg(resetVal = UFix(0,VADDR_BITS));
 | 
			
		||||
  val ex_reg_pc_plus4       = Reg(resetVal = UFix(0,VADDR_BITS));
 | 
			
		||||
  val ex_reg_inst           = Reg(resetVal = Bits(0,32));
 | 
			
		||||
  val ex_reg_raddr2         = Reg(resetVal = UFix(0,5));
 | 
			
		||||
  val ex_reg_raddr1         = Reg(resetVal = UFix(0,5));
 | 
			
		||||
@@ -79,8 +81,8 @@ class rocketDpath extends Component
 | 
			
		||||
 | 
			
		||||
  // memory definitions
 | 
			
		||||
  val mem_reg_valid          = Reg(resetVal = Bool(false));
 | 
			
		||||
  val mem_reg_pc             = Reg(resetVal = UFix(0,32));
 | 
			
		||||
  val mem_reg_pc_plus4       = Reg(resetVal = UFix(0,32));
 | 
			
		||||
  val mem_reg_pc             = Reg(resetVal = UFix(0,VADDR_BITS));
 | 
			
		||||
  val mem_reg_pc_plus4       = Reg(resetVal = UFix(0,VADDR_BITS));
 | 
			
		||||
  val mem_reg_waddr          = Reg(resetVal = UFix(0,5));
 | 
			
		||||
  val mem_reg_wdata          = Reg(resetVal = Bits(0,64));
 | 
			
		||||
  val mem_reg_raddr2         = Reg(resetVal = UFix(0,5));
 | 
			
		||||
@@ -94,7 +96,7 @@ class rocketDpath extends Component
 | 
			
		||||
  
 | 
			
		||||
  // writeback definitions
 | 
			
		||||
  val wb_reg_valid          = Reg(resetVal = Bool(false));
 | 
			
		||||
  val wb_reg_pc             = Reg(resetVal = UFix(0,32));
 | 
			
		||||
  val wb_reg_pc             = Reg(resetVal = UFix(0,VADDR_BITS));
 | 
			
		||||
  val wb_reg_waddr          = Reg(resetVal = UFix(0,5));
 | 
			
		||||
  val wb_reg_wdata          = Reg(resetVal = Bits(0,64));
 | 
			
		||||
  val wb_reg_ctrl_ll_wb     = Reg(resetVal = Bool(false));
 | 
			
		||||
@@ -112,7 +114,7 @@ class rocketDpath extends Component
 | 
			
		||||
  val r_dmem_resp_data      = Reg(resetVal = Bits(0,64));
 | 
			
		||||
  
 | 
			
		||||
  // instruction fetch stage
 | 
			
		||||
  val if_pc_plus4 = if_reg_pc + UFix(4, 32);
 | 
			
		||||
  val if_pc_plus4 = if_reg_pc + UFix(4);
 | 
			
		||||
 | 
			
		||||
  val ex_sign_extend = 
 | 
			
		||||
    Cat(Fill(52, ex_reg_inst(21)), ex_reg_inst(21,10));
 | 
			
		||||
@@ -135,17 +137,18 @@ class rocketDpath extends Component
 | 
			
		||||
    Mux(io.ctrl.sel_pc === PC_BR,  ex_branch_target,
 | 
			
		||||
    Mux(io.ctrl.sel_pc === PC_J,   ex_branch_target,
 | 
			
		||||
    Mux(io.ctrl.sel_pc === PC_JR,  ex_jr_target.toUFix,
 | 
			
		||||
    Mux(io.ctrl.sel_pc === PC_PCR, mem_reg_pcr(31,0).toUFix,
 | 
			
		||||
    Mux(io.ctrl.sel_pc === PC_PCR, mem_reg_pcr(VADDR_BITS-1,0).toUFix,
 | 
			
		||||
    Mux(io.ctrl.sel_pc === PC_MEM, mem_reg_pc, 
 | 
			
		||||
        UFix(0, 32))))))))));
 | 
			
		||||
        UFix(0, VADDR_BITS))))))))));
 | 
			
		||||
 | 
			
		||||
  when (!io.host.start){
 | 
			
		||||
    if_reg_pc <== UFix(0, 32); //32'hFFFF_FFFC;
 | 
			
		||||
    if_reg_pc <== UFix(0, VADDR_BITS); //32'hFFFF_FFFC;
 | 
			
		||||
  }  
 | 
			
		||||
  when (!io.ctrl.stallf) {
 | 
			
		||||
    if_reg_pc <== if_next_pc;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
  io.imem.req_addr :=
 | 
			
		||||
    Mux(io.ctrl.stallf, if_reg_pc,
 | 
			
		||||
        if_next_pc);
 | 
			
		||||
@@ -334,7 +337,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_out;
 | 
			
		||||
  io.dmem.req_addr  := ex_alu_out(PADDR_BITS-1,0);
 | 
			
		||||
  io.dmem.req_data  := ex_reg_rs2;
 | 
			
		||||
  io.dmem.req_tag   := ex_reg_waddr;
 | 
			
		||||
 | 
			
		||||
@@ -355,6 +358,7 @@ class rocketDpath extends Component
 | 
			
		||||
//   pcr.io.pc					:= ex_reg_pc;
 | 
			
		||||
  
 | 
			
		||||
  io.ctrl.status       := pcr.io.status;
 | 
			
		||||
  io.ptbr              := pcr.io.ptbr;
 | 
			
		||||
 	io.debug.error_mode  := pcr.io.debug.error_mode;
 | 
			
		||||
 	io.debug.log_control := pcr.io.debug.log_control;
 | 
			
		||||
  
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,18 @@
 | 
			
		||||
package Top
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import Chisel._;
 | 
			
		||||
import Node._;
 | 
			
		||||
 | 
			
		||||
import Constants._;
 | 
			
		||||
 | 
			
		||||
class ioDpathBTB extends Bundle()
 | 
			
		||||
{
 | 
			
		||||
  val current_pc4    = UFix(32, 'input);
 | 
			
		||||
  val current_pc4    = UFix(VADDR_BITS, 'input);
 | 
			
		||||
  val hit            = Bool('output);
 | 
			
		||||
  val target         = UFix(32, 'output);
 | 
			
		||||
  val target         = UFix(VADDR_BITS, 'output);
 | 
			
		||||
  val wen            = Bool('input);
 | 
			
		||||
  val correct_pc4    = UFix(32, 'input);
 | 
			
		||||
  val correct_target = UFix(32, 'input);
 | 
			
		||||
  val correct_pc4    = UFix(VADDR_BITS, 'input);
 | 
			
		||||
  val correct_target = UFix(VADDR_BITS, 'input);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketDpathBTB extends Component
 | 
			
		||||
@@ -21,11 +20,15 @@ class rocketDpathBTB extends Component
 | 
			
		||||
  override val io = new ioDpathBTB();
 | 
			
		||||
  val rst_lwlr_pf  = Mem(4, io.wen, io.correct_pc4(3, 2), UFix(1, 1), resetVal = UFix(0, 1)); 
 | 
			
		||||
  val lwlr_pf      = Mem(4, io.wen, io.correct_pc4(3, 2), 
 | 
			
		||||
                         Cat(io.correct_pc4(31,4), io.correct_target(31,2)), resetVal = UFix(0, 1));
 | 
			
		||||
                         Cat(io.correct_pc4(VADDR_BITS-1,4), io.correct_target(VADDR_BITS-1,2)), resetVal = UFix(0, 1));
 | 
			
		||||
//                          Cat(io.correct_pc4(31,4), io.correct_target(31,2)), resetVal = UFix(0, 1));
 | 
			
		||||
  val is_val       = rst_lwlr_pf(io.current_pc4(3, 2));
 | 
			
		||||
  val tag_target   = lwlr_pf(io.current_pc4(3, 2));
 | 
			
		||||
  io.hit    := (is_val & (tag_target(57,30) === io.current_pc4(31, 4))).toBool;
 | 
			
		||||
  io.target := Cat(tag_target(29, 0), Bits(0,2)).toUFix;
 | 
			
		||||
  io.hit    := (is_val & (tag_target(2*VADDR_BITS-7,VADDR_BITS-2) === io.current_pc4(VADDR_BITS-1, 4))).toBool;
 | 
			
		||||
  io.target := Cat(tag_target(VADDR_BITS-3, 0), Bits(0,2)).toUFix;
 | 
			
		||||
  
 | 
			
		||||
//   io.hit    := (is_val & (tag_target(57,30) === io.current_pc4(31, 4))).toBool;
 | 
			
		||||
//   io.target := Cat(tag_target(29, 0), Bits(0,2)).toUFix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ioDpathPCR extends Bundle()
 | 
			
		||||
@@ -35,20 +38,19 @@ class ioDpathPCR extends Bundle()
 | 
			
		||||
  val r     = new ioReadPort();
 | 
			
		||||
  val w     = new ioWritePort();
 | 
			
		||||
  
 | 
			
		||||
  val status 		= Bits(8, 'output);
 | 
			
		||||
  val status 		= Bits(17, 'output);
 | 
			
		||||
  val ptbr      = UFix(PADDR_BITS, 'output);
 | 
			
		||||
  val exception = Bool('input);
 | 
			
		||||
  val cause 		= UFix(5, 'input);
 | 
			
		||||
  val pc    		= UFix(32, 'input);
 | 
			
		||||
  val pc    		= UFix(VADDR_BITS, 'input);
 | 
			
		||||
  val eret  		= Bool('input);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketDpathPCR extends Component
 | 
			
		||||
{
 | 
			
		||||
  override val io = new ioDpathPCR();
 | 
			
		||||
  
 | 
			
		||||
  val HAVE_FPU = Bool(false);
 | 
			
		||||
  val HAVE_VEC = Bool(false);
 | 
			
		||||
  val io = new ioDpathPCR();
 | 
			
		||||
  val w = 32;
 | 
			
		||||
  
 | 
			
		||||
  val reg_epc      = Reg(resetVal = Bits(0, w)); 
 | 
			
		||||
  val reg_badvaddr = Reg(resetVal = Bits(0, w)); 
 | 
			
		||||
  val reg_ebase    = Reg(resetVal = Bits(0, w)); 
 | 
			
		||||
@@ -59,9 +61,11 @@ class rocketDpathPCR extends Component
 | 
			
		||||
  val reg_fromhost = Reg(resetVal = Bits(0, w));
 | 
			
		||||
  val reg_k0       = Reg(resetVal = Bits(0, 2*w));
 | 
			
		||||
  val reg_k1       = Reg(resetVal = Bits(0, 2*w));
 | 
			
		||||
  val reg_ptbr     = Reg(resetVal = UFix(0, PADDR_BITS));
 | 
			
		||||
  
 | 
			
		||||
  val reg_error_mode  = Reg(resetVal = Bool(false));
 | 
			
		||||
  val reg_log_control = Reg(resetVal = Bool(false));
 | 
			
		||||
  val reg_status_vm   = Reg(resetVal = Bool(false));
 | 
			
		||||
  val reg_status_im   = Reg(resetVal = Bits(0,8));
 | 
			
		||||
  val reg_status_sx   = Reg(resetVal = Bool(true));
 | 
			
		||||
  val reg_status_ux   = Reg(resetVal = Bool(true));
 | 
			
		||||
@@ -74,7 +78,8 @@ class rocketDpathPCR extends Component
 | 
			
		||||
  val reg_status = Cat(reg_status_sx, reg_status_ux, reg_status_s, reg_status_ps, Bits(0,1), reg_status_ev, reg_status_ef, reg_status_et);
 | 
			
		||||
  val rdata = Wire() { Bits() };
 | 
			
		||||
 | 
			
		||||
  io.status  						:= reg_status;
 | 
			
		||||
  io.status  						:= Cat(reg_status_vm, reg_status_im, reg_status);
 | 
			
		||||
  io.ptbr               := reg_ptbr;
 | 
			
		||||
  io.host.to 						:= Mux(io.host.from_wen, Bits(0, w), reg_tohost);
 | 
			
		||||
  io.debug.error_mode  	:= reg_error_mode;
 | 
			
		||||
  io.debug.log_control 	:= reg_log_control;
 | 
			
		||||
@@ -110,6 +115,7 @@ class rocketDpathPCR extends Component
 | 
			
		||||
 | 
			
		||||
  when (!io.exception && !io.eret && io.w.en) {
 | 
			
		||||
  	when (io.w.addr === PCR_STATUS) {
 | 
			
		||||
  	  reg_status_vm <== io.w.data(16).toBool;
 | 
			
		||||
	    reg_status_im <== io.w.data(15,8);
 | 
			
		||||
      reg_status_sx <== io.w.data(7).toBool;
 | 
			
		||||
      reg_status_ux <== io.w.data(6).toBool;
 | 
			
		||||
@@ -129,11 +135,12 @@ class rocketDpathPCR extends Component
 | 
			
		||||
  	when (io.w.addr === PCR_FROMHOST) { reg_fromhost 		<== io.w.data(w-1,0); }
 | 
			
		||||
  	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.r.en) { rdata <== Bits(0,2*w); }
 | 
			
		||||
  switch (io.r.addr) {
 | 
			
		||||
    is (PCR_STATUS) 	{ rdata <== Cat(Bits(0,w+16), reg_status_im, reg_status); }
 | 
			
		||||
    is (PCR_STATUS) 	{ rdata <== Cat(Bits(0,w+15), reg_status_vm, reg_status_im, reg_status); }
 | 
			
		||||
    is (PCR_EPC) 			{ rdata <== Cat(Fill(w, reg_epc(w-1)), reg_epc); }
 | 
			
		||||
    is (PCR_BADVADDR) { rdata <== Cat(Fill(w, reg_badvaddr(w-1)), reg_badvaddr); }
 | 
			
		||||
    is (PCR_EVEC) 		{ rdata <== Cat(Fill(w, reg_ebase(w-1)), reg_ebase); }
 | 
			
		||||
@@ -146,6 +153,7 @@ class rocketDpathPCR extends Component
 | 
			
		||||
    is (PCR_TOHOST)  	{ rdata <== Cat(Fill(w, reg_tohost(w-1)), reg_tohost); }
 | 
			
		||||
    is (PCR_K0) 			{ rdata <== reg_k0; }
 | 
			
		||||
    is (PCR_K1) 			{ rdata <== reg_k1; }
 | 
			
		||||
    is (PCR_PTBR) 		{ rdata <== Cat(Bits(0,2*w-PADDR_BITS), reg_ptbr); }
 | 
			
		||||
    otherwise					{ rdata <== Bits(0,2*w); }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
package Top {
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import Chisel._;
 | 
			
		||||
import Node._;
 | 
			
		||||
import Constants._;
 | 
			
		||||
import scala.math._;
 | 
			
		||||
 | 
			
		||||
// interface between I$ and processor (32 bits wide)
 | 
			
		||||
@@ -17,7 +18,7 @@ class ioImem(view: List[String] = null) extends Bundle (view)
 | 
			
		||||
// interface between I$ and memory (128 bits wide)
 | 
			
		||||
class ioIcache(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_rdy   = Bool('output);
 | 
			
		||||
  val resp_data = Bits(128, 'output);
 | 
			
		||||
@@ -55,9 +56,10 @@ class rocketSRAMsp(entries: Int, width: Int) extends Component {
 | 
			
		||||
//    addr_bits = address width (word addressable) bits
 | 
			
		||||
//    32 bit wide cpu port, 128 bit wide memory port, 64 byte cachelines
 | 
			
		||||
 | 
			
		||||
class rocketICacheDM(lines: Int, addrbits : Int) extends Component {
 | 
			
		||||
class rocketICacheDM(lines: Int) extends Component {
 | 
			
		||||
  val io = new ioICacheDM();
 | 
			
		||||
 | 
			
		||||
  val addrbits = PADDR_BITS;
 | 
			
		||||
  val indexbits = ceil(log10(lines)/log10(2)).toInt;
 | 
			
		||||
  val offsetbits = 6;
 | 
			
		||||
  val tagmsb    = addrbits - 1;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										178
									
								
								rocket/src/main/scala/itlb.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								rocket/src/main/scala/itlb.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
package Top
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
import Chisel._;
 | 
			
		||||
import Node._;
 | 
			
		||||
import Constants._;
 | 
			
		||||
import scala.math._;
 | 
			
		||||
 | 
			
		||||
class ioCAM(addr_bits: Int, tag_bits: Int) extends Bundle {
 | 
			
		||||
    val tag          = Bits(tag_bits, 'input);
 | 
			
		||||
    val hit          = Bool('output);
 | 
			
		||||
    val hit_addr     = UFix(addr_bits, 'output);
 | 
			
		||||
    
 | 
			
		||||
    val write        = Bool('input);
 | 
			
		||||
    val write_tag    = Bits(tag_bits, 'input);
 | 
			
		||||
    val write_addr    = UFix(addr_bits, 'input);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketCAM(entries: Int, addr_bits: Int, tag_bits: Int) extends Component {
 | 
			
		||||
    val io = new ioCAM(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() };
 | 
			
		||||
    
 | 
			
		||||
    for (i <- 0 to entries-1) {
 | 
			
		||||
        when (cam_tags(UFix(i)) === io.tag) {
 | 
			
		||||
            l_hit      <== Bool(true);
 | 
			
		||||
            l_hit_addr <== UFix(i,addr_bits);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    l_hit <== Bool(false);
 | 
			
		||||
    l_hit_addr <== UFix(0, addr_bits);
 | 
			
		||||
    
 | 
			
		||||
    io.hit := l_hit;
 | 
			
		||||
    io.hit_addr := l_hit_addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// interface between TLB and PTW
 | 
			
		||||
class ioTLB_PTW extends Bundle
 | 
			
		||||
{
 | 
			
		||||
  // requests
 | 
			
		||||
  val req_val = Bool('output);
 | 
			
		||||
  val req_rdy = Bool('input);
 | 
			
		||||
  val req_vpn = Bits(VPN_BITS, 'output);
 | 
			
		||||
  // responses
 | 
			
		||||
  val resp_val = Bool('input);
 | 
			
		||||
  val resp_err = Bool('input);
 | 
			
		||||
  val resp_ppn = Bits(PPN_BITS, 'input);
 | 
			
		||||
  val resp_perm = Bits(PERM_BITS, 'input);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// interface between ITLB and fetch stage of pipeline
 | 
			
		||||
class ioITLB_CPU 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
 | 
			
		||||
  val req_val  = Bool('input);
 | 
			
		||||
  val req_rdy  = Bool('output);
 | 
			
		||||
  val req_asid = Bits(ASID_BITS, 'input);
 | 
			
		||||
  val req_vpn  = Bits(VPN_BITS, 'input);
 | 
			
		||||
  // lookup responses
 | 
			
		||||
  val resp_val = Bool('output);
 | 
			
		||||
  val resp_ppn = Bits(PPN_BITS, 'output);
 | 
			
		||||
  val exception = Bool('output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ioITLB extends Bundle
 | 
			
		||||
{
 | 
			
		||||
  val cpu = new ioITLB_CPU();
 | 
			
		||||
  val ptw = new ioTLB_PTW();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketITLB(entries: Int) extends Component
 | 
			
		||||
{
 | 
			
		||||
  val addr_bits = ceil(log10(entries)/log10(2)).toInt;  
 | 
			
		||||
  val io = new ioITLB();
 | 
			
		||||
 | 
			
		||||
  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 lookup_tag = Cat(io.cpu.req_asid, io.cpu.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;
 | 
			
		||||
  val status_vm   = io.cpu.status(16).toBool
 | 
			
		||||
  
 | 
			
		||||
  // extract fields from PT permission bits
 | 
			
		||||
  val ptw_perm_ux = io.ptw.resp_perm(4);
 | 
			
		||||
  val ptw_perm_sx = io.ptw.resp_perm(7);
 | 
			
		||||
  
 | 
			
		||||
  // 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 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 <== ux_array.bitSet(r_refill_waddr, ptw_perm_sx);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
  // high if there are any unused (invalid) entries in the ITLB
 | 
			
		||||
//   val invalid_entry = orR(~vb_array);
 | 
			
		||||
  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 itlb_exception = 
 | 
			
		||||
    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.exception := itlb_exception;
 | 
			
		||||
  
 | 
			
		||||
  io.ptw.req_val := (state === s_request);
 | 
			
		||||
  io.ptw.req_vpn := r_refill_tag;
 | 
			
		||||
  
 | 
			
		||||
  // 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) {
 | 
			
		||||
        state <== s_ready;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }  
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										168
									
								
								rocket/src/main/scala/ptw.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								rocket/src/main/scala/ptw.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
package Top {
 | 
			
		||||
 | 
			
		||||
import Chisel._;
 | 
			
		||||
import Node._;
 | 
			
		||||
import Constants._;
 | 
			
		||||
import scala.math._;
 | 
			
		||||
 | 
			
		||||
class ioDmemArbiter extends Bundle
 | 
			
		||||
{
 | 
			
		||||
  val ptw = new ioDmem(List("req_val", "req_rdy", "req_cmd", "req_type", "req_addr", "resp_data", "resp_val"));
 | 
			
		||||
  val cpu = new ioDmem();
 | 
			
		||||
  val mem = new ioDmem().flip();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketDmemArbiter extends Component
 | 
			
		||||
{
 | 
			
		||||
  val io = new ioDmemArbiter();
 | 
			
		||||
  
 | 
			
		||||
  io.mem.req_val  := io.ptw.req_val || io.cpu.req_val;
 | 
			
		||||
  io.mem.req_cmd  := Mux(io.ptw.req_val, io.ptw.req_cmd,  io.cpu.req_cmd);
 | 
			
		||||
  io.mem.req_type := Mux(io.ptw.req_val, io.ptw.req_type, io.cpu.req_type);
 | 
			
		||||
  io.mem.req_addr := Mux(io.ptw.req_val, io.ptw.req_addr, io.cpu.req_addr);
 | 
			
		||||
  io.mem.req_data := io.cpu.req_data;
 | 
			
		||||
  io.mem.req_tag  := Mux(io.ptw.req_val, Bits(0,5), io.cpu.req_tag);
 | 
			
		||||
  
 | 
			
		||||
  io.ptw.req_rdy   := io.mem.req_rdy;
 | 
			
		||||
  io.cpu.req_rdy   := io.mem.req_rdy && !io.ptw.req_val;  
 | 
			
		||||
  io.cpu.resp_miss := io.mem.resp_miss; // FIXME
 | 
			
		||||
 | 
			
		||||
  io.cpu.resp_val  := io.mem.resp_val && !io.mem.resp_tag(12).toBool;
 | 
			
		||||
  io.ptw.resp_val  := io.mem.resp_val &&  io.mem.resp_tag(12).toBool; 
 | 
			
		||||
 | 
			
		||||
  io.ptw.resp_data := io.mem.resp_data;
 | 
			
		||||
  io.cpu.resp_data := io.mem.resp_data;
 | 
			
		||||
  io.cpu.resp_tag  := io.mem.resp_tag;
 | 
			
		||||
  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ioPTW extends Bundle
 | 
			
		||||
{
 | 
			
		||||
  val itlb = 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class rocketPTW extends Component
 | 
			
		||||
{
 | 
			
		||||
  val io = new ioPTW();
 | 
			
		||||
  
 | 
			
		||||
  val s_ready :: s_l1_req :: s_l1_wait :: s_l1_fake :: s_l2_req :: s_l2_wait :: s_l2_fake:: s_l3_req :: s_l3_wait :: s_done :: s_error :: Nil = Enum(11) { UFix() };
 | 
			
		||||
  val state = Reg(resetVal = s_ready);
 | 
			
		||||
  
 | 
			
		||||
  val r_req_vpn = Reg(resetVal = Bits(0,VPN_BITS));
 | 
			
		||||
  
 | 
			
		||||
  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)); 
 | 
			
		||||
  
 | 
			
		||||
  when ((state === s_ready) && io.itlb.req_val) {
 | 
			
		||||
    r_req_vpn  <== io.itlb.req_vpn;
 | 
			
		||||
    req_addr <== Cat(io.ptbr(PADDR_BITS-1,PGIDX_BITS), io.itlb.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);
 | 
			
		||||
    r_resp_ppn <== io.dmem.resp_data(PPN_BITS-1, PGIDX_BITS);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  io.dmem.req_val :=
 | 
			
		||||
    (state === s_l1_req) ||
 | 
			
		||||
    (state === s_l2_req) ||
 | 
			
		||||
    (state === s_l3_req);
 | 
			
		||||
    
 | 
			
		||||
  io.dmem.req_cmd  := M_PRD;
 | 
			
		||||
  io.dmem.req_type := MT_D;
 | 
			
		||||
  io.dmem.req_addr := req_addr;
 | 
			
		||||
    
 | 
			
		||||
  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(PADDR_BITS-1, PADDR_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)),
 | 
			
		||||
      r_resp_ppn));
 | 
			
		||||
 | 
			
		||||
  val resp_ptd = (io.dmem.resp_data(1,0) === Bits(1,2));
 | 
			
		||||
  val resp_pte = (io.dmem.resp_data(1,0) === Bits(2,2));
 | 
			
		||||
  
 | 
			
		||||
  // control state machine
 | 
			
		||||
  switch (state) {
 | 
			
		||||
    is (s_ready) {
 | 
			
		||||
      when (io.itlb.req_val) {
 | 
			
		||||
        state <== s_l1_req;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // level 1
 | 
			
		||||
    is (s_l1_req) {
 | 
			
		||||
      when (io.dmem.req_rdy) {
 | 
			
		||||
        state <== s_l1_wait;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    is (s_l1_wait) {
 | 
			
		||||
      when (io.dmem.resp_val) {
 | 
			
		||||
        when (resp_ptd) { // page table descriptor
 | 
			
		||||
          state <== s_l2_req;
 | 
			
		||||
        }
 | 
			
		||||
        when (resp_pte) { // page table entry
 | 
			
		||||
          state <== s_l1_fake;
 | 
			
		||||
        }
 | 
			
		||||
        otherwise {
 | 
			
		||||
          state <== s_error;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    is (s_l1_fake) {
 | 
			
		||||
      state <== s_ready;
 | 
			
		||||
    }
 | 
			
		||||
    // level 2
 | 
			
		||||
    is (s_l2_req) {
 | 
			
		||||
      when (io.dmem.req_rdy) {
 | 
			
		||||
        state <== s_l2_wait;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    is (s_l2_wait) {
 | 
			
		||||
      when (io.dmem.resp_val) {
 | 
			
		||||
        when (resp_ptd) { // page table descriptor
 | 
			
		||||
          state <== s_l3_req;
 | 
			
		||||
        }
 | 
			
		||||
        when (resp_pte) { // page table entry
 | 
			
		||||
          state <== s_l2_fake;
 | 
			
		||||
        }
 | 
			
		||||
        otherwise {
 | 
			
		||||
          state <== s_error;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    is (s_l2_fake) {
 | 
			
		||||
      state <== s_ready;
 | 
			
		||||
    }
 | 
			
		||||
    // level 3
 | 
			
		||||
    is (s_l3_req) {
 | 
			
		||||
      when (io.dmem.req_rdy) {
 | 
			
		||||
        state <== s_l3_wait;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    is (s_l3_wait) {
 | 
			
		||||
      when (io.dmem.resp_val) {
 | 
			
		||||
        when (resp_pte) { // page table entry
 | 
			
		||||
          state <== s_done;
 | 
			
		||||
        }
 | 
			
		||||
        otherwise {
 | 
			
		||||
          state <== s_error;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }  
 | 
			
		||||
    is (s_done) {
 | 
			
		||||
      state <== s_ready;
 | 
			
		||||
    }
 | 
			
		||||
    is (s_error) {
 | 
			
		||||
      state <== s_ready;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -15,9 +15,9 @@ class Top() extends Component {
 | 
			
		||||
  val io        = new ioTop();
 | 
			
		||||
  
 | 
			
		||||
  val cpu       = new rocketProc();
 | 
			
		||||
  val icache    = new rocketICacheDM(128, 32); // lines, address bits
 | 
			
		||||
  val icache    = new rocketICacheDM(128); // # 64 byte cache lines
 | 
			
		||||
  val icache_pf = new rocketIPrefetcher();
 | 
			
		||||
  val dcache    = new rocketDCacheDM_flush(128, 32);
 | 
			
		||||
  val dcache    = new rocketDCacheDM_flush(128);
 | 
			
		||||
  val arbiter   = new rocketMemArbiter();
 | 
			
		||||
 | 
			
		||||
  arbiter.io.mem    ^^ io.mem; 
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								rocket/src/main/scala/util.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								rocket/src/main/scala/util.scala
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
package Top
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import Node._;
 | 
			
		||||
import scala.math._;
 | 
			
		||||
 | 
			
		||||
class ioPriorityDecoder(in_width: Int, out_width: Int) extends Bundle
 | 
			
		||||
{
 | 
			
		||||
  val in  = UFix(in_width, 'input);
 | 
			
		||||
  val out = Bits(out_width, 'output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class priorityDecoder(width: Int) extends Component
 | 
			
		||||
{
 | 
			
		||||
  val in_width = ceil(log10(width)/log10(2)).toInt;  
 | 
			
		||||
  val io = new ioPriorityEncoder(in_width, width);
 | 
			
		||||
  val l_out = Wire() { Bits() };
 | 
			
		||||
  
 | 
			
		||||
  for (i <- 0 to width-1) {
 | 
			
		||||
    when (io.in === UFix(i, in_width)) {
 | 
			
		||||
      l_out <== Bits(1,1) << UFix(i);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  l_out <== Bits(0, width);
 | 
			
		||||
  io.out := l_out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ioPriorityEncoder(in_width: Int, out_width: Int) extends Bundle
 | 
			
		||||
{
 | 
			
		||||
  val in = Bits(in_width, 'input);
 | 
			
		||||
  val out = UFix(out_width, 'output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class priorityEncoder(width: Int) extends Component
 | 
			
		||||
{
 | 
			
		||||
  val out_width = ceil(log10(width)/log10(2)).toInt;  
 | 
			
		||||
  val io = new ioPriorityDecoder(width, out_width);
 | 
			
		||||
  val l_out = Wire() { UFix() };
 | 
			
		||||
  
 | 
			
		||||
  for (i <- 0 to width-1) {
 | 
			
		||||
    when (io.in(i).toBool) {
 | 
			
		||||
      l_out <== UFix(i, out_width);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  l_out <== UFix(0, out_width);
 | 
			
		||||
  io.out := l_out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user