Skip to content

Commit

Permalink
Proper support for FENCE and FENCE.I
Browse files Browse the repository at this point in the history
  • Loading branch information
robotman2412 committed Jan 5, 2024
1 parent 4677d7a commit 2a04687
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 11 deletions.
9 changes: 8 additions & 1 deletion dev/hdl/main.sv
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ module main#(
// External data bus.
boa_mem_bus.CPU xmd_bus,

// Perform a release data fence.
output logic fence_rl,
// Perform an acquire data fence.
output logic fence_aq,
// Perform an acquire instruction fence.
output logic fence_i,

// Power management unit interface.
pmu_bus.CPU pmb
);
Expand Down Expand Up @@ -99,7 +106,7 @@ module main#(

// CPU.
logic[31:16] irq;
boa32_cpu#(32'h40001000, 32'hff000000, 0, 0) cpu(clk, rtc_clk, rst, pbus, dbus, irq);
boa32_cpu#(32'h40001000, 32'hff000000, 0, 0) cpu(clk, rtc_clk, rst, pbus, dbus, fence_rl, fence_aq, fence_i, irq);

// Interrupts.
assign irq[16] = tx_empty;
Expand Down
4 changes: 4 additions & 0 deletions fpga/cmod_a7/top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ module top(
assign xmd_bus.ready = 1;
assign xmd_bus.rdata = 0;

// Fence signals.
logic fence_rl, fence_aq, fence_i;

pmu_bus pmb();
main#(
.rom_file({boa_parentdir(`__FILE__), "/../../prog/bootloader/build/rom.mem"}),
Expand All @@ -72,6 +75,7 @@ module top(
gpio_out, gpio_oe, gpio_in,
randomness,
xmp_bus, xmi_bus, xmd_bus,
fence_rl, fence_aq, fence_i,
pmb
);

Expand Down
22 changes: 22 additions & 0 deletions hdl/boa32_cpu.sv
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ module boa32_cpu#(
// Data memory bus.
boa_mem_bus.CPU dbus,

// Perform a release data fence.
output logic fence_rl,
// Perform an acquire data fence.
output logic fence_aq,
// Perform an acquire instruction fence.
output logic fence_i,

// External interrupts 16 to 31.
input logic[31:16] irq
);
Expand Down Expand Up @@ -230,6 +237,9 @@ module boa32_cpu#(


/* ==== Data hazard avoidance ==== */
// Is an instruction fetch fence instruction.
logic is_fencei;

// EX uses RS1 value.
logic use_rs1_ex;
// EX uses RS2 value.
Expand Down Expand Up @@ -332,6 +342,7 @@ module boa32_cpu#(
// Data dependency resolution.
boa_stage_ex_fw st_ex_fw (id_ex_insn, use_rs1_ex, use_rs2_ex);
boa_stage_mem_fw st_mem_fw(ex_mem_insn, use_rs1_mem, use_rs2_mem);
assign fence_i = is_fencei && !fw_stall_id;
always @(*) begin
fw_stall_mem = mem_stall_req;
fw_stall_ex = ex_stall_req;
Expand Down Expand Up @@ -366,6 +377,11 @@ module boa32_cpu#(
// Stall ID so that MEM will produce a result that may then be used by the branch target address.
fw_stall_id = 1;
end
if (is_fencei && (ex_mem_valid || mem_wb_valid)) begin
// A fence.i instruction requires the rest of the pipeline to be emptied.
// Wait for the instructions in EX and MEM to either trap or finish.
fw_stall_id = 1;
end

fw_stall_ex |= fw_stall_mem;
fw_stall_id |= fw_stall_ex;
Expand Down Expand Up @@ -476,6 +492,8 @@ module boa32_cpu#(
clk, rst, clear_if, pbus,
// Pipeline output.
if_id_valid, if_id_pc, if_id_insn, if_id_trap, if_id_cause,
// Instruction fetch fence.
is_fencei,
// Control transfer.
fw_branch_predict, fw_branch_target, if_next_pc, fw_branch_correct, fw_branch_alt, fw_exception, fw_tvec,
// Data hazard avoicance.
Expand All @@ -487,6 +505,8 @@ module boa32_cpu#(
if_id_valid && !fw_stall_if, if_id_pc, if_id_insn, if_id_trap && !fw_stall_if, if_id_cause,
// Pipeline output.
id_ex_valid, id_ex_pc, id_ex_insn, id_ex_ilen, id_ex_use_rd, id_ex_rs1_val, id_ex_rs2_val, id_ex_branch, id_ex_branch_predict, id_ex_trap, id_ex_cause,
// Instruction fetch fence.
is_fencei,
// Control transfer.
is_xret, is_sret, is_jump, is_branch, branch_predict, branch_target,
// Write-back.
Expand All @@ -505,6 +525,8 @@ module boa32_cpu#(
);
boa_stage_mem st_mem(
clk, rst, clear_mem, dbus_in, csr,
// Data fence.
fence_rl, fence_aq,
// Pipeline input.
ex_mem_valid && !fw_stall_ex, ex_mem_pc, ex_mem_insn, ex_mem_use_rd, fw_rs1_mem ? fw_in_rs1_mem : ex_mem_rs1_val, fw_rs2_mem ? fw_in_rs2_mem : ex_mem_rs2_val, ex_mem_trap && !fw_stall_ex, ex_mem_cause,
// Pipeline output.
Expand Down
8 changes: 7 additions & 1 deletion hdl/stages/boa_stage_id.sv
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ module boa_stage_id#(
output logic[3:0] q_cause,


// FENCE.I instructions.
output logic is_fencei,

// MRET or SRET instruction.
output logic is_xret,
// Is SRET instead of MRET.
Expand Down Expand Up @@ -155,6 +158,9 @@ module boa_stage_id#(
wire is_ecall = insn[6:2] == `RV_OP_SYSTEM && insn[14:12] == 0 && insn[31:20] == 0;
wire is_ebreak = insn[6:2] == `RV_OP_SYSTEM && insn[14:12] == 0 && insn[31:20] == 1;

// FENCE.I logic.
assign is_fencei = r_valid && r_insn[6:2] == `RV_OP_MISC_MEM && r_insn[1:0] == 3 && r_insn[14:12] == 1;

// Register decoder.
logic use_rs1, use_rs2, use_rs3, use_rd;
boa_reg_decoder reg_decd(insn, use_rs1, use_rs2, use_rs3, use_rd);
Expand Down Expand Up @@ -515,7 +521,7 @@ module boa_insn_validator#(
default: begin valid = 0; end
`RV_OP_LOAD: begin valid = insn[14] ? (insn[13:12] < 2) + rv64 : (insn[13:12] < 3) + rv64; end
`RV_OP_LOAD_FP: begin valid = 0; $strobe("TODO: validity for LOAD_FP"); end
`RV_OP_MISC_MEM: begin valid = insn[14:12] == 0; end
`RV_OP_MISC_MEM: begin valid = insn[14:12] == 0 || insn[14:12] == 1; end
`RV_OP_OP_IMM: begin valid = valid_op_imm; end
`RV_OP_AUIPC: begin valid = 1; end
`RV_OP_OP_IMM_32: begin valid = rv64 && valid_op_imm; end
Expand Down
14 changes: 10 additions & 4 deletions hdl/stages/boa_stage_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ module boa_stage_aligned_if#(
output logic[3:0] q_cause,


// Instruction fetch fence.
input logic fence_i,

// Unconditional control transfer or branch predicted as taken.
input logic fw_branch_predict,
// Branch target address.
Expand Down Expand Up @@ -88,7 +91,7 @@ module boa_stage_aligned_if#(
assign q_trap = valid && q_pc[1];
assign q_cause = `RV_ECAUSE_IALIGN;

assign valid = pbus.ready && !fw_branch_predict && !fw_branch_correct && !clear;
assign valid = pbus.ready && !fw_branch_predict && !fw_branch_correct && !clear && !fence_i;
assign q_pc = pc;
assign q_insn = pbus.rdata;
always @(posedge clk) begin
Expand Down Expand Up @@ -131,6 +134,9 @@ module boa_stage_if#(
output logic[3:0] q_cause,


// Instruction fetch fence.
input logic fence_i,

// Unconditional control transfer or branch predicted as taken.
input logic fw_branch_predict,
// Branch target address.
Expand Down Expand Up @@ -201,7 +207,7 @@ module boa_stage_if#(
generate
for (x = 1; x < cache_depth; x = x + 1) begin
always @(posedge clk) begin
if (rst) begin
if (rst || fence_i) begin
icache[x] <= 'bx;
acache[x] <= 'bx;
cvalid[x] <= 0;
Expand Down Expand Up @@ -237,7 +243,7 @@ module boa_stage_if#(
assign pbus.we = 0;
assign pbus.wdata = 'bx;
always @(*) begin
if (rst) begin
if (rst || fence_i) begin
// Reset; don't do anything.
pbus.re = 0;
pbus.addr = 'bx;
Expand All @@ -257,7 +263,7 @@ module boa_stage_if#(
end

// Pipeline output logic.
assign q_valid = insn_valid && !clear;
assign q_valid = insn_valid && !clear && !fence_i;
assign q_trap = 0;
assign q_cause = 'bx;

Expand Down
11 changes: 11 additions & 0 deletions hdl/stages/boa_stage_mem.sv
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ module boa_stage_mem(
// CSR access bus.
boa_csr_bus.CPU csr,

// Perform a release data fence.
output logic fence_rl,
// Perform an acquire data fence.
output logic fence_aq,


// EX/MEM: Result valid.
input logic d_valid,
Expand Down Expand Up @@ -98,6 +103,12 @@ module boa_stage_mem(
logic[3:0] cause;


/* ==== Fence logic ==== */
// Is this a FENCE instruction?
logic is_fence = r_valid && !clear && !fw_stall_mem && r_insn[6:2] == `RV_OP_MISC_MEM && r_insn[14:12] == 0;
assign fence_aq = is_fence && r_insn[27:24] != 0;
assign fence_rl = is_fence && r_insn[23:20] != 0;

/* ==== Memory access logic ==== */
// Alignment error.
logic ealign;
Expand Down
9 changes: 7 additions & 2 deletions prog/bootloader/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ void p_speed() {
}

// Wait for UART to finish sending.
while (UART0.status.tx_busy || UART0.status.rx_hasdat);
while (UART0.status.tx_busy || UART0.status.rx_hasdat)
;
// Configure new frequency.
UART0.clk_div = divider;
}
Expand Down Expand Up @@ -289,12 +290,16 @@ void isr() {

// Does stuff?
void main() {
asm("fence");
asm("fence.i");

// Blink the LED red at startup.
if (!IS_SIMULATOR) {
mtime = 0;
GPIO.oe = 1 << 8;
GPIO.port = 1 << 8;
while (mtime < 100000);
while (mtime < 100000)
;
GPIO.oe = 0;
GPIO.port = 0;
}
Expand Down
2 changes: 1 addition & 1 deletion prog/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ target_compile_definitions(${target} PUBLIC

target_compile_options(${target} PUBLIC
-ffreestanding -nostdlib -nodefaultlibs -nostdinc -O2
-march=rv32imc_zicsr -mabi=ilp32
-march=rv32imc_zicsr_zifencei -mabi=ilp32
-ffunction-sections
)

Expand Down
4 changes: 4 additions & 0 deletions sim/dev/hdl/top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ module top(
boa_mem_bus#(24) xmd_bus();
pmu_bus pmb();

// Fence signals.
logic fence_rl, fence_aq, fence_i;

// Main microcontroller device.
main#(
.rom_file({boa_parentdir(`__FILE__), "/../obj_dir/rom.mem"}),
Expand All @@ -40,6 +43,7 @@ module top(
gpio_out, gpio_oe, gpio_in,
randomness,
xmp_bus, xmi_bus, xmd_bus,
fence_rl, fence_aq, fence_i,
pmb
);

Expand Down
3 changes: 2 additions & 1 deletion sim/riscv-tests/hdl/top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ module top(
end

// The boa CPU core.
logic fence_rl, fence_aq, fence_i;
boa32_cpu#(
.entrypoint(32'h8000_0000),
.has_c(1),
.has_m(1)
) cpu (
clk, clk, rst, pbus, dbus, 0
clk, clk, rst, pbus, dbus, fence_rl, fence_aq, fence_i, 0
);
endmodule

2 changes: 1 addition & 1 deletion sim/riscv-tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def list_tests(file):
def compile_test(test):
cc = os.environ.get("CC", "riscv32-unknown-elf-gcc")
cp = os.environ.get("OBJCOPY", "riscv32-unknown-elf-objcopy")
isa = os.environ.get("ISA", "rv32imc_zicsr")
isa = os.environ.get("ISA", "rv32imc_zicsr_zifencei")
abi = os.environ.get("ABI", "ilp32")

Path("build/"+test).parent.mkdir(parents=True, exist_ok=True)
Expand Down

0 comments on commit 2a04687

Please sign in to comment.