From 6c66ea19ae56cf997f6f2447e300a1b9469e1d4b Mon Sep 17 00:00:00 2001 From: Florian Zaruba Date: Fri, 16 Feb 2018 12:39:44 +0100 Subject: [PATCH] VM based RISC-V tests are passing --- Makefile | 24 ++++----- src/ariane.sv | 2 - src/frontend.sv | 23 +++++---- src/icache.sv | 134 ++++++++++++++++++++++++++++-------------------- src/mmu.sv | 2 +- 5 files changed, 102 insertions(+), 83 deletions(-) diff --git a/Makefile b/Makefile index 262d1c6b3..50f4918eb 100755 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/src/ariane.sv b/src/ariane.sv index 005f854af..a9291cc99 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -286,8 +286,6 @@ module ariane #( .* ); - assign fetch_req_if_ex = 1'b0; - // --------- // ID // --------- diff --git a/src/frontend.sv b/src/frontend.sv index 2bca94c30..a6c054074 100644 --- a/src/frontend.sv +++ b/src/frontend.sv @@ -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]; diff --git a/src/icache.sv b/src/icache.sv index c66c1dba0..e1087510f 100644 --- a/src/icache.sv +++ b/src/icache.sv @@ -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 #( diff --git a/src/mmu.sv b/src/mmu.sv index 7b5f5a04a..05e37d626 100644 --- a/src/mmu.sv +++ b/src/mmu.sv @@ -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