diff --git a/Makefile b/Makefile index e6bea45cc..06d9c87ed 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ max_cycles = 10000000 # Test case to run test_case = core_test # QuestaSim Version -questa_version = -10.6 +questa_version = compile_flag = +cover=bcfst+/dut -incr -64 -nologo -quiet -suppress 13262 -permissive # Moore binary moore = ~fschuiki/bin/moore diff --git a/include/ariane_pkg.sv b/include/ariane_pkg.sv index b6e364505..927e0567b 100644 --- a/include/ariane_pkg.sv +++ b/include/ariane_pkg.sv @@ -91,7 +91,7 @@ package ariane_pkg; // set lower than operations SLTS, SLTU, // CSR functions - MRET, SRET, ECALL, WFI, FENCE_I, SFENCE_VMA, CSR_WRITE, CSR_READ, CSR_SET, CSR_CLEAR, + MRET, SRET, ECALL, WFI, FENCE, FENCE_I, SFENCE_VMA, CSR_WRITE, CSR_READ, CSR_SET, CSR_CLEAR, // LSU functions LD, SD, LW, LWU, SW, LH, LHU, SH, LB, SB, LBU } fu_op; diff --git a/src/ariane.sv b/src/ariane.sv index 66c605cc6..34ef516dd 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -37,6 +37,8 @@ module ariane input logic test_en_i, // enable all clock gates for testing output logic flush_icache_o, // request to flush icache + output logic flush_dcache_o, // request to flush the dcache + input logic flush_dcache_ack_i, // dcache flushed successfully // CPU Control Signals input logic fetch_enable_i, output logic core_busy_o, @@ -233,6 +235,7 @@ module ariane logic flush_ctrl_ex; logic flush_tlb_ctrl_ex; logic fence_i_commit_controller; + logic fence_commit_controller; logic sfence_vma_commit_controller; logic halt_ctrl_commit; logic halt_debug_ctrl; @@ -480,6 +483,7 @@ module ariane .csr_rdata_i ( csr_rdata_csr_commit ), .csr_exception_i ( csr_exception_csr_commit ), .fence_i_o ( fence_i_commit_controller ), + .fence_o ( fence_commit_controller ), .sfence_vma_o ( sfence_vma_commit_controller ), .* ); @@ -546,6 +550,7 @@ module ariane .flush_csr_i ( flush_csr_ctrl ), .resolved_branch_i ( resolved_branch ), .fence_i_i ( fence_i_commit_controller ), + .fence_i ( fence_commit_controller ), .sfence_vma_i ( sfence_vma_commit_controller ), .* diff --git a/src/commit_stage.sv b/src/commit_stage.sv index 034bdb40b..34a6d70fc 100644 --- a/src/commit_stage.sv +++ b/src/commit_stage.sv @@ -43,7 +43,8 @@ module commit_stage ( output logic commit_lsu_o, // commit the pending store input logic no_st_pending_i, // there is no store pending output logic commit_csr_o, // commit the pending CSR instruction - output logic fence_i_o, // flush icache and pipeline + output logic fence_i_o, // flush icache and pipeline + output logic fence_o, // flush dcache and pipeline output logic sfence_vma_o // flush TLBs and pipeline ); @@ -64,6 +65,7 @@ module commit_stage ( csr_op_o = ADD; // this corresponds to a CSR NOP csr_wdata_o = 64'b0; fence_i_o = 1'b0; + fence_o = 1'b0; sfence_vma_o = 1'b0; // we will not commit the instruction if we took an exception @@ -119,6 +121,14 @@ module commit_stage ( // tell the controller to flush the I$ fence_i_o = 1'b1; end + // ------------------ + // FENCE Logic + // ------------------ + if (commit_instr_i.op == FENCE) begin + commit_ack_o = 1'b1; + // tell the controller to flush the D$ + fence_o = 1'b1; + end end end diff --git a/src/controller.sv b/src/controller.sv index 972db773c..5e177499a 100644 --- a/src/controller.sv +++ b/src/controller.sv @@ -20,6 +20,8 @@ import ariane_pkg::*; module controller ( + input logic clk_i, + input logic rst_ni, output logic flush_bp_o, // Flush branch prediction data structures output logic flush_pcgen_o, // Flush PC Generation Stage output logic flush_if_o, // Flush the IF stage @@ -27,6 +29,8 @@ module controller ( output logic flush_id_o, // Flush ID stage output logic flush_ex_o, // Flush EX stage output logic flush_icache_o, // Flush ICache + output logic flush_dcache_o, // Flush DCache + input logic flush_dcache_ack_i, // Acknowledge the whole DCache Flush output logic flush_tlb_o, // Flush TLBs input logic halt_csr_i, // Halt request from CSR (WFI instruction) @@ -38,15 +42,19 @@ module controller ( input branchpredict resolved_branch_i, // We got a resolved branch, check if we need to flush the front-end input logic flush_csr_i, // We got an instruction which altered the CSR, flush the pipeline input logic fence_i_i, // fence.i in + input logic fence_i, // fence in input logic sfence_vma_i // We got an instruction to flush the TLBs and pipeline ); // flush branch prediction assign flush_bp_o = 1'b0; - + // active fence - high if we are currently flushing the dcache + logic fence_active_n, fence_active_q; + logic flush_dcache; // ------------ // Flush CTRL // ------------ always_comb begin : flush_ctrl + fence_active_n = fence_active_q; flush_pcgen_o = 1'b0; flush_if_o = 1'b0; flush_unissued_instr_o = 1'b0; @@ -54,6 +62,7 @@ module controller ( flush_ex_o = 1'b0; flush_tlb_o = 1'b0; flush_icache_o = 1'b0; + flush_dcache = 1'b0; // ------------ // Mis-predict // ------------ @@ -68,6 +77,21 @@ module controller ( // --------------------------------- // FENCE // --------------------------------- + if (fence_i) begin + fence_active_n = 1'b1; + flush_dcache = 1'b1; + // this can be seen as a CSR instruction with side-effect + flush_pcgen_o = 1'b1; + flush_if_o = 1'b1; + flush_unissued_instr_o = 1'b1; + flush_id_o = 1'b1; + flush_ex_o = 1'b1; + end + + // wait for the acknowledge here + if (flush_dcache_ack_i && fence_active_q) begin + fence_active_n = 1'b0; + end // --------------------------------- // FENCE.I @@ -80,6 +104,7 @@ module controller ( flush_ex_o = 1'b1; flush_icache_o = 1'b1; end + // --------------------------------- // SFENCE.VMA // --------------------------------- @@ -123,6 +148,21 @@ module controller ( // Halt Logic // ---------------------- always_comb begin - halt_o = halt_debug_i || halt_csr_i; + // halt the core if the fence is active + halt_o = halt_debug_i || halt_csr_i || fence_active_q; + end + + // ---------------------- + // Registers + // ---------------------- + always_ff @(posedge clk_i or negedge rst_ni) begin + if(~rst_ni) begin + fence_active_q <= 1'b0; + flush_dcache_o <= 1'b0; + end else begin + fence_active_q <= fence_active_n; + // register on the flush signal, this signal might be critical + flush_dcache_o <= flush_dcache; + end end endmodule diff --git a/src/decoder.sv b/src/decoder.sv index 1ab808710..688b8b1a2 100644 --- a/src/decoder.sv +++ b/src/decoder.sv @@ -205,13 +205,11 @@ module decoder ( instruction_o.rs1 = '0; instruction_o.rs2 = '0; instruction_o.rd = '0; - // FENCE - // TODO: Implement end else begin - // Currently implemented as NOP - instruction_o.fu = ALU; - instruction_o.op = ADD; + // Currently implemented as a whole DCache flush boldly ignoring other things + instruction_o.fu = CSR; + instruction_o.op = FENCE; instruction_o.rs1 = '0; instruction_o.rs2 = '0; instruction_o.rd = '0;