diff --git a/projects/common/divint_std.si b/projects/common/divint_std.si index c76d0451..b2ec8bdd 100644 --- a/projects/common/divint_std.si +++ b/projects/common/divint_std.si @@ -14,7 +14,11 @@ $$div_width_pow2 = clog2(div_width) algorithm div$div_width$( input int$div_width$ inum, input int$div_width$ iden, - output int$div_width$ ret = 0) + output int$div_width$ ret = 0, +$$if div_remainder then + output int$div_width$ rem = 0, +$$end + ) { uint$div_width+1$ ac = uninitialized; uint$div_width+1$ diff <:: ac - :den; @@ -54,4 +58,7 @@ $$end $$if not div_unsigned then ret = ((inum_neg) ^ (iden_neg)) ? -ret : ret; $$end +$$if div_remainder then + rem = ac[1,$div_width$]; +$$end } diff --git a/projects/ice-v/CPUs/ice-v-swirl.si b/projects/ice-v/CPUs/ice-v-swirl.si index 80b2a40f..5f30bebb 100644 --- a/projects/ice-v/CPUs/ice-v-swirl.si +++ b/projects/ice-v/CPUs/ice-v-swirl.si @@ -17,16 +17,17 @@ $$end $$if ICEV_MULDIV then $$ print("Ice-V-swirl 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 -$$ICEV_BRANCH_PRED = 1 +$$ICEV_BRANCH_PRED = 1 // set to 1 for a copious amount of debug output in simulation -$$DEBUG_swirl = nil -$$TRACE_swirl = nil +$$DEBUG_swirl = 1 +$$TRACE_swirl = nil // -------------------------------------------------- // bitfield for easier decoding of instructions @@ -161,7 +162,7 @@ $$end always { $$if DEBUG_swirl then - uint1 debug_on = 0; // (cycle > 40333206) && (cycle < 40339206); + uint1 debug_on = 1; // (cycle > 40333206) && (cycle < 40339206); $$end // tracks whether a register was written cycle before @@ -673,34 +674,44 @@ $$ if not ICEV_FAST_SHIFT then $$ error('ICEV_MULDIV requires ICEV_FAST_SHIFT') $$ end // mul div + uint1 mulh = op == 3b001; + uint1 mulhsu = op == 3b010; + 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 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) { + if (~op[2,1]) { + // MUL, MULH, MULHSU, MULHU + r = (|op[0,2]) ? mul[32,32] : mul[0,32]; + } else { + // DIV, DIVU, REM, REMU + if (trigger) { + $$if DEBUG_swirl then + //__display("[cycle %d] DIVISION trigger",cycle); + $$end + working = 1; + dividing = 1; + div <- ( signa?-xa:xa, signb?-xb:xb ); + } else { + if (isdone(div) & dividing) { $$if DEBUG_swirl then - //__display("[cycle %d] DIVISION trigger",cycle); + __display("[cycle %d] DIVISION %d / %d = %d",cycle, + div.inum,div.iden,div.ret); $$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); - $$end - dividing = 0; - working = 0; - } + dividing = 0; + working = 0; } - r = div.ret; } - default: { r = {32{1bx}}; } + // division result + uint1 div_negate = ~ op[0,1]/*DIVU*/ & (signa ^ signb) /*DIV*/; + if (op[1,1]) { // REM,REMU + r = div_negate ? -div.rem : div.rem; + } else { // DIV,DIVU + r = div_negate ? -div.ret : div.ret; + } } } else { dividing = 0; @@ -709,7 +720,7 @@ $$ end $$end // ====================== Comparator for branching switch (op[1,2]) { - case 2b00: { j = a_eq_b; } /*BEQ */ case 2b10: { j=a_lt_b;} /*BLT*/ + case 2b00: { j = a_eq_b; } /*BEQ */ case 2b10: { j = a_lt_b;} /*BLT*/ case 2b11: { j = a_lt_b_u;} /*BLTU*/ default: { j = 1bx; } } jump = (JAL | JALR) | (branch & (j ^ op[0,1])); diff --git a/projects/ice-v/SOCs/ice-v-soc-swirl-cache.si b/projects/ice-v/SOCs/ice-v-soc-swirl-cache.si index 00f69807..f7b2720e 100644 --- a/projects/ice-v/SOCs/ice-v-soc-swirl-cache.si +++ b/projects/ice-v/SOCs/ice-v-soc-swirl-cache.si @@ -255,7 +255,7 @@ $$end algorithm { $$if SIMULATION and not BARE then //while (1) { } - while (cycle < 1000000) { } + while (cycle < 4000) { } __display("stopping at cycle %d",cycle); $$else while (1) { } diff --git a/projects/ice-v/compile/icebreaker/swirl-cache/compile_asm.sh b/projects/ice-v/compile/icebreaker/swirl-cache/compile_asm.sh new file mode 100644 index 00000000..d3d9ab07 --- /dev/null +++ b/projects/ice-v/compile/icebreaker/swirl-cache/compile_asm.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +export PATH=$PATH:$DIR/../../tools/fpga-binutils/mingw32/bin/ + +source ../../tools/bash/find_riscv.sh + +echo "using $ARCH" + +BASE=./compile/icebreaker/swirl-cache +DST=./compile/build + +$ARCH-as.exe -march=rv32im -mabi=ilp32 -o $DST/code.o $1 +$ARCH-ld.exe -m elf32lriscv -b elf32-littleriscv -T$BASE/config_c.ld --no-relax -o $DST/code.elf $DST/code.o +$ARCH-objcopy.exe -O verilog $DST/code.elf $DST/code.hex + +$ARCH-objcopy.exe -O binary $DST/code.elf $DST/code.bin +$ARCH-objdump.exe -D -b binary -m riscv $DST/code.bin diff --git a/projects/ice-v/src/test_div.s b/projects/ice-v/src/test_div.s new file mode 100644 index 00000000..2b54ca18 --- /dev/null +++ b/projects/ice-v/src/test_div.s @@ -0,0 +1,12 @@ +.globl _start + +_start: + + addi t1, zero, 123 + addi t2, zero,-10 + div t3, t1, t2 + rem t3, t1, t2 + divu t3, t1, t2 + remu t3, t1, t2 + +jal _start