mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-20 03:57:18 -04:00
Now always in-order commit
This commit is contained in:
parent
7bd80c1f1c
commit
c0727257f4
19 changed files with 297 additions and 367 deletions
|
@ -92,7 +92,8 @@ module alu_unit(
|
|||
assign wb.rd = rd_bank[wb.writeback_instruction_id];
|
||||
assign wb.rs1_data = rd_bank[wb.writeback_rs1_id];
|
||||
assign wb.rs2_data = rd_bank[wb.writeback_rs2_id];
|
||||
assign wb.done_next_cycle = issue.instruction_id_one_hot & {MAX_INFLIGHT_COUNT{issue.new_request}};
|
||||
assign wb.done_next_cycle = issue.new_request;
|
||||
assign wb.id = issue.instruction_id;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
|
|
|
@ -78,6 +78,7 @@ module decode(
|
|||
logic [4:0] rs1_addr;
|
||||
logic [4:0] rs2_addr;
|
||||
logic [4:0] future_rd_addr;
|
||||
unit_id_t unit_id;
|
||||
|
||||
logic nop;
|
||||
|
||||
|
@ -130,23 +131,27 @@ module decode(
|
|||
assign rf_decode.future_rd_addr = future_rd_addr;
|
||||
assign rf_decode.instruction_issued = instruction_issued_with_rd & ~rd_zero;
|
||||
assign rf_decode.id = ti.issue_id;
|
||||
assign rf_decode.unit_id = unit_id;
|
||||
assign rf_decode.uses_rs1 = uses_rs1;
|
||||
assign rf_decode.uses_rs2 = uses_rs2;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Tracking Interface
|
||||
//assign ti.inflight_packet.unit_id = new_request;
|
||||
assign ti.inflight_packet.rd_addr = future_rd_addr;
|
||||
assign ti.inflight_packet.rd_addr_nzero = ~rd_zero;
|
||||
assign ti.issued = instruction_issued & (uses_rd | new_request[LS_UNIT_WB_ID]);
|
||||
|
||||
always_comb begin
|
||||
new_request_for_id_gen = new_request[NUM_WB_UNITS-1:0];
|
||||
new_request_for_id_gen[LS_UNIT_WB_ID] |= new_request[GC_UNIT_ID];
|
||||
end
|
||||
|
||||
one_hot_to_integer #(NUM_WB_UNITS) new_request_to_int (.*, .one_hot(new_request_for_id_gen), .int_out(ti.inflight_packet.unit_id));
|
||||
one_hot_to_integer #(NUM_WB_UNITS) new_request_to_int (.*, .one_hot(new_request_for_id_gen), .int_out(unit_id));
|
||||
|
||||
assign ti.inflight_packet.rd_addr = future_rd_addr;
|
||||
assign ti.inflight_packet.rd_addr_nzero = ~rd_zero;
|
||||
assign ti.inflight_packet.is_store = (opcode_trim == STORE_T) || (amo_op && store_conditional);
|
||||
assign ti.inflight_packet.id = ti.issue_id;
|
||||
assign ti.inflight_packet.unit_id = unit_id;
|
||||
assign ti.issued = instruction_issued & (uses_rd | new_request[LS_UNIT_WB_ID]);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Unit Determination
|
||||
assign mult_div_op = fb.instruction[25];
|
||||
|
@ -267,7 +272,6 @@ module decode(
|
|||
assign ls_inputs.load = ls_is_load;
|
||||
assign ls_inputs.store = (opcode_trim == STORE_T) || (amo_op && store_conditional);
|
||||
assign ls_inputs.load_store_forward = rf_decode.rs2_conflict;
|
||||
assign ls_inputs.instruction_id_one_hot = ti.issue_id_one_hot;
|
||||
assign ls_inputs.instruction_id = ti.issue_id;
|
||||
|
||||
//Last store RD tracking for Load-Store data forwarding
|
||||
|
@ -385,7 +389,6 @@ module decode(
|
|||
assign div_inputs.rs2 = rf_decode.rs2_data;
|
||||
assign div_inputs.op = fn3[1:0];
|
||||
assign div_inputs.reuse_result = prev_div_result_valid_r & current_op_resuses_rs1_rs2;
|
||||
assign div_inputs.instruction_id_one_hot = ti.issue_id_one_hot;
|
||||
assign div_inputs.instruction_id = ti.issue_id;
|
||||
end
|
||||
endgenerate
|
||||
|
@ -398,7 +401,6 @@ module decode(
|
|||
assign unit_issue[i].possible_issue = new_request[i] & ti.id_available;
|
||||
assign unit_issue[i].new_request = issue[i];
|
||||
assign unit_issue[i].instruction_id = ti.issue_id;
|
||||
assign unit_issue[i].instruction_id_one_hot = ti.issue_id_one_hot;
|
||||
always_ff @(posedge clk) begin
|
||||
unit_issue[i].new_request_r <= issue[i];
|
||||
end
|
||||
|
|
|
@ -123,11 +123,11 @@ module div_unit
|
|||
rd_bank[stage1.instruction_id] <= wb_div_result;
|
||||
end
|
||||
|
||||
assign wb.done_next_cycle = stage1.instruction_id_one_hot & {MAX_INFLIGHT_COUNT{div_done}};
|
||||
assign wb.rd = rd_bank[wb.writeback_instruction_id];
|
||||
assign wb.rs1_data = rd_bank[wb.writeback_rs1_id];
|
||||
assign wb.rs2_data = rd_bank[wb.writeback_rs2_id];
|
||||
|
||||
assign wb.done_next_cycle = div_done;
|
||||
assign wb.id = stage1.instruction_id;
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
|
||||
|
|
|
@ -40,8 +40,6 @@ module gc_unit(
|
|||
//Load Store Unit
|
||||
input exception_packet_t ls_exception,
|
||||
input logic ls_exception_valid,
|
||||
input logic load_store_issue,
|
||||
input logic load_store_FIFO_emptying,
|
||||
|
||||
//TLBs
|
||||
output logic tlb_on,
|
||||
|
@ -68,7 +66,6 @@ module gc_unit(
|
|||
output logic gc_fetch_pc_override,
|
||||
output logic gc_supress_writeback,
|
||||
|
||||
output logic inorder,
|
||||
output logic inuse_clear,
|
||||
|
||||
output logic [31:0] gc_fetch_pc,
|
||||
|
@ -76,7 +73,6 @@ module gc_unit(
|
|||
//Write-back to Load-Store Unit
|
||||
output logic[31:0] csr_rd,
|
||||
output instruction_id_t csr_id,
|
||||
output instruction_id_one_hot_t csr_id_done,
|
||||
output logic csr_done
|
||||
);
|
||||
|
||||
|
@ -132,7 +128,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, PRE_CLEAR_STATE, CLEAR_STATE, IDLE_STATE, TLB_CLEAR_STATE, LS_EXCEPTION_POSSIBLE, IQ_DRAIN, IQ_DISCARD} gc_state;
|
||||
typedef enum {RST_STATE, PRE_CLEAR_STATE, CLEAR_STATE, IDLE_STATE, TLB_CLEAR_STATE, IQ_DRAIN, IQ_DISCARD} gc_state;
|
||||
gc_state state;
|
||||
gc_state next_state;
|
||||
|
||||
|
@ -168,7 +164,6 @@ module gc_unit(
|
|||
logic processing_csr;
|
||||
logic csr_ready_to_complete;
|
||||
logic csr_ready_to_complete_r;
|
||||
instruction_id_one_hot_t id;
|
||||
instruction_id_t instruction_id;
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -189,7 +184,6 @@ module gc_unit(
|
|||
always_ff @ (posedge clk) begin
|
||||
gc_issue_hold <= issue.new_request || is_csr || processing_csr || (next_state inside {PRE_CLEAR_STATE, CLEAR_STATE, TLB_CLEAR_STATE, IQ_DRAIN, IQ_DISCARD});
|
||||
inuse_clear <= (next_state == CLEAR_STATE);
|
||||
inorder <= 0;//(next_state inside {LS_EXCEPTION_POSSIBLE, IQ_DRAIN});
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
|
@ -209,26 +203,14 @@ module gc_unit(
|
|||
state <= next_state;
|
||||
end
|
||||
|
||||
gc_state ls_exception_next_state;
|
||||
always_comb begin
|
||||
ls_exception_next_state = state;
|
||||
if (load_store_FIFO_emptying)
|
||||
ls_exception_next_state = IDLE_STATE;
|
||||
else if (ls_exception_valid) begin
|
||||
if (ls_exception.id == oldest_id)
|
||||
ls_exception_next_state = IQ_DISCARD;
|
||||
else
|
||||
ls_exception_next_state = IQ_DRAIN;
|
||||
end
|
||||
|
||||
next_state = state;
|
||||
case (state)
|
||||
RST_STATE : next_state = PRE_CLEAR_STATE;
|
||||
PRE_CLEAR_STATE : next_state = CLEAR_STATE;
|
||||
CLEAR_STATE : if (clear_done) next_state = IDLE_STATE;
|
||||
IDLE_STATE : if (load_store_issue) next_state = LS_EXCEPTION_POSSIBLE;
|
||||
IDLE_STATE : if (ls_exception_valid) next_state = IQ_DISCARD;
|
||||
TLB_CLEAR_STATE : if (tlb_clear_done) next_state = IDLE_STATE;
|
||||
LS_EXCEPTION_POSSIBLE : next_state = ls_exception_next_state;
|
||||
IQ_DRAIN : if (ls_exception.id == oldest_id) next_state = IQ_DISCARD;
|
||||
IQ_DISCARD : if (instruction_queue_empty) next_state = IDLE_STATE;
|
||||
default : next_state = RST_STATE;
|
||||
|
@ -244,7 +226,7 @@ module gc_unit(
|
|||
logic ls_exception_first_cycle;
|
||||
logic ls_exception_second_cycle;
|
||||
|
||||
assign ls_exception_first_cycle = ls_exception_valid && (state == LS_EXCEPTION_POSSIBLE);
|
||||
assign ls_exception_first_cycle = ls_exception_valid;
|
||||
always_ff @ (posedge clk) begin
|
||||
ls_exception_second_cycle <= ls_exception_first_cycle;
|
||||
end
|
||||
|
@ -303,10 +285,8 @@ module gc_unit(
|
|||
assign csr_ready_to_complete = (is_csr | processing_csr) && (oldest_id == csr_id);
|
||||
always_ff @(posedge clk) begin
|
||||
csr_ready_to_complete_r <= csr_ready_to_complete;
|
||||
csr_id_done <= id & {MAX_INFLIGHT_COUNT{csr_ready_to_complete}};
|
||||
csr_id <= instruction_id;
|
||||
if (issue.new_request) begin
|
||||
id <= issue.instruction_id_one_hot;
|
||||
instruction_id <= issue.instruction_id;
|
||||
end
|
||||
end
|
||||
|
|
141
core/id_stack.sv
141
core/id_stack.sv
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* Copyright © 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>
|
||||
*/
|
||||
|
||||
module id_stack # (
|
||||
parameter STACK_DEPTH = 4
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
input logic issued,
|
||||
input logic retired,
|
||||
input logic store_committed,
|
||||
input instruction_id_t store_id,
|
||||
input logic [STACK_DEPTH-1:0] id_done_ordered,
|
||||
input instruction_id_t retired_id,
|
||||
output logic [$clog2(STACK_DEPTH)-1:0] ordering [STACK_DEPTH-1:0],
|
||||
output logic [$clog2(STACK_DEPTH)-1:0] ordering_post_store [STACK_DEPTH-1:0],
|
||||
output logic id_available,
|
||||
output logic [$clog2(STACK_DEPTH)-1:0] next_id,
|
||||
output logic empty
|
||||
);
|
||||
//////////////////////////////////////////
|
||||
localparam STACK_DEPTH_W = $clog2(STACK_DEPTH);
|
||||
|
||||
logic [STACK_DEPTH_W-1:0] stack [STACK_DEPTH-1:0];
|
||||
logic [STACK_DEPTH_W-1:0] new_stack [STACK_DEPTH-1:0];
|
||||
logic [STACK_DEPTH_W-1:0] store_shiffted_stack_input [STACK_DEPTH-1:0];
|
||||
logic [STACK_DEPTH_W-1:0] store_shiffted_stack [STACK_DEPTH-1:0];
|
||||
logic [STACK_DEPTH_W-1:0] retired_store_shiffted_stack [STACK_DEPTH-1:0];
|
||||
|
||||
logic [STACK_DEPTH-1:0] store_done_ordered;
|
||||
|
||||
logic [STACK_DEPTH-1:0] store_shift_bits;
|
||||
logic [STACK_DEPTH-1:0] retired_shift_bits;
|
||||
|
||||
logic [STACK_DEPTH_W:0] next_id_index;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
//Initial ordering, stack has no reset, as ID ordering is arbitrary
|
||||
initial begin
|
||||
for (int i=0; i<STACK_DEPTH; i++) begin
|
||||
stack[i] = i[STACK_DEPTH_W-1:0];
|
||||
end
|
||||
end
|
||||
|
||||
//TODO inorder support
|
||||
generate begin
|
||||
genvar i;
|
||||
assign store_shift_bits[0] = 1;
|
||||
assign retired_shift_bits[0] = 1;
|
||||
for (i=1; i<STACK_DEPTH; i++) begin
|
||||
assign store_shift_bits[i] = |store_done_ordered[STACK_DEPTH-1:i];
|
||||
assign retired_shift_bits[i] = |id_done_ordered[STACK_DEPTH-1:i];
|
||||
end
|
||||
end endgenerate
|
||||
|
||||
always_comb begin
|
||||
//Lowest entry always shifted, each older entry shifts all below
|
||||
for (int i=0; i<STACK_DEPTH; i++) begin
|
||||
store_done_ordered[i] = (stack[i] == store_id);
|
||||
end
|
||||
|
||||
//Stack shift due to stores being popped
|
||||
store_shiffted_stack_input[STACK_DEPTH-1:1] = stack[STACK_DEPTH-2:0];
|
||||
store_shiffted_stack_input[0] = store_id;
|
||||
foreach (store_shiffted_stack[i]) begin
|
||||
store_shiffted_stack[i] = (store_committed & store_shift_bits[i]) ? store_shiffted_stack_input[i] : stack[i];
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
//Stack shift due to writes to register file being popped
|
||||
retired_store_shiffted_stack[STACK_DEPTH-1:1] = store_shiffted_stack[STACK_DEPTH-2:0];
|
||||
retired_store_shiffted_stack[0] = retired_id;
|
||||
foreach (new_stack[i]) begin
|
||||
new_stack[i] = (retired & retired_shift_bits[i]) ? retired_store_shiffted_stack[i] : store_shiffted_stack[i];
|
||||
end
|
||||
end
|
||||
|
||||
//Starts at oldest entry (STACK_DEPTH-1).
|
||||
//When entry 0 is issued, id_available will become zero
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
next_id_index <= '1;
|
||||
else
|
||||
next_id_index <= next_id_index + STACK_DEPTH_W'(retired) + STACK_DEPTH_W'(store_committed) - STACK_DEPTH_W'(issued);
|
||||
end
|
||||
|
||||
assign next_id = stack[next_id_index[STACK_DEPTH_W-1:0]];
|
||||
|
||||
assign id_available = next_id_index[STACK_DEPTH_W];
|
||||
assign empty = &next_id_index;//all ones
|
||||
|
||||
//Shift bits computed in parallel to retired_id in write-back
|
||||
always_ff @ (posedge clk) begin
|
||||
stack <= new_stack;
|
||||
end
|
||||
|
||||
assign ordering = stack;
|
||||
assign ordering_post_store = store_shiffted_stack;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
logic entries_different = 1;
|
||||
always_comb begin
|
||||
for (int i=0; i < STACK_DEPTH_W; i++) begin
|
||||
for (int j = i+1; j < STACK_DEPTH_W; j++) begin
|
||||
if (stack[i] == stack[j])
|
||||
entries_different = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
assert (1'b0) else $display("ID stack corrupted");
|
||||
end
|
||||
endmodule
|
114
core/id_tracking.sv
Normal file
114
core/id_tracking.sv
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright © 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 taiga_types::*;
|
||||
|
||||
module id_tracking
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
input logic issued,
|
||||
input logic retired,
|
||||
output logic id_available,
|
||||
output instruction_id_t oldest_id,
|
||||
output instruction_id_t next_id,
|
||||
output logic empty
|
||||
);
|
||||
//////////////////////////////////////////
|
||||
|
||||
localparam MAX_INFLIGHT_COUNT_W = $clog2(MAX_INFLIGHT_COUNT+1);
|
||||
|
||||
logic [MAX_INFLIGHT_COUNT_W-1:0] in_use_index;
|
||||
logic [MAX_INFLIGHT_COUNT_W-1:0] available_index;
|
||||
|
||||
instruction_id_t in_use_ids [MAX_INFLIGHT_COUNT-1:0];
|
||||
instruction_id_t available_ids [MAX_INFLIGHT_COUNT-1:0];
|
||||
genvar i;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
//Initial ordering, FIFO has no reset, as ID ordering is arbitrary
|
||||
initial begin
|
||||
for (int i=0; i<MAX_INFLIGHT_COUNT; i++) begin
|
||||
available_ids[i] = i[$clog2(MAX_INFLIGHT_COUNT)-1:0];
|
||||
end
|
||||
end
|
||||
|
||||
//On first write will roll over to [1,00...0]
|
||||
//Upper bit indicates is the valid signal
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
in_use_index[MAX_INFLIGHT_COUNT_W-1] <= 0;
|
||||
in_use_index[MAX_INFLIGHT_COUNT_W-2:0] <= '1;
|
||||
end else
|
||||
in_use_index <= in_use_index + MAX_INFLIGHT_COUNT_W'(issued) - MAX_INFLIGHT_COUNT_W'(retired);
|
||||
end
|
||||
|
||||
//Available FIFO starts full
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
available_index[MAX_INFLIGHT_COUNT_W-1:0] <= '1;
|
||||
else
|
||||
available_index <= available_index + MAX_INFLIGHT_COUNT_W'(retired) - MAX_INFLIGHT_COUNT_W'(issued);
|
||||
end
|
||||
|
||||
assign empty = ~in_use_index[MAX_INFLIGHT_COUNT_W-1];
|
||||
assign id_available = available_index[MAX_INFLIGHT_COUNT_W-1];
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (issued)
|
||||
in_use_ids[0] <= next_id;
|
||||
end
|
||||
|
||||
generate
|
||||
for (i=1 ; i < MAX_INFLIGHT_COUNT; i++) begin
|
||||
always_ff @ (posedge clk) begin
|
||||
if (issued)
|
||||
in_use_ids[i] <= in_use_ids[i-1];
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (retired)
|
||||
available_ids[0] <= oldest_id;
|
||||
end
|
||||
|
||||
generate
|
||||
for (i=1 ; i < MAX_INFLIGHT_COUNT; i++) begin
|
||||
always_ff @ (posedge clk) begin
|
||||
if (retired)
|
||||
available_ids[i] <= available_ids[i-1];
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign next_id = available_ids[available_index[MAX_INFLIGHT_COUNT_W-2:0]];
|
||||
assign oldest_id = in_use_ids[in_use_index[MAX_INFLIGHT_COUNT_W-2:0]];
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
endmodule
|
|
@ -54,12 +54,11 @@ interface unit_issue_interface;
|
|||
logic new_request;
|
||||
logic new_request_r;
|
||||
instruction_id_t instruction_id;
|
||||
instruction_id_one_hot_t instruction_id_one_hot;
|
||||
|
||||
logic ready;
|
||||
|
||||
modport decode (input ready, output possible_issue, new_request, new_request_r, instruction_id, instruction_id_one_hot);
|
||||
modport unit (output ready, input possible_issue, new_request, new_request_r, instruction_id, instruction_id_one_hot);
|
||||
modport decode (input ready, output possible_issue, new_request, new_request_r, instruction_id);
|
||||
modport unit (output ready, input possible_issue, new_request, new_request_r, instruction_id);
|
||||
endinterface
|
||||
|
||||
interface ras_interface;
|
||||
|
@ -76,7 +75,8 @@ endinterface
|
|||
|
||||
interface unit_writeback_interface;
|
||||
//unit output
|
||||
instruction_id_one_hot_t done_next_cycle;
|
||||
instruction_id_t id;
|
||||
logic done_next_cycle;
|
||||
logic [XLEN-1:0] rd;
|
||||
logic [XLEN-1:0] rs1_data;
|
||||
logic [XLEN-1:0] rs2_data;
|
||||
|
@ -85,8 +85,8 @@ interface unit_writeback_interface;
|
|||
instruction_id_t writeback_instruction_id;
|
||||
instruction_id_t writeback_rs1_id;
|
||||
instruction_id_t writeback_rs2_id;
|
||||
modport writeback (input done_next_cycle, rd, rs1_data, rs2_data, output accepted, writeback_instruction_id, writeback_rs1_id, writeback_rs2_id);
|
||||
modport unit (output done_next_cycle, rd, rs1_data, rs2_data, input accepted, writeback_instruction_id, writeback_rs1_id, writeback_rs2_id);
|
||||
modport writeback (input id, done_next_cycle, rd, rs1_data, rs2_data, output accepted, writeback_instruction_id, writeback_rs1_id, writeback_rs2_id);
|
||||
modport unit (output id, done_next_cycle, rd, rs1_data, rs2_data, input accepted, writeback_instruction_id, writeback_rs1_id, writeback_rs2_id);
|
||||
endinterface
|
||||
|
||||
//********************************
|
||||
|
@ -125,14 +125,16 @@ interface register_file_decode_interface;
|
|||
logic[4:0] rs2_addr; //if not used required to be zero
|
||||
logic[XLEN-1:0] rs2_data;
|
||||
instruction_id_t id;
|
||||
unit_id_t unit_id;
|
||||
|
||||
logic uses_rs1;
|
||||
logic uses_rs2;
|
||||
logic rs1_conflict;
|
||||
logic rs2_conflict;
|
||||
logic instruction_issued;
|
||||
|
||||
modport decode (output future_rd_addr, rs1_addr, rs2_addr, instruction_issued, id, uses_rs1, uses_rs2, input rs1_conflict, rs2_conflict, rs1_data, rs2_data);
|
||||
modport unit (input future_rd_addr, rs1_addr, rs2_addr, instruction_issued, id, uses_rs1, uses_rs2, output rs1_conflict, rs2_conflict, rs1_data, rs2_data);
|
||||
modport decode (output future_rd_addr, rs1_addr, rs2_addr, instruction_issued, id, unit_id, uses_rs1, uses_rs2, input rs1_conflict, rs2_conflict, rs1_data, rs2_data);
|
||||
modport unit (input future_rd_addr, rs1_addr, rs2_addr, instruction_issued, id, unit_id, uses_rs1, uses_rs2, output rs1_conflict, rs2_conflict, rs1_data, rs2_data);
|
||||
endinterface
|
||||
|
||||
|
||||
|
@ -146,27 +148,29 @@ interface register_file_writeback_interface;
|
|||
|
||||
instruction_id_t rs1_id;
|
||||
instruction_id_t rs2_id;
|
||||
unit_id_t rs1_unit_id;
|
||||
unit_id_t rs2_unit_id;
|
||||
|
||||
logic[XLEN-1:0] rs1_data;
|
||||
logic[XLEN-1:0] rs2_data;
|
||||
logic rs1_valid;
|
||||
logic rs2_valid;
|
||||
|
||||
modport writeback (output rd_addr, commit, rd_nzero, rd_data, id, rs1_data, rs2_data, rs1_valid, rs2_valid, input rs1_id, rs2_id);
|
||||
modport unit (input rd_addr, commit, rd_nzero, rd_data, id, rs1_data, rs2_data, rs1_valid, rs2_valid, output rs1_id, rs2_id);
|
||||
modport writeback (output rd_addr, commit, rd_nzero, rd_data, id, rs1_data, rs2_data, rs1_valid, rs2_valid, input rs1_id, rs2_id, rs1_unit_id, rs2_unit_id);
|
||||
modport unit (input rd_addr, commit, rd_nzero, rd_data, id, rs1_data, rs2_data, rs1_valid, rs2_valid, output rs1_id, rs2_id, rs1_unit_id, rs2_unit_id);
|
||||
|
||||
endinterface
|
||||
|
||||
|
||||
interface tracking_interface;
|
||||
instruction_id_t issue_id;
|
||||
instruction_id_one_hot_t issue_id_one_hot;
|
||||
logic id_available;
|
||||
|
||||
inflight_instruction_packet inflight_packet;
|
||||
logic issued;
|
||||
|
||||
modport decode (input issue_id, id_available, issue_id_one_hot, output inflight_packet, issued);
|
||||
modport wb (output issue_id, id_available, issue_id_one_hot, input inflight_packet, issued);
|
||||
modport decode (input issue_id, id_available, output inflight_packet, issued);
|
||||
modport wb (output issue_id, id_available, input inflight_packet, issued);
|
||||
endinterface
|
||||
|
||||
interface fifo_interface #(parameter DATA_WIDTH = 42);//#(parameter type data_type = logic[31:0]);
|
||||
|
|
|
@ -47,14 +47,9 @@ module load_store_unit (
|
|||
local_memory_interface.master data_bram,
|
||||
|
||||
input logic[31:0] csr_rd,
|
||||
input instruction_id_one_hot_t csr_id_done,
|
||||
input instruction_id_t csr_id,
|
||||
input logic csr_done,
|
||||
|
||||
output logic store_committed,
|
||||
output instruction_id_t store_id,
|
||||
|
||||
output logic load_store_FIFO_emptying,
|
||||
output exception_packet_t ls_exception,
|
||||
output logic ls_exception_valid,
|
||||
|
||||
|
@ -106,7 +101,7 @@ module load_store_unit (
|
|||
logic [2:0] fn3;
|
||||
logic [1:0] byte_addr;
|
||||
instruction_id_t instruction_id;
|
||||
instruction_id_one_hot_t instruction_id_one_hot;
|
||||
logic is_store;
|
||||
} load_attributes_t;
|
||||
load_attributes_t load_attributes_in, stage2_attr;
|
||||
load_store_inputs_t stage1;
|
||||
|
@ -127,7 +122,6 @@ module load_store_unit (
|
|||
assign input_fifo.push = issue.new_request;
|
||||
assign issue.ready = (LS_INPUT_BUFFER_DEPTH >= MAX_INFLIGHT_COUNT) ? 1 : ~input_fifo.full;
|
||||
assign input_fifo.pop = issue_request | gc_issue_flush;
|
||||
assign load_store_FIFO_emptying = input_fifo.almost_empty & issue_request & ~issue.new_request;
|
||||
assign stage1 = input_fifo.data_out;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -140,19 +134,6 @@ module load_store_unit (
|
|||
last_unit <= sub_unit_address_match;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Store commit tracking
|
||||
always_ff @ (posedge clk) begin
|
||||
store_id <= stage1.instruction_id;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
store_committed <= 0;
|
||||
else
|
||||
store_committed <= stage1.store & (issue_request | ls_exception_valid);
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Primary Control Signals
|
||||
assign units_ready = &unit_ready;
|
||||
|
@ -245,12 +226,12 @@ module load_store_unit (
|
|||
assign load_attributes_in.fn3 = stage1.fn3;
|
||||
assign load_attributes_in.byte_addr = virtual_address[1:0];
|
||||
assign load_attributes_in.instruction_id = stage1.instruction_id;
|
||||
assign load_attributes_in.instruction_id_one_hot = stage1.instruction_id_one_hot;
|
||||
assign load_attributes_in.is_store = stage1.store;
|
||||
|
||||
assign load_attributes.data_in = load_attributes_in;
|
||||
|
||||
assign load_attributes.push = issue_request & stage1.load;
|
||||
assign load_attributes.pop = load_complete;
|
||||
assign load_attributes.push = issue_request;
|
||||
assign load_attributes.pop = load_complete | (stage2_attr.is_store & load_attributes.valid);
|
||||
|
||||
assign stage2_attr = load_attributes.data_out;
|
||||
|
||||
|
@ -349,9 +330,10 @@ module load_store_unit (
|
|||
always_ff @ (posedge clk) begin
|
||||
exception_complete <= (input_fifo.valid & ls_exception_valid & stage1.load);
|
||||
end
|
||||
assign ls_done = load_complete | exception_complete;
|
||||
assign ls_done = load_complete | exception_complete | (stage2_attr.is_store & load_attributes.valid);
|
||||
|
||||
assign wb.done_next_cycle = csr_id_done | (stage2_attr.instruction_id_one_hot & {MAX_INFLIGHT_COUNT{ls_done}});
|
||||
assign wb.done_next_cycle = csr_done | ls_done;
|
||||
assign wb.id = csr_done ? csr_id : stage2_attr.instruction_id;
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -34,7 +34,7 @@ module mul_unit(
|
|||
|
||||
logic signed [65:0] result;
|
||||
logic [1:0] mulh;
|
||||
instruction_id_one_hot_t id_one_hot_done [1:0];
|
||||
logic [1:0] done_next_cycle;
|
||||
instruction_id_t id [1:0];
|
||||
|
||||
logic rs1_signed, rs2_signed;
|
||||
|
@ -65,14 +65,14 @@ module mul_unit(
|
|||
id[0] <= issue.instruction_id;
|
||||
id[1] <= id[0];
|
||||
|
||||
id_one_hot_done[0] <= issue.instruction_id_one_hot & {MAX_INFLIGHT_COUNT{issue.new_request}};
|
||||
id_one_hot_done[1] <= id_one_hot_done[0];
|
||||
done_next_cycle[0] <= issue.new_request;
|
||||
done_next_cycle[1] <= done_next_cycle[0];
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Output bank
|
||||
always_ff @ (posedge clk) begin
|
||||
if (|id_one_hot_done[1])
|
||||
if (done_next_cycle[1])
|
||||
rd_bank[id[1]] <= mulh[1] ? result[63:32] : result[31:0];
|
||||
end
|
||||
|
||||
|
@ -82,8 +82,8 @@ module mul_unit(
|
|||
assign wb.rd = rd_bank[wb.writeback_instruction_id];
|
||||
assign wb.rs1_data = rd_bank[wb.writeback_rs1_id];
|
||||
assign wb.rs2_data = rd_bank[wb.writeback_rs2_id];
|
||||
assign wb.done_next_cycle = id_one_hot_done[1];
|
||||
|
||||
assign wb.done_next_cycle = done_next_cycle[1];
|
||||
assign wb.id = id[1];
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -26,15 +26,29 @@ import taiga_types::*;
|
|||
module register_file(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
input logic inorder,
|
||||
input logic inuse_clear,
|
||||
input logic gc_supress_writeback,
|
||||
register_file_writeback_interface.unit rf_wb,
|
||||
register_file_decode_interface.unit rf_decode
|
||||
register_file_decode_interface.unit rf_decode,
|
||||
|
||||
//Trace signals
|
||||
output logic tr_rs1_forwarding_needed,
|
||||
output logic tr_rs2_forwarding_needed,
|
||||
output logic tr_rs1_and_rs2_forwarding_needed
|
||||
);
|
||||
|
||||
typedef struct packed{
|
||||
instruction_id_t id;
|
||||
unit_id_t unit_id;
|
||||
} register_id_store_t;
|
||||
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic [XLEN-1:0] register [31:0];
|
||||
(* ramstyle = "MLAB, no_rw_check" *) instruction_id_t in_use_by [31:0];
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic[$bits(register_id_store_t)-1:0] in_use_by [31:0];
|
||||
|
||||
register_id_store_t new_id_store;
|
||||
register_id_store_t rs1_usage;
|
||||
register_id_store_t rs2_usage;
|
||||
register_id_store_t wb_usage;
|
||||
|
||||
logic rs1_inuse;
|
||||
logic rs2_inuse;
|
||||
|
@ -45,7 +59,6 @@ module register_file(
|
|||
logic valid_write;
|
||||
logic in_use_match;
|
||||
|
||||
instruction_id_t in_use_by_id;
|
||||
instruction_id_t rs1_id;
|
||||
instruction_id_t rs2_id;
|
||||
//////////////////////////////////////////
|
||||
|
@ -59,7 +72,7 @@ module register_file(
|
|||
|
||||
//Writeback unit does not assert rf_wb.commit when the target register is r0
|
||||
always_ff @ (posedge clk) begin
|
||||
if (~gc_supress_writeback & valid_write & (in_use_match | inorder)) //inorder needed for when a L/S exception occurs
|
||||
if (~gc_supress_writeback & valid_write)
|
||||
register[rf_wb.rd_addr] <= rf_wb.rd_data;
|
||||
end
|
||||
|
||||
|
@ -73,29 +86,41 @@ module register_file(
|
|||
.rs2_inuse(rs2_inuse)
|
||||
);
|
||||
|
||||
assign new_id_store.id = rf_decode.id;
|
||||
assign new_id_store.unit_id = rf_decode.unit_id;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rf_decode.instruction_issued)
|
||||
in_use_by[rf_decode.future_rd_addr] <= rf_decode.id;
|
||||
in_use_by[rf_decode.future_rd_addr] <= new_id_store;
|
||||
end
|
||||
|
||||
assign in_use_by_id = in_use_by[rf_wb.rd_addr];
|
||||
assign rs1_id = in_use_by[rf_decode.rs1_addr];
|
||||
assign rs2_id = in_use_by[rf_decode.rs2_addr];
|
||||
|
||||
assign rf_wb.rs1_id = rs1_id;
|
||||
assign rf_wb.rs2_id = rs2_id;
|
||||
|
||||
assign valid_write = rf_wb.rd_nzero && rf_wb.commit;
|
||||
assign in_use_match = (rf_wb.id == in_use_by_id);
|
||||
|
||||
assign rs1_feedforward = rs1_inuse;// && (rs1_id == rf_wb.id) && rf_wb.commit;
|
||||
assign rs2_feedforward = rs2_inuse;// && (rs2_id == rf_wb.id) && rf_wb.commit;
|
||||
assign rs1_usage = in_use_by[rf_decode.rs1_addr];
|
||||
assign rs2_usage = in_use_by[rf_decode.rs2_addr];
|
||||
assign wb_usage = in_use_by[rf_wb.rd_addr];
|
||||
|
||||
assign in_use_match = (wb_usage.id == rf_wb.id);
|
||||
|
||||
assign rf_wb.rs1_id = rs1_usage.id;
|
||||
assign rf_wb.rs2_id = rs2_usage.id;
|
||||
assign rf_wb.rs1_unit_id = rs1_usage.unit_id;
|
||||
assign rf_wb.rs2_unit_id = rs2_usage.unit_id;
|
||||
|
||||
assign valid_write = rf_wb.rd_nzero & rf_wb.commit;
|
||||
|
||||
assign rs1_feedforward = rs1_inuse;
|
||||
assign rs2_feedforward = rs2_inuse;
|
||||
|
||||
assign rf_decode.rs1_data = rs1_feedforward ? rf_wb.rs1_data : register[rf_decode.rs1_addr];
|
||||
assign rf_decode.rs2_data = rs2_feedforward ? rf_wb.rs2_data : register[rf_decode.rs2_addr];
|
||||
|
||||
assign rf_decode.rs1_conflict = rf_decode.uses_rs1 & rs1_inuse & ~rf_wb.rs1_valid;//rs1_inuse & ~rs1_feedforward;
|
||||
assign rf_decode.rs2_conflict = rf_decode.uses_rs2 & rs2_inuse & ~rf_wb.rs2_valid;//rs2_inuse & ~rs2_feedforward;
|
||||
assign rf_decode.rs1_conflict = rf_decode.uses_rs1 & rs1_inuse & ~rf_wb.rs1_valid;
|
||||
assign rf_decode.rs2_conflict = rf_decode.uses_rs2 & rs2_inuse & ~rf_wb.rs2_valid;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
|
@ -115,4 +140,10 @@ module register_file(
|
|||
end
|
||||
// synthesis translate_on
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Trace Interface
|
||||
assign tr_rs1_forwarding_needed = rs1_inuse & rf_decode.uses_rs1 & ~tr_rs1_and_rs2_forwarding_needed;
|
||||
assign tr_rs2_forwarding_needed = rs2_inuse & rf_decode.uses_rs2 & ~tr_rs1_and_rs2_forwarding_needed;
|
||||
assign tr_rs1_and_rs2_forwarding_needed = (rs1_inuse & rf_decode.uses_rs1) & (rs2_inuse & rf_decode.uses_rs2);
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -90,24 +90,19 @@ module taiga (
|
|||
fetch_buffer_packet_t fb;
|
||||
|
||||
//Global Control
|
||||
logic load_store_FIFO_emptying;
|
||||
logic gc_issue_hold;
|
||||
logic gc_issue_flush;
|
||||
logic gc_fetch_flush;
|
||||
logic gc_fetch_pc_override;
|
||||
logic gc_supress_writeback;
|
||||
logic inorder;
|
||||
logic inuse_clear;
|
||||
instruction_id_t oldest_id;
|
||||
logic load_store_issue;
|
||||
logic [31:0] gc_fetch_pc;
|
||||
|
||||
logic store_committed;
|
||||
instruction_id_t store_id;
|
||||
|
||||
logic[31:0] csr_rd;
|
||||
instruction_id_t csr_id;
|
||||
instruction_id_one_hot_t csr_id_done;
|
||||
logic csr_done;
|
||||
|
||||
//Decode Unit and Fetch Unit
|
||||
|
@ -133,6 +128,10 @@ module taiga (
|
|||
logic tr_branch_misspredict;
|
||||
logic tr_return_misspredict;
|
||||
logic tr_wb_mux_contention;
|
||||
|
||||
logic tr_rs1_forwarding_needed;
|
||||
logic tr_rs2_forwarding_needed;
|
||||
logic tr_rs1_and_rs2_forwarding_needed;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
|
@ -221,6 +220,9 @@ module taiga (
|
|||
tr.branch_misspredict <= tr_branch_misspredict;
|
||||
tr.return_misspredict <= tr_return_misspredict;
|
||||
tr.wb_mux_contention <= tr_wb_mux_contention;
|
||||
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;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
|
|
@ -162,11 +162,11 @@ package taiga_config;
|
|||
////////////////////////////////////////////////////
|
||||
//FIFO/Buffer Depths
|
||||
//All parameters restricted to powers of two
|
||||
parameter MAX_INFLIGHT_COUNT = 4;
|
||||
parameter MAX_INFLIGHT_COUNT = 8;
|
||||
parameter FETCH_BUFFER_DEPTH = 4;
|
||||
|
||||
parameter LS_INPUT_BUFFER_DEPTH = 4;
|
||||
parameter DIV_INPUT_BUFFER_DEPTH = 4;
|
||||
parameter LS_INPUT_BUFFER_DEPTH = 8;
|
||||
parameter DIV_INPUT_BUFFER_DEPTH = 8;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Trace Options
|
||||
|
|
|
@ -88,7 +88,6 @@ module taiga_fifo #(parameter DATA_WIDTH = 32, parameter FIFO_DEPTH = 4, paramet
|
|||
end
|
||||
end
|
||||
assign fifo.data_out = lut_ram[read_index];
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (fifo.push)
|
||||
lut_ram[write_index] <= fifo.data_in;
|
||||
|
|
|
@ -270,9 +270,11 @@ package taiga_types;
|
|||
} exception_packet_t;
|
||||
|
||||
typedef struct packed{
|
||||
instruction_id_t id;
|
||||
unit_id_t unit_id;
|
||||
logic [4:0] rd_addr;
|
||||
logic rd_addr_nzero;
|
||||
logic is_store;
|
||||
} inflight_instruction_packet;
|
||||
|
||||
typedef struct packed{
|
||||
|
@ -452,6 +454,11 @@ package taiga_types;
|
|||
logic [31:0] instruction_pc_dec;
|
||||
logic [31:0] instruction_data_dec;
|
||||
|
||||
//Register File
|
||||
logic rs1_forwarding_needed;
|
||||
logic rs2_forwarding_needed;
|
||||
logic rs1_and_rs2_forwarding_needed;
|
||||
|
||||
//Branch Unit
|
||||
logic branch_misspredict;
|
||||
logic return_misspredict;
|
||||
|
|
|
@ -27,11 +27,7 @@ module write_back(
|
|||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
input logic inorder,
|
||||
|
||||
input logic instruction_issued_with_rd,
|
||||
input logic store_committed,
|
||||
input instruction_id_t store_id,
|
||||
|
||||
unit_writeback_interface.writeback unit_wb[NUM_WB_UNITS-1:0],
|
||||
register_file_writeback_interface.writeback rf_wb,
|
||||
|
@ -49,7 +45,8 @@ module write_back(
|
|||
logic[$bits(inflight_instruction_packet)-1:0] packet_table [MAX_INFLIGHT_COUNT-1:0];
|
||||
|
||||
//aliases for write-back-interface signals
|
||||
logic [MAX_INFLIGHT_COUNT-1:0] unit_done_next_cycle [NUM_WB_UNITS-1:0];
|
||||
instruction_id_t unit_instruction_id [NUM_WB_UNITS-1:0];
|
||||
logic [NUM_WB_UNITS-1:0] unit_done_next_cycle;
|
||||
logic [XLEN-1:0] unit_rd [NUM_WB_UNITS-1:0];
|
||||
logic [XLEN-1:0] unit_rs1 [NUM_WB_UNITS-1:0];
|
||||
logic [XLEN-1:0] unit_rs2 [NUM_WB_UNITS-1:0];
|
||||
|
@ -77,6 +74,7 @@ module write_back(
|
|||
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_next_cycle[i] = unit_wb[i].done_next_cycle;
|
||||
assign unit_rd[i] = unit_wb[i].rd;
|
||||
assign unit_rs1[i] = unit_wb[i].rs1_data;
|
||||
|
@ -87,29 +85,11 @@ module write_back(
|
|||
end
|
||||
endgenerate
|
||||
|
||||
//ID stack. id_ordering[0] is the next ID to be issued. Entries filled from
|
||||
//MAX_INFLIGHT_COUNT-1 downwards.
|
||||
id_stack #(.STACK_DEPTH(MAX_INFLIGHT_COUNT)) instruction_ordering_stack (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.issued(ti.issued),
|
||||
.retired(retired),
|
||||
.store_committed(store_committed),
|
||||
.store_id(store_id),
|
||||
.id_done_ordered(id_done_ordered_post_store),
|
||||
.retired_id(retired_id),
|
||||
.ordering(id_ordering),
|
||||
.ordering_post_store(id_ordering_post_store),
|
||||
.id_available(ti.id_available),
|
||||
.next_id(issue_id),
|
||||
.empty(instruction_queue_empty)
|
||||
);
|
||||
//ID tracking
|
||||
id_tracking id_fifos (.*, .issued(ti.issued), .retired(retired), .id_available(ti.id_available),
|
||||
.oldest_id(oldest_id), .next_id(issue_id), .empty(instruction_queue_empty));
|
||||
|
||||
assign ti.issue_id = issue_id;
|
||||
always_comb begin
|
||||
ti.issue_id_one_hot = 0;
|
||||
ti.issue_id_one_hot[issue_id] = 1;
|
||||
end
|
||||
|
||||
//Inflight Instruction ID table
|
||||
//Stores unit id (in one-hot encoding), rd_addr and whether rd_addr is zero
|
||||
|
@ -135,8 +115,10 @@ module write_back(
|
|||
//Or together all unit done signals for the same ID.
|
||||
always_comb begin
|
||||
id_done = (id_done_r & ~id_retired_last_cycle); //Still pending instructions
|
||||
for (int i=0; i< NUM_WB_UNITS; i++) begin
|
||||
id_done |= unit_done_next_cycle[i];
|
||||
for (int i=0; i < MAX_INFLIGHT_COUNT; i++) begin
|
||||
for (int j=0; j< NUM_WB_UNITS; j++) begin
|
||||
id_done[i] |= unit_done_next_cycle[j] && (unit_instruction_id[j] == i[$clog2(MAX_INFLIGHT_COUNT)-1:0]);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -147,49 +129,33 @@ module write_back(
|
|||
id_done_r <= id_done;
|
||||
end
|
||||
|
||||
assign retired = (inorder ? id_done_ordered[MAX_INFLIGHT_COUNT-1] : |id_done);
|
||||
assign retired = id_done[oldest_id];
|
||||
assign retired_id = oldest_id;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
retired_r <= retired;
|
||||
retired_id_r <= retired_id;
|
||||
end
|
||||
|
||||
assign oldest_id = id_ordering[MAX_INFLIGHT_COUNT-1];
|
||||
|
||||
//Stack ordered from newest to oldest issued instruction
|
||||
//Find oldest done.
|
||||
always_comb begin
|
||||
foreach (id_done[i]) begin
|
||||
id_done_ordered[i] = id_done[id_ordering[i]];
|
||||
id_done_ordered_post_store[i] = id_done[id_ordering_post_store[i]];
|
||||
end
|
||||
|
||||
retired_id = id_ordering[MAX_INFLIGHT_COUNT-1];
|
||||
for (int i=MAX_INFLIGHT_COUNT-1; i>0; i--) begin
|
||||
if (inorder | id_done_ordered[i])
|
||||
break;
|
||||
retired_id = id_ordering[i-1];
|
||||
end
|
||||
//Read table for unit ID (acks, and rd_addr for register file)
|
||||
always_ff @(posedge clk) begin
|
||||
retired_instruction_packet <= instruction_queue_empty ? ti.inflight_packet : packet_table[retired_id];
|
||||
end
|
||||
|
||||
//Read table for unit ID (acks, and rd_addr for register file)
|
||||
assign retired_instruction_packet = packet_table[retired_id_r];
|
||||
assign instruction_complete = retired_r;
|
||||
assign instruction_complete = retired_r & ~retired_instruction_packet.is_store;
|
||||
|
||||
//Register file interaction
|
||||
assign rf_wb.rd_addr = retired_instruction_packet.rd_addr;
|
||||
assign rf_wb.id = retired_id_r;
|
||||
assign rf_wb.commit = retired_r;
|
||||
assign rf_wb.commit = retired_r & ~retired_instruction_packet.is_store;
|
||||
assign rf_wb.rd_nzero = retired_instruction_packet.rd_addr_nzero;
|
||||
assign rf_wb.rd_data = unit_rd[retired_instruction_packet.unit_id];
|
||||
|
||||
assign rf_wb.rs1_valid = id_done_r[rf_wb.rs1_id];
|
||||
assign rf_wb.rs2_valid = id_done_r[rf_wb.rs2_id];
|
||||
|
||||
assign rs1_packet = packet_table[rf_wb.rs1_id];
|
||||
assign rs2_packet = packet_table[rf_wb.rs2_id];
|
||||
|
||||
assign rf_wb.rs1_data = unit_rs1[rs1_packet.unit_id];
|
||||
assign rf_wb.rs2_data = unit_rs2[rs2_packet.unit_id];
|
||||
assign rf_wb.rs1_data = unit_rs1[rf_wb.rs1_unit_id];
|
||||
assign rf_wb.rs2_data = unit_rs2[rf_wb.rs2_unit_id];
|
||||
////////////////////////////////////////////////////
|
||||
//End of Implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -17,6 +17,9 @@ uint64_t instruction_issued_dec = 0;
|
|||
uint64_t branch_misspredict = 0;
|
||||
uint64_t return_misspredict = 0;
|
||||
uint64_t wb_mux_contention = 0;
|
||||
uint64_t rs1_forwarding_needed = 0;
|
||||
uint64_t rs2_forwarding_needed = 0;
|
||||
uint64_t rs1_and_rs2_forwarding_needed = 0;
|
||||
|
||||
using namespace std;
|
||||
int main(int argc, char **argv) {
|
||||
|
@ -86,6 +89,10 @@ int main(int argc, char **argv) {
|
|||
branch_misspredict += tb->branch_misspredict;
|
||||
return_misspredict += tb->return_misspredict;
|
||||
wb_mux_contention += tb->wb_mux_contention;
|
||||
|
||||
rs1_forwarding_needed += tb->rs1_forwarding_needed;
|
||||
rs2_forwarding_needed += tb->rs2_forwarding_needed;
|
||||
rs1_and_rs2_forwarding_needed += tb->rs1_and_rs2_forwarding_needed;
|
||||
}
|
||||
|
||||
|
||||
|
@ -143,11 +150,8 @@ int main(int argc, char **argv) {
|
|||
tracer->close();
|
||||
#endif
|
||||
|
||||
cout << "\n--------------------------------------------------------------\n";
|
||||
cout << " Simulation Completed: " << cycle_cout << " cycles.\n";
|
||||
cout << "--------------------------------------------------------------\n";
|
||||
|
||||
cout << "\n\n--------------------------------------------------------------\n";
|
||||
cout << " Simulation Completed: " << cycle_cout << " cycles.\n";
|
||||
cout << " Taiga trace stats:\n";
|
||||
cout << "--------------------------------------------------------------\n";
|
||||
cout << " operand_stall: " << operand_stall << "\n";
|
||||
|
@ -159,7 +163,11 @@ int main(int argc, char **argv) {
|
|||
cout << " branch_misspredict: " << branch_misspredict << "\n";
|
||||
cout << " return_misspredict: " << return_misspredict << "\n";
|
||||
cout << " wb_mux_contention: " << wb_mux_contention << "\n";
|
||||
cout << "--------------------------------------------------------------\n";
|
||||
cout << " rs1_forwarding_needed: " << rs1_forwarding_needed << "\n";
|
||||
cout << " rs2_forwarding_needed: " << rs2_forwarding_needed << "\n";
|
||||
cout << " rs1_OR_rs2_forwarding_needed: " << rs1_forwarding_needed + rs2_forwarding_needed << "\n";
|
||||
cout << " rs1_AND_rs2_forwarding_needed: " << rs1_and_rs2_forwarding_needed << "\n";
|
||||
cout << "--------------------------------------------------------------\n\n";
|
||||
|
||||
logFile.close();
|
||||
sigFile.close();
|
||||
|
|
|
@ -92,6 +92,10 @@ module taiga_local_mem # (
|
|||
output logic return_misspredict,
|
||||
output logic wb_mux_contention,
|
||||
|
||||
output logic rs1_forwarding_needed,
|
||||
output logic rs2_forwarding_needed,
|
||||
output logic rs1_and_rs2_forwarding_needed,
|
||||
|
||||
//L2
|
||||
//l2 request
|
||||
output logic [29:0] addr,
|
||||
|
@ -347,5 +351,7 @@ module taiga_local_mem # (
|
|||
assign branch_misspredict = tr.branch_misspredict;
|
||||
assign return_misspredict = tr.return_misspredict;
|
||||
assign wb_mux_contention = tr.wb_mux_contention;
|
||||
|
||||
assign rs1_forwarding_needed = tr.rs1_forwarding_needed;
|
||||
assign rs2_forwarding_needed = tr.rs2_forwarding_needed;
|
||||
assign rs1_and_rs2_forwarding_needed = tr.rs1_and_rs2_forwarding_needed;
|
||||
endmodule
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
|
||||
MAKEFLAGS += --silent
|
||||
#MAKEFLAGS += --silent
|
||||
MAKEFILE_DIR=$(pwd)
|
||||
TAIGA_DIR=/home/ematthew/taiga
|
||||
|
||||
|
@ -13,7 +13,7 @@ VERILATOR_DIR=$(TAIGA_DIR)/test_benches/verilator
|
|||
|
||||
TAIGA_SRCS = $(shell cat taiga_compile_order)
|
||||
|
||||
VERILATOR_LINT_IGNORE= -Wno-UNOPTFLAT -Wno-WIDTH -Wno-WIDTHCONCAT -Wno-LITENDIAN -Wno-SYMRSVDWORD -Wno-CASEINCOMPLETE -Wno-CASEX
|
||||
VERILATOR_LINT_IGNORE= -Wno-LITENDIAN -Wno-SYMRSVDWORD
|
||||
VERILATOR_CFLAGS = -CFLAGS "-g0 -Os -march=native -pipe -flto -Wl,-flto" -LDFLAGS "-flto"
|
||||
|
||||
AR="gcc-ar"
|
||||
|
@ -28,24 +28,6 @@ COMPLIANCE_DIR=/home/ematthew/Research/RISCV/sfu-rcl/taiga-riscv-compliance/
|
|||
COMPLIANCE_TARGET=rv32im
|
||||
###############################################################
|
||||
|
||||
#Benchmark parameters
|
||||
#Assumes binaries are in the BENCHMARK_DIR
|
||||
###############################################################
|
||||
BENCHMARK_DIR=/home/ematthew/Research/RISCV/software/taiga-benchmarks/
|
||||
BENCHMARKS = \
|
||||
dhrystone \
|
||||
prime \
|
||||
rand \
|
||||
sqrt \
|
||||
micro \
|
||||
rsa \
|
||||
aes \
|
||||
fft \
|
||||
qsort \
|
||||
###############################################################
|
||||
|
||||
|
||||
|
||||
#Benchmark parameters
|
||||
#Assumes binaries are in the BENCHMARK_DIR
|
||||
###############################################################
|
||||
|
@ -71,6 +53,9 @@ statemate \
|
|||
ud \
|
||||
wikisort \
|
||||
|
||||
embench_logs = $(addsuffix _full.log, $(EMBENCH_BENCHMARKS))
|
||||
embench_hw = $(addsuffix .hw_init, $(EMBENCH_BENCHMARKS))
|
||||
embench_sim = $(addsuffix .sim_init, $(EMBENCH_BENCHMARKS))
|
||||
###############################################################
|
||||
|
||||
#Binary to Verilog HW init file
|
||||
|
@ -79,17 +64,15 @@ ELF_TO_HW_INIT ?= python3 $(TAIGA_DIR)/tools/taiga_binary_converter.py $(RISCV_P
|
|||
###############################################################
|
||||
|
||||
|
||||
COREMARK_DIR=/home/ematthew/Research/RISCV/software/coremark
|
||||
|
||||
|
||||
define verilator_local_mem_test
|
||||
mkdir -p $@
|
||||
cp $(VERILATOR_DIR)/taiga_local_mem.cc $@/
|
||||
verilator -cc --exe --Mdir $@ $(VERILATOR_LINT_IGNORE) $(VERILATOR_CFLAGS) $(TAIGA_SRCS) \
|
||||
mkdir -p $1
|
||||
cp $(VERILATOR_DIR)/taiga_local_mem.cc $1/
|
||||
verilator -cc --exe --Mdir $1 $(VERILATOR_LINT_IGNORE) $(VERILATOR_CFLAGS) $(TAIGA_SRCS) \
|
||||
../test_benches/verilator/taiga_local_mem.sv --top-module taiga_local_mem taiga_local_mem.cc \
|
||||
-GMEMORY_FILE=$1
|
||||
$(MAKE) -C $@ -f Vtaiga_local_mem.mk AR="gcc-ar" RANLIB="gcc-ranlib"
|
||||
time ./$@/Vtaiga_local_mem $2 $3
|
||||
-GMEMORY_FILE=$2
|
||||
$(MAKE) -C $1 -f Vtaiga_local_mem.mk AR="gcc-ar" RANLIB="gcc-ranlib"
|
||||
echo $1 > $@
|
||||
./$1/Vtaiga_local_mem $3 $4 >> $@
|
||||
endef
|
||||
|
||||
.PHONY: lint
|
||||
|
@ -105,25 +88,22 @@ lint_full:
|
|||
../test_benches/verilator/taiga_local_mem.sv \
|
||||
--top-module taiga_local_mem \
|
||||
--lint-only -Wall
|
||||
|
||||
.PHONY: verilator_taiga_dhrystone
|
||||
verilator_taiga_dhrystone:
|
||||
$(call verilator_local_mem_test,\"$(BENCHMARK_DIR)dhrystone.riscv.hw_init\", "$@/dhrystone.log", "/dev/null")
|
||||
|
||||
.PHONY: verilator_taiga_benchmarks
|
||||
verilator_taiga_benchmarks:
|
||||
$(foreach BENCHMARK,$(BENCHMARKS), \
|
||||
$(call verilator_local_mem_test,\"$(BENCHMARK_DIR)$(BENCHMARK).riscv.hw_init\", $@/$(BENCHMARK).log, "/dev/null") \
|
||||
)
|
||||
|
||||
.PHONY: verilator_taiga_embench
|
||||
verilator_taiga_embench:
|
||||
$(foreach BENCHMARK,$(EMBENCH_BENCHMARKS), \
|
||||
cd $(EMBENCH_DIR)/$(BENCHMARK); \
|
||||
$(ELF_TO_HW_INIT) $(BENCHMARK) $(BENCHMARK).hw_init $(BENCHMARK).sim_init; \
|
||||
cd $(TAIGA_DIR)/tools; \
|
||||
$(call verilator_local_mem_test,\"$(EMBENCH_DIR)/$(BENCHMARK)/$(BENCHMARK).hw_init\", $@/$(BENCHMARK).log, "/dev/null"); \
|
||||
)
|
||||
#Benchmarks already built
|
||||
.PHONY : $(EMBENCH_BENCHMARKS)
|
||||
|
||||
#Create hw_init files for benchmarks
|
||||
$(embench_hw) : %.hw_init : %
|
||||
$(ELF_TO_HW_INIT) $(EMBENCH_DIR)/$</$< $@ $<.sim_init
|
||||
|
||||
#Run verilator
|
||||
$(embench_logs) : %_full.log : % $(embench_hw)
|
||||
$(call verilator_local_mem_test,$<,\"$(TAIGA_DIR)/tools/$<.hw_init\","/dev/null","/dev/null")
|
||||
|
||||
run_embench_verilator: $(embench_logs)
|
||||
cat $^ > embench.log
|
||||
|
||||
CRUFT= $(EMBENCH_BENCHMARKS) $(embench_hw) $(embench_sim) $(embench_logs) embench.log
|
||||
|
||||
#Called by compliance makefile
|
||||
.PHONY: verilator_taiga_compliance_unit_test
|
||||
|
@ -135,16 +115,5 @@ verilator_taiga_compliance_tests:
|
|||
$(MAKE) -C $(COMPLIANCE_DIR) clean
|
||||
$(MAKE) -C $(COMPLIANCE_DIR) RISCV_TARGET=taiga RISCV_DEVICE=$(COMPLIANCE_TARGET) RISCV_PREFIX=$(RISCV_PREFIX) TAIGA_ROOT=$(TAIGA_DIR)/tools
|
||||
|
||||
.PHONY: verilator_taiga_coremark
|
||||
verilator_taiga_coremark:
|
||||
$(MAKE) -C $(COREMARK_DIR) compile PORT_DIR=taiga-sim ITERATIONS=5000;
|
||||
cd $(MAKEFILE_DIR);
|
||||
$(ELF_TO_HW_INIT) $(COREMARK_DIR)/coremark.bin coremark.hw_init coremark.sim_init
|
||||
$(call verilator_local_mem_test,\"coremark.hw_init\", "coremark.log", "coremark.sig")
|
||||
|
||||
clean:
|
||||
rm -rf ./verilator_taiga_dhrystone
|
||||
rm -rf ./verilator_taiga_benchmarks
|
||||
rm -rf ./verilator_taiga_compliance_unit_test
|
||||
rm -rf ./verilator_taiga_coremark
|
||||
|
||||
rm -rf $(CRUFT)
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
../core/inuse.sv
|
||||
../core/register_file.sv
|
||||
|
||||
../core/id_stack.sv
|
||||
../core/id_tracking.sv
|
||||
../core/write_back.sv
|
||||
|
||||
../core/placer_randomizer.sv
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue