mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-20 03:57:18 -04:00
misc changes and fixes
This commit is contained in:
parent
9e66c2a331
commit
4c2c0915b3
29 changed files with 780 additions and 644 deletions
|
@ -31,66 +31,45 @@ module alu_unit(
|
|||
input alu_inputs_t alu_inputs
|
||||
);
|
||||
|
||||
logic [XLEN:0] add_sub_result;
|
||||
logic [XLEN-1:0] logic_result;
|
||||
|
||||
logic [XLEN-1:0] result;
|
||||
logic [XLEN-1:0] result2;
|
||||
logic[XLEN:0] add_sub_result;
|
||||
logic[XLEN-1:0] logic_result;
|
||||
logic[XLEN-1:0] shifter_result;
|
||||
|
||||
logic done;
|
||||
|
||||
logic[XLEN:0] add_sub_1;
|
||||
logic[XLEN:0] add_sub_2;
|
||||
logic[XLEN-1:0] shifter_resultl;
|
||||
logic[XLEN-1:0] shifter_resultr;
|
||||
|
||||
|
||||
assign add_sub_1 = {(alu_inputs.in1[XLEN-1] & ~alu_inputs.sltu), alu_inputs.in1};
|
||||
assign add_sub_2 = {(alu_inputs.in2[XLEN-1] & ~alu_inputs.sltu), alu_inputs.in2};
|
||||
|
||||
//Add sub op
|
||||
//assign add_sub_result = alu_inputs.subtract ? (add_sub_1 - add_sub_2) : (add_sub_1 + add_sub_2);
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
assign add_sub_result = alu_inputs.subtract ? alu_inputs.in1 - alu_inputs.in2 : alu_inputs.in1 + alu_inputs.in2;
|
||||
always_comb begin
|
||||
case (alu_inputs.logic_op) // <-- 010, 011 unused
|
||||
ALU_XOR : add_sub_result = add_sub_1 ^ add_sub_2;
|
||||
ALU_OR : add_sub_result = add_sub_1 | add_sub_2;
|
||||
ALU_AND : add_sub_result = add_sub_1 & add_sub_2;
|
||||
ALU_ADD_SUB : add_sub_result = alu_inputs.subtract ? add_sub_1 - add_sub_2 : add_sub_1 + add_sub_2;
|
||||
case (alu_inputs.fn3[1:0])
|
||||
XOR_fn3 : logic_result = alu_inputs.in1[XLEN-1:0] ^ alu_inputs.in2[XLEN-1:0];
|
||||
OR_fn3 : logic_result = alu_inputs.in1[XLEN-1:0] | alu_inputs.in2[XLEN-1:0];
|
||||
default : logic_result = alu_inputs.in1[XLEN-1:0] & alu_inputs.in2[XLEN-1:0];
|
||||
endcase
|
||||
end
|
||||
|
||||
//alu_logic_ops_and_adder logic_and_adder (
|
||||
// .op_type(alu_inputs.op[1:0]),
|
||||
// .sub(alu_inputs.subtract),
|
||||
// .A(add_sub_1),
|
||||
// .B(add_sub_2),
|
||||
// .result(add_sub_result)
|
||||
// );
|
||||
|
||||
//Barrel Shifter (initial bit flipping occurs in decode/issue stage)
|
||||
barrel_shifter shifter (
|
||||
.shifter_input(alu_inputs.shifter_in),
|
||||
.shifter_input(alu_inputs.in1[XLEN-1:0]),
|
||||
.shift_amount(alu_inputs.in2[4:0]),
|
||||
.arith(alu_inputs.arith),
|
||||
.lshifted_result(shifter_resultl),
|
||||
.rshifted_result(shifter_resultr)
|
||||
.lshift(alu_inputs.lshift),
|
||||
.shifted_result(shifter_result)
|
||||
);
|
||||
|
||||
//Result mux
|
||||
always_comb begin
|
||||
case (alu_inputs.op)
|
||||
ALU_SLT : result = {31'b0, add_sub_result[XLEN]};
|
||||
ALU_SHIFTR : result = shifter_resultr;
|
||||
ALU_SHIFT : result = shifter_resultl;
|
||||
ALU_ADD_SUB : result = add_sub_result[XLEN-1:0];
|
||||
ALU_ADD_SUB : alu_wb.rd = add_sub_result[XLEN-1:0];
|
||||
ALU_LOGIC : alu_wb.rd = logic_result;
|
||||
ALU_SLT : alu_wb.rd = {31'b0, add_sub_result[XLEN]};
|
||||
ALU_SHIFT : alu_wb.rd = shifter_result;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
//Issue/write-back handshaking
|
||||
////////////////////////////////////////////////////
|
||||
assign alu_ex.ready = ~done | (done & alu_wb.accepted);
|
||||
|
||||
assign alu_wb.rd = result;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
done <= 0;
|
||||
|
@ -101,8 +80,8 @@ module alu_unit(
|
|||
end
|
||||
end
|
||||
|
||||
assign alu_wb.done = (done & ~alu_wb.accepted);
|
||||
assign alu_wb.early_done = alu_ex.possible_issue;
|
||||
|
||||
assign alu_wb.done_next_cycle = (done & ~alu_wb.accepted);
|
||||
assign alu_wb.done_on_first_cycle = 1;
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 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
|
||||
|
@ -19,7 +19,7 @@
|
|||
* Author(s):
|
||||
* Eric Matthews <ematthew@sfu.ca>
|
||||
*/
|
||||
|
||||
|
||||
import taiga_config::*;
|
||||
import taiga_types::*;
|
||||
import l2_config_and_types::*;
|
||||
|
@ -234,7 +234,7 @@ module axi_to_arb
|
|||
on_last_burst <= 0;
|
||||
else if (axi_bvalid)
|
||||
on_last_burst <= 0;
|
||||
else if ((~write_in_progress && write_reference_burst_count == 0) || write_in_progress && write_reference_burst_count == write_burst_count)
|
||||
else if ((~write_in_progress && write_reference_burst_count == 0) || (write_in_progress && write_reference_burst_count == write_burst_count))
|
||||
on_last_burst <= 1;
|
||||
end
|
||||
|
||||
|
|
|
@ -27,38 +27,68 @@ module barrel_shifter (
|
|||
input logic[XLEN-1:0] shifter_input,
|
||||
input logic[4:0] shift_amount,
|
||||
input logic arith,
|
||||
output logic[XLEN-1:0] lshifted_result,
|
||||
output logic[XLEN-1:0] rshifted_result
|
||||
|
||||
input logic lshift,
|
||||
output logic[XLEN-1:0] shifted_result
|
||||
);
|
||||
|
||||
logic[XLEN-1:0] lshifter_input;
|
||||
logic[XLEN-1:0] shifter_in;
|
||||
logic[XLEN-1:0] lshifted;
|
||||
logic[XLEN:0] shifted;
|
||||
|
||||
|
||||
//Bit flipping shared shifter
|
||||
// always_comb begin
|
||||
// for (int i =0; i < 32; i++) begin
|
||||
// lshifter_input[i] = shifter_input[31-i];
|
||||
// end
|
||||
//end
|
||||
|
||||
//assign shifter_in = left_shift ? lshifter_input : shifter_input;
|
||||
assign shifted = signed'({arith,shifter_input}) >>> shift_amount;
|
||||
|
||||
logic[XLEN-1:0] shifted;
|
||||
logic[XLEN-1:0] shiftx16, shiftx4, shiftx1;
|
||||
logic[XLEN*2-1:0] shiftx16_padded, shiftx4_padded;
|
||||
|
||||
//Flip left shift input
|
||||
always_comb begin
|
||||
for (int i =0; i < 32; i++) begin
|
||||
lshifted[i] = shifted[31-i];
|
||||
lshifter_input[i] = shifter_input[31-i];
|
||||
end
|
||||
end
|
||||
//assign lshifted = {<<{shifted}};//if stream operator supported
|
||||
assign shifter_in = lshift ? lshifter_input : shifter_input;
|
||||
//Bit flipping shared shifter
|
||||
//left shift occurs in decode logic
|
||||
|
||||
//assign shifted_result = left_shift ? lshifted : shifted[31:0];
|
||||
assign lshifted_result = lshifted;
|
||||
assign rshifted_result = shifted[31:0];
|
||||
always_comb begin
|
||||
case ({shift_amount[4],lshift})
|
||||
0: shiftx16 = shifter_input;
|
||||
1: shiftx16 = lshifter_input;
|
||||
2: shiftx16 = {{16{arith}}, shifter_input[15:0]};
|
||||
3: shiftx16 = {{16{arith}}, lshifter_input[15:0]};
|
||||
endcase
|
||||
end
|
||||
|
||||
assign shiftx16_padded = {{32{arith}}, shiftx16};
|
||||
|
||||
always_comb begin
|
||||
case (shift_amount[3:2])
|
||||
0: shiftx4 <= shiftx16_padded[31:0];
|
||||
1: foreach (shiftx4[i]) shiftx4[i] <= shiftx16_padded[i+4];
|
||||
2: foreach (shiftx4[i]) shiftx4[i] <= shiftx16_padded[i+8];
|
||||
3: foreach (shiftx4[i]) shiftx4[i] <= shiftx16_padded[i+12];
|
||||
endcase
|
||||
end
|
||||
|
||||
assign shiftx4_padded = {{32{arith}}, shiftx4};
|
||||
|
||||
always_comb begin
|
||||
case (shift_amount[1:0])
|
||||
0: shiftx1 <= shiftx4_padded[31:0];
|
||||
1: foreach (shiftx1[i]) shiftx1[i] <= shiftx4_padded[i+1];
|
||||
2: foreach (shiftx1[i]) shiftx1[i] <= shiftx4_padded[i+2];
|
||||
3: foreach (shiftx1[i]) shiftx1[i] <= shiftx4_padded[i+3];
|
||||
endcase
|
||||
end
|
||||
|
||||
//Flip left shift output
|
||||
always_comb begin
|
||||
for (int i =0; i < 32; i++) begin
|
||||
lshifted[i] = shiftx1[31-i];
|
||||
end
|
||||
end
|
||||
|
||||
assign shifted_result = lshift ? lshifted : shiftx1;
|
||||
|
||||
//assign shifted_result = lshift ? signed'({arith,shifter_input} <<< shift_amount) : signed'({arith,shifter_input} >>> shift_amount);
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
108
core/binary_occupancy.sv
Normal file
108
core/binary_occupancy.sv
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright © 2017 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 binary_occupancy #(parameter DEPTH = 4)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
input logic push,
|
||||
input logic pop,
|
||||
output logic early_full,
|
||||
output logic full,
|
||||
output logic empty,
|
||||
output logic valid,
|
||||
output logic early_valid,
|
||||
output logic two_plus
|
||||
);
|
||||
|
||||
|
||||
logic[$clog2(DEPTH)-1:0] count;
|
||||
|
||||
//Occupancy Tracking
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
count <= 0;
|
||||
else if (push & ~pop)
|
||||
count <= count + 1;
|
||||
else if (pop & ~push)
|
||||
count <= count - 1;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
valid <= 0;
|
||||
else if (push)
|
||||
valid <= 1;
|
||||
else if (pop && (count == 1))
|
||||
valid <= 0;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
full <= 0;
|
||||
else if ((push & ~pop) && (count == DEPTH-1))
|
||||
full <= 1;
|
||||
else if (pop)
|
||||
full <= 0;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
early_full <= 0;
|
||||
else if ((push & ~pop) && (count == DEPTH-2))
|
||||
early_full <= 1;
|
||||
else if (pop && (count == DEPTH-1))
|
||||
early_full <= 0;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
two_plus <= 0;
|
||||
else if ((push & ~pop) && (count >= 1))
|
||||
two_plus <= 1;
|
||||
else if (pop && (count == 2))
|
||||
two_plus <= 0;
|
||||
end
|
||||
|
||||
assign empty = ~valid;//(count == 0);
|
||||
//assign valid = //(count != 0);
|
||||
//assign full = (count == (DEPTH-1));
|
||||
//assign early_full = (count == (DEPTH-2)) & push & ~pop;
|
||||
|
||||
//pushing, or more than one, or at least one and not popping
|
||||
//assign two_plus = (count > 1);
|
||||
assign early_valid = push | (two_plus) | (valid & ~pop);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
always_ff @ (posedge clk) begin
|
||||
assert (!(~rst & full & push)) else $error("overflow");
|
||||
assert (!(~rst & empty & pop)) else $error("underflow");
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
@ -53,19 +53,18 @@ module branch_table(
|
|||
logic [31:0] miss_predict_ret;
|
||||
logic [31:0] miss_predict_jalr;
|
||||
|
||||
|
||||
logic miss_predict;
|
||||
logic miss_predict2;
|
||||
|
||||
logic tag_match;
|
||||
/////////////////////////////////////////
|
||||
|
||||
logic bt_on;
|
||||
|
||||
initial begin
|
||||
for(int i=0; i<BRANCH_TABLE_ENTRIES; i=i+1) begin
|
||||
//foreach(branch_table_tag_ram[i]) begin
|
||||
branch_table_tag_ram[i] = 0;
|
||||
branch_table_addr_ram[i] = 0;
|
||||
branch_table_addr_ram[i] = RESET_VEC;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -99,19 +98,13 @@ module branch_table(
|
|||
(bt.branch_taken && bt.dec_pc != bt.jump_pc) ||
|
||||
(~bt.branch_taken && bt.dec_pc != bt.njump_pc));
|
||||
|
||||
assign tag_match = ({if_entry.valid, if_entry.tag} == {(bt.next_pc_valid & bt_on), bt.if_pc[31:32-BTAG_W]});
|
||||
|
||||
assign tag_match = ({if_entry.valid, if_entry.tag} == {1'b1, bt.if_pc[31:32-BTAG_W]});
|
||||
assign bt.predicted_pc = predicted_pc;
|
||||
assign bt.prediction = if_entry.prediction;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
bt_on <= 0;
|
||||
else if (bt.branch_ex)
|
||||
bt_on <= 1;
|
||||
end
|
||||
|
||||
generate if (USE_BRANCH_PREDICTOR) begin
|
||||
assign bt.use_prediction = bt_on & tag_match;
|
||||
assign bt.use_prediction = tag_match;
|
||||
assign bt.flush = miss_predict;
|
||||
end else begin
|
||||
assign bt.use_prediction = 0;
|
||||
|
@ -129,8 +122,6 @@ module branch_table(
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
miss_predict_ret <= 0;
|
||||
|
|
|
@ -53,8 +53,8 @@ module branch_unit(
|
|||
logic [31:0] ret_count;
|
||||
logic [31:0] br_count;
|
||||
|
||||
logic [32:0] rs1_sext;
|
||||
logic [32:0] rs2_sext;
|
||||
logic signed [32:0] rs1_sext;
|
||||
logic signed [32:0] rs2_sext;
|
||||
|
||||
logic jump_ex;
|
||||
logic bcomp_ex;
|
||||
|
@ -67,7 +67,6 @@ module branch_unit(
|
|||
logic [31:0] select_new_carry;
|
||||
logic [31:0] carry;
|
||||
|
||||
|
||||
assign equal = (branch_inputs.rs1 == branch_inputs.rs2);
|
||||
assign rs1_sext = {branch_inputs.rs1[XLEN-1] & branch_inputs.use_signed, branch_inputs.rs1};
|
||||
assign rs2_sext = {branch_inputs.rs2[XLEN-1] & branch_inputs.use_signed, branch_inputs.rs2};
|
||||
|
@ -75,14 +74,13 @@ module branch_unit(
|
|||
assign lessthan = signed'(rs1_sext) < signed'(rs2_sext);
|
||||
|
||||
always_comb begin
|
||||
case (fn3_ex) // <-- 010, 011 unused
|
||||
unique case (fn3_ex) // <-- 010, 011 unused
|
||||
BEQ_fn3 : result = equal_ex;
|
||||
BNE_fn3 : result = ~equal_ex;
|
||||
BLT_fn3 : result = lessthan_ex;
|
||||
BGE_fn3 : result = ~lessthan_ex;
|
||||
BLTU_fn3 : result = lessthan_ex;
|
||||
BGEU_fn3 : result = ~lessthan_ex;
|
||||
default : result = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -104,7 +102,11 @@ module branch_unit(
|
|||
|
||||
assign bt.branch_ex = branch_ex.new_request;
|
||||
always_ff @(posedge clk) begin
|
||||
fn3_ex <= branch_inputs.fn3;
|
||||
if (branch_ex.new_request_dec)
|
||||
fn3_ex <= branch_inputs.fn3;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
equal_ex <= equal;
|
||||
lessthan_ex <= lessthan;
|
||||
bt.ex_pc <= branch_inputs.dec_pc;
|
||||
|
@ -114,7 +116,7 @@ module branch_unit(
|
|||
bt.njump_pc <= pc_plus_4;
|
||||
end
|
||||
|
||||
|
||||
//if the destination reg is zero, the result is not "written back" to the register file.
|
||||
assign new_jal_jalr_dec = (branch_inputs.jal | branch_inputs.jalr) & ~branch_inputs.rdx0;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
|
@ -163,8 +165,8 @@ module branch_unit(
|
|||
end
|
||||
end
|
||||
|
||||
assign branch_wb.done = (done & ~branch_wb.accepted);
|
||||
assign branch_wb.early_done = branch_ex.possible_issue & new_jal_jalr_dec;
|
||||
assign branch_wb.done_next_cycle = (done & ~branch_wb.accepted);
|
||||
assign branch_wb.done_on_first_cycle = 1;//branch_ex.possible_issue & new_jal_jalr_dec;
|
||||
|
||||
/*********************************************/
|
||||
|
||||
|
|
|
@ -654,8 +654,8 @@ module csr_unit (
|
|||
end
|
||||
end
|
||||
|
||||
assign csr_wb.early_done = 0;
|
||||
assign csr_wb.done = csr_ex.new_request | (done & ~csr_wb.accepted);
|
||||
assign csr_wb.done_on_first_cycle = 0;
|
||||
assign csr_wb.done_next_cycle = csr_ex.new_request | (done & ~csr_wb.accepted);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
|
|
|
@ -31,7 +31,7 @@ module dbram(
|
|||
ls_sub_unit_interface.sub_unit ls,
|
||||
output logic[31:0] data_out,
|
||||
|
||||
bram_interface.user data_bram
|
||||
local_memory_interface.master data_bram
|
||||
);
|
||||
|
||||
assign ls.ready = 1;
|
||||
|
|
171
core/decode.sv
171
core/decode.sv
|
@ -136,36 +136,25 @@ module decode(
|
|||
assign rf_decode.instruction_issued = advance & uses_rd;
|
||||
assign rf_decode.id = id_gen.issue_id;
|
||||
//Issue logic
|
||||
|
||||
always_comb begin
|
||||
case (opcode)
|
||||
LUI : illegal_instruction = 1'b0;
|
||||
AUIPC : illegal_instruction = 1'b0;
|
||||
JAL : illegal_instruction = 1'b0;
|
||||
JALR : illegal_instruction = 1'b0;
|
||||
BRANCH : illegal_instruction = 1'b0;
|
||||
LOAD : illegal_instruction = 1'b0;
|
||||
STORE : illegal_instruction = 1'b0;
|
||||
ARITH_IMM : illegal_instruction = 1'b0;
|
||||
ARITH : begin
|
||||
if (!USE_MUL && !USE_DIV)
|
||||
illegal_instruction = ib.data_out.instruction[25];
|
||||
else if (!USE_MUL && USE_DIV)
|
||||
illegal_instruction = ib.data_out.instruction[25] & ~fn3[2];
|
||||
else if (!USE_MUL && !USE_DIV)
|
||||
illegal_instruction = ib.data_out.instruction[25] & fn3[2];
|
||||
else
|
||||
illegal_instruction = 1'b0;
|
||||
end
|
||||
FENCE : illegal_instruction = 1'b0;
|
||||
AMO : illegal_instruction = 1'b0;
|
||||
SYSTEM : illegal_instruction = 1'b0;
|
||||
default : illegal_instruction = 1'b1;
|
||||
endcase
|
||||
illegal_instruction = !(opcode inside {LUI, AUIPC, JAL, JALR, BRANCH, LOAD, STORE, ARITH, ARITH_IMM, FENCE, AMO, SYSTEM});
|
||||
if (opcode == ARITH) begin
|
||||
if (!USE_MUL && !USE_DIV)
|
||||
illegal_instruction = ib.data_out.instruction[25];
|
||||
else if (!USE_MUL && USE_DIV)
|
||||
illegal_instruction = ib.data_out.instruction[25] & ~fn3[2];
|
||||
else if (!USE_MUL && !USE_DIV)
|
||||
illegal_instruction = ib.data_out.instruction[25] & fn3[2];
|
||||
else
|
||||
illegal_instruction = 0;
|
||||
end
|
||||
end
|
||||
|
||||
one_hot_to_integer #(NUM_WB_UNITS) iq_id (.one_hot(new_request), .int_out(iq.data_in.unit_id));
|
||||
|
||||
assign iq.future_rd_addr = future_rd_addr;
|
||||
assign iq.uses_rd = uses_rd && (future_rd_addr != 0);
|
||||
assign iq.data_in.id = id_gen.issue_id;
|
||||
assign iq.new_issue = advance & uses_rd;
|
||||
|
||||
|
@ -188,53 +177,39 @@ module decode(
|
|||
|
||||
assign mult_div_op = (opcode_trim == ARITH_T) && ib.data_out.instruction[25];
|
||||
|
||||
assign new_request[BRANCH_UNIT_ID] = ((opcode_trim == BRANCH_T) || (opcode_trim == JAL_T) || (opcode_trim == JALR_T));
|
||||
assign new_request[ALU_UNIT_ID] = ((opcode_trim == ARITH_T) && ~ib.data_out.instruction[25]) || (opcode_trim == ARITH_IMM_T) || (opcode_trim == AUIPC_T) || (opcode_trim == LUI_T);
|
||||
assign new_request[LS_UNIT_ID] = (opcode_trim == LOAD_T || opcode_trim == STORE_T || opcode_trim == AMO_T);
|
||||
assign new_request[BRANCH_UNIT_ID] = opcode_trim inside {BRANCH_T, JAL_T, JALR_T};
|
||||
assign new_request[ALU_UNIT_ID] = ((opcode_trim == ARITH_T) && ~ib.data_out.instruction[25]) || opcode_trim inside {ARITH_IMM_T, AUIPC_T, LUI_T};
|
||||
assign new_request[LS_UNIT_ID] = opcode_trim inside {LOAD_T, STORE_T, AMO_T};
|
||||
assign new_request[CSR_UNIT_ID] = (opcode_trim == SYSTEM_T);
|
||||
|
||||
generate if (USE_MUL)
|
||||
assign new_request[MUL_UNIT_ID] = mult_div_op & ~fn3[2];
|
||||
else
|
||||
assign new_request[MUL_UNIT_ID] = 0;
|
||||
endgenerate
|
||||
generate if (USE_DIV)
|
||||
assign new_request[DIV_UNIT_ID] = mult_div_op & fn3[2];
|
||||
else
|
||||
assign new_request[DIV_UNIT_ID] = 0;
|
||||
endgenerate
|
||||
|
||||
// assign new_request[CUSTOM_ID_0] = (opcode_trim == CUSTOM_T) && ~ib.data_out.instruction[25] && ~ib.data_out.instruction[26];
|
||||
// assign new_request[CUSTOM_ID_1] = (opcode_trim == CUSTOM_T) && ~ib.data_out.instruction[25] && ib.data_out.instruction[26];
|
||||
// assign new_request[CUSTOM_ID_2] = (opcode_trim == CUSTOM_T) && ib.data_out.instruction[25] && ~ib.data_out.instruction[26];
|
||||
// assign new_request[CUSTOM_ID_3] = (opcode_trim == CUSTOM_T) && ib.data_out.instruction[25] && ib.data_out.instruction[26];
|
||||
//
|
||||
|
||||
assign issue_ready[BRANCH_UNIT_ID] = new_request[BRANCH_UNIT_ID] & (branch_ex.ready | ~uses_rd);//| ~uses_rd
|
||||
assign issue_ready[ALU_UNIT_ID] = new_request[ALU_UNIT_ID] & alu_ex.ready;
|
||||
assign issue_ready[LS_UNIT_ID] = new_request[LS_UNIT_ID] & ls_ex.ready;
|
||||
assign issue_ready[CSR_UNIT_ID] = new_request[CSR_UNIT_ID] & csr_ex.ready;
|
||||
assign issue_ready[MUL_UNIT_ID] = new_request[MUL_UNIT_ID] & mul_ex.ready;
|
||||
assign issue_ready[DIV_UNIT_ID] = new_request[DIV_UNIT_ID] & div_ex.ready;
|
||||
|
||||
// assign issue_ready[CUSTOM_ID_0] = new_request[CUSTOM_ID_0] & cust0_ex.ready;
|
||||
//assign issue_ready[CUSTOM_ID_1] = new_request[CUSTOM_ID_1] & cust1_ex.ready;
|
||||
// assign issue_ready[CUSTOM_ID_2] = new_request[CUSTOM_ID_2] & cust2_ex.ready;
|
||||
// assign issue_ready[CUSTOM_ID_3] = new_request[CUSTOM_ID_3] & cust3_ex.ready;
|
||||
|
||||
|
||||
|
||||
generate if (USE_MUL)
|
||||
assign issue_ready[MUL_UNIT_ID] = new_request[MUL_UNIT_ID] & mul_ex.ready;
|
||||
endgenerate
|
||||
generate if (USE_DIV)
|
||||
assign issue_ready[DIV_UNIT_ID] = new_request[DIV_UNIT_ID] & div_ex.ready;
|
||||
endgenerate
|
||||
assign issue[BRANCH_UNIT_ID] = issue_valid & operands_ready & issue_ready[BRANCH_UNIT_ID];
|
||||
assign issue[ALU_UNIT_ID] = issue_valid & operands_ready & issue_ready[ALU_UNIT_ID];
|
||||
assign issue[LS_UNIT_ID] = issue_valid & load_store_operands_ready & issue_ready[LS_UNIT_ID];
|
||||
assign issue[CSR_UNIT_ID] = issue_valid & operands_ready & issue_ready[CSR_UNIT_ID];
|
||||
assign issue[MUL_UNIT_ID] = issue_valid & operands_ready & issue_ready[MUL_UNIT_ID];
|
||||
assign issue[DIV_UNIT_ID] = issue_valid & operands_ready & issue_ready[DIV_UNIT_ID];
|
||||
|
||||
//assign issue[CUSTOM_ID_0] = issue_valid & operands_ready & issue_ready[CUSTOM_ID_0];
|
||||
//assign issue[CUSTOM_ID_1] = issue_valid & operands_ready & issue_ready[CUSTOM_ID_1];
|
||||
//assign issue[CUSTOM_ID_2] = issue_valid & operands_ready & issue_ready[CUSTOM_ID_2];
|
||||
//assign issue[CUSTOM_ID_3] = issue_valid & operands_ready & issue_ready[CUSTOM_ID_3];
|
||||
|
||||
generate if (USE_MUL)
|
||||
assign issue[MUL_UNIT_ID] = issue_valid & operands_ready & issue_ready[MUL_UNIT_ID];
|
||||
endgenerate
|
||||
generate if (USE_DIV)
|
||||
assign issue[DIV_UNIT_ID] = issue_valid & operands_ready & issue_ready[DIV_UNIT_ID];
|
||||
endgenerate
|
||||
|
||||
assign advance = (|issue_ready) & issue_valid & load_store_operands_ready;
|
||||
|
||||
|
@ -273,17 +248,8 @@ module decode(
|
|||
XOR_fn3 : alu_op = ALU_LOGIC;
|
||||
OR_fn3 : alu_op = ALU_LOGIC;
|
||||
AND_fn3 : alu_op = ALU_LOGIC;
|
||||
SRA_fn3 : alu_op = ALU_SHIFTR;
|
||||
ADD_SUB_fn3 : alu_op = ALU_LOGIC;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
case (fn3)
|
||||
XOR_fn3 : alu_logic_op = ALU_XOR;
|
||||
OR_fn3 : alu_logic_op = ALU_OR;
|
||||
AND_fn3 : alu_logic_op = ALU_AND;
|
||||
default: alu_logic_op = ALU_ADD_SUB;
|
||||
SRA_fn3 : alu_op = ALU_SHIFT;
|
||||
ADD_SUB_fn3 : alu_op = ALU_ADD_SUB;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -302,15 +268,14 @@ module decode(
|
|||
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue[ALU_UNIT_ID]) begin
|
||||
alu_inputs.in1 <= alu_rs1_data;
|
||||
alu_inputs.in2 <= alu_rs2_data;
|
||||
alu_inputs.in1 <= {(alu_rs1_data[XLEN-1] & ~fn3[0]), alu_rs1_data};//(fn3[0] is SLTU_fn3);
|
||||
alu_inputs.in2 <= {(alu_rs2_data[XLEN-1] & ~fn3[0]), alu_rs2_data};
|
||||
alu_inputs.subtract <= alu_sub;
|
||||
alu_inputs.arith <= alu_rs1_data[XLEN-1] & ib.data_out.instruction[30];//shift in bit
|
||||
alu_inputs.shifter_in <= fn3[2] ? rf_decode.rs1_data : left_shift_in;
|
||||
alu_inputs.sltu <= fn3[0];//(fn3 ==SLTU_fn3);
|
||||
alu_inputs.logic_op <= opcode[2] ? ALU_ADD_SUB : alu_logic_op;//put LUI and AUIPC through adder path
|
||||
alu_inputs.op <= opcode[2] ? ALU_LOGIC : alu_op;//put LUI and AUIPC through adder path
|
||||
end
|
||||
alu_inputs.lshift <= ~fn3[2];
|
||||
alu_inputs.fn3 <= fn3;
|
||||
alu_inputs.op <= opcode[2] ? ALU_ADD_SUB : alu_op;//put LUI and AUIPC through adder path
|
||||
end
|
||||
end
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
|
@ -326,7 +291,7 @@ module decode(
|
|||
assign ls_inputs.fn3 = ls_inputs.is_amo ? LS_W_fn3 : fn3;
|
||||
assign ls_inputs.amo = USE_AMO ? ib.data_out.instruction[31:27] : 0;
|
||||
assign ls_inputs.is_amo = USE_AMO ? (opcode_trim == AMO_T) : 0;
|
||||
assign ls_inputs.load = (opcode_trim == LOAD_T) || ((opcode_trim == AMO_T) && (ls_inputs.amo != AMO_SC)); //LR and AMO_ops perform a read operation as well
|
||||
assign ls_inputs.load = (opcode_trim inside {LOAD_T, AMO_T}) && (ls_inputs.amo != AMO_SC); //LR and AMO_ops perform a read operation as well
|
||||
assign ls_inputs.store = (opcode_trim == STORE_T);
|
||||
assign ls_inputs.load_store_forward = (opcode_trim == STORE_T) && rf_decode.rs2_conflict;
|
||||
assign ls_inputs.id = id_gen.issue_id;
|
||||
|
@ -357,7 +322,7 @@ module decode(
|
|||
assign branch_inputs.rs2 = rf_decode.rs2_data;
|
||||
assign branch_inputs.fn3 = fn3;
|
||||
assign branch_inputs.dec_pc = ib.data_out.pc;
|
||||
assign branch_inputs.use_signed = !((fn3 == BLTU_fn3) || (fn3 == BGEU_fn3));
|
||||
assign branch_inputs.use_signed = !(fn3 inside {BLTU_fn3, BGEU_fn3});
|
||||
assign branch_inputs.rdx0 = ~uses_rd;//(future_rd_addr == 0); jal jalr x0
|
||||
assign branch_inputs.rs1_addr = rs1_addr;
|
||||
assign branch_inputs.rd_addr = future_rd_addr;
|
||||
|
@ -390,38 +355,40 @@ module decode(
|
|||
//----------------------------------------------------------------------------------
|
||||
//Mul Div unit inputs
|
||||
//----------------------------------------------------------------------------------
|
||||
assign mul_ex.new_request_dec = issue[MUL_UNIT_ID];
|
||||
assign mul_inputs.rs1 = rf_decode.rs1_data;
|
||||
assign mul_inputs.rs2 = rf_decode.rs2_data;
|
||||
assign mul_inputs.op = fn3[1:0];
|
||||
|
||||
generate if (USE_MUL)
|
||||
assign mul_ex.new_request_dec = issue[MUL_UNIT_ID];
|
||||
assign mul_inputs.rs1 = rf_decode.rs1_data;
|
||||
assign mul_inputs.rs2 = rf_decode.rs2_data;
|
||||
assign mul_inputs.op = fn3[1:0];
|
||||
endgenerate
|
||||
//If a subsequent div request uses the same inputs then
|
||||
//don't rerun div operation
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue[DIV_UNIT_ID]) begin
|
||||
prev_div_rs1_addr <= rs1_addr;
|
||||
prev_div_rs2_addr <= rs2_addr;
|
||||
generate if (USE_DIV)
|
||||
always_ff @(posedge clk) begin
|
||||
if (issue[DIV_UNIT_ID]) begin
|
||||
prev_div_rs1_addr <= rs1_addr;
|
||||
prev_div_rs2_addr <= rs2_addr;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
prev_div_result_valid <= 0;
|
||||
else if (advance) begin
|
||||
if(new_request[DIV_UNIT_ID] && !(future_rd_addr inside {rs1_addr, rs2_addr}))
|
||||
prev_div_result_valid <=1;
|
||||
else if (uses_rd && (future_rd_addr inside {prev_div_rs1_addr, prev_div_rs2_addr}))
|
||||
prev_div_result_valid <=0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
prev_div_result_valid <= 0;
|
||||
else if (advance) begin
|
||||
if(new_request[DIV_UNIT_ID] && !(rs1_addr == future_rd_addr || rs2_addr == future_rd_addr))
|
||||
prev_div_result_valid <=1;
|
||||
else if (uses_rd && (prev_div_rs1_addr == future_rd_addr || prev_div_rs2_addr == future_rd_addr))
|
||||
prev_div_result_valid <=0;
|
||||
end
|
||||
end
|
||||
|
||||
assign div_ex.new_request_dec = issue[DIV_UNIT_ID];
|
||||
assign div_inputs.rs1 = rf_decode.rs1_data;
|
||||
assign div_inputs.rs2 = rf_decode.rs2_data;
|
||||
assign div_inputs.op = fn3[1:0];
|
||||
assign div_inputs.reuse_result = 0;//prev_div_result_valid && (prev_div_rs1_addr == rs1_addr) && (prev_div_rs2_addr == rs2_addr);
|
||||
assign div_inputs.div_zero = (rf_decode.rs2_data == 0);
|
||||
|
||||
assign div_ex.new_request_dec = issue[DIV_UNIT_ID];
|
||||
assign div_inputs.rs1 = rf_decode.rs1_data;
|
||||
assign div_inputs.rs2 = rf_decode.rs2_data;
|
||||
assign div_inputs.op = fn3[1:0];
|
||||
assign div_inputs.reuse_result = prev_div_result_valid && (prev_div_rs1_addr == rs1_addr) && (prev_div_rs2_addr == rs2_addr);
|
||||
assign div_inputs.div_zero = (rf_decode.rs2_data == 0);
|
||||
endgenerate
|
||||
//----------------------------------------------------------------------------------
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst) begin
|
||||
|
|
|
@ -37,27 +37,23 @@ module div_unit(
|
|||
logic [31:0] quotient;
|
||||
logic [31:0] remainder;
|
||||
|
||||
logic [31:0] result;
|
||||
|
||||
logic signed_divop;
|
||||
logic quotient_signed;
|
||||
logic remainder_signed;
|
||||
logic dividend_signed;
|
||||
logic divisor_signed;
|
||||
|
||||
logic div_abort;
|
||||
|
||||
logic start;
|
||||
logic in_progress;
|
||||
logic output_ready;
|
||||
logic ack;
|
||||
|
||||
logic [31:0] complementerA;
|
||||
logic [31:0] complementerB;
|
||||
logic negateA;
|
||||
logic negateB;
|
||||
logic [31:0] inA;
|
||||
logic [31:0] inB;
|
||||
|
||||
logic [31:0] div_result_muxed;
|
||||
logic [31:0] result_input;
|
||||
logic negateResult;
|
||||
|
||||
logic [31:0] div_result_sign_corrected;
|
||||
logic [31:0] wb_div_result;
|
||||
|
||||
|
@ -79,20 +75,21 @@ module div_unit(
|
|||
assign stage1 = input_fifo.data_out;
|
||||
/*********************************************/
|
||||
|
||||
assign start = input_fifo.valid & ( ~in_progress);
|
||||
assign output_ready = ~div_wb.done_next_cycle | (div_wb.done_next_cycle & div_wb.accepted);
|
||||
assign ack = div_complete & output_ready;
|
||||
|
||||
assign start = input_fifo.valid & (~in_progress) & ~(stage1.reuse_result | stage1.div_zero);
|
||||
//Abort prevents divider circuit from starting in the case that we are done in one cycle
|
||||
assign div_abort = input_fifo.valid & (stage1.div_zero | stage1.reuse_result);
|
||||
assign div_done = (div_complete | div_abort) & ~wb_fifo.full;
|
||||
assign div_done = (div_complete | (input_fifo.valid & (stage1.reuse_result | stage1.div_zero))) & output_ready;
|
||||
|
||||
//If more than one cycle, set in_progress so that multiple start signals are not sent to the div unit. Also in progress if an abort occurs but the output FIFO is full
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
if (rst)
|
||||
in_progress <= 0;
|
||||
end else if (start & ((div_abort & wb_fifo.full) | (~div_abort))) begin
|
||||
else if (start)
|
||||
in_progress <= 1;
|
||||
end else if (div_done) begin
|
||||
else if (ack)
|
||||
in_progress <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
//Input and output sign determination
|
||||
|
@ -103,52 +100,42 @@ module div_unit(
|
|||
|
||||
assign quotient_signed = signed_divop & (stage1.rs1[31] ^ stage1.rs2[31]);
|
||||
assign remainder_signed = signed_divop & (stage1.rs1[31]);
|
||||
|
||||
// Shared adders for sign conversion of inputs and outputs as they never occur on the same cycle
|
||||
//(div_complete | stage1.reuse_result) instead of div_done as other signals are not relevant for sign conversion
|
||||
//************
|
||||
assign inA = (div_complete | stage1.reuse_result) ? quotient : stage1.rs1;
|
||||
assign inB = (div_complete | stage1.reuse_result) ? remainder : stage1.rs2;
|
||||
|
||||
assign negateA = (div_complete | stage1.reuse_result) ? quotient_signed : dividend_signed;
|
||||
assign negateB = (div_complete | stage1.reuse_result) ? remainder_signed : divisor_signed;
|
||||
assign complementerA = (dividend_signed ? ~stage1.rs1 : stage1.rs1) + dividend_signed;
|
||||
assign complementerB = (divisor_signed ? ~stage1.rs2 : stage1.rs2) + divisor_signed;
|
||||
|
||||
assign complementerA = (negateA ? ~inA : inA) + negateA;
|
||||
assign complementerB = (negateB ? ~inB : inB) + negateB;
|
||||
assign result_input = stage1.op[1] ? remainder : quotient;
|
||||
assign negateResult = (stage1.op[1] ? remainder_signed : quotient_signed);
|
||||
assign div_result_sign_corrected = (negateResult ? ~result_input : result_input) + negateResult;
|
||||
assign wb_div_result = stage1.div_zero ? (stage1.op[1] ? stage1.rs1 : '1) : div_result_sign_corrected;
|
||||
//*************
|
||||
|
||||
//Synthesis time algorithm choice for divider
|
||||
generate
|
||||
if(USE_VARIABLE_LATENCY_DIV)
|
||||
quickdiv #(XLEN) div (.*, .start(start & ~div_abort), .A(complementerA), .B(complementerB), .Q(quotient), .R(remainder), .complete(div_complete), .ack(div_done));
|
||||
quickdiv #(XLEN) div (.*, .start(start), .A(complementerA), .B(complementerB), .Q(quotient), .R(remainder), .complete(div_complete), .ack(ack));
|
||||
else
|
||||
normdiv #(XLEN) div (.*, .start(start & ~div_abort), .A(complementerA), .B(complementerB), .Q(quotient), .R(remainder), .complete(div_complete), .ack(div_done));
|
||||
normdiv #(XLEN) div (.*, .start(start), .A(complementerA), .B(complementerB), .Q(quotient), .R(remainder), .complete(div_complete), .ack(ack));
|
||||
endgenerate
|
||||
|
||||
//Output muxing
|
||||
always_comb begin
|
||||
case (stage1.op)
|
||||
DIV_fn3[1:0] : div_result_muxed <= stage1.div_zero ? '1 : complementerA;
|
||||
DIVU_fn3[1:0] : div_result_muxed <= stage1.div_zero ? '1 : complementerA;
|
||||
REM_fn3[1:0] : div_result_muxed <=stage1.div_zero ? stage1.rs1 : complementerB;
|
||||
REMU_fn3[1:0] : div_result_muxed <= stage1.div_zero ? stage1.rs1 : complementerB;
|
||||
endcase
|
||||
/*********************************
|
||||
* Output registering/handshaking
|
||||
*********************************/
|
||||
always_ff @(posedge clk) begin
|
||||
if (div_done)
|
||||
div_wb.rd <= wb_div_result;
|
||||
end
|
||||
|
||||
/*********************************
|
||||
* Output FIFO
|
||||
*********************************/
|
||||
taiga_fifo #(.DATA_WIDTH(XLEN), .FIFO_DEPTH(DIV_OUTPUT_BUFFER_DEPTH), .FIFO_TYPE(NON_MUXED_INPUT_FIFO)
|
||||
) output_fifo (.fifo(wb_fifo), .*);
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
div_wb.done_next_cycle <= 0;
|
||||
else if (div_done)
|
||||
div_wb.done_next_cycle <= 1;
|
||||
else if (div_wb.accepted)
|
||||
div_wb.done_next_cycle <= 0;
|
||||
end
|
||||
|
||||
assign wb_fifo.data_in = div_result_muxed;
|
||||
assign wb_fifo.push = div_done;
|
||||
assign wb_fifo.pop = div_wb.accepted;
|
||||
assign div_wb.rd = wb_fifo.data_out;
|
||||
|
||||
assign div_wb.done = wb_fifo.early_valid;
|
||||
assign div_wb.early_done = 0;//div_done | (div_wb.done & ~div_wb.accepted);
|
||||
|
||||
/*********************************************/
|
||||
assign div_wb.done_on_first_cycle = 0;
|
||||
|
||||
endmodule
|
||||
|
|
218
core/fetch.sv
218
core/fetch.sv
|
@ -34,7 +34,7 @@ module fetch(
|
|||
ras_interface.fetch ras,
|
||||
|
||||
tlb_interface.mem tlb,
|
||||
bram_interface.user instruction_bram,
|
||||
local_memory_interface.master instruction_bram,
|
||||
input logic icache_on,
|
||||
l1_arbiter_request_interface.requester l1_request,
|
||||
l1_arbiter_return_interface.requester l1_response,
|
||||
|
@ -46,22 +46,24 @@ module fetch(
|
|||
|
||||
);
|
||||
|
||||
localparam NUM_SUB_UNITS = USE_I_SCRATCH_MEM + USE_ICACHE;
|
||||
localparam NUM_SUB_UNITS_W = $clog2(NUM_SUB_UNITS);
|
||||
|
||||
localparam BRAM_ID = 0;
|
||||
localparam ICACHE_ID = 1;
|
||||
localparam ICACHE_ID = USE_I_SCRATCH_MEM;
|
||||
|
||||
fetch_sub_unit_interface fetch_sub[1:0]();
|
||||
fetch_sub_unit_interface fetch_sub[NUM_SUB_UNITS-1:0]();
|
||||
|
||||
logic cache_access;
|
||||
logic bram_access;
|
||||
logic [NUM_SUB_UNITS-1:0] sub_unit_address_match;
|
||||
logic [NUM_SUB_UNITS-1:0] last_sub_unit_id;
|
||||
logic [NUM_SUB_UNITS-1:0] unit_ready;
|
||||
logic [NUM_SUB_UNITS-1:0] unit_data_valid;
|
||||
logic [31:0] unit_data_array [NUM_SUB_UNITS-1:0];
|
||||
logic units_ready;
|
||||
|
||||
logic mem_ready;
|
||||
|
||||
logic [31:0] offset;
|
||||
logic [31:0] next_pc_source;
|
||||
logic [31:0] next_pc;
|
||||
|
||||
logic [31:0] if_pc;
|
||||
logic stage1_prediction;
|
||||
|
||||
logic space_in_inst_buffer;
|
||||
logic new_mem_request;
|
||||
|
@ -74,10 +76,8 @@ module fetch(
|
|||
|
||||
logic [31:0] stage2_phys_address;
|
||||
logic stage2_valid;
|
||||
logic stage2_prediction;
|
||||
logic stage2_cache_access;
|
||||
|
||||
logic pc_valid;
|
||||
logic update_pc;
|
||||
|
||||
logic[6:0] opcode;
|
||||
logic[4:0] opcode_trimmed;
|
||||
|
@ -88,49 +88,51 @@ module fetch(
|
|||
logic sys_op;
|
||||
logic jal_jalr_x0;
|
||||
|
||||
assign flush = bt.flush | exception;
|
||||
logic rs1_link, rd_link, rs1_eq_rd, use_ras;
|
||||
logic predicted_control_flow;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
pc_valid <= 0;
|
||||
end else begin
|
||||
pc_valid <= 1;
|
||||
logic[$clog2(FETCH_BUFFER_DEPTH+1)-1:0] inflight_count;
|
||||
/////////////////////////////////////////
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for(i=0; i < NUM_SUB_UNITS; i++) begin
|
||||
assign unit_ready[i] = fetch_sub[i].ready;
|
||||
assign unit_data_valid[i] = fetch_sub[i].data_valid;
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
assign units_ready = &unit_ready;
|
||||
|
||||
assign bt.next_pc_valid = pc_valid;
|
||||
assign fetch_flush = (bt.flush | exception);
|
||||
assign flush = fetch_flush;
|
||||
|
||||
assign update_pc = new_mem_request | fetch_flush;
|
||||
|
||||
//Fetch PC
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
if (rst)
|
||||
if_pc <= RESET_VEC;
|
||||
end
|
||||
else if (new_mem_request | flush) begin
|
||||
else if (update_pc)
|
||||
if_pc <= {next_pc[31:2], 2'b0};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always_comb begin
|
||||
if (exception)
|
||||
next_pc = RESET_VEC;
|
||||
else if (bt.flush)
|
||||
next_pc = bt.branch_taken ? bt.jump_pc : bt.njump_pc;
|
||||
else if (bt.use_prediction) begin
|
||||
if (bt.use_ras & ras.valid)
|
||||
next_pc = ras.addr;
|
||||
else
|
||||
next_pc = bt.predicted_pc;
|
||||
end
|
||||
//else if (predicted_control_flow)
|
||||
// next_pc = (use_ras & ras.valid) ? ras.addr : bt.predicted_pc;
|
||||
else if (bt.use_prediction)
|
||||
next_pc = (bt.use_ras & ras.valid) ? ras.addr : bt.predicted_pc;
|
||||
else
|
||||
next_pc = if_pc + 4;
|
||||
end
|
||||
|
||||
assign bt.new_mem_request = new_mem_request | bt.flush;
|
||||
assign bt.new_mem_request = update_pc;
|
||||
assign bt.next_pc = next_pc;
|
||||
|
||||
assign if2_pc = if_pc;
|
||||
|
||||
assign bt.if_pc = if_pc;
|
||||
/*************************************
|
||||
* TLB
|
||||
|
@ -139,81 +141,83 @@ module fetch(
|
|||
assign tlb.execute = 1;
|
||||
assign tlb.rnw = 0;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst)
|
||||
stage2_valid <= 0;
|
||||
if (new_mem_request)
|
||||
stage2_valid <= 1;
|
||||
else if (new_issue | fetch_flush)
|
||||
stage2_valid <= 0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (new_mem_request) begin
|
||||
stage2_phys_address <= tlb.physical_address;
|
||||
stage2_cache_access <= cache_access;
|
||||
end
|
||||
end
|
||||
//////////////////////////////////////////////
|
||||
|
||||
|
||||
//Cache check done before cache access
|
||||
assign cache_access = tlb.physical_address[31:32-MEMORY_BIT_CHECK] == MEMORY_ADDR_L[31:32-MEMORY_BIT_CHECK];
|
||||
|
||||
//BRAM check can be done a cycle later, can be used for address checking
|
||||
assign bram_access = stage2_phys_address[31:32-SCRATCH_BIT_CHECK] == SCRATCH_ADDR_L[31:32-SCRATCH_BIT_CHECK];
|
||||
|
||||
assign mem_ready = fetch_sub[ICACHE_ID].ready;
|
||||
|
||||
assign fetch_flush = (bt.flush | exception);
|
||||
|
||||
assign space_in_inst_buffer = (stage2_valid & ~ib.early_full) | (~stage2_valid & ~ib.full);
|
||||
assign new_mem_request = pc_valid & tlb.complete & ~fetch_flush & space_in_inst_buffer & mem_ready;
|
||||
|
||||
assign fetch_sub[BRAM_ID].new_request = new_mem_request & bram_access;
|
||||
assign fetch_sub[ICACHE_ID].new_request = new_mem_request & cache_access;
|
||||
|
||||
assign fetch_sub[BRAM_ID].stage1_addr = tlb.physical_address;
|
||||
assign fetch_sub[ICACHE_ID].stage1_addr = tlb.physical_address;
|
||||
|
||||
assign fetch_sub[BRAM_ID].stage2_addr = stage2_phys_address;
|
||||
assign fetch_sub[ICACHE_ID].stage2_addr = stage2_phys_address;
|
||||
|
||||
//Memory interfaces
|
||||
generate if (USE_I_SCRATCH_MEM)
|
||||
ibram i_bram (.*, .fetch_sub(fetch_sub[BRAM_ID]));
|
||||
else begin
|
||||
assign fetch_sub[BRAM_ID].ready = 1;
|
||||
assign fetch_sub[BRAM_ID].data_valid = 0;
|
||||
assign fetch_sub[BRAM_ID].data_out = 0;
|
||||
end
|
||||
endgenerate
|
||||
generate if (USE_ICACHE)
|
||||
icache i_cache (.*, .fetch_sub(fetch_sub[ICACHE_ID]));
|
||||
else begin
|
||||
assign fetch_sub[ICACHE_ID].ready = 1;
|
||||
assign fetch_sub[ICACHE_ID].data_valid = 0;
|
||||
assign fetch_sub[ICACHE_ID].data_out = 0;
|
||||
end
|
||||
endgenerate
|
||||
//TODO potentially move support into cache so that we're not stalled on a request we no longer need due to a flush
|
||||
//If the cache is processing a miss when a flush occurs we need to discard the result once complete
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
delayed_flush <= 0;
|
||||
else if ((bt.flush | exception) & stage2_valid & stage2_cache_access & ~fetch_sub[ICACHE_ID].data_valid)//& ~fetch_sub[ICACHE_ID].ready
|
||||
delayed_flush <= 1;
|
||||
else if (fetch_sub[ICACHE_ID].data_valid)
|
||||
delayed_flush <= 0;
|
||||
if (rst | fetch_flush)
|
||||
inflight_count <= 0;
|
||||
else if (new_mem_request & ~ib.pop)
|
||||
inflight_count <= inflight_count + 1;
|
||||
else if (~new_mem_request & ib.pop)
|
||||
inflight_count <= inflight_count - 1;
|
||||
end
|
||||
|
||||
assign mem_valid = ~(bt.flush | exception | delayed_flush);
|
||||
assign new_issue = mem_valid & (fetch_sub[BRAM_ID].data_valid | fetch_sub[ICACHE_ID].data_valid);
|
||||
assign ib.push = new_issue;
|
||||
assign ib.flush = bt.flush;
|
||||
assign space_in_inst_buffer = inflight_count < FETCH_BUFFER_DEPTH;
|
||||
assign new_mem_request = tlb.complete & (~fetch_flush) & space_in_inst_buffer & units_ready;
|
||||
|
||||
assign ib.data_in.instruction = ({32{~stage2_cache_access}} & fetch_sub[BRAM_ID].data_out) |
|
||||
({32{stage2_cache_access}} & fetch_sub[ICACHE_ID].data_out);
|
||||
//Memory interfaces
|
||||
generate if (USE_I_SCRATCH_MEM) begin
|
||||
ibram i_bram (.*, .fetch_sub(fetch_sub[BRAM_ID]));
|
||||
assign sub_unit_address_match[BRAM_ID] = (tlb.physical_address[31:32-SCRATCH_BIT_CHECK] == SCRATCH_ADDR_L[31:32-SCRATCH_BIT_CHECK]);
|
||||
assign fetch_sub[BRAM_ID].new_request = new_mem_request & sub_unit_address_match[BRAM_ID];
|
||||
assign fetch_sub[BRAM_ID].stage1_addr = tlb.physical_address;
|
||||
assign fetch_sub[BRAM_ID].stage2_addr = stage2_phys_address;
|
||||
assign unit_data_array[BRAM_ID] = fetch_sub[BRAM_ID].data_out;
|
||||
end
|
||||
endgenerate
|
||||
generate if (USE_ICACHE) begin
|
||||
icache i_cache (.*, .fetch_sub(fetch_sub[ICACHE_ID]));
|
||||
assign sub_unit_address_match[ICACHE_ID] = tlb.physical_address[31:32-MEMORY_BIT_CHECK] == MEMORY_ADDR_L[31:32-MEMORY_BIT_CHECK];
|
||||
assign fetch_sub[ICACHE_ID].new_request = new_mem_request & sub_unit_address_match[ICACHE_ID];
|
||||
assign fetch_sub[ICACHE_ID].stage1_addr = tlb.physical_address;
|
||||
assign fetch_sub[ICACHE_ID].stage2_addr = stage2_phys_address;
|
||||
assign unit_data_array[ICACHE_ID] = fetch_sub[ICACHE_ID].data_out;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if(rst)
|
||||
stage2_valid <= 0;
|
||||
else if (new_mem_request)
|
||||
stage2_valid <= 1;
|
||||
else if (new_issue | fetch_flush)
|
||||
stage2_valid <= 0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (new_mem_request) begin
|
||||
last_sub_unit_id <= sub_unit_address_match;
|
||||
end
|
||||
end
|
||||
//TODO potentially move support into cache so that we're not stalled on a request we no longer need due to a flush
|
||||
//If the cache is processing a miss when a flush occurs we need to discard the result once complete
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
delayed_flush <= 0;
|
||||
else if (fetch_flush & stage2_valid & last_sub_unit_id[ICACHE_ID] & ~fetch_sub[ICACHE_ID].data_valid)//& ~fetch_sub[ICACHE_ID].ready
|
||||
delayed_flush <= 1;
|
||||
else if (fetch_sub[ICACHE_ID].data_valid)
|
||||
delayed_flush <= 0;
|
||||
end
|
||||
end else begin
|
||||
assign delayed_flush = 0;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign mem_valid = ~(bt.flush | exception | delayed_flush);
|
||||
assign new_issue = mem_valid & (|unit_data_valid);
|
||||
assign ib.push = new_issue;
|
||||
assign ib.flush = fetch_flush;
|
||||
|
||||
always_comb begin
|
||||
ib.data_in.instruction = {32{unit_data_valid[0]}} & unit_data_array[0];
|
||||
for(int i=1; i < NUM_SUB_UNITS; i++) begin
|
||||
ib.data_in.instruction |= {32{unit_data_valid[i]}} & unit_data_array[i];
|
||||
end
|
||||
end
|
||||
|
||||
assign ib.data_in.pc = stage2_phys_address;
|
||||
|
||||
|
@ -225,12 +229,20 @@ module fetch(
|
|||
assign csr_imm_op = (opcode_trimmed == SYSTEM_T) && fn3[2];
|
||||
assign sys_op = (opcode_trimmed == SYSTEM_T) && (fn3 == 0);
|
||||
|
||||
assign jal_jalr_x0 = ((opcode_trimmed == JAL_T) || (opcode_trimmed == JALR_T)) && (ib.data_in.instruction[11:7] == 0);//rd is x0
|
||||
assign jal_jalr_x0 = (opcode_trimmed inside {JAL_T, JALR_T}) && (ib.data_in.instruction[11:7] == 0);//rd is x0
|
||||
|
||||
//TODO: function for set comparison
|
||||
assign ib.data_in.uses_rs1 = !((opcode_trimmed == LUI_T) || (opcode_trimmed == AUIPC_T) || (opcode_trimmed == JAL_T) || (opcode_trimmed == FENCE_T) || csr_imm_op || sys_op);
|
||||
assign ib.data_in.uses_rs2 = ((opcode_trimmed == BRANCH_T) || (opcode_trimmed == STORE_T) || (opcode_trimmed == ARITH_T) || (opcode_trimmed == AMO_T) || (opcode_trimmed == CUSTOM_T));
|
||||
assign ib.data_in.uses_rd = !((opcode_trimmed == BRANCH_T) || (opcode_trimmed == STORE_T) || (opcode_trimmed == FENCE_T) || sys_op || jal_jalr_x0);
|
||||
assign predicted_control_flow = opcode_trimmed inside {JAL_T, JALR_T, BRANCH_T};
|
||||
|
||||
assign rs1_link = (ib.data_in.instruction[19:15] ==? 5'b00?01);
|
||||
assign rd_link = (ib.data_in.instruction[11:7] ==? 5'b00?01);
|
||||
assign rs1_eq_rd = (ib.data_in.instruction[19:15] == ib.data_in.instruction[11:7]);
|
||||
assign use_ras = ((opcode_trimmed == JALR_T & ((rs1_link & ~rd_link) | (rs1_link & rd_link & ~rs1_eq_rd))));
|
||||
|
||||
|
||||
|
||||
assign ib.data_in.uses_rs1 = !(opcode_trimmed inside {LUI_T, AUIPC_T, JAL_T, FENCE_T} || csr_imm_op || sys_op);
|
||||
assign ib.data_in.uses_rs2 = opcode_trimmed inside {BRANCH_T, STORE_T, ARITH_T, AMO_T, CUSTOM_T};
|
||||
assign ib.data_in.uses_rd = !(opcode_trimmed inside {BRANCH_T, STORE_T, FENCE_T} || sys_op || jal_jalr_x0);
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -28,23 +28,11 @@ module ibram(
|
|||
input logic rst,
|
||||
|
||||
fetch_sub_unit_interface.sub_unit fetch_sub,
|
||||
bram_interface.user instruction_bram
|
||||
local_memory_interface.master instruction_bram
|
||||
);
|
||||
|
||||
logic stage2_adv;
|
||||
logic address_range_valid;
|
||||
|
||||
assign fetch_sub.ready = 1;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
stage2_adv <= 0;
|
||||
end
|
||||
else begin
|
||||
stage2_adv <= fetch_sub.new_request;
|
||||
end
|
||||
end
|
||||
|
||||
assign instruction_bram.addr = fetch_sub.stage1_addr[31:2];
|
||||
assign instruction_bram.en = fetch_sub.new_request;
|
||||
assign instruction_bram.be = '0;
|
||||
|
@ -60,5 +48,4 @@ module ibram(
|
|||
fetch_sub.data_valid <= 0;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -58,15 +58,6 @@ module icache(
|
|||
* General Control Logic
|
||||
*************************************/
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
hit_allowed <= 0;
|
||||
end
|
||||
else begin
|
||||
hit_allowed <= fetch_sub.new_request & icache_on;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
second_cycle <= 0;
|
||||
|
@ -130,14 +121,14 @@ module icache(
|
|||
.stage2_addr(fetch_sub.stage2_addr),
|
||||
.update_way(tag_update_way),
|
||||
.update(tag_update),
|
||||
.stage1_adv(fetch_sub.new_request)
|
||||
.stage1_adv(fetch_sub.new_request & icache_on)
|
||||
);
|
||||
|
||||
//Data Banks
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < ICACHE_WAYS; i++) begin : data_bank_gen
|
||||
byte_en_BRAM #(ICACHE_LINES*ICACHE_LINE_W) data_bank (
|
||||
for (i=0; i < ICACHE_WAYS; i++) begin : idata_bank_gen
|
||||
byte_en_BRAM #(ICACHE_LINES*ICACHE_LINE_W) idata_bank (
|
||||
.clk(clk),
|
||||
.addr_a(fetch_sub.stage1_addr[ICACHE_LINE_ADDR_W+ICACHE_SUB_LINE_ADDR_W+2-1:2]),
|
||||
.addr_b({fetch_sub.stage2_addr[ICACHE_LINE_ADDR_W+ICACHE_SUB_LINE_ADDR_W+2-1:ICACHE_SUB_LINE_ADDR_W+2], word_count}),
|
||||
|
@ -180,7 +171,7 @@ module icache(
|
|||
end
|
||||
end
|
||||
|
||||
assign fetch_sub.data_valid = miss_data_ready | (hit_allowed & tag_hit);
|
||||
assign fetch_sub.data_valid = miss_data_ready | tag_hit;
|
||||
|
||||
/*************************************
|
||||
* Pipeline Advancement
|
||||
|
@ -194,14 +185,14 @@ module icache(
|
|||
memory_complete <= line_complete;
|
||||
end
|
||||
|
||||
assign fetch_sub.ready = (hit_allowed & tag_hit) | memory_complete | idle;//~(second_cycle & ~tag_hit) & ~miss;
|
||||
assign fetch_sub.ready = tag_hit | memory_complete | idle;//~(second_cycle & ~tag_hit) & ~miss;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
idle <= 1;
|
||||
else if (fetch_sub.new_request)
|
||||
idle <= 0;
|
||||
else if (memory_complete | (hit_allowed & tag_hit)) //read miss OR write through complete
|
||||
else if (memory_complete | tag_hit) //read miss OR write through complete
|
||||
idle <= 1;
|
||||
end
|
||||
|
||||
|
|
|
@ -81,13 +81,16 @@ module inflight_queue
|
|||
|
||||
//future rd_addt table
|
||||
logic [4:0] rd_addrs [INFLIGHT_QUEUE_DEPTH-1:0];
|
||||
logic rd_addr_not_zero [INFLIGHT_QUEUE_DEPTH-1:0];
|
||||
always_ff @ (posedge clk) begin
|
||||
if (iq.new_issue) begin
|
||||
rd_addrs[iq.data_in.id] <= iq.future_rd_addr;
|
||||
rd_addr_not_zero[iq.data_in.id] <= iq.uses_rd;
|
||||
end
|
||||
end
|
||||
|
||||
assign iq.wb_rd_addr = rd_addrs[iq.wb_id];
|
||||
assign iq.wb_uses_rd = rd_addr_not_zero[iq.wb_id];
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -44,7 +44,13 @@ module instruction_buffer
|
|||
assign ib_fifo.push = ib.push;
|
||||
assign ib_fifo.pop = ib.pop;
|
||||
assign ib_fifo.data_in = ib.data_in;
|
||||
assign ib.data_out = ib_fifo.data_out;
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
ib.data_out <= ib_fifo.data_out;
|
||||
end
|
||||
|
||||
//assign ib.data_out = ib_fifo.data_out;
|
||||
|
||||
assign ib.valid = ib_fifo.valid;
|
||||
assign ib.full = ib_fifo.full;
|
||||
assign ib.early_full = ib_fifo.early_full;
|
||||
|
|
|
@ -24,17 +24,6 @@ import taiga_config::*;
|
|||
import taiga_types::*;
|
||||
import l2_config_and_types::*;
|
||||
|
||||
interface bram_interface;
|
||||
logic[29:0] addr;
|
||||
logic en;
|
||||
logic[XLEN/8-1:0] be;
|
||||
logic[XLEN-1:0] data_in;
|
||||
logic[XLEN-1:0] data_out;
|
||||
|
||||
modport bram (input addr, en, be, data_in, output data_out);
|
||||
modport user (output addr, en, be, data_in, input data_out);
|
||||
endinterface
|
||||
|
||||
interface branch_table_interface;
|
||||
logic[31:0] if_pc;
|
||||
logic[31:0] dec_pc;
|
||||
|
@ -44,8 +33,6 @@ interface branch_table_interface;
|
|||
|
||||
logic[31:0] next_pc;
|
||||
|
||||
logic next_pc_valid;
|
||||
|
||||
logic branch_taken;
|
||||
logic branch_ex;
|
||||
logic prediction_dec;
|
||||
|
@ -58,8 +45,8 @@ interface branch_table_interface;
|
|||
logic use_prediction;
|
||||
logic use_ras;
|
||||
logic flush;
|
||||
modport branch_table (input if_pc, dec_pc, ex_pc, next_pc, njump_pc, jump_pc, branch_taken, branch_ex, is_return_ex, prediction_dec, next_pc_valid, new_mem_request, output predicted_pc, prediction, use_prediction, use_ras, flush);
|
||||
modport fetch (input predicted_pc, prediction, use_prediction, branch_taken, flush, njump_pc, jump_pc, use_ras, output if_pc, next_pc, next_pc_valid, new_mem_request);
|
||||
modport branch_table (input if_pc, dec_pc, ex_pc, next_pc, njump_pc, jump_pc, branch_taken, branch_ex, is_return_ex, prediction_dec, new_mem_request, output predicted_pc, prediction, use_prediction, use_ras, flush);
|
||||
modport fetch (input predicted_pc, prediction, use_prediction, branch_taken, flush, njump_pc, jump_pc, use_ras, output if_pc, next_pc, new_mem_request);
|
||||
modport decode (output dec_pc);
|
||||
modport branch_unit (output branch_taken, prediction_dec, branch_ex, is_return_ex, ex_pc, njump_pc, jump_pc);
|
||||
|
||||
|
@ -88,12 +75,12 @@ interface ras_interface;
|
|||
endinterface
|
||||
|
||||
interface unit_writeback_interface;
|
||||
logic done;
|
||||
logic early_done;
|
||||
logic done_next_cycle;
|
||||
logic done_on_first_cycle;
|
||||
logic accepted;
|
||||
logic [XLEN-1:0] rd;
|
||||
modport writeback (input done, early_done, rd, output accepted);
|
||||
modport unit (output done, early_done, rd, input accepted);
|
||||
modport writeback (input done_next_cycle, done_on_first_cycle, rd, output accepted);
|
||||
modport unit (output done_next_cycle, done_on_first_cycle, rd, input accepted);
|
||||
endinterface
|
||||
|
||||
//********************************
|
||||
|
@ -160,14 +147,17 @@ interface inflight_queue_interface;
|
|||
|
||||
inflight_queue_packet data_in;
|
||||
logic [4:0] future_rd_addr;
|
||||
logic uses_rd;
|
||||
logic wb_uses_rd;
|
||||
|
||||
inflight_queue_packet[INFLIGHT_QUEUE_DEPTH:0] data_out;
|
||||
logic [4:0] wb_rd_addr;
|
||||
instruction_id_t wb_id;
|
||||
logic [INFLIGHT_QUEUE_DEPTH:0] valid;
|
||||
|
||||
modport queue (input pop, data_in, new_issue, future_rd_addr, wb_id, output data_out, wb_rd_addr, shift_pop, valid);
|
||||
modport decode (output data_in, future_rd_addr, new_issue);
|
||||
modport wb (input data_in, future_rd_addr, shift_pop, valid, data_out, wb_rd_addr, output pop, wb_id);
|
||||
modport queue (input pop, data_in, new_issue, future_rd_addr, uses_rd, wb_id, output data_out, wb_rd_addr, wb_uses_rd, shift_pop, valid);
|
||||
modport decode (output data_in, future_rd_addr, uses_rd, new_issue);
|
||||
modport wb (input data_in, future_rd_addr, uses_rd, wb_uses_rd, shift_pop, valid, data_out, wb_rd_addr, output pop, wb_id);
|
||||
|
||||
endinterface
|
||||
|
||||
|
@ -197,7 +187,7 @@ interface instruction_buffer_interface;
|
|||
logic early_full;
|
||||
|
||||
modport buffer (input push, pop, flush, data_in, output data_out, valid, full, early_full);
|
||||
modport fetch (input full, early_full, output push, data_in, flush);
|
||||
modport fetch (input full, early_full, pop, output push, data_in, flush);
|
||||
modport decode (input valid, data_out, output pop);
|
||||
//modport exception_control (output flush);
|
||||
endinterface
|
||||
|
|
|
@ -77,7 +77,7 @@ module itag_banks(
|
|||
.data_in_b(stage2_tag), .data_out_b()
|
||||
);
|
||||
|
||||
assign tag_hit_way[i] = hit_allowed & (stage2_tag == tag_line[i]);
|
||||
assign tag_hit_way[i] = ({hit_allowed,stage2_tag} == {1'b1,tag_line[i]});
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
|
|
@ -41,7 +41,7 @@ module load_store_unit (
|
|||
axi_interface.master m_axi,
|
||||
avalon_interface.master m_avalon,
|
||||
|
||||
bram_interface.user data_bram,
|
||||
local_memory_interface.master data_bram,
|
||||
|
||||
output logic inorder,
|
||||
unit_writeback_interface.unit ls_wb
|
||||
|
@ -71,13 +71,15 @@ module load_store_unit (
|
|||
logic [3:0] be;
|
||||
|
||||
logic [31:0] unit_muxed_load_data;
|
||||
logic [31:0] aligned_load_data;
|
||||
logic [7:0] byte_load_data;
|
||||
logic [15:0] halfword_load_data;
|
||||
|
||||
logic [31:0] final_load_data;
|
||||
|
||||
logic [31:0] rs2_muxed;
|
||||
logic [31:0] most_recent_load;
|
||||
logic [31:0] forwarded_data;
|
||||
logic [31:0] previous_load;
|
||||
logic [31:0] previous_load, previous_load_r;
|
||||
logic [31:0] stage1_raw_data;
|
||||
|
||||
logic [31:0] unit_data_array [NUM_SUB_UNITS-1:0];
|
||||
|
@ -92,7 +94,7 @@ module load_store_unit (
|
|||
logic dcache_forward_data;
|
||||
logic [2:0] dcache_stage2_fn3;
|
||||
|
||||
logic [$clog2(LS_OUTPUT_BUFFER_DEPTH)-1:0] inflight_count;
|
||||
logic [1:0] inflight_count;
|
||||
|
||||
|
||||
//AMO support
|
||||
|
@ -125,9 +127,9 @@ module load_store_unit (
|
|||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
inflight_count <= 0;
|
||||
else if (issue_request & stage1.load & ~ls_wb.accepted)
|
||||
else if (load_attributes.push & ~ls_wb.accepted)
|
||||
inflight_count <= inflight_count + 1;
|
||||
else if (~issue_request & stage1.load & ls_wb.accepted)
|
||||
else if (~load_attributes.push & ls_wb.accepted)
|
||||
inflight_count <= inflight_count - 1;
|
||||
end
|
||||
|
||||
|
@ -146,14 +148,14 @@ module load_store_unit (
|
|||
|
||||
assign current_unit = sub_unit_address_match;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (issue_request)
|
||||
if (load_attributes.push)
|
||||
last_unit <= sub_unit_address_match;
|
||||
end
|
||||
|
||||
//When switching units, ensure no outstanding loads so that there can be no timing collisions with results
|
||||
assign unit_stall = (current_unit != last_unit) & ~load_attributes.empty;
|
||||
|
||||
assign issue_request = input_fifo.valid & units_ready & ~unit_stall & (inflight_count < LS_OUTPUT_BUFFER_DEPTH);
|
||||
assign issue_request = input_fifo.valid & units_ready & (inflight_count < 2) & ~unit_stall;
|
||||
assign load_complete = data_valid;
|
||||
|
||||
generate if (USE_D_SCRATCH_MEM) begin
|
||||
|
@ -180,7 +182,7 @@ module load_store_unit (
|
|||
* Input FIFO
|
||||
*********************************/
|
||||
taiga_fifo #(.DATA_WIDTH($bits(load_store_inputs_t)), .FIFO_DEPTH(LS_INPUT_BUFFER_DEPTH), .FIFO_TYPE(NON_MUXED_INPUT_FIFO)
|
||||
) ls_input_fifo (.fifo(input_fifo), .*);
|
||||
) ls_input_fifo (.fifo(input_fifo), .*);
|
||||
|
||||
assign input_fifo.data_in = ls_inputs;
|
||||
assign input_fifo.push = ls_ex.new_request_dec;
|
||||
|
@ -224,15 +226,18 @@ module load_store_unit (
|
|||
*/
|
||||
always_comb begin
|
||||
for (integer i = 0; i < XLEN/8; i = i+ 1) begin
|
||||
be[i] = stage1.store && (
|
||||
((stage1.fn3[1:0] == LS_W_fn3[1:0])) ||
|
||||
((stage1.fn3[1:0] == LS_H_fn3[1:0]) && (virtual_address[1] == i[1])) ||
|
||||
((stage1.fn3[1:0] == LS_B_fn3[1:0]) && (virtual_address[1:0] == i)));
|
||||
case(stage1.fn3[1:0])
|
||||
LS_B_fn3[1:0] : be[i] = stage1.store && (virtual_address[1:0] == i);
|
||||
LS_H_fn3[1:0] : be[i] = stage1.store && (virtual_address[1] == i[1]);
|
||||
LS_W_fn3[1:0] : be[i] = stage1.store;
|
||||
default : be[i] = 0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
assign most_recent_load = data_valid ? final_load_data : previous_load;
|
||||
assign stage1_raw_data = (stage1.load_store_forward | dcache_forward_data) ? most_recent_load : stage1.rs2;
|
||||
assign stage1_raw_data = (stage1.load_store_forward | dcache_forward_data) ?
|
||||
(data_valid ? final_load_data : previous_load) :
|
||||
stage1.rs2;
|
||||
|
||||
//AMO identification for dcache
|
||||
generate
|
||||
|
@ -255,11 +260,12 @@ module load_store_unit (
|
|||
assign d_inputs.store = stage1.store;
|
||||
assign d_inputs.be = be;
|
||||
assign d_inputs.fn3 = stage1.fn3;
|
||||
|
||||
always_comb begin
|
||||
case(dcache_forward_data ? dcache_stage2_fn3[1:0] : stage1.fn3[1:0]) //<--011, 110, 111, 100, 101 unused
|
||||
LS_B_fn3[1:0] : d_inputs.data_in = {4{stage1_raw_data[7:0]}};
|
||||
LS_H_fn3[1:0] : d_inputs.data_in = {2{stage1_raw_data[15:0]}};
|
||||
LS_W_fn3[1:0] : d_inputs.data_in = stage1_raw_data;
|
||||
default : d_inputs.data_in = {4{stage1_raw_data[7:0]}}; //LS_B_fn3
|
||||
default : d_inputs.data_in = stage1_raw_data;//LS_W_fn3
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -267,7 +273,7 @@ module load_store_unit (
|
|||
* Load attributes FIFO
|
||||
*********************************/
|
||||
taiga_fifo #(.DATA_WIDTH($bits(load_attributes_t)), .FIFO_DEPTH(ATTRIBUTES_DEPTH), .FIFO_TYPE(NON_MUXED_INPUT_FIFO)
|
||||
) attributes_fifo (.fifo(load_attributes), .*);
|
||||
) attributes_fifo (.fifo(load_attributes), .*);
|
||||
assign load_attributes_in.fn3 = stage1.fn3;
|
||||
assign load_attributes_in.byte_addr = virtual_address[1:0];
|
||||
assign load_attributes.data_in = load_attributes_in;
|
||||
|
@ -327,52 +333,57 @@ module load_store_unit (
|
|||
unit_muxed_load_data |= unit_data_array[i];
|
||||
end
|
||||
|
||||
//Byte select
|
||||
//Byte/halfword select: assumes aligned operations
|
||||
always_comb begin
|
||||
aligned_load_data[31:16] = unit_muxed_load_data[31:16];
|
||||
aligned_load_data[15:8] = stage2_attr.byte_addr[1] ? unit_muxed_load_data[31:24] : unit_muxed_load_data[15:8];
|
||||
halfword_load_data = stage2_attr.byte_addr[1] ? unit_muxed_load_data[31:16] : unit_muxed_load_data[15:0];
|
||||
case(stage2_attr.byte_addr)
|
||||
2'b00 : aligned_load_data[7:0] = unit_muxed_load_data[7:0];
|
||||
2'b01 : aligned_load_data[7:0] = unit_muxed_load_data[15:8];
|
||||
2'b10 : aligned_load_data[7:0] = unit_muxed_load_data[23:16];
|
||||
2'b11 : aligned_load_data[7:0] = unit_muxed_load_data[31:24];
|
||||
2'b00 : byte_load_data = unit_muxed_load_data[7:0];
|
||||
2'b01 : byte_load_data = unit_muxed_load_data[15:8];
|
||||
2'b10 : byte_load_data = unit_muxed_load_data[23:16];
|
||||
2'b11 : byte_load_data = unit_muxed_load_data[31:24];
|
||||
endcase
|
||||
end
|
||||
|
||||
//Sign extending
|
||||
always_comb begin
|
||||
case(stage2_attr.fn3)
|
||||
LS_B_fn3 : final_load_data = 32'(signed'(aligned_load_data[7:0]));
|
||||
LS_H_fn3 : final_load_data = 32'(signed'(aligned_load_data[15:0]));
|
||||
LS_W_fn3 : final_load_data = aligned_load_data;
|
||||
unique case(stage2_attr.fn3)
|
||||
LS_B_fn3 : final_load_data = 32'(signed'(byte_load_data));
|
||||
LS_H_fn3 : final_load_data = 32'(signed'(halfword_load_data));
|
||||
LS_W_fn3 : final_load_data = unit_muxed_load_data;
|
||||
//unused 011
|
||||
L_BU_fn3 : final_load_data = 32'(unsigned'(aligned_load_data[7:0]));
|
||||
L_HU_fn3 : final_load_data = 32'(unsigned'(aligned_load_data[15:0]));
|
||||
L_BU_fn3 : final_load_data = 32'(unsigned'(byte_load_data));
|
||||
L_HU_fn3 : final_load_data = 32'(unsigned'(halfword_load_data));
|
||||
//unused 110
|
||||
//unused 111
|
||||
default : final_load_data = aligned_load_data;
|
||||
//default : final_load_data = unit_muxed_load_data;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (data_valid)
|
||||
previous_load <= final_load_data;
|
||||
end
|
||||
|
||||
/*********************************
|
||||
* Output FIFO
|
||||
*********************************/
|
||||
taiga_fifo #(.DATA_WIDTH(XLEN), .FIFO_DEPTH(LS_OUTPUT_BUFFER_DEPTH), .FIFO_TYPE(NON_MUXED_INPUT_FIFO)
|
||||
) output_fifo (.fifo(wb_fifo), .*);
|
||||
logic[2:0] valid_chain;
|
||||
|
||||
assign wb_fifo.data_in = final_load_data;
|
||||
assign wb_fifo.push = load_complete;
|
||||
assign wb_fifo.pop = ls_wb.accepted;
|
||||
assign ls_wb.rd = wb_fifo.data_out;
|
||||
assign ls_wb.done = wb_fifo.early_valid;
|
||||
//Occupancy Tracking
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
valid_chain <= 1;
|
||||
else if (load_complete & ~ls_wb.accepted)
|
||||
valid_chain <= {valid_chain[2-1:0], 1'b0};
|
||||
else if (ls_wb.accepted & ~load_complete)
|
||||
valid_chain <= {1'b0, valid_chain[2:1]};
|
||||
end
|
||||
|
||||
assign ls_wb.early_done = 0;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (load_complete) begin
|
||||
previous_load <= final_load_data;
|
||||
previous_load_r <= previous_load;
|
||||
end
|
||||
end
|
||||
|
||||
assign ls_wb.rd = valid_chain[2] ? previous_load_r : previous_load;
|
||||
assign ls_wb.done_next_cycle = load_complete | valid_chain[2] | (valid_chain[1] & ~ls_wb.accepted);
|
||||
assign ls_wb.done_on_first_cycle = 0;
|
||||
/*********************************************/
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -31,14 +31,14 @@ module mul_unit(
|
|||
unit_writeback_interface.unit mul_wb
|
||||
);
|
||||
|
||||
logic [65:0] result;
|
||||
logic signed [65:0] result;
|
||||
logic [1:0] mulh;
|
||||
logic [1:0] advance;
|
||||
logic [1:0] valid;
|
||||
|
||||
logic rs1_signed, rs2_signed;
|
||||
logic [33:0] rs1_ext, rs2_ext;
|
||||
logic [33:0] rs1_r, rs2_r;
|
||||
logic signed [33:0] rs1_ext, rs2_ext;
|
||||
logic signed [33:0] rs1_r, rs2_r;
|
||||
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -71,7 +71,7 @@ module mul_unit(
|
|||
mulh[0] <= ~(mul_inputs.op[1:0] == 0);
|
||||
end
|
||||
if (advance[1]) begin
|
||||
result <= (rs1_r) * (rs2_r);
|
||||
result <= signed'(rs1_r) * signed'(rs2_r);
|
||||
mulh[1] <= mulh[0];
|
||||
end
|
||||
end
|
||||
|
@ -81,8 +81,8 @@ module mul_unit(
|
|||
assign mul_ex.ready = mul_wb.accepted | ~(&valid);
|
||||
|
||||
assign mul_wb.rd = mulh[1] ? result[63:32] : result[31:0];
|
||||
assign mul_wb.done = valid[0] | (valid[1] & ~mul_wb.accepted);
|
||||
assign mul_wb.early_done = 0;
|
||||
assign mul_wb.done_next_cycle = valid[0] | (valid[1] & ~mul_wb.accepted);
|
||||
assign mul_wb.done_on_first_cycle = 0;
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -36,7 +36,6 @@ module normdiv
|
|||
output logic complete
|
||||
);
|
||||
|
||||
logic running;
|
||||
logic terminate;
|
||||
|
||||
logic [C_WIDTH:0] new_PR;
|
||||
|
@ -48,10 +47,10 @@ module normdiv
|
|||
////////////////////////////////////////////////////
|
||||
assign new_PR = {1'b0, PR} - {1'b0, B};
|
||||
|
||||
//Shift reg for
|
||||
always_ff @ (posedge clk) begin
|
||||
shift_count[0] <= start;
|
||||
shift_count[31:1] <= shift_count[30:0];
|
||||
terminate <= shift_count[31];
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
|
@ -74,23 +73,24 @@ module normdiv
|
|||
assign R = PR[C_WIDTH:1];
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
running <= 0;
|
||||
complete <= 0;
|
||||
end
|
||||
if (rst)
|
||||
terminate <= 0;
|
||||
else begin
|
||||
if (start) begin
|
||||
running <= 1;
|
||||
complete <= 0;
|
||||
end
|
||||
else if (running & terminate) begin
|
||||
running <= 0;
|
||||
if (start)
|
||||
terminate <= 0;
|
||||
if (shift_count[31])
|
||||
terminate <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
complete <= 0;
|
||||
else begin
|
||||
if (shift_count[31])
|
||||
complete <= 1;
|
||||
end
|
||||
else if (ack) begin
|
||||
running <= 0;
|
||||
else if (ack)
|
||||
complete <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
92
core/one_hot_occupancy.sv
Normal file
92
core/one_hot_occupancy.sv
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright © 2017 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 one_hot_occupancy #(parameter DEPTH = 2)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
input logic push,
|
||||
input logic pop,
|
||||
output logic early_full,
|
||||
output logic full,
|
||||
output logic empty,
|
||||
output logic valid,
|
||||
output logic early_valid,
|
||||
output logic two_plus
|
||||
);
|
||||
|
||||
|
||||
logic[DEPTH:0] valid_chain;
|
||||
|
||||
//Occupancy Tracking
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
valid_chain <= 1;
|
||||
else if (push & ~pop)
|
||||
valid_chain <= {valid_chain[DEPTH-1:0], 1'b0};
|
||||
else if (pop & ~push)
|
||||
valid_chain <= {1'b0, valid_chain[DEPTH:1]};
|
||||
end
|
||||
|
||||
assign empty = valid_chain[0];
|
||||
assign valid = ~valid_chain[0];
|
||||
assign full = valid_chain[DEPTH];
|
||||
|
||||
// always_ff @ (posedge clk) begin
|
||||
// if (rst)
|
||||
// early_full <= 0;
|
||||
// else if (push & ~pop & valid_chain[DEPTH-2])
|
||||
// early_full <= 1;
|
||||
// else if (pop & ~push & valid_chain[DEPTH-1])
|
||||
// early_full <= 0;
|
||||
// end
|
||||
|
||||
|
||||
assign early_full = valid_chain[DEPTH-1] | valid_chain[DEPTH];
|
||||
|
||||
//pushing, or more than one, or at least one and not popping
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
two_plus <= 0;
|
||||
else if ((valid & push) & ~pop)
|
||||
two_plus <= 1;
|
||||
else if (~push & (two_plus & pop))
|
||||
two_plus <= 0;
|
||||
end
|
||||
|
||||
// assign two_plus = ~valid_chain[0] & ~valid_chain[1];
|
||||
assign early_valid = push | (two_plus) | (valid & ~pop);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
always_ff @ (posedge clk) begin
|
||||
assert (!(~rst & valid_chain[DEPTH] & push)) else $error("overflow");
|
||||
assert (!(~rst & valid_chain[0] & pop)) else $error("underflow");
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
@ -27,20 +27,18 @@ module taiga (
|
|||
input logic clk,
|
||||
input logic rst,
|
||||
|
||||
bram_interface.user instruction_bram,
|
||||
bram_interface.user data_bram,
|
||||
local_memory_interface.master instruction_bram,
|
||||
local_memory_interface.master data_bram,
|
||||
|
||||
axi_interface.master m_axi,
|
||||
avalon_interface.master m_avalon,
|
||||
|
||||
l2_requester_interface.requester l2,
|
||||
|
||||
input logic interrupt,
|
||||
|
||||
//debug
|
||||
output logic[31:0] dec_pc_debug,
|
||||
output logic[31:0] if2_pc_debug,
|
||||
output logic[31:0] dec_pc_debug
|
||||
|
||||
input logic interrupt
|
||||
);
|
||||
|
||||
l1_arbiter_request_interface l1_request[L1_CONNECTIONS-1:0]();
|
||||
|
@ -72,9 +70,6 @@ module taiga (
|
|||
id_generator_interface id_gen();
|
||||
|
||||
unit_writeback_interface unit_wb [NUM_WB_UNITS-1:0]();
|
||||
|
||||
//writeback_unit_interface unit_wb();
|
||||
|
||||
register_file_writeback_interface rf_wb();
|
||||
|
||||
csr_exception_interface csr_exception();
|
||||
|
@ -110,12 +105,11 @@ module taiga (
|
|||
logic instruction_issued_no_rd;
|
||||
logic instruction_complete;
|
||||
|
||||
assign instruction_issued = dec_advance;
|
||||
|
||||
|
||||
assign if2_pc_debug = if2_pc;
|
||||
assign dec_pc_debug = dec_pc;
|
||||
|
||||
assign instruction_issued = dec_advance;
|
||||
|
||||
|
||||
/*************************************
|
||||
* Memory Interface
|
||||
|
@ -154,14 +148,6 @@ module taiga (
|
|||
*************************************/
|
||||
branch_unit branch_unit_block (.*, .branch_wb(unit_wb[BRANCH_UNIT_ID].unit));
|
||||
alu_unit alu_unit_block (.*, .alu_wb(unit_wb[ALU_UNIT_ID].unit));
|
||||
|
||||
// genvar i;
|
||||
// generate
|
||||
// for (i = 0; i < 5; i++) begin
|
||||
// alu_unit single_cycle_accelerators (.*, .alu_ex(single_accel), .alu_wb(unit_wb[ACCEL+i].unit));
|
||||
// end
|
||||
// endgenerate
|
||||
//
|
||||
load_store_unit load_store_unit_block (.*, .dcache_on(1'b1), .clear_reservation(1'b0), .tlb(dtlb), .ls_wb(unit_wb[LS_UNIT_ID].unit), .l1_request(l1_request[L1_DCACHE_ID]), .l1_response(l1_response[L1_DCACHE_ID]));
|
||||
generate if (USE_MMU) begin
|
||||
tlb_lut_ram #(DTLB_WAYS, DTLB_DEPTH) d_tlb (.*, .tlb(dtlb), .mmu(dmmu));
|
||||
|
|
|
@ -41,33 +41,24 @@ package taiga_config;
|
|||
|
||||
parameter USE_AMO = 0;
|
||||
|
||||
parameter NUM_WB_UNITS = 6;
|
||||
parameter NUM_WB_UNITS = 4 + USE_MUL + USE_DIV;
|
||||
parameter WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
|
||||
|
||||
typedef enum {//bit [WB_UNITS_WIDTH-1:0] {
|
||||
ALU_UNIT_ID = 0,
|
||||
BRANCH_UNIT_ID=1,
|
||||
CSR_UNIT_ID = 2,
|
||||
LS_UNIT_ID = 3,
|
||||
MUL_UNIT_ID = 4,
|
||||
DIV_UNIT_ID = 5,
|
||||
CUSTOM_ID_0 = 6,
|
||||
CUSTOM_ID_1 = 7,
|
||||
CUSTOM_ID_2 = 8,
|
||||
CUSTOM_ID_3 = 9
|
||||
} unit_ids;
|
||||
typedef logic[WB_UNITS_WIDTH-1:0] unit_ids;
|
||||
|
||||
parameter ALU_UNIT_ID = 0;
|
||||
parameter BRANCH_UNIT_ID = 1;
|
||||
parameter CSR_UNIT_ID = 2;
|
||||
parameter LS_UNIT_ID = 3;
|
||||
parameter MUL_UNIT_ID = LS_UNIT_ID + USE_MUL;
|
||||
parameter DIV_UNIT_ID = LS_UNIT_ID + USE_MUL + USE_DIV;
|
||||
|
||||
|
||||
parameter INFLIGHT_QUEUE_DEPTH = 4;
|
||||
parameter FETCH_BUFFER_DEPTH = 4;
|
||||
|
||||
parameter LS_INPUT_BUFFER_DEPTH = 4;
|
||||
parameter LS_OUTPUT_BUFFER_DEPTH = 4;
|
||||
|
||||
parameter MUL_CYCLES = 1;
|
||||
parameter MUL_OUTPUT_BUFFER_DEPTH = 2;
|
||||
|
||||
parameter DIV_INPUT_BUFFER_DEPTH = 2;
|
||||
parameter DIV_OUTPUT_BUFFER_DEPTH = 2;
|
||||
|
||||
//Address space
|
||||
parameter USE_I_SCRATCH_MEM = 1;
|
||||
|
@ -94,10 +85,10 @@ package taiga_config;
|
|||
//Caches
|
||||
//Size in bytes: (DCACHE_LINES * DCACHE_WAYS * DCACHE_LINE_W * 4)
|
||||
parameter USE_DCACHE = 0;
|
||||
parameter DCACHE_LINES = 512;
|
||||
parameter DCACHE_LINES = 256;
|
||||
parameter DCACHE_WAYS = 2;
|
||||
parameter DCACHE_LINE_ADDR_W = $clog2(DCACHE_LINES);
|
||||
parameter DCACHE_LINE_W = 8; //In words
|
||||
parameter DCACHE_LINE_W = 4; //In words
|
||||
parameter DCACHE_SUB_LINE_ADDR_W = $clog2(DCACHE_LINE_W);
|
||||
parameter DCACHE_TAG_W = ADDR_W - DCACHE_LINE_ADDR_W - DCACHE_SUB_LINE_ADDR_W - 2;
|
||||
|
||||
|
@ -110,14 +101,14 @@ package taiga_config;
|
|||
//Size in bytes: (ICACHE_LINES * ICACHE_WAYS * ICACHE_LINE_W * 4)
|
||||
//For optimal BRAM packing lines should not be less than 512
|
||||
parameter USE_ICACHE = 0;
|
||||
parameter ICACHE_LINES = 128;
|
||||
parameter ICACHE_LINES = 256;
|
||||
parameter ICACHE_WAYS = 2;
|
||||
parameter ICACHE_LINE_ADDR_W = $clog2(ICACHE_LINES);
|
||||
parameter ICACHE_LINE_W = 8; //In words
|
||||
parameter ICACHE_LINE_W = 4; //In words
|
||||
parameter ICACHE_SUB_LINE_ADDR_W = $clog2(ICACHE_LINE_W);
|
||||
parameter ICACHE_TAG_W = ADDR_W - ICACHE_LINE_ADDR_W - ICACHE_SUB_LINE_ADDR_W - 2;
|
||||
|
||||
parameter USE_BRANCH_PREDICTOR = 1;
|
||||
parameter USE_BRANCH_PREDICTOR = 0;
|
||||
parameter BRANCH_TABLE_ENTRIES = 512;
|
||||
parameter RAS_DEPTH = 8;
|
||||
|
||||
|
|
|
@ -34,42 +34,31 @@ module taiga_fifo #(parameter DATA_WIDTH = 42, parameter FIFO_DEPTH = 4, paramet
|
|||
fifo_interface.structure fifo
|
||||
);
|
||||
|
||||
logic[DATA_WIDTH-1:0] lut_ram[FIFO_DEPTH-1:0];
|
||||
(* ramstyle = "MLAB, no_rw_check" *) logic[DATA_WIDTH-1:0] lut_ram[FIFO_DEPTH-1:0];
|
||||
logic[DATA_WIDTH-1:0] shift_reg[FIFO_DEPTH-1:0];
|
||||
logic[DATA_WIDTH-1:0] shift_reg_new[FIFO_DEPTH-1:0];
|
||||
|
||||
logic[$clog2(FIFO_DEPTH)-1:0] write_index;
|
||||
logic[$clog2(FIFO_DEPTH)-1:0] read_index;
|
||||
|
||||
logic two_plus;
|
||||
logic[FIFO_DEPTH:0] valid_chain;
|
||||
|
||||
genvar i;
|
||||
|
||||
//implementation
|
||||
////////////////////////////////////////////////////
|
||||
//Occupancy Tracking
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
valid_chain <= 1;
|
||||
else if (fifo.push & ~fifo.pop)
|
||||
valid_chain <= {valid_chain[FIFO_DEPTH-1:0], 1'b0};
|
||||
else if (fifo.pop & ~fifo.push)
|
||||
valid_chain <= {1'b0, valid_chain[FIFO_DEPTH:1]};
|
||||
end
|
||||
one_hot_occupancy #(.DEPTH(FIFO_DEPTH)) occupancy_tracking
|
||||
(
|
||||
.push(fifo.push), .pop(fifo.pop),
|
||||
.early_full(fifo.early_full), .full(fifo.full),
|
||||
.empty(fifo.empty), .valid(fifo.valid), .early_valid(fifo.early_valid), .two_plus(two_plus), .*
|
||||
);
|
||||
|
||||
assign fifo.empty = valid_chain[0];
|
||||
assign fifo.valid = ~valid_chain[0];
|
||||
assign fifo.full = valid_chain[FIFO_DEPTH];
|
||||
assign fifo.early_full = valid_chain[FIFO_DEPTH-1] | valid_chain[FIFO_DEPTH];
|
||||
|
||||
//pushing, or more than one, or at least one and not popping
|
||||
assign two_plus = ~valid_chain[0] & ~valid_chain[1];
|
||||
assign fifo.early_valid = fifo.push | (two_plus) | (fifo.valid & ~fifo.pop);
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//LUT-RAM version
|
||||
generate if (FIFO_TYPE == LUTRAM_FIFO) begin
|
||||
////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst) begin
|
||||
|
@ -81,7 +70,6 @@ module taiga_fifo #(parameter DATA_WIDTH = 42, parameter FIFO_DEPTH = 4, paramet
|
|||
write_index <= write_index + fifo.push;
|
||||
end
|
||||
end
|
||||
|
||||
assign fifo.data_out = lut_ram[read_index];
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
|
@ -94,13 +82,22 @@ module taiga_fifo #(parameter DATA_WIDTH = 42, parameter FIFO_DEPTH = 4, paramet
|
|||
////////////////////////////////////////////////////
|
||||
//SRL version
|
||||
generate if (FIFO_TYPE == NON_MUXED_INPUT_FIFO) begin
|
||||
////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
// always_ff @ (posedge clk) begin
|
||||
// if (rst)
|
||||
// read_index <= 0;
|
||||
// else if ((fifo.valid & fifo.push) | (two_plus & fifo.pop))
|
||||
// read_index <= read_index + fifo.push - fifo.pop;
|
||||
// end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
read_index <= 0;
|
||||
else if ((fifo.valid & fifo.push) | (two_plus & fifo.pop))
|
||||
read_index <= read_index + fifo.push - fifo.pop;
|
||||
else if ((fifo.valid & fifo.push) & ~fifo.pop)
|
||||
read_index <= read_index + 1;
|
||||
else if (~fifo.push & (two_plus & fifo.pop))
|
||||
read_index <= read_index - 1;
|
||||
end
|
||||
|
||||
assign fifo.data_out = shift_reg[read_index];
|
||||
|
@ -110,7 +107,7 @@ module taiga_fifo #(parameter DATA_WIDTH = 42, parameter FIFO_DEPTH = 4, paramet
|
|||
shift_reg[0] <= fifo.data_in;
|
||||
end
|
||||
|
||||
for (i=1 ; i < FIFO_DEPTH; i++) begin : shift_reg_gen
|
||||
for (i=1 ; i < FIFO_DEPTH; i++) begin : taiga_fifo_shift_reg_gen
|
||||
always_ff @ (posedge clk) begin
|
||||
if (fifo.push)
|
||||
shift_reg[i] <= shift_reg[i-1];
|
||||
|
@ -122,7 +119,7 @@ module taiga_fifo #(parameter DATA_WIDTH = 42, parameter FIFO_DEPTH = 4, paramet
|
|||
////////////////////////////////////////////////////
|
||||
//Non-muxed output version
|
||||
generate if (FIFO_TYPE == NON_MUXED_OUTPUT_FIFO) begin
|
||||
////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
|
@ -133,7 +130,7 @@ module taiga_fifo #(parameter DATA_WIDTH = 42, parameter FIFO_DEPTH = 4, paramet
|
|||
|
||||
assign fifo.data_out = shift_reg[0];
|
||||
|
||||
for (i=0 ; i <FIFO_DEPTH; i++) begin : new_reg_non_muxed_gen
|
||||
for (i=0 ; i <FIFO_DEPTH; i++) begin : taiga_fifo_new_reg_non_muxed_gen
|
||||
always_comb begin
|
||||
if (fifo.push && write_index == i)
|
||||
shift_reg_new[i] = fifo.data_in;
|
||||
|
@ -146,7 +143,7 @@ module taiga_fifo #(parameter DATA_WIDTH = 42, parameter FIFO_DEPTH = 4, paramet
|
|||
shift_reg[FIFO_DEPTH-1] <= shift_reg_new[FIFO_DEPTH-1];
|
||||
end
|
||||
|
||||
for (i=0 ; i < FIFO_DEPTH-1; i++) begin : shift_reg_non_muxed_gen
|
||||
for (i=0 ; i < FIFO_DEPTH-1; i++) begin : taiga_fifo_shift_reg_non_muxed_gen
|
||||
always_ff @ (posedge clk) begin
|
||||
if (fifo.pop)
|
||||
shift_reg[i] <= shift_reg_new[i+1];
|
||||
|
@ -157,12 +154,6 @@ module taiga_fifo #(parameter DATA_WIDTH = 42, parameter FIFO_DEPTH = 4, paramet
|
|||
|
||||
end
|
||||
endgenerate
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
always_ff @ (posedge clk) begin
|
||||
assert (!(~rst & valid_chain[FIFO_DEPTH] & fifo.push)) else $error("fifo overflow");
|
||||
assert (!(~rst & valid_chain[0] & fifo.pop)) else $error("fifo underflow");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -67,6 +67,20 @@ package taiga_types;
|
|||
AND_fn3 = 3'b111
|
||||
} fn3_arith_t;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
ALU_ADD_SUB = 2'b00,
|
||||
ALU_LOGIC = 2'b01,
|
||||
ALU_SLT = 2'b10,
|
||||
ALU_SHIFT =2'b11
|
||||
} alu_op_t;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
ALU_XOR = 2'b00,
|
||||
ALU_OR = 2'b01,
|
||||
ALU_AND = 2'b10,
|
||||
ALU_ADD_SUB2 = 2'b11
|
||||
} alu_logicop_t;
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
LS_B_fn3 = 3'b000,
|
||||
LS_H_fn3 = 3'b001,
|
||||
|
@ -228,21 +242,6 @@ package taiga_types;
|
|||
M_EXTERNAL_INTERRUPT = 4'd11
|
||||
} interrupt_code_t;
|
||||
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
ALU_SLT = 2'b00,
|
||||
ALU_SHIFTR = 2'b01,
|
||||
ALU_SHIFT =2'b10,
|
||||
ALU_LOGIC = 2'b11
|
||||
} alu_op_t;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
ALU_XOR = 2'b00,
|
||||
ALU_OR = 2'b01,
|
||||
ALU_AND = 2'b10,
|
||||
ALU_ADD_SUB = 2'b11
|
||||
} alu_logicop_t;
|
||||
|
||||
typedef logic[$clog2(INFLIGHT_QUEUE_DEPTH)-1:0] instruction_id_t;
|
||||
|
||||
|
||||
|
@ -262,13 +261,12 @@ package taiga_types;
|
|||
|
||||
|
||||
typedef struct packed{
|
||||
logic [XLEN-1:0] in1;
|
||||
logic [XLEN-1:0] in2;
|
||||
logic [XLEN:0] in1;//contains sign padding bit for slt operation
|
||||
logic [XLEN:0] in2;//contains sign padding bit for slt operation
|
||||
logic subtract;
|
||||
logic arith;
|
||||
logic [XLEN-1:0] shifter_in;
|
||||
logic sltu;
|
||||
logic [1:0] logic_op;
|
||||
logic arith;//contains sign padding bit for arithmetic shift right operation
|
||||
logic lshift;
|
||||
logic [2:0] fn3;
|
||||
logic [1:0] op;
|
||||
}alu_inputs_t;
|
||||
|
||||
|
@ -337,6 +335,7 @@ package taiga_types;
|
|||
logic [XLEN-1:0] rs1;
|
||||
logic [XLEN-1:0] rs2;
|
||||
logic [1:0] op;
|
||||
logic skip_algo;
|
||||
logic reuse_result;
|
||||
logic div_zero;
|
||||
} div_inputs_t;
|
||||
|
@ -358,7 +357,7 @@ package taiga_types;
|
|||
logic con;
|
||||
} to_l1_arbiter_packet;
|
||||
|
||||
typedef struct {
|
||||
typedef struct packed {
|
||||
logic [31:0] addr;
|
||||
logic load;
|
||||
logic store;
|
||||
|
|
|
@ -35,26 +35,29 @@ module write_back(
|
|||
output logic instruction_complete
|
||||
);
|
||||
|
||||
logic [NUM_WB_UNITS-1:0] early_done;
|
||||
logic [NUM_WB_UNITS-1:0] done;
|
||||
logic [NUM_WB_UNITS-1:0] done_on_first_cycle;
|
||||
logic [NUM_WB_UNITS-1:0] done_next_cycle;
|
||||
|
||||
logic selected_unit_done;
|
||||
logic selected_unit_done_next_cycle;
|
||||
logic entry_found;
|
||||
|
||||
logic [NUM_WB_UNITS-1:0] accepted;
|
||||
logic [NUM_WB_UNITS-1:0] new_accepted;
|
||||
|
||||
logic [XLEN-1:0] rd [NUM_WB_UNITS-1:0];
|
||||
|
||||
logic [4:0] rd_addr, rd_addr_r;
|
||||
logic rd_addr_not_zero;
|
||||
logic [WB_UNITS_WIDTH-1:0] unit_id, unit_id_r;
|
||||
instruction_id_t issue_id, issue_id_r;
|
||||
|
||||
int iq_index;
|
||||
|
||||
//Re-assigning interface inputs to array types so that they can be dynamically indexed
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i< NUM_WB_UNITS; i++) begin : interface_to_array_g
|
||||
assign done[i] = unit_wb[i].done;
|
||||
assign early_done[i] = unit_wb[i].early_done;
|
||||
assign done_next_cycle[i] = unit_wb[i].done_next_cycle;
|
||||
assign done_on_first_cycle[i] = unit_wb[i].done_on_first_cycle;
|
||||
assign rd[i] = unit_wb[i].rd;
|
||||
assign unit_wb[i].accepted = accepted[i];
|
||||
end
|
||||
|
@ -67,17 +70,17 @@ module write_back(
|
|||
always_comb begin
|
||||
entry_found = 0;
|
||||
iq.pop = 0;
|
||||
selected_unit_done = 0;
|
||||
selected_unit_done_next_cycle = 0;
|
||||
|
||||
for (int i=INFLIGHT_QUEUE_DEPTH; i>0; i--) begin
|
||||
unit_id = iq.data_out[i].unit_id;
|
||||
issue_id = iq.data_out[i].id;
|
||||
for (iq_index=INFLIGHT_QUEUE_DEPTH; iq_index>0; iq_index--) begin
|
||||
unit_id = iq.data_out[iq_index].unit_id;
|
||||
issue_id = iq.data_out[iq_index].id;
|
||||
|
||||
if (iq.valid[i]) begin
|
||||
selected_unit_done = done[iq.data_out[i].unit_id];
|
||||
iq.pop[i] = done[iq.data_out[i].unit_id];
|
||||
if (iq.valid[iq_index]) begin
|
||||
selected_unit_done_next_cycle = done_next_cycle[unit_id];
|
||||
iq.pop[iq_index] = selected_unit_done_next_cycle;
|
||||
|
||||
if (inorder | (~inorder & done[iq.data_out[i].unit_id])) begin
|
||||
if (inorder | (~inorder & selected_unit_done_next_cycle)) begin
|
||||
entry_found = 1;
|
||||
break;
|
||||
end
|
||||
|
@ -87,23 +90,30 @@ module write_back(
|
|||
//Access rd_addr table in inflight_queue
|
||||
iq.wb_id = issue_id;
|
||||
rd_addr = iq.wb_rd_addr;
|
||||
rd_addr_not_zero = |rd_addr;//iq.wb_uses_rd;
|
||||
|
||||
//No valid completing instructions in queue, check for new issues.
|
||||
if (~entry_found) begin
|
||||
unit_id = iq.data_out[0].unit_id;
|
||||
issue_id = iq.data_out[0].id;
|
||||
rd_addr = iq.future_rd_addr;
|
||||
rd_addr_not_zero = iq.uses_rd;
|
||||
|
||||
//Pop and unit done only if valid issue
|
||||
selected_unit_done = early_done[iq.data_out[0].unit_id] & iq.valid[0];
|
||||
iq.pop[0] = early_done[iq.data_out[0].unit_id] & iq.valid[0];
|
||||
if (iq.valid[0]) begin
|
||||
selected_unit_done_next_cycle = done_on_first_cycle[unit_id];
|
||||
iq.pop[0] = selected_unit_done_next_cycle;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
instruction_complete <= 0;
|
||||
else
|
||||
instruction_complete <= selected_unit_done;
|
||||
instruction_complete <= selected_unit_done_next_cycle;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
|
@ -120,23 +130,24 @@ module write_back(
|
|||
if (rst)
|
||||
rf_wb.valid_write <= 0;
|
||||
else
|
||||
rf_wb.valid_write <= selected_unit_done && (rd_addr != 0);
|
||||
rf_wb.valid_write <= selected_unit_done_next_cycle & rd_addr_not_zero;
|
||||
end
|
||||
|
||||
assign rf_wb.rd_addr_early = rd_addr;
|
||||
assign rf_wb.id_early = issue_id;
|
||||
assign rf_wb.valid_write_early = selected_unit_done;
|
||||
assign rf_wb.valid_write_early = selected_unit_done_next_cycle;
|
||||
|
||||
generate
|
||||
for (i=0; i<NUM_WB_UNITS; i=i+1) begin : wb_mux
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
accepted[i] <= 0;
|
||||
else
|
||||
accepted[i] <= selected_unit_done && (unit_id == i);
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
always_comb begin
|
||||
new_accepted = 0;
|
||||
new_accepted[unit_id] = selected_unit_done_next_cycle;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
accepted <= 0;
|
||||
else
|
||||
accepted <= new_accepted;
|
||||
end
|
||||
|
||||
//ID generator signals
|
||||
assign id_gen.complete = instruction_complete;
|
||||
|
|
|
@ -222,8 +222,8 @@ module taiga_wrapper (
|
|||
assign m_axi.bresp = bus_axi_bresp;
|
||||
|
||||
|
||||
bram_interface instruction_bram();
|
||||
bram_interface data_bram();
|
||||
local_memory_interface instruction_bram();
|
||||
local_memory_interface data_bram();
|
||||
|
||||
taiga cpu(.*, .l2(l2[0]));
|
||||
|
||||
|
@ -238,15 +238,15 @@ module taiga_wrapper (
|
|||
|
||||
arm proc(.*);
|
||||
|
||||
byte_en_BRAM #(8192*4, "/home/ematthew/Research/RISCV/software2/riscv-tools/riscv-tests/benchmarks/dhrystone.riscv.hw_init", 1) inst_data_ram (
|
||||
byte_en_BRAM #(8192, "/home/ematthew/Research/RISCV/software2/riscv-tools/riscv-tests/benchmarks/dhrystone.riscv.hw_init", 1) inst_data_ram (
|
||||
.clk(clk),
|
||||
.addr_a(instruction_bram.addr[$clog2(8192*4)- 1:0]),
|
||||
.addr_a(instruction_bram.addr[$clog2(8192)- 1:0]),
|
||||
.en_a(instruction_bram.en),
|
||||
.be_a(instruction_bram.be),
|
||||
.data_in_a(instruction_bram.data_in),
|
||||
.data_out_a(instruction_bram.data_out),
|
||||
|
||||
.addr_b(data_bram.addr[$clog2(8192*4)- 1:0]),
|
||||
.addr_b(data_bram.addr[$clog2(8192)- 1:0]),
|
||||
.en_b(data_bram.en),
|
||||
.be_b(data_bram.be),
|
||||
.data_in_b(data_bram.data_in),
|
||||
|
|
|
@ -27,7 +27,7 @@ import taiga_config::*;
|
|||
import taiga_types::*;
|
||||
import l2_config_and_types::*;
|
||||
|
||||
`define MEMORY_FILE "/home/ematthew/Research/RISCV/software2/riscv-tools/riscv-tests/benchmarks/sqrt.riscv.sim_init"
|
||||
`define MEMORY_FILE "/home/ematthew/Research/RISCV/software2/riscv-tools/riscv-tests/benchmarks/fft.riscv.sim_init"
|
||||
`define UART_LOG "/home/ematthew/uart.log"
|
||||
|
||||
module taiga_tb ( );
|
||||
|
@ -164,8 +164,8 @@ module taiga_tb ( );
|
|||
assign clk = simulator_clk;
|
||||
assign rst = processor_reset;
|
||||
|
||||
bram_interface instruction_bram();
|
||||
bram_interface data_bram();
|
||||
local_memory_interface instruction_bram();
|
||||
local_memory_interface data_bram();
|
||||
|
||||
axi_interface m_axi();
|
||||
avalon_interface m_avalon();
|
||||
|
@ -238,7 +238,7 @@ module taiga_tb ( );
|
|||
end
|
||||
do_reset();
|
||||
|
||||
#3600000;
|
||||
#1500000;
|
||||
$fclose(output_file);
|
||||
$finish;
|
||||
end
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
</db_ref>
|
||||
</db_ref_list>
|
||||
<zoom_setting>
|
||||
<ZoomStartTime time="4143000000fs"></ZoomStartTime>
|
||||
<ZoomEndTime time="4445500001fs"></ZoomEndTime>
|
||||
<Cursor1Time time="4293000000fs"></Cursor1Time>
|
||||
<ZoomStartTime time="0fs"></ZoomStartTime>
|
||||
<ZoomEndTime time="11193913045fs"></ZoomEndTime>
|
||||
<Cursor1Time time="3537100000fs"></Cursor1Time>
|
||||
</zoom_setting>
|
||||
<column_width_setting>
|
||||
<NameColumnWidth column_width="297"></NameColumnWidth>
|
||||
<ValueColumnWidth column_width="87"></ValueColumnWidth>
|
||||
<ValueColumnWidth column_width="79"></ValueColumnWidth>
|
||||
</column_width_setting>
|
||||
<WVObjectSize size="183" />
|
||||
<WVObjectSize size="188" />
|
||||
<wvobject type="logic" fp_name="/taiga_tb/clk">
|
||||
<obj_property name="ElementShortName">clk</obj_property>
|
||||
<obj_property name="ObjectShortName">clk</obj_property>
|
||||
|
@ -99,6 +99,26 @@
|
|||
<obj_property name="ElementShortName">stage2_phys_address[31:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">stage2_phys_address[31:0]</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="array" fp_name="/taiga_tb/uut/fetch_block/inflight_count">
|
||||
<obj_property name="ElementShortName">inflight_count[8:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">inflight_count[8:0]</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/fetch_block/space_in_inst_buffer">
|
||||
<obj_property name="ElementShortName">space_in_inst_buffer</obj_property>
|
||||
<obj_property name="ObjectShortName">space_in_inst_buffer</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="array" fp_name="/taiga_tb/uut/inst_buffer/ib_fifo_block/valid_chain">
|
||||
<obj_property name="ElementShortName">valid_chain[256:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">valid_chain[256:0]</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/fetch_block/stage2_cache_access">
|
||||
<obj_property name="ElementShortName">stage2_cache_access</obj_property>
|
||||
<obj_property name="ObjectShortName">stage2_cache_access</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/fetch_block/new_issue">
|
||||
<obj_property name="ElementShortName">new_issue</obj_property>
|
||||
<obj_property name="ObjectShortName">new_issue</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/fetch_block/bram_access">
|
||||
<obj_property name="ElementShortName">bram_access</obj_property>
|
||||
<obj_property name="ObjectShortName">bram_access</obj_property>
|
||||
|
@ -321,8 +341,8 @@
|
|||
<obj_property name="ObjectShortName">in_use_match</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="array" fp_name="/taiga_tb/uut/register_file_block/in_use_by">
|
||||
<obj_property name="ElementShortName">in_use_by[0:31][1:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">in_use_by[0:31][1:0]</obj_property>
|
||||
<obj_property name="ElementShortName">in_use_by[0:31][2:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">in_use_by[0:31][2:0]</obj_property>
|
||||
<obj_property name="Radix">UNSIGNEDDECRADIX</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/write_back_mux/entry_found">
|
||||
|
@ -342,8 +362,8 @@
|
|||
<obj_property name="DisplayName">label</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="array" fp_name="/taiga_tb/uut/inst_queue/shift_reg">
|
||||
<obj_property name="ElementShortName">shift_reg[4:0][4:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">shift_reg[4:0][4:0]</obj_property>
|
||||
<obj_property name="ElementShortName">shift_reg[8:0][5:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">shift_reg[8:0][5:0]</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="array" fp_name="/taiga_tb/uut/write_back_mux/unit_id">
|
||||
<obj_property name="ElementShortName">unit_id[2:0]</obj_property>
|
||||
|
@ -361,9 +381,17 @@
|
|||
<obj_property name="ElementShortName">ls_inputs</obj_property>
|
||||
<obj_property name="ObjectShortName">ls_inputs</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/issue_request">
|
||||
<obj_property name="ElementShortName">issue_request</obj_property>
|
||||
<obj_property name="ObjectShortName">issue_request</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="array" fp_name="/taiga_tb/uut/load_store_unit_block/inflight_count">
|
||||
<obj_property name="ElementShortName">inflight_count[1:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">inflight_count[1:0]</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="array" fp_name="/taiga_tb/uut/load_store_unit_block/ls_input_fifo/read_index">
|
||||
<obj_property name="ElementShortName">read_index[2:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">read_index[2:0]</obj_property>
|
||||
<obj_property name="ElementShortName">read_index[1:0]</obj_property>
|
||||
<obj_property name="ObjectShortName">read_index[1:0]</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="array" fp_name="/taiga_tb/uut/load_store_unit_block/ls_input_fifo/valid_chain">
|
||||
<obj_property name="ElementShortName">valid_chain[4:0]</obj_property>
|
||||
|
@ -390,33 +418,11 @@
|
|||
<obj_property name="ObjectShortName">unit_data_valid[2:0]</obj_property>
|
||||
<obj_property name="CustomSignalColor">#FFD700</obj_property>
|
||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/unit_data_valid[2]">
|
||||
<obj_property name="ElementShortName">[2]</obj_property>
|
||||
<obj_property name="ObjectShortName">[2]</obj_property>
|
||||
<obj_property name="CustomSignalColor">#FFD700</obj_property>
|
||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/unit_data_valid[1]">
|
||||
<obj_property name="ElementShortName">[1]</obj_property>
|
||||
<obj_property name="ObjectShortName">[1]</obj_property>
|
||||
<obj_property name="CustomSignalColor">#FFD700</obj_property>
|
||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/unit_data_valid[0]">
|
||||
<obj_property name="ElementShortName">[0]</obj_property>
|
||||
<obj_property name="ObjectShortName">[0]</obj_property>
|
||||
<obj_property name="CustomSignalColor">#FFD700</obj_property>
|
||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||
</wvobject>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/\genblk6.d_bram /data_bram/en">
|
||||
<obj_property name="ElementShortName">en</obj_property>
|
||||
<obj_property name="ObjectShortName">en</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/issue_request">
|
||||
<obj_property name="ElementShortName">issue_request</obj_property>
|
||||
<obj_property name="ObjectShortName">issue_request</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/load_complete">
|
||||
<obj_property name="ElementShortName">load_complete</obj_property>
|
||||
<obj_property name="ObjectShortName">load_complete</obj_property>
|
||||
|
@ -481,10 +487,6 @@
|
|||
<obj_property name="ElementShortName">store_complete</obj_property>
|
||||
<obj_property name="ObjectShortName">store_complete</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/\genblk8.data_cache /memory_complete">
|
||||
<obj_property name="ElementShortName">memory_complete</obj_property>
|
||||
<obj_property name="ObjectShortName">memory_complete</obj_property>
|
||||
</wvobject>
|
||||
<wvobject type="logic" fp_name="/taiga_tb/uut/load_store_unit_block/\genblk8.data_cache /idle">
|
||||
<obj_property name="ElementShortName">idle</obj_property>
|
||||
<obj_property name="ObjectShortName">idle</obj_property>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue