From c06e2d16e4791bdd4bb36e661d36bec21c627c89 Mon Sep 17 00:00:00 2001 From: Rimas Avizienis Date: Tue, 25 Oct 2011 23:02:47 -0700 Subject: [PATCH] initial commit of rocket chisel project, riscv assembly tests and benchmarks --- rocket/src/main/scala/arbiter.scala | 74 ++++ rocket/src/main/scala/consts.scala | 153 ++++++++ rocket/src/main/scala/cpu.scala | 95 +++++ rocket/src/main/scala/ctrl.scala | 405 ++++++++++++++++++++ rocket/src/main/scala/ctrl_util.scala | 62 +++ rocket/src/main/scala/dcache.scala | 251 ++++++++++++ rocket/src/main/scala/divider.scala | 147 +++++++ rocket/src/main/scala/dpath.scala | 345 +++++++++++++++++ rocket/src/main/scala/dpath_alu.scala | 90 +++++ rocket/src/main/scala/dpath_util.scala | 184 +++++++++ rocket/src/main/scala/icache.scala | 120 ++++++ rocket/src/main/scala/icache_prefetch.scala | 91 +++++ rocket/src/main/scala/instructions.scala | 162 ++++++++ rocket/src/main/scala/memory.scala | 124 ++++++ rocket/src/main/scala/multiplier.scala | 61 +++ rocket/src/main/scala/queues.scala | 225 +++++++++++ rocket/src/main/scala/top.scala | 54 +++ rocket/src/main/scala/writeback.scala | 56 +++ 18 files changed, 2699 insertions(+) create mode 100644 rocket/src/main/scala/arbiter.scala create mode 100644 rocket/src/main/scala/consts.scala create mode 100644 rocket/src/main/scala/cpu.scala create mode 100644 rocket/src/main/scala/ctrl.scala create mode 100644 rocket/src/main/scala/ctrl_util.scala create mode 100644 rocket/src/main/scala/dcache.scala create mode 100644 rocket/src/main/scala/divider.scala create mode 100644 rocket/src/main/scala/dpath.scala create mode 100644 rocket/src/main/scala/dpath_alu.scala create mode 100644 rocket/src/main/scala/dpath_util.scala create mode 100644 rocket/src/main/scala/icache.scala create mode 100644 rocket/src/main/scala/icache_prefetch.scala create mode 100644 rocket/src/main/scala/instructions.scala create mode 100644 rocket/src/main/scala/memory.scala create mode 100644 rocket/src/main/scala/multiplier.scala create mode 100644 rocket/src/main/scala/queues.scala create mode 100644 rocket/src/main/scala/top.scala create mode 100644 rocket/src/main/scala/writeback.scala diff --git a/rocket/src/main/scala/arbiter.scala b/rocket/src/main/scala/arbiter.scala new file mode 100644 index 00000000..eaf0241d --- /dev/null +++ b/rocket/src/main/scala/arbiter.scala @@ -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); + +} + +} diff --git a/rocket/src/main/scala/consts.scala b/rocket/src/main/scala/consts.scala new file mode 100644 index 00000000..e5660ca6 --- /dev/null +++ b/rocket/src/main/scala/consts.scala @@ -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); +} + +} diff --git a/rocket/src/main/scala/cpu.scala b/rocket/src/main/scala/cpu.scala new file mode 100644 index 00000000..a891582e --- /dev/null +++ b/rocket/src/main/scala/cpu.scala @@ -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; +} + +} diff --git a/rocket/src/main/scala/ctrl.scala b/rocket/src/main/scala/ctrl.scala new file mode 100644 index 00000000..90899de1 --- /dev/null +++ b/rocket/src/main/scala/ctrl.scala @@ -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; +} + +} diff --git a/rocket/src/main/scala/ctrl_util.scala b/rocket/src/main/scala/ctrl_util.scala new file mode 100644 index 00000000..73661fa6 --- /dev/null +++ b/rocket/src/main/scala/ctrl_util.scala @@ -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); +} + +} diff --git a/rocket/src/main/scala/dcache.scala b/rocket/src/main/scala/dcache.scala new file mode 100644 index 00000000..e0cdc8cd --- /dev/null +++ b/rocket/src/main/scala/dcache.scala @@ -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; + } + } +} + +} diff --git a/rocket/src/main/scala/divider.scala b/rocket/src/main/scala/divider.scala new file mode 100644 index 00000000..6e383a3e --- /dev/null +++ b/rocket/src/main/scala/divider.scala @@ -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); +} + +} diff --git a/rocket/src/main/scala/dpath.scala b/rocket/src/main/scala/dpath.scala new file mode 100644 index 00000000..6c7e5287 --- /dev/null +++ b/rocket/src/main/scala/dpath.scala @@ -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; + +} + +} diff --git a/rocket/src/main/scala/dpath_alu.scala b/rocket/src/main/scala/dpath_alu.scala new file mode 100644 index 00000000..d7ae1e90 --- /dev/null +++ b/rocket/src/main/scala/dpath_alu.scala @@ -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) + )); +} +*/ + +} diff --git a/rocket/src/main/scala/dpath_util.scala b/rocket/src/main/scala/dpath_util.scala new file mode 100644 index 00000000..4c53db11 --- /dev/null +++ b/rocket/src/main/scala/dpath_util.scala @@ -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)); +} + +} diff --git a/rocket/src/main/scala/icache.scala b/rocket/src/main/scala/icache.scala new file mode 100644 index 00000000..7bf4ad3f --- /dev/null +++ b/rocket/src/main/scala/icache.scala @@ -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; + } + } +} + +} diff --git a/rocket/src/main/scala/icache_prefetch.scala b/rocket/src/main/scala/icache_prefetch.scala new file mode 100644 index 00000000..1c1219e3 --- /dev/null +++ b/rocket/src/main/scala/icache_prefetch.scala @@ -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; } + } + } +} + +} \ No newline at end of file diff --git a/rocket/src/main/scala/instructions.scala b/rocket/src/main/scala/instructions.scala new file mode 100644 index 00000000..13d822b1 --- /dev/null +++ b/rocket/src/main/scala/instructions.scala @@ -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); +} + +} diff --git a/rocket/src/main/scala/memory.scala b/rocket/src/main/scala/memory.scala new file mode 100644 index 00000000..3d0b5869 --- /dev/null +++ b/rocket/src/main/scala/memory.scala @@ -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); +} + +} diff --git a/rocket/src/main/scala/multiplier.scala b/rocket/src/main/scala/multiplier.scala new file mode 100644 index 00000000..67a53ac3 --- /dev/null +++ b/rocket/src/main/scala/multiplier.scala @@ -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; + +} + +} diff --git a/rocket/src/main/scala/queues.scala b/rocket/src/main/scala/queues.scala new file mode 100644 index 00000000..b2f7aa16 --- /dev/null +++ b/rocket/src/main/scala/queues.scala @@ -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; +} + +} diff --git a/rocket/src/main/scala/top.scala b/rocket/src/main/scala/top.scala new file mode 100644 index 00000000..bb035340 --- /dev/null +++ b/rocket/src/main/scala/top.scala @@ -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()); + } +} + +} diff --git a/rocket/src/main/scala/writeback.scala b/rocket/src/main/scala/writeback.scala new file mode 100644 index 00000000..327358c6 --- /dev/null +++ b/rocket/src/main/scala/writeback.scala @@ -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; + +} + +}