Reduces LUT needed by mul extension

This commit is contained in:
2025-11-14 19:08:41 +01:00
parent ca03b29774
commit e55c3fde14
22 changed files with 923 additions and 241 deletions

View File

@@ -50,7 +50,7 @@ OBJCOPY := $(PREFIX)objcopy
OBTOMEM := common/objtomem.awk
## Flags
ASFLAGS :=-march=rv64i -mabi=lp64 -ffreestanding -nostdlib -T $(BENCH_DIR)/link.ld
ASFLAGS :=-march=rv64im -mabi=lp64 -ffreestanding -nostdlib -T $(BENCH_DIR)/link.ld
CFLAGS :=$(ASFLAGS)
ELFFLAGS :=$(ASFLAGS) $(MEM_DIR)/crt.o -Os -fno-unroll-loops
ODFLAGS :=-j .text -j .rodata -j .data -s

View File

@@ -1,25 +1,60 @@
# expected: ffffffffffffffff, ffffffffffffffff, dead0, 1, 8000000000000000, 7
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, (-2355)
li x8, (-324)
li x9, 0x8000000000000000
li x2, 0xdead0 # 912080
li x3, 0x1234 # 4660
li x4, 1 # 1
li x5, -123456 # -123456
li x6, 0xdead0 # duplicate of x2
li x7, -765432 # -765432
li x8, 123456 # 123456
li x9, -234567 # -234567
li x10, 0x7fffffffffffffff # max positive 64b
li x11, 0x8000000000000000 # min negative 64b
# Div by 0
div x31, x2, x3
div x31, x5, x3
# Basic divisions
# 1. DIV : a / 1
div x31, x2, x4
# expected: 00000000000dead0
# 2. DIV : a / a
div x31, x2, x6
# expected: 0000000000000001
# Overflow
div x31, x9, x5
# 3. DIV : negative / positive
div x31, x5, x8
# expected: ffffffffffffffff
# Signed / signed
# 4. DIV : negative / positive
div x31, x7, x8
# expected: fffffffffffffffa
# 5. DIV : positive / negative
div x31, x8, x7
# expected: 0000000000000000
# 6. DIV : negative / negative
div x31, x7, x9
# expected: 0000000000000003
# 7. DIV : max / 2
li x12, 2
div x31, x10, x12
# expected: 3fffffffffffffff
# 8. DIV : min / -1
li x12, -1 # -1
div x31, x11, x12
# expected: 8000000000000000
# 9. DIV : min / 1
div x31, x11, x4
# expected: 8000000000000000
# 10. DIV : 0 / any
div x31, x3, x2
# expected: 0000000000000000
# 11. DIV : any / 0
div x31, x2, x0
# expected: ffffffffffffffff
div x31, x7, x0
# expected: ffffffffffffffff

View File

@@ -1,14 +1,55 @@
# expected: ffffffffffffffff, dead0, 1
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x6, 0xdead0
li x2, 0xdead0 # 912080
li x3, 0x1234 # 4660
li x4, 1 # 1
li x5, 123456 # 123456
li x6, 0xdead0 # duplicate of x2
li x7, 765432 # 765432
li x8, 123456 # 123456
li x9, 234567 # 234567
li x10, 0x7fffffffffffffff # max positive 64b
li x11, 0x8000000000000000 # min negative 64b (treated as unsigned = 0x8000...)
# Div by 0
divu x31, x2, x3
# Basic divisions
# 1. DIVU : a / 1
divu x31, x2, x4
# expected: 00000000000dead0
# 2. DIVU : a / a
divu x31, x2, x6
# expected: 0000000000000001
# 3. DIVU : smaller / larger
divu x31, x5, x8
# expected: 0000000000000001
# 4. DIVU : larger / smaller
divu x31, x7, x8
# expected: 0000000000000006
# 5. DIVU : any / any
divu x31, x8, x7
# expected: 0000000000000000
# 6. DIVU : larger / larger
divu x31, x7, x9
# expected: 0000000000000003
# 7. DIVU : max / 2
li x12, 2
divu x31, x10, x12
# expected: 3fffffffffffffff
# 8. DIVU : min / 1
divu x31, x11, x4
# expected: 8000000000000000
# 9. DIVU : 0 / any
divu x31, x3, x2
# expected: 0000000000000000
# 10. DIVU : any / 0
divu x31, x2, x0
# expected: ffffffffffffffff
divu x31, x7, x0
# expected: ffffffffffffffff

View File

