mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-23 05:27:23 -04:00
bug fixes
This commit is contained in:
parent
f164ef291d
commit
9df3814782
9 changed files with 79 additions and 67 deletions
|
@ -119,24 +119,23 @@ module branch_unit(
|
|||
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
always_ff @(posedge clk) begin
|
||||
if (instruction_is_completing | ~branch_issued_r)
|
||||
if (instruction_is_completing | ~branch_issued_r) begin
|
||||
jmp_id <= issue.id;
|
||||
branch_exception_is_jump <= (branch_inputs.jal | branch_inputs.jalr);
|
||||
end
|
||||
end
|
||||
|
||||
assign potential_branch_exception = new_pc[1] & issue.new_request;
|
||||
assign branch_exception_is_jump = (branch_inputs.jal | branch_inputs.jalr);
|
||||
|
||||
assign br_exception.valid = new_pc_ex[1] & branch_taken_ex & branch_issued_r;
|
||||
assign br_exception.code = INST_ADDR_MISSALIGNED;
|
||||
assign br_exception.tval = new_pc_ex;
|
||||
assign br_exception.id = jmp_id;
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign branch_complete = (instruction_is_completing & ~jal_jalr_ex);
|
||||
assign branch_complete = instruction_is_completing & (~jal_jalr_ex) & (~br_exception.valid);
|
||||
assign branch_id = id_ex;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -39,7 +39,6 @@ module csr_regs
|
|||
input exception_packet_t gc_exception,
|
||||
output exception_packet_t csr_exception,
|
||||
output logic [1:0] current_privilege,
|
||||
input logic gc_supress_writeback,
|
||||
input logic [31:0] exception_pc,
|
||||
|
||||
//exception_control
|
||||
|
@ -55,7 +54,6 @@ module csr_regs
|
|||
mmu_interface.csr dmmu,
|
||||
|
||||
//WB
|
||||
input logic instruction_retired,
|
||||
input logic [$clog2(MAX_COMPLETE_COUNT)-1:0] retire_inc,
|
||||
|
||||
//External
|
||||
|
@ -124,14 +122,13 @@ module csr_regs
|
|||
|
||||
//convert addr into packed struct form
|
||||
assign csr_addr = csr_inputs.csr_addr;
|
||||
assign supervisor_write = commit && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == SUPERVISOR_PRIVILEGE);
|
||||
assign machine_write = commit && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == MACHINE_PRIVILEGE);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Exception Check
|
||||
assign privilege_exception = new_request & (csr_addr.privilege > privilege_level);
|
||||
|
||||
assign supervisor_write = commit && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == SUPERVISOR_PRIVILEGE);
|
||||
assign machine_write = commit && !privilege_exception && (csr_addr.rw_bits != CSR_READ_ONLY && csr_addr.privilege == MACHINE_PRIVILEGE);
|
||||
|
||||
logic illegal_instruction;
|
||||
assign illegal_instruction = invalid_addr | privilege_exception;
|
||||
assign csr_exception.valid = new_request & illegal_instruction;
|
||||
assign csr_exception.valid = new_request & (invalid_addr | privilege_exception);
|
||||
|
||||
always_comb begin
|
||||
case (csr_inputs.csr_op)
|
||||
|
|
|
@ -43,6 +43,7 @@ module decode_and_issue (
|
|||
output div_inputs_t div_inputs,
|
||||
|
||||
unit_issue_interface.decode unit_issue [NUM_UNITS-1:0],
|
||||
input logic potential_branch_exception,
|
||||
output logic alu_issued,
|
||||
|
||||
input logic gc_issue_hold,
|
||||
|
@ -297,7 +298,7 @@ module decode_and_issue (
|
|||
assign alu_inputs.shifter_in = rs_data[RS1];
|
||||
assign alu_inputs.shift_amount = issue.opcode[5] ? rs_data[RS2][4:0] : issue.rs_addr[RS2];
|
||||
|
||||
assign alu_issued = issue_to[ALU_UNIT_WB_ID];
|
||||
assign alu_issued = issue_to[ALU_UNIT_WB_ID] & ~potential_branch_exception;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Load Store unit inputs
|
||||
|
@ -534,8 +535,8 @@ module decode_and_issue (
|
|||
////////////////////////////////////////////////////
|
||||
//Trace Interface
|
||||
generate if (ENABLE_TRACE_INTERFACE) begin
|
||||
assign tr_operand_stall = |(unit_needed_issue_stage & unit_ready) & issue_valid & ~|(unit_operands_ready & issue_ready);
|
||||
assign tr_unit_stall = ~|(unit_needed_issue_stage & unit_ready) & issue_valid & |(unit_operands_ready & issue_ready);
|
||||
assign tr_operand_stall = |(unit_needed_issue_stage & unit_ready) & issue_valid & ~|(unit_operands_ready & unit_needed_issue_stage);
|
||||
assign tr_unit_stall = ~|(unit_needed_issue_stage & unit_ready) & issue_valid & |(unit_operands_ready & unit_needed_issue_stage);
|
||||
assign tr_no_id_stall = 0;
|
||||
assign tr_no_instruction_stall = ~issue.stage_valid | gc_fetch_flush;
|
||||
assign tr_other_stall = issue.stage_valid & ~instruction_issued & ~(tr_operand_stall | tr_unit_stall | tr_no_id_stall | tr_no_instruction_stall);
|
||||
|
|
|
@ -38,13 +38,14 @@ module gc_unit(
|
|||
input logic branch_flush,
|
||||
//instruction misalignement
|
||||
input logic potential_branch_exception,
|
||||
input exception_packet_t br_exception,
|
||||
input logic branch_exception_is_jump,
|
||||
input exception_packet_t br_exception,
|
||||
//Illegal instruction
|
||||
input logic illegal_instruction,
|
||||
|
||||
//Load Store Unit
|
||||
input exception_packet_t ls_exception,
|
||||
input logic ls_exception_is_store,
|
||||
|
||||
//TLBs
|
||||
output logic tlb_on,
|
||||
|
@ -60,7 +61,6 @@ module gc_unit(
|
|||
output id_t system_op_or_exception_id,
|
||||
|
||||
//Exception
|
||||
output id_t exception_id,
|
||||
input logic [31:0] exception_pc,
|
||||
|
||||
//WB
|
||||
|
@ -105,40 +105,25 @@ module gc_unit(
|
|||
//SFENCE
|
||||
// flush and hold fetch, wait until L/S input FIFO empty, hold fetch until TLB update complete
|
||||
//ECALL, EBREAK, SRET, MRET:
|
||||
// flush fetch, update CSRs (could be illegal instruction exception as well)
|
||||
// flush fetch, update to CSRs is pipelined
|
||||
|
||||
//Interrupt
|
||||
//Hold issue, wait until IDLE state, flush fetch, take exception
|
||||
//wait until issue/execute exceptions are no longer possible, flush fetch, take exception
|
||||
|
||||
//Fetch Exception
|
||||
//flush fetch, wait until IDLE state, take exception. If decode stage or later exception occurs first, exception is overridden
|
||||
//Fetch Exception (TLB and MMU) (fetch stage)
|
||||
//flush fetch, wait until issue/execute exceptions are no longer possible, take exception. If decode stage or later exception occurs first, exception is overridden
|
||||
|
||||
//Illegal opcode (decode stage)
|
||||
//fetch flush, issue hold, wait until IDLE state, take exception. If execute or later exception occurs first, exception is overridden
|
||||
//Illegal opcode (issue stage)
|
||||
//fetch flush, take exception. If execute or later exception occurs first, exception is overridden
|
||||
|
||||
//CSR exceptions
|
||||
//fetch flush, issue hold, capture ID/rd_non_zero and drain instruction queue, take exception.
|
||||
//Branch exceptions (issue/execute stage)
|
||||
//fetch flush, take exception.
|
||||
|
||||
//LS exceptions (miss-aligned, TLB and MMU)
|
||||
//fetch flush, issue hold, capture ID/rd_non_zero and drain instruction queue, take exception.
|
||||
//CSR exceptions (issue/execute stage)
|
||||
//fetch flush, take exception.
|
||||
|
||||
//Instruction queue drain:
|
||||
// Two possibilities:
|
||||
// 1. Instruction stores to reg file. ID in instruction queue, wait until that ID is oldest (either find oldest valid, or for small cycle penalty just look at last entry and wait for ID and valid)
|
||||
// 2. Instruction does not store to reg file. If IQ not empty, wait for previously issued ID to complete, if empty no waiting required.
|
||||
//
|
||||
// After all preceding instructions have been committed, continue popping instructions from queue but supress write-back operation until queue is drained.
|
||||
|
||||
//In-order mode:
|
||||
// Turn on when an instruction in the execute phase could cause an interrupt (L/S or CSR)
|
||||
// Turn off when exception can no-longer occur (after one cycle for CSR, when L/S input FIFO will be empty)
|
||||
|
||||
//*Complete issued instructions before exception
|
||||
//*Drain L/S FIFO then Hold fetch/issue during TLB clear
|
||||
//*Hold fetch until all stores committed
|
||||
//*Turn on inorder mode when L/S issued, turn off when no instruction can cause interrupt
|
||||
// *If in-order mode and inflight queue empty, disable zero cycle write-back (eg. ALU)
|
||||
//*Hold fetch during potential fetch exception, when fetch buffer drained, if no other exceptions trigger exception
|
||||
//LS exceptions (miss-aligned, TLB and MMU) (issue stage)
|
||||
//fetch flush, take exception. If execute or later exception occurs first, exception is overridden
|
||||
|
||||
typedef enum {RST_STATE, IDLE_STATE, TLB_CLEAR_STATE, IQ_DRAIN} gc_state;
|
||||
gc_state state;
|
||||
|
@ -157,6 +142,9 @@ module gc_unit(
|
|||
logic [XLEN-1:0] wb_csr;
|
||||
csr_inputs_t csr_inputs;
|
||||
exception_packet_t gc_exception;
|
||||
exception_packet_t gc_exception_r;
|
||||
id_t exception_or_system_id;
|
||||
|
||||
exception_packet_t csr_exception;
|
||||
logic [1:0] current_privilege;
|
||||
logic [31:0] trap_pc;
|
||||
|
@ -178,21 +166,24 @@ module gc_unit(
|
|||
logic csr_ready_to_complete_r;
|
||||
id_t instruction_id;
|
||||
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
//Input registering
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue.possible_issue) begin
|
||||
if (issue.possible_issue & ~gc_issue_hold) begin
|
||||
stage1 <= gc_inputs;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign system_op_or_exception_complete =
|
||||
(issue.new_request & (gc_inputs.is_fence | gc_inputs.is_i_fence)) |
|
||||
gc_exception.valid;
|
||||
assign exception_with_rd_complete = ls_exception.valid;
|
||||
assign system_op_or_exception_id = issue.new_request ? issue.id : exception_id;
|
||||
always_ff @(posedge clk) begin
|
||||
system_op_or_exception_complete <=
|
||||
(issue.new_request & (gc_inputs.is_ret | gc_inputs.is_fence | gc_inputs.is_i_fence)) |
|
||||
gc_exception.valid;
|
||||
system_op_or_exception_id <= exception_or_system_id;
|
||||
exception_with_rd_complete <= (ls_exception.valid & ~ls_exception_is_store) | (br_exception.valid & branch_exception_is_jump);
|
||||
end
|
||||
|
||||
//Instruction decode
|
||||
assign opcode = stage1.instruction[6:0];
|
||||
|
@ -206,7 +197,7 @@ module gc_unit(
|
|||
assign gc_fetch_flush = branch_flush | gc_fetch_pc_override;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
gc_issue_hold <= issue.new_request || processing_csr || (next_state inside {TLB_CLEAR_STATE, IQ_DRAIN}) || potential_branch_exception;
|
||||
gc_issue_hold <= issue.new_request || second_cycle_flush || processing_csr || (next_state inside {TLB_CLEAR_STATE, IQ_DRAIN}) || potential_branch_exception;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
|
@ -234,7 +225,7 @@ module gc_unit(
|
|||
case (state)
|
||||
RST_STATE : next_state = IDLE_STATE;
|
||||
IDLE_STATE : begin
|
||||
if (ls_exception.valid | (branch_exception_is_jump & potential_branch_exception)) begin
|
||||
if (ls_exception.valid | potential_branch_exception) begin
|
||||
next_state = IQ_DRAIN;
|
||||
end
|
||||
end
|
||||
|
@ -266,8 +257,8 @@ module gc_unit(
|
|||
endcase
|
||||
end
|
||||
|
||||
assign exception_id =
|
||||
potential_branch_exception ? br_exception.id :
|
||||
assign exception_or_system_id =
|
||||
br_exception.valid ? br_exception.id :
|
||||
(ls_exception.valid ? ls_exception.id : issue.id);
|
||||
|
||||
//TODO: check if possible to convert to unique if, verify potential for overlap
|
||||
|
@ -298,6 +289,7 @@ module gc_unit(
|
|||
//Two cycles: on first cycle the processor front end is flushed,
|
||||
//on the second cycle the new PC is fetched
|
||||
always_ff @ (posedge clk) begin
|
||||
gc_exception_r <= gc_exception;
|
||||
second_cycle_flush <= gc_flush_required;
|
||||
gc_fetch_pc_override <= gc_flush_required | second_cycle_flush | ls_exception.valid | br_exception.valid;
|
||||
if (gc_exception.valid | stage1.is_i_fence | (issue.new_request & gc_inputs.is_ret)) begin
|
||||
|
@ -315,7 +307,30 @@ module gc_unit(
|
|||
assign csr_inputs.rs1_is_zero = (rs1_addr == 0);
|
||||
assign csr_inputs.rd_is_zero = (rd_addr == 0);
|
||||
|
||||
csr_regs csr_registers (.*, .new_request(stage1.is_csr), .read_regs(csr_ready_to_complete), .commit(csr_ready_to_complete_r));
|
||||
csr_regs csr_registers (
|
||||
.clk(clk), .rst(rst),
|
||||
.csr_inputs(csr_inputs),
|
||||
.new_request(stage1.is_csr),
|
||||
.read_regs(csr_ready_to_complete),
|
||||
.commit(csr_ready_to_complete_r),
|
||||
.gc_exception(gc_exception_r),
|
||||
.csr_exception(csr_exception),
|
||||
.current_privilege(current_privilege),
|
||||
.exception_pc(exception_pc),
|
||||
.mret(mret),
|
||||
.sret(sret),
|
||||
.tlb_on(tlb_on),
|
||||
.asid(asid),
|
||||
.immu(immu),
|
||||
.dmmu(dmmu),
|
||||
.retire_inc(retire_inc),
|
||||
.interrupt(interrupt),
|
||||
.timer_interrupt(timer_interrupt),
|
||||
.wb_csr(wb_csr),
|
||||
.trap_pc(trap_pc),
|
||||
.csr_mepc(csr_mepc),
|
||||
.csr_sepc(csr_sepc)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Decode / Write-back Handshaking
|
||||
|
|
|
@ -75,7 +75,6 @@ module instruction_metadata_and_id_management
|
|||
output logic [4:0] retired_rd_addr [COMMIT_PORTS],
|
||||
output id_t id_for_rd [COMMIT_PORTS],
|
||||
//Exception
|
||||
input id_t exception_id,
|
||||
output logic [31:0] exception_pc
|
||||
|
||||
);
|
||||
|
@ -336,7 +335,7 @@ module instruction_metadata_and_id_management
|
|||
always_comb begin
|
||||
for (int i = 0; i < REGFILE_READ_PORTS; i++) begin
|
||||
rs_id[i] = rd_to_id_table[issue.rs_addr[i]];
|
||||
rs_inuse[i] = (issue.rs_addr[i] == instruction_table[rs_id[i]][11:7]);//11:7 is rd_addr
|
||||
rs_inuse[i] = (|issue.rs_addr[i]) & (issue.rs_addr[i] == instruction_table[rs_id[i]][11:7]);//11:7 is rd_addr
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -350,7 +349,7 @@ module instruction_metadata_and_id_management
|
|||
|
||||
//Exception Support
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
assign exception_pc = pc_table[exception_id];
|
||||
assign exception_pc = pc_table[system_op_or_exception_id];
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -149,7 +149,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
if (new_forwarded_store)
|
||||
needed_id_r <= lsq.data_id;
|
||||
end
|
||||
assign wb_store.id_needed = possible_new_forwarded_store ? lsq.data_id : needed_id_r;
|
||||
assign wb_store.id_needed = waiting_r ? needed_id_r : lsq.data_id;
|
||||
|
||||
|
||||
|
||||
|
@ -159,7 +159,6 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
|
||||
assign oldest_lsq_entry = lsq_entries[oldest_id];
|
||||
assign lsq.transaction_ready = oldest_fifo.valid & (~oldest_lsq_entry.forwarded_store | wb_store.id_done);
|
||||
assign lsq.id_needed_by_store = oldest_lsq_entry.data_id;
|
||||
|
||||
always_comb begin
|
||||
lsq.transaction_out.addr = oldest_lsq_entry.addr;
|
||||
|
|
|
@ -62,6 +62,7 @@ module load_store_unit (
|
|||
output logic ls_is_idle,
|
||||
|
||||
output exception_packet_t ls_exception,
|
||||
output logic ls_exception_is_store,
|
||||
|
||||
unit_writeback_interface.unit wb
|
||||
);
|
||||
|
@ -138,7 +139,7 @@ generate if (ENABLE_M_MODE) begin
|
|||
default : unaligned_addr = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign ls_exception_is_store = ls_inputs.store;
|
||||
assign ls_exception.valid = unaligned_addr & issue.new_request;
|
||||
assign ls_exception.code = ls_inputs.store ? STORE_AMO_ADDR_MISSALIGNED : LOAD_ADDR_MISSALIGNED;
|
||||
assign ls_exception.tval = virtual_address;
|
||||
|
@ -228,7 +229,7 @@ endgenerate
|
|||
|
||||
assign ready_for_issue = units_ready & (~unit_switch_stall);
|
||||
|
||||
assign issue.ready = lsq.ready & ~(ls_inputs.forwarded_store & ~ready_for_forwarded_store);
|
||||
assign issue.ready = ls_inputs.forwarded_store ? lsq.ready & ready_for_forwarded_store : lsq.ready;
|
||||
assign issue_request = lsq.accepted;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -241,7 +242,7 @@ endgenerate
|
|||
|
||||
assign load_attributes.data_in = load_attributes_in;
|
||||
assign load_attributes.push = issue_request & shared_inputs.load;
|
||||
assign load_attributes.potential_push = ~load_attributes.full;
|
||||
assign load_attributes.potential_push = issue_request & shared_inputs.load;
|
||||
assign load_attributes.pop = load_complete;
|
||||
|
||||
assign stage2_attr = load_attributes.data_out;
|
||||
|
|
|
@ -52,7 +52,7 @@ module mul_unit(
|
|||
assign rs1_ext = signed'({mul_inputs.rs1[31] & rs1_signed, mul_inputs.rs1});
|
||||
assign rs2_ext = signed'({mul_inputs.rs2[31] & rs2_signed, mul_inputs.rs2});
|
||||
|
||||
assign issue.ready = stage1_advance;
|
||||
assign issue.ready = (~done[0] | ~done[1]);//stage1_advance;
|
||||
assign stage1_advance = ~done[0] | stage2_advance;
|
||||
assign stage2_advance = ~done[1] | wb.ack;
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ module taiga (
|
|||
logic alu_issued;
|
||||
|
||||
exception_packet_t ls_exception;
|
||||
logic ls_exception_is_store;
|
||||
|
||||
unit_writeback_interface unit_wb [NUM_WB_UNITS]();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue