Skip to content

Commit

Permalink
fixed issue in ice-v swirl with div
Browse files Browse the repository at this point in the history
  • Loading branch information
sylefeb committed Dec 2, 2023
1 parent 49448be commit 2ef82e5
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 39 deletions.
22 changes: 22 additions & 0 deletions frameworks/templates/simple_dualport_bram_generic_rw.v.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SL 2019, MIT license
module %MODULE%(
input [%ADDR0_WIDTH%-1:0] in_addr0,
output reg %DATA_TYPE% [%DATA_WIDTH%-1:0] out_rdata0,
output reg %DATA_TYPE% [%DATA_WIDTH%-1:0] out_rdata1,
input [%WENABLE1_WIDTH%-1:0] in_wenable1,
input [%DATA_WIDTH%-1:0] in_wdata1,
input [%ADDR1_WIDTH%-1:0] in_addr1,
input clock0,
input clock1
);
reg %DATA_TYPE% [%DATA_WIDTH%-1:0] buffer[%DATA_SIZE%-1:0];
always @(posedge clock0) begin
out_rdata0 <= buffer[in_addr0];
end
always @(posedge clock1) begin
if (in_wenable1) begin
buffer[in_addr1] <= in_wdata1;
end
end
%INITIAL%
endmodule
4 changes: 3 additions & 1 deletion get_started_mingw64.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ pacman -S --noconfirm --needed ${MINGW_PACKAGE_PREFIX}-glfw

# -------------- retrieve oss-cad-suite package --------------
OSS_CAD_MONTH=11
OSS_CAD_DAY=15
OSS_CAD_DAY=29
OSS_CAD_YEAR=2023

rm -rf tools/fpga-binutils/
rm -rf tools/oss-cad-suite/
wget -c https://github.com/YosysHQ/oss-cad-suite-build/releases/download/$OSS_CAD_YEAR-$OSS_CAD_MONTH-$OSS_CAD_DAY/oss-cad-suite-windows-x64-$OSS_CAD_YEAR$OSS_CAD_MONTH$OSS_CAD_DAY.exe
cd tools ; ../oss-cad-suite-windows-x64-$OSS_CAD_YEAR$OSS_CAD_MONTH$OSS_CAD_DAY.exe ; cd -

Expand Down
59 changes: 32 additions & 27 deletions projects/ice-v/CPUs/ice-v-ram.si
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ $$ cycleW = 32

$$if ICEV_MULDIV then
$$ print("Ice-V-ram configured with mul and div (*not* full RV32IM)")
$$div_width = 32
$$div_signed = 1
$$div_width = 32
$$div_unsigned = 1
$$div_remainder = 1
$include('../../common/divint_std.si')
$$end

Expand Down Expand Up @@ -415,32 +416,36 @@ $$end

$$if ICEV_MULDIV then
// mul div
uint1 mulh = op[0,2] == 2b01;
uint1 mulhsu = op[0,2] == 2b10;
uint1 signa = xa[31,1];
uint1 signb = xb[31,1]; // vvvvvvvvvv keep the sign?
int33 ma = {signa & (mulh | mulhsu), xa};
int33 mb = {signb & mulh, xb};
int64 mul = ma * mb; // multiply
uint1 signdiv = ~ op[0,1];
uint1 divdone = isdone(div) & ~prev_divdone; // pulses on div done
uint1 prev_divdone = isdone(div);
//if (muldiv & working & divdone) {
// __display("DIVISION %d / %d = %d (%d)\n",div.inum,div.iden,div.ret,div.rem);
//}
working = (working | (trigger & op[2,1]))
& muldiv
& ~(working & divdone);
if (trigger) { // div restarts each trigger
div.inum = (signdiv&signa) ? -xa : xa;
div.iden = (signdiv&signb) ? -xb : xb;
div <- ();
}
uint1 div_negate = signdiv & (signa ^ signb);
uint1 ret_h = |op[0,2];
if (muldiv) {
// __display("[cycle %d] dividing:%b working:%b isdone(div):%b",cycle,dividing,working,isdone(div));
switch ({op}) {
case 3b000: { // MUL
// __display("MULTIPLICATION %d * %d",xa,xb);
r = xa * xb;
}
case 3b100: { // DIV
if (trigger) {
// __display("[cycle %d] DIVISION trigger",cycle);
working = 1;
dividing = 1;
div <- (xa,xb);
} else {
if (isdone(div) & dividing) {
// __display("[cycle %d] DIVISION %d / %d = %d",cycle,div.inum,div.iden,div.ret);
dividing = 0;
working = 0;
}
}
r = div.ret;
}
default: { r = {32{1bx}}; }
}
} else {
dividing = 0;
r = ((~op[2,1] & ret_h) ? mul[32,32] : 32b0) // MULH, MULHSU, MULHU
| ((~op[2,1] & ~ret_h) ? mul[ 0,32] : 32b0) // MUL
| (( op[2,1] & div_negate & op[1,1] ) ? -div.rem : 32b0) // REM
| (( op[2,1] & ~div_negate & op[1,1] ) ? div.rem : 32b0) // REMU
| (( op[2,1] & div_negate & ~op[1,1] ) ? -div.ret : 32b0) // DIV
| (( op[2,1] & ~div_negate & ~op[1,1] ) ? div.ret : 32b0);// DIVU
}
$$end

