Also flush dcache on fence.i

This commit is contained in:
Florian Zaruba 2017-08-07 16:07:48 +02:00
parent 5f9d7a5ea0
commit 97b8b12a42
5 changed files with 36 additions and 14 deletions

View file

@ -241,7 +241,7 @@ module ariane
logic fence_i_commit_controller; logic fence_i_commit_controller;
logic fence_commit_controller; logic fence_commit_controller;
logic sfence_vma_commit_controller; logic sfence_vma_commit_controller;
logic halt_ctrl_commit; logic halt_ctrl;
logic halt_debug_ctrl; logic halt_debug_ctrl;
logic halt_csr_ctrl; logic halt_csr_ctrl;
// -------------- // --------------
@ -290,6 +290,7 @@ module ariane
// --------- // ---------
if_stage if_stage_i ( if_stage if_stage_i (
.flush_i ( flush_ctrl_if ), .flush_i ( flush_ctrl_if ),
.halt_i ( halt_ctrl ),
.if_busy_o ( if_ready_if_pcgen ), .if_busy_o ( if_ready_if_pcgen ),
.fetch_address_i ( fetch_address_pcgen_if ), .fetch_address_i ( fetch_address_pcgen_if ),
.fetch_valid_i ( fetch_valid_pcgen_if ), .fetch_valid_i ( fetch_valid_pcgen_if ),
@ -475,7 +476,7 @@ module ariane
// Commit // Commit
// --------- // ---------
commit_stage commit_stage_i ( commit_stage commit_stage_i (
.halt_i ( halt_ctrl_commit ), .halt_i ( halt_ctrl ),
.exception_o ( ex_commit ), .exception_o ( ex_commit ),
.commit_instr_i ( commit_instr_id_commit ), .commit_instr_i ( commit_instr_id_commit ),
.commit_ack_o ( commit_ack ), .commit_ack_o ( commit_ack ),
@ -552,7 +553,7 @@ module ariane
.halt_csr_i ( halt_csr_ctrl ), .halt_csr_i ( halt_csr_ctrl ),
.halt_debug_i ( halt_debug_ctrl ), .halt_debug_i ( halt_debug_ctrl ),
.debug_set_pc_i ( set_pc_debug ), .debug_set_pc_i ( set_pc_debug ),
.halt_o ( halt_ctrl_commit ), .halt_o ( halt_ctrl ),
// control ports // control ports
.eret_i ( eret ), .eret_i ( eret ),
.ex_valid_i ( ex_commit.valid ), .ex_valid_i ( ex_commit.valid ),

View file

@ -123,6 +123,8 @@ module commit_stage (
// ------------------ // ------------------
// FENCE.I Logic // FENCE.I Logic
// ------------------ // ------------------
// Fence synchronizes data and instruction streams. That means that we need to flush the private icache
// and the private dcache. This is the most expensive instruction.
if (commit_instr_i.op == FENCE_I) begin if (commit_instr_i.op == FENCE_I) begin
commit_ack_o = 1'b1; commit_ack_o = 1'b1;
// tell the controller to flush the I$ // tell the controller to flush the I$

View file

@ -78,22 +78,15 @@ module controller (
// FENCE // FENCE
// --------------------------------- // ---------------------------------
if (fence_i) begin if (fence_i) begin
fence_active_n = 1'b1;
flush_dcache = 1'b1;
// this can be seen as a CSR instruction with side-effect // this can be seen as a CSR instruction with side-effect
flush_pcgen_o = 1'b1; flush_pcgen_o = 1'b1;
flush_if_o = 1'b1; flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1; flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1; flush_id_o = 1'b1;
flush_ex_o = 1'b1; flush_ex_o = 1'b1;
end
// wait for the acknowledge here flush_dcache = 1'b1;
if (flush_dcache_ack_i && fence_active_q) begin fence_active_n = 1'b1;
fence_active_n = 1'b0;
// keep the flush dcache signal high as long as we didn't get the acknowledge from the cache
end else if (fence_active_q) begin
flush_dcache = 1'b1;
end end
// --------------------------------- // ---------------------------------
@ -106,6 +99,17 @@ module controller (
flush_id_o = 1'b1; flush_id_o = 1'b1;
flush_ex_o = 1'b1; flush_ex_o = 1'b1;
flush_icache_o = 1'b1; flush_icache_o = 1'b1;
flush_dcache = 1'b1;
fence_active_n = 1'b1;
end
// wait for the acknowledge here
if (flush_dcache_ack_i && fence_active_q) begin
fence_active_n = 1'b0;
// keep the flush dcache signal high as long as we didn't get the acknowledge from the cache
end else if (fence_active_q) begin
flush_dcache = 1'b1;
end end
// --------------------------------- // ---------------------------------
@ -137,8 +141,8 @@ module controller (
// 3. Debug // 3. Debug
// --------------------------------- // ---------------------------------
if (ex_valid_i || eret_i || debug_set_pc_i) begin if (ex_valid_i || eret_i || debug_set_pc_i) begin
// don't flush pcgen as we want to take the exception, flush pcgen is not a flush signal // don't flush pcgen as we want to take the exception: Flush PCGen is not a flush signal
// for the PC GEN stage but instead tells it to take the PC we gave it // for the PC Gen stage but instead tells it to take the PC we gave it
flush_pcgen_o = 1'b0; flush_pcgen_o = 1'b0;
flush_if_o = 1'b1; flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1; flush_unissued_instr_o = 1'b1;

View file

@ -24,6 +24,7 @@ module if_stage (
// control signals // control signals
input logic flush_i, input logic flush_i,
output logic if_busy_o, // is the IF stage busy fetching instructions? output logic if_busy_o, // is the IF stage busy fetching instructions?
input logic halt_i,
// fetch direction from PC Gen // fetch direction from PC Gen
input logic [63:0] fetch_address_i, // address to fetch from input logic [63:0] fetch_address_i, // address to fetch from
input logic fetch_valid_i, // the fetch address is valid input logic fetch_valid_i, // the fetch address is valid
@ -189,6 +190,17 @@ module if_stage (
else else
NS = WAIT_ABORTED; NS = WAIT_ABORTED;
end end
// -------------
// Halt
// -------------
// halt the instruction interface if we halt the core:
// the idea behind this is mainly in the case of an fence.i. For that instruction we need to flush both private caches
// now it could be the case that the icache flush finishes earlier than the dcache flush (most likely even). In that case
// a fetch can return stale data so we need to wait for the dcache flush to finish before making any new request.
// The solution is to check if the core is halted and in that case do not make any new request.
if (halt_i)
instr_req_o = 1'b0;
end end
// --------------------------------- // ---------------------------------

View file

@ -118,6 +118,7 @@ module pcgen_stage (
if (if_ready_i && branch_predict_btb.valid && branch_predict_btb.predict_taken && !fetch_address[1]) begin if (if_ready_i && branch_predict_btb.valid && branch_predict_btb.predict_taken && !fetch_address[1]) begin
npc_n = branch_predict_btb.predict_address; npc_n = branch_predict_btb.predict_address;
end end
// ------------------------------- // -------------------------------
// 2. Debug // 2. Debug
// ------------------------------- // -------------------------------
@ -125,6 +126,7 @@ module pcgen_stage (
npc_n = debug_pc_i; npc_n = debug_pc_i;
set_pc_n = 1'b1; set_pc_n = 1'b1;
end end
// ------------------------------- // -------------------------------
// 4. Exception // 4. Exception
// ------------------------------- // -------------------------------
@ -164,6 +166,7 @@ module pcgen_stage (
fetch_address_o = fetch_address; fetch_address_o = fetch_address;
end end
// ------------------- // -------------------
// Sequential Process // Sequential Process
// ------------------- // -------------------