Fix issue with next PC calculation

This commit is contained in:
Florian Zaruba 2018-02-12 17:39:11 +01:00
parent 45de87b551
commit 4f73473b1b
16 changed files with 109 additions and 77 deletions

View file

@ -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
View 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
View file

0
src/decoder.sv Executable file → Normal file
View file

0
src/ff1.sv Executable file → Normal file
View file

122
src/frontend.sv Executable file → Normal file
View 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
View 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
View file

0
src/mmu.sv Executable file → Normal file
View file

0
src/mult.sv Executable file → Normal file
View file

0
src/nbdcache.sv Executable file → Normal file
View file

0
src/pcgen_stage.sv Executable file → Normal file
View file

0
src/ptw.sv Executable file → Normal file
View file

0
src/tlb.sv Executable file → Normal file
View file