diff --git a/Makefile b/Makefile index 919aa64a1..df3a0eccc 100644 --- a/Makefile +++ b/Makefile @@ -43,14 +43,14 @@ riscv-tests = rv64ui-p-add rv64ui-p-addi rv64ui-p-slli rv64ui-p-addiw rv64ui-p- 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-sllw \ - # 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 + 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-sllw \ + 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 riscv-test = rv64ui-p-add diff --git a/src/ariane.sv b/src/ariane.sv index b0bdf404a..8beda455a 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -273,9 +273,10 @@ module ariane .fetch_entry_valid_0_o ( fetch_valid_if_id ), .fetch_ack_0_i ( decode_ack_id_if ), - .fetch_entry_1_o (), - .fetch_entry_valid_1_o (), - .fetch_ack_1_i (), + // Reserved for future use + .fetch_entry_1_o ( ), + .fetch_entry_valid_1_o ( ), + .fetch_ack_1_i ( ), .* ); @@ -524,9 +525,9 @@ module ariane assign tracer_if.flush_unissued = flush_unissued_instr_ctrl_id; assign tracer_if.flush = flush_ctrl_ex; // fetch - assign tracer_if.fetch = fetch_entry_if_id; - assign tracer_if.fetch_valid = fetch_valid_if_id; - assign tracer_if.fetch_ack = decode_ack_id_if; + assign tracer_if.instruction = id_stage_i.compressed_decoder_i.instr_o; + assign tracer_if.fetch_valid = id_stage_i.instr_realigner_i.fetch_entry_valid_o; + assign tracer_if.fetch_ack = id_stage_i.instr_realigner_i.fetch_ack_i; // Issue assign tracer_if.issue_ack = issue_stage_i.scoreboard_i.issue_ack_i; assign tracer_if.issue_sbe = issue_stage_i.scoreboard_i.issue_instr_o; diff --git a/src/dcache_arbiter.sv b/src/dcache_arbiter.sv index 7cf80b01b..5526b8fb6 100644 --- a/src/dcache_arbiter.sv +++ b/src/dcache_arbiter.sv @@ -177,7 +177,7 @@ module dcache_arbiter #( else begin $error("There was a grant without a request."); $stop(); end // assert that the address does not contain X when request is sent assert property ( @(posedge clk_i) (data_req_o) |-> (!$isunknown(address_index_o)) ) - else begin $info("address contains X when request is set"); end + else begin $error("address contains X when request is set"); $stop(); end // there should be no rvalid when we are in IDLE // assert property ( diff --git a/src/id_stage.sv b/src/id_stage.sv index 2481ee9a4..f0cda51a3 100644 --- a/src/id_stage.sv +++ b/src/id_stage.sv @@ -51,12 +51,12 @@ module id_stage ( logic is_control_flow_instr; scoreboard_entry decoded_instruction; - fetch_entry fetch_entry; logic is_illegal; logic [31:0] instruction; logic is_compressed; logic fetch_ack_i; + logic fetch_entry_valid; instr_realigner instr_realigner_i ( .fetch_entry_0_i ( fetch_entry_i ), @@ -64,7 +64,7 @@ module id_stage ( .fetch_ack_0_o ( decoded_instr_ack_o ), .fetch_entry_o ( fetch_entry ), - .fetch_entry_valid_o ( fetch_entry_valid_o ), + .fetch_entry_valid_o ( fetch_entry_valid ), .fetch_ack_i ( fetch_ack_i ), .* ); @@ -106,7 +106,7 @@ module id_stage ( // if we have a space in the register and the fetch is valid, go get it // or the issue stage is currently acknowledging an instruction, which means that we will have space // for a new instruction - if ((!issue_q.valid || issue_instr_ack_i) && fetch_entry_valid_i) begin + if ((!issue_q.valid || issue_instr_ack_i) && fetch_entry_valid) begin fetch_ack_i = 1'b1; issue_n = { 1'b1, decoded_instruction, is_control_flow_instr}; end diff --git a/src/instr_realigner.sv b/src/instr_realigner.sv index e1ed74c52..417482f53 100755 --- a/src/instr_realigner.sv +++ b/src/instr_realigner.sv @@ -32,13 +32,19 @@ module instr_realigner ( output logic fetch_entry_valid_o, input logic fetch_ack_i ); - + // ---------- + // Registers + // ---------- // the last instruction was unaligned - logic unaligned_n, unaligned_q; + logic unaligned_n, unaligned_q; // save the unaligned part of the instruction to this ff - logic [15:0] unaligned_instr_n, unaligned_instr_q; + logic [15:0] unaligned_instr_n, unaligned_instr_q; // the previous instruction was compressed - logic compressed_n, compressed_q; + logic compressed_n, compressed_q; + // register to save the unaligned address + logic [63:0] unaligned_address_n, unaligned_address_q; + // get the next instruction, needed on a unaligned access + logic jump_unaligned_half_word; // check if the lower compressed instruction was no branch otherwise we will need to squash this instruction // but only if we predicted it to be taken, the predict was on the lower 16 bit compressed instruction @@ -46,17 +52,22 @@ module instr_realigner ( assign kill_upper_16_bit = fetch_entry_0_i.branch_predict.valid && fetch_entry_0_i.branch_predict.predict_taken && fetch_entry_0_i.branch_predict.is_lower_16; - + // ---------- + // Registers + // ---------- always_comb begin : realign_instr - unaligned_n = unaligned_q; - unaligned_instr_n = unaligned_instr_q; - compressed_n = compressed_q; + unaligned_n = unaligned_q; + unaligned_instr_n = unaligned_instr_q; + compressed_n = compressed_q; + unaligned_address_n = unaligned_address_q; // directly output this instruction. adoptions are made throughout the process - fetch_entry_o = fetch_entry_0_i; - fetch_entry_valid_o = fetch_entry_valid_0_i; - fetch_ack_0_o = fetch_ack_i; + fetch_entry_o = fetch_entry_0_i; + fetch_entry_valid_o = fetch_entry_valid_0_i; + fetch_ack_0_o = fetch_ack_i; + // we just jumped to a half word and encountered an unaligned 32-bit instruction + jump_unaligned_half_word = 1'b0; // --------------------------------- // Input port & Instruction Aligner // --------------------------------- @@ -95,6 +106,8 @@ module instr_realigner ( end else begin // save the lower 16 bit unaligned_instr_n = fetch_entry_0_i.instruction[31:16]; + // save the address + unaligned_address_n = {fetch_entry_0_i.address[63:2], 2'b10}; // and that it was unaligned unaligned_n = 1'b1; // this does not consume space in the FIFO @@ -110,9 +123,11 @@ module instr_realigner ( // we have an outstanding unaligned instruction else if (unaligned_q) begin - fetch_entry_o.address = {fetch_entry_0_i.address, 2'b10}; + + fetch_entry_o.address = unaligned_address_q; fetch_entry_o.instruction = {fetch_entry_0_i.instruction[15:0], unaligned_instr_q}; + // again should we look at the upper bits? if (!kill_upper_16_bit) begin // whats up with the other upper 16 bit of this instruction // is the second instruction also compressed, like: @@ -135,6 +150,8 @@ module instr_realigner ( end else if (!kill_upper_16_bit) begin // save the lower 16 bit unaligned_instr_n = fetch_entry_0_i.instruction[31:16]; + // save the address + unaligned_address_n = {fetch_entry_0_i.address[63:2], 2'b10}; // and that it was unaligned unaligned_n = 1'b1; end @@ -163,22 +180,40 @@ module instr_realigner ( unaligned_instr_n = fetch_entry_0_i.instruction[31:16]; // and that it was unaligned unaligned_n = 1'b1; + // save the address + unaligned_address_n = {fetch_entry_0_i.address[63:2], 2'b10}; + // we need to wait for the second instruction + fetch_entry_valid_o = 1'b0; + // so get it by acknowledging this instruction + fetch_ack_0_o = 1'b1; + // we got to an unaligned instruction -> get the next entry to full-fill the need + jump_unaligned_half_word = 1'b1; end // there can never be a whole 32 bit instruction on a half word access end - end else + end // ---------------------------- // Next compressed instruction // ---------------------------- // we are serving the second part of an instruction which was also compressed - if (fetch_entry_valid_0_i) begin - compressed_n = 1'b0; + if (compressed_q) begin + fetch_ack_0_o = fetch_ack_i; + compressed_n = 1'b0; fetch_entry_o.instruction = {16'b0, fetch_entry_0_i.instruction[31:16]}; - fetch_entry_o.address = {fetch_entry_0_i.address, 2'b10}; + fetch_entry_o.address = {fetch_entry_0_i.address[63:2], 2'b10}; + fetch_entry_valid_o = 1'b1; + end + + // if we didn't get an acknowledge keep the registers stable + if (!fetch_ack_i && !jump_unaligned_half_word) begin + unaligned_n = unaligned_q; + unaligned_instr_n = unaligned_instr_q; + compressed_n = compressed_q; + unaligned_address_n = unaligned_address_q; end if (flush_i) begin - // clear the unaligned instruction + // clear the unaligned and compressed instruction unaligned_n = 1'b0; compressed_n = 1'b0; end @@ -191,10 +226,12 @@ module instr_realigner ( if (~rst_ni) begin unaligned_q <= 1'b0; unaligned_instr_q <= 16'b0; + unaligned_address_q <= 64'b0; compressed_q <= 1'b0; end else begin unaligned_q <= unaligned_n; unaligned_instr_q <= unaligned_instr_n; + unaligned_address_q <= unaligned_address_n; compressed_q <= compressed_n; end end diff --git a/src/util/instruction_tracer.svh b/src/util/instruction_tracer.svh index 798665557..a42202cc8 100755 --- a/src/util/instruction_tracer.svh +++ b/src/util/instruction_tracer.svh @@ -22,9 +22,9 @@ class instruction_tracer; // interface to the core virtual instruction_tracer_if tracer_if; // keep the decoded instructions in a queue - fetch_entry decode_queue [$]; + logic [31:0] decode_queue [$]; // keep the issued instructions in a queue - fetch_entry issue_queue [$]; + logic [31:0] issue_queue [$]; // issue scoreboard entries scoreboard_entry issue_sbe_queue [$]; scoreboard_entry issue_sbe; @@ -52,7 +52,7 @@ class instruction_tracer; endfunction : create_file task trace(); - fetch_entry decode_instruction, issue_instruction, issue_commit_instruction; + logic [31:0] decode_instruction, issue_instruction, issue_commit_instruction; scoreboard_entry commit_instruction; // initialize register 0 @@ -69,7 +69,7 @@ class instruction_tracer; // ------------------- // we are decoding an instruction if (tracer_if.pck.fetch_valid && tracer_if.pck.fetch_ack) begin - decode_instruction = fetch_entry'(tracer_if.pck.fetch); + decode_instruction = tracer_if.pck.instruction; decode_queue.push_back(decode_instruction); end // ------------------- @@ -111,9 +111,9 @@ class instruction_tracer; // check if the write back is valid, if not we need to source the result from the register file // as the most recent version of this register will be there. if (tracer_if.pck.we) begin - printInstr(issue_sbe, issue_commit_instruction.instruction, tracer_if.pck.wdata, address_mapping); + printInstr(issue_sbe, issue_commit_instruction, tracer_if.pck.wdata, address_mapping); end else - printInstr(issue_sbe, issue_commit_instruction.instruction, reg_file[commit_instruction.rd], address_mapping); + printInstr(issue_sbe, issue_commit_instruction, reg_file[commit_instruction.rd], address_mapping); end // -------------- @@ -162,7 +162,7 @@ class instruction_tracer; load_mapping = {}; endfunction; - function void printInstr(scoreboard_entry sbe, logic [63:0] instr, logic [63:0] result, logic [63:0] paddr); + function void printInstr(scoreboard_entry sbe, logic [31:0] instr, logic [63:0] result, logic [63:0] paddr); instruction_trace_item iti = new ($time, clk_ticks, sbe, instr, this.reg_file, result, paddr); // print instruction to console string print_instr = iti.printInstr(); diff --git a/src/util/instruction_tracer_if.sv b/src/util/instruction_tracer_if.sv index b42d8ac3a..3b0209301 100755 --- a/src/util/instruction_tracer_if.sv +++ b/src/util/instruction_tracer_if.sv @@ -26,7 +26,7 @@ interface instruction_tracer_if ( logic flush_unissued; logic flush; // Decode - fetch_entry fetch; + logic [31:0] instruction; logic fetch_valid; logic fetch_ack; // Issue stage @@ -53,7 +53,7 @@ interface instruction_tracer_if ( exception exception; // the tracer just has a passive interface we do not drive anything with it clocking pck @(posedge clk); - input rstn, flush_unissued, flush, fetch, fetch_valid, fetch_ack, issue_ack, issue_sbe, waddr, + input rstn, flush_unissued, flush, instruction, fetch_valid, fetch_ack, issue_ack, issue_sbe, waddr, st_valid, st_paddr, ld_valid, ld_kill, ld_paddr, wdata, we, commit_instr, commit_ack, exception; endclocking