Stage 4: Implements auipc
This commit is contained in:
6
bench/auipc.s
Normal file
6
bench/auipc.s
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# expected: 0000a000,0000b004,0000c008
|
||||||
|
.text
|
||||||
|
_start:
|
||||||
|
auipc x31, 0xa
|
||||||
|
auipc x31, 0xb
|
||||||
|
auipc x31, 0xc
|
||||||
32
src/main/scala/projet/Alu.scala
Normal file
32
src/main/scala/projet/Alu.scala
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package projet
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util.switch
|
||||||
|
import chisel3.util.is
|
||||||
|
|
||||||
|
object AluOpCode extends ChiselEnum
|
||||||
|
{
|
||||||
|
val Add = Value
|
||||||
|
}
|
||||||
|
|
||||||
|
class Alu extends Module {
|
||||||
|
import AluOpCode._
|
||||||
|
|
||||||
|
val io = IO(new Bundle {
|
||||||
|
val a = Input(UInt(32.W))
|
||||||
|
val b = Input(UInt(32.W))
|
||||||
|
val out = Output(UInt(32.W))
|
||||||
|
val opcode = Input(AluOpCode())
|
||||||
|
})
|
||||||
|
|
||||||
|
io.out := 0.U;
|
||||||
|
|
||||||
|
switch(io.opcode)
|
||||||
|
{
|
||||||
|
is(Add)
|
||||||
|
{
|
||||||
|
io.out := io.a + io.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,10 +7,14 @@ import chisel3.util.is
|
|||||||
class CUInterface extends Bundle {
|
class CUInterface extends Bundle {
|
||||||
val instruction = Input(UInt(32.W))
|
val instruction = Input(UInt(32.W))
|
||||||
val reg_file_we = Output(Bool())
|
val reg_file_we = Output(Bool())
|
||||||
|
val alu_opcode = Output(AluOpCode())
|
||||||
|
|
||||||
|
val mux_imm_alu = Output(Bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
object OPCode extends ChiselEnum {
|
object OPCode extends ChiselEnum {
|
||||||
val LUI = 0b0110111.U
|
val LUI = 0b0110111.U
|
||||||
|
val AUIPC = 0b0010111.U
|
||||||
}
|
}
|
||||||
|
|
||||||
class ControlUnit() extends Module {
|
class ControlUnit() extends Module {
|
||||||
@@ -19,9 +23,17 @@ class ControlUnit() extends Module {
|
|||||||
val io = IO(new CUInterface())
|
val io = IO(new CUInterface())
|
||||||
|
|
||||||
io.reg_file_we := false.B
|
io.reg_file_we := false.B
|
||||||
|
io.alu_opcode := AluOpCode.Add
|
||||||
|
io.mux_imm_alu := false.B;
|
||||||
switch(io.instruction(6, 0)) {
|
switch(io.instruction(6, 0)) {
|
||||||
is(LUI) {
|
is(LUI) {
|
||||||
io.reg_file_we := true.B
|
io.reg_file_we := true.B
|
||||||
|
io.mux_imm_alu := false.B;
|
||||||
|
}
|
||||||
|
is(AUIPC) {
|
||||||
|
io.alu_opcode := AluOpCode.Add
|
||||||
|
io.reg_file_we := true.B
|
||||||
|
io.mux_imm_alu := true.B;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,21 +24,26 @@ class RegFile(sim: Boolean = false) extends Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val valid = WireInit(false.B);
|
|
||||||
when(io.we && io.rd_addr =/= 0.U) {
|
when(io.we && io.rd_addr =/= 0.U) {
|
||||||
regs(io.rd_addr) := io.rd_data
|
regs(io.rd_addr) := io.rd_data
|
||||||
|
}
|
||||||
|
|
||||||
if (sim) {
|
|
||||||
when(io.rd_addr === 31.U) {
|
|
||||||
valid := true.B
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sim) {
|
|
||||||
io.valid_x31.get := Delay.Delay(valid, 2, false.B)
|
|
||||||
}
|
|
||||||
io.rs1_data := regs(io.rs1_addr)
|
io.rs1_data := regs(io.rs1_addr)
|
||||||
io.rs2_data := regs(io.rs2_addr)
|
io.rs2_data := regs(io.rs2_addr)
|
||||||
|
|
||||||
|
// Simulation stuff
|
||||||
|
val valid = WireInit(false.B);
|
||||||
|
when(io.we && io.rd_addr === 31.U)
|
||||||
|
{
|
||||||
|
io.x31 := io.rd_data
|
||||||
|
if (sim) {
|
||||||
|
valid := true.B
|
||||||
|
}
|
||||||
|
}.otherwise
|
||||||
|
{
|
||||||
io.x31 := regs(31)
|
io.x31 := regs(31)
|
||||||
|
}
|
||||||
|
if (sim) {
|
||||||
|
io.valid_x31.get := Delay.Delay(valid, 1, false.B)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,22 +13,30 @@ class Rv32i(sim: Boolean = true) extends Module {
|
|||||||
|
|
||||||
val reg_pc = RegInit(0.U(32.W));
|
val reg_pc = RegInit(0.U(32.W));
|
||||||
val reg_file = Module(new RegFile(sim));
|
val reg_file = Module(new RegFile(sim));
|
||||||
|
val instruction = io.ibus.rdata;
|
||||||
|
|
||||||
reg_file.io.rd_data := 0.U;
|
reg_file.io.rd_data := 0.U;
|
||||||
io.x31 := reg_file.io.x31
|
io.x31 := reg_file.io.x31
|
||||||
if (sim) {
|
if (sim) {
|
||||||
io.valid_x31.get := reg_file.io.valid_x31.get
|
io.valid_x31.get := reg_file.io.valid_x31.get
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val alu = Module(new Alu());
|
||||||
val control_unit = Module(new ControlUnit());
|
val control_unit = Module(new ControlUnit());
|
||||||
|
|
||||||
|
alu.io.opcode := control_unit.io.alu_opcode;
|
||||||
reg_file.io.we := control_unit.io.reg_file_we
|
reg_file.io.we := control_unit.io.reg_file_we
|
||||||
|
|
||||||
// Increment PC each clock
|
// Increment PC each clock
|
||||||
reg_pc := reg_pc + 4.U;
|
reg_pc := reg_pc + 4.U;
|
||||||
|
|
||||||
|
// PC delayed to execute stage for auipc op
|
||||||
|
val execute_pc = Delay.Delay(reg_pc, 1, 0.U);
|
||||||
|
|
||||||
// Fetch instruction
|
// Fetch instruction
|
||||||
io.ibus.en := true.B;
|
io.ibus.en := true.B;
|
||||||
io.ibus.addr := reg_pc;
|
io.ibus.addr := reg_pc;
|
||||||
|
|
||||||
val instruction = io.ibus.rdata;
|
|
||||||
control_unit.io.instruction := instruction;
|
control_unit.io.instruction := instruction;
|
||||||
|
|
||||||
// Decode rs1 index
|
// Decode rs1 index
|
||||||
@@ -42,10 +50,14 @@ class Rv32i(sim: Boolean = true) extends Module {
|
|||||||
reg_file.io.rd_addr := rd
|
reg_file.io.rd_addr := rd
|
||||||
|
|
||||||
// Decode imm-u
|
// Decode imm-u
|
||||||
val imm_u = instruction(31, 12)
|
val imm_u = Cat(instruction(31, 12), 0.U(12.W));
|
||||||
|
|
||||||
// Send imm-u to the register file
|
// EXECUTE
|
||||||
reg_file.io.rd_data := Cat(imm_u, 0.U(12.W))
|
|
||||||
|
alu.io.a := execute_pc;
|
||||||
|
alu.io.b := imm_u;
|
||||||
|
|
||||||
|
reg_file.io.rd_data := Mux(control_unit.io.mux_imm_alu, alu.io.out, imm_u);
|
||||||
|
|
||||||
io.dbus.addr := 0.U;
|
io.dbus.addr := 0.U;
|
||||||
io.dbus.wdata := 0.U;
|
io.dbus.wdata := 0.U;
|
||||||
|
|||||||
Reference in New Issue
Block a user