@@ -1,14 +1,55 @@
# expected: ffffffffffffffff, dead0, 1
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x6, 0xdead0
li x2, 0xdead0 # 912080
li x3, 0x1234 # 4660
li x4, 1 # 1
li x5, -123456 # 0xfffe1dc0 (4294843840)
li x6, 0xdead0 # duplicate of x2
li x7, -765432 # 0xffed32b8 (4294201864)
li x8, 123456 # 123456
li x9, -234567 # 0xfffc7239 (4294732729)
li x10, 0xffffffff # max unsigned 32b (4294967295)
li x11, 0x80000000 # 2147483648
# Div by 0
divuw x31, x2, x3
# Basic divisions
# 1. DIVUW : a / 1
divuw x31, x2, x4
# expected: 000000000000dead0
# 2. DIVUW : a / a
divuw x31, x2, x6
# expected: 0000000000000001
# 3. DIVUW : unsigned(0xfffe1dc0) / 123456
divuw x31, x5, x8
# expected: 00000000000087e4
# 4. DIVUW : unsigned(0xffed32b8) / 123456
divuw x31, x7, x8
# expected: 00000000000087df
# 5. DIVUW : unsigned(123456) / unsigned(0xffed32b8)
divuw x31, x8, x7
# expected: 0000000000000000
# 6. DIVUW : unsigned(x7) / unsigned(x9)
divuw x31, x7, x9
# expected: 0000000000000000
# 7. DIVUW : max32 / 2
li x12, 2
divuw x31, x10, x12
# expected: 000000007fffffff
# 8. DIVUW : min32 / 1
divuw x31, x11, x4
# expected: ffffffff80000000
# 9. DIVUW : 0 / any
divuw x31, x0, x2
# expected: 0000000000000000
# 10. DIVUW : any / 0
divuw x31, x2, x0
# expected: ffffffffffffffff
divuw x31, x7, x0
# expected: ffffffffffffffff

View File

@@ -1,25 +1,60 @@
# expected: ffffffffffffffff, ffffffffffffffff, dead0, 1, ffffffff80000000, 7
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, (-2355)
li x8, (-324)
li x9, 0x80000000
li x2, 0xdead0 # 912080
li x3, 0x1234 # 4660
li x4, 1 # 1
li x5, -123456 # -123456
li x6, 0xdead0 # duplicate of x2
li x7, -765432 # -765432
li x8, 123456 # 123456
li x9, -234567 # -234567
li x10, 0x7fffffff # max positive 32b
li x11, 0x80000000 # min negative 32b
# Div by 0
divw x31, x2, x3
divw x31, x5, x3
# Basic divisions
# 1. DIVW : a / 1
divw x31, x2, x4
# expected: 000000000000dead0
# 2. DIVW : a / a
divw x31, x2, x6
# expected: 0000000000000001
# Overflow
divw x31, x9, x5
# 3. DIVW : negative / positive
divw x31, x5, x8
# expected: ffffffffffffffff
# Signed / signed
# 4. DIVW : negative / positive
divw x31, x7, x8
# expected: fffffffffffffffa
# 5. DIVW : positive / negative
divw x31, x8, x7
# expected: 0000000000000000
# 6. DIVW : negative / negative
divw x31, x7, x9
# expected: 0000000000000003
# 7. DIVW : max / 2
li x12, 2
divw x31, x10, x12
# expected: 000000003fffffff
# 8. DIVW : min / -1
li x12, -1 # -1
divw x31, x11, x12
# expected: ffffffff80000000
# 9. DIVW : min / 1
divw x31, x11, x4
# expected: ffffffff80000000
# 10. DIVW : 0 / any
divw x31, x0, x2
# expected: 0000000000000000
# 11. DIVW : any / 0
divw x31, x2, x0
# expected: ffffffffffffffff
divw x31, x7, x0
# expected: ffffffffffffffff

View File

@@ -1,22 +1,54 @@
# expected: 0000000000000000, 00000000000dead0, c1b080e900, -dead0, 54a029
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, (-2355)
li x2, 0xdead0 # +912080
li x3, 0 # zero
li x4, 1 # one
li x5, -1 # -1
li x6, 0xdead0 # duplicate of x2
li x7, -2355 # negative
li x8, 123456 # positive
li x9, -765432 # negative
li x10, 0x7fffffffffffffff # max positive 64b
li x11, 0x8000000000000000 # min negative 64b
# Mul 0
# --------------------------------------------------------------
# 1. MUL : a * 0
mul x31, x2, x3
# expected: 0000000000000000
# Basic multiplications
# 2. MUL : a * 1
mul x31, x2, x4
# expected: 00000000000dead0
# 3. MUL : a * a
mul x31, x2, x6
# expected: 0000000c1b080e900
# Overflow
# 4. MUL : -1 * a
mul x31, x5, x2
# expected: -00000000000dead0
# Signed * signed
# 5. MUL : negative * negative
mul x31, x7, x7
# expected: 000000000054a029
# 6. MUL : negative * positive
mul x31, x7, x8
# expected: -00000000115452c0
# 7. MUL : positive * negative
mul x31, x8, x9
# expected: -0000001600786e00
# 8. MUL : overflow example (max * 2)
li x12, 2
mul x31, x10, x12
# expected: fffffffffffffffe
# 9. MUL : max * max
mul x31, x10, x10
# expected: 0000000000000001
# 10. MUL : min * min
mul x31, x11, x11
# expected: 0000000000000000

