From cfacd6a9fc938298296760056766debc93733dc2 Mon Sep 17 00:00:00 2001 From: supersurviveur Date: Wed, 12 Nov 2025 11:50:09 +0100 Subject: [PATCH] rv64im: passing tests --- bench/tests/op/div.s | 25 +++++++++++ bench/tests/op/divu.s | 14 ++++++ bench/tests/op/divuw.s | 14 ++++++ bench/tests/op/divw.s | 25 +++++++++++ bench/tests/op/mul.s | 16 ++++--- bench/tests/op/mulh.s | 15 ++++--- bench/tests/op/mulhsu.s | 16 ++++--- bench/tests/op/mulhu.s | 20 +++++++++ bench/tests/op/mulw.s | 22 ++++++++++ bench/tests/op/rem.s | 27 ++++++++++++ bench/tests/op/remu.s | 27 ++++++++++++ bench/tests/op/remuw.s | 27 ++++++++++++ bench/tests/op/remw.s | 27 ++++++++++++ src/main/scala/projet/Alu.scala | 58 +++++++++++++++++++++++-- src/main/scala/projet/ControlUnit.scala | 35 +-------------- src/test/scala/projet/ZzTopCommon.scala | 13 ++++-- 16 files changed, 321 insertions(+), 60 deletions(-) create mode 100644 bench/tests/op/div.s create mode 100644 bench/tests/op/divu.s create mode 100644 bench/tests/op/divuw.s create mode 100644 bench/tests/op/divw.s create mode 100644 bench/tests/op/mulhu.s create mode 100644 bench/tests/op/mulw.s create mode 100644 bench/tests/op/rem.s create mode 100644 bench/tests/op/remu.s create mode 100644 bench/tests/op/remuw.s create mode 100644 bench/tests/op/remw.s diff --git a/bench/tests/op/div.s b/bench/tests/op/div.s new file mode 100644 index 0000000..344269d --- /dev/null +++ b/bench/tests/op/div.s @@ -0,0 +1,25 @@ +# 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 + + # Div by 0 + div x31, x2, x3 + div x31, x5, x3 + + # Basic divisions + div x31, x2, x4 + div x31, x2, x6 + + # Overflow + div x31, x9, x5 + + # Signed / signed + div x31, x7, x8 diff --git a/bench/tests/op/divu.s b/bench/tests/op/divu.s new file mode 100644 index 0000000..dabe844 --- /dev/null +++ b/bench/tests/op/divu.s @@ -0,0 +1,14 @@ +# expected: ffffffffffffffff, dead0, 1 + .text +_start: + li x2, 0xdead0 + li x3, 0x0 + li x4, 0x1 + li x6, 0xdead0 + + # Div by 0 + divu x31, x2, x3 + + # Basic divisions + divu x31, x2, x4 + divu x31, x2, x6 diff --git a/bench/tests/op/divuw.s b/bench/tests/op/divuw.s new file mode 100644 index 0000000..25a763d --- /dev/null +++ b/bench/tests/op/divuw.s @@ -0,0 +1,14 @@ +# expected: ffffffffffffffff, dead0, 1 + .text +_start: + li x2, 0xdead0 + li x3, 0x0 + li x4, 0x1 + li x6, 0xdead0 + + # Div by 0 + divuw x31, x2, x3 + + # Basic divisions + divuw x31, x2, x4 + divuw x31, x2, x6 diff --git a/bench/tests/op/divw.s b/bench/tests/op/divw.s new file mode 100644 index 0000000..66a198c --- /dev/null +++ b/bench/tests/op/divw.s @@ -0,0 +1,25 @@ +# 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 + + # Div by 0 + divw x31, x2, x3 + divw x31, x5, x3 + + # Basic divisions + divw x31, x2, x4 + divw x31, x2, x6 + + # Overflow + divw x31, x9, x5 + + # Signed / signed + divw x31, x7, x8 diff --git a/bench/tests/op/mul.s b/bench/tests/op/mul.s index 429aab2..ce007ef 100644 --- a/bench/tests/op/mul.s +++ b/bench/tests/op/mul.s @@ -1,11 +1,12 @@ -# expected: 0000000000000000, ffffffffdead0000, 045680e900000000, 0000000021530000 +# expected: 0000000000000000, 00000000000dead0, c1b080e900, -dead0, 54a029 .text _start: - lui x2, 0xdead0 - lui x3, 0x0 - addi x4, x0, 0x1 - addi x5, x0, (-1) - lui x6, 0xdead0 + li x2, 0xdead0 + li x3, 0x0 + li x4, 0x1 + li x5, (-1) + li x6, 0xdead0 + li x7, (-2355) # Mul 0 mul x31, x2, x3 @@ -16,3 +17,6 @@ _start: # Overflow mul x31, x5, x2 + + # Signed * signed + mul x31, x7, x7 diff --git a/bench/tests/op/mulh.s b/bench/tests/op/mulh.s index 8fd593a..7eb3d98 100644 --- a/bench/tests/op/mulh.s +++ b/bench/tests/op/mulh.s @@ -1,18 +1,19 @@ -# expected: 0000000000000000, 0000000000000000, ffffffffbd5a0000, ffffffffdeacffff +# expected: 0000000000000000, 0000000000000000, c1b080e9, ffffffffffffffff .text _start: - lui x2, 0xdead0 - lui x3, 0x0 - addi x4, x0, 0x1 - addi x5, x0, (-1) - lui x6, 0xdead0 + li x2, 0xdead0 + li x3, 0x0 + li x4, 0x1 + li x5, (-1) + li x6, 0xdead0 + li x7, 0xdead00000000 # Mul 0 mulh x31, x2, x3 # Basic multiplications mulh x31, x2, x4 - mulh x31, x2, x6 + mulh x31, x7, x7 # Overflow mulh x31, x5, x2 diff --git a/bench/tests/op/mulhsu.s b/bench/tests/op/mulhsu.s index 5cb8e1e..57c2d10 100644 --- a/bench/tests/op/mulhsu.s +++ b/bench/tests/op/mulhsu.s @@ -1,18 +1,20 @@ -# expected: 0000000000000000, 0000000000000000, ffffffffbd5a0000, ffffffffdeacffff +# expected: 0000000000000000, 0000000000000000, c1b080e9, ffffffffffffffff, deacf .text _start: - lui x2, 0xdead0 - lui x3, 0x0 - addi x4, x0, 0x1 - addi x5, x0, (-1) - lui x6, 0xdead0 + li x2, 0xdead0 + li x3, 0x0 + li x4, 0x1 + li x5, (-1) + li x6, 0xdead0 + li x7, 0xdead00000000 # Mul 0 mulhsu x31, x2, x3 # Basic multiplications mulhsu x31, x2, x4 - mulhsu x31, x2, x6 + mulhsu x31, x7, x7 # Overflow mulhsu x31, x5, x2 + mulhsu x31, x2, x5 diff --git a/bench/tests/op/mulhu.s b/bench/tests/op/mulhu.s new file mode 100644 index 0000000..a77da19 --- /dev/null +++ b/bench/tests/op/mulhu.s @@ -0,0 +1,20 @@ +# 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 + + # Mul 0 + mulhu x31, x2, x3 + + # Basic multiplications + mulhu x31, x2, x4 + mulhu x31, x7, x7 + + # Overflow + mulhu x31, x5, x2 + mulhu x31, x2, x5 diff --git a/bench/tests/op/mulw.s b/bench/tests/op/mulw.s new file mode 100644 index 0000000..cc96cae --- /dev/null +++ b/bench/tests/op/mulw.s @@ -0,0 +1,22 @@ +# 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) + + # Mul 0 + mulw x31, x2, x3 + + # Basic multiplications + mulw x31, x2, x4 + mulw x31, x2, x6 + + # Overflow + mulw x31, x5, x2 + + # Signed * signed + mulw x31, x7, x7 diff --git a/bench/tests/op/rem.s b/bench/tests/op/rem.s new file mode 100644 index 0000000..3b59175 --- /dev/null +++ b/bench/tests/op/rem.s @@ -0,0 +1,27 @@ +# 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 + + # Remainder by 0 + rem x31, x2, x3 + rem x31, x5, x3 + + # Basic remainders + rem x31, x2, x4 + rem x31, x2, x6 + rem x31, x6, x1 + + # Overflow + rem x31, x9, x5 + + # Signed / signed + rem x31, x7, x8 diff --git a/bench/tests/op/remu.s b/bench/tests/op/remu.s new file mode 100644 index 0000000..5ff7246 --- /dev/null +++ b/bench/tests/op/remu.s @@ -0,0 +1,27 @@ +# 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 + + # Remainder by 0 + remu x31, x2, x3 + remu x31, x5, x3 + + # Basic remainders + remu x31, x2, x4 + remu x31, x2, x6 + remu x31, x6, x1 + + # Overflow + remu x31, x9, x5 + + # Signed / signed + remu x31, x7, x8 diff --git a/bench/tests/op/remuw.s b/bench/tests/op/remuw.s new file mode 100644 index 0000000..bfecbae --- /dev/null +++ b/bench/tests/op/remuw.s @@ -0,0 +1,27 @@ +# 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 + + # Remainder by 0 + remuw x31, x2, x3 + remuw x31, x5, x3 + + # Basic remainders + remuw x31, x2, x4 + remuw x31, x2, x6 + remuw x31, x6, x1 + + # Overflow + remuw x31, x9, x5 + + # Signed / signed + remuw x31, x7, x8 diff --git a/bench/tests/op/remw.s b/bench/tests/op/remw.s new file mode 100644 index 0000000..2c08bbe --- /dev/null +++ b/bench/tests/op/remw.s @@ -0,0 +1,27 @@ +# 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 + + # Remainder by 0 + remw x31, x2, x3 + remw x31, x5, x3 + + # Basic remainders + remw x31, x2, x4 + remw x31, x2, x6 + remw x31, x6, x1 + + # Overflow + remw x31, x9, x5 + + # Signed / signed + remw x31, x7, x8 diff --git a/src/main/scala/projet/Alu.scala b/src/main/scala/projet/Alu.scala index 133549d..5dfef00 100644 --- a/src/main/scala/projet/Alu.scala +++ b/src/main/scala/projet/Alu.scala @@ -3,12 +3,10 @@ package projet import chisel3._ import chisel3.util.switch import chisel3.util.is -import chisel3.util.Cat -import chisel3.util.Fill 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, + 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 = Value @@ -58,6 +56,58 @@ class Alu extends Module { out := io.a - io.b; } + is(Mul) { + out := (io.a.asSInt * io.b.asSInt).asUInt; + } + + is(Mulh) { + out := ((io.a.asSInt * io.b.asSInt) >> 64.U).asUInt; + } + + is(Mulhsu) { + out := ((io.a.asSInt * io.b).asSInt >> 64.U).asUInt; + } + + is(Mulhu) { + out := (io.a * io.b) >> 64.U; + } + + 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(And) { out := io.a & io.b; } diff --git a/src/main/scala/projet/ControlUnit.scala b/src/main/scala/projet/ControlUnit.scala index 12b0262..5032028 100644 --- a/src/main/scala/projet/ControlUnit.scala +++ b/src/main/scala/projet/ControlUnit.scala @@ -163,7 +163,8 @@ class ControlUnit() extends Module { // OpMw instructions is(OpCode.OpMw) { io.reg_file_we := true.B // Write to regfile - opMw(funct3, io); + io.alu_word_mode := true.B + opM(funct3, io); } // J instructions @@ -614,36 +615,4 @@ class ControlUnit() extends Module { } } } - - // ~~ Rv64M ~~ - - // Implements functions for instructions of the M extension with word size - def opMw(funct3: UInt, io: CUInterface) = { - // Meaning of Funct3 in the context of an OpMw instruction - object Funct3 extends ChiselEnum { - val MULW = "b000".U - val DIVW = "b100".U - val DIVUW = "b101".U - val REMW = "b110".U - val REMUW = "b111".U - } - - switch(funct3) { - is(Funct3.MULW) { - io.alu_opcode := AluOpCode.Mulw - } - is(Funct3.DIVW) { - io.alu_opcode := AluOpCode.Divw - } - is(Funct3.DIVUW) { - io.alu_opcode := AluOpCode.Divuw - } - is(Funct3.REMW) { - io.alu_opcode := AluOpCode.Remw - } - is(Funct3.REMUW) { - io.alu_opcode := AluOpCode.Remuw - } - } - } } diff --git a/src/test/scala/projet/ZzTopCommon.scala b/src/test/scala/projet/ZzTopCommon.scala index 3025901..19a69f1 100644 --- a/src/test/scala/projet/ZzTopCommon.scala +++ b/src/test/scala/projet/ZzTopCommon.scala @@ -15,7 +15,14 @@ object ZzTopCommon extends AnyFreeSpec with ChiselSim { .split(",") .map(_.trim) .filter(_.nonEmpty) - .map(str => BigInt(str, 16)) + .map(str => { + if (str.charAt(0) == '-') { + BigInt("FFFFFFFFFFFFFFFF", 16) - + BigInt(str.substring(1), 16) + 1 + } else { + BigInt(str, 16) + } + }) .toSeq case None => Seq.empty @@ -52,10 +59,10 @@ object ZzTopCommon extends AnyFreeSpec with ChiselSim { if (cycles < timeout) { // Vérifier la nouvelle valeur val got = dut.io.x31.get.peek().litValue - trace += f"Valeur attendue = 0x$expected%08X, reçue = 0x$got%08X" + trace += f"Valeur attendue = 0x$expected%016X, reçue = 0x$got%016X" if (got != expected) failTrace("Mauvaise sortie", trace) } else { - trace += f"Valeur attendue = 0x$expected%08X, reçue = ⏰" + trace += f"Valeur attendue = 0x$expected%016X, reçue = ⏰" failTrace("Simulation bloquée", trace) } }