initial commit of rocket chisel project, riscv assembly tests and benchmarks
This commit is contained in:
commit
c06e2d16e4
74
rocket/src/main/scala/arbiter.scala
Normal file
74
rocket/src/main/scala/arbiter.scala
Normal file
@ -0,0 +1,74 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._;
|
||||
import Node._;
|
||||
import Constants._;
|
||||
|
||||
class ioMem() extends Bundle
|
||||
{
|
||||
val req_val = Bool('output);
|
||||
val req_rdy = Bool('input);
|
||||
val req_rw = Bool('output);
|
||||
val req_addr = UFix(32, 'output);
|
||||
val req_wdata = Bits(128, 'output);
|
||||
val req_tag = Bits(4, 'output);
|
||||
|
||||
val resp_val = Bool('input);
|
||||
val resp_tag = Bits(4, 'input);
|
||||
val resp_data = Bits(128, 'input);
|
||||
}
|
||||
|
||||
class ioArbiter extends Bundle() {
|
||||
val mem = new ioMem();
|
||||
val dcache = new ioDcache();
|
||||
// val icache = new ioIcache();
|
||||
val icache = new ioIPrefetcherMem().flip();
|
||||
}
|
||||
|
||||
class rocketMemArbiter extends Component {
|
||||
val io = new ioArbiter();
|
||||
|
||||
// *****************************
|
||||
// Interface to memory
|
||||
// *****************************
|
||||
|
||||
// Memory request is valid if either icache or dcache have a valid request
|
||||
io.mem.req_val := (io.icache.req_val || io.dcache.req_val);
|
||||
|
||||
// Set read/write bit. Icache always reads
|
||||
io.mem.req_rw := Mux(io.icache.req_val,Bool(false),io.dcache.req_rw);
|
||||
|
||||
// Give priority to Icache
|
||||
io.mem.req_addr := Mux(io.icache.req_val,io.icache.req_addr,io.dcache.req_addr);
|
||||
|
||||
// high bit of tag=0 for I$, tag=0 for D$
|
||||
// io.mem.req_tag := Mux(io.icache.req_val,Bits(0,4),Bits(1,4));
|
||||
io.mem.req_tag := Mux(io.icache.req_val,
|
||||
Cat(Bits(0,1), io.icache.req_tag),
|
||||
Cat(Bits(1,1), io.dcache.req_tag));
|
||||
|
||||
// Just pass through write data (only D$ will write)
|
||||
io.mem.req_wdata := io.dcache.req_wdata;
|
||||
|
||||
// *****************************
|
||||
// Interface to caches
|
||||
// *****************************
|
||||
|
||||
// Read for request from cache if the memory is ready. Give priority to I$
|
||||
io.icache.req_rdy := io.mem.req_rdy;
|
||||
io.dcache.req_rdy := io.mem.req_rdy && !io.icache.req_val;
|
||||
|
||||
// Response will only be valid for D$ or I$ not both because of tag bits
|
||||
io.icache.resp_val := io.mem.resp_val && !io.mem.resp_tag(3).toBool;
|
||||
io.dcache.resp_val := io.mem.resp_val && io.mem.resp_tag(3).toBool;
|
||||
|
||||
// Feed through data to both
|
||||
io.icache.resp_data := io.mem.resp_data;
|
||||
io.dcache.resp_data := io.mem.resp_data;
|
||||
|
||||
io.icache.resp_tag := io.mem.resp_tag(2,0);
|
||||
io.dcache.resp_tag := io.mem.resp_tag(2,0);
|
||||
|
||||
}
|
||||
|
||||
}
|
153
rocket/src/main/scala/consts.scala
Normal file
153
rocket/src/main/scala/consts.scala
Normal file
@ -0,0 +1,153 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
|
||||
object Constants
|
||||
{
|
||||
val BR_N = UFix(0, 4);
|
||||
val BR_EQ = UFix(1, 4);
|
||||
val BR_NE = UFix(2, 4);
|
||||
val BR_LT = UFix(3, 4);
|
||||
val BR_LTU = UFix(4, 4);
|
||||
val BR_GE = UFix(5, 4);
|
||||
val BR_GEU = UFix(6, 4);
|
||||
val BR_J = UFix(7, 4);
|
||||
val BR_JR = UFix(8, 4);
|
||||
|
||||
val PC_4 = UFix(0, 3);
|
||||
val PC_BTB = UFix(1, 3);
|
||||
val PC_EX4 = UFix(2, 3);
|
||||
val PC_BR = UFix(3, 3);
|
||||
val PC_J = UFix(4, 3);
|
||||
val PC_JR = UFix(5, 3);
|
||||
val PC_PCR = UFix(6, 3);
|
||||
|
||||
val KF_Y = UFix(1, 1);
|
||||
val KF_N = UFix(0, 1);
|
||||
|
||||
val REN_Y = UFix(1, 1);
|
||||
val REN_N = UFix(0, 1);
|
||||
|
||||
val AS_X = UFix(0, 1);
|
||||
val AS_IMM = UFix(0, 1);
|
||||
val AS_RS2 = UFix(1, 1);
|
||||
|
||||
val A2_X = UFix(0, 2);
|
||||
val A2_0 = UFix(0, 2);
|
||||
val A2_SEXT = UFix(1, 2);
|
||||
val A2_RS2 = UFix(2, 2);
|
||||
val A2_SPLIT = UFix(3, 2);
|
||||
|
||||
val A1_X = UFix(0, 1);
|
||||
val A1_RS1 = UFix(0, 1);
|
||||
val A1_LUI = UFix(1, 1);
|
||||
|
||||
val MUL_X = UFix(0, 3);
|
||||
val MUL_NO = UFix(0, 3);
|
||||
val MUL_64 = UFix(1, 3);
|
||||
val MUL_64H = UFix(2, 3);
|
||||
val MUL_64HU = UFix(3, 3);
|
||||
val MUL_64HSU = UFix(4, 3);
|
||||
val MUL_32 = UFix(5, 3);
|
||||
|
||||
val DIV_X = UFix(0, 4);
|
||||
val DIV_NO = UFix(0, 4);
|
||||
val DIV_64D = UFix(1, 4);
|
||||
val DIV_64DU = UFix(2, 4);
|
||||
val DIV_64R = UFix(3, 4);
|
||||
val DIV_64RU = UFix(4, 4);
|
||||
val DIV_32D = UFix(5, 4);
|
||||
val DIV_32DU = UFix(6, 4);
|
||||
val DIV_32R = UFix(7, 4);
|
||||
val DIV_32RU = UFix(8, 4);
|
||||
|
||||
val M_N = UFix(0, 1);
|
||||
val M_Y = UFix(1, 1);
|
||||
|
||||
val WEN_N = UFix(0, 1);
|
||||
val WEN_Y = UFix(1, 1);
|
||||
|
||||
val WA_X = UFix(0, 1);
|
||||
val WA_RD = UFix(0, 1);
|
||||
val WA_RA = UFix(1, 1);
|
||||
|
||||
val WB_X = UFix(0, 3);
|
||||
val WB_PC = UFix(0, 3);
|
||||
val WB_ALU = UFix(1, 3);
|
||||
val WB_PCR = UFix(2, 3);
|
||||
val WB_CR = UFix(3, 3);
|
||||
val WB_MUL = UFix(4, 3);
|
||||
|
||||
val N = UFix(0, 1);
|
||||
val Y = UFix(1, 1);
|
||||
val Y_SH = UFix(1, 1);
|
||||
|
||||
// val FPU_N = UFix(0, 1);
|
||||
// val FPU_Y = FPU_N;
|
||||
|
||||
val FWBQ_N = UFix(0, 1);
|
||||
val FWBQ_Y = UFix(1, 1);
|
||||
|
||||
val FSDQ_N = UFix(0, 1);
|
||||
val FSDQ_Y = UFix(1, 1);
|
||||
|
||||
val FN_X = UFix(0, 4);
|
||||
val FN_ADD = UFix(0, 4);
|
||||
val FN_SUB = UFix(1, 4);
|
||||
val FN_SLT = UFix(2, 4);
|
||||
val FN_SLTU = UFix(3, 4);
|
||||
val FN_AND = UFix(4, 4);
|
||||
val FN_OR = UFix(5, 4);
|
||||
val FN_XOR = UFix(6, 4);
|
||||
val FN_SL = UFix(7, 4);
|
||||
val FN_SR = UFix(8, 4);
|
||||
val FN_SRA = UFix(9, 4);
|
||||
|
||||
val DW_X = UFix(0, 1);
|
||||
val DW_32 = UFix(0, 1);
|
||||
val DW_64 = UFix(1, 1);
|
||||
val DW_XPR = UFix(1, 1);
|
||||
|
||||
val RA = UFix(1, 5);
|
||||
|
||||
val MT_X = Bits("b000", 3);
|
||||
val MT_B = Bits("b000", 3);
|
||||
val MT_H = Bits("b001", 3);
|
||||
val MT_W = Bits("b010", 3);
|
||||
val MT_D = Bits("b011", 3);
|
||||
val MT_BU = Bits("b100", 3);
|
||||
val MT_HU = Bits("b101", 3);
|
||||
val MT_WU = Bits("b110", 3);
|
||||
|
||||
val M_X = UFix(0, 4);
|
||||
val M_XRD = Bits("b0000", 4); // int load
|
||||
val M_XWR = Bits("b0001", 4); // int store
|
||||
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_XA_ADD = Bits("b1000", 4);
|
||||
val M_XA_SWAP = Bits("b1001", 4);
|
||||
val M_XA_AND = Bits("b1010", 4);
|
||||
val M_XA_OR = Bits("b1011", 4);
|
||||
val M_XA_MIN = Bits("b1100", 4);
|
||||
val M_XA_MAX = Bits("b1101", 4);
|
||||
val M_XA_MINU = Bits("b1110", 4);
|
||||
val M_XA_MAXU = Bits("b1111", 4);
|
||||
|
||||
val PCR_STATUS = UFix( 0, 5);
|
||||
val PCR_EPC = UFix( 1, 5);
|
||||
val PCR_BADVADDR = UFix( 2, 5);
|
||||
val PCR_EVEC = UFix( 3, 5);
|
||||
val PCR_COUNT = UFix( 4, 5);
|
||||
val PCR_COMPARE = UFix( 5, 5);
|
||||
val PCR_CAUSE = UFix( 6, 5);
|
||||
val PCR_MEMSIZE = UFix( 8, 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);
|
||||
}
|
||||
|
||||
}
|
95
rocket/src/main/scala/cpu.scala
Normal file
95
rocket/src/main/scala/cpu.scala
Normal file
@ -0,0 +1,95 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
|
||||
class ioDebug extends Bundle()
|
||||
{
|
||||
val error_mode = Bool('output);
|
||||
val log_control = Bool('output);
|
||||
}
|
||||
|
||||
class ioHost(view: List[String] = null) extends Bundle(view)
|
||||
{
|
||||
val start = Bool('input);
|
||||
val from_wen = Bool('input);
|
||||
val from = Bits(32, 'input);
|
||||
val to = Bits(32, 'output);
|
||||
}
|
||||
|
||||
class ioConsole(view: List[String] = null) extends Bundle(view)
|
||||
{
|
||||
val rdy = Bool('input);
|
||||
val valid = Bool('output);
|
||||
val bits = Bits(8, 'output);
|
||||
}
|
||||
|
||||
class ioRocket extends Bundle()
|
||||
{
|
||||
val debug = new ioDebug();
|
||||
val console = new ioConsole();
|
||||
val host = new ioHost();
|
||||
val imem = new ioImem().flip();
|
||||
val dmem = new ioDmem().flip();
|
||||
}
|
||||
|
||||
class rocketProc extends Component
|
||||
{
|
||||
val io = new ioRocket();
|
||||
|
||||
val ctrl = new rocketCtrl();
|
||||
val dpath = new rocketDpath();
|
||||
val mem = new rocketMemory();
|
||||
val wb = new rocketWriteback();
|
||||
|
||||
dpath.io.host ^^ io.host;
|
||||
dpath.io.debug ^^ io.debug;
|
||||
// dpath.io.wb <> wb.io;
|
||||
dpath.io.wb.wen <> wb.io.wb_wen;
|
||||
dpath.io.wb.waddr <> wb.io.wb_waddr;
|
||||
dpath.io.wb.wdata <> wb.io.wb_wdata;
|
||||
dpath.io.imem.req_addr ^^ io.imem.req_addr;
|
||||
dpath.io.imem.resp_data ^^ io.imem.resp_data;
|
||||
|
||||
ctrl.io.ctrl <> dpath.io.ctrl;
|
||||
ctrl.io.dpath <> dpath.io.dpath;
|
||||
// ctrl.io.mem <> mem.io;
|
||||
ctrl.io.mem.mrq_val <> mem.io.mem_mrq_val;
|
||||
ctrl.io.mem.mrq_cmd <> mem.io.mem_mrq_cmd;
|
||||
ctrl.io.mem.mrq_type <> mem.io.mem_mrq_type;
|
||||
ctrl.io.mem.mrq_deq <> mem.io.mem_mrq_deq;
|
||||
ctrl.io.mem.xsdq_rdy <> mem.io.mem_xsdq_rdy;
|
||||
ctrl.io.mem.xsdq_val <> mem.io.mem_xsdq_val;
|
||||
ctrl.io.mem.dc_busy := !io.dmem.req_rdy;
|
||||
ctrl.io.host.start ^^ io.host.start;
|
||||
ctrl.io.imem ^^ io.imem;
|
||||
// ctrl.io.console ^^ io.console;
|
||||
ctrl.io.wb.waddr <> wb.io.wb_waddr;
|
||||
ctrl.io.wb.wen <> wb.io.wb_wen;
|
||||
|
||||
// TODO: SHOULD BE THE FOLLOWING BUT NEED BETTER INTERFACE CHUNKS
|
||||
// mem.io.dmem >< io.dmem;
|
||||
|
||||
mem.io.dmem_req_val ^^ io.dmem.req_val;
|
||||
mem.io.dmem_req_rdy ^^ io.dmem.req_rdy;
|
||||
mem.io.dmem_req_op ^^ io.dmem.req_op;
|
||||
mem.io.dmem_req_addr ^^ io.dmem.req_addr;
|
||||
mem.io.dmem_req_data ^^ io.dmem.req_data;
|
||||
mem.io.dmem_req_wmask ^^ io.dmem.req_wmask;
|
||||
mem.io.dmem_req_tag ^^ io.dmem.req_tag;
|
||||
|
||||
mem.io.dpath_rs2 <> dpath.io.dpath.rs2;
|
||||
mem.io.dpath_waddr <> dpath.io.dpath.waddr;
|
||||
mem.io.dpath_alu_out <> dpath.io.dpath.alu_out;
|
||||
|
||||
wb.io.dmem_resp_val ^^ io.dmem.resp_val;
|
||||
wb.io.dmem_resp_data ^^ io.dmem.resp_data;
|
||||
wb.io.dmem_resp_tag ^^ io.dmem.resp_tag;
|
||||
|
||||
io.console.bits := dpath.io.dpath.rs1(7,0);
|
||||
io.console.valid := ctrl.io.console.valid;
|
||||
ctrl.io.console.rdy := io.console.rdy;
|
||||
}
|
||||
|
||||
}
|
405
rocket/src/main/scala/ctrl.scala
Normal file
405
rocket/src/main/scala/ctrl.scala
Normal file
@ -0,0 +1,405 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
|
||||
import Constants._
|
||||
import Instructions._
|
||||
|
||||
class ioCtrl extends Bundle()
|
||||
{
|
||||
val sel_pc = UFix(3, 'output);
|
||||
val wen_btb = Bool('output);
|
||||
val stallf = Bool('output);
|
||||
val stalld = Bool('output);
|
||||
val killf = Bool('output);
|
||||
val killd = Bool('output);
|
||||
val ren2 = Bool('output);
|
||||
val ren1 = Bool('output);
|
||||
val sel_alu2 = UFix(2, 'output);
|
||||
val sel_alu1 = Bool('output);
|
||||
val fn_dw = Bool('output);
|
||||
val fn_alu = UFix(4, 'output);
|
||||
val mul_val = Bool('output);
|
||||
val mul_fn = UFix(3, 'output);
|
||||
val mul_wb = Bool('output);
|
||||
val div_val = Bool('output);
|
||||
val div_fn = UFix(4, 'output);
|
||||
val div_wb = Bool('output);
|
||||
val wen = Bool('output);
|
||||
val sel_wa = Bool('output);
|
||||
val sel_wb = UFix(3, 'output);
|
||||
val ren_pcr = Bool('output);
|
||||
val wen_pcr = Bool('output);
|
||||
val xcpt_illegal = Bool('output);
|
||||
val xcpt_privileged = Bool('output);
|
||||
val xcpt_fpu = Bool('output);
|
||||
val xcpt_syscall = Bool('output);
|
||||
val eret = Bool('output);
|
||||
}
|
||||
|
||||
class ioCtrlDpath extends Bundle()
|
||||
{
|
||||
val btb_hit = Bool('input);
|
||||
val inst = UFix(32, 'input);
|
||||
val br_eq = Bool('input);
|
||||
val br_lt = Bool('input);
|
||||
val br_ltu = Bool('input);
|
||||
val div_rdy = Bool('input);
|
||||
val div_result_val = Bool('input);
|
||||
val mul_result_val = Bool('input);
|
||||
val wen = Bool('input);
|
||||
val waddr = UFix(5, 'input);
|
||||
val exception = Bool('input);
|
||||
val status = Bits(8, 'input);
|
||||
}
|
||||
|
||||
class ioCtrlMem extends Bundle()
|
||||
{
|
||||
val mrq_val = Bool('output);
|
||||
val mrq_cmd = UFix(4, 'output);
|
||||
val mrq_type = UFix(3, 'output);
|
||||
val mrq_deq = Bool('input);
|
||||
val xsdq_rdy = Bool('input);
|
||||
val xsdq_val = Bool('output);
|
||||
val dc_busy = Bool('input);
|
||||
}
|
||||
|
||||
class ioCtrlImem extends Bundle()
|
||||
{
|
||||
val req_val = Bool('output);
|
||||
val req_rdy = Bool('input);
|
||||
val resp_val = Bool('input);
|
||||
}
|
||||
|
||||
class ioCtrlWB extends Bundle()
|
||||
{
|
||||
val waddr = UFix(5, 'input);
|
||||
val wen = Bool('input);
|
||||
}
|
||||
|
||||
class ioCtrlAll extends Bundle()
|
||||
{
|
||||
val ctrl = new ioCtrl();
|
||||
val console = new ioConsole(List("rdy", "valid"));
|
||||
val dpath = new ioCtrlDpath();
|
||||
val imem = new ioCtrlImem();
|
||||
val mem = new ioCtrlMem();
|
||||
val wb = new ioCtrlWB();
|
||||
val host = new ioHost(List("start"));
|
||||
}
|
||||
|
||||
class rocketCtrl extends Component
|
||||
{
|
||||
val io = new ioCtrlAll();
|
||||
|
||||
val xpr64 = Y;
|
||||
val cs =
|
||||
ListLookup(io.dpath.inst,
|
||||
List( N, BR_N, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
Array(
|
||||
BNE-> List(Y, BR_NE, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
ADDI-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
BEQ-> List(Y, BR_EQ, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
BLT-> List(Y, BR_LT, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
BLTU-> List(Y, BR_LTU,REN_Y,REN_Y,A2_RS2, A1_RS1,DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
BGE-> List(Y, BR_GE, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
BGEU-> List(Y, BR_GEU,REN_Y,REN_Y,A2_RS2, A1_RS1,DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
J-> List(Y, BR_J, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
JAL-> List(Y, BR_J, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RA,WB_PC, REN_N,WEN_N,N,N,N,N),
|
||||
JALR_C-> List(Y, BR_JR, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_PC, REN_N,WEN_N,N,N,N,N),
|
||||
JALR_J-> List(Y, BR_JR, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_PC, REN_N,WEN_N,N,N,N,N),
|
||||
JALR_R-> List(Y, BR_JR, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_PC, REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
LB-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XRD, MT_B, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
LH-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XRD, MT_H, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
LW-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XRD, MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
LD-> List(xpr64, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XRD, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
LBU-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XRD, MT_BU,N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
LHU-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XRD, MT_HU,N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
LWU-> List(xpr64, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XRD, MT_WU,N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
SB-> List(Y, BR_N, REN_Y,REN_Y,A2_SPLIT,A1_RS1,DW_XPR,FN_ADD, M_Y,M_XWR, MT_B, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
SH-> List(Y, BR_N, REN_Y,REN_Y,A2_SPLIT,A1_RS1,DW_XPR,FN_ADD, M_Y,M_XWR, MT_H, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
SW-> List(Y, BR_N, REN_Y,REN_Y,A2_SPLIT,A1_RS1,DW_XPR,FN_ADD, M_Y,M_XWR, MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
SD-> List(xpr64, BR_N, REN_Y,REN_Y,A2_SPLIT,A1_RS1,DW_XPR,FN_ADD, M_Y,M_XWR, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
LUI-> List(Y, BR_N, REN_N,REN_Y,A2_0, A1_LUI,DW_XPR,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SLTI -> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_SLT, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SLTIU-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_SLTU,M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
ANDI-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_AND, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
ORI-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_OR, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
XORI-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_XOR, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SLLI-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_SL, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SRLI-> List(Y_SH, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_SR, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SRAI-> List(Y_SH, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_SRA, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
ADD-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SUB-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_SUB, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SLT-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_SLT, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SLTU-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_SLTU,M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
riscvAND-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_AND, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
riscvOR-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_OR, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
riscvXOR-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_XOR, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SLL-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_SL, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SRL-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_SR, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SRA-> List(Y, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_XPR,FN_SRA, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
ADDIW-> List(xpr64, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_32,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SLLIW-> List(xpr64, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_32,FN_SL, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SRLIW-> List(xpr64, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_32,FN_SR, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SRAIW-> List(xpr64, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_32,FN_SRA, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
ADDW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_32,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SUBW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_32,FN_SUB, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SLLW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_32,FN_SL, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SRLW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_32,FN_SR, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
SRAW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_RS2, A1_RS1,DW_32,FN_SRA, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_ALU,REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
MUL-> List(Y, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, Y,MUL_64, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
MULH-> List(Y, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, Y,MUL_64H, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
MULHU-> List(Y, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, Y,MUL_64HU, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
MULHSU-> List(Y, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, Y,MUL_64HSU, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
MULW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, Y,MUL_32, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
DIV-> List(Y, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, Y,DIV_64D, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
DIVU-> List(Y, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, Y,DIV_64DU, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
REM-> List(Y, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, Y,DIV_64R, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
REMU-> List(Y, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, Y,DIV_64RU, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
DIVW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, Y,DIV_32D, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
DIVUW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, Y,DIV_32DU, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
REMW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, Y,DIV_32R, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
REMUW-> List(xpr64, BR_N, REN_Y,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, Y,DIV_32RU, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
SYSCALL-> List(Y, BR_N, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,Y,N),
|
||||
EI-> List(Y, BR_N, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,Y),
|
||||
DI-> List(Y, BR_N, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,Y),
|
||||
ERET-> List(Y, BR_N, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,Y,N,Y),
|
||||
FENCE-> List(Y, BR_N, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,Y,N,N,N),
|
||||
CFLUSH-> List(Y, BR_N, REN_Y,REN_N,A2_X, A1_X, DW_X, FN_X, M_Y,M_FLA, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,Y),
|
||||
MFPCR-> List(Y, BR_N, REN_N,REN_N,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_PCR,REN_Y,WEN_N,N,N,N,Y),
|
||||
MTPCR-> List(Y, BR_N, REN_N,REN_Y,A2_X, A1_X, DW_X, FN_X, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_Y,N,N,N,Y)
|
||||
|
||||
// Instructions that have not yet been implemented
|
||||
/*
|
||||
// floating point
|
||||
FLW-> List(FPU_Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_FRD, MT_WU,N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
FLD-> List(FPU_Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_Y,M_FRD, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
FSW-> List(FPU_Y, BR_N, REN_Y,REN_Y,A2_SPLIT,A1_RS1,DW_XPR,FN_ADD, M_Y,M_FWR, MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
FSD-> List(FPU_Y, BR_N, REN_Y,REN_Y,A2_SPLIT,A1_RS1,DW_XPR,FN_ADD, M_Y,M_FWR, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_X, WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
// atomic memory operations
|
||||
AMOADD_W-> List(Y, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_ADD, MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOSWAP_W->List(Y, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_SWAP,MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOAND_W-> List(Y, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_AND, MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOOR_W-> List(Y, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_OR, MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOMIN_W-> List(Y, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_MIN, MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOMAX_W-> List(Y, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_MAX, MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOMINU_W->List(Y, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_MINU,MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOMAXU_W->List(Y, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_MAXU,MT_W, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOADD_D-> List(xpr64, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_ADD, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOSWAP_D->List(xpr64, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_SWAP,MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOAND_D-> List(xpr64, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_AND, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOOR_D-> List(xpr64, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_OR, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOMIN_D-> List(xpr64, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_MIN, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOMAX_D-> List(xpr64, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_MAX, MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOMINU_D->List(xpr64, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_MINU,MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
AMOMAXU_D->List(xpr64, BR_N, REN_Y,REN_Y,A2_0, A1_RS1,DW_XPR,FN_ADD, M_Y,M_XA_MAXU,MT_D, N,MUL_X, N,DIV_X, WEN_N,WA_RD,WB_X, REN_N,WEN_N,N,N,N,N),
|
||||
|
||||
// miscellaneous
|
||||
RDNPC-> List(Y, BR_N, REN_N,REN_Y,A2_SEXT, A1_RS1,DW_XPR,FN_ADD, M_N,M_X, MT_X, N,MUL_X, N,DIV_X, WEN_Y,WA_RD,WB_PC, REN_N,WEN_N,N,N,N,N),
|
||||
*/
|
||||
));
|
||||
|
||||
val id_int_val :: id_br_type :: id_renx2 :: id_renx1 :: id_sel_alu2 :: id_sel_alu1 :: id_fn_dw :: id_fn_alu :: csremainder = cs;
|
||||
val id_mem_val :: id_mem_cmd :: id_mem_type :: id_mul_val :: id_mul_fn :: id_div_val :: id_div_fn :: id_wen :: id_sel_wa :: id_sel_wb :: id_ren_pcr :: id_wen_pcr :: id_sync :: id_eret :: id_syscall :: id_privileged :: Nil = csremainder;
|
||||
|
||||
val id_raddr2 = io.dpath.inst(21,17);
|
||||
val id_raddr1 = io.dpath.inst(26,22);
|
||||
val id_waddr = io.dpath.inst(31,27);
|
||||
|
||||
val id_ren2 = id_renx2;
|
||||
val id_ren1 = id_renx1;
|
||||
|
||||
val id_console_out_val = id_wen_pcr & (id_raddr2 === PCR_CONSOLE);
|
||||
|
||||
val id_mem_val_masked = id_mem_val;
|
||||
|
||||
val mem_xload_val = id_mem_val_masked & (id_mem_cmd === M_XRD);
|
||||
val mem_xstore_val = id_mem_val_masked & (id_mem_cmd === M_XWR);
|
||||
|
||||
val mem_fire = id_mem_val_masked & ~io.ctrl.killd;
|
||||
val mem_xload_fire = mem_xload_val & ~io.ctrl.killd;
|
||||
val mem_xstore_fire = mem_xstore_val & ~io.ctrl.killd;
|
||||
|
||||
val console_out_fire = id_console_out_val & ~io.ctrl.killd;
|
||||
|
||||
val div_fire = id_div_val & ~io.ctrl.killd;
|
||||
val mul_fire = id_mul_val & ~io.ctrl.killd;
|
||||
|
||||
val sboard_wen = mem_xload_fire | div_fire | mul_fire;
|
||||
val sboard_waddr = id_waddr;
|
||||
|
||||
val sboard = new rocketCtrlSboard();
|
||||
sboard.io.raddra := id_raddr2;
|
||||
sboard.io.raddrb := id_raddr1;
|
||||
sboard.io.raddrc := id_waddr;
|
||||
sboard.io.set := sboard_wen.toBool;
|
||||
sboard.io.seta := sboard_waddr;
|
||||
sboard.io.clr0 := io.wb.wen.toBool;
|
||||
sboard.io.clr0a ^^ io.wb.waddr;
|
||||
sboard.io.clr1 := io.dpath.wen.toBool;
|
||||
sboard.io.clr1a := io.dpath.waddr;
|
||||
|
||||
val id_stall_raddr2 = sboard.io.stalla;
|
||||
val id_stall_raddr1 = sboard.io.stallb;
|
||||
val id_stall_waddr = sboard.io.stallc;
|
||||
val id_stall_ra = sboard.io.stallra;
|
||||
|
||||
val mrq = new rocketCtrlCnt(3, 4);
|
||||
mrq.io.enq := mem_fire.toBool;
|
||||
mrq.io.deq ^^ io.mem.mrq_deq;
|
||||
val id_empty_mrq = mrq.io.empty;
|
||||
val id_full_mrq = mrq.io.full;
|
||||
|
||||
val id_reg_btb_hit = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_br_type = Reg(){UFix(width = 4)};
|
||||
val ex_reg_btb_hit = Reg(){Bool()};
|
||||
val ex_reg_mem_val = Reg(){Bool()};
|
||||
val ex_reg_mem_cmd = Reg(){UFix(width = 4)};
|
||||
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));
|
||||
|
||||
when (!io.ctrl.stalld) {
|
||||
when (io.ctrl.killf) {
|
||||
id_reg_btb_hit <== Bool(false);
|
||||
}
|
||||
otherwise{
|
||||
id_reg_btb_hit <== io.dpath.btb_hit;
|
||||
}
|
||||
}
|
||||
when (reset.toBool || io.ctrl.killd) {
|
||||
ex_reg_br_type <== BR_N;
|
||||
ex_reg_btb_hit <== Bool(false);
|
||||
ex_reg_mem_val <== Bool(false);
|
||||
ex_reg_mem_cmd <== UFix(0, 4);
|
||||
ex_reg_mem_type <== UFix(0, 3);
|
||||
ex_reg_eret <== Bool(false);
|
||||
ex_reg_privileged <== Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
ex_reg_br_type <== id_br_type;
|
||||
ex_reg_btb_hit <== id_reg_btb_hit;
|
||||
ex_reg_mem_val <== id_mem_val_masked.toBool;
|
||||
ex_reg_mem_cmd <== id_mem_cmd;
|
||||
ex_reg_mem_type <== id_mem_type;
|
||||
ex_reg_eret <== id_eret.toBool;
|
||||
ex_reg_privileged <== id_privileged.toBool;
|
||||
}
|
||||
|
||||
val beq = io.dpath.br_eq;
|
||||
val bne = ~io.dpath.br_eq;
|
||||
val blt = io.dpath.br_lt;
|
||||
val bltu = io.dpath.br_ltu;
|
||||
val bge = ~io.dpath.br_lt;
|
||||
val bgeu = ~io.dpath.br_ltu;
|
||||
|
||||
val br_taken =
|
||||
(ex_reg_br_type === BR_EQ) & beq |
|
||||
(ex_reg_br_type === BR_NE) & bne |
|
||||
(ex_reg_br_type === BR_LT) & blt |
|
||||
(ex_reg_br_type === BR_LTU) & bltu |
|
||||
(ex_reg_br_type === BR_GE) & bge |
|
||||
(ex_reg_br_type === BR_GEU) & bgeu;
|
||||
|
||||
val jr_taken = (ex_reg_br_type === BR_JR);
|
||||
val j_taken = (ex_reg_br_type === BR_J);
|
||||
|
||||
io.imem.req_val := io.host.start;
|
||||
// io.imem.req_val := Bool(true);
|
||||
|
||||
io.mem.mrq_val := ex_reg_mem_val;
|
||||
io.mem.mrq_cmd := ex_reg_mem_cmd;
|
||||
io.mem.mrq_type := ex_reg_mem_type;
|
||||
io.mem.xsdq_val := mem_xstore_fire.toBool;
|
||||
io.console.valid := console_out_fire.toBool;
|
||||
|
||||
io.ctrl.sel_pc :=
|
||||
Mux(io.dpath.exception || ex_reg_eret, PC_PCR,
|
||||
Mux(!ex_reg_btb_hit && br_taken, PC_BR,
|
||||
Mux(ex_reg_btb_hit && !br_taken || ex_reg_privileged, PC_EX4,
|
||||
Mux(jr_taken, PC_JR,
|
||||
Mux(j_taken, PC_J,
|
||||
Mux(io.dpath.btb_hit, PC_BTB,
|
||||
PC_4))))));
|
||||
|
||||
io.ctrl.wen_btb := ~ex_reg_btb_hit & br_taken;
|
||||
|
||||
val take_pc =
|
||||
~ex_reg_btb_hit & br_taken |
|
||||
ex_reg_btb_hit & ~br_taken |
|
||||
jr_taken |
|
||||
j_taken |
|
||||
io.dpath.exception |
|
||||
ex_reg_privileged |
|
||||
ex_reg_eret;
|
||||
|
||||
io.ctrl.stallf :=
|
||||
~take_pc &
|
||||
(
|
||||
~io.imem.req_rdy |
|
||||
~io.imem.resp_val |
|
||||
io.ctrl.stalld
|
||||
);
|
||||
|
||||
val ctrl_stalld_wo_fpu_rdy =
|
||||
~take_pc &
|
||||
(
|
||||
id_ren2 & id_stall_raddr2 |
|
||||
id_ren1 & id_stall_raddr1 |
|
||||
(id_sel_wa === WA_RD) & id_stall_waddr |
|
||||
(id_sel_wa === WA_RA) & id_stall_ra |
|
||||
id_mem_val_masked & id_full_mrq |
|
||||
id_sync & (~id_empty_mrq | io.mem.dc_busy) |
|
||||
mem_xstore_val & ~io.mem.xsdq_rdy |
|
||||
id_console_out_val & ~io.console.rdy |
|
||||
id_div_val & ~io.dpath.div_rdy |
|
||||
io.dpath.div_result_val |
|
||||
io.dpath.mul_result_val
|
||||
);
|
||||
|
||||
// for divider, multiplier writeback
|
||||
val mul_wb = io.dpath.mul_result_val;
|
||||
val div_wb = io.dpath.div_result_val & !mul_wb;
|
||||
|
||||
io.ctrl.stalld := ctrl_stalld_wo_fpu_rdy.toBool;
|
||||
|
||||
io.ctrl.killf := take_pc | ~io.imem.resp_val;
|
||||
val ctrl_killd_wo_fpu_rdy = take_pc | ctrl_stalld_wo_fpu_rdy;
|
||||
io.ctrl.killd := ctrl_killd_wo_fpu_rdy.toBool;
|
||||
|
||||
io.ctrl.ren2 := id_ren2.toBool;
|
||||
io.ctrl.ren1 := id_ren1.toBool;
|
||||
io.ctrl.sel_alu2 := id_sel_alu2;
|
||||
io.ctrl.sel_alu1 := id_sel_alu1.toBool;
|
||||
io.ctrl.fn_dw := id_fn_dw.toBool;
|
||||
io.ctrl.fn_alu := id_fn_alu;
|
||||
io.ctrl.div_fn := id_div_fn;
|
||||
io.ctrl.div_val := id_div_val.toBool;
|
||||
io.ctrl.div_wb := div_wb;
|
||||
io.ctrl.mul_fn := id_mul_fn;
|
||||
io.ctrl.mul_val := id_mul_val.toBool;
|
||||
io.ctrl.mul_wb := mul_wb;
|
||||
io.ctrl.wen := id_wen.toBool;
|
||||
io.ctrl.sel_wa := id_sel_wa.toBool;
|
||||
io.ctrl.sel_wb := id_sel_wb;
|
||||
io.ctrl.ren_pcr := id_ren_pcr.toBool;
|
||||
io.ctrl.wen_pcr := id_wen_pcr.toBool;
|
||||
io.ctrl.eret := id_eret.toBool;
|
||||
|
||||
io.ctrl.xcpt_illegal := ~id_int_val.toBool;
|
||||
io.ctrl.xcpt_privileged := (id_privileged & ~io.dpath.status(5)).toBool;
|
||||
io.ctrl.xcpt_fpu := Bool(false);
|
||||
io.ctrl.xcpt_syscall := id_syscall.toBool;
|
||||
}
|
||||
|
||||
}
|
62
rocket/src/main/scala/ctrl_util.scala
Normal file
62
rocket/src/main/scala/ctrl_util.scala
Normal file
@ -0,0 +1,62 @@
|
||||
package Top
|
||||
{
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
|
||||
class ioCtrlSboard extends Bundle()
|
||||
{
|
||||
val clr0 = Bool('input);
|
||||
val clr0a = UFix(5, 'input);
|
||||
val clr1 = Bool('input);
|
||||
val clr1a = UFix(5, 'input);
|
||||
val set = Bool('input);
|
||||
val seta = UFix(5, 'input);
|
||||
val raddra = UFix(5, 'input);
|
||||
val raddrb = UFix(5, 'input);
|
||||
val raddrc = UFix(5, 'input);
|
||||
val stalla = Bool('output);
|
||||
val stallb = Bool('output);
|
||||
val stallc = Bool('output);
|
||||
val stallra = Bool('output);
|
||||
}
|
||||
|
||||
class rocketCtrlSboard extends Component
|
||||
{
|
||||
override val io = new ioCtrlSboard();
|
||||
val reg_busy = Reg(width = 32, resetVal = Bits(0, 32));
|
||||
|
||||
val set_mask = Mux(io.set, UFix(1,1) << io.seta, UFix(0,32));
|
||||
val clr0_mask = Mux(io.clr0, ~(UFix(1,1) << io.clr0a), ~UFix(0,32));
|
||||
val clr1_mask = Mux(io.clr1, ~(UFix(1,1) << io.clr1a), ~UFix(0,32));
|
||||
reg_busy <== ((reg_busy | set_mask) & clr0_mask) & clr1_mask;
|
||||
|
||||
io.stalla := reg_busy(io.raddra).toBool;
|
||||
io.stallb := reg_busy(io.raddrb).toBool;
|
||||
io.stallc := reg_busy(io.raddrc).toBool;
|
||||
io.stallra := reg_busy(RA).toBool;
|
||||
}
|
||||
|
||||
class ioCtrlCnt extends Bundle()
|
||||
{
|
||||
val enq = Bool('input);
|
||||
val deq = Bool('input);
|
||||
val empty = Bool('output);
|
||||
val full = Bool('output);
|
||||
}
|
||||
|
||||
class rocketCtrlCnt(n_bits: Int, limit: Int) extends Component
|
||||
{
|
||||
override val io = new ioCtrlCnt();
|
||||
val counter = Reg(width = n_bits, resetVal = UFix(0, n_bits));
|
||||
when (io.enq && !io.deq) {
|
||||
counter <== counter + UFix(1, n_bits);
|
||||
}
|
||||
when (!io.enq && io.deq) {
|
||||
counter <== counter - UFix(1, n_bits);
|
||||
}
|
||||
io.empty := counter === UFix(0, n_bits);
|
||||
io.full := counter === UFix(limit, n_bits);
|
||||
}
|
||||
|
||||
}
|
251
rocket/src/main/scala/dcache.scala
Normal file
251
rocket/src/main/scala/dcache.scala
Normal file
@ -0,0 +1,251 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
import scala.math._;
|
||||
|
||||
// interface between D$ and processor
|
||||
class ioDmem(view: List[String] = null) extends Bundle(view) {
|
||||
val req_val = Bool('input);
|
||||
val req_rdy = Bool('output);
|
||||
val req_op = Bits(4, 'input);
|
||||
val req_addr = UFix(32, 'input);
|
||||
val req_data = Bits(64, 'input);
|
||||
val req_wmask = Bits(8, 'input);
|
||||
val req_tag = Bits(12, 'input);
|
||||
val resp_val = Bool('output);
|
||||
val resp_data = Bits(64, 'output);
|
||||
val resp_tag = Bits(12, 'output);
|
||||
}
|
||||
|
||||
// interface between D$ and memory
|
||||
class ioDcache(view: List[String] = null) extends Bundle(view) {
|
||||
val req_addr = UFix(32, 'input);
|
||||
val req_tag = UFix(3, 'input);
|
||||
val req_val = Bool('input);
|
||||
val req_rdy = Bool('output);
|
||||
val req_wdata = Bits(128, 'input);
|
||||
val req_rw = Bool('input);
|
||||
val resp_data = Bits(128, 'output);
|
||||
val resp_tag = Bits(3, 'output);
|
||||
val resp_val = Bool('output);
|
||||
}
|
||||
|
||||
class ioDCacheDM extends Bundle() {
|
||||
val cpu = new ioDmem();
|
||||
val mem = new ioDcache().flip();
|
||||
}
|
||||
|
||||
// state machine to flush (write back dirty lines, invalidate clean ones) the D$
|
||||
class rocketDCacheDM_flush(lines: Int, addrbits: Int) extends Component {
|
||||
val io = new ioDCacheDM();
|
||||
val dcache = new rocketDCacheDM(lines, addrbits);
|
||||
|
||||
val indexbits = ceil(log10(lines)/log10(2)).toInt;
|
||||
val offsetbits = 6;
|
||||
val tagmsb = addrbits - 1;
|
||||
val taglsb = indexbits+offsetbits;
|
||||
val indexmsb = taglsb-1;
|
||||
val indexlsb = offsetbits;
|
||||
val offsetmsb = indexlsb-1;
|
||||
val offsetlsb = 3;
|
||||
|
||||
val flush_count = Reg(resetVal = UFix(0, indexbits));
|
||||
val flush_resp_count = Reg(resetVal = UFix(0, indexbits));
|
||||
val flushing = Reg(resetVal = Bool(false));
|
||||
val flush_waiting = Reg(resetVal = Bool(false));
|
||||
val r_cpu_req_tag = Reg(resetVal = Bits(0, 12));
|
||||
|
||||
when (io.cpu.req_val && io.cpu.req_rdy && (io.cpu.req_op === M_FLA))
|
||||
{
|
||||
r_cpu_req_tag <== io.cpu.req_tag;
|
||||
flushing <== Bool(true);
|
||||
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 (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); }
|
||||
|
||||
dcache.io.cpu.req_val := (io.cpu.req_val && (io.cpu.req_op != M_FLA) && !flush_waiting) || flushing;
|
||||
dcache.io.cpu.req_op := Mux(flushing, M_FLA, io.cpu.req_op);
|
||||
dcache.io.cpu.req_addr := Mux(flushing, Cat(Bits(0,tagmsb-taglsb+1), flush_count, Bits(0,offsetbits)).toUFix, io.cpu.req_addr);
|
||||
dcache.io.cpu.req_tag := Mux(flushing, r_cpu_req_tag, io.cpu.req_tag);
|
||||
dcache.io.cpu.req_data ^^ io.cpu.req_data;
|
||||
dcache.io.cpu.req_wmask ^^ io.cpu.req_wmask;
|
||||
dcache.io.mem ^^ io.mem;
|
||||
|
||||
io.cpu.req_rdy := dcache.io.cpu.req_rdy && !flush_waiting;
|
||||
io.cpu.resp_data := dcache.io.cpu.resp_data;
|
||||
io.cpu.resp_tag := dcache.io.cpu.resp_tag;
|
||||
io.cpu.resp_val := dcache.io.cpu.resp_val &
|
||||
!(flush_waiting && (io.cpu.resp_tag === r_cpu_req_tag) && (flush_count != ~Bits(0, addrbits)));
|
||||
|
||||
}
|
||||
|
||||
// basic direct mapped data cache, 2 cycle read latency
|
||||
// parameters :
|
||||
// lines = # of cache lines
|
||||
// addr_bits = address width (word addressable) bits
|
||||
// 64 bit wide cpu port, 128 bit wide memory port, 64 byte cachelines
|
||||
|
||||
class rocketDCacheDM(lines: Int, addrbits: Int) extends Component {
|
||||
val io = new ioDCacheDM();
|
||||
|
||||
val indexbits = ceil(log10(lines)/log10(2)).toInt;
|
||||
val offsetbits = 6;
|
||||
val tagmsb = addrbits - 1;
|
||||
val taglsb = indexbits+offsetbits;
|
||||
val indexmsb = taglsb-1;
|
||||
val indexlsb = offsetbits;
|
||||
val offsetmsb = indexlsb-1;
|
||||
val offsetlsb = 3;
|
||||
|
||||
val s_reset :: s_ready :: s_start_writeback :: s_writeback :: s_req_refill :: s_refill :: s_resolve_miss :: Nil = Enum(7) { UFix() };
|
||||
val state = Reg(resetVal = s_reset);
|
||||
|
||||
val r_cpu_req_addr = Reg(Bits(0, addrbits));
|
||||
val r_r_cpu_req_addr = Reg(r_cpu_req_addr);
|
||||
val r_cpu_req_val = Reg(Bool(false));
|
||||
val r_cpu_req_data = Reg(Bits(0,64));
|
||||
val r_cpu_req_op = Reg(Bits(0,4));
|
||||
val r_cpu_req_wmask = Reg(Bits(0,8));
|
||||
val r_cpu_req_tag = Reg(Bits(0,12));
|
||||
val r_cpu_resp_tag = Reg(r_cpu_req_tag);
|
||||
val r_cpu_resp_val = Reg(Bool(false));
|
||||
|
||||
when (io.cpu.req_val && io.cpu.req_rdy) {
|
||||
r_cpu_req_addr <== io.cpu.req_addr;
|
||||
r_cpu_req_data <== io.cpu.req_data;
|
||||
r_cpu_req_op <== io.cpu.req_op;
|
||||
r_cpu_req_wmask <== io.cpu.req_wmask;
|
||||
r_cpu_req_tag <== io.cpu.req_tag; }
|
||||
|
||||
val req_load = (r_cpu_req_op === M_XRD);
|
||||
val req_store = (r_cpu_req_op === M_XWR);
|
||||
val req_flush = (r_cpu_req_op === M_FLA);
|
||||
|
||||
when (io.cpu.req_rdy) { r_cpu_req_val <== io.cpu.req_val; }
|
||||
otherwise { r_cpu_req_val <== Bool(false); }
|
||||
|
||||
// counter
|
||||
val rr_count = Reg(resetVal = UFix(0,2));
|
||||
val rr_count_next = rr_count + UFix(1);
|
||||
when (((state === s_refill) && io.mem.resp_val) || ((state === s_writeback) && io.mem.req_rdy))
|
||||
{ rr_count <== rr_count_next; }
|
||||
|
||||
// tag array
|
||||
val tag_we = (state === s_resolve_miss);
|
||||
val tag_waddr = r_cpu_req_addr(indexmsb, indexlsb).toUFix;
|
||||
val tag_wdata = r_cpu_req_addr(tagmsb, taglsb);
|
||||
val tag_array = Mem(lines, tag_we, tag_waddr, tag_wdata);
|
||||
val tag_raddr = Mux((state === s_ready), io.cpu.req_addr(indexmsb, indexlsb).toUFix, r_cpu_req_addr(indexmsb, indexlsb).toUFix);
|
||||
val tag_rdata = Reg(tag_array.read(tag_raddr));
|
||||
|
||||
// valid bit array
|
||||
val vb_array = Reg(resetVal = Bits(0, lines));
|
||||
val vb_rdata = Reg(vb_array(tag_raddr));
|
||||
when (tag_we && !req_flush) { vb_array <== vb_array.bitSet(r_cpu_req_addr(indexmsb, indexlsb).toUFix, UFix(1,1)); }
|
||||
when (tag_we && req_flush) { vb_array <== vb_array.bitSet(r_cpu_req_addr(indexmsb, indexlsb).toUFix, UFix(0,1)); }
|
||||
|
||||
val tag_valid = vb_rdata.toBool;
|
||||
val tag_match = tag_valid && !req_flush && (tag_rdata === r_cpu_req_addr(tagmsb, taglsb));
|
||||
val store = ((state === s_ready) && r_cpu_req_val && req_store && tag_match ) ||
|
||||
((state === s_resolve_miss) && req_store);
|
||||
|
||||
// dirty bit array
|
||||
val db_array = Reg(resetVal = Bits(0, lines));
|
||||
val db_rdata = Reg(db_array(tag_raddr));
|
||||
val tag_dirty = db_rdata.toBool;
|
||||
when (store) { db_array <== db_array.bitSet(r_cpu_req_addr(indexmsb, indexlsb).toUFix, UFix(1,1)); }
|
||||
when (tag_we) { db_array <== db_array.bitSet(r_cpu_req_addr(indexmsb, indexlsb).toUFix, UFix(0,1)); }
|
||||
|
||||
// data array
|
||||
val data_array_we = ((state === s_refill) && io.mem.resp_val) || store;
|
||||
val data_array_waddr = Mux((state === s_refill),
|
||||
Cat(r_cpu_req_addr(indexmsb, indexlsb), rr_count).toUFix,
|
||||
r_cpu_req_addr(indexmsb, offsetmsb-1).toUFix);
|
||||
|
||||
val data_array_wdata = Mux((state === s_refill), io.mem.resp_data, Cat(r_cpu_req_data, r_cpu_req_data));
|
||||
|
||||
val req_wmask_expand = Cat(Fill(8, r_cpu_req_wmask(7)),
|
||||
Fill(8, r_cpu_req_wmask(6)),
|
||||
Fill(8, r_cpu_req_wmask(5)),
|
||||
Fill(8, r_cpu_req_wmask(4)),
|
||||
Fill(8, r_cpu_req_wmask(3)),
|
||||
Fill(8, r_cpu_req_wmask(2)),
|
||||
Fill(8, r_cpu_req_wmask(1)),
|
||||
Fill(8, r_cpu_req_wmask(0)));
|
||||
|
||||
val store_wmask = Mux(r_cpu_req_addr(offsetlsb).toBool,
|
||||
Cat(req_wmask_expand, Bits(0,64)),
|
||||
Cat(Bits(0,64), req_wmask_expand));
|
||||
|
||||
val data_array_wmask = Mux((state === s_refill), ~Bits(0,128), store_wmask);
|
||||
val data_array = Mem(lines*4, data_array_we, data_array_waddr, data_array_wdata, wrMask = data_array_wmask, resetVal = null);
|
||||
val data_array_raddr = Mux((state === s_writeback) && io.mem.req_rdy, Cat(r_cpu_req_addr(indexmsb, indexlsb), rr_count_next).toUFix,
|
||||
Mux((state === s_start_writeback) || (state === s_writeback), Cat(r_cpu_req_addr(indexmsb, indexlsb), rr_count).toUFix,
|
||||
r_cpu_req_addr(indexmsb, offsetmsb-1)));
|
||||
val data_array_rdata = Reg(data_array.read(data_array_raddr));
|
||||
|
||||
// output signals
|
||||
io.cpu.req_rdy := (state === s_ready) && (!r_cpu_req_val || tag_match);
|
||||
|
||||
when ((((state === s_ready) && r_cpu_req_val && tag_match) || (state === s_resolve_miss)) && !req_store)
|
||||
{ r_cpu_resp_val <== Bool(true); }
|
||||
otherwise { r_cpu_resp_val <== Bool(false); }
|
||||
|
||||
io.cpu.resp_val := r_cpu_resp_val;
|
||||
io.cpu.resp_data := Mux(r_r_cpu_req_addr(offsetlsb).toBool, data_array_rdata(127, 64), data_array_rdata(63,0));
|
||||
io.cpu.resp_tag := r_cpu_resp_tag;
|
||||
|
||||
io.mem.req_val := (state === s_req_refill) || (state === s_writeback);
|
||||
io.mem.req_rw := (state === s_writeback);
|
||||
io.mem.req_wdata := data_array_rdata;
|
||||
io.mem.req_tag := UFix(0);
|
||||
io.mem.req_addr := Mux(state === s_writeback,
|
||||
Cat(tag_rdata, r_cpu_req_addr(indexmsb, indexlsb), rr_count).toUFix,
|
||||
Cat(r_cpu_req_addr(tagmsb, indexlsb), Bits(0,2)).toUFix);
|
||||
|
||||
// control state machine
|
||||
switch (state) {
|
||||
is (s_reset) {
|
||||
state <== s_ready;
|
||||
}
|
||||
is (s_ready) {
|
||||
when (~r_cpu_req_val) { state <== s_ready; }
|
||||
when (r_cpu_req_val & tag_match) { state <== s_ready; }
|
||||
when (tag_valid & tag_dirty) { state <== s_start_writeback; }
|
||||
when (req_flush) { state <== s_resolve_miss; }
|
||||
otherwise { state <== s_req_refill; }
|
||||
}
|
||||
is (s_start_writeback) {
|
||||
state <== s_writeback;
|
||||
}
|
||||
is (s_writeback) {
|
||||
when (io.mem.req_rdy && (rr_count === UFix(3,2))) {
|
||||
when (req_flush) { state <== s_resolve_miss; }
|
||||
otherwise { state <== s_req_refill; }
|
||||
}
|
||||
}
|
||||
is (s_req_refill)
|
||||
{
|
||||
when (io.mem.req_rdy) { state <== s_refill; }
|
||||
}
|
||||
is (s_refill) {
|
||||
when (io.mem.resp_val && (rr_count === UFix(3,2))) { state <== s_resolve_miss; }
|
||||
}
|
||||
is (s_resolve_miss) {
|
||||
state <== s_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
147
rocket/src/main/scala/divider.scala
Normal file
147
rocket/src/main/scala/divider.scala
Normal file
@ -0,0 +1,147 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
|
||||
class ioDivider(width: Int) extends Bundle {
|
||||
// requests
|
||||
val div_val = Bool('input);
|
||||
val div_rdy = Bool('output);
|
||||
val div_fn = UFix(4, 'input);
|
||||
val div_waddr = UFix(5, 'input);
|
||||
val dpath_rs1 = Bits(width, 'input);
|
||||
val dpath_rs2 = Bits(width, 'input);
|
||||
// responses
|
||||
val div_result_bits = Bits(width, 'output);
|
||||
val div_result_tag = UFix(5, 'output);
|
||||
val div_result_val = Bool('output);
|
||||
val div_result_rdy = Bool('input);
|
||||
}
|
||||
|
||||
// class ioDivider extends Bundle {
|
||||
// // requests
|
||||
// val req_val = Bool('input);
|
||||
// val req_rdy = Bool('output);
|
||||
// val req_fn = UFix(3, 'input);
|
||||
// val req_tag = UFix(5, 'input);
|
||||
// val req_rs1 = Bits(64, 'input);
|
||||
// val req_rs2 = Bits(64, 'input);
|
||||
// // responses
|
||||
// val resp_val = Bool('output);
|
||||
// val resp_data = Bits(64, 'output);
|
||||
// val resp_tag = UFix(5, 'output);
|
||||
// }
|
||||
|
||||
class rocketDivider(width : Int) extends Component {
|
||||
val io = new ioDivider(width);
|
||||
|
||||
val s_ready :: s_neg_inputs :: s_busy :: s_neg_outputs :: s_done :: Nil = Enum(5) { UFix() };
|
||||
val state = Reg(resetVal = s_ready);
|
||||
|
||||
val count_bits = java.math.BigInteger.valueOf(width).bitLength();
|
||||
val count = Reg(resetVal = UFix(0, count_bits));
|
||||
val divby0 = Reg(resetVal = Bool(false));
|
||||
val neg_quo = Reg(resetVal = Bool(false));
|
||||
val neg_rem = Reg(resetVal = Bool(false));
|
||||
val reg_waddr = Reg(resetVal = UFix(0, 5));
|
||||
val rem = Reg(resetVal = Bool(false));
|
||||
val half = Reg(resetVal = Bool(false));
|
||||
val tc = Reg(resetVal = Bool(false));
|
||||
|
||||
val divisor = Reg(resetVal = UFix(0, width));
|
||||
val remainder = Reg(resetVal = UFix(0, 2*width+1));
|
||||
val subtractor = remainder(2*width, width).toUFix - divisor;
|
||||
|
||||
val v_tc = ((io.div_fn === DIV_64D) || (io.div_fn === DIV_64R)) ||
|
||||
((io.div_fn === DIV_32D) || (io.div_fn === DIV_32R));
|
||||
|
||||
val v_rem = ((io.div_fn === DIV_32R) || (io.div_fn === DIV_32RU)) ||
|
||||
((io.div_fn === DIV_64R) || (io.div_fn === DIV_64RU));
|
||||
|
||||
val v_half = ((io.div_fn === DIV_32R) || (io.div_fn === DIV_32RU)) ||
|
||||
((io.div_fn === DIV_32D) || (io.div_fn === DIV_32DU));
|
||||
|
||||
// state machine
|
||||
switch (state) {
|
||||
is (s_ready) {
|
||||
when (!io.div_val) { state <== s_ready; }
|
||||
when (v_tc) { state <== s_neg_inputs };
|
||||
otherwise { state <== s_busy; }
|
||||
}
|
||||
is (s_neg_inputs) { state <== s_busy; }
|
||||
is (s_busy) {
|
||||
when (count != UFix(width)) { state <== s_busy; }
|
||||
when (!(neg_quo || neg_rem)) { state <== s_done; }
|
||||
otherwise { state <== s_neg_outputs; }
|
||||
}
|
||||
is (s_neg_outputs) { state <== s_done; }
|
||||
is (s_done) {
|
||||
when (io.div_result_rdy) { state <== s_ready; }
|
||||
}
|
||||
}
|
||||
|
||||
// if we're doing 32-bit unsigned division, then we don't want the 32-bit
|
||||
// inputs to be sign-extended.
|
||||
val in_lhs = Mux((v_half && !v_tc),
|
||||
Cat(Fill(width/2, UFix(0,1)), io.dpath_rs1(width/2-1, 0)),
|
||||
io.dpath_rs1).toUFix;
|
||||
|
||||
val in_rhs = Mux((v_half && !v_tc),
|
||||
Cat(Fill(width/2, UFix(0,1)), io.dpath_rs2(width/2-1, 0)),
|
||||
io.dpath_rs2).toUFix;
|
||||
|
||||
when ((state === s_ready) && io.div_val) {
|
||||
count <== UFix(0, count_bits);
|
||||
half <== v_half;
|
||||
neg_quo <== Bool(false);
|
||||
neg_rem <== Bool(false);
|
||||
rem <== v_rem;
|
||||
tc <== v_tc;
|
||||
reg_waddr <== io.div_waddr;
|
||||
divby0 <== Bool(true);
|
||||
divisor <== in_rhs;
|
||||
remainder <== Cat(Fill(width+1, UFix(0,1)), in_lhs).toUFix;
|
||||
}
|
||||
|
||||
when (state === s_neg_inputs) {
|
||||
neg_rem <== remainder(width-1).toBool;
|
||||
neg_quo <== (remainder(width-1) != divisor(width-1));
|
||||
when (remainder(width-1).toBool) {
|
||||
remainder <== Cat(remainder(2*width, width), -remainder(width-1,0)).toUFix;
|
||||
}
|
||||
when (divisor(width-1).toBool) {
|
||||
divisor <== subtractor(width-1,0);
|
||||
}
|
||||
}
|
||||
when (state === s_neg_outputs) {
|
||||
when (neg_rem && neg_quo && !divby0) {
|
||||
remainder <== Cat(-remainder(2*width, width+1), remainder(width), -remainder(width-1,0)).toUFix;
|
||||
}
|
||||
when (neg_quo && !divby0) {
|
||||
remainder <== Cat(remainder(2*width, width), -remainder(width-1,0)).toUFix;
|
||||
}
|
||||
when (neg_rem) {
|
||||
remainder <== Cat(-remainder(2*width, width+1), remainder(width,0)).toUFix;
|
||||
}
|
||||
when (divisor(width-1).toBool) {
|
||||
divisor <== subtractor(width-1,0);
|
||||
}
|
||||
}
|
||||
when (state === s_busy) {
|
||||
count <== count + UFix(1);
|
||||
divby0 <== divby0 && !subtractor(width).toBool;
|
||||
remainder <== Mux(subtractor(width).toBool,
|
||||
Cat(remainder(2*width-1, width), remainder(width-1,0), ~subtractor(width)),
|
||||
Cat(subtractor(width-1, 0), remainder(width-1,0), ~subtractor(width))).toUFix;
|
||||
}
|
||||
|
||||
val result = Mux(rem, remainder(2*width, width+1), remainder(width-1,0));
|
||||
|
||||
io.div_result_bits := Mux(half, Cat(Fill(width/2, result(width/2-1)), result(width/2-1,0)), result);
|
||||
io.div_rdy := (state === s_ready);
|
||||
io.div_result_tag := reg_waddr;
|
||||
io.div_result_val := (state === s_done);
|
||||
}
|
||||
|
||||
}
|
345
rocket/src/main/scala/dpath.scala
Normal file
345
rocket/src/main/scala/dpath.scala
Normal file
@ -0,0 +1,345 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._
|
||||
import Instructions._
|
||||
|
||||
class ioDpath extends Bundle()
|
||||
{
|
||||
val btb_hit = Bool('output);
|
||||
val inst = Bits(32, 'output);
|
||||
val rs2 = Bits(64, 'output);
|
||||
val rs1 = Bits(64, 'output);
|
||||
val br_eq = Bool('output);
|
||||
val br_lt = Bool('output);
|
||||
val br_ltu = Bool('output);
|
||||
val div_result_val = Bool('output);
|
||||
val div_rdy = Bool('output);
|
||||
val mul_result_val = Bool('output);
|
||||
val wen = Bool('output);
|
||||
val waddr = UFix(5, 'output);
|
||||
val alu_out = UFix(64, 'output);
|
||||
val exception = Bool('output);
|
||||
val status = Bits(8, 'output);
|
||||
}
|
||||
|
||||
class ioDpathImem extends Bundle()
|
||||
{
|
||||
val req_addr = UFix(32, 'output);
|
||||
val resp_data = Bits(32, 'input);
|
||||
}
|
||||
|
||||
class ioDpathWB extends Bundle()
|
||||
{
|
||||
val waddr = UFix(5, 'input);
|
||||
val wen = Bool('input);
|
||||
val wdata = Bits(64, 'input);
|
||||
}
|
||||
|
||||
class ioDpathAll extends Bundle()
|
||||
{
|
||||
val dpath = new ioDpath();
|
||||
val host = new ioHost();
|
||||
val ctrl = new ioCtrl().flip();
|
||||
val debug = new ioDebug();
|
||||
val wb = new ioDpathWB();
|
||||
val imem = new ioDpathImem();
|
||||
}
|
||||
|
||||
class rocketDpath extends Component
|
||||
{
|
||||
val io = new ioDpathAll();
|
||||
|
||||
val btb = new rocketDpathBTB();
|
||||
val if_btb_target = btb.io.target;
|
||||
|
||||
val pcr = new rocketDpathPCR();
|
||||
val ex_pcr = pcr.io.r.data;
|
||||
|
||||
val alu = new rocketDpathALU();
|
||||
val ex_alu_out = alu.io.out;
|
||||
val ex_jr_target = ex_alu_out(31,0);
|
||||
|
||||
val div = new rocketDivider(64);
|
||||
val div_result = div.io.div_result_bits;
|
||||
val div_result_tag = div.io.div_result_tag;
|
||||
val div_result_val = div.io.div_result_val;
|
||||
|
||||
val mul = new rocketMultiplier();
|
||||
val mul_result = mul.io.result;
|
||||
val mul_result_tag = mul.io.result_tag;
|
||||
val mul_result_val = mul.io.result_val;
|
||||
|
||||
val rfile = new rocketDpathRegfile();
|
||||
|
||||
// instruction fetch definitions
|
||||
val if_reg_pc = Reg(width = 32, resetVal = UFix(0, 32));
|
||||
|
||||
// instruction decode definitions
|
||||
val id_reg_pc = Reg(){UFix(width = 32)};
|
||||
val id_reg_pc_plus4 = Reg(){UFix(width = 32)};
|
||||
val id_reg_inst = Reg(width = 32, resetVal = NOP);
|
||||
|
||||
// execute definitions
|
||||
val ex_reg_pc = Reg(width = 32, resetVal = UFix(0, 32));
|
||||
val ex_reg_pc_plus4 = Reg(width = 32, resetVal = UFix(0, 32));
|
||||
val ex_reg_inst = Reg(width = 32, resetVal = Bits(0, 32));
|
||||
val ex_reg_raddr2 = Reg(width = 5, resetVal = UFix(0, 5));
|
||||
val ex_reg_raddr1 = Reg(width = 5, resetVal = UFix(0, 5));
|
||||
val ex_reg_rs2 = Reg(width = 64, resetVal = Bits(0, 64));
|
||||
val ex_reg_rs1 = Reg(width = 64, resetVal = Bits(0, 64));
|
||||
val ex_reg_waddr = Reg(width = 5, resetVal = UFix(0, 5));
|
||||
val ex_reg_ctrl_sel_alu2 = Reg(width = 2, resetVal = A2_X);
|
||||
val ex_reg_ctrl_sel_alu1 = Reg(width = 1, resetVal = A1_X);
|
||||
val ex_reg_ctrl_fn_dw = Reg(width = 1, resetVal = DW_X);
|
||||
val ex_reg_ctrl_fn_alu = Reg(width = 4, resetVal = FN_X);
|
||||
val ex_reg_ctrl_ll_wb = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_ctrl_mul_val = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_ctrl_mul_fn = Reg(width = 3, resetVal = MUL_X);
|
||||
val ex_reg_ctrl_div_val = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_ctrl_div_fn = Reg(width = 4, resetVal = DIV_X);
|
||||
val ex_reg_ctrl_sel_wb = Reg(width = 3, resetVal = WB_X);
|
||||
val ex_reg_ctrl_wen = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_ctrl_ren_pcr = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_ctrl_wen_pcr = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_ctrl_eret = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_ctrl_exception = Reg(width = 1, resetVal = Bool(false));
|
||||
val ex_reg_ctrl_cause = Reg(width = 5, resetVal = UFix(0,5));
|
||||
val ex_wdata = Wire() { Bits() };
|
||||
|
||||
// instruction fetch stage
|
||||
val if_pc_plus4 = if_reg_pc + UFix(4, 32);
|
||||
|
||||
val ex_sign_extend =
|
||||
Cat(Fill(52, ex_reg_inst(21)), ex_reg_inst(21,10));
|
||||
val ex_sign_extend_split =
|
||||
Cat(Fill(52, ex_reg_inst(31)), ex_reg_inst(31,27), ex_reg_inst(16,10));
|
||||
|
||||
val branch_adder_rhs =
|
||||
Mux(io.ctrl.sel_pc === PC_BR, Cat(ex_sign_extend_split(30,0), UFix(0, 1)),
|
||||
Cat(Fill(6, ex_reg_inst(31)), ex_reg_inst(31,7), UFix(0, 1)));
|
||||
|
||||
val ex_branch_target = ex_reg_pc + branch_adder_rhs.toUFix;
|
||||
|
||||
btb.io.correct_target := ex_branch_target;
|
||||
|
||||
val if_next_pc =
|
||||
Mux(io.ctrl.sel_pc === PC_4, if_pc_plus4,
|
||||
Mux(io.ctrl.sel_pc === PC_BTB, if_btb_target,
|
||||
Mux(io.ctrl.sel_pc === PC_EX4, ex_reg_pc_plus4,
|
||||
Mux(io.ctrl.sel_pc === PC_BR, ex_branch_target,
|
||||
Mux(io.ctrl.sel_pc === PC_J, ex_branch_target,
|
||||
Mux(io.ctrl.sel_pc === PC_JR, ex_jr_target.toUFix,
|
||||
Mux(io.ctrl.sel_pc === PC_PCR, ex_pcr(31,0).toUFix,
|
||||
UFix(0, 32))))))));
|
||||
|
||||
when (!io.host.start){
|
||||
if_reg_pc <== UFix(0, 32); //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);
|
||||
|
||||
btb.io.current_pc4 := if_pc_plus4;
|
||||
btb.io.hit ^^ io.dpath.btb_hit;
|
||||
btb.io.wen ^^ io.ctrl.wen_btb;
|
||||
btb.io.correct_pc4 := ex_reg_pc_plus4;
|
||||
|
||||
// instruction decode stage
|
||||
when (!io.ctrl.stalld) {
|
||||
id_reg_pc <== if_reg_pc;
|
||||
id_reg_pc_plus4 <== if_pc_plus4;
|
||||
when(io.ctrl.killf) {
|
||||
id_reg_inst <== NOP;
|
||||
}
|
||||
otherwise {
|
||||
id_reg_inst <== io.imem.resp_data;
|
||||
}
|
||||
}
|
||||
|
||||
val id_raddr1 = id_reg_inst(26,22).toUFix;
|
||||
val id_raddr2 = id_reg_inst(21,17).toUFix;
|
||||
|
||||
// regfile read
|
||||
rfile.io.r0.en ^^ io.ctrl.ren2;
|
||||
rfile.io.r0.addr := id_raddr2;
|
||||
val id_rdata2 = rfile.io.r0.data;
|
||||
|
||||
rfile.io.r1.en ^^ io.ctrl.ren1;
|
||||
rfile.io.r1.addr := id_raddr1;
|
||||
val id_rdata1 = rfile.io.r1.data;
|
||||
|
||||
val id_waddr =
|
||||
Mux(io.ctrl.div_wb, div_result_tag,
|
||||
Mux(io.ctrl.mul_wb, mul_result_tag,
|
||||
Mux(io.ctrl.sel_wa === WA_RD, id_reg_inst(31,27).toUFix,
|
||||
Mux(io.ctrl.sel_wa === WA_RA, RA,
|
||||
UFix(0, 5)))));
|
||||
|
||||
val id_rs1 =
|
||||
Mux(io.ctrl.div_wb, div_result,
|
||||
Mux(io.ctrl.mul_wb, mul_result,
|
||||
Mux(id_raddr1 != UFix(0, 5) && ex_reg_ctrl_wen && id_raddr1 === ex_reg_waddr, ex_wdata,
|
||||
id_rdata1)));
|
||||
|
||||
val id_rs2 =
|
||||
Mux(id_raddr2 != UFix(0, 5) && ex_reg_ctrl_wen && id_raddr2 === ex_reg_waddr, ex_wdata,
|
||||
id_rdata2);
|
||||
|
||||
val id_exception = io.ctrl.xcpt_illegal || io.ctrl.xcpt_privileged || io.ctrl.xcpt_fpu || io.ctrl.xcpt_syscall;
|
||||
val id_cause =
|
||||
Mux(io.ctrl.xcpt_illegal, UFix(2,5),
|
||||
Mux(io.ctrl.xcpt_privileged, UFix(3,5),
|
||||
Mux(io.ctrl.xcpt_fpu, UFix(4,5),
|
||||
Mux(io.ctrl.xcpt_syscall, UFix(6,5),
|
||||
UFix(0,5)))));
|
||||
|
||||
io.dpath.inst := id_reg_inst;
|
||||
io.dpath.rs1 := id_rs1;
|
||||
io.dpath.rs2 := id_rs2;
|
||||
|
||||
// execute stage
|
||||
ex_reg_pc <== id_reg_pc;
|
||||
ex_reg_pc_plus4 <== id_reg_pc_plus4;
|
||||
ex_reg_inst <== id_reg_inst;
|
||||
ex_reg_raddr2 <== id_raddr2;
|
||||
ex_reg_raddr1 <== id_raddr1;
|
||||
ex_reg_rs2 <== id_rs2;
|
||||
ex_reg_rs1 <== id_rs1;
|
||||
ex_reg_waddr <== id_waddr;
|
||||
ex_reg_ctrl_sel_alu2 <== io.ctrl.sel_alu2;
|
||||
ex_reg_ctrl_sel_alu1 <== io.ctrl.sel_alu1.toUFix;
|
||||
ex_reg_ctrl_fn_dw <== io.ctrl.fn_dw.toUFix;
|
||||
ex_reg_ctrl_fn_alu <== io.ctrl.fn_alu;
|
||||
ex_reg_ctrl_mul_fn <== io.ctrl.mul_fn;
|
||||
ex_reg_ctrl_div_fn <== io.ctrl.div_fn;
|
||||
ex_reg_ctrl_ll_wb <== io.ctrl.div_wb | io.ctrl.mul_wb; // TODO: verify
|
||||
ex_reg_ctrl_sel_wb <== io.ctrl.sel_wb;
|
||||
ex_reg_ctrl_ren_pcr <== io.ctrl.ren_pcr;
|
||||
ex_reg_ctrl_cause <== id_cause;
|
||||
|
||||
when(io.ctrl.killd) {
|
||||
ex_reg_ctrl_div_val <== Bool(false);
|
||||
ex_reg_ctrl_mul_val <== Bool(false);
|
||||
ex_reg_ctrl_wen <== Bool(false);
|
||||
ex_reg_ctrl_wen_pcr <== Bool(false);
|
||||
ex_reg_ctrl_eret <== Bool(false);
|
||||
ex_reg_ctrl_exception <== Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
ex_reg_ctrl_div_val <== io.ctrl.div_val;
|
||||
ex_reg_ctrl_mul_val <== io.ctrl.mul_val;
|
||||
ex_reg_ctrl_wen <== io.ctrl.wen;
|
||||
ex_reg_ctrl_wen_pcr <== io.ctrl.wen_pcr;
|
||||
ex_reg_ctrl_eret <== io.ctrl.eret;
|
||||
ex_reg_ctrl_exception <== id_exception;
|
||||
}
|
||||
|
||||
val ex_alu_in2 =
|
||||
Mux(ex_reg_ctrl_sel_alu2 === A2_0, UFix(0, 64),
|
||||
Mux(ex_reg_ctrl_sel_alu2 === A2_SEXT, ex_sign_extend,
|
||||
Mux(ex_reg_ctrl_sel_alu2 === A2_SPLIT, ex_sign_extend_split,
|
||||
Mux(ex_reg_ctrl_sel_alu2 === A2_RS2, ex_reg_rs2,
|
||||
UFix(0, 64)))));
|
||||
|
||||
val ex_alu_in1 =
|
||||
Mux(ex_reg_ctrl_sel_alu1 === A1_RS1, ex_reg_rs1,
|
||||
Mux(ex_reg_ctrl_sel_alu1 === A1_LUI, Cat(Fill(32, ex_reg_inst(26)),ex_reg_inst(26,7),UFix(0, 12)),
|
||||
UFix(0, 64)));
|
||||
|
||||
val ex_alu_shamt =
|
||||
Cat(ex_alu_in2(5) & ex_reg_ctrl_fn_dw === DW_64, ex_alu_in2(4,0)).toUFix;
|
||||
|
||||
alu.io.dw := ex_reg_ctrl_fn_dw;
|
||||
alu.io.fn := ex_reg_ctrl_fn_alu;
|
||||
alu.io.shamt := ex_alu_shamt.toUFix;
|
||||
alu.io.in2 := ex_alu_in2.toUFix;
|
||||
alu.io.in1 := ex_alu_in1.toUFix;
|
||||
|
||||
// divider
|
||||
div.io.div_fn := ex_reg_ctrl_div_fn;
|
||||
div.io.div_val := ex_reg_ctrl_div_val;
|
||||
div.io.div_waddr := ex_reg_waddr;
|
||||
div.io.dpath_rs1 := ex_reg_rs1;
|
||||
div.io.dpath_rs2 := ex_reg_rs2;
|
||||
div.io.div_result_rdy := io.ctrl.div_wb;
|
||||
|
||||
io.dpath.div_rdy := div.io.div_rdy;
|
||||
io.dpath.div_result_val := div.io.div_result_val;
|
||||
|
||||
// multiplier
|
||||
mul.io.mul_val := ex_reg_ctrl_mul_val;
|
||||
mul.io.mul_fn := ex_reg_ctrl_mul_fn;
|
||||
mul.io.mul_tag := ex_reg_waddr;
|
||||
mul.io.in0 := ex_reg_rs1;
|
||||
mul.io.in1 := ex_reg_rs2;
|
||||
|
||||
io.dpath.mul_result_val := mul.io.result_val;
|
||||
|
||||
// processor control register i/o
|
||||
pcr.io.host.from_wen ^^ io.host.from_wen;
|
||||
pcr.io.host.from ^^ io.host.from;
|
||||
pcr.io.host.to ^^ io.host.to;
|
||||
|
||||
pcr.io.r.en := ex_reg_ctrl_ren_pcr | ex_reg_ctrl_exception | ex_reg_ctrl_eret;
|
||||
pcr.io.r.addr :=
|
||||
Mux(ex_reg_ctrl_exception, PCR_EVEC,
|
||||
Mux(ex_reg_ctrl_eret, PCR_EPC,
|
||||
ex_reg_raddr2));
|
||||
|
||||
pcr.io.w.addr := ex_reg_raddr2;
|
||||
pcr.io.w.en := ex_reg_ctrl_wen_pcr;
|
||||
pcr.io.w.data := ex_reg_rs1;
|
||||
|
||||
pcr.io.eret := ex_reg_ctrl_eret;
|
||||
pcr.io.exception := ex_reg_ctrl_exception;
|
||||
pcr.io.cause := ex_reg_ctrl_cause;
|
||||
pcr.io.pc := ex_reg_pc;
|
||||
|
||||
io.dpath.status := pcr.io.status;
|
||||
// io.debug ^^ pcr.io.debug;
|
||||
|
||||
io.debug.error_mode := pcr.io.debug.error_mode;
|
||||
io.debug.log_control := pcr.io.debug.log_control;
|
||||
|
||||
// branch resolution logic
|
||||
io.dpath.br_eq := (ex_reg_rs1 === ex_reg_rs2);
|
||||
io.dpath.br_ltu := (ex_reg_rs1.toUFix < ex_reg_rs2.toUFix);
|
||||
io.dpath.br_lt :=
|
||||
(~(ex_reg_rs1(63) ^ ex_reg_rs2(63)) & io.dpath.br_ltu |
|
||||
ex_reg_rs1(63) & ~ex_reg_rs2(63)).toBool;
|
||||
|
||||
io.dpath.alu_out := ex_alu_out;
|
||||
|
||||
// writeback select mux
|
||||
ex_wdata :=
|
||||
Mux(ex_reg_ctrl_ll_wb, ex_reg_rs1,
|
||||
Mux(ex_reg_ctrl_sel_wb === WB_PC, ex_reg_pc_plus4,
|
||||
Mux(ex_reg_ctrl_sel_wb === WB_ALU, ex_alu_out,
|
||||
Mux(ex_reg_ctrl_sel_wb === WB_PCR, ex_pcr,
|
||||
Bits(0, 64))))).toBits;
|
||||
|
||||
// regfile write
|
||||
rfile.io.w0.addr := ex_reg_waddr;
|
||||
rfile.io.w0.en := ex_reg_ctrl_wen | ex_reg_ctrl_ll_wb;
|
||||
rfile.io.w0.data := ex_wdata;
|
||||
|
||||
rfile.io.w1.addr ^^ io.wb.waddr;
|
||||
rfile.io.w1.en ^^ io.wb.wen;
|
||||
rfile.io.w1.data ^^ io.wb.wdata;
|
||||
|
||||
// clear scoreboard for "long latency" writebacks
|
||||
io.dpath.wen := ex_reg_ctrl_ll_wb;
|
||||
io.dpath.waddr := ex_reg_waddr;
|
||||
|
||||
// exception signal to control (for NPC select)
|
||||
io.dpath.exception := ex_reg_ctrl_exception;
|
||||
|
||||
}
|
||||
|
||||
}
|
90
rocket/src/main/scala/dpath_alu.scala
Normal file
90
rocket/src/main/scala/dpath_alu.scala
Normal file
@ -0,0 +1,90 @@
|
||||
package Top {
|
||||
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
|
||||
import Constants._
|
||||
import Instructions._
|
||||
|
||||
class ioALU extends Bundle(){
|
||||
val dw = UFix(1, 'input);
|
||||
val fn = UFix(4, 'input);
|
||||
val shamt = UFix(6, 'input);
|
||||
val in2 = UFix(64, 'input);
|
||||
val in1 = UFix(64, 'input);
|
||||
val out = UFix(64, 'output);
|
||||
}
|
||||
|
||||
class rocketDpathALU extends Component
|
||||
{
|
||||
override val io = new ioALU();
|
||||
val out64 =
|
||||
MuxCase(Fix(0, 64), Array(
|
||||
(io.fn === FN_ADD) -> (io.in1 + io.in2).toFix,
|
||||
(io.fn === FN_SUB) -> (io.in1 - io.in2).toFix,
|
||||
(io.fn === FN_SLT) -> (io.in1.toFix < io.in2.toFix), //(io.in1 < io.in2)
|
||||
(io.fn === FN_SLTU) -> (io.in1 < io.in2).toFix,
|
||||
(io.fn === FN_AND) -> (io.in1 & io.in2).toFix,
|
||||
(io.fn === FN_OR) -> (io.in1 | io.in2).toFix,
|
||||
(io.fn === FN_XOR) -> (io.in1 ^ io.in2).toFix,
|
||||
(io.fn === FN_SL) -> (io.in1 << io.shamt).toFix,
|
||||
(io.fn === FN_SR && io.dw === DW_64) -> (io.in1 >> io.shamt).toFix,
|
||||
(io.fn === FN_SR && io.dw === DW_32) -> (Cat(Fix(0, 32),io.in1(31, 0)).toUFix >> io.shamt),
|
||||
(io.fn === FN_SRA) -> (io.in1.toFix >>> io.shamt)));
|
||||
|
||||
io.out := MuxLookup(io.dw, Fix(0, 64), Array(
|
||||
DW_64 -> out64,
|
||||
DW_32 -> Cat(Fill(32, out64(31)), out64(31,0)).toFix)).toUFix;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
class IoDpathALU extends Bundle {
|
||||
val in0 = Bits(32,'input);
|
||||
val in1 = Bits(32,'input);
|
||||
val fn = Bits(4,'input);
|
||||
val out = Bits(32,'output);
|
||||
}
|
||||
|
||||
class DpathALU extends Component {
|
||||
val io = new IoDpathALU();
|
||||
|
||||
val adder_in0 = MuxCase(io.in0,Array(
|
||||
((io.fn === FN_SUB) | (io.fn === FN_SLT) | (io.fn === FN_SLTU)) -> (~io.in0)));
|
||||
|
||||
val adder_in1 = io.in1;
|
||||
val adder_cin = MuxCase(Bits(0),Array(
|
||||
((io.fn === FN_SUB) | (io.fn === FN_SLT) | (io.fn === FN_SLTU)) -> Bits(1)));
|
||||
|
||||
// Need to make the same width?
|
||||
val adder_out = Cat(Bits(0,1),adder_in1).toUFix + Cat(Bits(0,1),adder_in0).toUFix + adder_cin.toUFix;
|
||||
//adder_out := (adder_in1.toUFix + adder_in0.toUFix + adder_cin.toUFix);
|
||||
|
||||
// Determine if there is overflow
|
||||
val overflow = (io.in0(31) ^ io.in1(31)) & (adder_out(32) != io.in0(31));
|
||||
|
||||
val compare_yes = MuxLookup(io.fn,Bits(0),Array(
|
||||
// If unsigned, do subtraction, and if the result is negative, then slt=true
|
||||
FN_SLTU -> ~adder_out(32),
|
||||
// If signed, do subtraction, and if the result is negative, then slt=true as well
|
||||
// But if there is bad overflow (operands same sign and result is a different sign),
|
||||
// then need to flip
|
||||
FN_SLT -> ~(adder_out(32) ^ overflow)));
|
||||
|
||||
io.out := MuxLookup(io.fn,Fix(0),Array(
|
||||
FN_ADD -> adder_out,
|
||||
FN_SUB -> adder_out,
|
||||
FN_SLT -> compare_yes,
|
||||
FN_SLTU -> compare_yes,
|
||||
FN_AND -> (io.in0 & io.in1),
|
||||
FN_OR -> (io.in0 | io.in1),
|
||||
FN_XOR -> (io.in0 ^ io.in1),
|
||||
FN_SL -> (io.in1 << io.in0(4,0).toUFix),
|
||||
FN_SR -> (io.in1 >> io.in0(4,0).toUFix),
|
||||
FN_SRA -> (io.in1.toFix >> io.in0(4,0).toUFix)
|
||||
));
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
184
rocket/src/main/scala/dpath_util.scala
Normal file
184
rocket/src/main/scala/dpath_util.scala
Normal file
@ -0,0 +1,184 @@
|
||||
package Top
|
||||
{
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
|
||||
import Constants._;
|
||||
|
||||
class ioDpathBTB extends Bundle()
|
||||
{
|
||||
val current_pc4 = UFix(32, 'input);
|
||||
val hit = Bool('output);
|
||||
val target = UFix(32, 'output);
|
||||
val wen = Bool('input);
|
||||
val correct_pc4 = UFix(32, 'input);
|
||||
val correct_target = UFix(32, 'input);
|
||||
}
|
||||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
class ioDpathPCR extends Bundle()
|
||||
{
|
||||
val host = new ioHost(List("from", "from_wen", "to"));
|
||||
val debug = new ioDebug();
|
||||
val r = new ioReadPort();
|
||||
val w = new ioWritePort();
|
||||
|
||||
val status = Bits(8, 'output);
|
||||
val exception = Bool('input);
|
||||
val cause = UFix(5, 'input);
|
||||
val pc = UFix(32, '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 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));
|
||||
val reg_count = Reg(resetVal = Bits(0, w));
|
||||
val reg_compare = Reg(resetVal = Bits(0, w));
|
||||
val reg_cause = Reg(resetVal = Bits(0, 5));
|
||||
val reg_tohost = Reg(resetVal = Bits(0, w));
|
||||
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_error_mode = Reg(resetVal = Bool(false));
|
||||
val reg_log_control = 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));
|
||||
val reg_status_ef = Reg(resetVal = Bool(false));
|
||||
val reg_status_ev = Reg(resetVal = Bool(false));
|
||||
val reg_status_s = Reg(resetVal = Bool(true));
|
||||
val reg_status_ps = Reg(resetVal = Bool(false));
|
||||
val reg_status_et = Reg(resetVal = Bool(false));
|
||||
|
||||
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.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;
|
||||
io.r.data := rdata;
|
||||
|
||||
when (io.host.from_wen) {
|
||||
reg_tohost <== Bits(0, w);
|
||||
reg_fromhost <== io.host.from;
|
||||
}
|
||||
otherwise {
|
||||
when (!io.exception && io.w.en && (io.w.addr === PCR_TOHOST)) {
|
||||
reg_tohost <== io.w.data(w-1, 0);
|
||||
reg_fromhost <== Bits(0, w);
|
||||
}
|
||||
}
|
||||
|
||||
when (io.exception && !reg_status_et) {
|
||||
reg_error_mode <== Bool(true);
|
||||
}
|
||||
|
||||
when (io.exception && reg_status_et) {
|
||||
reg_status_s <== Bool(true);
|
||||
reg_status_ps <== reg_status_s;
|
||||
reg_status_et <== Bool(false);
|
||||
reg_epc <== io.pc;
|
||||
reg_cause <== io.cause;
|
||||
}
|
||||
|
||||
when (!io.exception && io.eret) {
|
||||
reg_status_s <== reg_status_ps;
|
||||
reg_status_et <== Bool(true);
|
||||
}
|
||||
|
||||
when (!io.exception && !io.eret && io.w.en) {
|
||||
when (io.w.addr === PCR_STATUS) {
|
||||
reg_status_im <== io.w.data(15,8);
|
||||
reg_status_sx <== io.w.data(7).toBool;
|
||||
reg_status_ux <== io.w.data(6).toBool;
|
||||
reg_status_s <== io.w.data(5).toBool;
|
||||
reg_status_ps <== io.w.data(4).toBool;
|
||||
reg_status_ev <== HAVE_VEC && io.w.data(2).toBool;
|
||||
reg_status_ef <== HAVE_FPU && io.w.data(1).toBool;
|
||||
reg_status_et <== io.w.data(0).toBool;
|
||||
}
|
||||
when (io.w.addr === PCR_EPC) { reg_epc <== io.w.data(w-1,0); }
|
||||
when (io.w.addr === PCR_BADVADDR) { reg_badvaddr <== io.w.data(w-1,0); }
|
||||
when (io.w.addr === PCR_EVEC) { reg_ebase <== io.w.data(w-1,0); }
|
||||
when (io.w.addr === PCR_COUNT) { reg_count <== io.w.data(w-1,0); }
|
||||
when (io.w.addr === PCR_COMPARE) { reg_compare <== io.w.data(w-1,0); }
|
||||
when (io.w.addr === PCR_CAUSE) { reg_cause <== io.w.data(4,0); }
|
||||
when (io.w.addr === PCR_LOG) { reg_log_control <== io.w.data(0).toBool; }
|
||||
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.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_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); }
|
||||
is (PCR_COUNT) { rdata <== Cat(Fill(w, reg_count(w-1)), reg_count); }
|
||||
is (PCR_COMPARE) { rdata <== Cat(Fill(w, reg_compare(w-1)), reg_compare); }
|
||||
is (PCR_CAUSE) { rdata <== Cat(Bits(0,w+27), reg_cause); }
|
||||
is (PCR_MEMSIZE) { rdata <== Bits("h2000", 2*w); }
|
||||
is (PCR_LOG) { rdata <== Cat(Bits(0,63), reg_log_control); }
|
||||
is (PCR_FROMHOST) { rdata <== Cat(Fill(w, reg_fromhost(w-1)), reg_fromhost); }
|
||||
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; }
|
||||
otherwise { rdata <== Bits(0,2*w); }
|
||||
}
|
||||
}
|
||||
|
||||
class ioReadPort extends Bundle()
|
||||
{
|
||||
val addr = UFix(5, 'input);
|
||||
val en = Bool('input);
|
||||
val data = Bits(64, 'output);
|
||||
}
|
||||
|
||||
class ioWritePort extends Bundle()
|
||||
{
|
||||
val addr = UFix(5, 'input);
|
||||
val en = Bool('input);
|
||||
val data = Bits(64, 'input);
|
||||
}
|
||||
|
||||
class ioRegfile extends Bundle()
|
||||
{
|
||||
val r0 = new ioReadPort();
|
||||
val r1 = new ioReadPort();
|
||||
val w0 = new ioWritePort();
|
||||
val w1 = new ioWritePort();
|
||||
}
|
||||
|
||||
class rocketDpathRegfile extends Component
|
||||
{
|
||||
override val io = new ioRegfile();
|
||||
val regfile = Mem(32, io.w0.en && (io.w0.addr != UFix(0,5)), io.w0.addr, io.w0.data);
|
||||
regfile.write(io.w1.en && (io.w1.addr != UFix(0,5)), io.w1.addr, io.w1.data);
|
||||
io.r0.data := Mux((io.r0.addr === UFix(0, 5)) || !io.r0.en, Bits(0, 64), regfile(io.r0.addr));
|
||||
io.r1.data := Mux((io.r1.addr === UFix(0, 5)) || !io.r1.en, Bits(0, 64), regfile(io.r1.addr));
|
||||
}
|
||||
|
||||
}
|
120
rocket/src/main/scala/icache.scala
Normal file
120
rocket/src/main/scala/icache.scala
Normal file
@ -0,0 +1,120 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import scala.math._;
|
||||
|
||||
// interface between I$ and processor (32 bits wide)
|
||||
class ioImem(view: List[String] = null) extends Bundle (view)
|
||||
{
|
||||
val req_addr = UFix(32, 'input);
|
||||
val req_val = Bool('input);
|
||||
val req_rdy = Bool('output);
|
||||
val resp_data = Bits(32, 'output);
|
||||
val resp_val = Bool('output);
|
||||
}
|
||||
|
||||
// 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_val = Bool('input);
|
||||
val req_rdy = Bool('output);
|
||||
val resp_data = Bits(128, 'output);
|
||||
val resp_val = Bool('output);
|
||||
}
|
||||
|
||||
class ioICacheDM extends Bundle() {
|
||||
val cpu = new ioImem();
|
||||
val mem = new ioIcache().flip();
|
||||
}
|
||||
|
||||
// basic direct mapped instruction cache
|
||||
// parameters :
|
||||
// lines = # cache lines
|
||||
// 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 {
|
||||
val io = new ioICacheDM();
|
||||
|
||||
val indexbits = ceil(log10(lines)/log10(2)).toInt;
|
||||
val offsetbits = 6;
|
||||
val tagmsb = addrbits - 1;
|
||||
val taglsb = indexbits+offsetbits;
|
||||
val indexmsb = taglsb-1;
|
||||
val indexlsb = offsetbits;
|
||||
val offsetmsb = indexlsb-1;
|
||||
val offsetlsb = 2;
|
||||
|
||||
val s_reset :: s_ready :: s_request :: s_refill_wait :: s_refill :: s_resolve_miss :: Nil = Enum(6) { UFix() };
|
||||
val state = Reg(resetVal = s_reset);
|
||||
|
||||
val r_cpu_req_addr = Reg(Bits(0, addrbits));
|
||||
when (io.cpu.req_val && ((state === s_ready) || (state === s_resolve_miss))) { r_cpu_req_addr <== io.cpu.req_addr; }
|
||||
|
||||
val r_cpu_req_val = Reg(Bool(false));
|
||||
when ((state === s_ready) || (state === s_resolve_miss)) { r_cpu_req_val <== io.cpu.req_val; }
|
||||
otherwise { r_cpu_req_val <== Bool(false); }
|
||||
|
||||
val refill_count = Reg(resetVal = UFix(0,2));
|
||||
when (io.mem.resp_val) { refill_count <== refill_count + UFix(1); }
|
||||
|
||||
// tag array
|
||||
val tag_wdata = r_cpu_req_addr(tagmsb, taglsb);
|
||||
val tag_waddr = r_cpu_req_addr(indexmsb, indexlsb).toUFix;
|
||||
val tag_we = (state === s_refill_wait) && io.mem.resp_val;
|
||||
val tag_array = Mem(lines, tag_we, tag_waddr, tag_wdata);
|
||||
val tag_raddr = io.cpu.req_addr(indexmsb, indexlsb);;
|
||||
val tag_lookup = Reg(tag_array.read(tag_raddr));
|
||||
|
||||
// valid bit array
|
||||
val vb_array = Reg(resetVal = Bits(0, lines));
|
||||
val vb_rdata = Reg(vb_array(io.cpu.req_addr(indexmsb, indexlsb)));
|
||||
|
||||
when ((state === s_refill_wait) && io.mem.resp_val) { vb_array <== vb_array.bitSet(r_cpu_req_addr(indexmsb, indexlsb).toUFix, UFix(1,1)); }
|
||||
|
||||
val tag_match = vb_rdata.toBool && (tag_lookup === r_cpu_req_addr(tagmsb, taglsb));
|
||||
|
||||
// data array
|
||||
val data_array_waddr = Cat(r_cpu_req_addr(indexmsb, indexlsb), refill_count).toUFix;
|
||||
val data_array = Mem(lines*4, io.mem.resp_val, data_array_waddr, io.mem.resp_data);
|
||||
val data_array_raddr = Cat(io.cpu.req_addr(indexmsb, indexlsb), io.cpu.req_addr(offsetmsb, offsetmsb-1));
|
||||
val data_array_read = data_array(data_array_raddr);
|
||||
val data_array_rdata = Reg(data_array_read);
|
||||
|
||||
io.cpu.resp_val := (r_cpu_req_val && tag_match && (state === s_ready)); // || (state === s_resolve_miss);
|
||||
io.cpu.req_rdy := ((state === s_ready) && (!r_cpu_req_val || (r_cpu_req_val && tag_match))); // || (state === s_resolve_miss);
|
||||
io.cpu.resp_data := MuxLookup(r_cpu_req_addr(offsetmsb-2, offsetlsb).toUFix, data_array_rdata(127, 96),
|
||||
Array(UFix(2) -> data_array_rdata(95,64),
|
||||
UFix(1) -> data_array_rdata(63,32),
|
||||
UFix(0) -> data_array_rdata(31,0)));
|
||||
|
||||
io.mem.req_val := (state === s_request);
|
||||
io.mem.req_addr := Cat(r_cpu_req_addr(tagmsb, indexlsb), Bits(0,2)).toUFix;
|
||||
|
||||
// control state machine
|
||||
switch (state) {
|
||||
is (s_reset) {
|
||||
state <== s_ready;
|
||||
}
|
||||
is (s_ready) {
|
||||
when (r_cpu_req_val && !tag_match) { state <== s_request; }
|
||||
}
|
||||
is (s_request)
|
||||
{
|
||||
when (io.mem.req_rdy) { state <== s_refill_wait; }
|
||||
}
|
||||
is (s_refill_wait) {
|
||||
when (io.mem.resp_val) { state <== s_refill; }
|
||||
}
|
||||
is (s_refill) {
|
||||
when (io.mem.resp_val && (refill_count === UFix(3,2))) { state <== s_resolve_miss; }
|
||||
}
|
||||
is (s_resolve_miss) {
|
||||
state <== s_ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
91
rocket/src/main/scala/icache_prefetch.scala
Normal file
91
rocket/src/main/scala/icache_prefetch.scala
Normal file
@ -0,0 +1,91 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._;
|
||||
import Node._;
|
||||
import queues._;
|
||||
|
||||
class ioIPrefetcherMem(view: List[String] = null) extends Bundle (view)
|
||||
{
|
||||
val req_addr = UFix(32, 'output);
|
||||
val req_val = Bool('output);
|
||||
val req_rdy = Bool('input);
|
||||
val req_tag = Bits(3, 'output);
|
||||
val resp_data = Bits(128, 'input);
|
||||
val resp_val = Bool('input);
|
||||
val resp_tag = Bits(3, 'input);
|
||||
}
|
||||
|
||||
class ioIPrefetcher extends Bundle() {
|
||||
val icache = new ioIcache();
|
||||
val mem = new ioIPrefetcherMem();
|
||||
}
|
||||
|
||||
class rocketIPrefetcher extends Component() {
|
||||
val io = new ioIPrefetcher();
|
||||
val pdq = new queueSimplePF(128, 4, 2);
|
||||
|
||||
val s_invalid :: s_valid :: s_refilling :: s_req_wait :: s_resp_wait :: s_bad_resp_wait :: Nil = Enum(6) { UFix() };
|
||||
val state = Reg(resetVal = s_invalid);
|
||||
|
||||
val demand_miss = io.icache.req_val & io.icache.req_rdy;
|
||||
val prefetch_addr = Reg(resetVal = UFix(0,32));
|
||||
when (demand_miss) { prefetch_addr <== io.icache.req_addr + UFix(4); }
|
||||
|
||||
val addr_match = (prefetch_addr === io.icache.req_addr);
|
||||
val hit = (state != s_invalid) & (state != s_req_wait) & addr_match;
|
||||
|
||||
io.icache.req_rdy := io.mem.req_rdy;
|
||||
val ip_mem_req_rdy = io.mem.req_rdy & ~(io.icache.req_val & ~hit);
|
||||
val ip_mem_resp_val = io.mem.resp_val && io.mem.resp_tag(0).toBool;
|
||||
|
||||
io.mem.req_val := io.icache.req_val & ~hit | (state === s_req_wait);
|
||||
io.mem.req_tag := !(io.icache.req_val && !hit);
|
||||
io.mem.req_addr := Mux(io.mem.req_tag.toBool, prefetch_addr, io.icache.req_addr);
|
||||
|
||||
val pdq_reset = Reg(resetVal = Bool(true));
|
||||
pdq_reset <== demand_miss & ~hit | (state === s_bad_resp_wait);
|
||||
|
||||
val fill_cnt = Reg(resetVal = UFix(0, 2));
|
||||
when (ip_mem_resp_val.toBool) { fill_cnt <== fill_cnt + UFix(1,1); }
|
||||
val fill_done = (fill_cnt === UFix(3,2)) & ip_mem_resp_val;
|
||||
|
||||
val forward = Reg(resetVal = Bool(false));
|
||||
val forward_cnt = Reg(resetVal = UFix(0, 2));
|
||||
when (forward & pdq.io.deq_val) { forward_cnt <== forward_cnt + UFix(1,1); }
|
||||
val forward_done = (forward_cnt === UFix(3, 2)) & pdq.io.deq_val;
|
||||
forward <== (demand_miss & hit | forward & ~forward_done);
|
||||
|
||||
io.icache.resp_val := (io.mem.resp_val && !io.mem.resp_tag.toBool) || (forward && pdq.io.deq_val);
|
||||
io.icache.resp_data := Mux(forward, pdq.io.deq_bits, io.mem.resp_data);
|
||||
|
||||
pdq.io.q_reset := pdq_reset;
|
||||
pdq.io.enq_bits := io.mem.resp_data;
|
||||
pdq.io.enq_val := ip_mem_resp_val.toBool;
|
||||
pdq.io.deq_rdy := forward;
|
||||
|
||||
switch (state) {
|
||||
is (s_invalid) {
|
||||
when (demand_miss) { state <== s_req_wait; }
|
||||
}
|
||||
is (s_valid) {
|
||||
when (demand_miss | (forward & forward_done)) { state <== s_req_wait; }
|
||||
}
|
||||
is (s_refilling) {
|
||||
when (demand_miss & ~addr_match & fill_done.toBool) { state <== s_req_wait; }
|
||||
when (demand_miss & ~addr_match) { state <== s_bad_resp_wait; }
|
||||
when (fill_done.toBool) { state <== s_valid; }
|
||||
}
|
||||
is (s_req_wait) {
|
||||
when (ip_mem_req_rdy) { state <== s_resp_wait; }
|
||||
}
|
||||
is (s_resp_wait) {
|
||||
when (demand_miss & ~addr_match) { state <== s_bad_resp_wait; }
|
||||
when (ip_mem_resp_val.toBool) { state <== s_refilling; }
|
||||
}
|
||||
is (s_bad_resp_wait) {
|
||||
when (fill_done.toBool & ip_mem_resp_val.toBool) { state <== s_req_wait; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
162
rocket/src/main/scala/instructions.scala
Normal file
162
rocket/src/main/scala/instructions.scala
Normal file
@ -0,0 +1,162 @@
|
||||
package Top {
|
||||
import Chisel._
|
||||
import Node._;
|
||||
|
||||
object Instructions
|
||||
{
|
||||
val UNIMP = Bits("b00000000000000000000000000000000", 32);
|
||||
val J = Bits("b?????????????????????????_1100111", 32);
|
||||
val JAL = Bits("b?????????????????????????_1101111", 32);
|
||||
val JALR_C = Bits("b?????_?????_????????????_000_1101011", 32);
|
||||
val JALR_R = Bits("b?????_?????_????????????_001_1101011", 32);
|
||||
val JALR_J = Bits("b?????_?????_????????????_010_1101011", 32);
|
||||
val BEQ = Bits("b?????_?????_?????_???????_000_1100011", 32);
|
||||
val BNE = Bits("b?????_?????_?????_???????_001_1100011", 32);
|
||||
val BLT = Bits("b?????_?????_?????_???????_100_1100011", 32);
|
||||
val BGE = Bits("b?????_?????_?????_???????_101_1100011", 32);
|
||||
val BLTU = Bits("b?????_?????_?????_???????_110_1100011", 32);
|
||||
val BGEU = Bits("b?????_?????_?????_???????_111_1100011", 32);
|
||||
val LUI = Bits("b?????_????????????????????_0110111", 32);
|
||||
val ADDI = Bits("b?????_?????_????????????_000_0010011", 32);
|
||||
val SLLI = Bits("b?????_?????_000000_??????_001_0010011", 32);
|
||||
val SLTI = Bits("b?????_?????_????????????_010_0010011", 32);
|
||||
val SLTIU = Bits("b?????_?????_????????????_011_0010011", 32);
|
||||
val XORI = Bits("b?????_?????_????????????_100_0010011", 32);
|
||||
val SRLI = Bits("b?????_?????_000000_??????_101_0010011", 32);
|
||||
val SRAI = Bits("b?????_?????_000001_??????_101_0010011", 32);
|
||||
val ORI = Bits("b?????_?????_????????????_110_0010011", 32);
|
||||
val ANDI = Bits("b?????_?????_????????????_111_0010011", 32);
|
||||
val ADD = Bits("b?????_?????_?????_0000000000_0110011", 32);
|
||||
val SUB = Bits("b?????_?????_?????_1000000000_0110011", 32);
|
||||
val SLL = Bits("b?????_?????_?????_0000000001_0110011", 32);
|
||||
val SLT = Bits("b?????_?????_?????_0000000010_0110011", 32);
|
||||
val SLTU = Bits("b?????_?????_?????_0000000011_0110011", 32);
|
||||
val riscvXOR = Bits("b?????_?????_?????_0000000100_0110011", 32);
|
||||
val SRL = Bits("b?????_?????_?????_0000000101_0110011", 32);
|
||||
val SRA = Bits("b?????_?????_?????_1000000101_0110011", 32);
|
||||
val riscvOR = Bits("b?????_?????_?????_0000000110_0110011", 32);
|
||||
val riscvAND = Bits("b?????_?????_?????_0000000111_0110011", 32);
|
||||
val MUL = Bits("b?????_?????_?????_0000001000_0110011", 32);
|
||||
val MULH = Bits("b?????_?????_?????_0000001001_0110011", 32);
|
||||
val MULHSU = Bits("b?????_?????_?????_0000001010_0110011", 32);
|
||||
val MULHU = Bits("b?????_?????_?????_0000001011_0110011", 32);
|
||||
val DIV = Bits("b?????_?????_?????_0000001100_0110011", 32);
|
||||
val DIVU = Bits("b?????_?????_?????_0000001101_0110011", 32);
|
||||
val REM = Bits("b?????_?????_?????_0000001110_0110011", 32);
|
||||
val REMU = Bits("b?????_?????_?????_0000001111_0110011", 32);
|
||||
val ADDIW = Bits("b?????_?????_????????????_000_0011011", 32);
|
||||
val SLLIW = Bits("b?????_?????_000000_0_?????_001_0011011", 32);
|
||||
val SRLIW = Bits("b?????_?????_000000_0_?????_101_0011011", 32);
|
||||
val SRAIW = Bits("b?????_?????_000001_0_?????_101_0011011", 32);
|
||||
val ADDW = Bits("b?????_?????_?????_0000000000_0111011", 32);
|
||||
val SUBW = Bits("b?????_?????_?????_1000000000_0111011", 32);
|
||||
val SLLW = Bits("b?????_?????_?????_0000000001_0111011", 32);
|
||||
val SRLW = Bits("b?????_?????_?????_0000000101_0111011", 32);
|
||||
val SRAW = Bits("b?????_?????_?????_1000000101_0111011", 32);
|
||||
val MULW = Bits("b?????_?????_?????_0000001000_0111011", 32);
|
||||
val DIVW = Bits("b?????_?????_?????_0000001100_0111011", 32);
|
||||
val DIVUW = Bits("b?????_?????_?????_0000001101_0111011", 32);
|
||||
val REMW = Bits("b?????_?????_?????_0000001110_0111011", 32);
|
||||
val REMUW = Bits("b?????_?????_?????_0000001111_0111011", 32);
|
||||
val LB = Bits("b?????_?????_????????????_000_0000011", 32);
|
||||
val LH = Bits("b?????_?????_????????????_001_0000011", 32);
|
||||
val LW = Bits("b?????_?????_????????????_010_0000011", 32);
|
||||
val LD = Bits("b?????_?????_????????????_011_0000011", 32);
|
||||
val LBU = Bits("b?????_?????_????????????_100_0000011", 32);
|
||||
val LHU = Bits("b?????_?????_????????????_101_0000011", 32);
|
||||
val LWU = Bits("b?????_?????_????????????_110_0000011", 32);
|
||||
val SB = Bits("b?????_?????_?????_???????_000_0100011", 32);
|
||||
val SH = Bits("b?????_?????_?????_???????_001_0100011", 32);
|
||||
val SW = Bits("b?????_?????_?????_???????_010_0100011", 32);
|
||||
val SD = Bits("b?????_?????_?????_???????_011_0100011", 32);
|
||||
val AMOADD_W = Bits("b?????_?????_?????_00000_000_10_1000011", 32);
|
||||
val AMOSWAP_W = Bits("b?????_?????_?????_00000_010_10_1000011", 32);
|
||||
val AMOAND_W = Bits("b?????_?????_?????_00000_100_10_1000011", 32);
|
||||
val AMOOR_W = Bits("b?????_?????_?????_00000_110_10_1000011", 32);
|
||||
val AMOMIN_W = Bits("b?????_?????_?????_00001_000_10_1000011", 32);
|
||||
val AMOMAX_W = Bits("b?????_?????_?????_00001_010_10_1000011", 32);
|
||||
val AMOMINU_W = Bits("b?????_?????_?????_00001_100_10_1000011", 32);
|
||||
val AMOMAXU_W = Bits("b?????_?????_?????_00001_110_10_1000011", 32);
|
||||
val AMOADD_D = Bits("b?????_?????_?????_00000_000_11_1000011", 32);
|
||||
val AMOSWAP_D = Bits("b?????_?????_?????_00000_010_11_1000011", 32);
|
||||
val AMOAND_D = Bits("b?????_?????_?????_00000_100_11_1000011", 32);
|
||||
val AMOOR_D = Bits("b?????_?????_?????_00000_110_11_1000011", 32);
|
||||
val AMOMIN_D = Bits("b?????_?????_?????_00001_000_11_1000011", 32);
|
||||
val AMOMAX_D = Bits("b?????_?????_?????_00001_010_11_1000011", 32);
|
||||
val AMOMINU_D = Bits("b?????_?????_?????_00001_100_11_1000011", 32);
|
||||
val AMOMAXU_D = Bits("b?????_?????_?????_00001_110_11_1000011", 32);
|
||||
val FENCE = Bits("b?????_?????_????????????_010_0101111", 32);
|
||||
val FENCE_I = Bits("b?????_?????_????????????_001_0101111", 32);
|
||||
val RDNPC = Bits("b?????_00000_00000_0000000000_0010111", 32);
|
||||
val SYNCI = Bits("b00000_00000_00000_0000000001_0010111", 32);
|
||||
val SYNC = Bits("b00000_00000_00000_0000000010_0010111", 32);
|
||||
val SYSCALL = Bits("b00000_00000_00000_0000000000_1110111", 32);
|
||||
val BREAK = Bits("b00000_00000_00000_0000000001_1110111", 32);
|
||||
val EI = Bits("b?????_00000_00000_0000000000_1111011", 32);
|
||||
val DI = Bits("b?????_00000_00000_0000000001_1111011", 32);
|
||||
val MFPCR = Bits("b?????_00000_?????_0000000010_1111011", 32);
|
||||
val MTPCR = Bits("b00000_?????_?????_0000000011_1111011", 32);
|
||||
val ERET = Bits("b00000_00000_00000_0000000100_1111011", 32);
|
||||
val FADD_S = Bits("b?????_?????_?????_00000_???_00_1010011", 32);
|
||||
val FSUB_S = Bits("b?????_?????_?????_00001_???_00_1010011", 32);
|
||||
val FMUL_S = Bits("b?????_?????_?????_00010_???_00_1010011", 32);
|
||||
val FDIV_S = Bits("b?????_?????_?????_00011_???_00_1010011", 32);
|
||||
val FSQRT_S = Bits("b?????_?????_00000_00100_???_00_1010011", 32);
|
||||
val FSGNJ_S = Bits("b?????_?????_?????_0010111100_1010011", 32);
|
||||
val FSGNJN_S = Bits("b?????_?????_?????_0011011100_1010011", 32);
|
||||
val FSGNJX_S = Bits("b?????_?????_?????_0011111100_1010011", 32);
|
||||
val FADD_D = Bits("b?????_?????_?????_00000_???_01_1010011", 32);
|
||||
val FSUB_D = Bits("b?????_?????_?????_00001_???_01_1010011", 32);
|
||||
val FMUL_D = Bits("b?????_?????_?????_00010_???_01_1010011", 32);
|
||||
val FDIV_D = Bits("b?????_?????_?????_00011_???_01_1010011", 32);
|
||||
val FSQRT_D = Bits("b?????_?????_00000_00100_???_01_1010011", 32);
|
||||
val FSGNJ_D = Bits("b?????_?????_?????_0010111101_1010011", 32);
|
||||
val FSGNJN_D = Bits("b?????_?????_?????_0011011101_1010011", 32);
|
||||
val FSGNJX_D = Bits("b?????_?????_?????_0011111101_1010011", 32);
|
||||
val FCVT_L_S = Bits("b?????_?????_00000_01000_???_00_1010011", 32);
|
||||
val FCVT_LU_S = Bits("b?????_?????_00000_01001_???_00_1010011", 32);
|
||||
val FCVT_W_S = Bits("b?????_?????_00000_01010_???_00_1010011", 32);
|
||||
val FCVT_WU_S = Bits("b?????_?????_00000_01011_???_00_1010011", 32);
|
||||
val FCVT_L_D = Bits("b?????_?????_00000_01000_???_01_1010011", 32);
|
||||
val FCVT_LU_D = Bits("b?????_?????_00000_01001_???_01_1010011", 32);
|
||||
val FCVT_W_D = Bits("b?????_?????_00000_01010_???_01_1010011", 32);
|
||||
val FCVT_WU_D = Bits("b?????_?????_00000_01011_???_01_1010011", 32);
|
||||
val FCVT_S_L = Bits("b?????_?????_00000_01100_???_00_1010011", 32);
|
||||
val FCVT_S_LU = Bits("b?????_?????_00000_01101_???_00_1010011", 32);
|
||||
val FCVT_S_W = Bits("b?????_?????_00000_01110_???_00_1010011", 32);
|
||||
val FCVT_S_WU = Bits("b?????_?????_00000_01111_???_00_1010011", 32);
|
||||
val FCVT_D_L = Bits("b?????_?????_00000_01100_???_01_1010011", 32);
|
||||
val FCVT_D_LU = Bits("b?????_?????_00000_01101_???_01_1010011", 32);
|
||||
val FCVT_D_W = Bits("b?????_?????_00000_0111011101_1010011", 32);
|
||||
val FCVT_D_WU = Bits("b?????_?????_00000_0111111101_1010011", 32);
|
||||
val FCVT_S_D = Bits("b?????_?????_00000_10001_???_00_1010011", 32);
|
||||
val FCVT_D_S = Bits("b?????_?????_00000_10000_???_01_1010011", 32);
|
||||
val FEQ_S = Bits("b?????_?????_?????_1010111100_1010011", 32);
|
||||
val FLT_S = Bits("b?????_?????_?????_1011011100_1010011", 32);
|
||||
val FLE_S = Bits("b?????_?????_?????_1011111100_1010011", 32);
|
||||
val FEQ_D = Bits("b?????_?????_?????_1010111101_1010011", 32);
|
||||
val FLT_D = Bits("b?????_?????_?????_1011011101_1010011", 32);
|
||||
val FLE_D = Bits("b?????_?????_?????_1011111101_1010011", 32);
|
||||
val MFTX_S = Bits("b?????_00000_?????_1100011100_1010011", 32);
|
||||
val MFTX_D = Bits("b?????_00000_?????_1100011101_1010011", 32);
|
||||
val MFFSR = Bits("b?????_00000_00000_1101111100_1010011", 32);
|
||||
val MXTF_S = Bits("b?????_?????_00000_1110011100_1010011", 32);
|
||||
val MXTF_D = Bits("b?????_?????_00000_1110011101_1010011", 32);
|
||||
val MTFSR = Bits("b00000_?????_00000_1110111100_1010011", 32);
|
||||
val FLW = Bits("b?????_?????_????????????_010_0000111", 32);
|
||||
val FLD = Bits("b?????_?????_????????????_011_0000111", 32);
|
||||
val FSW = Bits("b?????_?????_?????_???????_010_0100111", 32);
|
||||
val FSD = Bits("b?????_?????_?????_???????_011_0100111", 32);
|
||||
val FMADD_S = Bits("b?????_?????_?????_?????_???_00_1000011", 32);
|
||||
val FMSUB_S = Bits("b?????_?????_?????_?????_???_00_1000111", 32);
|
||||
val FNMSUB_S = Bits("b?????_?????_?????_?????_???_00_1001011", 32);
|
||||
val FNMADD_S = Bits("b?????_?????_?????_?????_???_00_1001111", 32);
|
||||
val FMADD_D = Bits("b?????_?????_?????_?????_???_01_1000011", 32);
|
||||
val FMSUB_D = Bits("b?????_?????_?????_?????_???_01_1000111", 32);
|
||||
val FNMSUB_D = Bits("b?????_?????_?????_?????_???_01_1001011", 32);
|
||||
val FNMADD_D = Bits("b?????_?????_?????_?????_???_01_1001111", 32);
|
||||
val NOP = ADDI & Bits("b00000000000000000000001111111111", 32);
|
||||
val CFLUSH = Bits("b00000_00000_00000_0000000101_1111011", 32);
|
||||
}
|
||||
|
||||
}
|
124
rocket/src/main/scala/memory.scala
Normal file
124
rocket/src/main/scala/memory.scala
Normal file
@ -0,0 +1,124 @@
|
||||
package Top
|
||||
{
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
|
||||
import queues._;
|
||||
import Constants._;
|
||||
|
||||
class ioMemory extends Bundle()
|
||||
{
|
||||
val mem_mrq_val = Bool('input);
|
||||
val mem_mrq_cmd = Bits(4, 'input);
|
||||
val mem_mrq_type = Bits(3, 'input);
|
||||
val mem_xsdq_rdy = Bool('output);
|
||||
val mem_xsdq_val = Bool('input);
|
||||
val mem_mrq_deq = Bool('output);
|
||||
val dpath_rs2 = Bits(64, 'input);
|
||||
val dpath_waddr = UFix(5, 'input);
|
||||
val dpath_alu_out = UFix(64, 'input);
|
||||
val dmem_req_val = Bool('output);
|
||||
val dmem_req_rdy = Bool('input);
|
||||
val dmem_req_op = Bits(4, 'output);
|
||||
val dmem_req_addr = UFix(32, 'output);
|
||||
val dmem_req_data = Bits(64, 'output);
|
||||
val dmem_req_wmask = Bits(8, 'output);
|
||||
val dmem_req_tag = Bits(12, 'output);
|
||||
}
|
||||
|
||||
class rocketMemory extends Component
|
||||
{
|
||||
override val io = new ioMemory();
|
||||
val mrq_enq_xf
|
||||
= (io.mem_mrq_cmd === M_FRD || io.mem_mrq_cmd === M_FWR);
|
||||
|
||||
val mrq_enq_op
|
||||
= Mux(io.mem_mrq_cmd === M_FRD, M_XRD,
|
||||
Mux(io.mem_mrq_cmd === M_FWR, M_XWR,
|
||||
io.mem_mrq_cmd));
|
||||
|
||||
val mrq_enq_type = io.mem_mrq_type;
|
||||
|
||||
val mrq = new queueSimplePF(45, 4, 2);
|
||||
val xsdq = new queueSimplePF(64, 4, 2);
|
||||
|
||||
mrq.io.q_reset := Bool(false);
|
||||
mrq.io.enq_bits := Cat(mrq_enq_xf,mrq_enq_op,mrq_enq_type,io.dpath_waddr,io.dpath_alu_out(31,0));
|
||||
mrq.io.enq_val ^^ io.mem_mrq_val;
|
||||
// mrq.io.enq_rdy <> (); issue logic takes care of this
|
||||
|
||||
val mrq_deq_xf = Wire(){Bits(width = 1)};
|
||||
val mrq_deq_op = Wire(){Bits(width = 4)};
|
||||
val mrq_deq_type = Wire(){Bits(width = 3)};
|
||||
val mrq_deq_waddr = Wire(){Bits(width = 5)};
|
||||
val mrq_deq_addr = Wire(){Bits(width = 32)};
|
||||
val mrq_deq_bits = mrq.io.deq_bits;
|
||||
mrq_deq_bits.Match(Array(mrq_deq_xf, mrq_deq_op, mrq_deq_type, mrq_deq_waddr, mrq_deq_addr));
|
||||
val mrq_deq_val = mrq.io.deq_val;
|
||||
|
||||
xsdq.io.q_reset := Bool(false);
|
||||
xsdq.io.enq_bits ^^ io.dpath_rs2;
|
||||
xsdq.io.enq_val ^^ io.mem_xsdq_val;
|
||||
xsdq.io.enq_rdy ^^ io.mem_xsdq_rdy;
|
||||
|
||||
val mrq_deq_flush = mrq_deq_op === M_FLA;
|
||||
val mrq_deq_load = mrq_deq_op === M_XRD;
|
||||
val mrq_deq_xstore = mrq_deq_op === M_XWR & ~mrq_deq_xf & xsdq.io.deq_val;
|
||||
|
||||
val mrq_deq_rdy = io.dmem_req_rdy & (mrq_deq_load | mrq_deq_xstore | mrq_deq_flush);
|
||||
io.mem_mrq_deq := (mrq_deq_val & mrq_deq_rdy).toBool;
|
||||
mrq.io.deq_rdy := mrq_deq_rdy.toBool;
|
||||
val xsdq_deq_rdy = io.dmem_req_rdy & mrq_deq_val & mrq_deq_op === M_XWR & ~mrq_deq_xf;
|
||||
xsdq.io.deq_rdy := xsdq_deq_rdy.toBool;
|
||||
|
||||
val wdata = xsdq.io.deq_bits;
|
||||
|
||||
val wmask_b =
|
||||
Mux(mrq_deq_addr(2,0) === UFix(0, 3), Bits("b0000_0001", 8),
|
||||
Mux(mrq_deq_addr(2,0) === UFix(1, 3), Bits("b0000_0010", 8),
|
||||
Mux(mrq_deq_addr(2,0) === UFix(2, 3), Bits("b0000_0100", 8),
|
||||
Mux(mrq_deq_addr(2,0) === UFix(3, 3), Bits("b0000_1000", 8),
|
||||
Mux(mrq_deq_addr(2,0) === UFix(4, 3), Bits("b0001_0000", 8),
|
||||
Mux(mrq_deq_addr(2,0) === UFix(5, 3), Bits("b0010_0000", 8),
|
||||
Mux(mrq_deq_addr(2,0) === UFix(6, 3), Bits("b0100_0000", 8),
|
||||
Mux(mrq_deq_addr(2,0) === UFix(7, 3), Bits("b1000_0000", 8),
|
||||
UFix(0, 8)))))))));
|
||||
|
||||
val wmask_h =
|
||||
Mux(mrq_deq_addr(2,1) === UFix(0, 2), Bits("b0000_0011", 8),
|
||||
Mux(mrq_deq_addr(2,1) === UFix(1, 2), Bits("b0000_1100", 8),
|
||||
Mux(mrq_deq_addr(2,1) === UFix(2, 2), Bits("b0011_0000", 8),
|
||||
Mux(mrq_deq_addr(2,1) === UFix(3, 2), Bits("b1100_0000", 8),
|
||||
UFix(0, 8)))));
|
||||
|
||||
val wmask_w =
|
||||
Mux(mrq_deq_addr(2) === UFix(0, 1), Bits("b0000_1111", 8),
|
||||
Mux(mrq_deq_addr(2) === UFix(1, 1), Bits("b1111_0000", 8),
|
||||
UFix(0, 8)));
|
||||
|
||||
val wmask_d =
|
||||
Bits("b1111_1111", 8);
|
||||
|
||||
io.dmem_req_val := (mrq_deq_val & (mrq_deq_load | mrq_deq_xstore | mrq_deq_flush)).toBool;
|
||||
io.dmem_req_op := mrq_deq_op;
|
||||
io.dmem_req_addr := Cat(mrq_deq_addr(31,3), UFix(0, 3)).toUFix;
|
||||
|
||||
io.dmem_req_data :=
|
||||
Mux(mrq_deq_type === MT_B, Fill(8, wdata( 7,0)),
|
||||
Mux(mrq_deq_type === MT_H, Fill(4, wdata(15,0)),
|
||||
Mux(mrq_deq_type === MT_W, Fill(2, wdata(31,0)),
|
||||
Mux(mrq_deq_type === MT_D, wdata,
|
||||
UFix(0, 64)))));
|
||||
|
||||
io.dmem_req_wmask :=
|
||||
Mux(mrq_deq_type === MT_B, wmask_b,
|
||||
Mux(mrq_deq_type === MT_H, wmask_h,
|
||||
Mux(mrq_deq_type === MT_W, wmask_w,
|
||||
Mux(mrq_deq_type === MT_D, wmask_d,
|
||||
UFix(0, 8)))));
|
||||
|
||||
io.dmem_req_tag := Cat(mrq_deq_xf,mrq_deq_type,mrq_deq_addr(2,0),mrq_deq_waddr);
|
||||
}
|
||||
|
||||
}
|
61
rocket/src/main/scala/multiplier.scala
Normal file
61
rocket/src/main/scala/multiplier.scala
Normal file
@ -0,0 +1,61 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
|
||||
class ioMultiplier(width: Int) extends Bundle {
|
||||
// requests
|
||||
val mul_val = Bool('input);
|
||||
val mul_fn = UFix(3, 'input);
|
||||
val mul_tag = UFix(5, 'input);
|
||||
val in0 = Bits(width, 'input);
|
||||
val in1 = Bits(width, 'input);
|
||||
|
||||
// responses
|
||||
val result = Bits(width, 'output);
|
||||
val result_tag = UFix(5, 'output);
|
||||
val result_val = Bool('output);
|
||||
}
|
||||
|
||||
class rocketMultiplier extends Component {
|
||||
val io = new ioMultiplier(64);
|
||||
|
||||
val r_val = Reg(resetVal = Bool(false));
|
||||
val r_fn = Reg(resetVal = UFix(0,3));
|
||||
val r_tag = Reg(resetVal = UFix(0,5));
|
||||
val r_in0 = Reg(resetVal = Bits(0,64));
|
||||
val r_in1 = Reg(resetVal = Bits(0,64));
|
||||
|
||||
r_val <== io.mul_val;
|
||||
when (io.mul_val) {
|
||||
r_fn <== io.mul_fn;
|
||||
r_tag <== io.mul_tag;
|
||||
r_in0 <== io.in0;
|
||||
r_in1 <== io.in1;
|
||||
}
|
||||
|
||||
val sxl64 = (r_fn === MUL_64H) || (r_fn === MUL_64HSU);
|
||||
val sxr64 = (r_fn === MUL_64H);
|
||||
|
||||
val lhs = Cat(r_in0(63) & sxl64, r_in0);
|
||||
val rhs = Cat(r_in1(63) & sxr64, r_in1);
|
||||
|
||||
val mul_result = lhs.toFix * rhs.toFix;
|
||||
|
||||
val mul_output = MuxCase(mul_result(63,0), Array(
|
||||
((r_fn === MUL_64H) || (r_fn === MUL_64HU) || (r_fn === MUL_64HSU)) -> mul_result(127,64),
|
||||
(r_fn === MUL_32) -> Cat(Fill(32, mul_result(31)), mul_result(31, 0))));
|
||||
|
||||
// just a hack for now, this should be a parameterized number of stages
|
||||
val r_result = Reg(Reg(Reg(mul_output)));
|
||||
val r_result_tag = Reg(Reg(Reg(r_tag)));
|
||||
val r_result_val = Reg(Reg(Reg(r_val)));
|
||||
|
||||
io.result := r_result;
|
||||
io.result_tag := r_result_tag;
|
||||
io.result_val := r_result_val;
|
||||
|
||||
}
|
||||
|
||||
}
|
225
rocket/src/main/scala/queues.scala
Normal file
225
rocket/src/main/scala/queues.scala
Normal file
@ -0,0 +1,225 @@
|
||||
package queues
|
||||
{
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
|
||||
class ioQueueCtrl(addr_sz: Int) extends Bundle()
|
||||
{
|
||||
val q_reset = Bool('input);
|
||||
val enq_val = Bool('input);
|
||||
val enq_rdy = Bool('output);
|
||||
val deq_val = Bool('output);
|
||||
val deq_rdy = Bool('input);
|
||||
val wen = Bool('output);
|
||||
val waddr = UFix(addr_sz, 'output);
|
||||
val raddr = UFix(addr_sz, 'output);
|
||||
}
|
||||
|
||||
class queueCtrl(entries: Int, addr_sz: Int) extends Component
|
||||
{
|
||||
override val io = new ioQueueCtrl(addr_sz);
|
||||
|
||||
// Enqueue and dequeue pointers
|
||||
|
||||
val enq_ptr = Reg(width = addr_sz, resetVal = UFix(0, addr_sz));
|
||||
val deq_ptr = Reg(width = addr_sz, resetVal = UFix(0, addr_sz));
|
||||
val full = Reg(width = 1, resetVal = Bool(false));
|
||||
|
||||
when (io.q_reset) {
|
||||
enq_ptr <== UFix(0, addr_sz);
|
||||
deq_ptr <== UFix(0, addr_sz);
|
||||
full <== Bool(false);
|
||||
}
|
||||
|
||||
io.waddr := enq_ptr;
|
||||
io.raddr := deq_ptr;
|
||||
|
||||
// We enq/deq only when they are both ready and valid
|
||||
|
||||
val do_enq = io.enq_rdy && io.enq_val;
|
||||
val do_deq = io.deq_rdy && io.deq_val;
|
||||
|
||||
// Determine if we have pipeline or flowthrough behaviour and
|
||||
// set the write enable accordingly.
|
||||
|
||||
val empty = ~full && (enq_ptr === deq_ptr);
|
||||
|
||||
io.wen := do_enq;
|
||||
|
||||
// Ready signals are calculated from full register. If pipeline
|
||||
// behavior is enabled, then the enq_rdy signal is also calculated
|
||||
// combinationally from the deq_rdy signal. If flowthrough behavior
|
||||
// is enabled then the deq_val signal is also calculated combinationally
|
||||
// from the enq_val signal.
|
||||
|
||||
io.enq_rdy := ~full;
|
||||
io.deq_val := ~empty;
|
||||
|
||||
// Control logic for the enq/deq pointers and full register
|
||||
|
||||
val deq_ptr_inc = deq_ptr + UFix(1, 1);
|
||||
val enq_ptr_inc = enq_ptr + UFix(1, 1);
|
||||
|
||||
val deq_ptr_next =
|
||||
Mux(do_deq, deq_ptr_inc,
|
||||
deq_ptr);
|
||||
|
||||
val enq_ptr_next =
|
||||
Mux(do_enq, enq_ptr_inc,
|
||||
enq_ptr);
|
||||
|
||||
val full_next =
|
||||
Mux(do_enq && ~do_deq && ( enq_ptr_inc === deq_ptr ), Bool(true),
|
||||
Mux(do_deq && full, Bool(false),
|
||||
full));
|
||||
|
||||
enq_ptr <== enq_ptr_next;
|
||||
deq_ptr <== deq_ptr_next;
|
||||
full <== full_next;
|
||||
}
|
||||
|
||||
class ioQueueSimplePF(data_sz: Int) extends Bundle()
|
||||
{
|
||||
val q_reset = Bool('input);
|
||||
val enq_val = Bool('input);
|
||||
val enq_rdy = Bool('output);
|
||||
val deq_val = Bool('output);
|
||||
val deq_rdy = Bool('input);
|
||||
val enq_bits = Bits(data_sz, 'input);
|
||||
val deq_bits = Bits(data_sz, 'output);
|
||||
}
|
||||
|
||||
class queueSimplePF(data_sz: Int, entries: Int, addr_sz: Int) extends Component
|
||||
{
|
||||
override val io = new ioQueueSimplePF(data_sz);
|
||||
val ctrl = new queueCtrl(entries, addr_sz);
|
||||
ctrl.io.q_reset ^^ io.q_reset;
|
||||
ctrl.io.deq_val ^^ io.deq_val;
|
||||
ctrl.io.enq_rdy ^^ io.enq_rdy;
|
||||
ctrl.io.enq_val ^^ io.enq_val;
|
||||
ctrl.io.deq_rdy ^^ io.deq_rdy;
|
||||
val ram = Mem(entries, ctrl.io.wen, ctrl.io.waddr, io.enq_bits);
|
||||
io.deq_bits := ram(ctrl.io.raddr);
|
||||
}
|
||||
|
||||
// TODO: SHOULD USE INHERITANCE BUT BREAKS INTROSPECTION CODE
|
||||
// class IOqueueCtrlFlow extends IOqueueCtrl
|
||||
class ioQueueCtrlFlow(addr_sz: Int) extends Bundle() /* IOqueueCtrl */
|
||||
{
|
||||
val enq_val = Bool('input);
|
||||
val enq_rdy = Bool('output);
|
||||
val deq_val = Bool('output);
|
||||
val deq_rdy = Bool('input);
|
||||
val wen = Bool('output);
|
||||
val waddr = UFix(addr_sz, 'output);
|
||||
val raddr = UFix(addr_sz, 'output);
|
||||
val flowthru = Bool('output);
|
||||
}
|
||||
|
||||
class queueCtrlFlow(entries: Int, addr_sz: Int) extends Component
|
||||
{
|
||||
override val io = new ioQueueCtrlFlow(addr_sz);
|
||||
// Enqueue and dequeue pointers
|
||||
|
||||
val enq_ptr = Reg(width = addr_sz, resetVal = UFix(0, addr_sz));
|
||||
val deq_ptr = Reg(width = addr_sz, resetVal = UFix(0, addr_sz));
|
||||
val full = Reg(width = 1, resetVal = Bool(false));
|
||||
|
||||
io.waddr := enq_ptr;
|
||||
io.raddr := deq_ptr;
|
||||
|
||||
// We enq/deq only when they are both ready and valid
|
||||
|
||||
val do_enq = io.enq_rdy && io.enq_val;
|
||||
val do_deq = io.deq_rdy && io.deq_val;
|
||||
|
||||
// Determine if we have pipeline or flowthrough behaviour and
|
||||
// set the write enable accordingly.
|
||||
|
||||
val empty = ~full && (enq_ptr === deq_ptr);
|
||||
val do_flowthru = empty && do_enq && do_deq;
|
||||
io.flowthru := do_flowthru;
|
||||
|
||||
io.wen := do_enq && ~do_flowthru;
|
||||
|
||||
// Ready signals are calculated from full register. If pipeline
|
||||
// behavior is enabled, then the enq_rdy signal is also calculated
|
||||
// combinationally from the deq_rdy signal. If flowthrough behavior
|
||||
// is enabled then the deq_val signal is also calculated combinationally
|
||||
// from the enq_val signal.
|
||||
|
||||
io.enq_rdy := ~full;
|
||||
io.deq_val := ~empty || ( empty && io.enq_val );
|
||||
|
||||
// Control logic for the enq/deq pointers and full register
|
||||
|
||||
val deq_ptr_inc = deq_ptr + UFix(1, 1);
|
||||
val enq_ptr_inc = enq_ptr + UFix(1, 1);
|
||||
|
||||
val deq_ptr_next =
|
||||
Mux(do_deq && ~do_flowthru, deq_ptr_inc,
|
||||
deq_ptr);
|
||||
|
||||
val enq_ptr_next =
|
||||
Mux(do_enq && ~do_flowthru, enq_ptr_inc,
|
||||
enq_ptr);
|
||||
|
||||
val full_next =
|
||||
Mux(do_enq && ~do_deq && ( enq_ptr_inc === deq_ptr ), Bool(true),
|
||||
Mux(do_deq && full, Bool(false),
|
||||
full));
|
||||
|
||||
enq_ptr <== enq_ptr_next;
|
||||
deq_ptr <== deq_ptr_next;
|
||||
full <== full_next;
|
||||
}
|
||||
|
||||
class ioQueueDpathFlow(data_sz: Int, addr_sz: Int) extends Bundle()
|
||||
{
|
||||
val wen = Bool('input);
|
||||
val flowthru = Bool('input);
|
||||
val deq_bits = Bits(data_sz, 'output);
|
||||
val enq_bits = Bits(data_sz, 'input);
|
||||
val waddr = UFix(addr_sz, 'input);
|
||||
val raddr = UFix(addr_sz, 'input);
|
||||
}
|
||||
|
||||
class queueDpathFlow(data_sz: Int, entries: Int, addr_sz: Int) extends Component
|
||||
{
|
||||
override val io = new ioQueueDpathFlow(data_sz, addr_sz);
|
||||
val ram = Mem(entries, io.wen, io.waddr, io.enq_bits);
|
||||
val rout = ram(io.raddr);
|
||||
io.deq_bits := Mux(io.flowthru, io.enq_bits, rout);
|
||||
}
|
||||
|
||||
class ioQueueFlowPF(data_sz: Int) extends Bundle()
|
||||
{
|
||||
val enq_val = Bool('input);
|
||||
val enq_rdy = Bool('output);
|
||||
val enq_bits = Bits(data_sz, 'input);
|
||||
val deq_val = Bool('output);
|
||||
val deq_rdy = Bool('input);
|
||||
val deq_bits = Bits(data_sz, 'output);
|
||||
}
|
||||
|
||||
class queueFlowPF(data_sz: Int, entries: Int, addr_sz: Int) extends Component
|
||||
{
|
||||
override val io = new ioQueueFlowPF(data_sz);
|
||||
val ctrl = new queueCtrlFlow(entries, addr_sz);
|
||||
val dpath = new queueDpathFlow(data_sz, entries, addr_sz);
|
||||
|
||||
ctrl.io.deq_rdy ^^ io.deq_rdy;
|
||||
ctrl.io.wen <> dpath.io.wen;
|
||||
ctrl.io.raddr <> dpath.io.raddr;
|
||||
ctrl.io.waddr <> dpath.io.waddr;
|
||||
ctrl.io.flowthru <> dpath.io.flowthru;
|
||||
ctrl.io.enq_val ^^ io.enq_val;
|
||||
dpath.io.enq_bits ^^ io.enq_bits;
|
||||
|
||||
ctrl.io.deq_val ^^ io.deq_val;
|
||||
ctrl.io.enq_rdy ^^ io.enq_rdy;
|
||||
dpath.io.deq_bits ^^ io.deq_bits;
|
||||
}
|
||||
|
||||
}
|
54
rocket/src/main/scala/top.scala
Normal file
54
rocket/src/main/scala/top.scala
Normal file
@ -0,0 +1,54 @@
|
||||
package Top {
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
|
||||
class ioTop extends Bundle {
|
||||
val debug = new ioDebug();
|
||||
val console = new ioConsole();
|
||||
val host = new ioHost();
|
||||
val mem = new ioMem();
|
||||
}
|
||||
|
||||
class Top() extends Component {
|
||||
val io = new ioTop();
|
||||
|
||||
val cpu = new rocketProc();
|
||||
val icache = new rocketICacheDM(128, 32); // lines, address bits
|
||||
val icache_pf = new rocketIPrefetcher();
|
||||
val dcache = new rocketDCacheDM_flush(128, 32);
|
||||
val arbiter = new rocketMemArbiter();
|
||||
|
||||
arbiter.io.mem ^^ io.mem;
|
||||
arbiter.io.dcache <> dcache.io.mem;
|
||||
arbiter.io.icache <> icache_pf.io.mem;
|
||||
|
||||
cpu.io.host ^^ io.host;
|
||||
cpu.io.debug ^^ io.debug;
|
||||
cpu.io.console ^^ io.console;
|
||||
|
||||
icache.io.mem <> icache_pf.io.icache;
|
||||
cpu.io.imem <> icache.io.cpu;
|
||||
cpu.io.dmem <> dcache.io.cpu;
|
||||
|
||||
}
|
||||
|
||||
object top_main {
|
||||
def main(args: Array[String]) = {
|
||||
// Can turn off --debug and --vcd when done with debugging to improve emulator performance
|
||||
// val cpu_args = args ++ Array("--target-dir", "generated-src","--debug","--vcd");
|
||||
val cpu_args = args ++ Array("--target-dir", "generated-src","--debug");
|
||||
// Set variables based off of command flags
|
||||
// for(a <- args) {
|
||||
// a match {
|
||||
// case "-bp" => isBranchPrediction = true;
|
||||
// case any =>
|
||||
// }
|
||||
// }
|
||||
|
||||
chiselMain(cpu_args, () => new Top());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
56
rocket/src/main/scala/writeback.scala
Normal file
56
rocket/src/main/scala/writeback.scala
Normal file
@ -0,0 +1,56 @@
|
||||
package Top
|
||||
{
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
|
||||
class ioWriteback extends Bundle()
|
||||
{
|
||||
val dmem_resp_val = Bool('input);
|
||||
val dmem_resp_data = UFix(64, 'input);
|
||||
val dmem_resp_tag = UFix(12, 'input);
|
||||
val wb_waddr = UFix(5, 'output);
|
||||
val wb_wen = Bool('output);
|
||||
val wb_wdata = Bits(64, 'output);
|
||||
}
|
||||
|
||||
class rocketWriteback extends Component
|
||||
{
|
||||
override val io = new ioWriteback();
|
||||
|
||||
val r_dmem_resp_val = Reg(io.dmem_resp_val);
|
||||
val r_dmem_resp_data = Reg(io.dmem_resp_data);
|
||||
val r_dmem_resp_tag = Reg(io.dmem_resp_tag);
|
||||
|
||||
val dmem_resp_xf = r_dmem_resp_tag(11);
|
||||
val dmem_resp_type = r_dmem_resp_tag(10, 8);
|
||||
val dmem_resp_pos = r_dmem_resp_tag(7, 5);
|
||||
val dmem_resp_waddr = r_dmem_resp_tag(4, 0);
|
||||
val dmem_resp_xval = r_dmem_resp_val & ~dmem_resp_xf;
|
||||
val dmem_resp_fval = r_dmem_resp_val & dmem_resp_xf;
|
||||
|
||||
val dmem_resp_data_w =
|
||||
Mux(dmem_resp_pos(2).toBool, r_dmem_resp_data(63, 32), r_dmem_resp_data(31, 0));
|
||||
val dmem_resp_data_h =
|
||||
Mux(dmem_resp_pos(1).toBool, dmem_resp_data_w(31, 16), dmem_resp_data_w(15, 0));
|
||||
val dmem_resp_data_b =
|
||||
Mux(dmem_resp_pos(0).toBool, dmem_resp_data_h(15, 8), dmem_resp_data_h(7, 0));
|
||||
|
||||
val dmem_resp_data_final =
|
||||
Mux(dmem_resp_type === MT_B, Cat(Fill(56, dmem_resp_data_b(7)), dmem_resp_data_b),
|
||||
Mux(dmem_resp_type === MT_BU, Cat(UFix(0, 56), dmem_resp_data_b),
|
||||
Mux(dmem_resp_type === MT_H, Cat(Fill(48, dmem_resp_data_h(15)), dmem_resp_data_h),
|
||||
Mux(dmem_resp_type === MT_HU, Cat(UFix(0, 48), dmem_resp_data_h),
|
||||
Mux(dmem_resp_type === MT_W, Cat(Fill(32, dmem_resp_data_w(31)), dmem_resp_data_w),
|
||||
Mux(dmem_resp_type === MT_WU, Cat(UFix(0, 32), dmem_resp_data_w),
|
||||
Mux(dmem_resp_type === MT_D, r_dmem_resp_data,
|
||||
UFix(0, 64))))))));
|
||||
|
||||
io.wb_wen := dmem_resp_xval.toBool;
|
||||
io.wb_waddr := dmem_resp_waddr;
|
||||
io.wb_wdata := dmem_resp_data_final;
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user