View File

@@ -1,19 +1,54 @@
# expected: 0000000000000000, 0000000000000000, c1b080e9, ffffffffffffffff
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, 0xdead00000000
li x2, 0xdead00000 # +59774074880
li x3, 0 # zero
li x4, 1 # one
li x5, -1 # -1
li x6, 0xdead00000 # duplicate of x2
li x7, -235555555555 # negative
li x8, 123456789 # positive
li x9, -765432000000 # negative
li x10, 0x7fffffffffffffff # max positive 64b
li x11, 0x8000000000000000 # min negative 64b
# Mul 0
# --------------------------------------------------------------
# 1. MULH : a * 0
mulh x31, x2, x3
# expected: 0000000000000000
# Basic multiplications
# 2. MULH : a * 1
mulh x31, x2, x4
mulh x31, x7, x7
# expected: 0000000000000000
# Overflow
# 3. MULH : a * a
mulh x31, x2, x6
# expected: 00000000000000c1
# 4. MULH : -1 * a
mulh x31, x5, x2
# expected: ffffffffffffffff
# 5. MULH : negative * negative
mulh x31, x7, x7
# expected: 0000000000000bbf
# 6. MULH : negative * positive
mulh x31, x7, x8
# expected: fffffffffffffffe
# 7. MULH : positive * negative
mulh x31, x8, x9
# expected: fffffffffffffffa
# 8. MULH : overflow example (max * 2)
li x12, 2
mulh x31, x10, x12
# expected: 0000000000000000
# 9. MULH : max * max
mulh x31, x10, x10
# expected: 3fffffffffffffff
# 10. MULH : min * min
mulh x31, x11, x11
# expected: 4000000000000000

View File

@@ -1,20 +1,54 @@
# expected: 0000000000000000, 0000000000000000, c1b080e9, ffffffffffffffff, deacf
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, 0xdead00000000
li x2, 0xdead00000 # +59774074880
li x3, 0 # zero
li x4, 1 # one
li x5, -1 # -1
li x6, 0xdead00000 # duplicate of x2
li x7, -235555555555 # negative
li x8, 123456789 # positive
li x9, 765432000000 # positive
li x10, 0x7fffffffffffffff # max positive 64b
li x11, 0x8000000000000000 # min negative 64b
# Mul 0
# --------------------------------------------------------------
# 1. MULHSU : a * 0
mulhsu x31, x2, x3
# expected: 0000000000000000
# Basic multiplications
# 2. MULHSU : a * 1
mulhsu x31, x2, x4
mulhsu x31, x7, x7
# expected: 0000000000000000
# Overflow
# 3. MULHSU : a * a
mulhsu x31, x2, x6
# expected: 00000000000000c1
# 4. MULHSU : -1 * a
mulhsu x31, x5, x2
mulhsu x31, x2, x5
# expected: ffffffffffffffff
# 5. MULHSU : negative * positive
mulhsu x31, x7, x8
# expected: fffffffffffffffe
# 6. MULHSU : negative * positive large
mulhsu x31, x7, x9
# expected: ffffffffffffd9d1
# 7. MULHSU : positive * positive
mulhsu x31, x8, x9
# expected: 0000000000000005
# 8. MULHSU : overflow example (max * 2)
li x12, 2
mulhsu x31, x10, x12
# expected: 0000000000000000
# 9. MULHSU : max * max
mulhsu x31, x10, x10
# expected: 3fffffffffffffff
# 10. MULHSU : min * max
mulhsu x31, x11, x10
# expected: c000000000000000

View File

@@ -1,20 +1,54 @@
# expected: 0000000000000000, 0000000000000000, c1b080e9, deacf, deacf
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, 0xdead00000000
li x2, 0xdead00000 # +59774074880
li x3, 0 # zero
li x4, 1 # one
li x5, 123456789 # small positive
li x6, 0xdead00000 # duplicate of x2
li x7, 765432000000 # large positive
li x8, 123456789 # small positive
li x9, 234567890000 # large positive
li x10, 0xffffffffffffffff # max positive 64b
li x11, 0x8000000000000000 # min unsigned = 2^63
# Mul 0
# --------------------------------------------------------------
# 1. MULHU : a * 0
mulhu x31, x2, x3
# expected: 0000000000000000
# Basic multiplications
# 2. MULHU : a * 1
mulhu x31, x2, x4
mulhu x31, x7, x7
# expected: 0000000000000000
# Overflow
mulhu x31, x5, x2
mulhu x31, x2, x5
# 3. MULHU : a * a
mulhu x31, x2, x6
# expected: 00000000000000c1
# 4. MULHU : small * small
mulhu x31, x5, x8
# expected: 0000000000000000
# 5. MULHU : small * large
mulhu x31, x5, x7
# expected: 0000000000000005
# 6. MULHU : large * small
mulhu x31, x7, x8
# expected: 0000000000000005
# 7. MULHU : large * large
mulhu x31, x7, x9
# expected: 0000000000002605
# 8. MULHU : max * 2
li x12, 2
mulhu x31, x10, x12
# expected: 0000000000000001
# 9. MULHU : max * max
mulhu x31, x10, x10
# expected: fffffffffffffffe
# 10. MULHU : min * max
mulhu x31, x11, x10
# expected: 7fffffffffffffff

