bug fixes

This commit is contained in:
Eric Matthews 2020-06-16 16:48:27 -07:00
parent f164ef291d
commit 9df3814782
9 changed files with 79 additions and 67 deletions

View file

@ -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;
////////////////////////////////////////////////////

View file

@ -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)

View file

@ -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);

View file

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

View file

@ -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
////////////////////////////////////////////////////

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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]();