Skip to content

Commit

Permalink
fixes to ice-v-ram (muldiv), swirl (refetch during stall), trace outp…
Browse files Browse the repository at this point in the history
…ut for both
  • Loading branch information
sylefeb committed Nov 4, 2023
1 parent d1030ae commit 3796492
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 71 deletions.
83 changes: 23 additions & 60 deletions projects/ice-v/CPUs/ice-v-ram.si
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ $$end
// --------------------------------------------------

$$if SIMULATION then
$$VERBOSE = nil
$$TRACE = nil
$$end

$$ print("--------------- Ice-V-ram ---------------")
Expand Down Expand Up @@ -124,10 +124,10 @@ $$end
// uint1 load_store <: (exec.load | exec.store);


$$if VERBOSE then
$$if TRACE then
uint32 cycle(0);
uint32 last_cycle(0);
uint1 debug(0);
uint1 trace(0);
$$end

int32 write_back(0);
Expand All @@ -143,12 +143,6 @@ $$end

// always block, done every cycle
always {
$$if VERBOSE then
if (~reset) {
//__display("\n[cycle %d] ---------------- stage: %b ----- exec.working:%b mem.done:%b(%b|%b)=%h(@%h)",cycle,stage,exec.working,mem.done,reqmem,reqmem_done,mem.rdata,mem.addr);
//__display("[cycle %d] RAM, reqmem_done:%d, reqmem: %b",cycle,reqmem_done,reqmem);
}
$$end
// maintain request valid low
mem.req_valid = 0;
do_load_store = 0;
Expand Down Expand Up @@ -182,10 +176,6 @@ $$end
// (pulsed when necessary)
xregsA.wenable = 0;

$$if VERBOSE then
// __display("[cycle %d] ====== stage:%b reset:%b pc:%h mem.done:%b",cycle,stage,reset,pc,mem.done);
$$end

// four states: F, T, LS1, LS2/commit
onehot (stage) {
case 0: {
Expand All @@ -195,22 +185,13 @@ $$end
pc = reqmem_done ? mem.addr : pc;
// instruction fetch done?
instr_trigger = reqmem_done;
$$if VERBOSE then
$$if TRACE then
if (instr_trigger) {
//if (cycle-last_cycle < 18) {
__display("[cycle %d] (0) F instr:%h (@%h) [elapsed: %d cycles]",cycle,instr,pc<<2,cycle-last_cycle);
debug = 1;
//}
last_cycle = cycle;
trace = 1;
}
$$end
}
case 1: {
$$if VERBOSE then
if (instr_trigger) {
// __display("[cycle %d] (0) T %h @%h xa[%d]=%h xb[%d]=%h",cycle,instr,pc,xregsA.addr,xregsA.rdata,xregsB.addr,xregsB.rdata);
}
$$end
// ---- T
// registers are now in, triggers exec
exec.trigger = instr_trigger;
Expand All @@ -229,26 +210,24 @@ $$end
mem.wenable = exec.store;
mem.byte_size = 1 << exec.op[0,2]; // gives 4,2 or 1
mem.byte_offset = exec.n[0,2];
$$if VERBOSE then
if (debug) {
// __display("[cycle %d] load: %b store: %b",cycle,exec.load,exec.store);
if (mem.req_valid) {
// __display("[cycle %d] (0) LS1(%b) @%h = %h (wen:%b)",cycle,mem.req_valid,mem.addr,mem.wdata,mem.wenable);
}
}
$$end
}
case 3: {
// ---- LS2/commit
// may wait on RAM
// commit result
xregsA.wenable = ~exec.no_rd & ~reqmem_pending;
// ^^^^^^^^^^^^^^
// wait on RAM if request pending
$$if VERBOSE then
if (xregsA.wenable & debug) {
__display("[cycle %d] (0) LS2/C xr[%d]=%h (mem.rdata:%x)",cycle,exec.write_rd,write_back,mem.rdata);
debug = 0;
xregsA.wenable = ~exec.no_rd & ~reqmem_pending & ~exec.working;
// ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
// wait on RAM if request pending wait on working ALU
$$if TRACE then
if (trace & ~reqmem_pending & ~exec.working) {
__write("instr:%h (@%h) ",instr,pc<<2);
last_cycle = cycle;
if (xregsA.wenable) {
__display(" x[%d]=%h",exec.write_rd,write_back);
} else {
__display("");
}
trace = 0;
}
$$end
// prepare instruction fetch
Expand All @@ -257,7 +236,7 @@ $$end
// ^^^^^^^^^^^^^^
// wait on RAM from load/store
mem.addr = do_fetch ? (exec.jump ? (exec.n >> 2) : pc_plus1)
: mem.addr; // <= preserve addr is RAM is busy
: mem.addr; // <= preserve addr if RAM is busy
mem.req_valid = do_fetch;
}
}
Expand All @@ -276,22 +255,18 @@ $$end
// ^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^
// on fetch, on load/store, or previous still active

$$if VERBOSE then
// if (reset) { __display("[cycle %d] reset (reqmem:%b reqmem_done:%b)",cycle,reqmem,reqmem_done); }
$$end

// write back data to both register BRAMs
xregsA.wdata = write_back; xregsB.wdata = write_back;
// xregsB written when xregsA is
xregsB.wenable = xregsA.wenable;
// write to write_rd, else track instruction register
xregsA.addr = xregsA.wenable ? exec.write_rd : Rtype(instr).rs1;
xregsB.addr = xregsA.wenable ? exec.write_rd : Rtype(instr).rs2;
$$if VERBOSE then
// __display("[cycle %d] mem @%h (req:%b pending:%b) w:%b ",cycle,mem.addr,mem.req_valid,reqmem_pending,mem.wenable);
$$end

$$if VERBOSE then
$$if TRACE then
if (mem.wenable) {
__display("store @%x = %x",mem.addr<<2,mem.wdata<<{mem.byte_offset,3b000});
}
cycle = cycle + 1;
$$end

Expand Down Expand Up @@ -366,12 +341,6 @@ $$end
always {
uint1 j(0); // temp variables for and comparator

$$if VERBOSE then
if (trigger) {
// __display("[cycle %d] %h @%h xa=%h xb=%h",cycle,instr,pc,xa,xb);
}
$$end

// ==== set decoder outputs depending on incoming instructions
// load/store?
load = opcode == 5b00000; store = opcode == 5b01000;
Expand Down Expand Up @@ -461,12 +430,6 @@ $$if ICEV_MULDIV then
}
$$end

$$if VERBOSE then
if (trigger) {
// __display("[cycle %d] load %b store %b",cycle,load,store);
}
$$end

// ====================== Comparator for branching
switch (op[1,2]) {
case 2b00: { j = a_eq_b; } /*BEQ */ case 2b10: { j=a_lt_b;} /*BLT*/
Expand Down
55 changes: 44 additions & 11 deletions projects/ice-v/CPUs/ice-v-swirl.si
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ $$end
$$ICEV_BRANCH_PRED = 1

// set to 1 for a copious amount of debug output in simulation
$$DEBUG_swirl = nil
$$DEBUG_swirl = nil
$$TRACE_swirl = nil

// --------------------------------------------------
// bitfield for easier decoding of instructions
Expand Down Expand Up @@ -146,14 +147,19 @@ $$end
$$if SIMULATION then
uint32 cycle(0); uint32 reinstr(0);
$$end
$$if TRACE_swirl then
uint32 last_cycle(0);
$$end
$$if not ICEV_STALL then
uint1 stall_cpu(0); // stall disabled, never used
uint1 stall_cpu(0); // stall disabled, never used
$$else
uint1 refetching(0); // tracks if a refetch is in progress
$$end

always {

$$if DEBUG_swirl then
uint1 debug_on = 1;
uint1 debug_on = 1; // (cycle > 88430 && cycle < 90000);
$$end

// tracks whether a register was written cycle before
Expand All @@ -177,7 +183,7 @@ $$if ICEV_BRANCH_PRED then
$$end
$$if DEBUG_swirl then
if (debug_on) {
__display("[1] cycle:%d stall_cpu:%b refetch:%b refetch_addr:%x pc:%x",cycle,stall_cpu,refetch,refetch_addr<<2,pc<<2);
__display("[1] cycle:%d stall_cpu:%b refetch:%b refetch_addr:%x refetching:%b pc:%x",cycle,stall_cpu,refetch,refetch_addr<<2,refetching,pc<<2);
__display("[1] cycle:%d imem.addr:%x imem.rdata:%x dmem.addr:%x dmem.rdata:%x",cycle,imem.addr<<2,imem.rdata,dmem.addr<<2,dmem.rdata);
}
$$end
Expand Down Expand Up @@ -308,6 +314,7 @@ if (debug_on) {
}
$$end
xb_regR = 0; xb_regW = 0; xb_regW_prev = 1; xb_keep = 0; // same for rs2
// ^^^^^^^^^^^^^ selects value previously written
}
// [data hazards] case (b) detection
// instruction in stage 4 writes on a register used now
Expand All @@ -322,6 +329,7 @@ if (debug_on) {
}
$$end
xa_regR = 0; xa_regW = 1; xa_regW_prev = 0; xa_keep = 0;
// ^^^^^^^^^^^ selects value being written
}
if (~no_rd & (Rtype(instr).rs2 == rd) & has_rs2) { // same for rs2
$$if DEBUG_swirl then
Expand Down Expand Up @@ -425,20 +433,40 @@ if (debug_on) {
__display("[4] wreg:[%d]=%x",Rtype(instr).rd,xregsA.wdata1);
}
}
$$end
$$if TRACE_swirl then
if (instr_done) {
__write("instr:%h (@%h) ",instr,pc<<2);
last_cycle = cycle;
if (xregsA.wenable1) {
__display(" x[%d]=%h",xregsA.addr1,xregsA.wdata1);
} else {
__display("");
}
}
$$end

// signal a jump if needed (flushes pipeline and jumps)
refetch = stall_cpu // on a stall trigger (and hold) a refetch
| ( ( jump ^ bpred ) // jump prediction failed
& ~refetch & ~bubble );
// ^^^^^^ reset refetch if done at prev cycle
$$if ICEV_STALL then
// indicates whether a refetch is in progress
// (on a stall, refetch at the ongoing refetch if one is in progress)
uint1 was_refetching = refetching & ~instr_done;
refetching = refetch | was_refetching;
$$end
jumping ^= refetch; // warn stage 3 (cancel any store)
exec.cancel = refetch; // cancel any pending ALU op on refetch
// new address on refetch
refetch_addr = (stall_cpu & ~on_stall) ? refetch_addr // fix pc
refetch_addr = ~refetch | was_refetching | (stall_cpu & ~on_stall) ? refetch_addr // keep the refetch_addr
: jump ? (alu_n>>2) // jump destination
: instr_done ? pcp1 // next by address
: pc; // stay on same
: pc; // stay on same
//if (debug_on || ((pc<<2) == 32h0b50)) {
// __display("[!] cycle:%d refetch:%b (jump:%b pred:%b) refetch_addr:%h on_stall:%b",cycle,refetch,jump,bpred,refetch_addr<<2,on_stall);
//}

$$if DEBUG_swirl then
if (debug_on) {
Expand Down Expand Up @@ -467,7 +495,7 @@ $$end
| xb_regW_prev ? xregsB.wdata1 : 32b0;
// what to write on a store
dmem.wdata = stall_cpu ? dmem.wdata
: (xb_regW ? xregsA.wdata1 : xb) << {exec.n[0,2],3b000};
: (/*xb_regW ? xregsA.wdata1 :*/ xb) << {exec.n[0,2],3b000};
// ^^---------\
// capture xb from stage 2 so that stage 3 assign above sees the correct value
$$if DEBUG_swirl then
Expand All @@ -477,7 +505,12 @@ if (debug_on) {
}
}
$$end
xb = exec.xb;
$$if TRACE_swirl then
if ((|dmem.wenable) & ~stall_cpu) {
__display("store @%x = %x",dmem.addr<<2,dmem.wdata);
}
$$end
xb = exec.xb;
// register bank B follows A writes
xregsB.wenable1 = xregsA.wenable1;
xregsB.wdata1 = xregsA.wdata1;
Expand Down Expand Up @@ -634,16 +667,16 @@ $$ end
case 3b100: { // DIV
if (trigger) {
$$if DEBUG_swirl then
__display("[cycle %d] DIVISION trigger",cycle);
//__display("[cycle %d] DIVISION trigger",cycle);
$$end
working = 1;
dividing = 1;
div <- (xa,xb);
} else {
if (isdone(div) & dividing) {
$$if DEBUG_swirl then
__display("[cycle %d] DIVISION %d / %d = %d",cycle,
div.inum,div.iden,div.ret);
//__display("[cycle %d] DIVISION %d / %d = %d",cycle,
// div.inum,div.iden,div.ret);
$$end
dividing = 0;
working = 0;
Expand Down

0 comments on commit 3796492

Please sign in to comment.