interface cleanup, major pipeline changes
This commit is contained in:
parent
ace4c9d13c
commit
08b89e7710
@ -21,6 +21,7 @@ object Constants
|
||||
val PC_J = UFix(4, 3);
|
||||
val PC_JR = UFix(5, 3);
|
||||
val PC_PCR = UFix(6, 3);
|
||||
val PC_MEM = UFix(7, 3);
|
||||
|
||||
val KF_Y = UFix(1, 1);
|
||||
val KF_N = UFix(0, 1);
|
||||
|
@ -39,57 +39,64 @@ class rocketProc extends Component
|
||||
val io = new ioRocket();
|
||||
|
||||
val ctrl = new rocketCtrl();
|
||||
val dpath = new rocketDpath();
|
||||
val mem = new rocketMemory();
|
||||
val wb = new rocketWriteback();
|
||||
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.dpath <> dpath.io.ctrl;
|
||||
ctrl.io.host.start ^^ io.host.start;
|
||||
ctrl.io.imem ^^ io.imem;
|
||||
dpath.io.imem.req_addr ^^ io.imem.req_addr;
|
||||
dpath.io.imem.resp_data ^^ io.imem.resp_data;
|
||||
dpath.io.host ^^ io.host;
|
||||
dpath.io.debug ^^ io.debug;
|
||||
|
||||
ctrl.io.dmem ^^ io.dmem;
|
||||
dpath.io.dmem ^^ io.dmem;
|
||||
|
||||
// FIXME
|
||||
// io.console.bits := dpath.io.dpath.rs1(7,0);
|
||||
io.console.bits := Bits(0,8);
|
||||
io.console.valid := ctrl.io.console.valid;
|
||||
ctrl.io.console.rdy := io.console.rdy;
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
// 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.console ^^ io.console;
|
||||
ctrl.io.wb.waddr <> wb.io.wb_waddr;
|
||||
ctrl.io.wb.wen <> wb.io.wb_wen;
|
||||
// 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.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;
|
||||
//
|
||||
// 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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,14 +6,17 @@ import Node._;
|
||||
import Constants._
|
||||
import Instructions._
|
||||
|
||||
class ioCtrl extends Bundle()
|
||||
class ioCtrlDpath extends Bundle()
|
||||
{
|
||||
// outputs to datapath
|
||||
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 killx = Bool('output);
|
||||
val killm = Bool('output);
|
||||
val ren2 = Bool('output);
|
||||
val ren1 = Bool('output);
|
||||
val sel_alu2 = UFix(2, 'output);
|
||||
@ -26,7 +29,6 @@ class ioCtrl extends Bundle()
|
||||
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);
|
||||
@ -36,56 +38,34 @@ class ioCtrl extends Bundle()
|
||||
val xcpt_fpu = Bool('output);
|
||||
val xcpt_syscall = Bool('output);
|
||||
val eret = Bool('output);
|
||||
}
|
||||
|
||||
class ioCtrlDpath extends Bundle()
|
||||
{
|
||||
val dcache_miss = Bool('output);
|
||||
val wen = Bool('output);
|
||||
// inputs from datapath
|
||||
val btb_hit = Bool('input);
|
||||
val inst = UFix(32, 'input);
|
||||
val inst = Bits(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 ex_waddr = UFix(5,'input); // write addr from execute stage
|
||||
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);
|
||||
val sboard_set = Bool('input);
|
||||
val sboard_seta = UFix(5, 'input);
|
||||
val sboard_clr0 = Bool('input);
|
||||
val sboard_clr0a = UFix(5, 'input);
|
||||
val sboard_clr1 = Bool('input);
|
||||
val sboard_clr1a = UFix(5, '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 console = new ioConsole(List("rdy", "valid"));
|
||||
val imem = new ioImem(List("req_val", "req_rdy", "resp_val")).flip();
|
||||
val dmem = new ioDmem(List("req_val", "req_rdy", "req_cmd", "req_type", "resp_val")).flip();
|
||||
val host = new ioHost(List("start"));
|
||||
}
|
||||
|
||||
@ -219,47 +199,27 @@ class rocketCtrl extends Component
|
||||
val id_ren2 = id_renx2;
|
||||
val id_ren1 = id_renx1;
|
||||
|
||||
val id_console_out_val = id_wen_pcr & (id_raddr2 === PCR_CONSOLE);
|
||||
val id_console_out_val = id_wen_pcr & (id_raddr2 === PCR_CONSOLE);
|
||||
val console_out_fire = id_console_out_val & ~io.dpath.killd;
|
||||
io.console.valid := console_out_fire.toBool;
|
||||
|
||||
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;
|
||||
sboard.io.raddra := id_raddr2.toUFix;
|
||||
sboard.io.raddrb := id_raddr1.toUFix;
|
||||
sboard.io.raddrc := id_waddr.toUFix;
|
||||
|
||||
sboard.io.set := io.dpath.sboard_set;
|
||||
sboard.io.seta := io.dpath.sboard_seta;
|
||||
sboard.io.clr0 := io.dpath.sboard_clr0;
|
||||
sboard.io.clr0a := io.dpath.sboard_clr0a;
|
||||
sboard.io.clr1 := io.dpath.sboard_clr1;
|
||||
sboard.io.clr1a := io.dpath.sboard_clr1a;
|
||||
|
||||
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()};
|
||||
@ -269,15 +229,16 @@ class rocketCtrl extends Component
|
||||
val ex_reg_eret = Reg(resetVal = Bool(false));
|
||||
val ex_reg_privileged = Reg(resetVal = Bool(false));
|
||||
|
||||
when (!io.ctrl.stalld) {
|
||||
when (io.ctrl.killf) {
|
||||
when (!io.dpath.stalld) {
|
||||
when (io.dpath.killf) {
|
||||
id_reg_btb_hit <== Bool(false);
|
||||
}
|
||||
otherwise{
|
||||
id_reg_btb_hit <== io.dpath.btb_hit;
|
||||
}
|
||||
}
|
||||
when (reset.toBool || io.ctrl.killd) {
|
||||
|
||||
when (reset.toBool || io.dpath.killd) {
|
||||
ex_reg_br_type <== BR_N;
|
||||
ex_reg_btb_hit <== Bool(false);
|
||||
ex_reg_mem_val <== Bool(false);
|
||||
@ -289,7 +250,7 @@ class rocketCtrl extends Component
|
||||
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_val <== id_mem_val.toBool;
|
||||
ex_reg_mem_cmd <== id_mem_cmd;
|
||||
ex_reg_mem_type <== id_mem_type;
|
||||
ex_reg_eret <== id_eret.toBool;
|
||||
@ -317,22 +278,42 @@ class rocketCtrl extends Component
|
||||
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.dmem.req_val := ex_reg_mem_val && ~io.dpath.killx;
|
||||
io.dmem.req_cmd := ex_reg_mem_cmd;
|
||||
io.dmem.req_type := ex_reg_mem_type;
|
||||
|
||||
io.ctrl.sel_pc :=
|
||||
val mem_reg_mem_val = Reg(){Bool()};
|
||||
val mem_reg_mem_cmd = Reg(){UFix(width = 4)};
|
||||
val mem_reg_mem_type = Reg(){UFix(width = 3)};
|
||||
|
||||
when (reset.toBool || io.dpath.killx) {
|
||||
mem_reg_mem_val <== Bool(false);
|
||||
mem_reg_mem_cmd <== UFix(0, 4);
|
||||
mem_reg_mem_type <== UFix(0, 3);
|
||||
}
|
||||
otherwise {
|
||||
mem_reg_mem_val <== ex_reg_mem_val;
|
||||
mem_reg_mem_cmd <== ex_reg_mem_cmd;
|
||||
mem_reg_mem_type <== ex_reg_mem_type;
|
||||
}
|
||||
|
||||
// replay on a D$ load miss : FIXME - add a miss signal to D$
|
||||
val replay_mem = mem_reg_mem_val && (mem_reg_mem_cmd === M_XRD) && !io.dmem.resp_val;
|
||||
val dcache_miss = Reg(replay_mem);
|
||||
|
||||
io.dpath.dcache_miss := dcache_miss;
|
||||
|
||||
io.dpath.sel_pc :=
|
||||
Mux(replay_mem, PC_MEM,
|
||||
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))))));
|
||||
PC_4)))))));
|
||||
|
||||
io.ctrl.wen_btb := ~ex_reg_btb_hit & br_taken;
|
||||
io.dpath.wen_btb := ~ex_reg_btb_hit & br_taken;
|
||||
|
||||
val take_pc =
|
||||
~ex_reg_btb_hit & br_taken |
|
||||
@ -341,65 +322,86 @@ class rocketCtrl extends Component
|
||||
j_taken |
|
||||
io.dpath.exception |
|
||||
ex_reg_privileged |
|
||||
ex_reg_eret;
|
||||
ex_reg_eret |
|
||||
replay_mem;
|
||||
|
||||
io.ctrl.stallf :=
|
||||
io.dpath.stallf :=
|
||||
~take_pc &
|
||||
(
|
||||
~io.imem.req_rdy |
|
||||
~io.imem.resp_val |
|
||||
io.ctrl.stalld
|
||||
io.dpath.stalld
|
||||
);
|
||||
|
||||
val ctrl_stalld_wo_fpu_rdy =
|
||||
// check for loads in execute stage to detect load/use hazards
|
||||
val lu_stall_raddr1 =
|
||||
ex_reg_mem_val &&
|
||||
(ex_reg_mem_cmd === M_XRD) &&
|
||||
id_ren1.toBool &&
|
||||
(id_raddr1 === io.dpath.ex_waddr);
|
||||
|
||||
val lu_stall_raddr2 =
|
||||
ex_reg_mem_val &&
|
||||
(ex_reg_mem_cmd === M_XRD) &&
|
||||
id_ren2.toBool &&
|
||||
(id_raddr2 === io.dpath.ex_waddr);
|
||||
|
||||
val ctrl_stalld =
|
||||
~take_pc &
|
||||
(
|
||||
id_ren2 & id_stall_raddr2 |
|
||||
id_ren1 & id_stall_raddr1 |
|
||||
(id_sel_wa === WA_RD) & id_stall_waddr |
|
||||
lu_stall_raddr1 |
|
||||
lu_stall_raddr2 |
|
||||
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_mem_val & ~io.dmem.req_rdy |
|
||||
id_sync & ~io.dmem.req_rdy |
|
||||
// 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
|
||||
);
|
||||
|
||||
val ctrl_killd = take_pc | ctrl_stalld;
|
||||
|
||||
// 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.dpath.stalld := ctrl_stalld.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.dpath.killf := take_pc | ~io.imem.resp_val;
|
||||
io.dpath.killd := ctrl_killd.toBool;
|
||||
io.dpath.killx := replay_mem.toBool;
|
||||
io.dpath.killm := replay_mem.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.dpath.ren2 := id_ren2.toBool;
|
||||
io.dpath.ren1 := id_ren1.toBool;
|
||||
io.dpath.sel_alu2 := id_sel_alu2;
|
||||
io.dpath.sel_alu1 := id_sel_alu1.toBool;
|
||||
io.dpath.fn_dw := id_fn_dw.toBool;
|
||||
io.dpath.fn_alu := id_fn_alu;
|
||||
io.dpath.div_fn := id_div_fn;
|
||||
io.dpath.div_val := id_div_val.toBool;
|
||||
io.dpath.div_wb := div_wb;
|
||||
io.dpath.mul_fn := id_mul_fn;
|
||||
io.dpath.mul_val := id_mul_val.toBool;
|
||||
io.dpath.mul_wb := mul_wb;
|
||||
io.dpath.wen := id_wen.toBool;
|
||||
io.dpath.sel_wa := id_sel_wa.toBool;
|
||||
io.dpath.sel_wb := id_sel_wb;
|
||||
io.dpath.ren_pcr := id_ren_pcr.toBool;
|
||||
io.dpath.wen_pcr := id_wen_pcr.toBool;
|
||||
io.dpath.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;
|
||||
io.dpath.xcpt_illegal := ~id_int_val.toBool;
|
||||
io.dpath.xcpt_privileged := (id_privileged & ~io.dpath.status(5)).toBool;
|
||||
io.dpath.xcpt_fpu := Bool(false);
|
||||
io.dpath.xcpt_syscall := id_syscall.toBool;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ import scala.math._;
|
||||
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_cmd = Bits(4, 'input);
|
||||
val req_type = Bits(3, '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);
|
||||
@ -58,7 +58,7 @@ class rocketDCacheDM_flush(lines: Int, addrbits: Int) extends Component {
|
||||
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))
|
||||
when (io.cpu.req_val && io.cpu.req_rdy && (io.cpu.req_cmd === M_FLA))
|
||||
{
|
||||
r_cpu_req_tag <== io.cpu.req_tag;
|
||||
flushing <== Bool(true);
|
||||
@ -75,12 +75,12 @@ class rocketDCacheDM_flush(lines: Int, addrbits: Int) extends Component {
|
||||
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_val := (io.cpu.req_val && (io.cpu.req_cmd != M_FLA) && !flush_waiting) || flushing;
|
||||
dcache.io.cpu.req_cmd := Mux(flushing, M_FLA, io.cpu.req_cmd);
|
||||
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_type := io.cpu.req_type;
|
||||
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;
|
||||
@ -96,7 +96,7 @@ class rocketDCacheDM_flush(lines: Int, addrbits: Int) extends Component {
|
||||
// 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();
|
||||
|
||||
@ -116,7 +116,7 @@ class rocketDCacheDM(lines: Int, addrbits: Int) extends Component {
|
||||
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_cmd = 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);
|
||||
@ -125,13 +125,13 @@ class rocketDCacheDM(lines: Int, addrbits: Int) extends Component {
|
||||
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_cmd <== io.cpu.req_cmd;
|
||||
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);
|
||||
val req_load = (r_cpu_req_cmd === M_XRD);
|
||||
val req_store = (r_cpu_req_cmd === M_XWR);
|
||||
val req_flush = (r_cpu_req_cmd === M_FLA);
|
||||
|
||||
when (io.cpu.req_rdy) { r_cpu_req_val <== io.cpu.req_val; }
|
||||
otherwise { r_cpu_req_val <== Bool(false); }
|
||||
@ -248,6 +248,7 @@ class rocketDCacheDM(lines: Int, addrbits: Int) extends Component {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
class rocketDCacheDM_1C(lines: Int, addrbits: Int) extends Component {
|
||||
val io = new ioDCacheDM();
|
||||
@ -267,24 +268,26 @@ class rocketDCacheDM_1C(lines: Int, addrbits: Int) extends Component {
|
||||
val r_cpu_req_addr = Reg(resetVal = Bits(0, addrbits));
|
||||
val r_cpu_req_val = Reg(resetVal = Bool(false));
|
||||
val r_cpu_req_data = Reg(resetVal = Bits(0,64));
|
||||
val r_cpu_req_op = Reg(resetVal = Bits(0,4));
|
||||
val r_cpu_req_wmask = Reg(resetVal = Bits(0,8));
|
||||
val r_cpu_req_tag = Reg(resetVal = Bits(0,12));
|
||||
val r_cpu_req_cmd = Reg(resetVal = Bits(0,4));
|
||||
val r_cpu_req_type = Reg(resetVal = Bits(0,3));
|
||||
// val r_cpu_req_wmask = Reg(resetVal = Bits(0,8));
|
||||
val r_cpu_req_tag = Reg(resetVal = Bits(0,5));
|
||||
|
||||
val p_store_data = Reg(resetVal = Bits(0,64));
|
||||
val p_store_addr = Reg(resetVal = Bits(0,64));
|
||||
val p_store_wmask = Reg(resetVal = Bits(0,64));
|
||||
val p_store_valid = Reg(resetVal = Bool(false));
|
||||
|
||||
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);
|
||||
val req_load = (r_cpu_req_cmd === M_XRD);
|
||||
val req_store = (r_cpu_req_cmd === M_XWR);
|
||||
val req_flush = (r_cpu_req_cmd === M_FLA);
|
||||
|
||||
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_cmd <== io.cpu.req_cmd;
|
||||
r_cpu_req_type <== io.cpu.req_type;
|
||||
// r_cpu_req_wmask <== io.cpu.req_wmask;
|
||||
r_cpu_req_tag <== io.cpu.req_tag;
|
||||
}
|
||||
|
||||
@ -325,10 +328,51 @@ class rocketDCacheDM_1C(lines: Int, addrbits: Int) extends Component {
|
||||
val tag_valid = vb_rdata.toBool;
|
||||
val tag_match = tag_valid && (tag_rdata === r_cpu_req_addr(tagmsb, taglsb));
|
||||
|
||||
// generate write mask and store data signals based on store type and address LSBs
|
||||
val wmask_b =
|
||||
Mux(r_cpu_req_addr(2,0) === UFix(0, 3), Bits("b0000_0001", 8),
|
||||
Mux(r_cpu_req_addr(2,0) === UFix(1, 3), Bits("b0000_0010", 8),
|
||||
Mux(r_cpu_req_addr(2,0) === UFix(2, 3), Bits("b0000_0100", 8),
|
||||
Mux(r_cpu_req_addr(2,0) === UFix(3, 3), Bits("b0000_1000", 8),
|
||||
Mux(r_cpu_req_addr(2,0) === UFix(4, 3), Bits("b0001_0000", 8),
|
||||
Mux(r_cpu_req_addr(2,0) === UFix(5, 3), Bits("b0010_0000", 8),
|
||||
Mux(r_cpu_req_addr(2,0) === UFix(6, 3), Bits("b0100_0000", 8),
|
||||
Mux(r_cpu_req_addr(2,0) === UFix(7, 3), Bits("b1000_0000", 8),
|
||||
UFix(0, 8)))))))));
|
||||
|
||||
val wmask_h =
|
||||
Mux(r_cpu_req_addr(2,1) === UFix(0, 2), Bits("b0000_0011", 8),
|
||||
Mux(r_cpu_req_addr(2,1) === UFix(1, 2), Bits("b0000_1100", 8),
|
||||
Mux(r_cpu_req_addr(2,1) === UFix(2, 2), Bits("b0011_0000", 8),
|
||||
Mux(r_cpu_req_addr(2,1) === UFix(3, 2), Bits("b1100_0000", 8),
|
||||
UFix(0, 8)))));
|
||||
|
||||
val wmask_w =
|
||||
Mux(r_cpu_req_addr(2) === UFix(0, 1), Bits("b0000_1111", 8),
|
||||
Mux(r_cpu_req_addr(2) === UFix(1, 1), Bits("b1111_0000", 8),
|
||||
UFix(0, 8)));
|
||||
|
||||
val wmask_d =
|
||||
Bits("b1111_1111", 8);
|
||||
|
||||
val store_wmask =
|
||||
Mux(r_cpu_req_type === MT_B, wmask_b,
|
||||
Mux(r_cpu_req_type === MT_H, wmask_h,
|
||||
Mux(r_cpu_req_type === MT_W, wmask_w,
|
||||
Mux(r_cpu_req_type === MT_D, wmask_d,
|
||||
UFix(0, 8)))));
|
||||
|
||||
val store_data =
|
||||
Mux(r_cpu_req_type === MT_B, Fill(8, r_cpu_req_data( 7,0)),
|
||||
Mux(r_cpu_req_type === MT_H, Fill(4, r_cpu_req_data(15,0)),
|
||||
Mux(r_cpu_req_type === MT_W, Fill(2, r_cpu_req_data(31,0)),
|
||||
Mux(r_cpu_req_type === MT_D, r_cpu_req_data,
|
||||
UFix(0, 64)))));
|
||||
|
||||
when ((state === s_ready) && r_cpu_req_val && req_store) {
|
||||
p_store_data <== r_cpu_req_data;
|
||||
p_store_data <== store_data;
|
||||
p_store_addr <== r_cpu_req_addr;
|
||||
p_store_wmask <== r_cpu_req_wmask;
|
||||
p_store_wmask <== store_wmask;
|
||||
p_store_valid <== Bool(true);
|
||||
}
|
||||
|
||||
@ -370,14 +414,14 @@ class rocketDCacheDM_1C(lines: Int, addrbits: Int) extends Component {
|
||||
Fill(8, p_store_wmask(1)),
|
||||
Fill(8, p_store_wmask(0)));
|
||||
|
||||
val store_wmask =
|
||||
val da_store_wmask =
|
||||
Mux(p_store_addr(offsetlsb).toBool,
|
||||
Cat(p_wmask_expand, Bits(0,64)),
|
||||
Cat(Bits(0,64), p_wmask_expand));
|
||||
|
||||
val data_array_wmask =
|
||||
Mux((state === s_refill), ~Bits(0,128),
|
||||
store_wmask);
|
||||
da_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,
|
||||
@ -394,7 +438,7 @@ class rocketDCacheDM_1C(lines: Int, addrbits: Int) extends Component {
|
||||
io.cpu.resp_val := ((state === s_ready) && r_cpu_req_val && tag_match && req_load && !(p_store_valid && addr_match)) ||
|
||||
((state === s_resolve_miss) && req_flush);
|
||||
|
||||
io.cpu.resp_tag := r_cpu_req_tag;
|
||||
io.cpu.resp_tag := Cat(Bits(0,1), r_cpu_req_type, r_cpu_req_addr(2,0), r_cpu_req_tag);
|
||||
|
||||
io.cpu.resp_data :=
|
||||
Mux(r_cpu_req_addr(offsetlsb).toBool, data_array_rdata(127, 64),
|
||||
|
@ -5,46 +5,13 @@ 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 ctrl = new ioCtrlDpath().flip();
|
||||
val debug = new ioDebug();
|
||||
val wb = new ioDpathWB();
|
||||
val imem = new ioDpathImem();
|
||||
val dmem = new ioDmem(List("req_addr", "req_data", "req_tag", "resp_val", "resp_tag", "resp_data")).flip();
|
||||
val imem = new ioImem(List("req_addr", "resp_data")).flip();
|
||||
}
|
||||
|
||||
class rocketDpath extends Component
|
||||
@ -77,37 +44,60 @@ class rocketDpath extends Component
|
||||
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);
|
||||
val id_reg_pc = Reg(resetVal = UFix(0,32));
|
||||
val id_reg_pc_plus4 = Reg(resetVal = UFix(0,32));
|
||||
val id_reg_inst = Reg(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() };
|
||||
|
||||
val ex_reg_pc = Reg(resetVal = UFix(0,32));
|
||||
val ex_reg_pc_plus4 = Reg(resetVal = UFix(0,32));
|
||||
val ex_reg_inst = Reg(resetVal = Bits(0,32));
|
||||
val ex_reg_raddr2 = Reg(resetVal = UFix(0,5));
|
||||
val ex_reg_raddr1 = Reg(resetVal = UFix(0,5));
|
||||
val ex_reg_rs2 = Reg(resetVal = Bits(0,64));
|
||||
val ex_reg_rs1 = Reg(resetVal = Bits(0,64));
|
||||
val ex_reg_waddr = Reg(resetVal = UFix(0,5));
|
||||
val ex_reg_ctrl_sel_alu2 = Reg(resetVal = A2_X);
|
||||
val ex_reg_ctrl_sel_alu1 = Reg(resetVal = A1_X);
|
||||
val ex_reg_ctrl_fn_dw = Reg(resetVal = DW_X);
|
||||
val ex_reg_ctrl_fn_alu = Reg(resetVal = FN_X);
|
||||
val ex_reg_ctrl_ll_wb = Reg(resetVal = Bool(false));
|
||||
val ex_reg_ctrl_mul_val = Reg(resetVal = Bool(false));
|
||||
val ex_reg_ctrl_mul_fn = Reg(resetVal = MUL_X);
|
||||
val ex_reg_ctrl_div_val = Reg(resetVal = Bool(false));
|
||||
val ex_reg_ctrl_div_fn = Reg(resetVal = DIV_X);
|
||||
val ex_reg_ctrl_sel_wb = Reg(resetVal = WB_X);
|
||||
val ex_reg_ctrl_wen = Reg(resetVal = Bool(false));
|
||||
val ex_reg_ctrl_ren_pcr = Reg(resetVal = Bool(false));
|
||||
val ex_reg_ctrl_wen_pcr = Reg(resetVal = Bool(false));
|
||||
val ex_reg_ctrl_eret = Reg(resetVal = Bool(false));
|
||||
val ex_reg_ctrl_exception = Reg(resetVal = Bool(false));
|
||||
val ex_reg_ctrl_cause = Reg(resetVal = UFix(0,5));
|
||||
val ex_wdata = Wire() { Bits() };
|
||||
|
||||
val mem_reg_pc = Reg(resetVal = UFix(0,32));
|
||||
val mem_reg_pc_plus4 = Reg(resetVal = UFix(0,32));
|
||||
val mem_reg_waddr = Reg(resetVal = UFix(0,5));
|
||||
val mem_reg_wdata = Reg(resetVal = Bits(0,64));
|
||||
val mem_reg_raddr2 = Reg(resetVal = UFix(0,5));
|
||||
val mem_reg_ctrl_ll_wb = Reg(resetVal = Bool(false));
|
||||
val mem_reg_ctrl_div_val = Reg(resetVal = Bool(false));
|
||||
val mem_reg_ctrl_mul_val = Reg(resetVal = Bool(false));
|
||||
val mem_reg_ctrl_wen = Reg(resetVal = Bool(false));
|
||||
val mem_reg_ctrl_wen_pcr = Reg(resetVal = Bool(false));
|
||||
val mem_reg_ctrl_exception = Reg(resetVal = Bool(false));
|
||||
|
||||
val wb_reg_pc = Reg(resetVal = UFix(0,32));
|
||||
val wb_reg_pc_plus4 = Reg(resetVal = UFix(0,32));
|
||||
val wb_reg_waddr = Reg(resetVal = UFix(0,5));
|
||||
val wb_reg_wdata = Reg(resetVal = Bits(0,64));
|
||||
val wb_reg_ctrl_ll_wb = Reg(resetVal = Bool(false));
|
||||
val wb_reg_raddr2 = Reg(resetVal = UFix(0,5));
|
||||
val wb_reg_ctrl_div_val = Reg(resetVal = Bool(false));
|
||||
val wb_reg_ctrl_mul_val = Reg(resetVal = Bool(false));
|
||||
val wb_reg_ctrl_wen = Reg(resetVal = Bool(false));
|
||||
val wb_reg_ctrl_wen_pcr = Reg(resetVal = Bool(false));
|
||||
|
||||
// instruction fetch stage
|
||||
val if_pc_plus4 = if_reg_pc + UFix(4, 32);
|
||||
|
||||
@ -132,7 +122,8 @@ class rocketDpath extends Component
|
||||
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))))))));
|
||||
Mux(io.ctrl.sel_pc === PC_MEM, mem_reg_pc,
|
||||
UFix(0, 32)))))))));
|
||||
|
||||
when (!io.host.start){
|
||||
if_reg_pc <== UFix(0, 32); //32'hFFFF_FFFC;
|
||||
@ -146,7 +137,7 @@ class rocketDpath extends Component
|
||||
if_next_pc);
|
||||
|
||||
btb.io.current_pc4 := if_pc_plus4;
|
||||
btb.io.hit ^^ io.dpath.btb_hit;
|
||||
btb.io.hit ^^ io.ctrl.btb_hit;
|
||||
btb.io.wen ^^ io.ctrl.wen_btb;
|
||||
btb.io.correct_pc4 := ex_reg_pc_plus4;
|
||||
|
||||
@ -174,6 +165,7 @@ class rocketDpath extends Component
|
||||
rfile.io.r1.addr := id_raddr1;
|
||||
val id_rdata1 = rfile.io.r1.data;
|
||||
|
||||
// destination register selection
|
||||
val id_waddr =
|
||||
Mux(io.ctrl.div_wb, div_result_tag,
|
||||
Mux(io.ctrl.mul_wb, mul_result_tag,
|
||||
@ -181,16 +173,22 @@ class rocketDpath extends Component
|
||||
Mux(io.ctrl.sel_wa === WA_RA, RA,
|
||||
UFix(0, 5)))));
|
||||
|
||||
// bypass muxes
|
||||
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)));
|
||||
Mux(id_raddr1 != UFix(0, 5) && ex_reg_ctrl_wen && id_raddr1 === ex_reg_waddr, ex_wdata,
|
||||
Mux(id_raddr1 != UFix(0, 5) && mem_reg_ctrl_wen && id_raddr1 === mem_reg_waddr, mem_reg_wdata,
|
||||
Mux(id_raddr1 != UFix(0, 5) && wb_reg_ctrl_wen && id_raddr1 === wb_reg_waddr, wb_reg_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);
|
||||
Mux(id_raddr2 != UFix(0, 5) && ex_reg_ctrl_wen && id_raddr2 === ex_reg_waddr, ex_wdata,
|
||||
Mux(id_raddr2 != UFix(0, 5) && mem_reg_ctrl_wen && id_raddr2 === mem_reg_waddr, mem_reg_wdata,
|
||||
Mux(id_raddr2 != UFix(0, 5) && wb_reg_ctrl_wen && id_raddr2 === wb_reg_waddr, wb_reg_wdata,
|
||||
id_rdata2)));
|
||||
|
||||
// write value to cause register based on exception type
|
||||
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),
|
||||
@ -199,9 +197,9 @@ class rocketDpath extends Component
|
||||
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;
|
||||
io.ctrl.inst := id_reg_inst;
|
||||
// io.ctrl.rs1 := id_rs1;
|
||||
// io.ctrl.rs2 := id_rs2;
|
||||
|
||||
// execute stage
|
||||
ex_reg_pc <== id_reg_pc;
|
||||
@ -269,8 +267,8 @@ class rocketDpath extends Component
|
||||
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;
|
||||
io.ctrl.div_rdy := div.io.div_rdy;
|
||||
io.ctrl.div_result_val := div.io.div_result_val;
|
||||
|
||||
// multiplier
|
||||
mul.io.mul_val := ex_reg_ctrl_mul_val;
|
||||
@ -279,66 +277,145 @@ class rocketDpath extends Component
|
||||
mul.io.in0 := ex_reg_rs1;
|
||||
mul.io.in1 := ex_reg_rs2;
|
||||
|
||||
io.dpath.mul_result_val := mul.io.result_val;
|
||||
io.ctrl.mul_result_val := mul.io.result_val;
|
||||
|
||||
io.ctrl.ex_waddr := ex_reg_waddr; // for load/use hazard detection
|
||||
|
||||
// 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;
|
||||
// D$ request interface (registered inside D$ module)
|
||||
// other signals (req_val, req_rdy) connect to control module
|
||||
io.dmem.req_addr := ex_alu_out;
|
||||
io.dmem.req_data := ex_reg_rs2;
|
||||
io.dmem.req_tag := ex_reg_waddr;
|
||||
|
||||
// processor control regfile read
|
||||
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.host.from_wen ^^ io.host.from_wen;
|
||||
pcr.io.host.from ^^ io.host.from;
|
||||
pcr.io.host.to ^^ io.host.to;
|
||||
|
||||
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.ctrl.status := pcr.io.status;
|
||||
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 |
|
||||
io.ctrl.br_eq := (ex_reg_rs1 === ex_reg_rs2);
|
||||
io.ctrl.br_ltu := (ex_reg_rs1.toUFix < ex_reg_rs2.toUFix);
|
||||
io.ctrl.br_lt :=
|
||||
(~(ex_reg_rs1(63) ^ ex_reg_rs2(63)) & io.ctrl.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_ll_wb || ex_reg_ctrl_wen_pcr, 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;
|
||||
// memory stage
|
||||
mem_reg_pc <== ex_reg_pc;
|
||||
mem_reg_pc_plus4 <== ex_reg_pc_plus4;
|
||||
mem_reg_waddr <== ex_reg_waddr;
|
||||
mem_reg_wdata <== ex_wdata;
|
||||
mem_reg_ctrl_ll_wb <== ex_reg_ctrl_ll_wb;
|
||||
mem_reg_raddr2 <== ex_reg_raddr2;
|
||||
|
||||
when (io.ctrl.killx) {
|
||||
mem_reg_ctrl_div_val <== Bool(false);
|
||||
mem_reg_ctrl_mul_val <== Bool(false);
|
||||
mem_reg_ctrl_wen <== Bool(false);
|
||||
mem_reg_ctrl_wen_pcr <== Bool(false);
|
||||
mem_reg_ctrl_exception <== Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
mem_reg_ctrl_div_val <== ex_reg_ctrl_div_val;
|
||||
mem_reg_ctrl_mul_val <== ex_reg_ctrl_mul_val;
|
||||
mem_reg_ctrl_wen <== ex_reg_ctrl_wen;
|
||||
mem_reg_ctrl_wen_pcr <== ex_reg_ctrl_wen_pcr;
|
||||
mem_reg_ctrl_exception <== ex_reg_ctrl_exception;
|
||||
}
|
||||
|
||||
// exception signal to control (for NPC select)
|
||||
io.dpath.exception := ex_reg_ctrl_exception;
|
||||
io.ctrl.exception := mem_reg_ctrl_exception;
|
||||
|
||||
// writeback stage
|
||||
val r_dmem_resp_val = Reg(io.dmem.resp_val);
|
||||
val r_dmem_resp_waddr = Reg(io.dmem.resp_tag(4,0).toUFix);
|
||||
val r_dmem_resp_pos = Reg(io.dmem.resp_tag(7,5));
|
||||
val r_dmem_resp_type = Reg(io.dmem.resp_tag(9,8));
|
||||
val r_dmem_resp_data = Reg(io.dmem.resp_data);
|
||||
|
||||
wb_reg_pc <== mem_reg_pc;
|
||||
wb_reg_pc_plus4 <== mem_reg_pc_plus4;
|
||||
wb_reg_waddr <== mem_reg_waddr;
|
||||
wb_reg_wdata <== mem_reg_wdata;
|
||||
wb_reg_ctrl_ll_wb <== mem_reg_ctrl_ll_wb;
|
||||
wb_reg_raddr2 <== mem_reg_raddr2;
|
||||
|
||||
when (io.ctrl.killm) {
|
||||
wb_reg_ctrl_div_val <== Bool(false);
|
||||
wb_reg_ctrl_mul_val <== Bool(false);
|
||||
wb_reg_ctrl_wen <== Bool(false);
|
||||
wb_reg_ctrl_wen_pcr <== Bool(false);
|
||||
}
|
||||
otherwise {
|
||||
wb_reg_ctrl_div_val <== mem_reg_ctrl_div_val;
|
||||
wb_reg_ctrl_mul_val <== mem_reg_ctrl_mul_val;
|
||||
wb_reg_ctrl_wen <== mem_reg_ctrl_wen;
|
||||
wb_reg_ctrl_wen_pcr <== mem_reg_ctrl_wen_pcr;
|
||||
}
|
||||
|
||||
// crossbar/sign extension for 8/16/32 bit loads
|
||||
val dmem_resp_data_w =
|
||||
Mux(r_dmem_resp_pos(2).toBool, r_dmem_resp_data(63, 32), r_dmem_resp_data(31, 0));
|
||||
val dmem_resp_data_h =
|
||||
Mux(r_dmem_resp_pos(1).toBool, dmem_resp_data_w(31, 16), dmem_resp_data_w(15, 0));
|
||||
val dmem_resp_data_b =
|
||||
Mux(r_dmem_resp_pos(0).toBool, dmem_resp_data_h(15, 8), dmem_resp_data_h(7, 0));
|
||||
|
||||
val dmem_resp_data_final =
|
||||
Mux(r_dmem_resp_type === MT_B, Cat(Fill(56, dmem_resp_data_b(7)), dmem_resp_data_b),
|
||||
Mux(r_dmem_resp_type === MT_BU, Cat(UFix(0, 56), dmem_resp_data_b),
|
||||
Mux(r_dmem_resp_type === MT_H, Cat(Fill(48, dmem_resp_data_h(15)), dmem_resp_data_h),
|
||||
Mux(r_dmem_resp_type === MT_HU, Cat(UFix(0, 48), dmem_resp_data_h),
|
||||
Mux(r_dmem_resp_type === MT_W, Cat(Fill(32, dmem_resp_data_w(31)), dmem_resp_data_w),
|
||||
Mux(r_dmem_resp_type === MT_WU, Cat(UFix(0, 32), dmem_resp_data_w),
|
||||
Mux(r_dmem_resp_type === MT_D, r_dmem_resp_data,
|
||||
UFix(0, 64))))))));
|
||||
|
||||
// regfile write
|
||||
rfile.io.w0.addr := wb_reg_waddr;
|
||||
rfile.io.w0.en := wb_reg_ctrl_wen | wb_reg_ctrl_ll_wb;
|
||||
rfile.io.w0.data := wb_reg_wdata;
|
||||
|
||||
rfile.io.w1.addr := r_dmem_resp_waddr;
|
||||
rfile.io.w1.en := r_dmem_resp_val;
|
||||
rfile.io.w1.data := dmem_resp_data_final;
|
||||
|
||||
// scoreboard set (for D$ misses, div, mul)
|
||||
io.ctrl.sboard_set := wb_reg_ctrl_div_val | wb_reg_ctrl_mul_val | io.ctrl.dcache_miss;
|
||||
io.ctrl.sboard_seta := wb_reg_waddr;
|
||||
|
||||
// scoreboard clear (for div/mul and D$ load miss writebacks)
|
||||
io.ctrl.sboard_clr0 := wb_reg_ctrl_ll_wb;
|
||||
io.ctrl.sboard_clr0a := wb_reg_waddr;
|
||||
io.ctrl.sboard_clr1 := r_dmem_resp_val;
|
||||
io.ctrl.sboard_clr1a := r_dmem_resp_waddr;
|
||||
|
||||
// processor control regfile write
|
||||
pcr.io.w.addr := wb_reg_raddr2;
|
||||
pcr.io.w.en := wb_reg_ctrl_wen_pcr;
|
||||
pcr.io.w.data := wb_reg_wdata;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,124 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package Top
|
||||
{
|
||||
|
||||
import Chisel._
|
||||
import Node._;
|
||||
import Constants._;
|
||||
|
||||
class ioWriteback extends Bundle()
|
||||
{
|
||||
val dmem_resp_val = Bool('input);
|
||||
val dmem_resp_data = UFix(64, 'input);
|
||||
val dmem_resp_tag = UFix(12, 'input);
|
||||
val wb_waddr = UFix(5, 'output);
|
||||
val wb_wen = Bool('output);
|
||||
val wb_wdata = Bits(64, 'output);
|
||||
}
|
||||
|
||||
class rocketWriteback extends Component
|
||||
{
|
||||
override val io = new ioWriteback();
|
||||
|
||||
val r_dmem_resp_val = Reg(io.dmem_resp_val);
|
||||
val r_dmem_resp_data = Reg(io.dmem_resp_data);
|
||||
val r_dmem_resp_tag = Reg(io.dmem_resp_tag);
|
||||
|
||||
val dmem_resp_xf = r_dmem_resp_tag(11);
|
||||
val dmem_resp_type = r_dmem_resp_tag(10, 8);
|
||||
val dmem_resp_pos = r_dmem_resp_tag(7, 5);
|
||||
val dmem_resp_waddr = r_dmem_resp_tag(4, 0);
|
||||
val dmem_resp_xval = r_dmem_resp_val & ~dmem_resp_xf;
|
||||
val dmem_resp_fval = r_dmem_resp_val & dmem_resp_xf;
|
||||
|
||||
val dmem_resp_data_w =
|
||||
Mux(dmem_resp_pos(2).toBool, r_dmem_resp_data(63, 32), r_dmem_resp_data(31, 0));
|
||||
val dmem_resp_data_h =
|
||||
Mux(dmem_resp_pos(1).toBool, dmem_resp_data_w(31, 16), dmem_resp_data_w(15, 0));
|
||||
val dmem_resp_data_b =
|
||||
Mux(dmem_resp_pos(0).toBool, dmem_resp_data_h(15, 8), dmem_resp_data_h(7, 0));
|
||||
|
||||
val dmem_resp_data_final =
|
||||
Mux(dmem_resp_type === MT_B, Cat(Fill(56, dmem_resp_data_b(7)), dmem_resp_data_b),
|
||||
Mux(dmem_resp_type === MT_BU, Cat(UFix(0, 56), dmem_resp_data_b),
|
||||
Mux(dmem_resp_type === MT_H, Cat(Fill(48, dmem_resp_data_h(15)), dmem_resp_data_h),
|
||||
Mux(dmem_resp_type === MT_HU, Cat(UFix(0, 48), dmem_resp_data_h),
|
||||
Mux(dmem_resp_type === MT_W, Cat(Fill(32, dmem_resp_data_w(31)), dmem_resp_data_w),
|
||||
Mux(dmem_resp_type === MT_WU, Cat(UFix(0, 32), dmem_resp_data_w),
|
||||
Mux(dmem_resp_type === MT_D, r_dmem_resp_data,
|
||||
UFix(0, 64))))))));
|
||||
|
||||
io.wb_wen := dmem_resp_xval.toBool;
|
||||
io.wb_waddr := dmem_resp_waddr;
|
||||
io.wb_wdata := dmem_resp_data_final;
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user