View File

@@ -1,22 +1,54 @@
# expected: 0000000000000000, 00000000000dead0, ffffffffb080e900, -dead0, 54a029
.text
_start:
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, (-2355)
li x2, 0xdead0 # +912080
li x3, 0 # zero
li x4, 1 # one
li x5, -1 # -1
li x6, 0xdead0 # duplicate of x2
li x7, -2355 # negative
li x8, 123456 # positive
li x9, -765432 # negative
li x10, 0x7fffffff # max positive 32b
li x11, 0x80000000 # min negative 32b
# Mul 0
# --------------------------------------------------------------
# 1. MULW : a * 0
mulw x31, x2, x3
# expected: 0000000000000000
# Basic multiplications
# 2. MULW : a * 1
mulw x31, x2, x4
# expected: 000000000000dead0
# 3. MULW : a * a
mulw x31, x2, x6
# expected: FFFFFFFFB080E900
# Overflow
# 4. MULW : -1 * a
mulw x31, x5, x2
# expected: -dead0
# Signed * signed
# 5. MULW : negative * negative
mulw x31, x7, x7
# expected: 000000000054A029
# 6. MULW : negative * positive
mulw x31, x7, x8
# expected: FFFFFFFFEEABAD40
# 7. MULW : positive * negative
mulw x31, x8, x9
# expected: FFFFFFFFFF879200
# 8. MULW : overflow example (max * 2)
li x12, 2
mulw x31, x10, x12
# expected: fffffffffffffffe
# 9. MULW : max * max
mulw x31, x10, x10
# expected: 0000000000000001
# 10. MULW : min * min
mulw x31, x11, x11
# expected: 0000000000000000

View File

@@ -1,27 +1,60 @@
# expected: dead0, ffffffffffffffff, 0, 0, 18, 0, -57
.text
_start:
li x1, 0x0293
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, (-2355)
li x8, (-324)
li x9, 0x8000000000000000
li x2, 0xdead0 # 912080
li x3, 0x1234 # 4660
li x4, 1 # 1
li x5, -123456 # -123456
li x6, 0xdead0 # duplicate of x2
li x7, -765432 # -765432
li x8, 123456 # 123456
li x9, -234567 # -234567
li x10, 0x7fffffffffffffff # max positive 64b
li x11, 0x8000000000000000 # min negative 64b
# Remainder by 0
rem x31, x2, x3
rem x31, x5, x3
# Basic remainders
# 1. REM : a % 1
rem x31, x2, x4
# expected: 0000000000000000
# 2. REM : a % a
rem x31, x2, x6
rem x31, x6, x1
# expected: 0000000000000000
# Overflow
rem x31, x9, x5
# 3. REM : negative % positive
rem x31, x5, x8
# expected: 0000000000000000
# Signed / signed
# 4. REM : negative % positive
rem x31, x7, x8
# expected: 00000000000181c8
# 5. REM : positive % negative
rem x31, x8, x7
# expected: -9cbb8
# 6. REM : negative % negative
rem x31, x7, x9
# expected: -f123
# 7. REM : max % 2
li x12, 2
rem x31, x10, x12
# expected: 0000000000000001
# 8. REM : min % -1
li x12, -1
rem x31, x11, x12
# expected: 0000000000000000
# 9. REM : min % 1
rem x31, x11, x4
# expected: 0000000000000000
# 10. REM : 0 % any
rem x31, x3, x2
# expected: 0000000000001234
# 11. REM : any % 0
rem x31, x2, x0
# expected: 00000000000dead0
rem x31, x7, x0
# expected: -badf8

View File

