mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-24 14:17:16 -04:00
Also flush dcache on fence.i
This commit is contained in:
parent
5f9d7a5ea0
commit
97b8b12a42
5 changed files with 36 additions and 14 deletions
|
@ -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 ),
|
||||
|
|
|
@ -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$
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
// ---------------------------------
|
||||
|
|
|
@ -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
|
||||
// -------------------
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue