rv64im: passing tests

This commit is contained in:
2025-11-12 11:50:09 +01:00
parent 7a1221b16e
commit cfacd6a9fc
16 changed files with 321 additions and 60 deletions

View File

@@ -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;
}

View File

@@ -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
}
}
}
}

View File

@@ -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)
}
}