Merge branch 'rv64i' into rv64im

This commit is contained in:
2025-11-11 19:17:46 +01:00
9 changed files with 216 additions and 71 deletions

View File

@@ -7,7 +7,7 @@ import chisel3.util.Cat
import chisel3.util.Fill
object AluOpCode extends ChiselEnum {
val Add, AddW, Sub, Mul, Mulh, Mulhsu, Mulhu, Div, Divu, Rem, Remu, Mulw,
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 =
@@ -23,122 +23,87 @@ class Alu extends Module {
val out = Output(UInt(64.W))
val opcode = Input(AluOpCode())
val comp_result = 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.out := 0.U;
io.comp_result := false.B;
val out = WireInit(0.U(64.W))
val op_a = WireInit(0.U(64.W))
val op_b = WireInit(0.U(64.W))
// Defaults
op_a := io.a
op_b := io.b
io.out := out
// Truncate operands, sext result
when(io.word_mode) {
op_a := io.a(31, 0)
op_b := io.b(31, 0)
io.out := SignExtend.Sext(out(31, 0), 64)
}
switch(io.opcode) {
is(Add) {
io.out := io.a + io.b;
out := io.a + io.b;
}
is(Sub) {
io.out := io.a - io.b;
}
is(Mul) {
io.out := (io.a.asSInt * io.b.asSInt).asUInt;
}
is(Mulh) {
io.out := ((io.a.asSInt * io.b.asSInt) >> 64.U).asUInt;
}
is(Mulhsu) {
io.out := ((io.a.asSInt * io.b).asSInt >> 64.U).asUInt;
}
is(Mulhu) {
io.out := (io.a * io.b) >> 64.U;
}
is(Div) {
io.out := (io.a.asSInt / io.b.asSInt).asUInt;
}
is(Divu) {
io.out := io.a / io.b;
}
is(Rem) {
io.out := (io.a.asSInt % io.b.asSInt).asUInt;
}
is(Remu) {
io.out := io.a % io.b;
}
is(Mulw) {
val res = (io.a.asSInt * io.b.asSInt).asUInt
io.out := Cat(Fill(32, res(31)), res(31, 0))
}
is(Divw) {
val res = (io.a(31, 0).asSInt / io.b(31, 0).asSInt).asUInt;
io.out := Cat(Fill(32, res(31)), res(31, 0));
}
is(Divuw) {
val res = io.a(31, 0) / io.b(31, 0);
io.out := Cat(Fill(32, res(31)), res(31, 0));
}
is(Remw) {
val res = (io.a(31, 0).asSInt % io.b(31, 0).asSInt).asUInt;
io.out := Cat(Fill(32, res(31)), res(31, 0));
}
is(Remuw) {
val res = io.a(31, 0) % io.b(31, 0);
io.out := Cat(Fill(32, res(31)), res(31, 0));
out := io.a - io.b;
}
is(And) {
io.out := io.a & io.b;
out := io.a & io.b;
}
is(Or) {
io.out := io.a | io.b;
out := io.a | io.b;
}
is(Xor) {
io.out := io.a ^ io.b;
out := io.a ^ io.b;
}
is(ShiftLeft) {
io.out := io.a << io.b(5, 0);
out := io.a << io.b(5, 0);
}
is(ShiftRight) {
io.out := io.a >> io.b(5, 0);
out := io.a >> io.b(5, 0);
}
is(ShiftArithmeticRight) {
// >> means arithmetic shift for SInts
io.out := (io.a.asSInt >> io.b(5, 0)).asUInt;
out := (io.a.asSInt >> io.b(5, 0)).asUInt;
}
is(LessThanUnsigned) {
val less_than = io.a < io.b;
io.out := less_than;
out := less_than;
io.comp_result := less_than;
}
is(LessThanSigned) {
val less_than = io.a.asSInt < io.b.asSInt
io.out := less_than
out := less_than
io.comp_result := less_than;
}
is(GreaterEqualUnsigned) {
val geq_than = io.a >= io.b;
io.out := geq_than
out := geq_than
io.comp_result := geq_than;
}
is(GreaterEqualSigned) {
val geq_than = io.a.asSInt >= io.b.asSInt
io.out := geq_than
out := geq_than
io.comp_result := geq_than;
}

View File

@@ -8,8 +8,11 @@ class CUInterface extends Bundle {
val instruction = Input(UInt(32.W))
val reg_file_we = Output(Bool())
val alu_opcode = Output(AluOpCode())
// TODO: Maybe bundle alu <> cu
// Alu comparison result
val alu_comp_result = Input(Bool())
val alu_word_mode = Output(Bool())
val optype = Output(OpType())
@@ -98,6 +101,9 @@ object OpCode extends ChiselEnum {
// Type I
val OpLoad = "b0000011".U
// ~~ Rv64i ~~
val OpImmW = "b0011011".U
}
class ControlUnit() extends Module {
@@ -105,6 +111,7 @@ class ControlUnit() extends Module {
io.reg_file_we := false.B
io.alu_opcode := AluOpCode.Add
io.alu_word_mode := false.B
io.optype := OpType.U
io.is_jump := false.B;
io.memory_size := DMemSize.Word
@@ -205,6 +212,12 @@ class ControlUnit() extends Module {
io.optype := OpType.I
opLoad(funct3, io);
}
is(OpCode.OpImmW) {
io.reg_file_we := true.B // Write to regfile
io.optype := OpType.I
opImmW(funct3, funct7, io);
}
}
// Implements functions for all instruction of the opImm kind
@@ -233,6 +246,7 @@ class ControlUnit() extends Module {
io.mux_regb_imm := false.B; // OpImm are operations with imm, so send imm to ALU
io.mux_alu_imm := true.B;
io.mux_rega_pc := true.B;
io.alu_word_mode := false.B;
switch(funct3) {
// Type I
is(Funct3.ADDI) {
@@ -520,6 +534,45 @@ class ControlUnit() extends Module {
}
}
}
// ~~~ EXTENSIONS ~~~
// ~~ Rv64i ~~
// Implements functions for all instruction of the opImm, w kind
def opImmW(funct3: UInt, funct7: UInt, io: CUInterface) = {
// Meaning of Funct3 in the context of an OpImm instruction
val _ = funct7;
object Funct3 extends ChiselEnum {
// Type I
val ADDIW = "b000".U
val SLLIW = "b001".U
// Unimplemented
val SRLIW_SRAIW = "b101".U // Right shifts
}
// Meaning of Funct7 in the context of SHIFTR IR instructions
// object IRFunct7 extends ChiselEnum {
// val SRLI = "b0000000".U
// val SRAI = "b0100000".U
// }
io.mux_regb_imm := false.B; // OpImm are operations with imm, so send imm to ALU
io.mux_alu_imm := true.B;
io.mux_rega_pc := true.B;
switch(funct3) {
// Type I
is(Funct3.ADDIW) {
io.alu_word_mode := true.B
io.alu_opcode := AluOpCode.Add
io.optype := OpType.I
}
}
}
// ~~ Rv32M ~~
// Implements functions for instructions of the M extension of type R
def opM(funct3: UInt, io: CUInterface) = {
// Meaning of Funct3 in the context of an OpM instruction
@@ -561,6 +614,9 @@ 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

View File

@@ -30,6 +30,7 @@ class Rv64i(sim: Boolean = true) extends Module {
dmem.io.sign_extend := control_unit.io.memory_sign_extend
control_unit.io.alu_comp_result := alu.io.comp_result
alu.io.word_mode := control_unit.io.alu_word_mode
// PC delayed to execute stage for auipc op
val execute_pc = Delay.Delay(reg_pc, 1, 0.U);

View File

@@ -0,0 +1,11 @@
package projet
import chisel3.UInt
import chisel3.util.Fill
// Utility function to sign extend number to higher amount of bits
object SignExtend {
def Sext(x: UInt, n: Int): UInt = {
Fill(n - x.getWidth, x(x.getWidth - 1)) ## x
}
}