VM based RISC-V tests are passing

This commit is contained in:
Florian Zaruba 2018-02-16 12:39:44 +01:00
parent f2d45c007b
commit 6c66ea19ae
5 changed files with 102 additions and 83 deletions

View file

@ -54,18 +54,18 @@ riscv-tests := rv64ui-p-add rv64ui-p-addi rv64ui-p-slli rv64ui-p-addiw rv64ui-p-
rv64ui-p-lb rv64ui-p-lbu rv64ui-p-ld rv64ui-p-lh rv64ui-p-lhu rv64ui-p-lui rv64ui-p-lw rv64ui-p-lwu \
rv64mi-p-csr rv64mi-p-mcsr rv64mi-p-illegal rv64mi-p-ma_addr rv64mi-p-ma_fetch rv64mi-p-sbreak rv64mi-p-scall \
rv64si-p-csr rv64si-p-ma_fetch rv64si-p-scall rv64si-p-wfi rv64si-p-sbreak rv64si-p-dirty \
rv64uc-p-rvc
# rv64ui-v-add rv64ui-v-addi rv64ui-p-slli rv64ui-v-addiw rv64ui-v-addw rv64ui-v-and rv64ui-v-auipc \
# rv64ui-v-beq rv64ui-v-bge rv64ui-v-bgeu rv64ui-v-andi rv64ui-v-blt rv64ui-v-bltu rv64ui-v-bne \
# rv64ui-v-simple rv64ui-v-jal rv64ui-v-jalr rv64ui-v-or rv64ui-v-ori rv64ui-v-sub rv64ui-v-subw \
# rv64ui-v-xor rv64ui-v-xori rv64ui-v-slliw rv64ui-v-sll rv64ui-v-slli rv64ui-v-slliw \
# rv64ui-v-slt rv64ui-v-slti rv64ui-v-sltiu rv64ui-v-sltu rv64ui-v-sra rv64ui-v-srai \
# rv64ui-v-sraiw rv64ui-v-sraw rv64ui-v-srl rv64ui-v-srli rv64ui-v-srliw rv64ui-v-srlw \
# rv64ui-v-lb rv64ui-v-lbu rv64ui-v-ld rv64ui-v-lh rv64ui-v-lhu rv64ui-v-lui \
# rv64um-p-mul rv64um-p-mulh rv64um-p-mulhsu rv64um-p-mulhu rv64um-p-div rv64um-p-divu rv64um-p-rem \
# rv64um-p-remu rv64um-p-mulw rv64um-p-divw rv64um-p-divuw rv64um-p-remw rv64um-p-remuw \
# rv64um-v-mul rv64um-v-mulh rv64um-v-mulhsu rv64um-v-mulhu rv64um-v-div rv64um-v-divu rv64um-v-rem \
# rv64um-v-remu rv64um-v-mulw rv64um-v-divw rv64um-v-divuw rv64um-v-remw rv64um-v-remuw
rv64uc-p-rvc \
rv64ui-v-add rv64ui-v-addi rv64ui-p-slli rv64ui-v-addiw rv64ui-v-addw rv64ui-v-and rv64ui-v-auipc \
rv64ui-v-beq rv64ui-v-bge rv64ui-v-bgeu rv64ui-v-andi rv64ui-v-blt rv64ui-v-bltu rv64ui-v-bne \
rv64ui-v-simple rv64ui-v-jal rv64ui-v-jalr rv64ui-v-or rv64ui-v-ori rv64ui-v-sub rv64ui-v-subw \
rv64ui-v-xor rv64ui-v-xori rv64ui-v-slliw rv64ui-v-sll rv64ui-v-slli rv64ui-v-slliw \
rv64ui-v-slt rv64ui-v-slti rv64ui-v-sltiu rv64ui-v-sltu rv64ui-v-sra rv64ui-v-srai \
rv64ui-v-sraiw rv64ui-v-sraw rv64ui-v-srl rv64ui-v-srli rv64ui-v-srliw rv64ui-v-srlw \
rv64ui-v-lb rv64ui-v-lbu rv64ui-v-ld rv64ui-v-lh rv64ui-v-lhu rv64ui-v-lui \
rv64um-p-mul rv64um-p-mulh rv64um-p-mulhsu rv64um-p-mulhu rv64um-p-div rv64um-p-divu rv64um-p-rem \
rv64um-p-remu rv64um-p-mulw rv64um-p-divw rv64um-p-divuw rv64um-p-remw rv64um-p-remuw \
rv64um-v-mul rv64um-v-mulh rv64um-v-mulhsu rv64um-v-mulhu rv64um-v-div rv64um-v-divu rv64um-v-rem \
rv64um-v-remu rv64um-v-mulw rv64um-v-divw rv64um-v-divuw rv64um-v-remw rv64um-v-remuw
# failed test directory
failed-tests := $(wildcard failedtests/*.S)

View file

@ -286,8 +286,6 @@ module ariane #(
.*
);
assign fetch_req_if_ex = 1'b0;
// ---------
// ID
// ---------

View file

@ -65,6 +65,8 @@ module frontend #(
// Registers
logic [31:0] icache_data_d, icache_data_q;
logic icache_valid_d, icache_valid_q;
exception_t icache_ex_d, icache_ex_q;
logic instruction_valid;
logic icache_speculative_d, icache_speculative_q;
@ -384,6 +386,7 @@ module frontend #(
icache_valid_q <= 1'b0;
icache_speculative_q <= 1'b0;
icache_vaddr_q <= 'b0;
icache_ex_q <= '0;
unaligned_q <= 1'b0;
unaligned_address_q <= '0;
unaligned_instr_q <= '0;
@ -393,6 +396,7 @@ module frontend #(
icache_valid_q <= icache_valid_d;
icache_speculative_q <= icache_speculative_d;
icache_vaddr_q <= icache_vaddr_d;
icache_ex_q <= icache_ex_d;
unaligned_q <= unaligned_d;
unaligned_address_q <= unaligned_address_d;
unaligned_instr_q <= unaligned_instr_d;
@ -434,21 +438,21 @@ module frontend #(
.CACHE_LINE_WIDTH ( 128 ),
.FETCH_WIDTH ( FETCH_WIDTH )
) i_icache (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_icache_i ),
.vaddr_i ( fetch_vaddr ), // 1st cycle
.is_speculative_i ( fetch_is_speculative ), // 1st cycle
.data_o ( icache_data_d ),
.req_i ( icache_req ),
.kill_s1_i ( kill_s1 ),
.kill_s2_i ( kill_s2 ),
.kill_s1_i ( kill_s1 ),
.kill_s2_i ( kill_s2 ),
.ready_o ( icache_ready ),
.valid_o ( icache_valid_d ),
.ex_o ( icache_ex_d ),
.is_speculative_o ( icache_speculative_d ),
.vaddr_o ( icache_vaddr_d ),
.axi ( axi ),
.miss_o ( l1_icache_miss_o )
.miss_o ( l1_icache_miss_o ),
.*
);
for (genvar i = 0; i < INSTR_PER_FETCH; i++) begin
@ -471,13 +475,10 @@ module frontend #(
);
end
exception_t ex;
assign ex = '0;
fetch_fifo i_fetch_fifo (
.flush_i ( flush_i ),
.branch_predict_i ( bp_sbe ),
.ex_i ( ex ),
.ex_i ( icache_ex_q ),
.addr_i ( icache_vaddr_q ),
.rdata_i ( icache_data_q ),
.valid_i ( fifo_valid ),
@ -670,8 +671,8 @@ module bht #(
logic [1:0] saturation_counter;
} bht_d[NR_ENTRIES-1:0], bht_q[NR_ENTRIES-1:0];
logic [$clog2(NR_ENTRIES)-1:0] index, update_pc;
logic [1:0] saturation_counter;
logic [$clog2(NR_ENTRIES)-1:0] index, update_pc;
logic [1:0] saturation_counter;
assign index = vpc_i[PREDICTION_BITS - 1:OFFSET];
assign update_pc = bht_update_i.pc[PREDICTION_BITS - 1:OFFSET];

View file

@ -13,36 +13,46 @@
// ------------------------------
// Instruction Cache
// ------------------------------
import ariane_pkg::*;
module icache #(
parameter int unsigned SET_ASSOCIATIVITY = 4,
parameter int unsigned INDEX_WIDTH = 12, // in bit
parameter int unsigned TAG_WIDTH = 44, // in bit
parameter int unsigned CACHE_LINE_WIDTH = 64, // in bit
parameter int unsigned FETCH_WIDTH = 32 // in bit
)(
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 is_speculative_i, // is this request speculative or not
input logic kill_s1_i, // kill the current request
input logic kill_s2_i, // kill the last request
output logic ready_o, // icache is ready
input logic [63:0] vaddr_i, // 1st cycle: 12 bit index is taken for lookup
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
);
parameter int unsigned SET_ASSOCIATIVITY = 4,
parameter int unsigned INDEX_WIDTH = 12, // in bit
parameter int unsigned TAG_WIDTH = 44, // in bit
parameter int unsigned CACHE_LINE_WIDTH = 64, // in bit
parameter int unsigned FETCH_WIDTH = 32 // in bit
)(
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 is_speculative_i, // is this request speculative or not
input logic kill_s1_i, // kill the current request
input logic kill_s2_i, // kill the last request
output logic ready_o, // icache is ready
input logic [63:0] vaddr_i, // 1st cycle: 12 bit index is taken for lookup
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 exception_t ex_o, // we've encountered an exception
output logic miss_o, // we missed on the cache
AXI_BUS.Master axi,
// Address translation
output logic fetch_req_o,
output logic [63:0] fetch_vaddr_o,
input logic fetch_valid_i,
input logic [63:0] fetch_paddr_i,
input exception_t fetch_exception_i
);
localparam int unsigned BYTE_OFFSET = $clog2(CACHE_LINE_WIDTH/8); // 3
localparam int unsigned ICACHE_NUM_WORD = 2**(INDEX_WIDTH - BYTE_OFFSET);
localparam int unsigned NR_AXI_REFILLS = ($clog2(CACHE_LINE_WIDTH/64) == 0) ? 1 : $clog2(CACHE_LINE_WIDTH/64);
// registers
enum logic [3:0] { FLUSH, IDLE, TAG_CMP, WAIT_AXI_R_RESP, WAIT_KILLED_REFILL, WAIT_KILLED_AXI_R_RESP,
REDO_REQ, WAIT_TAG_SAVED, REFILL
REDO_REQ, TAG_CMP_SAVED, REFILL,
WAIT_ADDRESS_TRANSLATION, WAIT_ADDRESS_TRANSLATION_KILLED
} state_d, state_q;
logic [$clog2(ICACHE_NUM_WORD)-1:0] cnt_d, cnt_q;
logic [NR_AXI_REFILLS-1:0] burst_cnt_d, burst_cnt_q; // counter for AXI transfers
@ -187,6 +197,8 @@ module icache #(
assign data_be = be;
assign data_wdata = wdata;
assign ex_o = fetch_exception_i;
// ------------------
// Cache Ctrl
// ------------------
@ -211,13 +223,16 @@ module icache #(
wdata = '0;
tag_wdata = '0;
ready_o = 1'b0;
tag = vaddr_q[TAG_WIDTH+INDEX_WIDTH-1:INDEX_WIDTH];
tag = fetch_paddr_i[TAG_WIDTH+INDEX_WIDTH-1:INDEX_WIDTH];
valid_o = 1'b0;
update_lfsr = 1'b0;
miss_o = 1'b0;
axi.ar_valid = 1'b0;
axi.ar_addr = '0;
axi.ar_valid = 1'b0;
axi.ar_addr = '0;
fetch_req_o = 1'b0;
fetch_vaddr_o = vaddr_q;
case (state_q)
// ~> we are ready to receive a new request
@ -227,7 +242,7 @@ module icache #(
if (req_i) begin
// request the content of all arrays
req = '1;
// save the index
// save the virtual address
vaddr_d = vaddr_i;
spec_d = is_speculative_i;
state_d = TAG_CMP;
@ -241,11 +256,15 @@ module icache #(
state_d = IDLE;
end
// ~> compare the tag
TAG_CMP: begin
TAG_CMP, TAG_CMP_SAVED: begin
fetch_req_o = 1'b1; // request address translation
// use the saved tag
if (state_q == TAG_CMP_SAVED)
tag = tag_q;
// -------
// Hit
// -------
if (|hit) begin
if (|hit && fetch_valid_i) begin
ready_o = 1'b1;
valid_o = 1'b1;
// we've got another request
@ -255,6 +274,7 @@ module icache #(
// save the index and stay in compare mode
vaddr_d = vaddr_i;
spec_d = is_speculative_i;
state_d = TAG_CMP;
// no new request -> go back to idle
end else begin
state_d = IDLE;
@ -269,7 +289,7 @@ module icache #(
state_d = REFILL;
evict_way_d = '0;
// save tag
tag_d = vaddr_q[TAG_WIDTH+INDEX_WIDTH-1:INDEX_WIDTH];
tag_d = fetch_paddr_i[TAG_WIDTH+INDEX_WIDTH-1:INDEX_WIDTH];
miss_o = 1'b1;
// get way which to replace
if (repl_w_random) begin
@ -280,6 +300,28 @@ module icache #(
evict_way_d[repl_invalid] = 1'b1;
end
end
// if we didn't hit on the TLB we need to wait until the request has been completed
if (!fetch_valid_i) begin
state_d = WAIT_ADDRESS_TRANSLATION;
end
end
// ~> wait here for a valid address translation, or on a translation even if the request has been killed
WAIT_ADDRESS_TRANSLATION, WAIT_ADDRESS_TRANSLATION_KILLED: begin
fetch_req_o = 1'b1;
// retry the request if no exception occurred
if (fetch_valid_i && (state_q == WAIT_ADDRESS_TRANSLATION)) begin
if (fetch_exception_i.valid)
valid_o = 1'b1;
else begin
state_d = REDO_REQ;
tag_d = fetch_paddr_i[TAG_WIDTH+INDEX_WIDTH-1:INDEX_WIDTH];
end
end else if (fetch_valid_i) begin
state_d = IDLE;
end
if (kill_s2_i)
state_d = WAIT_ADDRESS_TRANSLATION_KILLED;
end
// ~> request a cache-line refill
REFILL, WAIT_KILLED_REFILL: begin
@ -326,33 +368,7 @@ module icache #(
req = '1;
addr = vaddr_q[INDEX_WIDTH-1:BYTE_OFFSET];
tag = tag_q;
state_d = WAIT_TAG_SAVED;
end
// we already saved the tag -> apply it
WAIT_TAG_SAVED: begin
tag = tag_q;
state_d = IDLE;
valid_o = 1'b1;
// TODO: Check if this is necessary in a real payload environment
// we can handle a new request here
ready_o = 1'b1;
// we are getting a new request
if (req_i) begin
// request the content of all arrays
req = '1;
// save the index
vaddr_d = vaddr_i;
spec_d = is_speculative_i;
state_d = TAG_CMP;
end
if (kill_s1_i)
state_d = IDLE;
// go to flushing state
if (flush_i || flushing_q)
state_d = FLUSH;
state_d = TAG_CMP_SAVED; // do tag comparison on the saved tag
end
// we need to wait for some AXI responses to come back
// here for the AW valid
@ -387,7 +403,11 @@ module icache #(
if (flush_i) begin
flushing_d = 1'b1;
ready_o = 1'b0; // we are not ready to accept a further request here
end
// if we are going to flush -> do not accept any new requests
if (flushing_q)
ready_o = 1'b0;
end
ff1 #(

View file

@ -224,7 +224,7 @@ module mmu #(
// ---------
// watch out for exceptions happening during walking the page table
if (ptw_active && walking_instr) begin
fetch_valid_o = 1'b1;
fetch_valid_o = ptw_error;
fetch_exception_o = {INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1};
end
end