Modifies test slightly because now RAM is relocated to 0x10000

This commit is contained in:
2025-11-15 01:26:49 +01:00
32 changed files with 974 additions and 274 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,4 +1,4 @@
# expected: 0000a000,0000b004,0000c008
# expected: 0001a000,0001b004,0001c008
.text
_start:
auipc x31, 0xa

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,10 +1,12 @@
# expected: FFFFFFFFFFFFFFFB, FFFFFFFFFFFFFFFB
.text
_start:
addi x1, x0, 0x0FB
sb x1, 100(x0)
lb x31, 100(x0)
li x2, 0x11000
addi x1, x0, 0x0FB
sb x1, 106(x0)
lb x31, 106(x0)
sb x1, 100(x2)
lb x31, 100(x2)
addi x1, x0, 0x0FB
sb x1, 106(x2)
lb x31, 106(x2)

View File

@@ -1,10 +1,12 @@
# expected: 000000FB, 000000FB
.text
_start:
li x2, 0x11000
addi x1, x0, 0x0FB
sb x1, 100(x0)
lbu x31, 100(x0)
sb x1, 100(x2)
lbu x31, 100(x2)
addi x1, x0, 0x0FB
sb x1, 106(x0)
lbu x31, 106(x0)
sb x1, 106(x2)
lbu x31, 106(x2)

View File

@@ -1,7 +1,9 @@
# expected: 1023456789ABCDEF
.text
_start:
li x1, 0x1023456789ABCDEF
sd x1, 100(x0)
li x2, 0x11000
ld x31, 100(x0)
li x1, 0x1023456789ABCDEF
sd x1, 100(x2)
ld x31, 100(x2)

View File

@@ -1,12 +1,14 @@
# expected: 0000F1BC, 0000F1BC
.text
_start:
lui x1, 0xF
ori x1, x1, 0x1BC
sh x1, 100(x0)
lhu x31, 100(x0)
li x2, 0x11000
lui x1, 0xF
ori x1, x1, 0x1BC
sh x1, 106(x0)
lhu x31, 106(x0)
sh x1, 100(x2)
lhu x31, 100(x2)
lui x1, 0xF
ori x1, x1, 0x1BC
sh x1, 106(x2)
lhu x31, 106(x2)

View File

@@ -1,6 +1,8 @@
# expected: 00000000FFFFFFFF
.text
_start:
li x2, 0x11000
li x1, 0xFFFFFFFFFFFFFFFF
sw x1, 100(x0)
lwu x31, 100(x0)
sw x1, 100(x2)
lwu x31, 100(x2)

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

@@ -1,10 +1,12 @@
# expected: 00000050, 000001AB
.text
_start:
auipc x12, 0x0
addi x1, x0, 0x5
# Write x1 in the next addi instruction, position 12+3 bytes
# Due to type I immediate, x31 must contain 0x050
sb x1, 15(x0)
sb x1, 19(x12)
nop
addi x31, x0, 0x0
@@ -14,11 +16,13 @@ _start:
addi x2, x0, 0x0F
addi x3, x0, 0xB0
addi x4, x0, 0x1A
sb x1, 52(x0)
sb x2, 53(x0)
sb x3, 54(x0)
sb x4, 55(x0)
sb x1, 56(x12)
sb x2, 57(x12)
sb x3, 58(x12)
sb x4, 59(x12)
nop
# Instruction will be written here
nop

View File

@@ -1,9 +1,10 @@
# expected: 000000009ABCDEF0, 0000000012345678
.text
_start:
auipc x2, 0x01
li x1, 0x123456789ABCDEF0
sd x1, 128(x0)
sd x1, 128(x2)
lwu x31, 128(x0)
lwu x31, 132(x0)
lwu x31, 128(x2)
lwu x31, 132(x2)

View File

@@ -1,10 +1,11 @@
# expected: 00000050, 000001AB
.text
_start:
auipc x12, 0x0
addi x1, x0, 0x500
# Write x1 in the next addi instruction, position 12+2 bytes
# Due to type I immediate, x31 must contain 0x050
sh x1, 14(x0)
sh x1, 18(x12)
nop
addi x31, x0, 0x0
@@ -14,8 +15,8 @@ _start:
srli x1, x1, 12
lui x2, 0x1AB0
srli x2, x2, 12
sh x1, 44(x0)
sh x2, 46(x0)
sh x1, 48(x12)
sh x2, 50(x12)
nop
# Instruction will be written here

View File

@@ -3,12 +3,14 @@
_start:
# Create an instruction bytes per bytes
# addi x31, x0, 0x1AB -> 0x1AB00F93
auipc x12, 0x0
lui x1, 0x0F93
srli x1, x1, 12
lui x2, 0x1AB0
slli x2, x2, 4
or x1, x1, x2
sw x1, 28(x0)
sw x1, 32(x12)
nop
# Instruction will be written here

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

@@ -44,27 +44,44 @@ class Rv64i(sim: Boolean = true) extends Module {
}
}
// 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(
@@ -162,4 +179,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)