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

View file

@ -123,6 +123,8 @@ module commit_stage (
// ------------------
// 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
commit_ack_o = 1'b1;
// tell the controller to flush the I$

View file

@ -78,22 +78,15 @@ 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;
// 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;
flush_dcache = 1'b1;
fence_active_n = 1'b1;
end
// ---------------------------------
@ -106,6 +99,17 @@ module controller (
flush_id_o = 1'b1;
flush_ex_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
// ---------------------------------
@ -137,8 +141,8 @@ module controller (
// 3. Debug
// ---------------------------------
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
// for the PC GEN stage but instead tells it to take the PC we gave it
// 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
flush_pcgen_o = 1'b0;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;

View file

@ -24,6 +24,7 @@ module if_stage (
// control signals
input logic flush_i,
output logic if_busy_o, // is the IF stage busy fetching instructions?
input logic halt_i,
// fetch direction from PC Gen
input logic [63:0] fetch_address_i, // address to fetch from
input logic fetch_valid_i, // the fetch address is valid
@ -189,6 +190,17 @@ module if_stage (
else
NS = WAIT_ABORTED;
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
// ---------------------------------

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
npc_n = branch_predict_btb.predict_address;
end
// -------------------------------
// 2. Debug
// -------------------------------
@ -125,6 +126,7 @@ module pcgen_stage (
npc_n = debug_pc_i;
set_pc_n = 1'b1;
end
// -------------------------------
// 4. Exception
// -------------------------------
@ -164,6 +166,7 @@ module pcgen_stage (
fetch_address_o = fetch_address;
end
// -------------------
// Sequential Process
// -------------------