@@ -1,27 +1,55 @@
# expected: dead0, ffffffffffffffff, 0, 0, 18, 8000000000000000, fffffffffffff6cd
.text
_start:
li x1, 0x0293
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, (-2355)
li x8, (-324)
li x9, 0x8000000000000000
li x2, 0xdead0 # 912080
li x3, 0x1234 # 4660
li x4, 1 # 1
li x5, 123456 # 123456
li x6, 0xdead0 # duplicate of x2
li x7, 765432 # 765432
li x8, 123456 # 123456
li x9, 234567 # 234567
li x10, 0x7fffffffffffffff # max positive 64b
li x11, 0x8000000000000000 # min negative 64b
# Remainder by 0
remu x31, x2, x3
remu x31, x5, x3
# Basic remainders
# 1. REMU : a % 1
remu x31, x2, x4
# expected: 0000000000000000
# 2. REMU : a % a
remu x31, x2, x6
remu x31, x6, x1
# expected: 0000000000000000
# Overflow
remu x31, x9, x5
# 3. REMU : smaller % larger
remu x31, x5, x7
# expected: 000000000001e240
# Signed / signed
# 4. REMU : larger % smaller
remu x31, x7, x8
# expected: 0000000000006078
# 5. REMU : any % any
remu x31, x8, x7
# expected: 000000000001e240
# 6. REMU : larger % larger
remu x31, x7, x9
# expected: 000000000000f123
# 7. REMU : max % 2
li x12, 2
remu x31, x10, x12
# expected: 0000000000000001
# 8. REMU : min % 1
remu x31, x11, x4
# expected: 0000000000000000
# 9. REMU : 0 % any
remu x31, x3, x2
# expected: 0000000000001234
# 10. REMU : any % 0
remu x31, x2, x0
# expected: 00000000000dead0
remu x31, x7, x0
# expected: 00000000000badf8

View File

@@ -1,27 +1,60 @@
# expected: dead0, ffffffffffffffff, 0, 0, 18, ffffffff80000000, fffffffffffff6cd
.text
_start:
li x1, 0x0293
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, (-2355)
li x8, (-324)
li x9, 0x80000000
li x2, 0xdead0 # 912080
li x3, 0x1234 # 4660
li x4, 1 # 1
li x5, -123456 # 0xfffe1dc0 (4294843840)
li x6, 0xdead0 # duplicate of x2
li x7, -765432 # 0xffed32b8 (4294201864)
li x8, 123456 # 123456
li x9, -234567 # 0xfffc7239 (4294732729)
li x10, 0xffffffff # max unsigned 32b
li x11, 0x80000000 # 2147483648
# Remainder by 0
remuw x31, x2, x3
remuw x31, x5, x3
# Basic remainders
# 1. REMUW : a % 1
remuw x31, x2, x4
# expected: 0000000000000000
# 2. REMUW : a % a
remuw x31, x2, x6
remuw x31, x6, x1
# expected: 0000000000000000
# Overflow
remuw x31, x9, x5
# 3. REMUW : unsigned(x5) % x8
remuw x31, x5, x8
# expected: 000000000000dcc0
# Signed / signed
# 4. REMUW : unsigned(x7) % x8
remuw x31, x7, x8
# expected: 0000000000007c48
# 5. REMUW : x8 % unsigned(x7)
remuw x31, x8, x7
# expected: 000000000001e240
# 6. REMUW : unsigned(x7) % unsigned(x9)
remuw x31, x7, x9
# expected: fffffffffff45208
# 7. REMUW : max32 % 2
li x12, 2
remuw x31, x10, x12
# expected: 0000000000000001
# 8. REMUW : min32 % -1
remuw x31, x11, x12
# expected: 0000000000000000
# 9. REMUW : min32 % 1
remuw x31, x11, x4
# expected: 0000000000000000
# 10. REMUW : 0 % any
remuw x31, x3, x2
# expected: 0000000000001234
# 11. REMUW : any % 0
remuw x31, x2, x0
# expected: 00000000000dead0
remuw x31, x7, x0
# expected: FFFFFFFFFFF45208

View File

@@ -1,27 +1,60 @@
# expected: dead0, ffffffffffffffff, 0, 0, 18, 0, -57
.text
_start:
li x1, 0x0293
li x2, 0xdead0
li x3, 0x0
li x4, 0x1
li x5, (-1)
li x6, 0xdead0
li x7, (-2355)
li x8, (-324)
li x9, 0x80000000
li x2, 0xdead0 # 912080
li x3, 0x1234 # 4660
li x4, 1 # 1
li x5, -123456 # -123456
li x6, 0xdead0 # duplicate of x2
li x7, -765432 # -765432
li x8, 123456 # 123456
li x9, -234567 # -234567
li x10, 0x7fffffff # max positive 32b
li x11, 0x80000000 # min negative 32b
# Remainder by 0
remw x31, x2, x3
remw x31, x5, x3
# Basic remainders
# 1. REMW : a % 1
remw x31, x2, x4
# expected: 0000000000000000
# 2. REMW : a % a
remw x31, x2, x6
remw x31, x6, x1
# expected: 0000000000000000
# Overflow
remw x31, x9, x5
# 3. REMW : negative % positive
remw x31, x5, x8
# expected: 0
# Signed / signed
# 4. REMW : negative % positive
remw x31, x7, x8
# expected: 181c8
# 5. REMW : positive % negative
remw x31, x8, x7
# expected: fffffffffff63448
# 6. REMW : negative % negative
remw x31, x7, x9
# expected: ffffffffffff0edd
# 7. REMW : max % 2
li x12, 2
remw x31, x10, x12
# expected: 00000001
# 8. REMW : min % -1
li x12, -1
remw x31, x11, x12
# expected: 00000000
# 9. REMW : min % 1
remw x31, x11, x4
# expected: 00000000
# 10. REMW : 0 % any
remw x31, x3, x2
# expected: 00001234
# 11. REMW : any % 0
remw x31, x2, x0
# expected: 000dead0
remw x31, x7, x0
# expected: -badf8

