Stage 11: Passing tests
This commit is contained in:
12
bench/tests/op/lb.s
Normal file
12
bench/tests/op/lb.s
Normal file
@@ -0,0 +1,12 @@
|
||||
# expected: FFFFFFFB, FFFFFFFB
|
||||
.text
|
||||
_start:
|
||||
addi x1, x0, 0x0FB
|
||||
nop # Next instruction depends on previous register op
|
||||
sb x1, 100(x0)
|
||||
lb x31, 100(x0)
|
||||
|
||||
addi x1, x0, 0x0FB
|
||||
nop # Next instruction depends on previous register op
|
||||
sb x1, 106(x0)
|
||||
lb x31, 106(x0)
|
||||
12
bench/tests/op/lbu.s
Normal file
12
bench/tests/op/lbu.s
Normal file
@@ -0,0 +1,12 @@
|
||||
# expected: 000000FB, 000000FB
|
||||
.text
|
||||
_start:
|
||||
addi x1, x0, 0x0FB
|
||||
nop # Next instruction depends on previous register op
|
||||
sb x1, 100(x0)
|
||||
lbu x31, 100(x0)
|
||||
|
||||
addi x1, x0, 0x0FB
|
||||
nop # Next instruction depends on previous register op
|
||||
sb x1, 106(x0)
|
||||
lbu x31, 106(x0)
|
||||
16
bench/tests/op/lh.s
Normal file
16
bench/tests/op/lh.s
Normal file
@@ -0,0 +1,16 @@
|
||||
# expected: FFFFF1BC, FFFFF1BC
|
||||
.text
|
||||
_start:
|
||||
lui x1, 0xF
|
||||
nop # Next instruction depends on previous register op
|
||||
ori x1, x1, 0x1BC
|
||||
nop # Next instruction depends on previous register op
|
||||
sh x1, 100(x0)
|
||||
lh x31, 100(x0)
|
||||
|
||||
lui x1, 0xF
|
||||
nop # Next instruction depends on previous register op
|
||||
ori x1, x1, 0x1BC
|
||||
nop # Next instruction depends on previous register op
|
||||
sh x1, 106(x0)
|
||||
lh x31, 106(x0)
|
||||
16
bench/tests/op/lhu.s
Normal file
16
bench/tests/op/lhu.s
Normal file
@@ -0,0 +1,16 @@
|
||||
# expected: 0000F1BC, 0000F1BC
|
||||
.text
|
||||
_start:
|
||||
lui x1, 0xF
|
||||
nop # Next instruction depends on previous register op
|
||||
ori x1, x1, 0x1BC
|
||||
nop # Next instruction depends on previous register op
|
||||
sh x1, 100(x0)
|
||||
lhu x31, 100(x0)
|
||||
|
||||
lui x1, 0xF
|
||||
nop # Next instruction depends on previous register op
|
||||
ori x1, x1, 0x1BC
|
||||
nop # Next instruction depends on previous register op
|
||||
sh x1, 106(x0)
|
||||
lhu x31, 106(x0)
|
||||
9
bench/tests/op/lw.s
Normal file
9
bench/tests/op/lw.s
Normal file
@@ -0,0 +1,9 @@
|
||||
# expected: 123451BC
|
||||
.text
|
||||
_start:
|
||||
lui x1, 0x12345
|
||||
nop # Next instruction depends on previous register op
|
||||
ori x1, x1, 0x1BC
|
||||
nop # Next instruction depends on previous register op
|
||||
sw x1, 100(x0)
|
||||
lw x31, 100(x0)
|
||||
@@ -20,6 +20,9 @@ class CUInterface extends Bundle {
|
||||
val memory_size = Output(DMemSize())
|
||||
val memory_en = Output(Bool())
|
||||
val memory_we = Output(Bool())
|
||||
val memory_sign_extend = Output(
|
||||
Bool()
|
||||
) // Wether to signe extend the output of the memory for bytes, half loads
|
||||
|
||||
// Muxers
|
||||
// The naming convention is as follows : mux_xxx_yyy.
|
||||
@@ -45,6 +48,9 @@ class CUInterface extends Bundle {
|
||||
|
||||
// Selects pc or write back for register write
|
||||
val mux_writeback_pc = Output(Bool())
|
||||
|
||||
// Selects aluout or memory data out for writeback_line
|
||||
val mux_executeout_dout = Output(Bool())
|
||||
}
|
||||
|
||||
object OpType extends ChiselEnum {
|
||||
@@ -101,6 +107,7 @@ class ControlUnit() extends Module {
|
||||
io.memory_size := DMemSize.Word
|
||||
io.memory_en := false.B
|
||||
io.memory_we := false.B
|
||||
io.memory_sign_extend := false.B;
|
||||
io.mux_alu_imm := true.B;
|
||||
io.mux_rega_pc := true.B;
|
||||
io.mux_regb_imm := true.B;
|
||||
@@ -108,6 +115,7 @@ class ControlUnit() extends Module {
|
||||
io.mux_regpc_executepc := true.B;
|
||||
io.mux_writeback_pc := true.B;
|
||||
io.mux_pcadder_writeback := true.B;
|
||||
io.mux_executeout_dout := true.B;
|
||||
|
||||
// Decode instruction
|
||||
val opcode = io.instruction(6, 0);
|
||||
@@ -447,21 +455,39 @@ class ControlUnit() extends Module {
|
||||
val LB = "b000".U
|
||||
val LH = "b001".U
|
||||
val LW = "b010".U
|
||||
val LBU = "b100".U
|
||||
val LHU = "b101".U
|
||||
}
|
||||
|
||||
io.alu_opcode := AluOpCode.Add
|
||||
io.mux_alu_imm := true.B
|
||||
io.mux_rega_pc := true.B
|
||||
io.mux_regb_imm := false.B
|
||||
io.mux_writeback_pc := true.B;
|
||||
io.mux_executeout_dout := false.B;
|
||||
io.reg_file_we := true.B
|
||||
io.memory_en := true.B
|
||||
io.memory_we := false.B
|
||||
switch(funct3) {
|
||||
// Byte load
|
||||
is(Funct3.LB) {
|
||||
io.memory_size := DMemSize.Byte
|
||||
io.memory_sign_extend := true.B;
|
||||
}
|
||||
is(Funct3.LBU) {
|
||||
io.memory_size := DMemSize.Byte
|
||||
}
|
||||
|
||||
// Half load
|
||||
is(Funct3.LH) {
|
||||
io.memory_size := DMemSize.Half
|
||||
io.memory_sign_extend := true.B;
|
||||
}
|
||||
is(Funct3.LHU) {
|
||||
io.memory_size := DMemSize.Half
|
||||
}
|
||||
|
||||
// Word load
|
||||
is(Funct3.LW) {
|
||||
io.memory_size := DMemSize.Word
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import chisel3._
|
||||
import chisel3.util.switch
|
||||
import chisel3.util.is
|
||||
import chisel3.util.Cat
|
||||
import chisel3.util.Fill
|
||||
|
||||
object DMemSize extends ChiselEnum {
|
||||
val Byte, Half, Word = Value
|
||||
@@ -20,14 +21,16 @@ class DMem extends Module {
|
||||
val data_in = Input(UInt(32.W))
|
||||
|
||||
val data_out = Output(UInt(32.W))
|
||||
val sign_extend = Input(Bool())
|
||||
})
|
||||
io.dbus.addr := Cat(io.addr(31, 2), 0.U(2.W));
|
||||
io.dbus.en := io.en;
|
||||
io.data_out := 0.U
|
||||
|
||||
val bytes_enabled = VecInit(false.B, false.B, false.B, false.B)
|
||||
val data = WireInit(0.U(32.W))
|
||||
|
||||
when(io.we) {
|
||||
when(io.we && io.en) {
|
||||
switch(io.size) {
|
||||
is(DMemSize.Byte) {
|
||||
bytes_enabled(io.addr(1, 0)) := true.B
|
||||
@@ -47,9 +50,37 @@ class DMem extends Module {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Data out is available one cycle after the read request
|
||||
val read_addr = Delay.Delay(io.addr, 1, 0.U);
|
||||
val read_sign_extend = Delay.Delay(io.sign_extend, 1, false.B);
|
||||
when(Delay.Delay(io.en && !io.we, 1, false.B)) {
|
||||
switch(Delay.Delay(io.size, 1, DMemSize.Byte)) {
|
||||
is(DMemSize.Byte) {
|
||||
val dout = (io.dbus.rdata >>
|
||||
(read_addr(1) * 16.U + read_addr(0) * 8.U)) & 0xff.U;
|
||||
io.data_out := dout | Mux(
|
||||
read_sign_extend,
|
||||
Fill(24, dout(7)) << 8.U,
|
||||
0.U
|
||||
);
|
||||
}
|
||||
is(DMemSize.Half) {
|
||||
val dout = (io.dbus.rdata >>
|
||||
(read_addr(1) * 16.U)) & 0xffff.U;
|
||||
io.data_out := dout | Mux(
|
||||
read_sign_extend,
|
||||
Fill(16, dout(15)) << 16.U,
|
||||
0.U
|
||||
);
|
||||
}
|
||||
is(DMemSize.Word) {
|
||||
io.data_out := io.dbus.rdata
|
||||
}
|
||||
}
|
||||
}
|
||||
io.dbus.be := bytes_enabled
|
||||
|
||||
io.dbus.wdata := data
|
||||
|
||||
io.data_out := 0.U
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ class Rv32i(sim: Boolean = true) extends Module {
|
||||
dmem.io.en := control_unit.io.memory_en
|
||||
dmem.io.we := control_unit.io.memory_we
|
||||
dmem.io.size := control_unit.io.memory_size
|
||||
dmem.io.sign_extend := control_unit.io.memory_sign_extend
|
||||
|
||||
control_unit.io.alu_comp_result := alu.io.comp_result
|
||||
|
||||
@@ -35,13 +36,23 @@ class Rv32i(sim: Boolean = true) extends Module {
|
||||
// True if the instruction in the execute stage is a jump
|
||||
val is_jump = Delay.Delay(control_unit.io.is_jump, 1, false.B);
|
||||
|
||||
// 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, 0b00000000000000000000000000010011.U, io.ibus.rdata);
|
||||
val instruction =
|
||||
Mux(is_jump, "b00000000000000000000000000010011".U, io.ibus.rdata);
|
||||
|
||||
immediate_decoder.io.instruction := instruction
|
||||
immediate_decoder.io.op_type := control_unit.io.optype
|
||||
alu.io.opcode := control_unit.io.alu_opcode;
|
||||
reg_file.io.we := control_unit.io.reg_file_we
|
||||
|
||||
// Reg file write-enable
|
||||
reg_regile_we := control_unit.io.reg_file_we;
|
||||
reg_file.io.we := reg_regile_we;
|
||||
|
||||
// Increment PC each clock
|
||||
val pc_adder_out = Mux(
|
||||
@@ -54,7 +65,6 @@ class Rv32i(sim: Boolean = true) extends Module {
|
||||
immediate_decoder.io.immediate
|
||||
);
|
||||
|
||||
|
||||
// Fetch instruction
|
||||
io.ibus.en := true.B;
|
||||
io.ibus.addr := reg_pc;
|
||||
@@ -62,14 +72,15 @@ class Rv32i(sim: Boolean = true) extends Module {
|
||||
control_unit.io.instruction := instruction;
|
||||
|
||||
// Decode rs1 index
|
||||
val rs1 = instruction(19, 15)
|
||||
reg_file.io.rs1_addr := rs1
|
||||
val rs1_index = instruction(19, 15)
|
||||
reg_file.io.rs1_addr := rs1_index
|
||||
// Decode rs2 index
|
||||
val rs2 = instruction(24, 20)
|
||||
reg_file.io.rs2_addr := rs2
|
||||
val rs2_index = instruction(24, 20)
|
||||
reg_file.io.rs2_addr := rs2_index
|
||||
// Decode rd index
|
||||
val rd = instruction(11, 7)
|
||||
reg_file.io.rd_addr := rd
|
||||
val rd_index = instruction(11, 7)
|
||||
reg_rd_index := rd_index;
|
||||
reg_file.io.rd_addr := reg_rd_index;
|
||||
|
||||
// EXECUTE
|
||||
|
||||
@@ -82,21 +93,33 @@ class Rv32i(sim: Boolean = true) extends Module {
|
||||
);
|
||||
alu.io.b := Mux(control_unit.io.mux_regb_imm, reg_file.io.rs2_data, imm);
|
||||
|
||||
val writeback_line = Mux(control_unit.io.mux_alu_imm, alu.io.out, imm);
|
||||
reg_file.io.rd_data :=
|
||||
Mux(
|
||||
control_unit.io.mux_writeback_pc,
|
||||
writeback_line,
|
||||
reg_pc
|
||||
);
|
||||
// Select what to send on writeback line
|
||||
val execute_out = Mux(control_unit.io.mux_alu_imm, alu.io.out, imm);
|
||||
reg_execute_out := execute_out;
|
||||
|
||||
reg_pc := Mux(control_unit.io.mux_pcadder_writeback,
|
||||
pc_adder_out,
|
||||
writeback_line
|
||||
);
|
||||
reg_mux_executeout_dout := control_unit.io.mux_executeout_dout;
|
||||
val writeback_line = Mux(
|
||||
reg_mux_executeout_dout,
|
||||
reg_execute_out,
|
||||
dmem.io.data_out
|
||||
);
|
||||
|
||||
reg_file.io.rd_data :=
|
||||
Mux(
|
||||
Delay.Delay(control_unit.io.mux_writeback_pc, 1, true.B),
|
||||
writeback_line,
|
||||
reg_pc
|
||||
);
|
||||
|
||||
// Writeback pipelining registers
|
||||
reg_pc := Mux(
|
||||
control_unit.io.mux_pcadder_writeback,
|
||||
pc_adder_out,
|
||||
writeback_line
|
||||
);
|
||||
|
||||
dmem.io.data_in := reg_file.io.rs2_data
|
||||
dmem.io.addr := writeback_line
|
||||
dmem.io.addr := execute_out
|
||||
|
||||
io.ibus.wdata := 0.U;
|
||||
io.ibus.be := VecInit(false.B, false.B, false.B, false.B)
|
||||
|
||||
Reference in New Issue
Block a user