1
0
Fork 0

initial commit of rocket chisel project, riscv assembly tests and benchmarks

This commit is contained in:
Rimas Avizienis 2011-10-25 23:02:47 -07:00
commit c06e2d16e4
18 changed files with 2699 additions and 0 deletions

View 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);
}
}

View 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);
}
}

View 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;
}
}

View 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;
}
}

View 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);
}
}

View 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;
}
}
}
}

View 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);
}
}

View 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;
}
}

View 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)
));
}
*/
}

View 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));
}
}

View 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;
}
}
}
}

View 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; }
}
}
}
}

View 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);
}
}

View 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);
}
}

View 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;
}
}

View 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;
}
}

View 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());
}
}
}

View 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;
}
}