mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-24 14:17:16 -04:00
Fix issue with next PC calculation
This commit is contained in:
parent
45de87b551
commit
4f73473b1b
16 changed files with 109 additions and 77 deletions
6
Makefile
6
Makefile
|
@ -12,7 +12,7 @@ max_cycles ?= 10000000
|
|||
# Test case to run
|
||||
test_case ?= core_test
|
||||
# QuestaSim Version
|
||||
questa_version ?= -10.6b
|
||||
questa_version ?=
|
||||
# verilator version
|
||||
verilator ?= verilator
|
||||
# preset which runs a single test
|
||||
|
@ -24,7 +24,7 @@ ariane_pkg := include/ariane_pkg.sv include/nbdcache_pkg.sv
|
|||
util := $(wildcard src/util/*.svh) src/util/instruction_tracer_pkg.sv src/util/instruction_tracer_if.sv \
|
||||
src/util/generic_fifo.sv src/util/cluster_clock_gating.sv src/util/behav_sram.sv
|
||||
# test targets
|
||||
tests := alu scoreboard fifo dcache_arbiter store_queue lsu core fetch_fifo icache
|
||||
tests := alu scoreboard fifo dcache_arbiter store_queue lsu core fetch_fifo
|
||||
# UVM agents
|
||||
agents := $(wildcard tb/agents/*/*.sv*)
|
||||
# path to interfaces
|
||||
|
@ -41,7 +41,7 @@ dpi := $(wildcard tb/dpi/*)
|
|||
src := $(wildcard src/*.sv) $(wildcard tb/common/*.sv) $(wildcard src/axi2per/*.sv) $(wildcard src/axi_slice/*.sv) \
|
||||
$(wildcard src/axi_node/*.sv) $(wildcard src/axi_mem_if/*.sv)
|
||||
# look for testbenches
|
||||
tbs := tb/alu_tb.sv tb/core_tb.sv tb/dcache_arbiter_tb.sv tb/store_queue_tb.sv tb/scoreboard_tb.sv tb/fifo_tb.sv tb/icache_tb.sv
|
||||
tbs := tb/alu_tb.sv tb/core_tb.sv tb/dcache_arbiter_tb.sv tb/store_queue_tb.sv tb/scoreboard_tb.sv tb/fifo_tb.sv
|
||||
|
||||
# RISCV-tests path
|
||||
riscv-test-dir := tmp/riscv-tests/build/isa
|
||||
|
|
0
src/ariane.sv
Executable file → Normal file
0
src/ariane.sv
Executable file → Normal file
|
@ -1 +1 @@
|
|||
Subproject commit fd48f4e1b2df100e80caa1787a7a29551639afeb
|
||||
Subproject commit 2f1e322c07b483990f31b22e20b8db635b1bec97
|
|
@ -1 +1 @@
|
|||
Subproject commit 41c04b338e1d8778470f6c28962270d31bb4fdb1
|
||||
Subproject commit f8886bd3f2d4967aaccff15b67bf1f9e1a0e3453
|
0
src/compressed_decoder.sv
Executable file → Normal file
0
src/compressed_decoder.sv
Executable file → Normal file
0
src/decoder.sv
Executable file → Normal file
0
src/decoder.sv
Executable file → Normal file
0
src/ff1.sv
Executable file → Normal file
0
src/ff1.sv
Executable file → Normal file
122
src/frontend.sv
Executable file → Normal file
122
src/frontend.sv
Executable file → Normal file
|
@ -88,6 +88,9 @@ module frontend #(
|
|||
logic icache_valid_d, icache_valid_q;
|
||||
logic set_pc_d, set_pc_q;
|
||||
|
||||
logic icache_speculative_d, icache_speculative_q;
|
||||
logic [63:0] icache_vaddr_d, icache_vaddr_q;
|
||||
|
||||
// BHT, BTB and RAS prediction
|
||||
bht_prediction_t bht_prediction;
|
||||
btb_prediction_t btb_prediction;
|
||||
|
@ -109,13 +112,12 @@ module frontend #(
|
|||
logic [63:0] rvi_imm;
|
||||
|
||||
fetch_entry_t fetch_queue[$];
|
||||
logic [63:0] fetch_vaddrs[$]; // save the fetch addresses
|
||||
|
||||
// virtual address of current fetch
|
||||
logic [63:0] fetch_vaddr;
|
||||
logic [63:0] bp_vaddr;
|
||||
logic bp_valid; // we have a valid branch-prediction
|
||||
|
||||
logic fetch_is_speculative; // is it a speculative fetch or a fetch which need to do for sure
|
||||
fetch_entry_t fe;
|
||||
|
||||
logic [63:0] vpc_i;
|
||||
|
@ -148,8 +150,8 @@ module frontend #(
|
|||
if_ready = icache_ready;
|
||||
icache_req = 1'b1;
|
||||
|
||||
bp_vaddr = '0;
|
||||
bp_valid = 1'b0;
|
||||
bp_vaddr = '0; // predicted address
|
||||
bp_valid = 1'b0; // prediction is valid
|
||||
|
||||
// is it a return and the RAS contains a valid prediction? **speculative**
|
||||
if (rvi_return && ras_predict.valid) begin
|
||||
|
@ -191,11 +193,11 @@ module frontend #(
|
|||
|
||||
if (take_rvi_cf) begin
|
||||
bp_valid = 1'b1;
|
||||
bp_vaddr = npc_q + rvi_imm;
|
||||
bp_vaddr = icache_vaddr_q + rvi_imm;
|
||||
end
|
||||
|
||||
// icache response is valid -> so is our prediction
|
||||
if (~icache_valid_q)
|
||||
// icache response is valid -> so is our prediction, also check that this was no mandatory fetch
|
||||
if (~icache_valid_q || ~icache_speculative_q)
|
||||
bp_valid = 1'b0;
|
||||
end
|
||||
|
||||
|
@ -206,7 +208,11 @@ module frontend #(
|
|||
// we mis-predicted so kill the icache request and the fetch queue
|
||||
if (is_mispredict || flush_i) begin
|
||||
icache_kill_req = 1'b1;
|
||||
fetch_vaddrs = {};
|
||||
end
|
||||
|
||||
// if we have a valid branch-prediction we need to kill the current cache request
|
||||
if (bp_valid) begin
|
||||
icache_kill_req = 1'b1;
|
||||
end
|
||||
|
||||
// also kill the fetch FIFO if we are flushing
|
||||
|
@ -214,25 +220,30 @@ module frontend #(
|
|||
fetch_queue = {};
|
||||
|
||||
// assemble fetch entry
|
||||
fe.address = fetch_vaddrs.pop_front();
|
||||
fe.address = icache_vaddr_q;
|
||||
fe.instruction = icache_data_q;
|
||||
fe.branch_predict.valid = bp_valid;
|
||||
fe.branch_predict.predict_address = bp_vaddr;
|
||||
fe.branch_predict.predict_taken = bp_valid;
|
||||
fe.branch_predict.is_lower_16 = 1'b0;
|
||||
fe.branch_predict.cf_type = (rvi_jalr) ? BTB : BHT;
|
||||
|
||||
// save the fetch address
|
||||
if (icache_ready && icache_req)
|
||||
fetch_vaddrs.push_back(fetch_vaddr);
|
||||
|
||||
if (fetch_ack_i)
|
||||
fetch_queue.pop_front();
|
||||
fe.ex = '0; // ToDo
|
||||
|
||||
fetch_entry_o = fetch_queue[0];
|
||||
fetch_entry_valid_o = (fetch_queue.size() != 0);
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
|
||||
if (fetch_ack_i) begin
|
||||
fetch_queue.pop_front();
|
||||
$display("acknowledged instr\n");
|
||||
end
|
||||
|
||||
if (icache_valid_q) begin
|
||||
fetch_queue.push_back(fe);
|
||||
$display("Add new instruction %h", fe.address);
|
||||
end
|
||||
end
|
||||
// --------------------
|
||||
// Update Predictions
|
||||
// --------------------
|
||||
|
@ -264,37 +275,39 @@ module frontend #(
|
|||
always_comb begin : npc_select
|
||||
automatic logic [63:0] fetch_address;
|
||||
|
||||
fetch_is_speculative = 1'b0;
|
||||
|
||||
fetch_address = npc_q;
|
||||
set_pc_d = set_pc_q;
|
||||
// keep stable by default
|
||||
npc_d = fetch_address;
|
||||
// -------------------------------
|
||||
// 0. Default assignment
|
||||
// -------------------------------
|
||||
if (if_ready && fetch_enable_i)
|
||||
npc_d = {fetch_address[63:2], 2'b0} + 64'h4;
|
||||
|
||||
npc_d = npc_q;
|
||||
// -------------------------------
|
||||
// 1. Branch Prediction
|
||||
// -------------------------------
|
||||
if (if_ready && bp_vaddr)
|
||||
|
||||
if (if_ready && bp_valid) begin
|
||||
fetch_is_speculative = 1'b1;
|
||||
fetch_address = bp_vaddr;
|
||||
end
|
||||
// -------------------------------
|
||||
// 0. Default assignment
|
||||
// -------------------------------
|
||||
if (if_ready && fetch_enable_i) begin
|
||||
npc_d = {fetch_address[63:2], 2'b0} + 64'h4;
|
||||
fetch_is_speculative = 1'b1;
|
||||
end
|
||||
// -------------------------------
|
||||
// 3. Return from environment call
|
||||
// -------------------------------
|
||||
if (eret_i) begin
|
||||
npc_d = epc_i;
|
||||
npc_d = epc_i;
|
||||
end
|
||||
|
||||
|
||||
// -------------------------------
|
||||
// 4. Exception/Interrupt
|
||||
// -------------------------------
|
||||
if (ex_valid_i) begin
|
||||
npc_d = trap_vector_base_i;
|
||||
set_pc_d = 1'b1;
|
||||
npc_d = trap_vector_base_i;
|
||||
set_pc_d = 1'b1;
|
||||
end
|
||||
|
||||
// -----------------------------------------------
|
||||
// 5. Pipeline Flush because of CSR side effects
|
||||
// -----------------------------------------------
|
||||
|
@ -321,15 +334,19 @@ module frontend #(
|
|||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
npc_q <= boot_addr_i;
|
||||
icache_data_q <= '0;
|
||||
icache_valid_q <= 1'b0;
|
||||
set_pc_q <= 1'b0;
|
||||
npc_q <= boot_addr_i;
|
||||
icache_data_q <= '0;
|
||||
icache_valid_q <= 1'b0;
|
||||
set_pc_q <= 1'b0;
|
||||
icache_speculative_q <= 1'b0;
|
||||
icache_vaddr_q <= 'b0;
|
||||
end else begin
|
||||
npc_q <= npc_d;
|
||||
icache_data_q <= icache_data_q;
|
||||
icache_valid_q <= icache_valid_d;
|
||||
set_pc_q <= set_pc_d;
|
||||
npc_q <= npc_d;
|
||||
icache_data_q <= icache_data_d;
|
||||
icache_valid_q <= icache_valid_d;
|
||||
icache_speculative_q <= icache_speculative_d;
|
||||
icache_vaddr_q <= icache_vaddr_d;
|
||||
set_pc_q <= set_pc_d;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -366,18 +383,21 @@ module frontend #(
|
|||
icache #(
|
||||
.SET_ASSOCIATIVITY ( 4 )
|
||||
) i_icache (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( 1'b0 ),
|
||||
.index_i ( fetch_vaddr[11:0] ),
|
||||
.tag_i ( npc_q[55:12] ),
|
||||
.data_o ( icache_data_d ),
|
||||
.req_i ( icache_req ),
|
||||
.kill_req_i ( icache_kill_req ),
|
||||
.ready_o ( icache_ready ),
|
||||
.valid_o ( icache_valid_d ),
|
||||
.axi ( axi ),
|
||||
.miss_o ( l1_icache_miss_o )
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( 1'b0 ),
|
||||
.vaddr_i ( fetch_vaddr ),
|
||||
.is_speculative_i ( fetch_is_speculative ),
|
||||
.tag_i ( npc_q[55:12] ),
|
||||
.data_o ( icache_data_d ),
|
||||
.req_i ( icache_req ),
|
||||
.kill_req_i ( icache_kill_req ),
|
||||
.ready_o ( icache_ready ),
|
||||
.valid_o ( icache_valid_d ),
|
||||
.is_speculative_o ( icache_speculative_d ),
|
||||
.vaddr_o ( icache_vaddr_d ),
|
||||
.axi ( axi ),
|
||||
.miss_o ( l1_icache_miss_o )
|
||||
);
|
||||
|
||||
instr_scan i_instr_scan (
|
||||
|
|
54
src/icache.sv
Executable file → Normal file
54
src/icache.sv
Executable file → Normal file
|
@ -22,15 +22,18 @@ module icache #(
|
|||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic flush_i, // flush the icache, flush and kill have to be asserted together
|
||||
input logic req_i, // we request a new word
|
||||
input logic kill_req_i, // kill the current request
|
||||
output logic ready_o, // icache is ready
|
||||
input logic [INDEX_WIDTH-1:0] index_i, // 1st cycle: 12 bit index
|
||||
input logic [TAG_WIDTH-1:0] tag_i, // 2nd cycle: physical tag
|
||||
output logic [FETCH_WIDTH-1:0] data_o, // 2+ cycle out: tag
|
||||
output logic valid_o, // signals a valid read
|
||||
output logic miss_o, // we missed on the cache
|
||||
input logic flush_i, // flush the icache, flush and kill have to be asserted together
|
||||
input logic req_i, // we request a new word
|
||||
input logic is_speculative_i, // is this request speculative or not
|
||||
input logic kill_req_i, // kill the current request
|
||||
output logic ready_o, // icache is ready
|
||||
input logic [63:0] vaddr_i, // 1st cycle: 12 bit index is taken for lookup
|
||||
input logic [TAG_WIDTH-1:0] tag_i, // 2nd cycle: physical tag
|
||||
output logic [FETCH_WIDTH-1:0] data_o, // 2+ cycle out: tag
|
||||
output logic is_speculative_o, // the fetch was speculative
|
||||
output logic [63:0] vaddr_o, // virtual address out
|
||||
output logic valid_o, // signals a valid read
|
||||
output logic miss_o, // we missed on the cache
|
||||
AXI_BUS.Master axi
|
||||
);
|
||||
|
||||
|
@ -42,7 +45,8 @@ module icache #(
|
|||
REDO_REQ, WAIT_TAG_SAVED, REFILL
|
||||
} state_d, state_q;
|
||||
logic [$clog2(ICACHE_NUM_WORD)-1:0] cnt_d, cnt_q;
|
||||
logic [INDEX_WIDTH-1:0] index_d, index_q;
|
||||
logic [63:0] vaddr_d, vaddr_q;
|
||||
logic spec_d, spec_q; // request is speculative
|
||||
logic [TAG_WIDTH-1:0] tag_d, tag_q;
|
||||
logic [SET_ASSOCIATIVITY-1:0] evict_way_d, evict_way_q;
|
||||
logic flushing_d, flushing_q;
|
||||
|
@ -119,7 +123,7 @@ module icache #(
|
|||
// ------------------
|
||||
// Way Select
|
||||
// ------------------
|
||||
assign idx = index_q[BYTE_OFFSET-1:2];
|
||||
assign idx = vaddr_q[BYTE_OFFSET-1:2];
|
||||
// cacheline selected by hit
|
||||
logic [CACHE_LINE_WIDTH/FETCH_WIDTH-1:0][FETCH_WIDTH-1:0] selected_cl;
|
||||
logic [CACHE_LINE_WIDTH-1:0] selected_cl_flat;
|
||||
|
@ -184,13 +188,17 @@ module icache #(
|
|||
// default assignments
|
||||
state_d = state_q;
|
||||
cnt_d = cnt_q;
|
||||
index_d = index_q;
|
||||
vaddr_d = vaddr_q;
|
||||
spec_d = spec_q;
|
||||
tag_d = tag_q;
|
||||
evict_way_d = evict_way_q;
|
||||
flushing_d = flushing_q;
|
||||
|
||||
is_speculative_o = spec_q;
|
||||
vaddr_o = vaddr_q;
|
||||
|
||||
req = '0;
|
||||
addr = index_i[INDEX_WIDTH-1:BYTE_OFFSET];
|
||||
addr = vaddr_i[INDEX_WIDTH-1:BYTE_OFFSET];
|
||||
we = 1'b0;
|
||||
data_wdata = '0;
|
||||
tag_wdata = '0;
|
||||
|
@ -212,7 +220,8 @@ module icache #(
|
|||
// request the content of all arrays
|
||||
req = '1;
|
||||
// save the index
|
||||
index_d = index_i;
|
||||
vaddr_d = vaddr_i;
|
||||
spec_d = is_speculative_i;
|
||||
state_d = TAG_CMP;
|
||||
end
|
||||
|
||||
|
@ -232,7 +241,8 @@ module icache #(
|
|||
// request the content of all arrays
|
||||
req = '1;
|
||||
// save the index and stay in compare mode
|
||||
index_d = index_i;
|
||||
vaddr_d = vaddr_i;
|
||||
spec_d = is_speculative_i;
|
||||
// no new request -> go back to idle
|
||||
end else begin
|
||||
state_d = IDLE;
|
||||
|
@ -256,7 +266,7 @@ module icache #(
|
|||
// ~> request a cache-line refill
|
||||
REFILL: begin
|
||||
axi.ar_valid = 1'b1;
|
||||
axi.ar_addr[INDEX_WIDTH+TAG_WIDTH-1:0] = {tag_q, index_q};
|
||||
axi.ar_addr[INDEX_WIDTH+TAG_WIDTH-1:0] = {tag_q, vaddr_q[INDEX_WIDTH-1:0]};
|
||||
|
||||
if (kill_req_i)
|
||||
state_d = WAIT_KILLED_REFILL;
|
||||
|
@ -270,7 +280,7 @@ module icache #(
|
|||
|
||||
state_d = REDO_REQ;
|
||||
req = evict_way_q;
|
||||
addr = index_q[INDEX_WIDTH-1:BYTE_OFFSET];
|
||||
addr = vaddr_q[INDEX_WIDTH-1:BYTE_OFFSET];
|
||||
|
||||
if (axi.r_valid) begin
|
||||
we = 1'b1;
|
||||
|
@ -289,7 +299,7 @@ module icache #(
|
|||
// ~> redo the request,
|
||||
REDO_REQ: begin
|
||||
req = '1;
|
||||
addr = index_q[INDEX_WIDTH-1:BYTE_OFFSET];
|
||||
addr = vaddr_q[INDEX_WIDTH-1:BYTE_OFFSET];
|
||||
tag = tag_q;
|
||||
state_d = WAIT_TAG_SAVED;
|
||||
end
|
||||
|
@ -326,7 +336,7 @@ module icache #(
|
|||
default : state_d = IDLE;
|
||||
endcase
|
||||
|
||||
if (kill_req_i && !(state_q inside {REFILL, WAIT_AXI_R_RESP, WAIT_KILLED_REFILL, WAIT_KILLED_AXI_R_RESP})) begin
|
||||
if (kill_req_i && !(state_q inside {REFILL, WAIT_AXI_R_RESP, WAIT_KILLED_REFILL, WAIT_KILLED_AXI_R_RESP}) && !ready_o) begin
|
||||
state_d = IDLE;
|
||||
end
|
||||
|
||||
|
@ -359,17 +369,19 @@ module icache #(
|
|||
if (~rst_ni) begin
|
||||
state_q <= FLUSH;
|
||||
cnt_q <= '0;
|
||||
index_q <= '0;
|
||||
vaddr_q <= '0;
|
||||
tag_q <= '0;
|
||||
evict_way_q <= '0;
|
||||
flushing_q <= 1'b0;
|
||||
spec_q <= 1'b0;
|
||||
end else begin
|
||||
state_q <= state_d;
|
||||
cnt_q <= cnt_d;
|
||||
index_q <= index_d;
|
||||
vaddr_q <= vaddr_d;
|
||||
tag_q <= tag_d;
|
||||
evict_way_q <= evict_way_d;
|
||||
flushing_q <= flushing_d;
|
||||
spec_q <= spec_d;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
0
src/lfsr.sv
Executable file → Normal file
0
src/lfsr.sv
Executable file → Normal file
0
src/mmu.sv
Executable file → Normal file
0
src/mmu.sv
Executable file → Normal file
0
src/mult.sv
Executable file → Normal file
0
src/mult.sv
Executable file → Normal file
0
src/nbdcache.sv
Executable file → Normal file
0
src/nbdcache.sv
Executable file → Normal file
0
src/pcgen_stage.sv
Executable file → Normal file
0
src/pcgen_stage.sv
Executable file → Normal file
0
src/ptw.sv
Executable file → Normal file
0
src/ptw.sv
Executable file → Normal file
0
src/tlb.sv
Executable file → Normal file
0
src/tlb.sv
Executable file → Normal file
Loading…
Add table
Add a link
Reference in a new issue