Expand Down
25 changes: 14 additions & 11 deletions projects/ice-v/CPUs/ice-v-swirl.si
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,13 @@ $$if ICEV_STALL then
input uint1 stall_cpu,
$$end
$$if TRACE_swirl then
// input uint1 trace_on,
input uint1 trace_on,
$$end
) {

// register file, uses two BRAMs to fetch two registers at once
//simple_dualport_bram int32 xregsA<"simple_dualport_bram_generic_rw">[32] = {pad(0)};
//simple_dualport_bram int32 xregsB<"simple_dualport_bram_generic_rw">[32] = {pad(0)};
simple_dualport_bram int32 xregsA[32] = {pad(0)};
simple_dualport_bram int32 xregsB[32] = {pad(0)};
// ^^^^^^^^^^^^^ dualport so that we can read/write simultaneously
Expand Down Expand Up @@ -163,7 +165,6 @@ $$if SIMULATION then
$$end
$$if TRACE_swirl then
uint32 last_cycle(0);
uint1 trace_on <:: nretired > 3145018;
$$end
$$if not ICEV_STALL then
uint1 stall_cpu(0); // stall disabled, never used
Expand All @@ -173,7 +174,7 @@ $$end
always {

$$if DEBUG_swirl then
uint1 debug_on = cycle > 106191974; // cycle > 284400; // nretired > 3145018;
uint1 debug_on = 1
$$end

// tracks whether a register was written cycle before
Expand Down Expand Up @@ -261,9 +262,10 @@ $$end
| (Rtype(instr).opcode[2,5] == 5b11000) // branch
| store;
// by default we select the register value read after stage 1
// (assuming no data haward)
xa_regR = ~hold; xa_regW = 0; xa_regW_prev = 0; xa_keep = hold;
xb_regR = ~hold; xb_regW = 0; xb_regW_prev = 0; xb_keep = hold;
// or keep the values as is on a hold or alu is working
uint1 keep = hold | exec.working;
xa_regR = ~keep; xa_regW = 0; xa_regW_prev = 0; xa_keep = keep;
xb_regR = ~keep; xb_regW = 0; xb_regW_prev = 0; xb_keep = keep;
// [data hazards] case (c) detection
// instruction in stage 3 will (cycle+2) write on a register needed now
// instruction in stage 4 will (cycle+1) write on a register needed now
Expand Down Expand Up @@ -302,6 +304,9 @@ if (debug_on) {
$$end
// update bubble
bubble = bubble | refetch | hold;
$$if SIMULATION then
stage2_bubble = bubble;
$$end
$$if DEBUG_swirl then
if (debug_on) {
if (~stall_cpu | on_stall) {
Expand Down Expand Up @@ -364,9 +369,6 @@ $$end
// trigger ALU if not in bubble (used by multi-cycle shifts, div)
exec.trigger = ~bubble & ~alu_was_working;
uint1 alu_was_working = exec.working;
$$if SIMULATION then
stage2_bubble = bubble;
$$end
} -> { // ==== stage 3 =====================================================
uint1 prev_bpred(0);
// propagate bpred
Expand Down Expand Up @@ -576,17 +578,18 @@ $$if TRACE_swirl then
}
}
$$end

// register bank B follows A writes
xregsB.wenable1 = xregsA.wenable1;
xregsB.wdata1 = xregsA.wdata1;
xregsB.addr1 = xregsA.addr1;
$$if SIMULATION then
if (xregsA_conflict_possible & xa_regR & ~stage2_bubble) {
__display("[cycle %d] ERROR reading from a written register (A)",cycle);
__display("[cycle %d] ERROR reading from a written register (A) @%h",cycle,pc<<2);
__finish();
}
if (xregsB_conflict_possible & xb_regR & ~stage2_bubble & has_rs2) {
__display("[cycle %d] ERROR reading from a written register (B)",cycle);
__display("[cycle %d] ERROR reading from a written register (B) @%h",cycle,pc<<2);
__finish();
}
$$end
Expand Down

0 comments on commit 2ef82e5

Please sign in to comment.