new htif protocol and implementation
You must update your fesvr and isasim!
This commit is contained in:
parent
9af86633d7
commit
7034c9be65
@ -24,6 +24,7 @@ class ioMemArbiter extends Bundle() {
|
|||||||
// val icache = new ioICache();
|
// val icache = new ioICache();
|
||||||
val icache = new ioIPrefetcherMem().flip();
|
val icache = new ioIPrefetcherMem().flip();
|
||||||
val vicache = new ioICache();
|
val vicache = new ioICache();
|
||||||
|
val htif = new ioDCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
class rocketMemArbiter extends Component {
|
class rocketMemArbiter extends Component {
|
||||||
@ -34,26 +35,31 @@ class rocketMemArbiter extends Component {
|
|||||||
// *****************************
|
// *****************************
|
||||||
|
|
||||||
// Memory request is valid if either icache or dcache have a valid request
|
// Memory request is valid if either icache or dcache have a valid request
|
||||||
io.mem.req_val := (io.icache.req_val || io.vicache.req_val || io.dcache.req_val);
|
io.mem.req_val := io.icache.req_val || io.vicache.req_val || io.dcache.req_val || io.htif.req_val
|
||||||
|
|
||||||
// Set read/write bit. ICache always reads
|
// Set read/write bit. I$ always reads
|
||||||
io.mem.req_rw := Mux(io.dcache.req_val, io.dcache.req_rw, Bool(false));
|
io.mem.req_rw :=
|
||||||
|
Mux(io.dcache.req_val, io.dcache.req_rw,
|
||||||
|
Mux(io.icache.req_val, Bool(false),
|
||||||
|
Mux(io.vicache.req_val, Bool(false),
|
||||||
|
io.htif.req_rw)))
|
||||||
|
|
||||||
// Give priority to ICache
|
// Give priority to D$
|
||||||
io.mem.req_addr :=
|
io.mem.req_addr :=
|
||||||
Mux(io.dcache.req_val, io.dcache.req_addr,
|
Mux(io.dcache.req_val, io.dcache.req_addr,
|
||||||
Mux(io.icache.req_val, io.icache.req_addr,
|
Mux(io.icache.req_val, io.icache.req_addr,
|
||||||
io.vicache.req_addr))
|
Mux(io.vicache.req_val, io.vicache.req_addr,
|
||||||
|
io.htif.req_addr)))
|
||||||
|
|
||||||
|
io.mem.req_wdata := Mux(io.dcache.req_val, io.dcache.req_wdata, io.htif.req_wdata)
|
||||||
|
|
||||||
// low bit of tag to indicate D$, I$, and VI$
|
// low bit of tag to indicate D$, I$, and VI$
|
||||||
val t_dcache :: t_icache :: t_vicache :: Nil = Enum(3){ UFix() }
|
val t_dcache :: t_icache :: t_vicache :: t_htif :: Nil = Enum(4){ UFix() }
|
||||||
io.mem.req_tag :=
|
io.mem.req_tag :=
|
||||||
Mux(io.dcache.req_val, Cat(io.dcache.req_tag, t_dcache),
|
Mux(io.dcache.req_val, Cat(io.dcache.req_tag, t_dcache),
|
||||||
Mux(io.icache.req_val, Cat(io.icache.req_tag, t_icache),
|
Mux(io.icache.req_val, Cat(io.icache.req_tag, t_icache),
|
||||||
Cat(Bits(0, MEM_TAG_BITS-2), t_vicache)))
|
Mux(io.vicache.req_val, t_vicache,
|
||||||
|
t_htif)))
|
||||||
// Just pass through write data (only D$ will write)
|
|
||||||
io.mem.req_wdata := io.dcache.req_wdata;
|
|
||||||
|
|
||||||
// *****************************
|
// *****************************
|
||||||
// Interface to caches
|
// Interface to caches
|
||||||
@ -64,16 +70,19 @@ class rocketMemArbiter extends Component {
|
|||||||
io.dcache.req_rdy := io.mem.req_rdy;
|
io.dcache.req_rdy := io.mem.req_rdy;
|
||||||
io.icache.req_rdy := io.mem.req_rdy && !io.dcache.req_val;
|
io.icache.req_rdy := io.mem.req_rdy && !io.dcache.req_val;
|
||||||
io.vicache.req_rdy := io.mem.req_rdy && !io.dcache.req_val && !io.icache.req_val
|
io.vicache.req_rdy := io.mem.req_rdy && !io.dcache.req_val && !io.icache.req_val
|
||||||
|
io.htif.req_rdy := io.mem.req_rdy && !io.dcache.req_val && !io.icache.req_val && !io.vicache.req_val
|
||||||
|
|
||||||
// Response will only be valid for D$ or I$ not both because of tag bits
|
// Response will only be valid for D$ or I$ not both because of tag bits
|
||||||
io.dcache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_dcache)
|
io.dcache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_dcache)
|
||||||
io.icache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_icache)
|
io.icache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_icache)
|
||||||
io.vicache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_vicache)
|
io.vicache.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_vicache)
|
||||||
|
io.htif.resp_val := io.mem.resp_val && (io.mem.resp_tag(1,0) === t_htif)
|
||||||
|
|
||||||
// Feed through data to both
|
// Feed through data to both
|
||||||
io.dcache.resp_data := io.mem.resp_data;
|
io.dcache.resp_data := io.mem.resp_data;
|
||||||
io.icache.resp_data := io.mem.resp_data;
|
io.icache.resp_data := io.mem.resp_data;
|
||||||
io.vicache.resp_data := io.mem.resp_data
|
io.vicache.resp_data := io.mem.resp_data
|
||||||
|
io.htif.resp_data := io.mem.resp_data
|
||||||
|
|
||||||
io.dcache.resp_tag := io.mem.resp_tag >> UFix(2)
|
io.dcache.resp_tag := io.mem.resp_tag >> UFix(2)
|
||||||
io.icache.resp_tag := io.mem.resp_tag >> UFix(2)
|
io.icache.resp_tag := io.mem.resp_tag >> UFix(2)
|
||||||
|
@ -138,7 +138,6 @@ object Constants
|
|||||||
val PCR_TOHOST = UFix(16, 5);
|
val PCR_TOHOST = UFix(16, 5);
|
||||||
val PCR_FROMHOST = UFix(17, 5);
|
val PCR_FROMHOST = UFix(17, 5);
|
||||||
val PCR_VECBANK = UFix(18, 5);
|
val PCR_VECBANK = UFix(18, 5);
|
||||||
val PCR_CONSOLE = UFix(19, 5);
|
|
||||||
|
|
||||||
// definition of bits in PCR status reg
|
// definition of bits in PCR status reg
|
||||||
val SR_ET = 0; // enable traps
|
val SR_ET = 0; // enable traps
|
||||||
|
@ -10,25 +10,10 @@ class ioDebug(view: List[String] = null) extends Bundle(view)
|
|||||||
val error_mode = Bool(OUTPUT);
|
val error_mode = Bool(OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ioHost(view: List[String] = null) extends Bundle(view)
|
|
||||||
{
|
|
||||||
val from_wen = Bool(INPUT);
|
|
||||||
val from = Bits(64, INPUT);
|
|
||||||
val to = Bits(64, 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()
|
class ioRocket extends Bundle()
|
||||||
{
|
{
|
||||||
val debug = new ioDebug();
|
val debug = new ioDebug();
|
||||||
val console = new ioConsole();
|
val host = new ioHTIF();
|
||||||
val host = new ioHost();
|
|
||||||
val imem = new ioImem().flip();
|
val imem = new ioImem().flip();
|
||||||
val vimem = new ioImem().flip();
|
val vimem = new ioImem().flip();
|
||||||
val dmem = new ioDmem().flip();
|
val dmem = new ioDmem().flip();
|
||||||
@ -47,6 +32,7 @@ class rocketProc extends Component
|
|||||||
val ptw = new rocketPTW();
|
val ptw = new rocketPTW();
|
||||||
val arb = new rocketDmemArbiter();
|
val arb = new rocketDmemArbiter();
|
||||||
|
|
||||||
|
ctrl.io.htif_reset := io.host.reset
|
||||||
ctrl.io.dpath <> dpath.io.ctrl;
|
ctrl.io.dpath <> dpath.io.ctrl;
|
||||||
dpath.io.host <> io.host;
|
dpath.io.host <> io.host;
|
||||||
dpath.io.debug <> io.debug;
|
dpath.io.debug <> io.debug;
|
||||||
@ -112,10 +98,6 @@ class rocketProc extends Component
|
|||||||
dpath.io.dmem.resp_data := arb.io.cpu.resp_data;
|
dpath.io.dmem.resp_data := arb.io.cpu.resp_data;
|
||||||
dpath.io.dmem.resp_data_subword := io.dmem.resp_data_subword;
|
dpath.io.dmem.resp_data_subword := io.dmem.resp_data_subword;
|
||||||
|
|
||||||
io.console.bits := dpath.io.console.bits;
|
|
||||||
io.console.valid := dpath.io.console.valid;
|
|
||||||
ctrl.io.console.rdy := io.console.rdy;
|
|
||||||
|
|
||||||
if (HAVE_FPU)
|
if (HAVE_FPU)
|
||||||
{
|
{
|
||||||
val fpu = new rocketFPU(4,6)
|
val fpu = new rocketFPU(4,6)
|
||||||
|
@ -77,8 +77,8 @@ class ioCtrlDpath extends Bundle()
|
|||||||
|
|
||||||
class ioCtrlAll extends Bundle()
|
class ioCtrlAll extends Bundle()
|
||||||
{
|
{
|
||||||
|
val htif_reset = Bool(INPUT)
|
||||||
val dpath = new ioCtrlDpath();
|
val dpath = new ioCtrlDpath();
|
||||||
val console = new ioConsole(List("rdy"));
|
|
||||||
val imem = new ioImem(List("req_val", "resp_val")).flip();
|
val imem = new ioImem(List("req_val", "resp_val")).flip();
|
||||||
val dmem = new ioDmem(List("req_val", "req_kill", "req_rdy", "req_cmd", "req_type", "resp_miss", "resp_nack")).flip();
|
val dmem = new ioDmem(List("req_val", "req_kill", "req_rdy", "req_cmd", "req_type", "resp_miss", "resp_nack")).flip();
|
||||||
val ext_mem = new ioDmem(List("req_val", "req_cmd", "req_type", "resp_nack"))
|
val ext_mem = new ioDmem(List("req_val", "req_cmd", "req_type", "resp_nack"))
|
||||||
@ -298,8 +298,6 @@ class rocketCtrl extends Component
|
|||||||
val id_raddr1 = io.dpath.inst(26,22);
|
val id_raddr1 = io.dpath.inst(26,22);
|
||||||
val id_waddr = Mux(id_sel_wa === WA_RA, RA, io.dpath.inst(31,27));
|
val id_waddr = Mux(id_sel_wa === WA_RA, RA, io.dpath.inst(31,27));
|
||||||
|
|
||||||
val id_console_out_val = id_wen_pcr.toBool && (id_raddr2 === PCR_CONSOLE);
|
|
||||||
|
|
||||||
val wb_reg_div_mul_val = Reg(resetVal = Bool(false))
|
val wb_reg_div_mul_val = Reg(resetVal = Bool(false))
|
||||||
val wb_reg_dcache_miss = Reg(io.dmem.resp_miss, resetVal = Bool(false));
|
val wb_reg_dcache_miss = Reg(io.dmem.resp_miss, resetVal = Bool(false));
|
||||||
|
|
||||||
@ -699,7 +697,7 @@ class rocketCtrl extends Component
|
|||||||
io.dpath.wen_btb := !ex_reg_btb_hit && br_taken
|
io.dpath.wen_btb := !ex_reg_btb_hit && br_taken
|
||||||
io.dpath.clr_btb := ex_reg_btb_hit && !br_taken || id_reg_icmiss;
|
io.dpath.clr_btb := ex_reg_btb_hit && !br_taken || id_reg_icmiss;
|
||||||
|
|
||||||
io.imem.req_val := take_pc_wb || !mem_reg_replay && !ex_reg_replay && (take_pc_ex || !id_reg_replay)
|
io.imem.req_val := !io.htif_reset && (take_pc_wb || !mem_reg_replay && !ex_reg_replay && (take_pc_ex || !id_reg_replay))
|
||||||
|
|
||||||
// stall for RAW/WAW hazards on loads, AMOs, and mul/div in execute stage.
|
// stall for RAW/WAW hazards on loads, AMOs, and mul/div in execute stage.
|
||||||
val data_hazard_ex = ex_reg_wen &&
|
val data_hazard_ex = ex_reg_wen &&
|
||||||
@ -753,8 +751,7 @@ class rocketCtrl extends Component
|
|||||||
id_mem_val.toBool && !(io.dmem.req_rdy && io.dtlb_rdy) ||
|
id_mem_val.toBool && !(io.dmem.req_rdy && io.dtlb_rdy) ||
|
||||||
id_vec_val.toBool && !(io.vec_iface.vcmdq_ready && io.vec_iface.vximm1q_ready && io.vec_iface.vximm2q_ready) || // being conservative
|
id_vec_val.toBool && !(io.vec_iface.vcmdq_ready && io.vec_iface.vximm1q_ready && io.vec_iface.vximm2q_ready) || // being conservative
|
||||||
((id_sync === SYNC_D) || (id_sync === SYNC_I)) && !io.dmem.req_rdy ||
|
((id_sync === SYNC_D) || (id_sync === SYNC_I)) && !io.dmem.req_rdy ||
|
||||||
vec_cpfence ||
|
vec_cpfence
|
||||||
id_console_out_val && !io.console.rdy
|
|
||||||
);
|
);
|
||||||
val ctrl_stallf = ctrl_stalld;
|
val ctrl_stallf = ctrl_stalld;
|
||||||
|
|
||||||
|
@ -29,9 +29,8 @@ class ioDpathImem extends Bundle()
|
|||||||
|
|
||||||
class ioDpathAll extends Bundle()
|
class ioDpathAll extends Bundle()
|
||||||
{
|
{
|
||||||
val host = new ioHost();
|
val host = new ioHTIF();
|
||||||
val ctrl = new ioCtrlDpath().flip();
|
val ctrl = new ioCtrlDpath().flip();
|
||||||
val console = new ioConsole(List("valid","bits"));
|
|
||||||
val debug = new ioDebug();
|
val debug = new ioDebug();
|
||||||
val dmem = new ioDpathDmem();
|
val dmem = new ioDpathDmem();
|
||||||
val ext_mem = new ioDmem(List("req_val", "req_idx", "req_ppn", "req_data", "req_tag", "resp_val", "resp_data", "resp_tag"))
|
val ext_mem = new ioDmem(List("req_val", "req_idx", "req_ppn", "req_data", "req_tag", "resp_val", "resp_data", "resp_tag"))
|
||||||
@ -313,9 +312,7 @@ class rocketDpath extends Component
|
|||||||
Mux(ex_reg_ctrl_eret, PCR_EPC,
|
Mux(ex_reg_ctrl_eret, PCR_EPC,
|
||||||
ex_reg_raddr2);
|
ex_reg_raddr2);
|
||||||
|
|
||||||
pcr.io.host.from_wen <> io.host.from_wen;
|
pcr.io.host <> io.host
|
||||||
pcr.io.host.from <> io.host.from;
|
|
||||||
pcr.io.host.to <> io.host.to;
|
|
||||||
|
|
||||||
io.ctrl.irq_timer := pcr.io.irq_timer;
|
io.ctrl.irq_timer := pcr.io.irq_timer;
|
||||||
io.ctrl.irq_ipi := pcr.io.irq_ipi;
|
io.ctrl.irq_ipi := pcr.io.irq_ipi;
|
||||||
@ -483,8 +480,6 @@ class rocketDpath extends Component
|
|||||||
pcr.io.cause := io.ctrl.cause;
|
pcr.io.cause := io.ctrl.cause;
|
||||||
pcr.io.pc := wb_reg_pc;
|
pcr.io.pc := wb_reg_pc;
|
||||||
pcr.io.badvaddr_wen := io.ctrl.badvaddr_wen;
|
pcr.io.badvaddr_wen := io.ctrl.badvaddr_wen;
|
||||||
io.console.bits := pcr.io.console_data;
|
|
||||||
io.console.valid := pcr.io.console_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ class rocketDpathBTB(entries: Int) extends Component
|
|||||||
|
|
||||||
class ioDpathPCR extends Bundle()
|
class ioDpathPCR extends Bundle()
|
||||||
{
|
{
|
||||||
val host = new ioHost(List("from", "from_wen", "to"));
|
val host = new ioHTIF()
|
||||||
val debug = new ioDebug(List("error_mode", "log_control"));
|
val debug = new ioDebug(List("error_mode", "log_control"));
|
||||||
val r = new ioReadPort();
|
val r = new ioReadPort();
|
||||||
val w = new ioWritePort();
|
val w = new ioWritePort();
|
||||||
@ -78,8 +78,6 @@ class ioDpathPCR extends Bundle()
|
|||||||
val ptbr_wen = Bool(OUTPUT);
|
val ptbr_wen = Bool(OUTPUT);
|
||||||
val irq_timer = Bool(OUTPUT);
|
val irq_timer = Bool(OUTPUT);
|
||||||
val irq_ipi = Bool(OUTPUT);
|
val irq_ipi = Bool(OUTPUT);
|
||||||
val console_data = Bits(8, OUTPUT);
|
|
||||||
val console_val = Bool(OUTPUT);
|
|
||||||
val vecbank = Bits(8, OUTPUT)
|
val vecbank = Bits(8, OUTPUT)
|
||||||
val vecbankcnt = UFix(4, OUTPUT)
|
val vecbankcnt = UFix(4, OUTPUT)
|
||||||
}
|
}
|
||||||
@ -119,11 +117,19 @@ class rocketDpathPCR extends Component
|
|||||||
val reg_status = Cat(reg_status_sx, reg_status_ux, reg_status_s, reg_status_ps, reg_status_ec, reg_status_ev, reg_status_ef, reg_status_et);
|
val reg_status = Cat(reg_status_sx, reg_status_ux, reg_status_s, reg_status_ps, reg_status_ec, reg_status_ev, reg_status_ef, reg_status_et);
|
||||||
val rdata = Wire() { Bits() };
|
val rdata = Wire() { Bits() };
|
||||||
|
|
||||||
io.ptbr_wen := reg_status_vm.toBool && io.w.en && (io.w.addr === PCR_PTBR);
|
val ren = io.r.en || io.host.pcr_ren
|
||||||
|
val raddr = Mux(io.r.en, io.r.addr, io.host.pcr_addr)
|
||||||
|
io.host.pcr_rdata := rdata
|
||||||
|
|
||||||
|
val wen = io.w.en || io.host.pcr_wen
|
||||||
|
val waddr = Mux(io.w.en, io.w.addr, io.host.pcr_addr)
|
||||||
|
val wdata = Mux(io.w.en, io.w.data, io.host.pcr_wdata)
|
||||||
|
io.host.pcr_rdy := Mux(io.host.pcr_wen, !io.w.en, !io.r.en)
|
||||||
|
|
||||||
|
io.ptbr_wen := reg_status_vm.toBool && wen && (waddr === PCR_PTBR);
|
||||||
io.status := Cat(reg_status_vm, reg_status_im, reg_status);
|
io.status := Cat(reg_status_vm, reg_status_im, reg_status);
|
||||||
io.evec := reg_ebase;
|
io.evec := reg_ebase;
|
||||||
io.ptbr := reg_ptbr;
|
io.ptbr := reg_ptbr;
|
||||||
io.host.to := Mux(io.host.from_wen, Bits(0), reg_tohost);
|
|
||||||
io.debug.error_mode := reg_error_mode;
|
io.debug.error_mode := reg_error_mode;
|
||||||
io.r.data := rdata;
|
io.r.data := rdata;
|
||||||
|
|
||||||
@ -133,19 +139,6 @@ class rocketDpathPCR extends Component
|
|||||||
cnt = cnt + reg_vecbank(i)
|
cnt = cnt + reg_vecbank(i)
|
||||||
io.vecbankcnt := cnt(3,0)
|
io.vecbankcnt := cnt(3,0)
|
||||||
|
|
||||||
val console_wen = !io.exception && io.w.en && (io.w.addr === PCR_CONSOLE);
|
|
||||||
io.console_data := Mux(console_wen, io.w.data(7,0), Bits(0,8));
|
|
||||||
io.console_val := console_wen;
|
|
||||||
|
|
||||||
when (io.host.from_wen) {
|
|
||||||
reg_tohost := Bits(0);
|
|
||||||
reg_fromhost := io.host.from;
|
|
||||||
}
|
|
||||||
.elsewhen (io.w.en && (io.w.addr === PCR_TOHOST)) {
|
|
||||||
reg_tohost := io.w.data;
|
|
||||||
reg_fromhost := Bits(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
val badvaddr_sign = Mux(io.w.data(VADDR_BITS-1), ~io.w.data(63,VADDR_BITS) === UFix(0), io.w.data(63,VADDR_BITS) != UFix(0))
|
val badvaddr_sign = Mux(io.w.data(VADDR_BITS-1), ~io.w.data(63,VADDR_BITS) === UFix(0), io.w.data(63,VADDR_BITS) != UFix(0))
|
||||||
when (io.badvaddr_wen) {
|
when (io.badvaddr_wen) {
|
||||||
reg_badvaddr := Cat(badvaddr_sign, io.w.data(VADDR_BITS-1,0)).toUFix;
|
reg_badvaddr := Cat(badvaddr_sign, io.w.data(VADDR_BITS-1,0)).toUFix;
|
||||||
@ -185,37 +178,38 @@ class rocketDpathPCR extends Component
|
|||||||
io.irq_timer := r_irq_timer;
|
io.irq_timer := r_irq_timer;
|
||||||
io.irq_ipi := r_irq_ipi;
|
io.irq_ipi := r_irq_ipi;
|
||||||
|
|
||||||
when (io.w.en) {
|
when (wen) {
|
||||||
when (io.w.addr === PCR_STATUS) {
|
when (waddr === PCR_STATUS) {
|
||||||
reg_status_vm := io.w.data(SR_VM).toBool;
|
reg_status_vm := wdata(SR_VM).toBool;
|
||||||
reg_status_im := io.w.data(15,8);
|
reg_status_im := wdata(15,8);
|
||||||
reg_status_sx := io.w.data(SR_SX).toBool;
|
reg_status_sx := wdata(SR_SX).toBool;
|
||||||
reg_status_ux := io.w.data(SR_UX).toBool;
|
reg_status_ux := wdata(SR_UX).toBool;
|
||||||
reg_status_s := io.w.data(SR_S).toBool;
|
reg_status_s := wdata(SR_S).toBool;
|
||||||
reg_status_ps := io.w.data(SR_PS).toBool;
|
reg_status_ps := wdata(SR_PS).toBool;
|
||||||
reg_status_ev := Bool(HAVE_VEC) && io.w.data(SR_EV).toBool;
|
reg_status_ev := Bool(HAVE_VEC) && wdata(SR_EV).toBool;
|
||||||
reg_status_ef := Bool(HAVE_FPU) && io.w.data(SR_EF).toBool;
|
reg_status_ef := Bool(HAVE_FPU) && wdata(SR_EF).toBool;
|
||||||
reg_status_ec := Bool(HAVE_RVC) && io.w.data(SR_EC).toBool;
|
reg_status_ec := Bool(HAVE_RVC) && wdata(SR_EC).toBool;
|
||||||
reg_status_et := io.w.data(SR_ET).toBool;
|
reg_status_et := wdata(SR_ET).toBool;
|
||||||
}
|
}
|
||||||
when (io.w.addr === PCR_EPC) { reg_epc := io.w.data(VADDR_BITS,0).toUFix; }
|
when (waddr === PCR_EPC) { reg_epc := wdata(VADDR_BITS,0).toUFix; }
|
||||||
when (io.w.addr === PCR_BADVADDR) { reg_badvaddr := io.w.data(VADDR_BITS,0).toUFix; }
|
when (waddr === PCR_BADVADDR) { reg_badvaddr := wdata(VADDR_BITS,0).toUFix; }
|
||||||
when (io.w.addr === PCR_EVEC) { reg_ebase := io.w.data(VADDR_BITS-1,0).toUFix; }
|
when (waddr === PCR_EVEC) { reg_ebase := wdata(VADDR_BITS-1,0).toUFix; }
|
||||||
when (io.w.addr === PCR_COUNT) { reg_count := io.w.data(31,0).toUFix; }
|
when (waddr === PCR_COUNT) { reg_count := wdata(31,0).toUFix; }
|
||||||
when (io.w.addr === PCR_COMPARE) { reg_compare := io.w.data(31,0).toUFix; r_irq_timer := Bool(false); }
|
when (waddr === PCR_COMPARE) { reg_compare := wdata(31,0).toUFix; r_irq_timer := Bool(false); }
|
||||||
when (io.w.addr === PCR_CAUSE) { reg_cause := io.w.data(4,0); }
|
when (waddr === PCR_CAUSE) { reg_cause := wdata(4,0); }
|
||||||
when (io.w.addr === PCR_FROMHOST) { reg_fromhost := io.w.data; }
|
when (waddr === PCR_TOHOST) { reg_tohost := wdata; reg_fromhost := Bits(0) }
|
||||||
when (io.w.addr === PCR_SEND_IPI) { r_irq_ipi := Bool(true); }
|
when (waddr === PCR_FROMHOST) { reg_fromhost := wdata; reg_tohost := Bits(0) }
|
||||||
when (io.w.addr === PCR_CLR_IPI) { r_irq_ipi := Bool(false); }
|
when (waddr === PCR_SEND_IPI) { r_irq_ipi := Bool(true); }
|
||||||
when (io.w.addr === PCR_K0) { reg_k0 := io.w.data; }
|
when (waddr === PCR_CLR_IPI) { r_irq_ipi := Bool(false); }
|
||||||
when (io.w.addr === PCR_K1) { reg_k1 := io.w.data; }
|
when (waddr === PCR_K0) { reg_k0 := wdata; }
|
||||||
when (io.w.addr === PCR_PTBR) { reg_ptbr := Cat(io.w.data(PADDR_BITS-1, PGIDX_BITS), Bits(0, PGIDX_BITS)).toUFix; }
|
when (waddr === PCR_K1) { reg_k1 := wdata; }
|
||||||
when (io.w.addr === PCR_VECBANK) { reg_vecbank := io.w.data(7,0) }
|
when (waddr === PCR_PTBR) { reg_ptbr := Cat(wdata(PADDR_BITS-1, PGIDX_BITS), Bits(0, PGIDX_BITS)).toUFix; }
|
||||||
|
when (waddr === PCR_VECBANK) { reg_vecbank := wdata(7,0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
rdata := Bits(0, 64)
|
rdata := Bits(0, 64)
|
||||||
when (io.r.en) {
|
when (ren) {
|
||||||
switch (io.r.addr) {
|
switch (raddr) {
|
||||||
is (PCR_STATUS) { rdata := Cat(Bits(0,47), reg_status_vm, reg_status_im, reg_status); }
|
is (PCR_STATUS) { rdata := Cat(Bits(0,47), reg_status_vm, reg_status_im, reg_status); }
|
||||||
is (PCR_EPC) { rdata := Cat(Fill(64-VADDR_BITS-1, reg_epc(VADDR_BITS)), reg_epc); }
|
is (PCR_EPC) { rdata := Cat(Fill(64-VADDR_BITS-1, reg_epc(VADDR_BITS)), reg_epc); }
|
||||||
is (PCR_BADVADDR) { rdata := Cat(Fill(64-VADDR_BITS-1, reg_badvaddr(VADDR_BITS)), reg_badvaddr); }
|
is (PCR_BADVADDR) { rdata := Cat(Fill(64-VADDR_BITS-1, reg_badvaddr(VADDR_BITS)), reg_badvaddr); }
|
||||||
|
168
rocket/src/main/scala/htif.scala
Normal file
168
rocket/src/main/scala/htif.scala
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
package Top
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import Node._;
|
||||||
|
import Constants._;
|
||||||
|
|
||||||
|
class ioHost(w: Int, view: List[String] = null) extends Bundle(view)
|
||||||
|
{
|
||||||
|
val in = new ioDecoupled()(Bits(width = w))
|
||||||
|
val out = new ioDecoupled()(Bits(width = w)).flip()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ioHTIF extends Bundle
|
||||||
|
{
|
||||||
|
val reset = Bool(INPUT)
|
||||||
|
val pcr_wen = Bool(INPUT)
|
||||||
|
val pcr_ren = Bool(INPUT)
|
||||||
|
val pcr_rdy = Bool(OUTPUT)
|
||||||
|
val pcr_addr = Bits(5, INPUT)
|
||||||
|
val pcr_wdata = Bits(64, INPUT)
|
||||||
|
val pcr_rdata = Bits(64, OUTPUT)
|
||||||
|
}
|
||||||
|
|
||||||
|
class rocketHTIF(w: Int, ncores: Int) extends Component
|
||||||
|
{
|
||||||
|
val io = new Bundle {
|
||||||
|
val host = new ioHost(w)
|
||||||
|
val cpu = Vec(ncores) { new ioHTIF().flip() }
|
||||||
|
val mem = new ioDCache().flip()
|
||||||
|
}
|
||||||
|
|
||||||
|
val short_request_bits = 64
|
||||||
|
val long_request_bits = 576
|
||||||
|
require(short_request_bits % w == 0)
|
||||||
|
|
||||||
|
val rx_count_w = 13 + log2up(8) - log2up(w) // data size field is 12 bits
|
||||||
|
val rx_count = Reg(resetVal = UFix(0,rx_count_w))
|
||||||
|
val rx_shifter = Reg() { Bits(width = short_request_bits) }
|
||||||
|
val header = Reg() { Bits() }
|
||||||
|
val rx_shifter_in = Cat(io.host.in.bits, rx_shifter(short_request_bits-1,w))
|
||||||
|
when (io.host.in.valid && io.host.in.ready) {
|
||||||
|
rx_shifter := rx_shifter_in
|
||||||
|
rx_count := rx_count + UFix(1)
|
||||||
|
when (rx_count === UFix(short_request_bits/w-1)) {
|
||||||
|
header := rx_shifter_in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val rx_count_words = rx_count >> UFix(log2up(short_request_bits/w))
|
||||||
|
val packet_ram_wen = rx_count(log2up(short_request_bits/w)-1,0).andR &&
|
||||||
|
io.host.in.valid && io.host.in.ready
|
||||||
|
val packet_ram = Mem(long_request_bits/short_request_bits-1,
|
||||||
|
packet_ram_wen, rx_count_words - UFix(1), rx_shifter_in)
|
||||||
|
|
||||||
|
val cmd_readmem :: cmd_writemem :: cmd_readcr :: cmd_writecr :: cmd_ack :: cmd_nack :: Nil = Enum(6) { UFix() }
|
||||||
|
val cmd = header(3,0)
|
||||||
|
val size = header(15,4)
|
||||||
|
val seqno = header(23,16)
|
||||||
|
val addr = header(63,24).toUFix
|
||||||
|
|
||||||
|
val pcr_addr = addr(19,0)
|
||||||
|
val pcr_coreid = addr(39,20)
|
||||||
|
val pcr_wdata = packet_ram(UFix(0))
|
||||||
|
|
||||||
|
val nack = Mux(cmd === cmd_readmem || cmd === cmd_writemem, size != UFix((1 << OFFSET_BITS)/8),
|
||||||
|
Mux(cmd === cmd_readcr || cmd === cmd_writecr, size != UFix(1),
|
||||||
|
Bool(true)))
|
||||||
|
|
||||||
|
val tx_count = Reg(resetVal = UFix(0, log2up(long_request_bits/w+1)))
|
||||||
|
val packet_ram_raddr = (tx_count >> UFix(log2up(short_request_bits/w)))
|
||||||
|
when (io.host.out.valid && io.host.out.ready) {
|
||||||
|
tx_count := tx_count + UFix(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val rx_size = Mux(cmd === cmd_writemem || cmd === cmd_writecr, size, UFix(0))
|
||||||
|
val rx_done = rx_count >= UFix(short_request_bits/w) && rx_count_words-UFix(1) === rx_size
|
||||||
|
val tx_size = Mux(!nack && cmd === cmd_readmem, UFix((1 << OFFSET_BITS)/8),
|
||||||
|
Mux(!nack && cmd === cmd_readcr, UFix(1), UFix(0)))
|
||||||
|
val tx_done = packet_ram_raddr - UFix(1) === tx_size
|
||||||
|
|
||||||
|
val state_rx :: state_pcr :: state_mem_req :: state_mem_resp :: state_tx :: Nil = Enum(5) { UFix() }
|
||||||
|
val state = Reg(resetVal = state_rx)
|
||||||
|
|
||||||
|
when (state === state_rx && rx_done) {
|
||||||
|
state := Mux(cmd === cmd_readmem || cmd === cmd_writemem, state_mem_req,
|
||||||
|
Mux(cmd === cmd_readcr || cmd === cmd_writecr, state_pcr,
|
||||||
|
state_tx))
|
||||||
|
}
|
||||||
|
|
||||||
|
val pcr_done = Reg() { Bool() }
|
||||||
|
when (state === state_pcr && pcr_done) {
|
||||||
|
state := state_tx
|
||||||
|
}
|
||||||
|
|
||||||
|
val mem_cnt = Reg(resetVal = UFix(0, log2up(REFILL_CYCLES)))
|
||||||
|
when (state === state_mem_req && io.mem.req_rdy) {
|
||||||
|
when (cmd === cmd_writemem) {
|
||||||
|
when (mem_cnt.andR) {
|
||||||
|
state := state_tx
|
||||||
|
}
|
||||||
|
mem_cnt := mem_cnt + UFix(1)
|
||||||
|
}
|
||||||
|
.otherwise {
|
||||||
|
state := state_mem_resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when (state === state_mem_resp && io.mem.resp_val) {
|
||||||
|
when (mem_cnt.andR) {
|
||||||
|
state := state_tx
|
||||||
|
}
|
||||||
|
mem_cnt := mem_cnt + UFix(1)
|
||||||
|
}
|
||||||
|
when (state === state_tx && tx_done) {
|
||||||
|
rx_count := UFix(0)
|
||||||
|
tx_count := UFix(0)
|
||||||
|
state := state_rx
|
||||||
|
}
|
||||||
|
|
||||||
|
var mem_req_data: Bits = null
|
||||||
|
for (i <- 0 until MEM_DATA_BITS/short_request_bits) {
|
||||||
|
val idx = Cat(mem_cnt, UFix(i, log2up(MEM_DATA_BITS/short_request_bits)))
|
||||||
|
packet_ram.write(idx, io.mem.resp_data((i+1)*short_request_bits-1, i*short_request_bits),
|
||||||
|
state === state_mem_resp && io.mem.resp_val)
|
||||||
|
mem_req_data = Cat(packet_ram.read(idx), mem_req_data)
|
||||||
|
}
|
||||||
|
io.mem.req_val := state === state_mem_req
|
||||||
|
io.mem.req_rw := cmd === cmd_writemem
|
||||||
|
io.mem.req_addr := addr >> UFix(3)
|
||||||
|
io.mem.req_wdata := mem_req_data
|
||||||
|
|
||||||
|
pcr_done := Bool(false)
|
||||||
|
val pcr_mux = (new Mux1H(ncores)) { Bits(width = 64) }
|
||||||
|
for (i <- 0 until ncores) {
|
||||||
|
val me = pcr_coreid === UFix(i)
|
||||||
|
io.cpu(i).pcr_wen := Reg(state === state_pcr && cmd === cmd_writecr && me, resetVal = Bool(false))
|
||||||
|
io.cpu(i).pcr_addr := Reg(pcr_addr)
|
||||||
|
io.cpu(i).pcr_wdata := Reg(pcr_wdata)
|
||||||
|
|
||||||
|
val my_reset = Reg(resetVal = Bool(true))
|
||||||
|
when (io.cpu(i).pcr_wen && io.cpu(i).pcr_rdy) {
|
||||||
|
when (io.cpu(i).pcr_addr === UFix(15)) { my_reset := io.cpu(i).pcr_wdata(0) }
|
||||||
|
pcr_done := Bool(true)
|
||||||
|
}
|
||||||
|
io.cpu(i).reset := my_reset
|
||||||
|
|
||||||
|
io.cpu(i).pcr_ren := Reg(state === state_pcr && cmd === cmd_readcr && me, resetVal = Bool(false))
|
||||||
|
val rdata = Reg() { Bits() }
|
||||||
|
when (io.cpu(i).pcr_ren && io.cpu(i).pcr_rdy) {
|
||||||
|
rdata := io.cpu(i).pcr_rdata
|
||||||
|
when (io.cpu(i).pcr_addr === UFix(15)) { rdata := my_reset }
|
||||||
|
pcr_done := Bool(true)
|
||||||
|
}
|
||||||
|
pcr_mux.io.sel(i) := Reg(me)
|
||||||
|
pcr_mux.io.in(i) := rdata
|
||||||
|
}
|
||||||
|
|
||||||
|
val tx_cmd = Mux(nack, cmd_nack, cmd_ack)
|
||||||
|
val tx_cmd_ext = Cat(Bits(0, 4-tx_cmd.getWidth), tx_cmd)
|
||||||
|
val tx_size_ext = Cat(Bits(0, 12-tx_size.getWidth), tx_size)
|
||||||
|
val tx_header = Cat(addr, seqno, tx_size_ext, tx_cmd_ext)
|
||||||
|
val tx_data = Mux(packet_ram_raddr === UFix(0), tx_header,
|
||||||
|
Mux(packet_ram_raddr === UFix(1) && cmd === cmd_readcr, pcr_mux.io.out,
|
||||||
|
packet_ram(packet_ram_raddr - UFix(1))))
|
||||||
|
|
||||||
|
io.host.in.ready := state === state_rx && !rx_done
|
||||||
|
io.host.out.valid := state === state_tx && !tx_done
|
||||||
|
io.host.out.bits := tx_data >> Cat(tx_count(log2up(short_request_bits/w)-1,0), Bits(0, log2up(w)))
|
||||||
|
}
|
@ -4,15 +4,17 @@ import Chisel._
|
|||||||
import Node._;
|
import Node._;
|
||||||
import Constants._;
|
import Constants._;
|
||||||
|
|
||||||
class ioTop extends Bundle {
|
class ioTop(htif_width: Int) extends Bundle {
|
||||||
val debug = new ioDebug();
|
val debug = new ioDebug();
|
||||||
val console = new ioConsole();
|
val host = new ioHost(htif_width);
|
||||||
val host = new ioHost();
|
|
||||||
val mem = new ioMem();
|
val mem = new ioMem();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Top() extends Component {
|
class Top() extends Component {
|
||||||
val io = new ioTop();
|
|
||||||
|
val htif_width = 16
|
||||||
|
val io = new ioTop(htif_width);
|
||||||
|
val htif = new rocketHTIF(htif_width, 1)
|
||||||
|
|
||||||
val cpu = new rocketProc();
|
val cpu = new rocketProc();
|
||||||
val icache = new rocketICache(128, 2); // 128 sets x 2 ways
|
val icache = new rocketICache(128, 2); // 128 sets x 2 ways
|
||||||
@ -25,10 +27,11 @@ class Top() extends Component {
|
|||||||
arbiter.io.dcache <> dcache.io.mem;
|
arbiter.io.dcache <> dcache.io.mem;
|
||||||
arbiter.io.icache <> icache_pf.io.mem;
|
arbiter.io.icache <> icache_pf.io.mem;
|
||||||
arbiter.io.vicache <> vicache.io.mem
|
arbiter.io.vicache <> vicache.io.mem
|
||||||
|
arbiter.io.htif <> htif.io.mem
|
||||||
|
|
||||||
cpu.io.host <> io.host;
|
htif.io.host <> io.host
|
||||||
|
cpu.io.host <> htif.io.cpu(0);
|
||||||
cpu.io.debug <> io.debug;
|
cpu.io.debug <> io.debug;
|
||||||
cpu.io.console <> io.console;
|
|
||||||
|
|
||||||
icache_pf.io.invalidate := cpu.io.imem.invalidate
|
icache_pf.io.invalidate := cpu.io.imem.invalidate
|
||||||
icache.io.mem <> icache_pf.io.icache;
|
icache.io.mem <> icache_pf.io.icache;
|
||||||
|
Loading…
Reference in New Issue
Block a user