mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-24 05:57:22 -04:00
execution and writeback changes for new ID system
This commit is contained in:
parent
faede7fe7e
commit
a0f4368f85
22 changed files with 443 additions and 587 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2017 Eric Matthews, Lesley Shannon
|
||||
* Copyright © 2017-2020 Eric Matthews, Lesley Shannon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -27,9 +27,10 @@ import taiga_types::*;
|
|||
module alu_unit(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
input logic single_cycle_issue_possible,
|
||||
unit_issue_interface.unit issue,
|
||||
input alu_inputs_t alu_inputs,
|
||||
output unit_writeback_t wb
|
||||
unit_writeback_interface.unit wb
|
||||
);
|
||||
|
||||
logic[XLEN:0] add_sub_result;
|
||||
|
@ -77,10 +78,10 @@ module alu_unit(
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Output
|
||||
assign issue.ready = 1;
|
||||
assign issue.ready = single_cycle_issue_possible;//single_cycle_issue_possible;
|
||||
assign wb.rd = result;
|
||||
assign wb.done = issue.new_request;
|
||||
assign wb.id = issue.instruction_id;
|
||||
assign wb.id = issue.id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
|
|
|
@ -65,6 +65,7 @@ module branch_unit(
|
|||
logic [31:0] pc_ex;
|
||||
logic instruction_is_completing;
|
||||
|
||||
logic jal_jalr_ex;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
//Only stall condition is if the following instruction is not valid for pc comparisons.
|
||||
|
@ -108,17 +109,18 @@ module branch_unit(
|
|||
new_pc_ex[31:1] <= new_pc[31:1];
|
||||
new_pc_ex[0] <= new_pc[0] & ~branch_inputs.jalr;
|
||||
id_ex <= issue.id;
|
||||
jal_jalr_ex <= branch_inputs.jal | branch_inputs.jalr;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Exception support
|
||||
instruction_id_t jmp_instruction_id;
|
||||
id_t jmp_id;
|
||||
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
always_ff @(posedge clk) begin
|
||||
if (instruction_is_completing | ~branch_issued_r)
|
||||
jmp_instruction_id <= issue.instruction_id;
|
||||
jmp_id <= issue.id;
|
||||
end
|
||||
|
||||
assign potential_branch_exception = new_pc[1] & issue.new_request;
|
||||
|
@ -126,16 +128,15 @@ module branch_unit(
|
|||
|
||||
assign br_exception.valid = new_pc_ex[1] & branch_taken_ex & branch_issued_r;
|
||||
assign br_exception.code = INST_ADDR_MISSALIGNED;
|
||||
assign br_exception.pc = pc_ex;
|
||||
assign br_exception.tval = new_pc_ex;
|
||||
assign br_exception.id = jmp_instruction_id;
|
||||
assign br_exception.id = jmp_id;
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign branch_complete = instruction_is_completing | br_exception.valid;
|
||||
assign branch_complete = (instruction_is_completing & ~jal_jalr_ex);
|
||||
assign branch_id = id_ex;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -40,6 +40,7 @@ module csr_regs
|
|||
output exception_packet_t csr_exception,
|
||||
output logic [1:0] current_privilege,
|
||||
input logic gc_supress_writeback,
|
||||
input logic [31:0] exception_pc,
|
||||
|
||||
//Decode
|
||||
input logic instruction_issued_no_rd,
|
||||
|
@ -382,7 +383,7 @@ generate if (ENABLE_M_MODE) begin
|
|||
always_ff @(posedge clk) begin
|
||||
mepc[1:0] <= '0;
|
||||
if (mwrite_decoder[MEPC[7:0]] | gc_exception.valid)
|
||||
mepc[XLEN-1:2] <= gc_exception.valid ? gc_exception.pc[XLEN-1:2] : updated_csr[XLEN-1:2];
|
||||
mepc[XLEN-1:2] <= gc_exception.valid ? exception_pc[XLEN-1:2] : updated_csr[XLEN-1:2];
|
||||
end
|
||||
assign csr_mepc = mepc;
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ module decode_and_issue (
|
|||
input logic [31:0] decode_pc,
|
||||
input logic [31:0] decode_instruction,
|
||||
|
||||
tracking_interface.decode ti,
|
||||
register_file_issue_interface.issue rf_issue,
|
||||
|
||||
output alu_inputs_t alu_inputs,
|
||||
|
@ -57,7 +56,6 @@ module decode_and_issue (
|
|||
output id_t issue_id,
|
||||
output logic issue_stage_valid,
|
||||
output logic id_issued,
|
||||
output logic dummy_id_complete,
|
||||
output logic instruction_issued_no_rd,
|
||||
output logic instruction_issued_with_rd,
|
||||
output logic illegal_instruction,
|
||||
|
@ -189,26 +187,7 @@ module decode_and_issue (
|
|||
end
|
||||
end
|
||||
assign rf_issue.instruction_issued = instruction_issued_with_rd & (|rd_addr_issue_stage);
|
||||
assign rf_issue.id = ti.issue_id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Tracking Interface
|
||||
//CSR results are passed through the load/store output
|
||||
always_comb begin
|
||||
unit_needed_for_id_gen = unit_needed[NUM_WB_UNITS-1:0];
|
||||
unit_needed_for_id_gen[LS_UNIT_WB_ID] |= (unit_needed[GC_UNIT_ID] & is_csr);
|
||||
end
|
||||
one_hot_to_integer #(NUM_WB_UNITS) unit_id_gen (.*, .one_hot(unit_needed_for_id_gen), .int_out(unit_needed_for_id_gen_int));
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_stage_ready) begin
|
||||
ti.inflight_packet.is_store <= is_store;
|
||||
ti.issue_unit_id <= unit_needed_for_id_gen_int;
|
||||
ti.exception_possible <= opcode_trim inside {LOAD_T, STORE_T, AMO_T};
|
||||
ti.inflight_packet.rd_addr <= rd_addr;
|
||||
end
|
||||
end
|
||||
assign ti.issued = instruction_issued & (uses_rd_issue_stage | unit_needed_issue_stage[LS_UNIT_WB_ID]);
|
||||
assign rf_issue.id = issue_id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit Determination
|
||||
|
@ -239,14 +218,15 @@ module decode_and_issue (
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Issue Determination
|
||||
assign issue_valid = issue_stage_valid & ti.id_available & ~gc_issue_hold & ~gc_fetch_flush;
|
||||
assign issue_valid = issue_stage_valid & ~gc_issue_hold & ~gc_fetch_flush;
|
||||
|
||||
assign operands_ready = ~rf_issue.rs1_conflict & ~rf_issue.rs2_conflict;
|
||||
|
||||
//All units share the same operand ready logic except load-store which has an internal forwarding path
|
||||
always_comb begin
|
||||
unit_operands_ready = {NUM_UNITS{operands_ready}};
|
||||
unit_operands_ready[LS_UNIT_WB_ID] = ~rf_issue.rs1_conflict;
|
||||
unit_operands_ready[LS_UNIT_WB_ID] = ~rf_issue.rs1_conflict & ~rf_issue.rs2_conflict;
|
||||
unit_operands_ready[BRANCH_UNIT_ID] &= unit_ready[ALU_UNIT_WB_ID];
|
||||
end
|
||||
|
||||
assign issue_ready = unit_needed_issue_stage & unit_ready;
|
||||
|
@ -257,7 +237,6 @@ module decode_and_issue (
|
|||
assign instruction_issued_with_rd = instruction_issued & uses_rd_issue_stage;
|
||||
|
||||
assign id_issued = instruction_issued;
|
||||
assign dummy_id_complete = instruction_issued & ~unit_needed_issue_stage[BRANCH_UNIT_ID];
|
||||
////////////////////////////////////////////////////
|
||||
//ALU unit inputs
|
||||
logic [XLEN-1:0] alu_rs1_data;
|
||||
|
@ -401,10 +380,9 @@ module decode_and_issue (
|
|||
assign ls_inputs.load = is_load_r;
|
||||
assign ls_inputs.store = is_store_r;
|
||||
assign ls_inputs.fn3 = amo_op ? LS_W_fn3 : fn3_issue_stage;
|
||||
assign ls_inputs.pc = pc_issue_stage;
|
||||
assign ls_inputs.rs1 = rf_issue.rs1_data;
|
||||
assign ls_inputs.rs2 = rf_issue.rs2_data;
|
||||
assign ls_inputs.forwarded_store = rf_issue.rs2_conflict;
|
||||
assign ls_inputs.forwarded_store = 0;//rf_issue.rs2_conflict;
|
||||
assign ls_inputs.store_forward_id = rf_issue.rs2_id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -558,9 +536,8 @@ module decode_and_issue (
|
|||
////////////////////////////////////////////////////
|
||||
//Unit EX signals
|
||||
generate for (i = 0; i < NUM_UNITS; i++) begin
|
||||
assign unit_issue[i].possible_issue = unit_needed_issue_stage[i] & unit_operands_ready[i] & issue_stage_valid & ti.id_available & ~gc_issue_hold;
|
||||
assign unit_issue[i].possible_issue = unit_needed_issue_stage[i] & unit_operands_ready[i] & issue_stage_valid & ~gc_issue_hold;
|
||||
assign unit_issue[i].new_request = issue[i];
|
||||
assign unit_issue[i].instruction_id = ti.issue_id;
|
||||
assign unit_issue[i].id = issue_id;
|
||||
always_ff @(posedge clk) begin
|
||||
unit_issue[i].new_request_r <= issue[i];
|
||||
|
@ -583,7 +560,7 @@ module decode_and_issue (
|
|||
|
||||
|
||||
//Illegal instruction if the instruction is invalid, but could otherwise be issued
|
||||
assign illegal_instruction = illegal_instruction_pattern_r & issue_stage_valid & ti.id_available & ~gc_issue_hold & ~gc_fetch_flush;
|
||||
assign illegal_instruction = illegal_instruction_pattern_r & issue_stage_valid & ~gc_issue_hold & ~gc_fetch_flush;
|
||||
end endgenerate
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
|
@ -597,7 +574,7 @@ module decode_and_issue (
|
|||
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_no_id_stall = |(unit_needed_issue_stage & unit_ready) & (issue_stage_valid & ~ti.id_available & ~gc_issue_hold & ~gc_fetch_flush) & |(unit_operands_ready & issue_ready);
|
||||
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);
|
||||
assign tr_branch_operand_stall = tr_operand_stall & unit_needed_issue_stage[BRANCH_UNIT_ID];
|
||||
|
|
|
@ -33,7 +33,7 @@ module div_unit
|
|||
|
||||
input div_inputs_t div_inputs,
|
||||
unit_issue_interface.unit issue,
|
||||
output unit_writeback_t wb
|
||||
unit_writeback_interface.unit wb
|
||||
);
|
||||
|
||||
logic signed_divop;
|
||||
|
@ -53,7 +53,7 @@ module div_unit
|
|||
logic negate_quotient;
|
||||
logic negate_remainder;
|
||||
logic reuse_result;
|
||||
instruction_id_t instruction_id;
|
||||
id_t id;
|
||||
} div_fifo_inputs_t;
|
||||
|
||||
div_fifo_inputs_t fifo_inputs;
|
||||
|
@ -94,18 +94,18 @@ module div_unit
|
|||
assign fifo_inputs.negate_quotient = negate_quotient;
|
||||
assign fifo_inputs.negate_remainder = negate_remainder;
|
||||
assign fifo_inputs.reuse_result = div_inputs.reuse_result;
|
||||
assign fifo_inputs.instruction_id = issue.instruction_id;
|
||||
assign fifo_inputs.id = issue.id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Input FIFO
|
||||
taiga_fifo #(.DATA_WIDTH($bits(div_fifo_inputs_t)), .FIFO_DEPTH(MAX_INFLIGHT_COUNT))
|
||||
taiga_fifo #(.DATA_WIDTH($bits(div_fifo_inputs_t)), .FIFO_DEPTH(MAX_IDS))
|
||||
div_input_fifo (.fifo(input_fifo), .*);
|
||||
|
||||
assign input_fifo.data_in = fifo_inputs;
|
||||
assign input_fifo.push = issue.possible_issue;
|
||||
assign input_fifo.supress_push = gc_fetch_flush;
|
||||
assign issue.ready = 1; //As FIFO depth is the same as MAX_INFLIGHT_COUNT
|
||||
assign input_fifo.pop = div_done;
|
||||
assign input_fifo.pop = wb.done & wb.ack;
|
||||
assign div_op = input_fifo.data_out;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -117,7 +117,7 @@ module div_unit
|
|||
set_clr_reg_with_rst #(.SET_OVER_CLR(1), .WIDTH(1), .RST_VALUE('0)) in_progress_m (
|
||||
.clk, .rst,
|
||||
.set(div_core.start),
|
||||
.clr(div_core.done),
|
||||
.clr(wb.ack),
|
||||
.result(in_progress)
|
||||
);
|
||||
|
||||
|
@ -129,10 +129,18 @@ module div_unit
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Output
|
||||
logic done_r;
|
||||
assign negate_result = div_op.remainder_op ? div_op.negate_remainder : (~div_core.divisor_is_zero & div_op.negate_quotient);
|
||||
assign wb.rd = negate_if (div_op.remainder_op ? div_core.remainder : ({32{div_core.divisor_is_zero}} | div_core.quotient), negate_result);
|
||||
assign wb.done = div_done;
|
||||
assign wb.id = div_op.instruction_id;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (wb.ack)
|
||||
done_r <= 0;
|
||||
else if (div_done)
|
||||
done_r <= 1;
|
||||
end
|
||||
assign wb.done = div_done | done_r;
|
||||
assign wb.id = div_op.id;
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ module gc_unit(
|
|||
|
||||
//Load Store Unit
|
||||
input exception_packet_t ls_exception,
|
||||
input logic ls_exception_valid,
|
||||
|
||||
//TLBs
|
||||
output logic tlb_on,
|
||||
|
@ -57,13 +56,17 @@ module gc_unit(
|
|||
mmu_interface.csr dmmu,
|
||||
|
||||
//ID Management
|
||||
output logic system_op_complete,
|
||||
output id_t system_op_id,
|
||||
output logic system_op_or_exception_complete,
|
||||
output id_t system_op_or_exception_id,
|
||||
|
||||
//Exception
|
||||
output id_t exception_id,
|
||||
input logic [31:0] exception_pc,
|
||||
|
||||
//WB
|
||||
input logic instruction_retired,
|
||||
input logic instruction_queue_empty,
|
||||
input instruction_id_t oldest_id,
|
||||
input logic writeback_is_idle,
|
||||
//unit_writeback_interface.unit gc_wb,
|
||||
|
||||
//External
|
||||
|
@ -77,14 +80,13 @@ module gc_unit(
|
|||
output logic gc_fetch_pc_override,
|
||||
output logic gc_supress_writeback,
|
||||
|
||||
output logic ls_exception_ack,
|
||||
|
||||
output logic [31:0] gc_fetch_pc,
|
||||
|
||||
//Write-back to Load-Store Unit
|
||||
output logic[31:0] csr_rd,
|
||||
output instruction_id_t csr_id,
|
||||
output logic csr_done
|
||||
output id_t csr_id,
|
||||
output logic csr_done,
|
||||
input logic ls_is_idle
|
||||
);
|
||||
|
||||
//Largest depth for TLBs
|
||||
|
@ -139,7 +141,7 @@ module gc_unit(
|
|||
// *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
|
||||
|
||||
typedef enum {RST_STATE, IDLE_STATE, TLB_CLEAR_STATE, IQ_DRAIN, IQ_DISCARD} gc_state;
|
||||
typedef enum {RST_STATE, IDLE_STATE, TLB_CLEAR_STATE, IQ_DRAIN} gc_state;
|
||||
gc_state state;
|
||||
gc_state next_state;
|
||||
gc_state prev_state;
|
||||
|
@ -175,10 +177,7 @@ module gc_unit(
|
|||
logic processing_csr;
|
||||
logic csr_ready_to_complete;
|
||||
logic csr_ready_to_complete_r;
|
||||
instruction_id_t instruction_id;
|
||||
|
||||
instruction_id_t exception_id;
|
||||
instruction_id_t exception_id_r;
|
||||
id_t instruction_id;
|
||||
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -190,8 +189,10 @@ module gc_unit(
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign system_op_complete = issue.new_request & (gc_inputs.is_fence | gc_inputs.is_i_fence);
|
||||
assign system_op_id = issue.id;
|
||||
assign system_op_or_exception_complete =
|
||||
(issue.new_request & (gc_inputs.is_fence | gc_inputs.is_i_fence)) |
|
||||
gc_exception.valid;
|
||||
assign system_op_or_exception_id = issue.new_request ? issue.id : exception_id;
|
||||
|
||||
//Instruction decode
|
||||
assign opcode = stage1.instruction[6:0];
|
||||
|
@ -205,15 +206,11 @@ 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, IQ_DISCARD}) || potential_branch_exception;
|
||||
gc_issue_hold <= issue.new_request || processing_csr || (next_state inside {TLB_CLEAR_STATE, IQ_DRAIN}) || potential_branch_exception;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
gc_issue_flush <= (next_state == IQ_DISCARD);
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
gc_supress_writeback <= next_state inside {TLB_CLEAR_STATE, IQ_DISCARD} ? 1 : 0;
|
||||
gc_supress_writeback <= next_state inside {TLB_CLEAR_STATE} ? 1 : 0;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -238,12 +235,11 @@ module gc_unit(
|
|||
RST_STATE : next_state = IDLE_STATE;
|
||||
IDLE_STATE : begin
|
||||
if (ls_exception.valid | (branch_exception_is_jump & potential_branch_exception)) begin
|
||||
next_state = (exception_id == oldest_id) ? IQ_DISCARD : IQ_DRAIN;
|
||||
next_state = IQ_DRAIN;
|
||||
end
|
||||
end
|
||||
TLB_CLEAR_STATE : if (tlb_clear_done) next_state = IDLE_STATE;
|
||||
IQ_DRAIN : if (exception_id_r == oldest_id) next_state = IQ_DISCARD;
|
||||
IQ_DISCARD : if (instruction_queue_empty) next_state = IDLE_STATE;
|
||||
IQ_DRAIN : next_state = IDLE_STATE;
|
||||
default : next_state = RST_STATE;
|
||||
endcase
|
||||
end
|
||||
|
@ -259,7 +255,6 @@ module gc_unit(
|
|||
end
|
||||
////////////////////////////////////////////////////
|
||||
//Exception handling
|
||||
logic processing_ls_exception;
|
||||
|
||||
//The type of call instruction is depedent on the current privilege level
|
||||
always_comb begin
|
||||
|
@ -271,43 +266,27 @@ module gc_unit(
|
|||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (gc_exception.valid)
|
||||
processing_ls_exception <= ls_exception.valid;
|
||||
end
|
||||
|
||||
assign ls_exception_ack = processing_ls_exception && (prev_state inside {IDLE_STATE, IQ_DRAIN}) && (state == IQ_DISCARD);
|
||||
|
||||
assign exception_id =
|
||||
potential_branch_exception ? br_exception.id :
|
||||
(ls_exception.valid ? ls_exception.id : issue.instruction_id);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (gc_exception.valid)
|
||||
exception_id_r <= exception_id;
|
||||
end
|
||||
(ls_exception.valid ? ls_exception.id : issue.id);
|
||||
|
||||
//TODO: check if possible to convert to unique if, verify potential for overlap
|
||||
always_comb begin
|
||||
//PC sourced from instruction metadata table
|
||||
if (br_exception.valid) begin
|
||||
gc_exception.code = br_exception.code;
|
||||
gc_exception.pc = br_exception.pc;
|
||||
gc_exception.tval = br_exception.tval;
|
||||
end else if (illegal_instruction) begin
|
||||
gc_exception.code = ILLEGAL_INST;
|
||||
gc_exception.pc = gc_inputs.pc;
|
||||
gc_exception.tval = gc_inputs.instruction;//optional, can be zero instead
|
||||
end else if (ls_exception.valid) begin
|
||||
gc_exception.code = ls_exception.code;
|
||||
gc_exception.pc = ls_exception.pc;
|
||||
gc_exception.tval = ls_exception.tval;
|
||||
end else if (gc_inputs.is_ecall) begin
|
||||
gc_exception.code = ecall_code;
|
||||
gc_exception.pc = gc_inputs.pc;
|
||||
gc_exception.tval = '0;
|
||||
end else begin
|
||||
gc_exception.code = BREAK;
|
||||
gc_exception.pc = gc_inputs.pc;
|
||||
gc_exception.tval = '0;
|
||||
end
|
||||
end
|
||||
|
@ -352,12 +331,12 @@ module gc_unit(
|
|||
.result(processing_csr)
|
||||
);
|
||||
|
||||
assign csr_ready_to_complete = processing_csr && (oldest_id == instruction_id);
|
||||
assign csr_ready_to_complete = processing_csr & ls_is_idle & writeback_is_idle;
|
||||
always_ff @(posedge clk) begin
|
||||
csr_ready_to_complete_r <= csr_ready_to_complete;
|
||||
csr_id <= instruction_id;
|
||||
if (issue.new_request) begin
|
||||
instruction_id <= issue.instruction_id;
|
||||
instruction_id <= issue.id;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ module id_inuse (
|
|||
input logic [4:0] rs1_addr,
|
||||
input logic [4:0] rs2_addr,
|
||||
input logic [4:0] issued_rd_addr,
|
||||
input instruction_id_t issue_id,
|
||||
input instruction_id_t retired_id,
|
||||
input id_t issue_id,
|
||||
input id_t retired_id,
|
||||
input logic issued,
|
||||
input logic retired,
|
||||
output logic rs1_inuse,
|
||||
|
|
|
@ -58,8 +58,8 @@ module id_management
|
|||
input logic branch_complete,
|
||||
input id_t branch_id,
|
||||
|
||||
input logic system_op_complete,
|
||||
input id_t system_op_id,
|
||||
input logic system_op_or_exception_complete,
|
||||
input id_t system_op_or_exception_id,
|
||||
|
||||
input logic instruction_retired,
|
||||
input id_t retired_id
|
||||
|
@ -75,10 +75,9 @@ module id_management
|
|||
logic decoded_toggle_mem [MAX_IDS];
|
||||
logic decoded_issued_toggle_mem [MAX_IDS];
|
||||
logic issued_toggle_mem [MAX_IDS];
|
||||
logic dummy_toggle_mem [MAX_IDS];
|
||||
logic branch_complete_toggle_mem [MAX_IDS];
|
||||
logic store_complete_toggle_mem [MAX_IDS];
|
||||
logic system_op_complete_toggle_mem [MAX_IDS];
|
||||
logic system_op_or_exception_complete_toggle_mem [MAX_IDS];
|
||||
logic retired_toggle_mem [MAX_IDS];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -146,12 +145,6 @@ module id_management
|
|||
issued_toggle_mem[issue_id] <= ~issued_toggle_mem[issue_id];
|
||||
end
|
||||
|
||||
initial dummy_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (dummy_id_complete)
|
||||
dummy_toggle_mem[issue_id] <= ~dummy_toggle_mem[issue_id];
|
||||
end
|
||||
|
||||
initial branch_complete_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (branch_complete)
|
||||
|
@ -164,10 +157,10 @@ module id_management
|
|||
store_complete_toggle_mem[store_id] <= ~store_complete_toggle_mem[store_id];
|
||||
end
|
||||
|
||||
initial system_op_complete_toggle_mem = '{default: 0};
|
||||
initial system_op_or_exception_complete_toggle_mem = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (system_op_complete)
|
||||
system_op_complete_toggle_mem[system_op_id] <= ~system_op_complete_toggle_mem[system_op_id];
|
||||
if (system_op_or_exception_complete)
|
||||
system_op_or_exception_complete_toggle_mem[system_op_or_exception_id] <= ~system_op_or_exception_complete_toggle_mem[system_op_or_exception_id];
|
||||
end
|
||||
|
||||
initial retired_toggle_mem = '{default: 0};
|
||||
|
@ -183,11 +176,9 @@ module id_management
|
|||
assign id_not_inflight =
|
||||
~(issued_toggle_mem[pc_id_i] ^
|
||||
branch_complete_toggle_mem[pc_id_i] ^
|
||||
dummy_toggle_mem[pc_id_i]
|
||||
);// ^
|
||||
//store_complete_toggle_mem[pc_id_i] ^
|
||||
//system_op_complete_toggle_mem[pc_id_i] ^
|
||||
//retired_toggle_mem[pc_id_i]);
|
||||
store_complete_toggle_mem[pc_id_i] ^
|
||||
system_op_or_exception_complete_toggle_mem[pc_id_i] ^
|
||||
retired_toggle_mem[pc_id_i]);
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2019 Eric Matthews, Lesley Shannon
|
||||
* Copyright © 2020 Eric Matthews, Lesley Shannon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,49 +20,67 @@
|
|||
* Eric Matthews <ematthew@sfu.ca>
|
||||
*/
|
||||
|
||||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
|
||||
module id_tracking
|
||||
(
|
||||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
input logic issued,
|
||||
input logic retired,
|
||||
|
||||
input logic gc_fetch_flush,
|
||||
|
||||
|
||||
//ID issuing
|
||||
output id_t next_id,
|
||||
output logic id_available,
|
||||
output instruction_id_t oldest_id,
|
||||
output instruction_id_t next_id,
|
||||
output logic empty
|
||||
);
|
||||
input id_assigned,
|
||||
|
||||
// m
|
||||
|
||||
//Decode ID
|
||||
input id_t decode_id,
|
||||
input decode_issued,
|
||||
output decode_id_valid,
|
||||
|
||||
//Issue stage
|
||||
input id_t issue_id,
|
||||
input instruction_issued,
|
||||
|
||||
);
|
||||
//////////////////////////////////////////
|
||||
localparam LOG2_MAX_INFLIGHT_COUNT = $clog2(MAX_INFLIGHT_COUNT);
|
||||
logic [LOG2_MAX_INFLIGHT_COUNT:0] inflight_count;
|
||||
localparam LOG2_MAX_IDS = $clog2(MAX_IDS);
|
||||
|
||||
fifo_interface #(.DATA_WIDTH($bits(id_t))) fetched_ids();
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
oldest_id <= 0;
|
||||
else
|
||||
oldest_id <= oldest_id + LOG2_MAX_INFLIGHT_COUNT'(retired);
|
||||
end
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
next_id <= 0;
|
||||
else
|
||||
next_id <= next_id + LOG2_MAX_INFLIGHT_COUNT'(issued);
|
||||
next_id <= next_id + LOG2_MAX_IDS'(id_assigned);
|
||||
end
|
||||
|
||||
//Upper bit is id_available
|
||||
assign fetched_ids.push = id_assigned;
|
||||
assign fetched_ids.pop = decode_issued;
|
||||
assign fetched_ids.data_in = next_id;
|
||||
|
||||
assign decode_id = fetched_ids.data_out;
|
||||
assign decode_id_valid = fetched_ids.valid;
|
||||
|
||||
taiga_fifo #(.DATA_WIDTH($bits(id_t)), .FIFO_DEPTH(MAX_IDS))
|
||||
fetched_ids_fifo (.fifo(fetched_ids), .rst(rst | gc_fetch_flush), .*);
|
||||
|
||||
|
||||
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
inflight_count <= '1;
|
||||
id_available <= 0;
|
||||
else
|
||||
inflight_count <= inflight_count + (LOG2_MAX_INFLIGHT_COUNT+1)'(retired) - (LOG2_MAX_INFLIGHT_COUNT+1)'(issued);
|
||||
id_available <=
|
||||
end
|
||||
|
||||
assign empty = &inflight_count;//all ones
|
||||
assign id_available = inflight_count[LOG2_MAX_INFLIGHT_COUNT];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -70,7 +88,6 @@ module id_tracking
|
|||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
always_ff @ (posedge clk) begin
|
||||
assert (rst | !(~rst & ~id_available & issued)) else $error("Issued without valid ID!");
|
||||
assert (rst | !(~rst & empty & (retired & ~issued))) else $error("Retired without any instruction inflight!");
|
||||
assert (rst | !(~rst & ~id_available & id_assigned)) else $error("Issued without valid ID!");
|
||||
end
|
||||
endmodule
|
||||
|
|
|
@ -38,7 +38,6 @@ module instruction_metadata
|
|||
input logic fetch_complete,
|
||||
input logic [31:0] fetch_instruction,
|
||||
|
||||
|
||||
//Decode ID
|
||||
input id_t decode_id,
|
||||
output logic [31:0] decode_pc,
|
||||
|
@ -47,18 +46,22 @@ module instruction_metadata
|
|||
//Branch Predictor
|
||||
input branch_metadata_t branch_metadata_if,
|
||||
input id_t branch_id,
|
||||
output branch_metadata_t branch_metadata_ex
|
||||
output branch_metadata_t branch_metadata_ex,
|
||||
|
||||
//Writeback/Register File
|
||||
input id_t retired_id,
|
||||
output logic [4:0] retired_rd_addr,
|
||||
|
||||
//Exception
|
||||
//input id_t exception_id,
|
||||
//output logic [31:0] exception_pc,
|
||||
//output logic [31:0] exception_instruction
|
||||
input id_t exception_id,
|
||||
output logic [31:0] exception_pc
|
||||
|
||||
);
|
||||
//////////////////////////////////////////
|
||||
logic [31:0] pc_table [MAX_IDS];
|
||||
logic [31:0] instruction_table [MAX_IDS];
|
||||
logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS];
|
||||
logic [31:0] rd_table [MAX_IDS];
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
|
@ -80,6 +83,12 @@ module instruction_metadata
|
|||
instruction_table[fetch_id] <= fetch_instruction;
|
||||
end
|
||||
|
||||
//rd table
|
||||
// always_ff @ (posedge clk) begin
|
||||
// if (instruction_retired)
|
||||
// rd_table[id_retired] <= retired_rd;
|
||||
// end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Outputs
|
||||
|
||||
|
@ -90,11 +99,13 @@ module instruction_metadata
|
|||
//Branch Predictor
|
||||
assign branch_metadata_ex = branch_metadata_table[branch_id];
|
||||
|
||||
//Register File
|
||||
assign retired_rd_addr = instruction_table[retired_id][11:7];
|
||||
|
||||
//Exception Support
|
||||
// generate if (ENABLE_M_MODE) begin
|
||||
// assign exception_pc = pc_table[exception_id];
|
||||
// assign exception_instruction = instruction_table[exception_id];
|
||||
// end endgenerate
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
assign exception_pc = pc_table[exception_id];
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
|
|
|
@ -53,13 +53,29 @@ interface unit_issue_interface;
|
|||
logic possible_issue;
|
||||
logic new_request;
|
||||
logic new_request_r;
|
||||
instruction_id_t instruction_id;
|
||||
id_t id;
|
||||
|
||||
logic ready;
|
||||
|
||||
modport decode (input ready, output possible_issue, new_request, new_request_r, instruction_id, id);
|
||||
modport unit (output ready, input possible_issue, new_request, new_request_r, instruction_id, id);
|
||||
modport decode (input ready, output possible_issue, new_request, new_request_r, id);
|
||||
modport unit (output ready, input possible_issue, new_request, new_request_r, id);
|
||||
endinterface
|
||||
|
||||
interface unit_writeback_interface;
|
||||
logic ack;
|
||||
|
||||
id_t id;
|
||||
logic done;
|
||||
logic [XLEN-1:0] rd;
|
||||
|
||||
modport unit (
|
||||
input ack,
|
||||
output id, done, rd
|
||||
);
|
||||
modport wb (
|
||||
output ack,
|
||||
input id, done, rd
|
||||
);
|
||||
endinterface
|
||||
|
||||
interface ras_interface;
|
||||
|
@ -95,7 +111,7 @@ interface exception_interface;
|
|||
exception_code_t code;
|
||||
logic [31:0] pc;
|
||||
logic [31:0] addr;
|
||||
instruction_id_t id;
|
||||
id_t id;
|
||||
|
||||
modport econtrol (output valid, code, pc, addr, id, input ack);
|
||||
modport unit (input valid, code, pc, addr, id, output ack);
|
||||
|
@ -107,13 +123,13 @@ interface register_file_issue_interface;
|
|||
logic[XLEN-1:0] rs1_data;
|
||||
logic[4:0] rs2_addr; //if not used required to be zero
|
||||
logic[XLEN-1:0] rs2_data;
|
||||
instruction_id_t id;
|
||||
id_t id;
|
||||
|
||||
logic uses_rs1;
|
||||
logic uses_rs2;
|
||||
logic rs1_conflict;
|
||||
logic rs2_conflict;
|
||||
instruction_id_t rs2_id;
|
||||
id_t rs2_id;
|
||||
logic instruction_issued;
|
||||
|
||||
modport issue (output rd_addr, rs1_addr, rs2_addr, instruction_issued, id, uses_rs1, uses_rs2, input rs1_conflict, rs2_conflict, rs1_data, rs2_data, rs2_id);
|
||||
|
@ -122,40 +138,24 @@ endinterface
|
|||
|
||||
|
||||
interface register_file_writeback_interface;
|
||||
logic[4:0] rd_addr;
|
||||
//Writeback data
|
||||
logic retiring;
|
||||
logic rd_nzero;
|
||||
|
||||
id_t id;
|
||||
logic[XLEN-1:0] rd_data;
|
||||
instruction_id_t id;
|
||||
|
||||
instruction_id_t rs1_id;
|
||||
instruction_id_t rs2_id;
|
||||
|
||||
//Forwarding signals
|
||||
id_t rs1_id;
|
||||
id_t rs2_id;
|
||||
logic[XLEN-1:0] rs1_data;
|
||||
logic[XLEN-1:0] rs2_data;
|
||||
logic rs1_valid;
|
||||
logic rs2_valid;
|
||||
|
||||
modport writeback (output rd_addr, retiring, rd_nzero, rd_data, id, rs1_data, rs2_data, rs1_valid, rs2_valid, input rs1_id, rs2_id);
|
||||
modport rf (input rd_addr, retiring, rd_nzero, rd_data, id, rs1_data, rs2_data, rs1_valid, rs2_valid, output rs1_id, rs2_id);
|
||||
modport writeback (output retiring, rd_data, id, rs1_data, rs2_data, rs1_valid, rs2_valid, input rs1_id, rs2_id);
|
||||
modport rf (input retiring, rd_data, id, rs1_data, rs2_data, rs1_valid, rs2_valid, output rs1_id, rs2_id);
|
||||
|
||||
endinterface
|
||||
|
||||
|
||||
interface tracking_interface;
|
||||
instruction_id_t issue_id;
|
||||
logic id_available;
|
||||
|
||||
inflight_instruction_packet inflight_packet;
|
||||
logic issued;
|
||||
logic [WB_UNITS_WIDTH-1:0] issue_unit_id;
|
||||
logic exception_possible;
|
||||
|
||||
modport decode (input issue_id, id_available, output inflight_packet, issued, issue_unit_id, exception_possible);
|
||||
modport wb (output issue_id, id_available, input inflight_packet, issued, issue_unit_id, exception_possible);
|
||||
endinterface
|
||||
|
||||
interface fifo_interface #(parameter DATA_WIDTH = 42);//#(parameter type data_type = logic[31:0]);
|
||||
logic push;
|
||||
logic pop;
|
||||
|
@ -218,30 +218,30 @@ interface load_store_queue_interface;
|
|||
logic [3:0] be;
|
||||
logic [2:0] fn3;
|
||||
logic [31:0] data_in;
|
||||
instruction_id_t id;
|
||||
id_t id;
|
||||
logic forwarded_store;
|
||||
instruction_id_t data_id;
|
||||
id_t data_id;
|
||||
|
||||
logic possible_issue;
|
||||
logic new_issue;
|
||||
logic ready;
|
||||
|
||||
instruction_id_t id_needed_by_store;
|
||||
id_t id_needed_by_store;
|
||||
data_access_shared_inputs_t transaction_out;
|
||||
logic transaction_ready;
|
||||
logic empty;
|
||||
logic accepted;
|
||||
|
||||
|
||||
modport queue (input addr, load, store, be, fn3, data_in, id, forwarded_store, data_id, possible_issue, new_issue, accepted, output ready, id_needed_by_store, transaction_out, transaction_ready);
|
||||
modport ls (output addr, load, store, be, fn3, data_in, id, forwarded_store, data_id, possible_issue, new_issue, accepted, input ready, id_needed_by_store, transaction_out, transaction_ready);
|
||||
modport queue (input addr, load, store, be, fn3, data_in, id, forwarded_store, data_id, possible_issue, new_issue, accepted, output ready, id_needed_by_store, transaction_out, transaction_ready, empty);
|
||||
modport ls (output addr, load, store, be, fn3, data_in, id, forwarded_store, data_id, possible_issue, new_issue, accepted, input ready, id_needed_by_store, transaction_out, transaction_ready, empty);
|
||||
endinterface
|
||||
|
||||
interface writeback_store_interface;
|
||||
instruction_id_t id_needed_at_issue;
|
||||
instruction_id_t id_needed_at_commit;
|
||||
instruction_id_t commit_id;
|
||||
id_t id_needed_at_issue;
|
||||
id_t id_needed_at_commit;
|
||||
id_t commit_id;
|
||||
logic commit;
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] hold_for_store_ids;
|
||||
logic [MAX_IDS-1:0] hold_for_store_ids;
|
||||
|
||||
logic forwarding_data_ready;
|
||||
logic [31:0] forwarded_data;
|
||||
|
@ -293,15 +293,3 @@ interface unsigned_division_interface #(parameter DATA_WIDTH = 32);
|
|||
modport divider (output remainder, quotient, done, divisor_is_zero, input dividend, divisor, start);
|
||||
endinterface
|
||||
|
||||
//Unit sets the ID of the instruction that will provide the data
|
||||
//data_valid is high when the data is valid
|
||||
interface post_issue_forwarding_interface;
|
||||
instruction_id_t id;
|
||||
|
||||
logic [31:0] data;
|
||||
logic data_valid;
|
||||
|
||||
modport unit (input data, data_valid, output id);
|
||||
modport wb (output data, data_valid, input id);
|
||||
endinterface
|
||||
|
||||
|
|
|
@ -33,16 +33,16 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
input logic gc_issue_flush,
|
||||
|
||||
load_store_queue_interface.queue lsq,
|
||||
output logic [MAX_INFLIGHT_COUNT-1:0] wb_hold_for_store_ids,
|
||||
output logic [MAX_IDS-1:0] wb_hold_for_store_ids,
|
||||
//Writeback data
|
||||
input logic [31:0] writeback_data,
|
||||
input logic writeback_valid
|
||||
);
|
||||
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] valid;
|
||||
logic [$clog2(MAX_INFLIGHT_COUNT)-1:0] hold_for_store_ids [MAX_INFLIGHT_COUNT];
|
||||
logic [$clog2(MAX_INFLIGHT_COUNT)-1:0] hold_for_store_ids_r [MAX_INFLIGHT_COUNT];
|
||||
instruction_id_t oldest_id;
|
||||
logic [MAX_IDS-1:0] valid;
|
||||
logic [$clog2(MAX_IDS)-1:0] hold_for_store_ids [MAX_IDS];
|
||||
logic [$clog2(MAX_IDS)-1:0] hold_for_store_ids_r [MAX_IDS];
|
||||
id_t oldest_id;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:0] addr;
|
||||
|
@ -51,24 +51,24 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
logic [3:0] be;
|
||||
logic [2:0] fn3;
|
||||
logic [31:0] data_in;
|
||||
instruction_id_t id;
|
||||
id_t id;
|
||||
logic forwarded_store;
|
||||
instruction_id_t data_id;
|
||||
id_t data_id;
|
||||
} lsq_entry_t;
|
||||
|
||||
lsq_entry_t new_lsq_entry;
|
||||
logic [$bits(lsq_entry_t)-1:0] lsq_entries [MAX_INFLIGHT_COUNT];
|
||||
logic [$bits(lsq_entry_t)-1:0] lsq_entries [MAX_IDS];
|
||||
lsq_entry_t oldest_lsq_entry;
|
||||
|
||||
fifo_interface #(.DATA_WIDTH($bits(instruction_id_t))) oldest_fifo ();
|
||||
fifo_interface #(.DATA_WIDTH($bits(id_t))) oldest_fifo ();
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
//Can accept an input so long as it is a load or as long as an update from writeback for an exisiting store is not in progress
|
||||
//Can always buffer new requests
|
||||
assign lsq.ready = 1;
|
||||
|
||||
//FIFO to store ordering of IDs
|
||||
taiga_fifo #(.DATA_WIDTH($bits(instruction_id_t)), .FIFO_DEPTH(MAX_INFLIGHT_COUNT)) oldest_id_fifo (
|
||||
taiga_fifo #(.DATA_WIDTH($bits(id_t)), .FIFO_DEPTH(MAX_IDS)) oldest_id_fifo (
|
||||
.clk, .rst(rst | gc_issue_flush),
|
||||
.fifo(oldest_fifo)
|
||||
);
|
||||
|
@ -79,6 +79,8 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
assign oldest_fifo.pop = lsq.accepted;
|
||||
assign oldest_id = oldest_fifo.data_out;
|
||||
|
||||
assign lsq.empty = ~oldest_fifo.valid;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Request attributes and input data (LUTRAMs)
|
||||
always_comb begin
|
||||
|
|
|
@ -55,20 +55,15 @@ module load_store_unit (
|
|||
//Writeback-Store Interface
|
||||
writeback_store_interface.ls wb_store,
|
||||
|
||||
input instruction_id_t oldest_id,
|
||||
output logic load_store_exception_clear,
|
||||
output instruction_id_t load_store_exception_id,
|
||||
input logic potential_exception,
|
||||
|
||||
//CSR support
|
||||
input logic[31:0] csr_rd,
|
||||
input instruction_id_t csr_id,
|
||||
input id_t csr_id,
|
||||
input logic csr_done,
|
||||
output logic ls_is_idle,
|
||||
|
||||
output exception_packet_t ls_exception,
|
||||
output logic ls_exception_valid,
|
||||
input logic ls_exception_ack,
|
||||
|
||||
output unit_writeback_t wb
|
||||
unit_writeback_interface.unit wb
|
||||
);
|
||||
|
||||
localparam NUM_SUB_UNITS = USE_D_SCRATCH_MEM+USE_BUS+USE_DCACHE;
|
||||
|
@ -108,11 +103,12 @@ module load_store_unit (
|
|||
logic [NUM_SUB_UNITS-1:0] sub_unit_address_match;
|
||||
|
||||
logic unit_stall;
|
||||
logic done_r;
|
||||
|
||||
typedef struct packed{
|
||||
logic [2:0] fn3;
|
||||
logic [1:0] byte_addr;
|
||||
instruction_id_t instruction_id;
|
||||
id_t id;
|
||||
logic [NUM_SUB_UNITS_W-1:0] subunit_id;
|
||||
} load_attributes_t;
|
||||
load_attributes_t load_attributes_in, stage2_attr;
|
||||
|
@ -133,12 +129,7 @@ module load_store_unit (
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Alignment Exception
|
||||
instruction_id_t exception_id;
|
||||
logic exception_is_store;
|
||||
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
assign load_store_exception_clear = issue.new_request;
|
||||
assign load_store_exception_id = issue.instruction_id;
|
||||
|
||||
always_comb begin
|
||||
case(ls_inputs.fn3)
|
||||
|
@ -151,16 +142,9 @@ generate if (ENABLE_M_MODE) begin
|
|||
|
||||
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.pc = ls_inputs.pc;
|
||||
assign ls_exception.tval = virtual_address;
|
||||
assign ls_exception.id = issue.instruction_id;
|
||||
assign ls_exception.id = issue.id;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (ls_exception.valid) begin
|
||||
exception_is_store <= ls_inputs.store;
|
||||
exception_id <= issue.instruction_id;
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -199,14 +183,14 @@ endgenerate
|
|||
assign lsq.data_in = ls_inputs.rs2;
|
||||
assign lsq.load = ls_inputs.load;
|
||||
assign lsq.store = ls_inputs.store;
|
||||
assign lsq.id = issue.instruction_id;
|
||||
assign lsq.id = issue.id;
|
||||
assign lsq.forwarded_store = ls_inputs.forwarded_store;
|
||||
assign lsq.data_id = ls_inputs.store_forward_id;
|
||||
|
||||
assign lsq.possible_issue = issue.possible_issue & ~unaligned_addr;
|
||||
assign lsq.new_issue = issue.new_request & ~unaligned_addr;
|
||||
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] wb_hold_for_store_ids;
|
||||
logic [MAX_IDS-1:0] wb_hold_for_store_ids;
|
||||
load_store_queue lsq_block (.*, .writeback_valid(wb_store.forwarding_data_ready), .writeback_data(wb_store.forwarded_data));
|
||||
assign shared_inputs = lsq.transaction_out;
|
||||
|
||||
|
@ -214,16 +198,9 @@ endgenerate
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
assign store_complete = (lsq.accepted & lsq.transaction_out.store) | (ls_exception_ack & exception_is_store);
|
||||
assign store_id = $clog2(MAX_IDS)'(wb_store.commit_id);
|
||||
assign store_complete = lsq.accepted & lsq.transaction_out.store;
|
||||
assign store_id = lsq.transaction_out.id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Writeback-Store interface
|
||||
assign wb_store.id_needed_at_issue = ls_inputs.store_forward_id;
|
||||
assign wb_store.id_needed_at_commit = lsq.id_needed_by_store;
|
||||
assign wb_store.commit_id = ls_exception_ack ? exception_id : lsq.transaction_out.id;
|
||||
assign wb_store.commit = (lsq.accepted & lsq.transaction_out.store) | (ls_exception_ack & exception_is_store);
|
||||
assign wb_store.hold_for_store_ids = wb_hold_for_store_ids;
|
||||
////////////////////////////////////////////////////
|
||||
//Unit tracking
|
||||
assign current_unit = sub_unit_address_match;
|
||||
|
@ -245,10 +222,12 @@ endgenerate
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Primary Control Signals
|
||||
assign ls_is_idle = lsq.empty & (~load_attributes.valid);
|
||||
|
||||
assign units_ready = &unit_ready;
|
||||
assign load_complete = |unit_data_valid;
|
||||
|
||||
assign ready_for_issue = units_ready & (~unit_switch_stall);
|
||||
assign ready_for_issue = units_ready & (~unit_switch_stall) & (~done_r | wb.ack);
|
||||
|
||||
assign issue.ready = lsq.ready;
|
||||
assign issue_request = lsq.accepted;
|
||||
|
@ -259,11 +238,11 @@ endgenerate
|
|||
taiga_fifo #(.DATA_WIDTH($bits(load_attributes_t)), .FIFO_DEPTH(ATTRIBUTES_DEPTH)) attributes_fifo (.fifo(load_attributes), .*);
|
||||
assign load_attributes_in.fn3 = shared_inputs.fn3;
|
||||
assign load_attributes_in.byte_addr = shared_inputs.addr[1:0];
|
||||
assign load_attributes_in.instruction_id = shared_inputs.id;
|
||||
assign load_attributes_in.id = shared_inputs.id;
|
||||
|
||||
assign load_attributes.data_in = load_attributes_in;
|
||||
assign load_attributes.push = issue_request & shared_inputs.load;
|
||||
assign load_attributes.pop = load_complete;
|
||||
assign load_attributes.pop = ((done_r | load_complete) & wb.ack);
|
||||
assign load_attributes.supress_push = 0;
|
||||
|
||||
assign stage2_attr = load_attributes.data_out;
|
||||
|
@ -338,9 +317,17 @@ endgenerate
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Output bank
|
||||
always_ff @ (posedge clk) begin
|
||||
if (wb.ack)
|
||||
done_r <= 0;
|
||||
else if (load_complete)
|
||||
done_r <= 1;
|
||||
end
|
||||
|
||||
|
||||
assign wb.rd = csr_done ? csr_rd : final_load_data;
|
||||
assign wb.done = csr_done | load_complete | (ls_exception_ack & ~exception_is_store);
|
||||
assign wb.id = csr_done ? csr_id : (ls_exception_ack ? exception_id : stage2_attr.instruction_id);
|
||||
assign wb.done = csr_done | load_complete | done_r;
|
||||
assign wb.id = csr_done ? csr_id : stage2_attr.id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
|
|
|
@ -30,17 +30,20 @@ module mul_unit(
|
|||
|
||||
input mul_inputs_t mul_inputs,
|
||||
unit_issue_interface.unit issue,
|
||||
output unit_writeback_t wb
|
||||
unit_writeback_interface.unit wb
|
||||
);
|
||||
|
||||
logic signed [63:0] result;
|
||||
logic mulh [2];
|
||||
logic done [2];
|
||||
instruction_id_t id [2];
|
||||
id_t id [2];
|
||||
|
||||
logic rs1_signed, rs2_signed;
|
||||
logic signed [32:0] rs1_ext, rs2_ext;
|
||||
logic signed [32:0] rs1_r, rs2_r;
|
||||
|
||||
logic stage1_advance;
|
||||
logic stage2_advance;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
assign rs1_signed = mul_inputs.op[1:0] inside {MULH_fn3[1:0], MULHSU_fn3[1:0]};//MUL doesn't matter
|
||||
|
@ -49,26 +52,36 @@ 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 stage1_advance = ~done[0] | stage2_advance;
|
||||
assign stage2_advance = ~done[1] | wb.ack;
|
||||
|
||||
//Input and output registered Multiply
|
||||
always_ff @ (posedge clk) begin
|
||||
rs1_r <= rs1_ext;
|
||||
rs2_r <= rs2_ext;
|
||||
result <= 64'(rs1_r * rs2_r);
|
||||
if (stage1_advance) begin
|
||||
rs1_r <= rs1_ext;
|
||||
rs2_r <= rs2_ext;
|
||||
end
|
||||
if (stage2_advance) begin
|
||||
result <= 64'(rs1_r * rs2_r);
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
mulh[0] <= (mul_inputs.op[1:0] != MUL_fn3[1:0]);
|
||||
id[0] <= issue.instruction_id;
|
||||
done[0] <= issue.new_request;
|
||||
|
||||
mulh[1] <= mulh[0];
|
||||
id[1] <= id[0];
|
||||
done[1] <= done[0];
|
||||
if (stage1_advance) begin
|
||||
mulh[0] <= (mul_inputs.op[1:0] != MUL_fn3[1:0]);
|
||||
id[0] <= issue.id;
|
||||
done[0] <= issue.new_request;
|
||||
end
|
||||
if (stage2_advance) begin
|
||||
mulh[1] <= mulh[0];
|
||||
id[1] <= id[0];
|
||||
done[1] <= done[0];
|
||||
end
|
||||
end
|
||||
|
||||
//Issue/write-back handshaking
|
||||
////////////////////////////////////////////////////
|
||||
assign issue.ready = 1;
|
||||
assign wb.rd = mulh[1] ? result[63:32] : result[31:0];
|
||||
assign wb.done = done[1];
|
||||
assign wb.id = id[1];
|
||||
|
|
|
@ -58,8 +58,8 @@ module one_hot_to_integer
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
always_ff @ (posedge clk) begin
|
||||
assert (rst || (~rst && $onehot0(one_hot))) else $error("One-hot signal has multiple bits set!");
|
||||
end
|
||||
// always_ff @ (posedge clk) begin
|
||||
// assert (rst || (~rst && $onehot0(one_hot))) else $error("One-hot signal has multiple bits set!");
|
||||
//end
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Initial code developed under the supervision of Dr. Lesley Shannon,
|
||||
* Reconfigurable Computing Lab, Simon Fraser University.
|
||||
*
|
||||
* Author(s):
|
||||
* Eric Matthews <ematthew@sfu.ca>
|
||||
*/
|
||||
|
||||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
|
||||
module pre_decode
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
//Fetch
|
||||
input logic [31:0] pre_decode_instruction,
|
||||
input logic [31:0] pre_decode_pc,
|
||||
input branch_predictor_metadata_t branch_metadata,
|
||||
input logic branch_prediction_used,
|
||||
input logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way,
|
||||
input logic pre_decode_push,
|
||||
|
||||
//Global Control
|
||||
input logic gc_fetch_flush,
|
||||
|
||||
//Decode
|
||||
input logic pre_decode_pop,
|
||||
output logic fb_valid,
|
||||
output fetch_buffer_packet_t fb
|
||||
);
|
||||
|
||||
logic buffer_reset;
|
||||
|
||||
fetch_buffer_packet_t new_data;
|
||||
fetch_buffer_packet_t data_in;
|
||||
fetch_buffer_packet_t data_out;
|
||||
fifo_interface #(.DATA_WIDTH($bits(fetch_buffer_packet_t))) fb_fifo();
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
//FIFO
|
||||
assign buffer_reset = rst | gc_fetch_flush;
|
||||
assign fb_fifo.supress_push = 0;//Covered by reseting on gc_fetch_flush
|
||||
|
||||
assign fb_fifo.push = pre_decode_push;
|
||||
assign fb_fifo.pop = pre_decode_pop;
|
||||
assign fb_fifo.data_in = data_in;
|
||||
assign fb = fb_fifo.data_out;
|
||||
assign fb_valid = fb_fifo.valid;
|
||||
|
||||
taiga_fifo #(
|
||||
.DATA_WIDTH($bits(fetch_buffer_packet_t)),
|
||||
.FIFO_DEPTH(FETCH_BUFFER_DEPTH)
|
||||
) fb_fifo_block (.fifo(fb_fifo), .rst(buffer_reset), .*);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Pre-Decode
|
||||
assign data_in.instruction = pre_decode_instruction;
|
||||
assign data_in.pc = pre_decode_pc;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Branch Predictor support
|
||||
assign data_in.branch_metadata = branch_metadata;
|
||||
assign data_in.branch_prediction_used = branch_prediction_used;
|
||||
assign data_in.bp_update_way = bp_update_way;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
|
||||
endmodule
|
|
@ -33,6 +33,9 @@ module register_file(
|
|||
register_file_writeback_interface.rf wb,
|
||||
register_file_issue_interface.rf issue,
|
||||
|
||||
//ID Metadata
|
||||
input logic [4:0] retired_rd_addr,
|
||||
|
||||
//Trace signals
|
||||
output logic tr_rs1_forwarding_needed,
|
||||
output logic tr_rs2_forwarding_needed,
|
||||
|
@ -40,7 +43,7 @@ module register_file(
|
|||
);
|
||||
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic [XLEN-1:0] register [32];
|
||||
(* ramstyle = "MLAB, no_rw_check" *) instruction_id_t in_use_by [32];
|
||||
(* ramstyle = "MLAB, no_rw_check" *) id_t in_use_by [32];
|
||||
|
||||
logic rs1_inuse;
|
||||
logic rs2_inuse;
|
||||
|
@ -57,16 +60,16 @@ module register_file(
|
|||
|
||||
//Writeback unit does not assert wb.commit when the target register is r0
|
||||
always_ff @ (posedge clk) begin
|
||||
if (~gc_supress_writeback & valid_write)
|
||||
register[wb.rd_addr] <= wb.rd_data;
|
||||
if (~gc_supress_writeback & in_use_match)
|
||||
register[retired_rd_addr] <= wb.rd_data;
|
||||
end
|
||||
|
||||
assign in_use_match = (wb.id == in_use_by[wb.rd_addr]) && valid_write;
|
||||
assign in_use_match = (wb.id == in_use_by[retired_rd_addr]) && valid_write;
|
||||
|
||||
reg_inuse inuse (.*,
|
||||
.clr(1'b0),
|
||||
.rs1_addr(issue.rs1_addr),.rs2_addr(issue.rs2_addr), .issued_rd_addr(issue.rd_addr),
|
||||
.retired_rd_addr(wb.rd_addr),
|
||||
.retired_rd_addr(retired_rd_addr),
|
||||
.issued(issue.instruction_issued),
|
||||
.retired(in_use_match),
|
||||
.rs1_inuse(rs1_inuse),
|
||||
|
@ -82,7 +85,7 @@ module register_file(
|
|||
assign wb.rs2_id = in_use_by[issue.rs2_addr];
|
||||
assign issue.rs2_id = wb.rs2_id;
|
||||
|
||||
assign valid_write = wb.rd_nzero & wb.retiring;
|
||||
assign valid_write = (|retired_rd_addr) & wb.retiring;
|
||||
|
||||
assign rs1_feedforward = rs1_inuse;
|
||||
assign rs2_feedforward = rs2_inuse;
|
||||
|
|
|
@ -66,13 +66,11 @@ module taiga (
|
|||
div_inputs_t div_inputs;
|
||||
gc_inputs_t gc_inputs;
|
||||
|
||||
unit_issue_interface unit_issue [NUM_UNITS-1:0]();
|
||||
unit_issue_interface unit_issue [NUM_UNITS]();
|
||||
|
||||
exception_packet_t ls_exception;
|
||||
logic ls_exception_valid;
|
||||
|
||||
tracking_interface ti();
|
||||
unit_writeback_t unit_wb [NUM_WB_UNITS-1:0];
|
||||
unit_writeback_interface unit_wb [NUM_WB_UNITS]();
|
||||
register_file_writeback_interface rf_wb();
|
||||
|
||||
mmu_interface immu();
|
||||
|
@ -111,10 +109,14 @@ module taiga (
|
|||
id_t store_id;
|
||||
logic branch_complete;
|
||||
id_t branch_id;
|
||||
logic system_op_complete;
|
||||
id_t system_op_id;
|
||||
logic system_op_or_exception_complete;
|
||||
id_t system_op_or_exception_id;
|
||||
logic instruction_retired;
|
||||
id_t retired_id;
|
||||
logic [4:0] retired_rd_addr;
|
||||
//Exception
|
||||
id_t exception_id;
|
||||
logic [31:0] exception_pc;
|
||||
|
||||
//Global Control
|
||||
logic gc_issue_hold;
|
||||
|
@ -122,13 +124,14 @@ module taiga (
|
|||
logic gc_fetch_flush;
|
||||
logic gc_fetch_pc_override;
|
||||
logic gc_supress_writeback;
|
||||
instruction_id_t oldest_id;
|
||||
id_t oldest_id;
|
||||
logic [31:0] gc_fetch_pc;
|
||||
logic ls_exception_ack;
|
||||
|
||||
logic[31:0] csr_rd;
|
||||
instruction_id_t csr_id;
|
||||
id_t csr_id;
|
||||
logic csr_done;
|
||||
logic ls_is_idle;
|
||||
|
||||
//Decode Unit and Fetch Unit
|
||||
logic illegal_instruction;
|
||||
|
@ -143,9 +146,9 @@ module taiga (
|
|||
//LS
|
||||
writeback_store_interface wb_store();
|
||||
|
||||
logic load_store_exception_clear;
|
||||
instruction_id_t load_store_exception_id;
|
||||
logic potential_exception;
|
||||
//WB
|
||||
logic single_cycle_issue_possible;
|
||||
logic writeback_is_idle;
|
||||
|
||||
//Trace Interface Signals
|
||||
logic tr_operand_stall;
|
||||
|
@ -180,8 +183,8 @@ module taiga (
|
|||
logic tr_rs1_and_rs2_forwarding_needed;
|
||||
|
||||
unit_id_t tr_num_instructions_completing;
|
||||
instruction_id_t tr_num_instructions_in_flight;
|
||||
instruction_id_t tr_num_of_instructions_pending_writeback;
|
||||
id_t tr_num_instructions_in_flight;
|
||||
id_t tr_num_of_instructions_pending_writeback;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
|
|
|
@ -163,11 +163,13 @@ package taiga_config;
|
|||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//FIFO/Buffer Depths
|
||||
//All parameters restricted to powers of two
|
||||
parameter MAX_IDS = 16;
|
||||
parameter MAX_INFLIGHT_COUNT = 4;
|
||||
parameter FETCH_BUFFER_DEPTH = 4;
|
||||
//ID limit
|
||||
//MAX_IDS restricted to a power of 2
|
||||
parameter MAX_IDS = 32;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Number of Writeback Buffers
|
||||
parameter WRITEBACK_BUFFERS = 3;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Trace Options
|
||||
|
@ -185,15 +187,19 @@ package taiga_config;
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Write-Back Unit IDs
|
||||
parameter NUM_WB_UNITS = 2 + USE_MUL + USE_DIV;
|
||||
parameter NUM_UNITS = NUM_WB_UNITS + 2;
|
||||
parameter NUM_MULTI_CYCLE_WB_UNITS = 1 + USE_MUL + USE_DIV;//LS
|
||||
parameter NUM_SINGLE_CYCLE_WB_UNITS = 1;//ALU
|
||||
|
||||
parameter ALU_UNIT_WB_ID = 0;
|
||||
parameter LS_UNIT_WB_ID = 1;
|
||||
parameter NUM_WB_UNITS = NUM_MULTI_CYCLE_WB_UNITS + NUM_SINGLE_CYCLE_WB_UNITS;
|
||||
|
||||
parameter NUM_UNITS = NUM_WB_UNITS + 2;//Branch and CSRs
|
||||
|
||||
parameter LS_UNIT_WB_ID = 0;
|
||||
parameter DIV_UNIT_WB_ID = LS_UNIT_WB_ID + USE_DIV;
|
||||
parameter MUL_UNIT_WB_ID = DIV_UNIT_WB_ID + USE_MUL;
|
||||
parameter MUL_UNIT_WB_ID = DIV_UNIT_WB_ID + 1;
|
||||
parameter ALU_UNIT_WB_ID = MUL_UNIT_WB_ID + USE_MUL;
|
||||
//Non-writeback units
|
||||
parameter BRANCH_UNIT_ID = MUL_UNIT_WB_ID + 1;
|
||||
parameter BRANCH_UNIT_ID = ALU_UNIT_WB_ID + 1;
|
||||
parameter GC_UNIT_ID = BRANCH_UNIT_ID + 1;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -24,12 +24,10 @@ package taiga_types;
|
|||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
|
||||
localparam ID_W = $clog2(MAX_INFLIGHT_COUNT);
|
||||
localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
|
||||
|
||||
typedef logic[$clog2(MAX_IDS)-1:0] id_t;
|
||||
|
||||
typedef logic[ID_W-1:0] instruction_id_t;
|
||||
typedef logic[WB_UNITS_WIDTH-1:0] unit_id_t;
|
||||
typedef logic[1:0] branch_predictor_metadata_t;
|
||||
|
||||
|
@ -63,24 +61,10 @@ package taiga_types;
|
|||
typedef struct packed{
|
||||
logic valid;
|
||||
exception_code_t code;
|
||||
logic [31:0] pc;
|
||||
logic [31:0] tval;
|
||||
instruction_id_t id;
|
||||
id_t id;
|
||||
} exception_packet_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic [4:0] rd_addr;
|
||||
logic is_store;
|
||||
} inflight_instruction_packet;
|
||||
|
||||
typedef struct packed{
|
||||
logic [31:0] instruction;
|
||||
logic [31:0] pc;
|
||||
branch_predictor_metadata_t branch_metadata;
|
||||
logic branch_prediction_used;
|
||||
logic [BRANCH_PREDICTOR_WAYS-1:0] bp_update_way;
|
||||
} fetch_buffer_packet_t;
|
||||
|
||||
typedef struct packed{
|
||||
branch_predictor_metadata_t branch_predictor_metadata;
|
||||
logic branch_prediction_used;
|
||||
|
@ -88,21 +72,6 @@ package taiga_types;
|
|||
} branch_metadata_t;
|
||||
|
||||
|
||||
typedef struct packed{
|
||||
logic id_assigned;
|
||||
id_t pc_id;
|
||||
logic [31:0] pc;
|
||||
logic complete;
|
||||
id_t instruction_id;
|
||||
logic [31:0] instruction;
|
||||
} fetch_instruction_metadata_t;
|
||||
|
||||
typedef struct packed{
|
||||
instruction_id_t id;
|
||||
logic done;
|
||||
logic [XLEN-1:0] rd;
|
||||
} unit_writeback_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic [XLEN:0] in1;//contains sign padding bit for slt operation
|
||||
logic [XLEN:0] in2;//contains sign padding bit for slt operation
|
||||
|
@ -159,9 +128,7 @@ package taiga_types;
|
|||
logic load;
|
||||
logic store;
|
||||
logic forwarded_store;
|
||||
instruction_id_t store_forward_id;
|
||||
//exception support
|
||||
logic [31:0] pc;
|
||||
id_t store_forward_id;
|
||||
//amo support
|
||||
amo_details_t amo;
|
||||
} load_store_inputs_t;
|
||||
|
@ -216,7 +183,7 @@ package taiga_types;
|
|||
logic [3:0] be;
|
||||
logic [2:0] fn3;
|
||||
logic [31:0] data_in;
|
||||
instruction_id_t id;
|
||||
id_t id;
|
||||
} data_access_shared_inputs_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -260,8 +227,8 @@ package taiga_types;
|
|||
|
||||
//Writeback
|
||||
unit_id_t num_instructions_completing;
|
||||
instruction_id_t num_instructions_in_flight;
|
||||
instruction_id_t num_of_instructions_pending_writeback;
|
||||
id_t num_instructions_in_flight;
|
||||
id_t num_of_instructions_pending_writeback;
|
||||
} taiga_trace_events_t;
|
||||
|
||||
typedef struct packed {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
|
||||
* Copyright © 2017-2020 Eric Matthews, Lesley Shannon
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -31,199 +31,188 @@ module write_back(
|
|||
input logic gc_fetch_flush,
|
||||
input logic instruction_issued_with_rd,
|
||||
|
||||
input unit_writeback_t unit_wb[NUM_WB_UNITS-1:0],
|
||||
unit_writeback_interface.wb unit_wb[NUM_WB_UNITS],
|
||||
register_file_writeback_interface.writeback rf_wb,
|
||||
tracking_interface.wb ti,
|
||||
|
||||
output logic instruction_retired,
|
||||
output id_t retired_id,
|
||||
output logic instruction_queue_empty,
|
||||
|
||||
output instruction_id_t oldest_id,
|
||||
|
||||
input logic load_store_exception_clear,
|
||||
input instruction_id_t load_store_exception_id,
|
||||
output logic potential_exception,
|
||||
|
||||
//Writeback-Store Interface
|
||||
writeback_store_interface.wb wb_store,
|
||||
output logic single_cycle_issue_possible,
|
||||
output logic writeback_is_idle,
|
||||
|
||||
//Trace signals
|
||||
output unit_id_t tr_num_instructions_completing,
|
||||
output instruction_id_t tr_num_instructions_in_flight,
|
||||
output instruction_id_t tr_num_of_instructions_pending_writeback
|
||||
output id_t tr_num_instructions_in_flight,
|
||||
output id_t tr_num_of_instructions_pending_writeback
|
||||
);
|
||||
//////////////////////////////////////
|
||||
|
||||
//Inflight metadata for IDs
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic[$bits(inflight_instruction_packet)-1:0] id_metadata [MAX_INFLIGHT_COUNT-1:0];
|
||||
|
||||
logic unit_ack [NUM_WB_UNITS];
|
||||
//aliases for write-back-interface signals
|
||||
instruction_id_t unit_instruction_id [NUM_WB_UNITS-1:0];
|
||||
logic [NUM_WB_UNITS-1:0] unit_done;
|
||||
logic [XLEN-1:0] unit_rd [NUM_WB_UNITS-1:0];
|
||||
id_t unit_instruction_id [NUM_WB_UNITS];
|
||||
logic unit_done [NUM_WB_UNITS];
|
||||
logic [XLEN-1:0] unit_rd [NUM_WB_UNITS];
|
||||
//Per-ID muxes for commit buffer
|
||||
logic [$clog2(NUM_WB_UNITS)-1:0] id_unit_select [MAX_INFLIGHT_COUNT-1:0];
|
||||
logic [$clog2(NUM_WB_UNITS)-1:0] id_unit_select_r [MAX_INFLIGHT_COUNT-1:0];
|
||||
logic [$clog2(NUM_WB_UNITS)-1:0] buffer_unit_select [WRITEBACK_BUFFERS];
|
||||
//Commit buffer
|
||||
logic [XLEN-1:0] results_by_id [MAX_INFLIGHT_COUNT-1:0];
|
||||
logic [XLEN-1:0] results_by_id_new [MAX_INFLIGHT_COUNT-1:0];
|
||||
instruction_id_t id_retiring;
|
||||
inflight_instruction_packet retiring_instruction_packet;
|
||||
typedef struct packed{
|
||||
logic [XLEN-1:0] rd;
|
||||
id_t id;
|
||||
} commit_buffer_t;
|
||||
commit_buffer_t commit_buffer [WRITEBACK_BUFFERS];
|
||||
logic commit_buffer_valid [WRITEBACK_BUFFERS];
|
||||
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] id_inuse;
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] id_potential_exception;
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] exception_cleared_one_hot;
|
||||
id_t id_retiring;
|
||||
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] id_writeback_pending;
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] id_writeback_pending_r;
|
||||
localparam LOG2_WRITEBACK_BUFFERS = $clog2(WRITEBACK_BUFFERS);
|
||||
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] id_writing_to_buffer;
|
||||
logic retiring;
|
||||
logic [$clog2(NUM_WB_UNITS):0] num_units_done;
|
||||
logic [$clog2(WRITEBACK_BUFFERS):0] num_buffers_ready;
|
||||
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] id_retiring_one_hot;
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] id_issued_one_hot;
|
||||
logic result_ready [WRITEBACK_BUFFERS];
|
||||
|
||||
logic retiring_next_cycle, retiring;
|
||||
logic commit_buffer_ready [WRITEBACK_BUFFERS];
|
||||
|
||||
logic [LOG2_WRITEBACK_BUFFERS-1:0] commit_buffer_index_retiring;
|
||||
|
||||
genvar i, j;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
//Re-assigning interface inputs to array types so that they can be dynamically indexed
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i< NUM_WB_UNITS; i++) begin : interface_to_array_g
|
||||
assign unit_instruction_id[i] = unit_wb[i].id;
|
||||
assign unit_done[i] = unit_wb[i].done;
|
||||
assign unit_rd[i] = unit_wb[i].rd;
|
||||
end
|
||||
endgenerate
|
||||
generate for (i=0; i< NUM_WB_UNITS; i++) begin : wb_interfaces_to_arrays_g
|
||||
assign unit_instruction_id[i] = unit_wb[i].id;
|
||||
assign unit_done[i] = unit_wb[i].done;
|
||||
assign unit_rd[i] = unit_wb[i].rd;
|
||||
assign unit_wb[i].ack = unit_ack[i];
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID done determination
|
||||
//For each ID, check if a unit is reporting that ID as done and OR the results together
|
||||
//Additionally, OR the result of any store operation completing
|
||||
//Unit done determination
|
||||
always_comb begin
|
||||
id_writing_to_buffer = '0;
|
||||
for (int i=0; i< MAX_INFLIGHT_COUNT; i++) begin
|
||||
for (int j=0; j< NUM_WB_UNITS; j++) begin
|
||||
id_writing_to_buffer[i] |= (unit_instruction_id[j] == ID_W'(i)) && unit_done[j];
|
||||
end
|
||||
id_writing_to_buffer[i] |= (wb_store.commit_id == ID_W'(i)) && wb_store.commit;
|
||||
num_units_done = 0;
|
||||
for (int i=0; i < NUM_MULTI_CYCLE_WB_UNITS; i++) begin
|
||||
num_units_done += ($clog2(NUM_WB_UNITS)+1)'(unit_done[i]);
|
||||
end
|
||||
num_buffers_ready = 0;
|
||||
for (int i=0; i < WRITEBACK_BUFFERS; i++) begin
|
||||
num_buffers_ready += ($clog2(WRITEBACK_BUFFERS)+1)'(commit_buffer_ready[i]);
|
||||
end
|
||||
single_cycle_issue_possible = (($clog2(NUM_WB_UNITS)+1)'(num_buffers_ready) > num_units_done);
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Commit Buffer index retiring
|
||||
//Priority given to decreasing indices
|
||||
always_comb begin
|
||||
commit_buffer_index_retiring = 0;
|
||||
for (int i=WRITEBACK_BUFFERS-1; i >= 0; i--) begin
|
||||
if (commit_buffer_valid[i])
|
||||
commit_buffer_index_retiring = LOG2_WRITEBACK_BUFFERS'(i);
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Commit Buffer ready to accept new data
|
||||
always_comb begin
|
||||
for (int i=0; i < WRITEBACK_BUFFERS; i++) begin
|
||||
commit_buffer_ready[i] = ~commit_buffer_valid[i];
|
||||
end
|
||||
//Can always retire, so if not retiring, this index will not be valid and thus ready to commit to
|
||||
commit_buffer_ready[commit_buffer_index_retiring] = 1;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit select for writeback buffer
|
||||
//Set unit_ID for each ID as they are issued
|
||||
//If ID is not in use, use the current issue_unit_id value
|
||||
//This is used to support single cycle units, such as the ALU
|
||||
logic commit_buffer_write [WRITEBACK_BUFFERS];
|
||||
always_comb begin
|
||||
id_issued_one_hot = 0;
|
||||
id_issued_one_hot[ti.issue_id] = 1;
|
||||
id_issued_one_hot &= {MAX_INFLIGHT_COUNT{ti.issued}};
|
||||
unit_ack = '{default: 0};
|
||||
buffer_unit_select = '{default: 0};
|
||||
commit_buffer_write = '{default: 0};
|
||||
for (int i=0; i < WRITEBACK_BUFFERS; i++) begin
|
||||
for (int j=0; j < NUM_WB_UNITS; j++) begin
|
||||
if (unit_done[j] & ~unit_ack[j] & ~commit_buffer_write[i]) begin
|
||||
buffer_unit_select[i] = $clog2(NUM_WB_UNITS)'(j);
|
||||
unit_ack[j] = commit_buffer_ready[i];
|
||||
commit_buffer_write[i] = commit_buffer_ready[i];
|
||||
end
|
||||
end
|
||||
end
|
||||
// single_cycle_issue_possible = 0;
|
||||
// for (int i=0; i < WRITEBACK_BUFFERS; i++) begin
|
||||
// if (commit_buffer_ready[i] & ~commit_buffer_write[i]) begin
|
||||
// single_cycle_issue_possible = 1;
|
||||
// buffer_unit_select[i] = ALU_UNIT_WB_ID;
|
||||
// commit_buffer_write[i] = 1;
|
||||
// break;
|
||||
// end
|
||||
// end
|
||||
end
|
||||
|
||||
generate for (i=0; i< MAX_INFLIGHT_COUNT; i++) begin
|
||||
always_ff @ (posedge clk) begin
|
||||
if (id_issued_one_hot[i])
|
||||
id_unit_select_r[i] <= ti.issue_unit_id;
|
||||
end
|
||||
assign id_unit_select[i] = id_inuse[i] ? id_unit_select_r[i] : ti.issue_unit_id;
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Writeback Buffer
|
||||
//Mux outputs of units based on IDs
|
||||
//If ID is done write result to buffer
|
||||
generate for (i=0; i< MAX_INFLIGHT_COUNT; i++) begin
|
||||
always_ff @ (posedge clk) begin
|
||||
if (id_writing_to_buffer[i])
|
||||
results_by_id[i] <= unit_rd[id_unit_select[i]];
|
||||
end
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit Forwarding Support
|
||||
//Track whether an ID has written to the commit buffer
|
||||
set_clr_reg_with_rst #(.SET_OVER_CLR(0), .WIDTH($bits(id_inuse)), .RST_VALUE('0)) id_inuse_m (
|
||||
.clk, .rst,
|
||||
.set(id_issued_one_hot),
|
||||
.clr(id_writing_to_buffer),
|
||||
.result(id_inuse)
|
||||
);
|
||||
|
||||
assign wb_store.forwarding_data_ready = ~id_inuse[wb_store.id_needed_at_commit];
|
||||
assign wb_store.forwarded_data = results_by_id[wb_store.id_needed_at_commit];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Tracking
|
||||
//Provides ordering of IDs, ID for issue and oldest ID for committing to register file
|
||||
writeback_id_tracking id_counters (.*, .issued(ti.issued), .retired(retiring_next_cycle), .id_available(ti.id_available),
|
||||
.oldest_id(oldest_id), .next_id(ti.issue_id), .empty(instruction_queue_empty));
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Metadata storage for IDs
|
||||
//stores destination register for each ID and whether it is a store instruction
|
||||
initial id_metadata = '{default: 0};
|
||||
//Inflight Instruction ID table
|
||||
//Stores rd_addr and whether instruction is a store
|
||||
//Writeback Commit Buffer
|
||||
always_ff @ (posedge clk) begin
|
||||
if (ti.id_available)
|
||||
id_metadata[ti.issue_id] <= ti.inflight_packet;
|
||||
for (int i=0; i < WRITEBACK_BUFFERS; i++) begin
|
||||
if (rst)
|
||||
commit_buffer_valid[i] <= 0;
|
||||
else
|
||||
commit_buffer_valid[i] <= commit_buffer_write[i] | (commit_buffer_valid[i] & ~commit_buffer_ready[i]);
|
||||
end
|
||||
end
|
||||
assign retiring_instruction_packet = id_metadata[id_retiring];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Potential Exception Tracking
|
||||
// always_comb begin
|
||||
// exception_cleared_one_hot = 0;
|
||||
// exception_cleared_one_hot[load_store_exception_id] = load_store_exception_clear;
|
||||
// end
|
||||
// always_ff @ (posedge clk) begin
|
||||
// if (rst)
|
||||
// id_potential_exception <= 0;
|
||||
// else
|
||||
// id_potential_exception <= (id_potential_exception | {MAX_INFLIGHT_COUNT{ti.exception_possible}} & id_issued_one_hot) & ~exception_cleared_one_hot;
|
||||
// end
|
||||
// assign potential_exception = |id_potential_exception;
|
||||
always_ff @ (posedge clk) begin
|
||||
for (int i=0; i < WRITEBACK_BUFFERS; i++) begin
|
||||
if (commit_buffer_ready[i]) begin
|
||||
commit_buffer[i].rd <= unit_rd[buffer_unit_select[i]];
|
||||
commit_buffer[i].id <= unit_instruction_id[buffer_unit_select[i]];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File Interface
|
||||
//Track whether the ID has a pending write to the register file
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
id_writeback_pending_r <= 0;
|
||||
else
|
||||
id_writeback_pending_r <= id_writeback_pending;
|
||||
end
|
||||
|
||||
assign id_writeback_pending = id_writing_to_buffer | (id_writeback_pending_r & ~id_retiring_one_hot);
|
||||
|
||||
//Is the oldest instruction ready to commit?
|
||||
assign retiring_next_cycle = id_writeback_pending[oldest_id] & ~wb_store.hold_for_store_ids[oldest_id];
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
retiring <= retiring_next_cycle;
|
||||
id_retiring <= oldest_id;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
id_retiring_one_hot = 0;
|
||||
id_retiring_one_hot[id_retiring] = retiring;
|
||||
retiring = 0;
|
||||
for (int i=0; i < WRITEBACK_BUFFERS; i++) begin
|
||||
retiring |= commit_buffer_valid[i];
|
||||
end
|
||||
end
|
||||
|
||||
assign id_retiring = commit_buffer[commit_buffer_index_retiring].id;
|
||||
|
||||
//Instruction completion tracking for retired instruction count
|
||||
assign instruction_retired = retiring & ~retiring_instruction_packet.is_store;
|
||||
assign retired_id = $clog2(MAX_IDS)'(id_retiring);
|
||||
assign instruction_retired = retiring;
|
||||
assign retired_id = id_retiring;
|
||||
|
||||
|
||||
assign rf_wb.rd_addr = retiring_instruction_packet.rd_addr;
|
||||
assign rf_wb.id = id_retiring;
|
||||
assign rf_wb.retiring = instruction_retired;
|
||||
assign rf_wb.rd_nzero = |retiring_instruction_packet.rd_addr;
|
||||
assign rf_wb.rd_data = results_by_id[id_retiring];
|
||||
assign rf_wb.rd_data = commit_buffer[commit_buffer_index_retiring].rd;
|
||||
|
||||
//Register bypass for issue operands
|
||||
assign rf_wb.rs1_valid = id_writeback_pending_r[rf_wb.rs1_id];//includes the instruction writing to the register file
|
||||
assign rf_wb.rs2_valid = id_writeback_pending_r[rf_wb.rs2_id];
|
||||
assign rf_wb.rs1_data = results_by_id[rf_wb.rs1_id];
|
||||
assign rf_wb.rs2_data = results_by_id[rf_wb.rs2_id];
|
||||
logic [WRITEBACK_BUFFERS-1:0] rs1_addr_match;
|
||||
logic [WRITEBACK_BUFFERS-1:0] rs2_addr_match;
|
||||
logic [LOG2_WRITEBACK_BUFFERS-1:0] rs1_sel;
|
||||
logic [LOG2_WRITEBACK_BUFFERS-1:0] rs2_sel;
|
||||
always_comb begin
|
||||
writeback_is_idle = 0;
|
||||
rs1_sel = {LOG2_WRITEBACK_BUFFERS{1'b?}};
|
||||
rs2_sel = {LOG2_WRITEBACK_BUFFERS{1'b?}};
|
||||
for (int i=0; i < WRITEBACK_BUFFERS; i++) begin
|
||||
writeback_is_idle |= commit_buffer_valid[i];
|
||||
rs1_addr_match[i] = commit_buffer_valid[i] && (commit_buffer[i].id == rf_wb.rs1_id);
|
||||
rs2_addr_match[i] = commit_buffer_valid[i] && (commit_buffer[i].id == rf_wb.rs2_id);
|
||||
if (rs1_addr_match[i])
|
||||
rs1_sel = LOG2_WRITEBACK_BUFFERS'(i);
|
||||
if (rs2_addr_match[i])
|
||||
rs2_sel = LOG2_WRITEBACK_BUFFERS'(i);
|
||||
end
|
||||
writeback_is_idle = ~writeback_is_idle;
|
||||
end
|
||||
|
||||
assign rf_wb.rs1_valid = |rs1_addr_match;
|
||||
assign rf_wb.rs2_valid = |rs2_addr_match;
|
||||
assign rf_wb.rs1_data = commit_buffer[rs1_sel].rd;
|
||||
assign rf_wb.rs2_data = commit_buffer[rs2_sel].rd;
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -233,22 +222,23 @@ module write_back(
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Trace Interface
|
||||
generate if (ENABLE_TRACE_INTERFACE) begin
|
||||
//Checks if any two pairs are set indicating mux contention
|
||||
always_comb begin
|
||||
tr_num_instructions_completing = 0;
|
||||
for (int i=0; i<NUM_WB_UNITS; i++) begin
|
||||
tr_num_instructions_completing += unit_done[i];
|
||||
end
|
||||
// instruction_id_t num_of_instructions_pending_writeback;
|
||||
// generate if (ENABLE_TRACE_INTERFACE) begin
|
||||
//Checks if any two pairs are set indicating mux contention
|
||||
// always_comb begin
|
||||
// tr_num_instructions_completing = 0;
|
||||
// for (int i=0; i<NUM_WB_UNITS; i++) begin
|
||||
// tr_num_instructions_completing += unit_done[i];
|
||||
// end
|
||||
|
||||
tr_num_instructions_in_flight = 0;
|
||||
tr_num_of_instructions_pending_writeback = 0;
|
||||
for (int i=0; i<MAX_INFLIGHT_COUNT-1; i++) begin
|
||||
tr_num_instructions_in_flight += ID_W'(id_inuse[i]);
|
||||
tr_num_of_instructions_pending_writeback += ID_W'(id_writeback_pending[i]);
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// num_of_instructions_pending_writeback = 0;
|
||||
// for (int i=0; i<MAX_INFLIGHT_COUNT-1; i++) begin
|
||||
// num_of_instructions_pending_writeback += ID_W'(id_writeback_pending_r[i]);
|
||||
// end
|
||||
// tr_num_instructions_in_flight = tr_num_of_instructions_pending_writeback > 2 ? 2'b1 : 0;
|
||||
// end
|
||||
// end
|
||||
// endgenerate
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -98,11 +98,9 @@
|
|||
../core/illegal_instruction_checker.sv
|
||||
../core/decode_and_issue.sv
|
||||
|
||||
../core/id_inuse.sv
|
||||
../core/reg_inuse.sv
|
||||
../core/register_file.sv
|
||||
|
||||
../core/writeback_id_tracking.sv
|
||||
../core/write_back.sv
|
||||
|
||||
../core/placer_randomizer.sv
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue