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