View File

@@ -5,10 +5,9 @@ import chisel3.util.switch
import chisel3.util.is
object AluOpCode extends ChiselEnum {
val Add, Sub, Mul, Mulh, Mulhsu, Mulhu, Div, Divu, Rem, Remu, Mulw, Divw,
Divuw, Remw, Remuw, And, Or, Xor, ShiftLeft, ShiftRight,
ShiftArithmeticRight, LessThanSigned, LessThanUnsigned,
GreaterEqualSigned, GreaterEqualUnsigned, Equal =
val Add, Sub, Mul, Mulh, Mulhsu, Mulhu, Div, Divu, Rem, Remu, And, Or, Xor,
ShiftLeft, ShiftRight, ShiftArithmeticRight, LessThanSigned,
LessThanUnsigned, GreaterEqualSigned, GreaterEqualUnsigned, Equal =
Value
}
@@ -22,12 +21,16 @@ class Alu extends Module {
val opcode = Input(AluOpCode())
val comp_result = Output(Bool())
// Should stop the stall for the current computation (e.g. Division)
val should_stop_stall = Output(Bool())
// ~~ Rv64i ~~
// If word_mode is enabled, operations are performed
// on 32-bit-truncated inputs and then sign extended to 64bits
val word_mode = Input(Bool())
})
io.should_stop_stall := false.B
io.out := 0.U;
io.comp_result := false.B;
val out = WireInit(0.U(64.W))
@@ -37,16 +40,56 @@ class Alu extends Module {
// Defaults
op_a := io.a
op_b := io.b
val op_a_sign = WireInit(op_a(63))
val op_b_sign = WireInit(op_b(63))
val op_a_unsigned = WireInit(op_a)
val op_b_unsigned = WireInit(op_b)
io.out := out
// Truncate operands, sext result
when(io.word_mode) {
op_a := io.a(31, 0)
op_b := io.b(31, 0)
op_a_sign := op_a(31)
op_b_sign := op_b(31)
io.out := SignExtend.Sext(out(31, 0), 64)
}
when(op_a_sign) {
op_a_unsigned := Utils.two_complement(op_a, io.word_mode)
}
when(op_b_sign) {
op_b_unsigned := Utils.two_complement(op_b, io.word_mode)
}
val in_computation = RegInit(false.B)
// Division
val divider = Module(new Divider(64, Constants.DIVISION_CYCLES_COUNT))
divider.io.word_mode := io.word_mode
divider.io.dividend := op_a_unsigned
divider.io.divisor := op_b_unsigned
divider.io.start := false.B
def div_by_zero() = {
when(io.word_mode) {
out := (-1).S(32.W).asUInt
}.otherwise {
out := (-1).S(64.W).asUInt
}
}
// Multiplication
val multiplication_res = op_a * op_b // Mul non signée
val multiplication_low =
Mux(io.word_mode, multiplication_res(31, 0), multiplication_res(63, 0))
val multiplication_high =
Mux(
io.word_mode,
multiplication_res(63, 32),
multiplication_res(127, 64)
)
switch(io.opcode) {
is(Add) {
out := op_a + op_b;
@@ -57,56 +100,77 @@ class Alu extends Module {
}
is(Mul) {
out := (io.a.asSInt * io.b.asSInt).asUInt;
out := multiplication_low;
}
is(Mulh) {
out := ((io.a.asSInt * io.b.asSInt) >> 64.U).asUInt;
val correction =
Mux(op_a_sign, op_b, 0.U) + Mux(op_b_sign, op_a, 0.U)
val multiplication_res_with_correction =
multiplication_high - correction
out := multiplication_res_with_correction;
}
is(Mulhsu) {
out := ((io.a.asSInt * io.b).asSInt >> 64.U).asUInt;
val correction =
Mux(op_a_sign, op_b, 0.U)
val multiplication_res_with_correction =
multiplication_high - correction
out := multiplication_res_with_correction;
}
is(Mulhu) {
out := (io.a * io.b) >> 64.U;
out := multiplication_high;
}
// is(Div) {
// when(io.b === 0.U) {
// when(io.word_mode) {
// out := (-1).S(32.W).asUInt
// }.otherwise {
// out := (-1).S(64.W).asUInt
// }
// }.otherwise {
// out := (io.a.asSInt / io.b.asSInt).asUInt;
// }
// }
//
// is(Divu) {
// when(io.b === 0.U) {
// out := "xFFFFFFFFFFFFFFFF".U
// }.otherwise {
// out := io.a / io.b;
// }
// }
//
// is(Rem) {
// when(io.b === 0.U) {
// out := io.a
// }.otherwise {
// out := (io.a.asSInt % io.b.asSInt).asUInt;
// }
// }
//
// is(Remu) {
// when(io.b === 0.U) {
// out := io.a
// }.otherwise {
// out := io.a % io.b;
// }
// }
is(Div) {
when(op_b === 0.U) {
div_by_zero()
}.elsewhen(op_a_sign ^ op_b_sign) {
out := Utils.two_complement(divider.io.quotient, io.word_mode)
}.otherwise {
out := divider.io.quotient
}
}
is(Divu) {
divider.io.dividend := op_a
divider.io.divisor := op_b
when(op_b === 0.U) {
div_by_zero()
}.otherwise { out := divider.io.quotient; }
}
is(Rem) {
when(op_b === 0.U) {
out := op_a
}.elsewhen(
op_a_sign && !op_b_sign && divider.io.remainder =/= 0.U
) {
out := op_b - divider.io.remainder
}.elsewhen(
!op_a_sign && op_b_sign && divider.io.remainder =/= 0.U
) {
out := Utils.two_complement(
Utils.two_complement(op_b) - divider.io.remainder,
io.word_mode
)
}.elsewhen(op_a_sign && op_b_sign) {
out := Utils.two_complement(divider.io.remainder, io.word_mode)
}.otherwise {
out := divider.io.remainder
}
}
is(Remu) {
divider.io.dividend := op_a
divider.io.divisor := op_b
when(op_b === 0.U) {
out := op_a
}.otherwise {
out := divider.io.remainder
}
}
is(And) {
out := op_a & op_b;
@@ -167,4 +231,44 @@ class Alu extends Module {
}
}
switch(io.opcode) {
is(Div, Divu, Rem, Remu) {
when(!in_computation) {
divider.io.start := true.B
in_computation := true.B
}.elsewhen(divider.io.ready) {
io.should_stop_stall := true.B
in_computation := false.B
}
}
}
// Special overflow cases for Div and Rem
when(
io.word_mode &&
op_b === ((BigInt(1) << 32) - 1).U(32.W) &&
op_a === (-1).S(32.W).asUInt
) {
switch(io.opcode) {
is(Div) {
out := (1.U << 31)
}
is(Rem) {
out := 0.U
}
}
}.elsewhen(
!io.word_mode &&
op_b === ((BigInt(1) << 64) - 1).U(64.W) &&
op_a === (-1).S(64.W).asUInt
) {
switch(io.opcode) {
is(Div) {
out := (1.U << 63)
}
is(Rem) {
out := 0.U
}
}
}
}

View File

@@ -0,0 +1,5 @@
package projet
object Constants {
def DIVISION_CYCLES_COUNT = 8
}

View File

@@ -25,6 +25,10 @@ class CUInterface extends Bundle {
// True if the decoded instruction is a jump
val is_jump = Output(Bool())
// Stall the pipeline on the current instruction
val should_stall = Output(Bool())
val should_stop_stall = Output(Bool())
// DMem connections
val memory_size = Output(DMemSize())
val memory_en = Output(Bool())
@@ -126,6 +130,8 @@ class ControlUnit() extends Module {
io.alu_word_mode := false.B
io.optype := OpType.U
io.is_jump := false.B;
io.should_stall := false.B;
io.should_stop_stall := false.B;
io.memory_size := DMemSize.Word
io.memory_en := false.B
io.memory_we := false.B

View File

@@ -0,0 +1,82 @@
package projet
import chisel3._
import chisel3.util._
class Divider(width: Int, nCycles: Int) extends Module {
require(
nCycles >= 1 && nCycles <= width,
"nCycles must be between 1 and width"
)
val io = IO(new Bundle {
val dividend = Input(UInt(width.W))
val divisor = Input(UInt(width.W))
val word_mode = Input(Bool())
val start = Input(Bool())
val ready = Output(Bool())
val quotient = Output(UInt(width.W))
val remainder = Output(UInt(width.W))
})
val reg_dividend = Reg(UInt(width.W))
val reg_divisor = Reg(UInt((width * 2).W))
val reg_divisor_start = Reg(UInt(width.W))
val reg_quotient = Reg(UInt(width.W))
val reg_current_shift = Reg(UInt((log2Ceil(width) + 1).W))
val bits_per_cycle = ((width + nCycles - 1) / nCycles)
val cycles_remaining = RegInit(0.U(log2Ceil(nCycles + 1).W))
val busy = RegInit(false.B)
io.ready := !busy
io.quotient := reg_quotient
io.remainder := reg_dividend(width - 1, 0)
when(io.start && !busy) {
reg_dividend := io.dividend
reg_divisor := io.divisor << (width - 1)
reg_divisor_start := io.divisor
reg_quotient := 0.U
reg_current_shift := (width - 1).U
cycles_remaining := nCycles.U
busy := true.B
}
when(busy) {
val stages = Wire(Vec(bits_per_cycle + 1, UInt(width.W)))
val dstages = Wire(Vec(bits_per_cycle + 1, UInt((width * 2).W)))
val qstages = Wire(Vec(bits_per_cycle + 1, UInt(width.W)))
stages(0) := reg_dividend
dstages(0) := reg_divisor
qstages(0) := reg_quotient
for (i <- 0 until bits_per_cycle) {
val cur = stages(i)
val curD = dstages(i)
val curQ = qstages(i)
when(cur >= curD) {
stages(i + 1) := cur - curD
qstages(i + 1) := curQ + (1.U << (reg_current_shift - i.U))
}.otherwise {
stages(i + 1) := cur
qstages(i + 1) := curQ
}
dstages(i + 1) := curD >> 1
}
reg_dividend := stages(bits_per_cycle)
reg_divisor := dstages(bits_per_cycle)
reg_quotient := qstages(bits_per_cycle)
reg_current_shift := reg_current_shift - bits_per_cycle.U
cycles_remaining := cycles_remaining - 1.U
when(cycles_remaining === 1.U) {
busy := false.B
}
}
}

View File

@@ -37,27 +37,44 @@ class Rv64i(sim: Boolean = true) extends Module {
// True if the instruction in the execute stage is a jump
val is_jump = Delay.Delay(control_unit.io.is_jump, 1, false.B);
// Insert no-op if jump
val decoded_instruction =
Mux(
is_jump,
"b00000000000000000000000000010011".U,
io.ibus.rdata >> (execute_pc(2) * 32.U)
)
val stalled_instruction = RegInit(0.U)
val should_stop_stall =
control_unit.io.should_stop_stall || alu.io.should_stop_stall
val is_stalled = RegInit(false.B)
val is_immediatly_stalled =
(!should_stop_stall && (is_stalled || control_unit.io.should_stall =/= 0.U))
when(!is_stalled && control_unit.io.should_stall =/= 0.U) {
// Stall the pipeline
is_stalled := true.B
stalled_instruction := decoded_instruction
}
when(is_stalled && should_stop_stall) {
is_stalled := false.B
}
val instruction = Mux(is_stalled, stalled_instruction, decoded_instruction)
// Pipelining registers for mem stage
val reg_rd_index = RegInit(0.U);
val reg_execute_out = RegInit(0.U);
val reg_mux_executeout_dout = RegInit(true.B);
val reg_regile_we = RegInit(false.B);
// Insert no-op if jump
val instruction =
Mux(
is_jump,
"b00000000000000000000000000010011".U,
io.ibus.rdata >> (execute_pc(2) * 32.U)
);
immediate_decoder.io.instruction := instruction
immediate_decoder.io.op_type := control_unit.io.optype
alu.io.opcode := control_unit.io.alu_opcode;
// Reg file write-enable
reg_regile_we := control_unit.io.reg_file_we;
reg_file.io.we := reg_regile_we;
reg_file.io.we := reg_regile_we && !is_stalled;
// Increment PC each clock
val pc_adder_out = Mux(
@@ -153,4 +170,7 @@ class Rv64i(sim: Boolean = true) extends Module {
false.B
)
when(is_immediatly_stalled) {
reg_pc := reg_pc
}
}

View File

@@ -0,0 +1,15 @@
package projet
import chisel3._
object Utils {
def two_complement(x: UInt, word_sized: Bool = false.B): UInt = {
val result = Wire(UInt(64.W))
when(word_sized) {
result := "xFFFFFFFF".U - x + 1.U
}.otherwise {
result := "xFFFFFFFFFFFFFFFF".U - x + 1.U
}
result
}
}

View File

@@ -38,15 +38,19 @@ object OpM {
}
is(Funct3.DIV) {
io.alu_opcode := AluOpCode.Div
io.should_stall := true.B
}
is(Funct3.DIVU) {
io.alu_opcode := AluOpCode.Divu
io.should_stall := true.B
}
is(Funct3.REM) {
io.alu_opcode := AluOpCode.Rem
io.should_stall := true.B
}
is(Funct3.REMU) {
io.alu_opcode := AluOpCode.Remu
io.should_stall := true.B
}
}
}

View File

@@ -10,9 +10,9 @@ object ZzTopCommon extends AnyFreeSpec with ChiselSim {
Source
.fromFile(path)
.getLines()
.filter(_.startsWith("# expected:"))
.filter(_.trim().startsWith("# expected:"))
.map(
_.stripPrefix("# expected:")
_.trim().stripPrefix("# expected:")
.split(",")
.map(_.trim)
.filter(_.nonEmpty)