mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-23 13:37:14 -04:00
renaming rework
This commit is contained in:
parent
5d3c5e928e
commit
cdb3f89c80
18 changed files with 1016 additions and 660 deletions
|
@ -34,7 +34,6 @@ module branch_unit(
|
|||
ras_interface.branch_unit ras,
|
||||
output logic branch_flush,
|
||||
|
||||
output logic branch_complete,
|
||||
output id_t branch_id,
|
||||
input branch_metadata_t branch_metadata_ex,
|
||||
|
||||
|
@ -65,6 +64,7 @@ module branch_unit(
|
|||
logic [31:0] pc_ex;
|
||||
logic instruction_is_completing;
|
||||
|
||||
logic branch_complete;
|
||||
logic jal_jalr_ex;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
|
|
@ -53,8 +53,8 @@ module csr_regs
|
|||
mmu_interface.csr immu,
|
||||
mmu_interface.csr dmmu,
|
||||
|
||||
//WB
|
||||
input logic [$clog2(MAX_COMPLETE_COUNT)-1:0] retire_inc,
|
||||
//Retire
|
||||
input retire_packet_t retire,
|
||||
|
||||
//External
|
||||
input logic interrupt,
|
||||
|
@ -543,7 +543,7 @@ endgenerate
|
|||
end
|
||||
|
||||
logic[COUNTER_W-1:0] minst_ret_next;
|
||||
assign minst_ret_next = minst_ret + COUNTER_W'(retire_inc);
|
||||
assign minst_ret_next = minst_ret + COUNTER_W'(retire.count);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
|
|
|
@ -33,8 +33,18 @@ module decode_and_issue (
|
|||
input decode_packet_t decode,
|
||||
output logic decode_advance,
|
||||
|
||||
//Renamer
|
||||
renamer_interface.decode renamer,
|
||||
|
||||
output logic decode_uses_rd,
|
||||
output rs_addr_t decode_rd_addr,
|
||||
output phys_addr_t decode_phys_rd_addr,
|
||||
output logic instruction_issued,
|
||||
output logic instruction_issued_with_rd,
|
||||
output issue_packet_t issue,
|
||||
input logic [31:0] rs_data [REGFILE_READ_PORTS],
|
||||
|
||||
//Register File
|
||||
register_file_issue_interface.issue rf,
|
||||
|
||||
output alu_inputs_t alu_inputs,
|
||||
output load_store_inputs_t ls_inputs,
|
||||
|
@ -44,8 +54,6 @@ 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_fetch_hold,
|
||||
input logic gc_issue_hold,
|
||||
|
@ -53,13 +61,6 @@ module decode_and_issue (
|
|||
input logic gc_issue_flush,
|
||||
output logic gc_flush_required,
|
||||
|
||||
//ID Management
|
||||
input logic rs_inuse [REGFILE_READ_PORTS],
|
||||
input id_t rs_id [REGFILE_READ_PORTS],
|
||||
input logic rs_id_inuse [REGFILE_READ_PORTS],
|
||||
|
||||
output logic instruction_issued,
|
||||
output logic instruction_issued_with_rd,
|
||||
output logic illegal_instruction,
|
||||
|
||||
//Trace signals
|
||||
|
@ -102,7 +103,6 @@ module decode_and_issue (
|
|||
logic environment_op;
|
||||
|
||||
logic issue_valid;
|
||||
logic operands_ready;
|
||||
logic [NUM_UNITS-1:0] unit_operands_ready;
|
||||
logic mult_div_op;
|
||||
|
||||
|
@ -149,32 +149,6 @@ module decode_and_issue (
|
|||
assign uses_rs2 = opcode_trim inside {BRANCH_T, STORE_T, ARITH_T, AMO_T};
|
||||
assign uses_rd = !(opcode_trim inside {BRANCH_T, STORE_T, FENCE_T} || environment_op);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst | gc_fetch_flush)
|
||||
issue.stage_valid <= 0;
|
||||
else if (issue_stage_ready)
|
||||
issue.stage_valid <= decode.valid;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_stage_ready) begin
|
||||
issue.pc <= decode.pc;
|
||||
issue.instruction <= decode.instruction;
|
||||
issue.fetch_metadata <= decode.fetch_metadata;
|
||||
issue.fn3 <= fn3;
|
||||
issue.opcode <= opcode;
|
||||
issue.rs_addr[RS1] <= rs1_addr;
|
||||
issue.rs_addr[RS2] <= rs2_addr;
|
||||
issue.rs_phys_addr[RS1] <= {1'b0, rs1_addr};
|
||||
issue.rs_phys_addr[RS2] <= {1'b0, rs2_addr};
|
||||
issue.rd_addr <= rd_addr;
|
||||
issue.id <= decode.id;
|
||||
issue.uses_rs1 <= uses_rs1;
|
||||
issue.uses_rs2 <= uses_rs2;
|
||||
issue.uses_rd <= uses_rd;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit Determination
|
||||
assign unit_needed[BRANCH_UNIT_ID] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T};
|
||||
|
@ -191,11 +165,58 @@ module decode_and_issue (
|
|||
assign unit_needed[DIV_UNIT_ID] = mult_div_op && fn3[2];
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Renamer Support
|
||||
assign renamer.rd_addr = rd_addr;
|
||||
assign renamer.rs_addr[RS1] = rs1_addr;
|
||||
assign renamer.rs_addr[RS2] = rs2_addr;
|
||||
assign renamer.uses_rd = uses_rd;
|
||||
assign renamer.rd_wb_group = ~unit_needed[ALU_UNIT_ID];//TODO: automate generation of wb group logic
|
||||
assign renamer.id = decode.id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Decode ID Support
|
||||
assign decode_uses_rd = uses_rd;
|
||||
assign decode_rd_addr = rd_addr;
|
||||
assign decode_phys_rd_addr = renamer.phys_rd_addr;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Issue
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_stage_ready) begin
|
||||
issue.pc <= decode.pc;
|
||||
issue.instruction <= decode.instruction;
|
||||
issue.fetch_metadata <= decode.fetch_metadata;
|
||||
issue.fn3 <= fn3;
|
||||
issue.opcode <= opcode;
|
||||
issue.rs_addr[RS1] <= rs1_addr;
|
||||
issue.rs_addr[RS2] <= rs2_addr;
|
||||
issue.phys_rs_addr[RS1] <= renamer.phys_rs_addr[RS1];
|
||||
issue.phys_rs_addr[RS2] <= renamer.phys_rs_addr[RS2];
|
||||
issue.rs_wb_group <= renamer.rs_wb_group;
|
||||
issue.rd_addr <= rd_addr;
|
||||
issue.phys_rd_addr <= renamer.phys_rd_addr;
|
||||
issue.rd_wb_group <= ~unit_needed[ALU_UNIT_ID];
|
||||
issue.id <= decode.id;
|
||||
issue.uses_rs1 <= uses_rs1;
|
||||
issue.uses_rs2 <= uses_rs2;
|
||||
issue.uses_rd <= uses_rd;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue_stage_ready)
|
||||
unit_needed_issue_stage <= unit_needed;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst | gc_fetch_flush)
|
||||
issue.stage_valid <= 0;
|
||||
else if (issue_stage_ready)
|
||||
issue.stage_valid <= decode.valid;
|
||||
end
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit ready
|
||||
generate for (i=0; i<NUM_UNITS; i++) begin
|
||||
|
@ -206,14 +227,12 @@ module decode_and_issue (
|
|||
//Issue Determination
|
||||
assign issue_valid = issue.stage_valid & ~gc_issue_hold & ~gc_fetch_flush;
|
||||
|
||||
assign rs1_conflict = rs_inuse[RS1] & rs_id_inuse[RS1] & issue.uses_rs1;
|
||||
assign rs2_conflict = rs_inuse[RS2] & rs_id_inuse[RS2] & issue.uses_rs2;
|
||||
|
||||
assign operands_ready = ~rs1_conflict & ~rs2_conflict;
|
||||
assign rs1_conflict = rf.inuse[RS1] & issue.uses_rs1;
|
||||
assign rs2_conflict = rf.inuse[RS2] & issue.uses_rs2;
|
||||
|
||||
//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 = {NUM_UNITS{(~rs1_conflict & ~rs2_conflict)}};
|
||||
unit_operands_ready[LS_UNIT_ID] = ~rs1_conflict;
|
||||
end
|
||||
|
||||
|
@ -222,6 +241,14 @@ module decode_and_issue (
|
|||
|
||||
assign instruction_issued = issue_valid & |(unit_operands_ready & issue_ready);
|
||||
assign instruction_issued_with_rd = instruction_issued & issue.uses_rd;
|
||||
|
||||
assign rf.phys_rs_addr[RS1] = issue.phys_rs_addr[RS1];
|
||||
assign rf.phys_rs_addr[RS2] = issue.phys_rs_addr[RS2];
|
||||
assign rf.phys_rd_addr = issue.phys_rd_addr;
|
||||
assign rf.rs_wb_group[RS1] = issue.rs_wb_group[RS1];
|
||||
assign rf.rs_wb_group[RS2] = issue.rs_wb_group[RS2];
|
||||
assign rf.rd_wb_group = issue.rd_wb_group;
|
||||
assign rf.issued = instruction_issued_with_rd;
|
||||
////////////////////////////////////////////////////
|
||||
//ALU unit inputs
|
||||
logic [XLEN-1:0] alu_rs1_data;
|
||||
|
@ -301,15 +328,13 @@ module decode_and_issue (
|
|||
assign alu_inputs.shifter_path = alu_shifter_path;
|
||||
assign alu_inputs.slt_path = alu_slt_path;
|
||||
|
||||
assign alu_rs1_data = rs1_use_regfile ? rs_data[RS1] : pre_alu_rs1_r;
|
||||
assign alu_rs2_data = rs2_use_regfile ? rs_data[RS2] : pre_alu_rs2_r;
|
||||
assign alu_rs1_data = rs1_use_regfile ? rf.data[RS1] : pre_alu_rs1_r;
|
||||
assign alu_rs2_data = rs2_use_regfile ? rf.data[RS2] : pre_alu_rs2_r;
|
||||
|
||||
assign alu_inputs.in1 = {(rs_data[RS1][XLEN-1] & ~issue.fn3[0]), alu_rs1_data};//(fn3[0] is SLTU_fn3);
|
||||
assign alu_inputs.in1 = {(rf.data[RS1][XLEN-1] & ~issue.fn3[0]), alu_rs1_data};//(fn3[0] is SLTU_fn3);
|
||||
assign alu_inputs.in2 = {(alu_rs2_data[XLEN-1] & ~issue.fn3[0]), alu_rs2_data};
|
||||
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_ID] & ~potential_branch_exception;
|
||||
assign alu_inputs.shifter_in = rf.data[RS1];
|
||||
assign alu_inputs.shift_amount = issue.opcode[5] ? rf.data[RS2][4:0] : issue.rs_addr[RS2];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Load Store unit inputs
|
||||
|
@ -350,14 +375,20 @@ module decode_and_issue (
|
|||
end
|
||||
end
|
||||
|
||||
id_t rd_to_id_table [32];
|
||||
always_ff @ (posedge clk) begin
|
||||
if (instruction_issued_with_rd)
|
||||
rd_to_id_table[issue.rd_addr] <= issue.id;
|
||||
end
|
||||
|
||||
assign ls_inputs.offset = ls_offset;
|
||||
assign ls_inputs.load = is_load_r;
|
||||
assign ls_inputs.store = is_store_r;
|
||||
assign ls_inputs.fn3 = amo_op ? LS_W_fn3 : issue.fn3;
|
||||
assign ls_inputs.rs1 = rs_data[RS1];
|
||||
assign ls_inputs.rs2 = rs_data[RS2];
|
||||
assign ls_inputs.rs1 = rf.data[RS1];
|
||||
assign ls_inputs.rs2 = rf.data[RS2];
|
||||
assign ls_inputs.forwarded_store = rs2_conflict;
|
||||
assign ls_inputs.store_forward_id = rs_id[RS2];
|
||||
assign ls_inputs.store_forward_id = rd_to_id_table[issue.rs_addr[RS2]];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Branch unit inputs
|
||||
|
@ -417,8 +448,8 @@ module decode_and_issue (
|
|||
|
||||
assign branch_inputs.issue_pc = issue.pc;
|
||||
assign branch_inputs.issue_pc_valid = issue.stage_valid;
|
||||
assign branch_inputs.rs1 = rs_data[RS1];
|
||||
assign branch_inputs.rs2 = rs_data[RS2];
|
||||
assign branch_inputs.rs1 = rf.data[RS1];
|
||||
assign branch_inputs.rs2 = rf.data[RS2];
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -480,15 +511,15 @@ module decode_and_issue (
|
|||
assign gc_inputs.is_fence = is_fence;
|
||||
assign gc_inputs.is_i_fence = ENABLE_M_MODE & issue_to[GC_UNIT_ID] & is_ifence_r;
|
||||
|
||||
assign gc_inputs.rs1 = rs_data[RS1];
|
||||
assign gc_inputs.rs2 = rs_data[RS2];
|
||||
assign gc_inputs.rs1 = rf.data[RS1];
|
||||
assign gc_inputs.rs2 = rf.data[RS2];
|
||||
assign gc_flush_required = ENABLE_M_MODE && issue_to[GC_UNIT_ID] && potential_flush;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Mul unit inputs
|
||||
generate if (USE_MUL) begin
|
||||
assign mul_inputs.rs1 = rs_data[RS1];
|
||||
assign mul_inputs.rs2 = rs_data[RS2];
|
||||
assign mul_inputs.rs1 = rf.data[RS1];
|
||||
assign mul_inputs.rs2 = rf.data[RS2];
|
||||
assign mul_inputs.op = issue.fn3[1:0];
|
||||
end endgenerate
|
||||
|
||||
|
@ -522,8 +553,8 @@ module decode_and_issue (
|
|||
.result(prev_div_result_valid)
|
||||
);
|
||||
|
||||
assign div_inputs.rs1 = rs_data[RS1];
|
||||
assign div_inputs.rs2 = rs_data[RS2];
|
||||
assign div_inputs.rs1 = rf.data[RS1];
|
||||
assign div_inputs.rs2 = rf.data[RS2];
|
||||
assign div_inputs.op = issue.fn3[1:0];
|
||||
assign div_inputs.reuse_result = prev_div_result_valid & current_op_resuses_rs1_rs2;
|
||||
end endgenerate
|
||||
|
|
|
@ -55,18 +55,12 @@ module gc_unit(
|
|||
mmu_interface.csr immu,
|
||||
mmu_interface.csr dmmu,
|
||||
|
||||
//ID Management
|
||||
output logic system_op_or_exception_complete,
|
||||
output logic exception_with_rd_complete,
|
||||
output id_t system_op_or_exception_id,
|
||||
|
||||
//Exception
|
||||
output id_t exception_id,
|
||||
input logic [31:0] exception_pc,
|
||||
|
||||
//WB
|
||||
input logic [$clog2(MAX_COMPLETE_COUNT)-1:0] retire_inc,
|
||||
input logic instruction_retired,
|
||||
//unit_writeback_interface.unit gc_wb,
|
||||
//Retire
|
||||
input retire_packet_t retire,
|
||||
|
||||
//External
|
||||
input logic interrupt,
|
||||
|
@ -91,7 +85,7 @@ module gc_unit(
|
|||
//Largest depth for TLBs
|
||||
localparam int TLB_CLEAR_DEPTH = (DTLB_DEPTH > ITLB_DEPTH) ? DTLB_DEPTH : ITLB_DEPTH;
|
||||
//For general reset clear, greater of TLB depth or id-flight memory blocks (MAX_IDS)
|
||||
localparam int INIT_CLEAR_DEPTH = ENABLE_S_MODE ? (TLB_CLEAR_DEPTH > MAX_IDS ? TLB_CLEAR_DEPTH : MAX_IDS) : MAX_IDS;
|
||||
localparam int INIT_CLEAR_DEPTH = ENABLE_S_MODE ? (TLB_CLEAR_DEPTH > 64 ? TLB_CLEAR_DEPTH : 64) : 64;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Instructions
|
||||
|
@ -137,6 +131,9 @@ module gc_unit(
|
|||
exception_code_t ecall_code;
|
||||
logic second_cycle_flush;
|
||||
|
||||
logic system_op_or_exception_complete;
|
||||
logic exception_with_rd_complete;
|
||||
|
||||
//CSR
|
||||
logic mret;
|
||||
logic sret;
|
||||
|
@ -182,7 +179,7 @@ module gc_unit(
|
|||
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_id <= exception_or_system_id;
|
||||
exception_with_rd_complete <= (ls_exception.valid & ~ls_exception_is_store) | (br_exception.valid & branch_exception_is_jump);
|
||||
end
|
||||
|
||||
|
@ -338,7 +335,7 @@ module gc_unit(
|
|||
.asid(asid),
|
||||
.immu(immu),
|
||||
.dmmu(dmmu),
|
||||
.retire_inc(retire_inc),
|
||||
.retire(retire),
|
||||
.interrupt(interrupt),
|
||||
.timer_interrupt(timer_interrupt),
|
||||
.wb_csr(wb_csr),
|
||||
|
|
|
@ -47,37 +47,32 @@ module instruction_metadata_and_id_management
|
|||
//Decode ID
|
||||
output decode_packet_t decode,
|
||||
input logic decode_advance,
|
||||
input logic decode_uses_rd,
|
||||
input rs_addr_t decode_rd_addr,
|
||||
//renamer
|
||||
input phys_addr_t decode_phys_rd_addr,
|
||||
|
||||
//Issue stage
|
||||
input issue_packet_t issue,
|
||||
input logic instruction_issued,
|
||||
output id_t rs_id [REGFILE_READ_PORTS],
|
||||
output logic rs_inuse [REGFILE_READ_PORTS],
|
||||
output logic rs_id_inuse[REGFILE_READ_PORTS],
|
||||
input logic instruction_issued_with_rd,
|
||||
|
||||
//Branch Predictor
|
||||
input branch_metadata_t branch_metadata_if,
|
||||
input id_t branch_id,
|
||||
output branch_metadata_t branch_metadata_ex,
|
||||
|
||||
//ID freeing
|
||||
input logic store_complete,
|
||||
input id_t store_id,
|
||||
//WB
|
||||
input wb_packet_t wb_packet [NUM_WB_GROUPS],
|
||||
output commit_packet_t commit_packet [NUM_WB_GROUPS],
|
||||
|
||||
input logic branch_complete,
|
||||
input id_t branch_id,
|
||||
//Retirer
|
||||
output retire_packet_t retire,
|
||||
output id_t retire_ids [RETIRE_PORTS],
|
||||
output logic retire_ids_retired [RETIRE_PORTS],
|
||||
|
||||
input logic system_op_or_exception_complete,
|
||||
input logic exception_with_rd_complete,
|
||||
input id_t system_op_or_exception_id,
|
||||
|
||||
output logic [$clog2(MAX_COMPLETE_COUNT)-1:0] retire_inc,
|
||||
|
||||
//Writeback/Register File
|
||||
input id_t ids_retiring [COMMIT_PORTS],
|
||||
input logic retired [COMMIT_PORTS],
|
||||
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
|
||||
|
||||
);
|
||||
|
@ -86,39 +81,21 @@ module instruction_metadata_and_id_management
|
|||
logic [31:0] instruction_table [MAX_IDS];
|
||||
logic valid_fetch_addr_table [MAX_IDS];
|
||||
|
||||
logic [4:0] rd_addr_table [MAX_IDS];
|
||||
rs_addr_t rd_addr_table [MAX_IDS];
|
||||
phys_addr_t phys_addr_table [MAX_IDS];
|
||||
logic uses_rd_table [MAX_IDS];
|
||||
|
||||
logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS];
|
||||
logic [$bits(fetch_metadata_t)-1:0] fetch_metadata_table [MAX_IDS];
|
||||
|
||||
localparam LOG2_MAX_IDS = $clog2(MAX_IDS);
|
||||
id_t clear_index;
|
||||
id_t pc_id_next;
|
||||
id_t decode_id;
|
||||
|
||||
logic [LOG2_MAX_IDS:0] fetched_count; //MSB used as valid for decode stage
|
||||
logic [LOG2_MAX_IDS:0] pre_issue_count;
|
||||
logic [LOG2_MAX_IDS:0] post_issue_count;
|
||||
logic [LOG2_MAX_IDS:0] inflight_count;
|
||||
|
||||
//Toggle memory results for tracking completion after issue
|
||||
logic decoded_status;
|
||||
logic decoded_issued_status;
|
||||
|
||||
logic issued_status;
|
||||
logic issued_status_rs [REGFILE_READ_PORTS];
|
||||
|
||||
logic branch_complete_status;
|
||||
logic store_complete_status;
|
||||
|
||||
logic system_op_or_exception_complete_status;
|
||||
logic exception_with_rd_complete_status_rs [REGFILE_READ_PORTS];
|
||||
|
||||
logic [COMMIT_PORTS-1:0] retired_status;
|
||||
logic [COMMIT_PORTS-1:0] retired_status_rs [REGFILE_READ_PORTS];
|
||||
|
||||
logic [$clog2(MAX_COMPLETE_COUNT)-1:0] complete_count;
|
||||
|
||||
logic id_not_in_decode_issue;
|
||||
logic id_not_inflight;
|
||||
|
||||
//Writes to register file
|
||||
id_t rd_to_id_table [32];
|
||||
genvar i;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
@ -143,40 +120,42 @@ module instruction_metadata_and_id_management
|
|||
instruction_table[fetch_id] <= fetch_instruction;
|
||||
end
|
||||
|
||||
//rd table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (fetch_complete)
|
||||
rd_addr_table[fetch_id] <= fetch_instruction[11:7];
|
||||
end
|
||||
|
||||
//valid fetched address table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (fetch_complete)
|
||||
fetch_metadata_table[fetch_id] <= fetch_metadata;
|
||||
end
|
||||
|
||||
|
||||
//Operand inuse determination
|
||||
initial rd_to_id_table = '{default: 0};
|
||||
//phys rd table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (instruction_issued & issue.uses_rd)//tracks most recently issued instruction that writes to the register file
|
||||
rd_to_id_table[issue.rd_addr] <= issue.id;
|
||||
if (decode_advance)
|
||||
phys_addr_table[decode_id] <= decode_phys_rd_addr;
|
||||
end
|
||||
|
||||
//rd table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (decode_advance)
|
||||
rd_addr_table[decode_id] <= decode_rd_addr;
|
||||
end
|
||||
|
||||
//uses rd table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (decode_advance)
|
||||
uses_rd_table[decode_id] <= decode_uses_rd;
|
||||
end
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
|
||||
|
||||
//Next ID always increases, except on a fetch buffer flush.
|
||||
//On a fetch buffer flush, the next ID is restored to the current decode ID.
|
||||
//On a fetch buffer flush, the next ID is restored to the oldest non-issued ID (decode or issue stage)
|
||||
//This prevents a stall in the case where all IDs are either in-flight or
|
||||
//in the fetch buffer at the point of a fetch flush.
|
||||
id_t next_pc_id_base;
|
||||
id_t next_fetch_id_base;
|
||||
assign next_pc_id_base = gc_fetch_flush ? decode_id : (early_branch_flush ? fetch_id : pc_id);
|
||||
assign next_fetch_id_base = gc_fetch_flush ? decode_id : fetch_id;
|
||||
assign next_pc_id_base = gc_fetch_flush ? (issue.stage_valid ? issue.id : decode_id) : (early_branch_flush ? fetch_id : pc_id);
|
||||
assign next_fetch_id_base = gc_fetch_flush ? (issue.stage_valid ? issue.id : decode_id) : fetch_id;
|
||||
|
||||
assign pc_id_next = next_pc_id_base + LOG2_MAX_IDS'({pc_id_assigned & ~gc_fetch_flush});
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
pc_id <= 0;
|
||||
|
@ -186,103 +165,107 @@ module instruction_metadata_and_id_management
|
|||
else begin
|
||||
pc_id <= next_pc_id_base + LOG2_MAX_IDS'({pc_id_assigned & (~gc_fetch_flush)});
|
||||
fetch_id <= next_fetch_id_base + LOG2_MAX_IDS'({fetch_complete & ~gc_fetch_flush});
|
||||
decode_id <= decode_id + LOG2_MAX_IDS'({decode_advance & ~gc_fetch_flush});
|
||||
decode_id <= ((gc_fetch_flush & issue.stage_valid) ? issue.id : decode_id) + LOG2_MAX_IDS'({decode_advance & ~gc_fetch_flush});
|
||||
end
|
||||
end
|
||||
//Retire IDs
|
||||
generate for (i = 0; i < RETIRE_PORTS; i++) begin
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
retire_ids[i] <= LOG2_MAX_IDS'(i);
|
||||
else
|
||||
retire_ids[i] <= retire_ids[i] + LOG2_MAX_IDS'(retire.count);
|
||||
end
|
||||
end endgenerate
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst | gc_fetch_flush)
|
||||
fetched_count <= 0;
|
||||
else
|
||||
fetched_count <= fetched_count + (LOG2_MAX_IDS+1)'(decode_advance) - (LOG2_MAX_IDS+1)'(fetch_complete);
|
||||
fetched_count <= fetched_count + (LOG2_MAX_IDS+1)'(fetch_complete) - (LOG2_MAX_IDS+1)'(decode_advance);
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Issue Tracking
|
||||
//As there are multiple completion sources, each source toggles a bit in its own LUTRAM.
|
||||
//All LUTRAMs are then xor-ed together to produce the status of the ID.
|
||||
|
||||
//Computed one cycle in advance using pc_id_next
|
||||
logic id_in_decode_issue [1];
|
||||
toggle_memory_set # (
|
||||
.DEPTH (MAX_IDS),
|
||||
.NUM_WRITE_PORTS (2),
|
||||
.NUM_READ_PORTS (1),
|
||||
.WRITE_INDEX_FOR_RESET (0),
|
||||
.READ_INDEX_FOR_RESET (0)
|
||||
) id_in_decode_tracking
|
||||
(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.init_clear (gc_init_clear),
|
||||
.toggle ('{(decode_advance & ~gc_fetch_flush), (instruction_issued | (gc_fetch_flush & issue.stage_valid))}),
|
||||
.toggle_addr ('{decode.id, issue.id}),
|
||||
.read_addr ('{pc_id_next}),
|
||||
.in_use (id_in_decode_issue)
|
||||
);
|
||||
assign id_not_in_decode_issue = ~id_in_decode_issue[0];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Outputs
|
||||
logic id_inflight [1];
|
||||
toggle_memory_set # (
|
||||
.DEPTH (MAX_IDS),
|
||||
.NUM_WRITE_PORTS (6),
|
||||
.NUM_READ_PORTS (1),
|
||||
.WRITE_INDEX_FOR_RESET (0),
|
||||
.READ_INDEX_FOR_RESET (0)
|
||||
) id_inflight_tracking
|
||||
(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.init_clear (gc_init_clear),
|
||||
.toggle ('{instruction_issued, branch_complete, store_complete, system_op_or_exception_complete, retired[0], retired[1]}),
|
||||
.toggle_addr ('{issue.id, branch_id, store_id, system_op_or_exception_id, ids_retiring[0], ids_retiring[1]}),
|
||||
.read_addr ('{pc_id_next}),
|
||||
.in_use (id_inflight)
|
||||
);
|
||||
assign id_not_inflight = ~id_inflight[0];
|
||||
|
||||
//rs1/rs2 conflicts don't check branch or store memories as the only
|
||||
//IDs stored in the rs to ID table are instructions that write to the register file
|
||||
toggle_memory_set # (
|
||||
.DEPTH (MAX_IDS),
|
||||
.NUM_WRITE_PORTS (4),
|
||||
.NUM_READ_PORTS (2),
|
||||
.WRITE_INDEX_FOR_RESET (0),
|
||||
.READ_INDEX_FOR_RESET (0)
|
||||
) rs_inuse_tacking
|
||||
(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.init_clear (gc_init_clear),
|
||||
.toggle ('{(instruction_issued & issue.uses_rd), exception_with_rd_complete, retired[0], retired[1]}),
|
||||
.toggle_addr ('{issue.id, system_op_or_exception_id, ids_retiring[0], ids_retiring[1]}),
|
||||
.read_addr (rs_id),
|
||||
.in_use (rs_id_inuse)
|
||||
);
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst | gc_fetch_flush)
|
||||
pre_issue_count <= 0;
|
||||
else
|
||||
pre_issue_count <= pre_issue_count
|
||||
+ (LOG2_MAX_IDS+1)'(pc_id_assigned)
|
||||
- (LOG2_MAX_IDS+1)'(instruction_issued);
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
pc_id_available <= 1;
|
||||
post_issue_count <= 0;
|
||||
else
|
||||
pc_id_available <= id_not_in_decode_issue & id_not_inflight;
|
||||
post_issue_count <= post_issue_count
|
||||
+ (LOG2_MAX_IDS+1)'(instruction_issued)
|
||||
- (LOG2_MAX_IDS+1)'(retire.count);
|
||||
end
|
||||
|
||||
localparam MCC_W = $clog2(MAX_COMPLETE_COUNT);
|
||||
assign inflight_count = pre_issue_count + post_issue_count;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID in-use determination
|
||||
logic id_inuse [RETIRE_PORTS];
|
||||
//WB group zero is not included as it completes within a single cycle
|
||||
//Non-writeback instructions not included as current instruction set
|
||||
//complete in their first cycle of the execute stage, or do not cause an
|
||||
//exception after that point
|
||||
toggle_memory_set # (
|
||||
.DEPTH (MAX_IDS),
|
||||
.NUM_WRITE_PORTS (2),
|
||||
.NUM_READ_PORTS (RETIRE_PORTS),
|
||||
.WRITE_INDEX_FOR_RESET (0),
|
||||
.READ_INDEX_FOR_RESET (0)
|
||||
) id_inuse_toggle_mem_set
|
||||
(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.init_clear (gc_init_clear),
|
||||
.toggle ('{(instruction_issued_with_rd & (issue.rd_wb_group == 1)), wb_packet[1].valid}),
|
||||
.toggle_addr ('{issue.id, wb_packet[1].id}),
|
||||
.read_addr (retire_ids),
|
||||
.in_use (id_inuse)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Retirer
|
||||
logic contiguous_retire;
|
||||
|
||||
always_comb begin
|
||||
complete_count = MCC_W'(branch_complete) + MCC_W'(store_complete) + MCC_W'(system_op_or_exception_complete);
|
||||
for (int i = 0; i < COMMIT_PORTS; i++) begin
|
||||
complete_count += MCC_W'(retired[i]);
|
||||
contiguous_retire = 1;
|
||||
retire_ids_retired = '{default: 0};
|
||||
|
||||
retire.valid = 0;
|
||||
retire.count = 0;
|
||||
retire.phys_id = retire_ids[0];
|
||||
|
||||
for (int i = 0; i < RETIRE_PORTS; i++) begin
|
||||
//Only pop if all older entries have been popped and only if this is either the first entry that writes to the regfile
|
||||
//or does not write to the regfile
|
||||
if ((post_issue_count > (LOG2_MAX_IDS+1)'(i)) && contiguous_retire) begin
|
||||
retire_ids_retired[i] = (~uses_rd_table[retire_ids[i]] | (~id_inuse[i] & ~retire.valid));
|
||||
contiguous_retire &= retire_ids_retired[i];
|
||||
retire.count += retire_ids_retired[i];
|
||||
|
||||
if (retire_ids_retired[i] & uses_rd_table[retire_ids[i]]) begin
|
||||
retire.valid |= 1;
|
||||
retire.phys_id = retire_ids[i];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
retire.rd_addr = rd_addr_table[retire.phys_id];
|
||||
end
|
||||
always_ff @ (posedge clk) begin
|
||||
retire_inc <= complete_count;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Outputs
|
||||
assign pc_id_available = ~inflight_count[LOG2_MAX_IDS];
|
||||
|
||||
//Decode
|
||||
assign decode.id = decode_id;
|
||||
assign decode.valid = fetched_count[LOG2_MAX_IDS];
|
||||
assign decode.valid = |fetched_count;
|
||||
assign decode.pc = pc_table[decode_id];
|
||||
assign decode.instruction = instruction_table[decode_id];
|
||||
assign decode.fetch_metadata = fetch_metadata_table[decode_id];
|
||||
|
@ -290,30 +273,24 @@ module instruction_metadata_and_id_management
|
|||
//Branch Predictor
|
||||
assign branch_metadata_ex = branch_metadata_table[branch_id];
|
||||
|
||||
//Issue
|
||||
//Writeback/Commit support
|
||||
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]) & (issue.rs_addr[i] == rd_addr_table[rs_id[i]]);
|
||||
end
|
||||
end
|
||||
|
||||
//Writeback support
|
||||
always_comb begin
|
||||
retired_rd_addr[0] = issue.rd_addr;
|
||||
for (int i = 1; i < COMMIT_PORTS; i++) begin
|
||||
retired_rd_addr[i] = rd_addr_table[ids_retiring[i]];
|
||||
for (int i = 0; i < NUM_WB_GROUPS; i++) begin
|
||||
commit_packet[i].id = wb_packet[i].id;
|
||||
commit_packet[i].valid = wb_packet[i].valid;
|
||||
commit_packet[i].data = wb_packet[i].data;
|
||||
end
|
||||
end
|
||||
always_comb begin
|
||||
for (int i = 0; i < COMMIT_PORTS; i++) begin
|
||||
id_for_rd[i] = rd_to_id_table[retired_rd_addr[i]];
|
||||
commit_packet[0].phys_addr = issue.phys_rd_addr;
|
||||
for (int i = 1; i < NUM_WB_GROUPS; i++) begin
|
||||
commit_packet[i].phys_addr = phys_addr_table[wb_packet[i].id];
|
||||
end
|
||||
end
|
||||
|
||||
//Exception Support
|
||||
generate if (ENABLE_M_MODE) begin
|
||||
assign exception_pc = pc_table[system_op_or_exception_id];
|
||||
assign exception_pc = pc_table[exception_id];
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -271,3 +271,46 @@ interface unsigned_division_interface #(parameter DATA_WIDTH = 32);
|
|||
modport divider (output remainder, quotient, done, divisor_is_zero, input dividend, divisor, start);
|
||||
endinterface
|
||||
|
||||
interface renamer_interface;
|
||||
rs_addr_t rd_addr;
|
||||
rs_addr_t [REGFILE_READ_PORTS-1:0] rs_addr;
|
||||
rs_wb_group_t rd_wb_group;
|
||||
logic uses_rd;
|
||||
id_t id;
|
||||
|
||||
phys_addr_t [REGFILE_READ_PORTS-1:0] phys_rs_addr;
|
||||
phys_addr_t phys_rd_addr;
|
||||
|
||||
rs_wb_group_t [REGFILE_READ_PORTS-1:0] rs_wb_group;
|
||||
|
||||
modport renamer (
|
||||
input rd_addr, rs_addr, rd_wb_group, uses_rd, id,
|
||||
output phys_rs_addr, rs_wb_group, phys_rd_addr
|
||||
);
|
||||
modport decode (
|
||||
input phys_rs_addr, rs_wb_group, phys_rd_addr,
|
||||
output rd_addr, rs_addr, rd_wb_group, uses_rd, id
|
||||
);
|
||||
endinterface
|
||||
|
||||
interface register_file_issue_interface;
|
||||
//read interface
|
||||
phys_addr_t phys_rs_addr [REGFILE_READ_PORTS];
|
||||
logic [LOG2_COMMIT_PORTS-1:0] rs_wb_group [REGFILE_READ_PORTS];
|
||||
logic [31:0] data [REGFILE_READ_PORTS];
|
||||
logic inuse [REGFILE_READ_PORTS];
|
||||
|
||||
//write interface
|
||||
phys_addr_t phys_rd_addr;
|
||||
logic [LOG2_COMMIT_PORTS-1:0] rd_wb_group;
|
||||
logic issued;
|
||||
|
||||
modport register_file (
|
||||
input phys_rs_addr, phys_rd_addr, issued, rs_wb_group, rd_wb_group,
|
||||
output data, inuse
|
||||
);
|
||||
modport issue (
|
||||
output phys_rs_addr, phys_rd_addr, issued, rs_wb_group, rd_wb_group,
|
||||
input data, inuse
|
||||
);
|
||||
endinterface
|
||||
|
|
|
@ -36,9 +36,10 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
//Writeback snooping
|
||||
input wb_packet_t wb_snoop,
|
||||
|
||||
//Writeback release
|
||||
input id_t ids_released [COMMIT_PORTS],
|
||||
input logic wb_released [COMMIT_PORTS],
|
||||
//Retire release
|
||||
input id_t retire_ids [RETIRE_PORTS],
|
||||
input logic retire_ids_retired [RETIRE_PORTS],
|
||||
|
||||
output logic tr_possible_load_conflict_delay
|
||||
);
|
||||
localparam SQ_DEPTH = 4;
|
||||
|
@ -97,8 +98,8 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
|
|||
.sq_entry (sq_entry),
|
||||
.sq_data (sq_data),
|
||||
.wb_snoop (wb_snoop),
|
||||
.ids_released (ids_released),
|
||||
.wb_released (wb_released),
|
||||
.retire_ids (retire_ids),
|
||||
.retire_ids_retired (retire_ids_retired),
|
||||
.store_ack (store_ack),
|
||||
.sq_output_valid (sq_output_valid)
|
||||
);
|
||||
|
|
|
@ -49,13 +49,13 @@ module load_store_unit (
|
|||
|
||||
local_memory_interface.master data_bram,
|
||||
|
||||
//ID Management
|
||||
output logic store_complete,
|
||||
output id_t store_id,
|
||||
|
||||
//Writeback-Store Interface
|
||||
input wb_packet_t wb_snoop,
|
||||
|
||||
//Retire release
|
||||
input id_t retire_ids [RETIRE_PORTS],
|
||||
input logic retire_ids_retired [RETIRE_PORTS],
|
||||
|
||||
//CSR support
|
||||
output logic ls_is_idle,
|
||||
|
||||
|
@ -188,29 +188,20 @@ endgenerate
|
|||
assign lsq.new_issue = issue.new_request & ~unaligned_addr & (~tlb_on | tlb.done);
|
||||
|
||||
load_store_queue lsq_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_issue_flush (gc_issue_flush),
|
||||
.lsq (lsq),
|
||||
.wb_snoop (wb_snoop),
|
||||
.ids_released ('{LOG2_MAX_IDS'(1'b0), store_id}),
|
||||
.wb_released ('{1'b0, store_complete}),
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_issue_flush (gc_issue_flush),
|
||||
.lsq (lsq),
|
||||
.wb_snoop (wb_snoop),
|
||||
.retire_ids (retire_ids),
|
||||
.retire_ids_retired (retire_ids_retired),
|
||||
.tr_possible_load_conflict_delay (tr_possible_load_conflict_delay)
|
||||
);
|
||||
assign shared_inputs = lsq.transaction_out;
|
||||
|
||||
assign lsq.accepted = issue_request;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//ID Management
|
||||
always_ff @ (posedge clk) begin
|
||||
store_id <= lsq.id;
|
||||
if (rst)
|
||||
store_complete <= 0;
|
||||
else
|
||||
store_complete <= lsq.new_issue & lsq.store;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit tracking
|
||||
assign current_unit = sub_unit_address_match;
|
||||
|
|
67
core/register_bank.sv
Normal file
67
core/register_bank.sv
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.
|
||||
* 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>
|
||||
*/
|
||||
|
||||
module register_bank
|
||||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
#(
|
||||
parameter NUM_READ_PORTS = 2
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
//Writeback
|
||||
input phys_addr_t write_addr,
|
||||
input logic [31:0] new_data,
|
||||
input logic commit,
|
||||
|
||||
//Issue
|
||||
input phys_addr_t read_addr [NUM_READ_PORTS],
|
||||
output logic [31:0] data [NUM_READ_PORTS]
|
||||
);
|
||||
|
||||
logic [31:0] register_file_bank [64];
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File
|
||||
//Assign zero to r0 and initialize all registers to zero for simulation
|
||||
initial register_file_bank = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (commit)
|
||||
register_file_bank[write_addr] <= new_data;
|
||||
end
|
||||
always_comb begin
|
||||
foreach(read_addr[i])
|
||||
data[i] = register_file_bank[read_addr[i]];
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
write_to_zero_reg_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) !(commit & write_addr == 0))
|
||||
else $error("Write to zero reg occured!");
|
||||
|
||||
endmodule
|
90
core/register_file.sv
Normal file → Executable file
90
core/register_file.sv
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2017-2020 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.
|
||||
|
@ -24,44 +24,86 @@ module register_file
|
|||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
#(
|
||||
parameter NUM_READ_PORTS = 2
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
input logic gc_init_clear,
|
||||
|
||||
//Issue interface
|
||||
register_file_issue_interface.register_file rf_issue,
|
||||
|
||||
//Writeback
|
||||
input phys_addr_t write_addr,
|
||||
input logic [31:0] new_data,
|
||||
input logic commit,
|
||||
|
||||
//Issue
|
||||
input phys_addr_t [NUM_READ_PORTS-1:0] read_addr,
|
||||
output logic [31:0] data [NUM_READ_PORTS]
|
||||
input commit_packet_t commit [NUM_WB_GROUPS]
|
||||
);
|
||||
typedef logic [31:0] rs_data_set_t [REGFILE_READ_PORTS];
|
||||
rs_data_set_t rs_data_set [NUM_WB_GROUPS];
|
||||
|
||||
logic [31:0] register_file [64];
|
||||
typedef logic inuse_t [REGFILE_READ_PORTS];
|
||||
inuse_t phys_reg_inuse_set [NUM_WB_GROUPS];
|
||||
|
||||
genvar i;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File
|
||||
//Assign zero to r0 and initialize all registers to zero for simulation
|
||||
initial register_file = '{default: 0};
|
||||
always_ff @ (posedge clk) begin
|
||||
if (commit)
|
||||
register_file[write_addr] <= new_data;
|
||||
end
|
||||
//Phys register inuse
|
||||
//WB group 0 contains the ALU, a single-cycle unit, thus any preceeding
|
||||
//instructions will have written their data to the register file
|
||||
assign phys_reg_inuse_set[0] = '{default : 0};
|
||||
|
||||
//WB groups 1+ have multiple-cycle operation and thus a status flag is set
|
||||
//for each physical register
|
||||
toggle_memory_set # (
|
||||
.DEPTH (64),
|
||||
.NUM_WRITE_PORTS (2),
|
||||
.NUM_READ_PORTS (REGFILE_READ_PORTS),
|
||||
.WRITE_INDEX_FOR_RESET (0),
|
||||
.READ_INDEX_FOR_RESET (0)
|
||||
) id_inuse_toggle_mem_set
|
||||
(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.init_clear (gc_init_clear),
|
||||
.toggle ('{(rf_issue.issued & (rf_issue.rd_wb_group == 1) & |rf_issue.phys_rd_addr), (commit[1].valid & |commit[1].phys_addr)}),
|
||||
.toggle_addr ('{rf_issue.phys_rd_addr, commit[1].phys_addr}),
|
||||
.read_addr (rf_issue.phys_rs_addr),
|
||||
.in_use (phys_reg_inuse_set[1])
|
||||
);
|
||||
always_comb begin
|
||||
foreach(read_addr[i])
|
||||
data[i] = register_file[read_addr[i]];
|
||||
for (int i = 0; i < REGFILE_READ_PORTS; i++) begin
|
||||
rf_issue.inuse[i] = phys_reg_inuse_set[rf_issue.rs_wb_group[i]][i];
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register Banks
|
||||
//Implemented in seperate module as there is not universal tool support for inferring
|
||||
//arrays of memory blocks.
|
||||
generate for (i = 0; i < NUM_WB_GROUPS; i++) begin : register_file_gen
|
||||
register_bank #(.NUM_READ_PORTS(REGFILE_READ_PORTS)) reg_group (
|
||||
.clk, .rst,
|
||||
.write_addr(commit[i].phys_addr),
|
||||
.new_data(commit[i].data),
|
||||
.commit(commit[i].valid & (|commit[i].phys_addr)),
|
||||
.read_addr(rf_issue.phys_rs_addr),
|
||||
.data(rs_data_set[i])
|
||||
);
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File Muxing
|
||||
always_comb begin
|
||||
for (int i = 0; i < REGFILE_READ_PORTS; i++) begin
|
||||
rf_issue.data[i] = rs_data_set[rf_issue.rs_wb_group[i]][i];
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
write_to_zero_reg_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) !(commit & write_addr == 0))
|
||||
else $error("Write to zero reg occured!");
|
||||
|
||||
endmodule
|
||||
|
|
92
core/register_free_list.sv
Normal file
92
core/register_free_list.sv
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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.
|
||||
* 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>
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIFOs Not underflow/overflow safe.
|
||||
* Intended for small FIFO depths.
|
||||
* For continuous operation when full, enqueing side must inspect pop signal
|
||||
*/
|
||||
module register_free_list
|
||||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
#(
|
||||
parameter DATA_WIDTH = 70,
|
||||
parameter FIFO_DEPTH = 4
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
fifo_interface.structure fifo,
|
||||
input logic rollback
|
||||
);
|
||||
|
||||
localparam LOG2_FIFO_DEPTH = $clog2(FIFO_DEPTH);
|
||||
|
||||
//Force FIFO depth to next power of 2
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic [DATA_WIDTH-1:0] lut_ram [(2**LOG2_FIFO_DEPTH)];
|
||||
logic [LOG2_FIFO_DEPTH-1:0] write_index;
|
||||
logic [LOG2_FIFO_DEPTH-1:0] read_index;
|
||||
logic [LOG2_FIFO_DEPTH:0] inflight_count;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Occupancy Tracking
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
inflight_count <= 0;
|
||||
else
|
||||
inflight_count <= inflight_count
|
||||
+ (LOG2_FIFO_DEPTH+1)'(fifo.pop)
|
||||
- (LOG2_FIFO_DEPTH+1)'(fifo.push)
|
||||
- (LOG2_FIFO_DEPTH+1)'(rollback);
|
||||
end
|
||||
|
||||
assign fifo.valid = inflight_count[LOG2_FIFO_DEPTH];
|
||||
assign fifo.full = fifo.valid & ~|inflight_count[LOG2_FIFO_DEPTH-1:0];
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
read_index <= '0;
|
||||
write_index <= '0;
|
||||
end
|
||||
else begin
|
||||
read_index <= read_index + LOG2_FIFO_DEPTH'(fifo.pop) - LOG2_FIFO_DEPTH'(rollback);
|
||||
write_index <= write_index + LOG2_FIFO_DEPTH'(fifo.push);
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (fifo.potential_push)
|
||||
lut_ram[write_index] <= fifo.data_in;
|
||||
end
|
||||
assign fifo.data_out = lut_ram[read_index];
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
fifo_overflow_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) fifo.push |-> (~fifo.full | fifo.pop)) else $error("overflow");
|
||||
fifo_underflow_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) fifo.pop |-> fifo.valid) else $error("underflow");
|
||||
|
||||
endmodule
|
163
core/renamer.sv
Normal file
163
core/renamer.sv
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* 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.
|
||||
* 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>
|
||||
*/
|
||||
|
||||
module renamer
|
||||
|
||||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
input logic gc_init_clear,
|
||||
input logic gc_fetch_flush,
|
||||
|
||||
//Decode
|
||||
input logic decode_advance,
|
||||
renamer_interface.renamer decode,
|
||||
|
||||
//Issue stage
|
||||
input issue_packet_t issue,
|
||||
|
||||
//Retire response
|
||||
input retire_packet_t retire
|
||||
);
|
||||
//////////////////////////////////////////
|
||||
phys_addr_t architectural_id_to_phys_table [MAX_IDS];
|
||||
phys_addr_t speculative_rd_to_phys_table [32];
|
||||
|
||||
rs_wb_group_t spec_wb_group [32];
|
||||
rs_wb_group_t arch_wb_group [32];
|
||||
rs_wb_group_t rollback_wb_group;
|
||||
|
||||
logic [5:0] clear_index;
|
||||
fifo_interface #(.DATA_WIDTH(6)) free_list ();
|
||||
logic rename_valid;
|
||||
logic rollback;
|
||||
phys_addr_t rollback_phys_addr;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
assign rename_valid = (~gc_fetch_flush) & decode_advance & decode.uses_rd & |decode.rd_addr;
|
||||
|
||||
//Revert physcial address assignment on a flush
|
||||
assign rollback = gc_fetch_flush & issue.stage_valid & issue.uses_rd & |issue.rd_addr;
|
||||
|
||||
//counter for indexing through memories for post-reset clearing/initialization
|
||||
initial clear_index = 0;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
clear_index <= 0;
|
||||
else
|
||||
clear_index <= clear_index + 6'(gc_init_clear);
|
||||
end
|
||||
////////////////////////////////////////////////////
|
||||
//Free list FIFO
|
||||
register_free_list #(.DATA_WIDTH(6), .FIFO_DEPTH(32)) free_list_fifo (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.fifo (free_list),
|
||||
.rollback (rollback)
|
||||
);
|
||||
|
||||
//During post reset init, initialize FIFO with free list (registers 32-63)
|
||||
assign free_list.potential_push = (gc_init_clear & ~clear_index[5]) | (retire.valid & |retire.rd_addr);
|
||||
assign free_list.push = free_list.potential_push;
|
||||
//TODO: restore spec if instruction has been discarded due to a speculation failure
|
||||
assign free_list.data_in = gc_init_clear ? {1'b1, clear_index[4:0]} : architectural_id_to_phys_table[retire.phys_id];
|
||||
assign free_list.pop = rename_valid;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Speculative rd-to-phys Table
|
||||
//On rollback restore the previous contents
|
||||
//During post reset init, initialize rd_to_phys with in-use list (lower 32 registers)
|
||||
logic spec_table_update;
|
||||
logic [4:0] spec_table_write_index;
|
||||
logic [5:0] spec_table_write_data;
|
||||
logic [$clog2(NUM_WB_GROUPS)-1:0] spec_table_wb_group_data;
|
||||
|
||||
assign spec_table_update = rename_valid | rollback | gc_init_clear;
|
||||
|
||||
always_comb begin
|
||||
if (gc_init_clear) begin
|
||||
spec_table_write_index = clear_index[4:0];
|
||||
spec_table_write_data = {1'b0, clear_index[4:0]};
|
||||
spec_table_wb_group_data = '0;
|
||||
end
|
||||
else if (rollback) begin
|
||||
spec_table_write_index = issue.rd_addr;
|
||||
spec_table_write_data = rollback_phys_addr;
|
||||
spec_table_wb_group_data = rollback_wb_group;
|
||||
end
|
||||
else begin
|
||||
spec_table_write_index = decode.rd_addr;
|
||||
spec_table_write_data = free_list.data_out;
|
||||
spec_table_wb_group_data = decode.rd_wb_group;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (spec_table_update) begin
|
||||
speculative_rd_to_phys_table[spec_table_write_index] <= spec_table_write_data;
|
||||
rollback_phys_addr <= speculative_rd_to_phys_table[spec_table_write_index];
|
||||
end
|
||||
end
|
||||
|
||||
//WB group
|
||||
always_ff @ (posedge clk) begin
|
||||
if (spec_table_update) begin
|
||||
spec_wb_group[spec_table_write_index] <= spec_table_wb_group_data;
|
||||
rollback_wb_group <= spec_wb_group[spec_table_write_index];
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Arch ID-to-phys Table
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rename_valid)
|
||||
architectural_id_to_phys_table[decode.id] <= speculative_rd_to_phys_table[spec_table_write_index];
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Renamed Outputs
|
||||
always_comb begin
|
||||
for (int i = 0; i < REGFILE_READ_PORTS; i++) begin
|
||||
decode.phys_rs_addr[i] = speculative_rd_to_phys_table[decode.rs_addr[i]];
|
||||
decode.rs_wb_group[i] = spec_wb_group[decode.rs_addr[i]];
|
||||
end
|
||||
end
|
||||
|
||||
assign decode.phys_rd_addr = rename_valid ? free_list.data_out : '0;
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
rename_rd_zero_assertion:
|
||||
assert property (@(posedge clk) disable iff (rst) (decode.rd_addr == 0) |-> (decode.phys_rd_addr == 0)) else $error("rd zero renamed");
|
||||
|
||||
for (genvar i = 0; i < REGFILE_READ_PORTS; i++) begin : rename_rs_zero_assertion
|
||||
assert property (@(posedge clk) disable iff (rst) (decode.rs_addr[i] == 0) |-> (decode.phys_rs_addr[i] == 0)) else $error("rs zero renamed");
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -51,9 +51,9 @@ module store_queue # (
|
|||
//Writeback snooping
|
||||
input wb_packet_t wb_snoop,
|
||||
|
||||
//Writeback release
|
||||
input id_t ids_released [COMMIT_PORTS],
|
||||
input wb_released [COMMIT_PORTS],
|
||||
//Retire
|
||||
input id_t retire_ids [RETIRE_PORTS],
|
||||
input logic retire_ids_retired [RETIRE_PORTS],
|
||||
|
||||
//lsq output
|
||||
output sq_entry_t sq_entry,
|
||||
|
@ -208,11 +208,13 @@ module store_queue # (
|
|||
////////////////////////////////////////////////////
|
||||
//Release Handling
|
||||
//Can be released on the same cycle the store arrives at the store queue
|
||||
//TODO: change to toggle memory
|
||||
logic [DEPTH-1:0] newly_released;
|
||||
always_comb begin
|
||||
for (int i = 0; i < DEPTH; i++) begin
|
||||
for (int j = 0; j < COMMIT_PORTS; j++) begin
|
||||
newly_released[i] = (ids[i] == ids_released[j]) & wb_released[j];
|
||||
newly_released[i] = 0;
|
||||
for (int j = 0; j < RETIRE_PORTS; j++) begin
|
||||
newly_released[i] |= (ids[i] == retire_ids[j]) & retire_ids_retired[j];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
552
core/taiga.sv
552
core/taiga.sv
|
@ -58,7 +58,7 @@ module taiga (
|
|||
ras_interface ras();
|
||||
|
||||
issue_packet_t issue;
|
||||
logic [31:0] rs_data [REGFILE_READ_PORTS];
|
||||
register_file_issue_interface rf_issue();
|
||||
|
||||
|
||||
alu_inputs_t alu_inputs;
|
||||
|
@ -69,7 +69,6 @@ module taiga (
|
|||
gc_inputs_t gc_inputs;
|
||||
|
||||
unit_issue_interface unit_issue [NUM_UNITS-1:0]();
|
||||
logic alu_issued;
|
||||
|
||||
exception_packet_t ls_exception;
|
||||
logic ls_exception_is_store;
|
||||
|
@ -99,28 +98,27 @@ module taiga (
|
|||
fetch_metadata_t fetch_metadata;
|
||||
//Decode stage
|
||||
logic decode_advance;
|
||||
decode_packet_t decode;
|
||||
//Issue stage
|
||||
id_t rs_id [REGFILE_READ_PORTS];
|
||||
logic rs_inuse [REGFILE_READ_PORTS];
|
||||
logic rs_id_inuse [REGFILE_READ_PORTS];
|
||||
decode_packet_t decode;
|
||||
logic decode_uses_rd;
|
||||
rs_addr_t decode_rd_addr;
|
||||
phys_addr_t decode_phys_rd_addr;
|
||||
//Branch predictor
|
||||
id_t branch_id;
|
||||
branch_metadata_t branch_metadata_if;
|
||||
branch_metadata_t branch_metadata_ex;
|
||||
//ID freeing
|
||||
logic store_complete;
|
||||
id_t store_id;
|
||||
logic branch_complete;
|
||||
id_t branch_id;
|
||||
logic system_op_or_exception_complete;
|
||||
logic exception_with_rd_complete;
|
||||
id_t system_op_or_exception_id;
|
||||
logic instruction_retired;
|
||||
logic [$clog2(MAX_COMPLETE_COUNT)-1:0] retire_inc;
|
||||
//Exception
|
||||
retire_packet_t retire;
|
||||
id_t retire_ids [RETIRE_PORTS];
|
||||
logic retire_ids_retired [RETIRE_PORTS];
|
||||
//Writeback
|
||||
wb_packet_t wb_packet [NUM_WB_GROUPS];
|
||||
commit_packet_t commit_packet [NUM_WB_GROUPS];
|
||||
//Exception
|
||||
id_t exception_id;
|
||||
logic [31:0] exception_pc;
|
||||
|
||||
renamer_interface decode_rename_interface ();
|
||||
|
||||
//Global Control
|
||||
logic gc_init_clear;
|
||||
logic gc_fetch_hold;
|
||||
|
@ -142,12 +140,6 @@ module taiga (
|
|||
//LS
|
||||
wb_packet_t wb_snoop;
|
||||
|
||||
//WB
|
||||
id_t ids_retiring [COMMIT_PORTS];
|
||||
logic retired [COMMIT_PORTS];
|
||||
logic [4:0] retired_rd_addr [COMMIT_PORTS];
|
||||
id_t id_for_rd [COMMIT_PORTS];
|
||||
|
||||
//Trace Interface Signals
|
||||
logic tr_early_branch_correction;
|
||||
logic tr_operand_stall;
|
||||
|
@ -195,13 +187,13 @@ module taiga (
|
|||
generate if (ENABLE_S_MODE || USE_ICACHE || USE_DCACHE)
|
||||
|
||||
l1_arbiter arb(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.l2 (l2),
|
||||
.sc_complete (sc_complete),
|
||||
.sc_success (sc_success),
|
||||
.l1_request (l1_request),
|
||||
.l1_response (l1_response)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.l2 (l2),
|
||||
.sc_complete (sc_complete),
|
||||
.sc_success (sc_success),
|
||||
.l1_request (l1_request),
|
||||
.l1_response (l1_response)
|
||||
);
|
||||
|
||||
endgenerate
|
||||
|
@ -209,109 +201,105 @@ module taiga (
|
|||
////////////////////////////////////////////////////
|
||||
// ID support
|
||||
instruction_metadata_and_id_management id_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.pc_id (pc_id),
|
||||
.pc_id_available (pc_id_available),
|
||||
.if_pc (if_pc),
|
||||
.pc_id_assigned (pc_id_assigned),
|
||||
.fetch_id (fetch_id),
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.pc_id (pc_id),
|
||||
.pc_id_available (pc_id_available),
|
||||
.if_pc (if_pc),
|
||||
.pc_id_assigned (pc_id_assigned),
|
||||
.fetch_id (fetch_id),
|
||||
.early_branch_flush (early_branch_flush),
|
||||
.fetch_complete (fetch_complete),
|
||||
.fetch_instruction (fetch_instruction),
|
||||
.fetch_metadata (fetch_metadata),
|
||||
.decode (decode),
|
||||
.decode_advance (decode_advance),
|
||||
.issue (issue),
|
||||
.instruction_issued (instruction_issued),
|
||||
.rs_id (rs_id),
|
||||
.rs_inuse (rs_inuse),
|
||||
.rs_id_inuse (rs_id_inuse),
|
||||
.branch_metadata_if (branch_metadata_if),
|
||||
.branch_metadata_ex (branch_metadata_ex),
|
||||
.store_complete (store_complete),
|
||||
.store_id (store_id),
|
||||
.branch_complete (branch_complete),
|
||||
.branch_id (branch_id),
|
||||
.system_op_or_exception_complete (system_op_or_exception_complete),
|
||||
.exception_with_rd_complete (exception_with_rd_complete),
|
||||
.system_op_or_exception_id (system_op_or_exception_id),
|
||||
.retire_inc (retire_inc),
|
||||
.ids_retiring (ids_retiring),
|
||||
.retired (retired),
|
||||
.retired_rd_addr (retired_rd_addr),
|
||||
.id_for_rd (id_for_rd),
|
||||
.exception_pc (exception_pc)
|
||||
.fetch_complete (fetch_complete),
|
||||
.fetch_instruction (fetch_instruction),
|
||||
.fetch_metadata (fetch_metadata),
|
||||
.decode (decode),
|
||||
.decode_advance (decode_advance),
|
||||
.decode_uses_rd (decode_uses_rd),
|
||||
.decode_rd_addr (decode_rd_addr),
|
||||
.decode_phys_rd_addr (decode_phys_rd_addr),
|
||||
.issue (issue),
|
||||
.instruction_issued (instruction_issued),
|
||||
.instruction_issued_with_rd (instruction_issued_with_rd),
|
||||
.branch_metadata_if (branch_metadata_if),
|
||||
.branch_metadata_ex (branch_metadata_ex),
|
||||
.branch_id (branch_id),
|
||||
.wb_packet (wb_packet),
|
||||
.commit_packet (commit_packet),
|
||||
.retire (retire),
|
||||
.retire_ids (retire_ids),
|
||||
.retire_ids_retired(retire_ids_retired),
|
||||
.exception_id (exception_id),
|
||||
.exception_pc (exception_pc)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Fetch
|
||||
fetch fetch_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.branch_flush (branch_flush),
|
||||
.gc_fetch_hold (gc_fetch_hold),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_fetch_pc_override (gc_fetch_pc_override),
|
||||
.gc_fetch_pc (gc_fetch_pc),
|
||||
.pc_id_available (pc_id_available),
|
||||
.pc_id_assigned (pc_id_assigned),
|
||||
.fetch_complete (fetch_complete),
|
||||
.fetch_metadata (fetch_metadata),
|
||||
.bp (bp),
|
||||
.ras (ras),
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.branch_flush (branch_flush),
|
||||
.gc_fetch_hold (gc_fetch_hold),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_fetch_pc_override (gc_fetch_pc_override),
|
||||
.gc_fetch_pc (gc_fetch_pc),
|
||||
.pc_id_available (pc_id_available),
|
||||
.pc_id_assigned (pc_id_assigned),
|
||||
.fetch_complete (fetch_complete),
|
||||
.fetch_metadata (fetch_metadata),
|
||||
.bp (bp),
|
||||
.ras (ras),
|
||||
.early_branch_flush (early_branch_flush),
|
||||
.early_branch_flush_ras_adjust (early_branch_flush_ras_adjust),
|
||||
.if_pc (if_pc),
|
||||
.fetch_instruction (fetch_instruction),
|
||||
.instruction_bram (instruction_bram),
|
||||
.icache_on('1),
|
||||
.tlb(itlb),
|
||||
.tlb_on (tlb_on),
|
||||
.l1_request(l1_request[L1_ICACHE_ID]),
|
||||
.l1_response(l1_response[L1_ICACHE_ID]),
|
||||
.exception(1'b0),
|
||||
.if_pc (if_pc),
|
||||
.fetch_instruction (fetch_instruction),
|
||||
.instruction_bram (instruction_bram),
|
||||
.icache_on ('1),
|
||||
.tlb (itlb),
|
||||
.tlb_on (tlb_on),
|
||||
.l1_request (l1_request[L1_ICACHE_ID]),
|
||||
.l1_response (l1_response[L1_ICACHE_ID]),
|
||||
.exception (1'b0),
|
||||
.tr_early_branch_correction (tr_early_branch_correction)
|
||||
);
|
||||
|
||||
branch_predictor bp_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.bp (bp),
|
||||
.branch_metadata_if (branch_metadata_if),
|
||||
.branch_metadata_ex (branch_metadata_ex),
|
||||
.br_results (br_results)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.bp (bp),
|
||||
.branch_metadata_if (branch_metadata_if),
|
||||
.branch_metadata_ex (branch_metadata_ex),
|
||||
.br_results (br_results)
|
||||
);
|
||||
|
||||
ras ras_block(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.early_branch_flush_ras_adjust (early_branch_flush_ras_adjust),
|
||||
.ras (ras)
|
||||
.ras (ras)
|
||||
);
|
||||
|
||||
generate if (ENABLE_S_MODE) begin
|
||||
|
||||
tlb_lut_ram #(ITLB_WAYS, ITLB_DEPTH) i_tlb (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.abort_request (gc_fetch_flush | early_branch_flush),
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.abort_request (gc_fetch_flush | early_branch_flush),
|
||||
.gc_tlb_flush (gc_tlb_flush),
|
||||
.asid (asid),
|
||||
.tlb (itlb),
|
||||
.mmu (immu)
|
||||
.asid (asid),
|
||||
.tlb (itlb),
|
||||
.mmu (immu)
|
||||
);
|
||||
|
||||
mmu i_mmu (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mmu (immu) ,
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mmu (immu) ,
|
||||
.abort_request (gc_fetch_flush),
|
||||
.l1_request (l1_request[L1_IMMU_ID]),
|
||||
.l1_response (l1_response[L1_IMMU_ID])
|
||||
.l1_request (l1_request[L1_IMMU_ID]),
|
||||
.l1_response (l1_response[L1_IMMU_ID])
|
||||
);
|
||||
|
||||
end
|
||||
|
@ -323,155 +311,155 @@ module taiga (
|
|||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Decode/Issue
|
||||
decode_and_issue decode_and_issue_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.pc_id_available (pc_id_available),
|
||||
.decode (decode),
|
||||
.decode_advance (decode_advance),
|
||||
.issue (issue),
|
||||
.rs_data (rs_data),
|
||||
.alu_inputs (alu_inputs),
|
||||
.ls_inputs (ls_inputs),
|
||||
.branch_inputs (branch_inputs),
|
||||
.gc_inputs (gc_inputs),
|
||||
.mul_inputs (mul_inputs),
|
||||
.div_inputs (div_inputs),
|
||||
.unit_issue (unit_issue),
|
||||
.potential_branch_exception (potential_branch_exception),
|
||||
.alu_issued (alu_issued),
|
||||
.gc_fetch_hold (gc_fetch_hold),
|
||||
.gc_issue_hold (gc_issue_hold),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_issue_flush (gc_issue_flush),
|
||||
.gc_flush_required (gc_flush_required),
|
||||
.rs_inuse (rs_inuse),
|
||||
.rs_id (rs_id),
|
||||
.rs_id_inuse (rs_id_inuse),
|
||||
.instruction_issued (instruction_issued),
|
||||
.instruction_issued_with_rd (instruction_issued_with_rd),
|
||||
.illegal_instruction (illegal_instruction),
|
||||
.tr_operand_stall (tr_operand_stall),
|
||||
.tr_unit_stall (tr_unit_stall),
|
||||
.tr_no_id_stall (tr_no_id_stall),
|
||||
.tr_no_instruction_stall (tr_no_instruction_stall),
|
||||
.tr_other_stall (tr_other_stall),
|
||||
.tr_branch_operand_stall (tr_branch_operand_stall),
|
||||
.tr_alu_operand_stall (tr_alu_operand_stall),
|
||||
.tr_ls_operand_stall (tr_ls_operand_stall),
|
||||
.tr_div_operand_stall (tr_div_operand_stall),
|
||||
.tr_alu_op (tr_alu_op),
|
||||
.tr_branch_or_jump_op (tr_branch_or_jump_op),
|
||||
.tr_load_op (tr_load_op),
|
||||
.tr_store_op (tr_store_op),
|
||||
.tr_mul_op (tr_mul_op),
|
||||
.tr_div_op (tr_div_op),
|
||||
.tr_misc_op (tr_misc_op),
|
||||
.tr_instruction_issued_dec (tr_instruction_issued_dec),
|
||||
.tr_instruction_pc_dec (tr_instruction_pc_dec),
|
||||
.tr_instruction_data_dec (tr_instruction_data_dec)
|
||||
//Renamer
|
||||
renamer renamer_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.decode_advance (decode_advance),
|
||||
.decode (decode_rename_interface),
|
||||
.issue (issue), //packet
|
||||
.retire (retire) //packet
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File and Writeback
|
||||
register_file_and_writeback register_file_and_writeback_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.issue (issue),
|
||||
//Decode/Issue
|
||||
decode_and_issue decode_and_issue_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.pc_id_available (pc_id_available),
|
||||
.decode (decode),
|
||||
.decode_advance (decode_advance),
|
||||
.renamer (decode_rename_interface),
|
||||
.decode_uses_rd (decode_uses_rd),
|
||||
.decode_rd_addr (decode_rd_addr),
|
||||
.decode_phys_rd_addr (decode_phys_rd_addr),
|
||||
.instruction_issued (instruction_issued),
|
||||
.instruction_issued_with_rd (instruction_issued_with_rd),
|
||||
.alu_issued (alu_issued),
|
||||
.rs_data (rs_data),
|
||||
.ids_retiring (ids_retiring),
|
||||
.retired (retired),
|
||||
.retired_rd_addr (retired_rd_addr),
|
||||
.id_for_rd (id_for_rd),
|
||||
.unit_wb (unit_wb),
|
||||
.wb_snoop (wb_snoop),
|
||||
.tr_rs1_forwarding_needed (tr_rs1_forwarding_needed),
|
||||
.tr_rs2_forwarding_needed (tr_rs2_forwarding_needed),
|
||||
.tr_rs1_and_rs2_forwarding_needed (tr_rs1_and_rs2_forwarding_needed)
|
||||
.issue (issue),
|
||||
.rf (rf_issue),
|
||||
.alu_inputs (alu_inputs),
|
||||
.ls_inputs (ls_inputs),
|
||||
.branch_inputs (branch_inputs),
|
||||
.gc_inputs (gc_inputs),
|
||||
.mul_inputs (mul_inputs),
|
||||
.div_inputs (div_inputs),
|
||||
.unit_issue (unit_issue),
|
||||
.gc_fetch_hold (gc_fetch_hold),
|
||||
.gc_issue_hold (gc_issue_hold),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_issue_flush (gc_issue_flush),
|
||||
.gc_flush_required (gc_flush_required),
|
||||
.illegal_instruction (illegal_instruction),
|
||||
.tr_operand_stall (tr_operand_stall),
|
||||
.tr_unit_stall (tr_unit_stall),
|
||||
.tr_no_id_stall (tr_no_id_stall),
|
||||
.tr_no_instruction_stall (tr_no_instruction_stall),
|
||||
.tr_other_stall (tr_other_stall),
|
||||
.tr_branch_operand_stall (tr_branch_operand_stall),
|
||||
.tr_alu_operand_stall (tr_alu_operand_stall),
|
||||
.tr_ls_operand_stall (tr_ls_operand_stall),
|
||||
.tr_div_operand_stall (tr_div_operand_stall),
|
||||
.tr_alu_op (tr_alu_op),
|
||||
.tr_branch_or_jump_op (tr_branch_or_jump_op),
|
||||
.tr_load_op (tr_load_op),
|
||||
.tr_store_op (tr_store_op),
|
||||
.tr_mul_op (tr_mul_op),
|
||||
.tr_div_op (tr_div_op),
|
||||
.tr_misc_op (tr_misc_op),
|
||||
.tr_instruction_issued_dec (tr_instruction_issued_dec),
|
||||
.tr_instruction_pc_dec (tr_instruction_pc_dec),
|
||||
.tr_instruction_data_dec (tr_instruction_data_dec)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File
|
||||
register_file register_file_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
.rf_issue (rf_issue),
|
||||
.commit (commit_packet)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Execution Units
|
||||
branch_unit branch_unit_block (
|
||||
.clk (clk ),
|
||||
.rst (rst ),
|
||||
.issue (unit_issue[BRANCH_UNIT_ID]),
|
||||
.branch_inputs (branch_inputs ),
|
||||
.br_results (br_results ),
|
||||
.ras (ras ),
|
||||
.branch_flush (branch_flush ),
|
||||
.branch_complete (branch_complete ),
|
||||
.branch_id (branch_id ),
|
||||
.branch_metadata_ex (branch_metadata_ex ),
|
||||
.potential_branch_exception (potential_branch_exception),
|
||||
.branch_exception_is_jump (branch_exception_is_jump ),
|
||||
.br_exception (br_exception ),
|
||||
.tr_branch_correct (tr_branch_correct ),
|
||||
.tr_branch_misspredict (tr_branch_misspredict ),
|
||||
.tr_return_correct (tr_return_correct ),
|
||||
.tr_return_misspredict (tr_return_misspredict )
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.issue (unit_issue[BRANCH_UNIT_ID]),
|
||||
.branch_inputs (branch_inputs),
|
||||
.br_results (br_results),
|
||||
.ras (ras),
|
||||
.branch_flush (branch_flush),
|
||||
.branch_id (branch_id),
|
||||
.branch_metadata_ex (branch_metadata_ex),
|
||||
.potential_branch_exception (potential_branch_exception),
|
||||
.branch_exception_is_jump (branch_exception_is_jump),
|
||||
.br_exception (br_exception),
|
||||
.tr_branch_correct (tr_branch_correct),
|
||||
.tr_branch_misspredict (tr_branch_misspredict),
|
||||
.tr_return_correct (tr_return_correct),
|
||||
.tr_return_misspredict (tr_return_misspredict)
|
||||
);
|
||||
|
||||
|
||||
alu_unit alu_unit_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.alu_inputs (alu_inputs),
|
||||
.issue (unit_issue[ALU_UNIT_ID]),
|
||||
.wb (unit_wb[ALU_UNIT_ID])
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.alu_inputs (alu_inputs),
|
||||
.issue (unit_issue[ALU_UNIT_ID]),
|
||||
.wb (unit_wb[ALU_UNIT_ID])
|
||||
);
|
||||
|
||||
load_store_unit load_store_unit_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.ls_inputs (ls_inputs),
|
||||
.issue (unit_issue[LS_UNIT_ID]),
|
||||
.dcache_on (1'b1),
|
||||
.clear_reservation (1'b0),
|
||||
.tlb (dtlb),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_issue_flush (gc_issue_flush),
|
||||
.tlb_on (tlb_on),
|
||||
.l1_request (l1_request[L1_DCACHE_ID]),
|
||||
.l1_response (l1_response[L1_DCACHE_ID]),
|
||||
.sc_complete (sc_complete),
|
||||
.sc_success (sc_success),
|
||||
.m_axi (m_axi),
|
||||
.m_avalon (m_avalon),
|
||||
.m_wishbone (m_wishbone),
|
||||
.data_bram (data_bram),
|
||||
.store_complete (store_complete),
|
||||
.store_id (store_id),
|
||||
.wb_snoop (wb_snoop),
|
||||
.ls_is_idle (ls_is_idle),
|
||||
.ls_exception (ls_exception),
|
||||
.ls_exception_is_store (ls_exception_is_store),
|
||||
.wb (unit_wb[LS_UNIT_ID]),
|
||||
.tr_load_conflict_delay (tr_load_conflict_delay)
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.ls_inputs (ls_inputs),
|
||||
.issue (unit_issue[LS_UNIT_ID]),
|
||||
.dcache_on (1'b1),
|
||||
.clear_reservation (1'b0),
|
||||
.tlb (dtlb),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_issue_flush (gc_issue_flush),
|
||||
.tlb_on (tlb_on),
|
||||
.l1_request (l1_request[L1_DCACHE_ID]),
|
||||
.l1_response (l1_response[L1_DCACHE_ID]),
|
||||
.sc_complete (sc_complete),
|
||||
.sc_success (sc_success),
|
||||
.m_axi (m_axi),
|
||||
.m_avalon (m_avalon),
|
||||
.m_wishbone (m_wishbone),
|
||||
.data_bram (data_bram),
|
||||
.wb_snoop (wb_snoop),
|
||||
.retire_ids (retire_ids),
|
||||
.retire_ids_retired(retire_ids_retired),
|
||||
.ls_is_idle (ls_is_idle),
|
||||
.ls_exception (ls_exception),
|
||||
.ls_exception_is_store (ls_exception_is_store),
|
||||
.wb (unit_wb[LS_UNIT_ID]),
|
||||
.tr_load_conflict_delay (tr_load_conflict_delay)
|
||||
);
|
||||
|
||||
generate if (ENABLE_S_MODE) begin
|
||||
|
||||
tlb_lut_ram #(DTLB_WAYS, DTLB_DEPTH) d_tlb (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.abort_request (1'b0),
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.abort_request (1'b0),
|
||||
.gc_tlb_flush (gc_tlb_flush),
|
||||
.asid (asid),
|
||||
.tlb (dtlb),
|
||||
.mmu (dmmu)
|
||||
.asid (asid),
|
||||
.tlb (dtlb),
|
||||
.mmu (dmmu)
|
||||
);
|
||||
|
||||
mmu d_mmu (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mmu (dmmu) ,
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mmu (dmmu) ,
|
||||
.abort_request (1'b0),
|
||||
.l1_request (l1_request[L1_DMMU_ID]),
|
||||
.l1_response (l1_response[L1_DMMU_ID])
|
||||
.l1_request (l1_request[L1_DMMU_ID]),
|
||||
.l1_response (l1_response[L1_DMMU_ID])
|
||||
);
|
||||
end
|
||||
else begin
|
||||
|
@ -480,69 +468,73 @@ module taiga (
|
|||
assign dtlb.physical_address = dtlb.virtual_address;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
gc_unit gc_unit_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.issue (unit_issue[GC_UNIT_ID]),
|
||||
.gc_inputs (gc_inputs),
|
||||
.gc_flush_required (gc_flush_required),
|
||||
.branch_flush (branch_flush),
|
||||
.potential_branch_exception (potential_branch_exception),
|
||||
.branch_exception_is_jump (branch_exception_is_jump),
|
||||
.br_exception (br_exception),
|
||||
.illegal_instruction (illegal_instruction),
|
||||
.ls_exception (ls_exception),
|
||||
.ls_exception_is_store (ls_exception_is_store),
|
||||
.tlb_on (tlb_on),
|
||||
.asid (asid),
|
||||
.immu (immu),
|
||||
.dmmu (dmmu),
|
||||
.system_op_or_exception_complete (system_op_or_exception_complete),
|
||||
.exception_with_rd_complete (exception_with_rd_complete),
|
||||
.system_op_or_exception_id (system_op_or_exception_id),
|
||||
.exception_pc (exception_pc),
|
||||
.retire_inc (retire_inc),
|
||||
.instruction_retired (instruction_retired),
|
||||
.interrupt (interrupt),
|
||||
.timer_interrupt (timer_interrupt),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
.gc_fetch_hold (gc_fetch_hold),
|
||||
.gc_issue_hold (gc_issue_hold),
|
||||
.gc_issue_flush (gc_issue_flush),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_fetch_pc_override (gc_fetch_pc_override),
|
||||
.gc_supress_writeback (gc_supress_writeback),
|
||||
.gc_tlb_flush (gc_tlb_flush),
|
||||
.gc_fetch_pc (gc_fetch_pc),
|
||||
.ls_is_idle (ls_is_idle),
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.issue (unit_issue[GC_UNIT_ID]),
|
||||
.gc_inputs (gc_inputs),
|
||||
.gc_flush_required (gc_flush_required),
|
||||
.branch_flush (branch_flush),
|
||||
.potential_branch_exception (potential_branch_exception),
|
||||
.branch_exception_is_jump (branch_exception_is_jump),
|
||||
.br_exception (br_exception),
|
||||
.illegal_instruction (illegal_instruction),
|
||||
.ls_exception (ls_exception),
|
||||
.ls_exception_is_store (ls_exception_is_store),
|
||||
.tlb_on (tlb_on),
|
||||
.asid (asid),
|
||||
.immu (immu),
|
||||
.dmmu (dmmu),
|
||||
.exception_id (exception_id),
|
||||
.exception_pc (exception_pc),
|
||||
.retire (retire),
|
||||
.interrupt (interrupt),
|
||||
.timer_interrupt (timer_interrupt),
|
||||
.gc_init_clear (gc_init_clear),
|
||||
.gc_fetch_hold (gc_fetch_hold),
|
||||
.gc_issue_hold (gc_issue_hold),
|
||||
.gc_issue_flush (gc_issue_flush),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.gc_fetch_pc_override (gc_fetch_pc_override),
|
||||
.gc_supress_writeback (gc_supress_writeback),
|
||||
.gc_tlb_flush (gc_tlb_flush),
|
||||
.gc_fetch_pc (gc_fetch_pc),
|
||||
.ls_is_idle (ls_is_idle),
|
||||
.wb (unit_wb[GC_UNIT_ID])
|
||||
);
|
||||
|
||||
generate if (USE_MUL)
|
||||
|
||||
mul_unit mul_unit_block (.*,
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mul_inputs (mul_inputs),
|
||||
.issue (unit_issue[MUL_UNIT_ID]),
|
||||
.wb (unit_wb[MUL_UNIT_ID])
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mul_inputs (mul_inputs),
|
||||
.issue (unit_issue[MUL_UNIT_ID]),
|
||||
.wb (unit_wb[MUL_UNIT_ID])
|
||||
);
|
||||
|
||||
endgenerate
|
||||
|
||||
generate if (USE_DIV)
|
||||
|
||||
div_unit div_unit_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.div_inputs (div_inputs),
|
||||
.issue (unit_issue[DIV_UNIT_ID]),
|
||||
.wb (unit_wb[DIV_UNIT_ID])
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.gc_fetch_flush (gc_fetch_flush),
|
||||
.div_inputs (div_inputs),
|
||||
.issue (unit_issue[DIV_UNIT_ID]),
|
||||
.wb (unit_wb[DIV_UNIT_ID])
|
||||
);
|
||||
|
||||
endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Writeback
|
||||
writeback writeback_block (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.wb_packet (wb_packet),
|
||||
.unit_wb (unit_wb),
|
||||
.wb_snoop (wb_snoop)
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -155,12 +155,12 @@ package taiga_config;
|
|||
////////////////////////////////////////////////////
|
||||
//ID limit
|
||||
//MAX_IDS restricted to a power of 2
|
||||
localparam MAX_IDS = 8; //8 sufficient for rv32im configs
|
||||
localparam MAX_IDS = 16; //8 sufficient for rv32im configs
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Number of commit ports
|
||||
localparam COMMIT_PORTS = 2; //min 2
|
||||
localparam REGFILE_READ_PORTS = 2; //min 2, for RS1 and RS2
|
||||
localparam RETIRE_PORTS = 2; //min 2. (Non-powers of two supported)
|
||||
localparam REGFILE_READ_PORTS = 2; //min 2, for RS1 and RS2. (Non-powers of two supported)
|
||||
typedef enum logic {
|
||||
RS1 = 0,
|
||||
RS2 = 1
|
||||
|
@ -180,7 +180,6 @@ package taiga_config;
|
|||
localparam L1_ICACHE_ID = 2;//ENABLE_S_MODE + USE_DCACHE;
|
||||
localparam L1_IMMU_ID = 3;//ENABLE_S_MODE + USE_DCACHE + USE_ICACHE;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Write-Back Unit IDs
|
||||
localparam NUM_WB_UNITS_GROUP_1 = 1;//ALU
|
||||
|
|
|
@ -24,10 +24,9 @@ package taiga_types;
|
|||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
|
||||
localparam MAX_COMPLETE_COUNT = 3 + COMMIT_PORTS; //Branch + Store + System + COMMIT_PORTS
|
||||
|
||||
localparam RETIRE_W = $clog2(RETIRE_PORTS);
|
||||
localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
|
||||
localparam LOG2_COMMIT_PORTS = $clog2(COMMIT_PORTS);
|
||||
localparam LOG2_COMMIT_PORTS = $clog2(NUM_WB_GROUPS);
|
||||
localparam LOG2_MAX_IDS = $clog2(MAX_IDS);
|
||||
|
||||
typedef logic[LOG2_MAX_IDS-1:0] id_t;
|
||||
|
@ -36,6 +35,7 @@ package taiga_types;
|
|||
|
||||
typedef logic [3:0] addr_hash_t;
|
||||
typedef logic [5:0] phys_addr_t;
|
||||
typedef logic [$clog2(NUM_WB_GROUPS)-1:0] rs_wb_group_t;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
ALU_LOGIC_XOR = 2'b00,
|
||||
|
@ -102,9 +102,12 @@ package taiga_types;
|
|||
logic [6:0] opcode;
|
||||
|
||||
rs_addr_t [REGFILE_READ_PORTS-1:0] rs_addr;
|
||||
phys_addr_t [REGFILE_READ_PORTS-1:0] rs_phys_addr;
|
||||
phys_addr_t [REGFILE_READ_PORTS-1:0] phys_rs_addr;
|
||||
rs_wb_group_t [REGFILE_READ_PORTS-1:0] rs_wb_group;
|
||||
|
||||
logic [4:0] rd_addr;
|
||||
rs_addr_t rd_addr;
|
||||
phys_addr_t phys_rd_addr;
|
||||
rs_wb_group_t rd_wb_group;
|
||||
|
||||
logic uses_rs1;
|
||||
logic uses_rs2;
|
||||
|
@ -234,12 +237,27 @@ package taiga_types;
|
|||
logic forwarded_store;
|
||||
} sq_entry_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:0] data;
|
||||
typedef struct packed{
|
||||
id_t id;
|
||||
logic valid;
|
||||
logic [31:0] data;
|
||||
} wb_packet_t;
|
||||
|
||||
typedef struct packed{
|
||||
id_t id;
|
||||
logic valid;
|
||||
phys_addr_t phys_addr;
|
||||
logic [31:0] data;
|
||||
} commit_packet_t;
|
||||
|
||||
typedef struct packed{
|
||||
logic valid;
|
||||
id_t phys_id;
|
||||
phys_addr_t phys_addr;
|
||||
rs_addr_t rd_addr;
|
||||
logic [RETIRE_W : 0] count;
|
||||
} retire_packet_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [31:0] addr;
|
||||
logic load;
|
||||
|
|
107
core/register_file_and_writeback.sv → core/writeback.sv
Executable file → Normal file
107
core/register_file_and_writeback.sv → core/writeback.sv
Executable file → Normal file
|
@ -20,55 +20,31 @@
|
|||
* Eric Matthews <ematthew@sfu.ca>
|
||||
*/
|
||||
|
||||
module register_file_and_writeback
|
||||
module writeback
|
||||
import taiga_config::*;
|
||||
import riscv_types::*;
|
||||
import taiga_types::*;
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
//Issue interface
|
||||
input issue_packet_t issue,
|
||||
input logic instruction_issued_with_rd,
|
||||
input logic alu_issued,
|
||||
output logic [31:0] rs_data [REGFILE_READ_PORTS],
|
||||
//ID Metadata
|
||||
output id_t ids_retiring [COMMIT_PORTS],
|
||||
output logic retired [COMMIT_PORTS],
|
||||
input logic [4:0] retired_rd_addr [COMMIT_PORTS],
|
||||
input id_t id_for_rd [COMMIT_PORTS],
|
||||
//Writeback
|
||||
//Unit writeback
|
||||
unit_writeback_interface.wb unit_wb[NUM_WB_UNITS],
|
||||
output wb_packet_t wb_snoop,
|
||||
|
||||
//Trace signals
|
||||
output logic tr_rs1_forwarding_needed,
|
||||
output logic tr_rs2_forwarding_needed,
|
||||
output logic tr_rs1_and_rs2_forwarding_needed
|
||||
//WB output
|
||||
output wb_packet_t wb_packet [NUM_WB_GROUPS],
|
||||
//Snoop interface (LS unit)
|
||||
output wb_packet_t wb_snoop
|
||||
);
|
||||
|
||||
//Register File
|
||||
typedef logic [XLEN-1:0] register_file_t [32];
|
||||
register_file_t register_file [COMMIT_PORTS];
|
||||
logic [LOG2_COMMIT_PORTS-1:0] rs_sel [REGFILE_READ_PORTS];
|
||||
|
||||
//Writeback
|
||||
logic alu_selected;
|
||||
logic [NUM_WB_UNITS-1:0] unit_ack [NUM_WB_GROUPS];
|
||||
//aliases for write-back-interface signals
|
||||
id_t [NUM_WB_UNITS-1:0] unit_instruction_id [NUM_WB_GROUPS];
|
||||
logic [NUM_WB_UNITS-1:0] unit_done [NUM_WB_GROUPS];
|
||||
|
||||
|
||||
typedef logic [XLEN-1:0] unit_rd_t [NUM_WB_UNITS];
|
||||
unit_rd_t unit_rd [NUM_WB_GROUPS];
|
||||
//Per-ID muxes for commit buffer
|
||||
logic [$clog2(NUM_WB_UNITS)-1:0] retiring_unit_select [NUM_WB_GROUPS];
|
||||
logic [31:0] retiring_data [NUM_WB_GROUPS];
|
||||
|
||||
typedef logic [31:0] rs_data_set_t [REGFILE_READ_PORTS];
|
||||
rs_data_set_t rs_data_set [NUM_WB_GROUPS];
|
||||
logic [$clog2(NUM_WB_UNITS)-1:0] unit_sel [NUM_WB_GROUPS];
|
||||
|
||||
genvar i, j;
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -87,14 +63,13 @@ module register_file_and_writeback
|
|||
//As units are selected for commit ports based on their unit ID,
|
||||
//for each additional commit port one unit can be skipped for the commit mux
|
||||
generate
|
||||
for (i = 0; i < NUM_WB_GROUPS; i++) begin : wb_rd_mux_gen
|
||||
for (i = 0; i < NUM_WB_GROUPS; i++) begin
|
||||
for (j = 0; j < NUM_WB_UNITS_GROUP[i]; j++) begin
|
||||
assign unit_rd[i][j] = unit_wb[CUMULATIVE_NUM_WB_UNITS_GROUP[i] + j].rd;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit select for register file
|
||||
//Iterating through all commit ports:
|
||||
|
@ -103,73 +78,37 @@ module register_file_and_writeback
|
|||
always_comb begin
|
||||
for (int i = 0; i < NUM_WB_GROUPS; i++) begin
|
||||
unit_ack[i] = '{default: 0};
|
||||
retired[i] = 0;
|
||||
retiring_unit_select[i] = WB_UNITS_WIDTH'(NUM_WB_UNITS_GROUP[i]-1);
|
||||
wb_packet[i].valid = 0;
|
||||
unit_sel[i] = WB_UNITS_WIDTH'(NUM_WB_UNITS_GROUP[i]-1);
|
||||
for (int j = 0; j < (NUM_WB_UNITS_GROUP[i] - 1); j++) begin
|
||||
if (unit_done[i][j]) begin
|
||||
retiring_unit_select[i] = WB_UNITS_WIDTH'(j);
|
||||
unit_sel[i] = WB_UNITS_WIDTH'(j);
|
||||
break;
|
||||
end
|
||||
end
|
||||
//ID and data muxes
|
||||
retired[i] = unit_done[i][retiring_unit_select[i]];
|
||||
ids_retiring[i] = unit_instruction_id[i][retiring_unit_select[i]];
|
||||
retiring_data[i] = unit_rd[i][retiring_unit_select[i]];
|
||||
unit_ack[i][retiring_unit_select[i]] = retired[i];
|
||||
end
|
||||
|
||||
retired[0] = alu_issued;
|
||||
unit_ack[0][retiring_unit_select[0]] = retired[0];
|
||||
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register Files
|
||||
//Implemented in seperate module as there is not universal tool support for inferring
|
||||
//arrays of memory blocks.
|
||||
generate for (i = 0; i < COMMIT_PORTS; i++) begin
|
||||
register_file #(.NUM_READ_PORTS(REGFILE_READ_PORTS)) register_file_blocks (
|
||||
.clk, .rst,
|
||||
.write_addr({1'b0, retired_rd_addr[i]}),
|
||||
.new_data(retiring_data[i]),
|
||||
.commit(retired[i] & (|retired_rd_addr[i])),
|
||||
.read_addr(issue.rs_phys_addr),
|
||||
.data(rs_data_set[i])
|
||||
);
|
||||
end endgenerate
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File LVT
|
||||
logic [$clog2(COMMIT_PORTS)-1:0] bank_sel [32];
|
||||
always_ff @ (posedge clk) begin
|
||||
if (instruction_issued_with_rd)
|
||||
bank_sel[issue.rd_addr] <= ~alu_issued;
|
||||
end
|
||||
always_comb begin
|
||||
for (int i = 0; i < REGFILE_READ_PORTS; i++) begin
|
||||
rs_sel[i] = bank_sel[issue.rs_addr[i]];
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Register File Muxing
|
||||
always_comb begin
|
||||
for (int i = 0; i < REGFILE_READ_PORTS; i++) begin
|
||||
rs_data[i] = rs_data_set[rs_sel[i]][i];
|
||||
end
|
||||
wb_packet[i].valid = unit_done[i][unit_sel[i]];
|
||||
wb_packet[i].id = unit_instruction_id[i][unit_sel[i]];
|
||||
wb_packet[i].data = unit_rd[i][unit_sel[i]];
|
||||
unit_ack[i][unit_sel[i]] = wb_packet[i].valid;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Store Forwarding Support
|
||||
//TODO: support additional writeback groups
|
||||
//currently limited to one writeback group with the
|
||||
//assumption that writeback group zero has single-cycle
|
||||
//operation
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
wb_snoop.valid <= 0;
|
||||
else
|
||||
wb_snoop.valid <= retired[1];
|
||||
wb_snoop.valid <= wb_packet[1].valid;
|
||||
end
|
||||
always_ff @ (posedge clk) begin
|
||||
wb_snoop.data <= retiring_data[1];
|
||||
wb_snoop.id <= ids_retiring[1];
|
||||
wb_snoop.data <= wb_packet[1].data;
|
||||
wb_snoop.id <= wb_packet[1].id;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
|
@ -88,9 +88,11 @@ core/fetch.sv
|
|||
core/illegal_instruction_checker.sv
|
||||
core/decode_and_issue.sv
|
||||
|
||||
core/regfile_bank_sel.sv
|
||||
core/register_free_list.sv
|
||||
core/renamer.sv
|
||||
core/register_bank.sv
|
||||
core/register_file.sv
|
||||
core/register_file_and_writeback.sv
|
||||
core/writeback.sv
|
||||
|
||||
core/placer_randomizer.sv
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue