Merge pull request #13 from e-matthews/code-cleanups

Code cleanups
This commit is contained in:
Mike Thompson 2023-05-02 20:11:12 +00:00 committed by GitHub
commit 041d5c7809
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
79 changed files with 1298 additions and 1906 deletions

View file

@ -1,115 +0,0 @@
/*
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
*/
module binary_occupancy
import cva5_config::*;
import cva5_types::*;
#(parameter DEPTH = 4)
(
input logic clk,
input logic rst,
input logic push,
input logic pop,
output logic almost_full,
output logic full,
output logic empty,
output logic almost_empty,
output logic valid
);
logic[$clog2(DEPTH)-1:0] count;
//Occupancy Tracking
always_ff @ (posedge clk) begin
if (rst)
count <= 0;
else begin
case ({push, pop})
2'b10: count <= count + 1;
2'b01: count <= count - 1;
default : count <= count;
endcase
end
end
always_ff @ (posedge clk) begin
if (rst)
valid <= 0;
else begin
case ({push, pop})
2'b10: valid <= 1;
2'b01: valid <= !(count == 1);
default : valid <= valid;
endcase
end
end
// always_ff @ (posedge clk) begin
// if (rst)
// full <= 0;
// else begin
// case ({push, pop})
// 2'b10: full <= (count == DEPTH-2);
// 2'b01: full <= 0;
// default : full <= full;
// endcase
// end
// end
// always_ff @ (posedge clk) begin
// if (rst)
// almost_full <= 0;
// else begin
// case ({push, pop})
// 2'b10: almost_full <= (count == DEPTH-3);
// 2'b01: almost_full <= (count == DEPTH-1);
// default : almost_full <= almost_full;
// endcase
// end
// end
// always_ff @ (posedge clk) begin
// if (rst)
// almost_empty <= 0;
// else begin
// case ({push, pop})
// 2'b10: almost_empty <=(count == 0);
// 2'b01: almost_empty <= (count == 2);
// default : almost_empty <= almost_empty;
// endcase
// end
// end
assign empty = ~valid;
////////////////////////////////////////////////////
//Assertions
always_ff @ (posedge clk) begin
assert (!(~rst & full & push)) else $error("overflow");
assert (!(~rst & empty & pop)) else $error("underflow");
end
endmodule

View file

@ -1,64 +0,0 @@
/*
* Copyright © 2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
*/
module branch_predictor_ram
import cva5_config::*;
import cva5_types::*;
#(
parameter C_DATA_WIDTH = 20,
parameter C_DEPTH = 512
)
(
input logic clk,
input logic rst,
input logic [$clog2(C_DEPTH)-1:0] write_addr,
input logic write_en,
input logic [$clog2(C_DEPTH)-1:0] read_addr,
input logic read_en,
input logic [C_DATA_WIDTH-1:0] write_data,
output logic [C_DATA_WIDTH-1:0] read_data
);
(* ram_style = "block" *)logic [C_DATA_WIDTH-1:0] branch_ram [C_DEPTH-1:0];
////////////////////////////////////////////////////
//Implementation
initial branch_ram = '{default: 0};
always_ff @(posedge clk) begin
if (write_en)
branch_ram[write_addr] <= write_data;
end
always_ff @(posedge clk) begin
if (read_en)
read_data <= branch_ram[read_addr];
end
////////////////////////////////////////////////////
//End of Implementation
////////////////////////////////////////////////////
////////////////////////////////////////////////////
//Assertions
////////////////////////////////////////////////////
//Trace Interface
endmodule

View file

@ -22,7 +22,7 @@
module byte_en_BRAM
module byte_en_bram
import cva5_config::*;
import cva5_types::*;

View file

@ -32,7 +32,7 @@ module cva5_fifo
import cva5_types::*;
#(
parameter DATA_WIDTH = 70,
parameter type DATA_TYPE = logic,
parameter FIFO_DEPTH = 4
)
(
@ -63,7 +63,7 @@ module cva5_fifo
//connected as a shift reg for the same resources as a LUTRAM FIFO
//but with better timing
else if (FIFO_DEPTH == 2) begin : gen_width_two
logic [DATA_WIDTH-1:0] shift_reg [FIFO_DEPTH];
DATA_TYPE shift_reg [FIFO_DEPTH];
logic [LOG2_FIFO_DEPTH:0] inflight_count;
////////////////////////////////////////////////////
//Occupancy Tracking
@ -115,7 +115,7 @@ module cva5_fifo
.value(write_index)
);
//Force FIFO depth to next power of 2
lutram_1w_1r #(.WIDTH(DATA_WIDTH), .DEPTH(2**LOG2_FIFO_DEPTH))
lutram_1w_1r #(.DATA_TYPE(DATA_TYPE), .DEPTH(2**LOG2_FIFO_DEPTH))
write_port (
.clk(clk),
.waddr(write_index),

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017-2020 Eric Matthews, Lesley Shannon
* Copyright © 2023 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,46 +20,51 @@
* Eric Matthews <ematthew@sfu.ca>
*/
module tag_bank
#(
module dual_port_bram
import cva5_config::*;
import cva5_types::*;
import riscv_types::*;
#(
parameter WIDTH = 32,
parameter LINES = 512
parameter LINES = 4096
)
(
input logic clk,
input logic rst,
input logic[$clog2(LINES)-1:0] addr_a,
input logic[$clog2(LINES)-1:0] addr_b,
input logic en_a,
input logic en_b,
input logic wen_a,
input logic[$clog2(LINES)-1:0] addr_a,
input logic[WIDTH-1:0] data_in_a,
output logic[WIDTH-1:0] data_out_a,
input logic en_b,
input logic wen_b,
input logic [WIDTH-1:0] data_in_a,
input logic [WIDTH-1:0] data_in_b,
output logic [WIDTH-1:0] data_out_a,
output logic [WIDTH-1:0] data_out_b
input logic[$clog2(LINES)-1:0] addr_b,
input logic[WIDTH-1:0] data_in_b,
output logic[WIDTH-1:0] data_out_b
);
(* ram_style = "block", ramstyle = "no_rw_check" *) logic [WIDTH-1:0] tag_entry [LINES];
initial tag_entry = '{default: 0};
(* ram_style = "block", ramstyle = "no_rw_check" *) logic [WIDTH-1:0] ram [LINES];
initial ram = '{default: 0};
always_ff @ (posedge clk) begin
if (en_a) begin
if (wen_a)
tag_entry[addr_a] <= data_in_a;
else
data_out_a <= tag_entry[addr_a];
ram[addr_a] <= data_in_a;
data_out_a <= ram[addr_a];
end
end
always_ff @ (posedge clk) begin
if (en_b) begin
if (wen_b)
tag_entry[addr_b] <= data_in_b;
else
data_out_b <= tag_entry[addr_b];
ram[addr_b] <= data_in_b;
data_out_b <= ram[addr_b];
end
end
endmodule
endmodule

View file

@ -22,7 +22,7 @@
module lutram_1w_1r
#(
parameter WIDTH = 32,
parameter type DATA_TYPE = logic,
parameter DEPTH = 32
)
(
@ -32,11 +32,11 @@ module lutram_1w_1r
input logic[$clog2(DEPTH)-1:0] raddr,
input logic ram_write,
input logic[WIDTH-1:0] new_ram_data,
output logic[WIDTH-1:0] ram_data_out
input DATA_TYPE new_ram_data,
output DATA_TYPE ram_data_out
);
(* ramstyle = "MLAB, no_rw_check", ram_style = "distributed" *) logic [WIDTH-1:0] ram [DEPTH-1:0];
(* ramstyle = "MLAB, no_rw_check", ram_style = "distributed" *) logic [$bits(DATA_TYPE)-1:0] ram [DEPTH-1:0];
initial ram = '{default: 0};
always_ff @ (posedge clk) begin

View file

@ -25,7 +25,7 @@ module lutram_1w_mr
import cva5_config::*;
#(
parameter WIDTH = 32,
parameter type DATA_TYPE = logic,
parameter DEPTH = 32,
parameter NUM_READ_PORTS = 2
)
@ -36,14 +36,14 @@ module lutram_1w_mr
input logic[$clog2(DEPTH)-1:0] raddr [NUM_READ_PORTS],
input logic ram_write,
input logic[WIDTH-1:0] new_ram_data,
output logic[WIDTH-1:0] ram_data_out [NUM_READ_PORTS]
input DATA_TYPE new_ram_data,
output DATA_TYPE ram_data_out [NUM_READ_PORTS]
);
//For Xilinx with their wider selection of LUTRAMs, infer a multi-read port LUTRAM
//For Intel, build the multi-read port ram from simple-dual-port LUTRAMs
generate if (FPGA_VENDOR == XILINX) begin : xilinx_gen
logic [WIDTH-1:0] ram [DEPTH-1:0];
logic [$bits(DATA_TYPE)-1:0] ram [DEPTH-1:0];
initial ram = '{default: 0};
always_ff @ (posedge clk) begin
@ -61,7 +61,7 @@ end
else if (FPGA_VENDOR == INTEL) begin : intel_gen
for (genvar i = 0; i < NUM_READ_PORTS; i++) begin : lutrams
lutram_1w_1r #(.WIDTH(WIDTH), .DEPTH(DEPTH))
lutram_1w_1r #(.DATA_TYPE(DATA_TYPE), .DEPTH(DEPTH))
write_port (
.clk(clk),
.waddr(waddr),

View file

@ -51,7 +51,7 @@ module toggle_memory
assign new_ram_data = toggle ^ _read_data[0];
lutram_1w_mr #(
.WIDTH(1),
.DATA_TYPE(logic),
.DEPTH(DEPTH),
.NUM_READ_PORTS(NUM_READ_PORTS+1)
)

View file

@ -51,51 +51,6 @@ module cva5
input interrupt_t m_interrupt
);
////////////////////////////////////////////////////
//Unit ID Assignment
//Generate Issue IDs based on configuration options
//Then assigned to a struct for ease in passing to sub modules
//Units with writeback
localparam int unsigned ALU_UNIT_ID = 32'd0;
localparam int unsigned LS_UNIT_ID = 32'd1;
localparam int unsigned CSR_UNIT_ID = LS_UNIT_ID + int'(CONFIG.INCLUDE_CSRS);
localparam int unsigned MUL_UNIT_ID = CSR_UNIT_ID + int'(CONFIG.INCLUDE_MUL);
localparam int unsigned DIV_UNIT_ID = MUL_UNIT_ID + int'(CONFIG.INCLUDE_DIV);
localparam int unsigned CUSTOM_UNIT_ID = DIV_UNIT_ID + int'(CONFIG.INCLUDE_CUSTOM);
//Non-writeback units
localparam int unsigned BRANCH_UNIT_ID = CUSTOM_UNIT_ID + 1;
localparam int unsigned IEC_UNIT_ID = BRANCH_UNIT_ID + 1;
//Total number of units
localparam int unsigned NUM_UNITS = IEC_UNIT_ID + 1;
localparam unit_id_param_t UNIT_IDS = '{
ALU : ALU_UNIT_ID,
LS : LS_UNIT_ID,
CSR : CSR_UNIT_ID,
MUL : MUL_UNIT_ID,
DIV : DIV_UNIT_ID,
CUSTOM : CUSTOM_UNIT_ID,
BR : BRANCH_UNIT_ID,
IEC : IEC_UNIT_ID
};
////////////////////////////////////////////////////
//Writeback Port Assignment
//
localparam int unsigned NUM_WB_UNITS_GROUP_1 = 1;//ALU
localparam int unsigned ALU_UNIT_WB1_ID = 32'd0;
localparam int unsigned NUM_WB_UNITS_GROUP_2 = 1;//LS
localparam int unsigned LS_UNIT_WB2_ID = 32'd0;
localparam int unsigned NUM_WB_UNITS_GROUP_3 = int'(CONFIG.INCLUDE_CSRS) + int'(CONFIG.INCLUDE_MUL) + int'(CONFIG.INCLUDE_DIV) + int'(CONFIG.INCLUDE_CUSTOM);
localparam int unsigned DIV_UNIT_WB3_ID = 32'd0;
localparam int unsigned MUL_UNIT_WB3_ID = 32'd0 + int'(CONFIG.INCLUDE_DIV);
localparam int unsigned CSR_UNIT_WB3_ID = 32'd0 + int'(CONFIG.INCLUDE_MUL)+ int'(CONFIG.INCLUDE_DIV);
localparam int unsigned CUSTOM_UNIT_WB3_ID = 32'd0 + int'(CONFIG.INCLUDE_MUL)+ int'(CONFIG.INCLUDE_DIV) + int'(CONFIG.INCLUDE_CSRS);
////////////////////////////////////////////////////
//Connecting Signals
l1_arbiter_request_interface l1_request[L1_CONNECTIONS-1:0]();
@ -115,21 +70,17 @@ module cva5
issue_packet_t issue;
register_file_issue_interface #(.NUM_WB_GROUPS(CONFIG.NUM_WB_GROUPS)) rf_issue();
logic [NUM_UNITS-1:0] unit_needed;
logic [NUM_UNITS-1:0][REGFILE_READ_PORTS-1:0] unit_uses_rs;
logic [NUM_UNITS-1:0] unit_uses_rd;
logic [MAX_NUM_UNITS-1:0] unit_needed;
logic [MAX_NUM_UNITS-1:0][REGFILE_READ_PORTS-1:0] unit_uses_rs;
logic [MAX_NUM_UNITS-1:0] unit_uses_rd;
logic [31:0] constant_alu;
unit_issue_interface unit_issue [NUM_UNITS-1:0]();
unit_issue_interface unit_issue [MAX_NUM_UNITS-1:0]();
exception_packet_t ls_exception;
logic ls_exception_is_store;
unit_writeback_interface unit_wb1 [NUM_WB_UNITS_GROUP_1]();
unit_writeback_interface unit_wb2 [NUM_WB_UNITS_GROUP_2]();
unit_writeback_interface unit_wb3 [NUM_WB_UNITS_GROUP_3 == 0 ? 1 : NUM_WB_UNITS_GROUP_3]();
mmu_interface immu();
mmu_interface dmmu();
@ -170,6 +121,7 @@ module cva5
logic retire_port_valid [RETIRE_PORTS];
logic [LOG2_RETIRE_PORTS : 0] retire_count;
//Writeback
unit_writeback_interface unit_wb [MAX_NUM_UNITS]();
wb_packet_t wb_packet [CONFIG.NUM_WB_GROUPS];
phys_addr_t wb_phys_addr [CONFIG.NUM_WB_GROUPS];
//Exception
@ -286,7 +238,6 @@ module cva5
.iwishbone (iwishbone),
.icache_on ('1),
.tlb (itlb),
.tlb_on (tlb_on),
.l1_request (l1_request[L1_ICACHE_ID]),
.l1_response (l1_response[L1_ICACHE_ID]),
.exception (1'b0)
@ -357,10 +308,8 @@ module cva5
////////////////////////////////////////////////////
//Decode/Issue
decode_and_issue #(
.CONFIG (CONFIG),
.NUM_UNITS (NUM_UNITS),
.UNIT_IDS (UNIT_IDS)
)
.CONFIG (CONFIG)
)
decode_and_issue_block (
.clk (clk),
.rst (rst),
@ -419,12 +368,12 @@ module cva5
.decode_stage (decode),
.issue_stage (issue),
.issue_stage_ready (issue_stage_ready),
.unit_needed (unit_needed[UNIT_IDS.BR]),
.uses_rs (unit_uses_rs[UNIT_IDS.BR]),
.uses_rd (unit_uses_rd[UNIT_IDS.BR]),
.unit_needed (unit_needed[BR_ID]),
.uses_rs (unit_uses_rs[BR_ID]),
.uses_rd (unit_uses_rd[BR_ID]),
.rf (rf_issue.data),
.constant_alu (constant_alu),
.issue (unit_issue[UNIT_IDS.BR]),
.issue (unit_issue[BR_ID]),
.br_results (br_results),
.branch_flush (branch_flush),
.exception (exception[BR_EXCEPTION])
@ -437,14 +386,14 @@ module cva5
.decode_stage (decode),
.issue_stage (issue),
.issue_stage_ready (issue_stage_ready),
.unit_needed (unit_needed[UNIT_IDS.ALU]),
.uses_rs (unit_uses_rs[UNIT_IDS.ALU]),
.uses_rd (unit_uses_rd[UNIT_IDS.ALU]),
.unit_needed (unit_needed[ALU_ID]),
.uses_rs (unit_uses_rs[ALU_ID]),
.uses_rd (unit_uses_rd[ALU_ID]),
.rf (rf_issue.data),
.constant_alu (constant_alu),
.issue_rs_addr (issue_rs_addr),
.issue (unit_issue[UNIT_IDS.ALU]),
.wb (unit_wb1[ALU_UNIT_WB1_ID])
.issue (unit_issue[ALU_ID]),
.wb (unit_wb[ALU_ID])
);
load_store_unit #(.CONFIG(CONFIG))
@ -455,16 +404,16 @@ module cva5
.decode_stage (decode),
.issue_stage (issue),
.issue_stage_ready (issue_stage_ready),
.unit_needed (unit_needed[UNIT_IDS.LS]),
.uses_rs (unit_uses_rs[UNIT_IDS.LS]),
.uses_rd (unit_uses_rd[UNIT_IDS.LS]),
.unit_needed (unit_needed[LS_ID]),
.uses_rs (unit_uses_rs[LS_ID]),
.uses_rd (unit_uses_rd[LS_ID]),
.decode_is_store (decode_is_store),
.instruction_issued_with_rd (instruction_issued_with_rd),
.issue_rs_addr (issue_rs_addr),
.issue_rd_wb_group (issue_rd_wb_group),
.rs2_inuse (rf_issue.inuse[RS2]),
.rf (rf_issue.data),
.issue (unit_issue[UNIT_IDS.LS]),
.issue (unit_issue[LS_ID]),
.dcache_on (1'b1),
.clear_reservation (1'b0),
.tlb (dtlb),
@ -481,7 +430,7 @@ module cva5
.store_retire (store_retire),
.exception (exception[LS_EXCEPTION]),
.load_store_status(load_store_status),
.wb (unit_wb2[LS_UNIT_WB2_ID])
.wb (unit_wb[LS_ID])
);
generate if (CONFIG.INCLUDE_S_MODE) begin : gen_dtlb_dmmu
@ -512,7 +461,7 @@ module cva5
end
endgenerate
generate if (CONFIG.INCLUDE_CSRS) begin : gen_csrs
generate if (CONFIG.INCLUDE_UNIT.CSR) begin : gen_csrs
csr_unit # (.CONFIG(CONFIG))
csr_unit_block (
.clk(clk),
@ -521,12 +470,12 @@ module cva5
.issue_stage (issue),
.issue_stage_ready (issue_stage_ready),
.issue_rs_addr (issue_rs_addr),
.unit_needed (unit_needed[UNIT_IDS.CSR]),
.uses_rs (unit_uses_rs[UNIT_IDS.CSR]),
.uses_rd (unit_uses_rd[UNIT_IDS.CSR]),
.unit_needed (unit_needed[CSR_ID]),
.uses_rs (unit_uses_rs[CSR_ID]),
.uses_rd (unit_uses_rd[CSR_ID]),
.rf (rf_issue.data),
.issue (unit_issue[UNIT_IDS.CSR]),
.wb (unit_wb3[CSR_UNIT_WB3_ID]),
.issue (unit_issue[CSR_ID]),
.wb (unit_wb[CSR_ID]),
.current_privilege(current_privilege),
.interrupt_taken(interrupt_taken),
.interrupt_pending(interrupt_pending),
@ -555,12 +504,12 @@ module cva5
.decode_stage (decode),
.issue_stage (issue),
.issue_stage_ready (issue_stage_ready),
.unit_needed (unit_needed[UNIT_IDS.IEC]),
.uses_rs (unit_uses_rs[UNIT_IDS.IEC]),
.uses_rd (unit_uses_rd[UNIT_IDS.IEC]),
.unit_needed (unit_needed[IEC_ID]),
.uses_rs (unit_uses_rs[IEC_ID]),
.uses_rd (unit_uses_rd[IEC_ID]),
.constant_alu (constant_alu),
.rf (rf_issue.data),
.issue (unit_issue[UNIT_IDS.IEC]),
.issue (unit_issue[IEC_ID]),
.branch_flush (branch_flush),
.exception (exception),
.exception_target_pc (exception_target_pc),
@ -580,23 +529,23 @@ module cva5
.post_issue_count (post_issue_count)
);
generate if (CONFIG.INCLUDE_MUL) begin : gen_mul
generate if (CONFIG.INCLUDE_UNIT.MUL) begin : gen_mul
mul_unit mul_unit_block (
.clk (clk),
.rst (rst),
.decode_stage (decode),
.issue_stage (issue),
.issue_stage_ready (issue_stage_ready),
.unit_needed (unit_needed[UNIT_IDS.MUL]),
.uses_rs (unit_uses_rs[UNIT_IDS.MUL]),
.uses_rd (unit_uses_rd[UNIT_IDS.MUL]),
.unit_needed (unit_needed[MUL_ID]),
.uses_rs (unit_uses_rs[MUL_ID]),
.uses_rd (unit_uses_rd[MUL_ID]),
.rf (rf_issue.data),
.issue (unit_issue[UNIT_IDS.MUL]),
.wb (unit_wb3[MUL_UNIT_WB3_ID])
.issue (unit_issue[MUL_ID]),
.wb (unit_wb[MUL_ID])
);
end endgenerate
generate if (CONFIG.INCLUDE_DIV) begin : gen_div
generate if (CONFIG.INCLUDE_UNIT.DIV) begin : gen_div
div_unit div_unit_block (
.clk (clk),
.rst (rst),
@ -606,69 +555,48 @@ module cva5
.issue_stage (issue),
.issue_stage_ready (issue_stage_ready),
.issue_rs_addr (issue_rs_addr),
.unit_needed (unit_needed[UNIT_IDS.DIV]),
.uses_rs (unit_uses_rs[UNIT_IDS.DIV]),
.uses_rd (unit_uses_rd[UNIT_IDS.DIV]),
.unit_needed (unit_needed[DIV_ID]),
.uses_rs (unit_uses_rs[DIV_ID]),
.uses_rd (unit_uses_rd[DIV_ID]),
.rf (rf_issue.data),
.issue (unit_issue[UNIT_IDS.DIV]),
.wb (unit_wb3[DIV_UNIT_WB3_ID])
.issue (unit_issue[DIV_ID]),
.wb (unit_wb[DIV_ID])
);
end endgenerate
generate if (CONFIG.INCLUDE_CUSTOM) begin : gen_custom
generate if (CONFIG.INCLUDE_UNIT.CUSTOM) begin : gen_custom
custom_unit custom_unit_block (
.clk (clk),
.rst (rst),
.decode_stage (decode),
.unit_needed (unit_needed[UNIT_IDS.CUSTOM]),
.uses_rs (unit_uses_rs[UNIT_IDS.CUSTOM]),
.uses_rd (unit_uses_rd[UNIT_IDS.CUSTOM]),
.unit_needed (unit_needed[CUSTOM_ID]),
.uses_rs (unit_uses_rs[CUSTOM_ID]),
.uses_rd (unit_uses_rd[CUSTOM_ID]),
.issue_stage (issue),
.issue_stage_ready (issue_stage_ready),
.rf (rf_issue.data),
.issue (unit_issue[UNIT_IDS.CUSTOM]),
.wb (unit_wb3[CUSTOM_UNIT_WB3_ID])
.issue (unit_issue[CUSTOM_ID]),
.wb (unit_wb[CUSTOM_ID])
);
end endgenerate
////////////////////////////////////////////////////
//Writeback
//First writeback port: ALU
//Second writeback port: LS, CSR, [MUL], [DIV]
writeback #(
.CONFIG (CONFIG),
.NUM_WB_UNITS (NUM_WB_UNITS_GROUP_1)
)
writeback_block1 (
.clk (clk),
.rst (rst),
.wb_packet (wb_packet[0]),
.unit_wb (unit_wb1)
);
writeback #(
.CONFIG (CONFIG),
.NUM_WB_UNITS (NUM_WB_UNITS_GROUP_2)
)
writeback_block2 (
.clk (clk),
.rst (rst),
.wb_packet (wb_packet[1]),
.unit_wb (unit_wb2)
);
generate if (NUM_WB_UNITS_GROUP_3 > 0) begin : gen_wb3
generate for (genvar i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin : gen_wb
writeback #(
.CONFIG (CONFIG),
.NUM_WB_UNITS (NUM_WB_UNITS_GROUP_3)
.NUM_WB_UNITS (get_num_wb_units(CONFIG.WB_GROUP[i])),
.WB_INDEX (CONFIG.WB_GROUP[i])
)
writeback_block3 (
writeback_block (
.clk (clk),
.rst (rst),
.wb_packet (wb_packet[2]),
.unit_wb (unit_wb3)
.wb_packet (wb_packet[i]),
.unit_wb (unit_wb)
);
end endgenerate
////////////////////////////////////////////////////
//End of Implementation
////////////////////////////////////////////////////

View file

@ -1,47 +0,0 @@
/*
* 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>
*/
module ddata_bank
import cva5_config::*;
import cva5_types::*;
#(
parameter LINES = 2048
)
(
input logic clk,
input logic[$clog2(LINES)-1:0] addr_a,
input logic en_a,
input logic[3:0] be_a,
input logic[31:0] data_in_a,
output logic[31:0] data_out_a,
//write only port
input logic[$clog2(LINES)-1:0] addr_b,
input logic en_b,
input logic[31:0] data_in_b
);
byte_en_BRAM #(LINES, "", 0) ram_block (.*, .be_b({4{en_b}}), .data_out_b());
endmodule

View file

@ -29,9 +29,7 @@ module decode_and_issue
import opcodes::*;
# (
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG,
parameter NUM_UNITS = 7,
parameter unit_id_param_t UNIT_IDS = EXAMPLE_UNIT_IDS
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
)
(
@ -47,9 +45,9 @@ module decode_and_issue
//Renamer
renamer_interface.decode renamer,
input logic [NUM_UNITS-1:0] unit_needed,
input logic [NUM_UNITS-1:0][REGFILE_READ_PORTS-1:0] unit_uses_rs,
input logic [NUM_UNITS-1:0] unit_uses_rd,
input logic [MAX_NUM_UNITS-1:0] unit_needed,
input logic [MAX_NUM_UNITS-1:0][REGFILE_READ_PORTS-1:0] unit_uses_rs,
input logic [MAX_NUM_UNITS-1:0] unit_uses_rd,
output logic decode_uses_rd,
output rs_addr_t decode_rd_addr,
@ -70,7 +68,7 @@ module decode_and_issue
output logic [31:0] constant_alu,
unit_issue_interface.decode unit_issue [NUM_UNITS-1:0],
unit_issue_interface.decode unit_issue [MAX_NUM_UNITS-1:0],
input gc_outputs_t gc,
input logic [1:0] current_privilege,
@ -81,27 +79,21 @@ module decode_and_issue
common_instruction_t decode_instruction;//rs1_addr, rs2_addr, fn3, fn7, rd_addr, upper/lower opcode
logic uses_rs [REGFILE_READ_PORTS];
logic uses_rd;
logic decode_uses_rs [REGFILE_READ_PORTS];
rs_addr_t decode_rs_addr [REGFILE_READ_PORTS];
logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] decode_wb_group;
logic issue_valid;
logic operands_ready;
logic [NUM_UNITS-1:0] unit_needed_issue_stage;
logic [NUM_UNITS-1:0] unit_ready;
logic [NUM_UNITS-1:0] issue_ready;
logic [NUM_UNITS-1:0] issue_to;
logic issue_hold;
logic [REGFILE_READ_PORTS-1:0] operand_ready;
logic [MAX_NUM_UNITS-1:0] unit_needed_issue_stage;
logic [MAX_NUM_UNITS-1:0] issue_to;
logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] issue_rs_wb_group [REGFILE_READ_PORTS];
logic issue_uses_rs [REGFILE_READ_PORTS];
logic pre_issue_exception_pending;
logic illegal_instruction_pattern;
logic illegal_instruction_pattern_r;
logic [REGFILE_READ_PORTS-1:0] rs_conflict;
genvar i;
////////////////////////////////////////////////////
@ -109,8 +101,8 @@ module decode_and_issue
//Can move data into issue stage if:
// there is no instruction currently in the issue stage, or
// an instruction could issue (issue_flush, issue_hold and whether the instruction is valid are not needed in this check)
assign issue_stage_ready = ((~issue.stage_valid) | (issue_valid & |issue_ready)) & ~gc.issue_hold;
// an instruction could issue (ignoring gc.fetch_flush)
assign issue_stage_ready = (~issue.stage_valid) | (|issue_to);
assign decode_advance = decode.valid & issue_stage_ready;
//Instruction aliases
@ -123,37 +115,44 @@ module decode_and_issue
////////////////////////////////////////////////////
//Register File Support
always_comb begin
uses_rd = |unit_uses_rd;
uses_rs = '{default: 0};
for (int i = 0; i < NUM_UNITS; i++)
decode_uses_rd = |unit_uses_rd;
decode_uses_rs = '{default: 0};
for (int i = 0; i < MAX_NUM_UNITS; i++)
for (int j = 0; j < REGFILE_READ_PORTS; j++)
uses_rs[j] |= unit_uses_rs[i][j];
decode_uses_rs[j] |= unit_uses_rs[i][j];
end
////////////////////////////////////////////////////
//Renamer Support
logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] renamer_wb_group;
//WB Group Determination
localparam units_t [MAX_NUM_UNITS-1:0] WB_UNITS_TYPE_REP = get_wb_units_type_representation(CONFIG.WB_GROUP);
logic [CONFIG.NUM_WB_GROUPS-1:0] uses_wb_group;
always_comb begin
renamer_wb_group = $clog2(CONFIG.NUM_WB_GROUPS)'(CONFIG.NUM_WB_GROUPS - 1);
if (unit_needed[UNIT_IDS.ALU])
renamer_wb_group = 0;
else if (unit_needed[UNIT_IDS.LS] )
renamer_wb_group = 1;
for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++)
uses_wb_group[i] = |(unit_needed & WB_UNITS_TYPE_REP[i]);
end
one_hot_to_integer #(.C_WIDTH(CONFIG.NUM_WB_GROUPS))
wb_group_one_hot_block (
.one_hot (uses_wb_group),
.int_out (decode_wb_group)
);
////////////////////////////////////////////////////
//Renamer Support
assign renamer.rd_addr = decode_instruction.rd_addr;
assign renamer.rs_addr = decode_rs_addr;
assign renamer.uses_rd = uses_rd;
assign renamer.rd_wb_group = renamer_wb_group;
assign renamer.uses_rd = decode_uses_rd;
assign renamer.rd_wb_group = decode_wb_group;
assign renamer.id = decode.id;
////////////////////////////////////////////////////
//Decode ID Support
assign decode_uses_rd = uses_rd;
assign decode_rd_addr = decode_instruction.rd_addr;
assign decode_phys_rd_addr = renamer.phys_rd_addr;
assign decode_phys_rs_addr = renamer.phys_rs_addr;
assign decode_rs_wb_group = renamer.rs_wb_group;
////////////////////////////////////////////////////
//Issue
always_ff @(posedge clk) begin
@ -168,12 +167,12 @@ module decode_and_issue
issue_rs_wb_group <= renamer.rs_wb_group;
issue.rd_addr <= decode_instruction.rd_addr;
issue.phys_rd_addr <= renamer.phys_rd_addr;
issue_rd_wb_group <= renamer_wb_group;
issue.is_multicycle <= ~unit_needed[UNIT_IDS.ALU];
issue_rd_wb_group <= decode_wb_group;
issue.is_multicycle <= ~unit_needed[ALU_ID];
issue.id <= decode.id;
issue.exception_unit <= decode_exception_unit;
issue_uses_rs <= uses_rs;
issue.uses_rd <= uses_rd;
issue_uses_rs <= decode_uses_rs;
issue.uses_rd <= decode_uses_rd;
end
end
@ -190,24 +189,23 @@ module decode_and_issue
end
////////////////////////////////////////////////////
//Unit ready
generate for (i=0; i<NUM_UNITS; i++)
assign unit_ready[i] = unit_issue[i].ready;
//Issue Determination
assign issue_hold = gc.issue_hold | pre_issue_exception_pending;
generate for (i=0; i<REGFILE_READ_PORTS; i++)
assign operand_ready[i] = ~rf.inuse[i] | (rf.inuse[i] & ~issue_uses_rs[i]);
endgenerate
////////////////////////////////////////////////////
//Issue Determination
generate for (i=0; i<REGFILE_READ_PORTS; i++)
assign rs_conflict[i] = rf.inuse[i] & issue_uses_rs[i];
endgenerate
assign operands_ready = ~|rs_conflict;
//Unit EX signals
generate for (i = 0; i < MAX_NUM_UNITS; i++) begin : gen_unit_issue_signals
assign unit_issue[i].possible_issue = issue.stage_valid & unit_needed_issue_stage[i] & unit_issue[i].ready;
assign issue_to[i] = unit_issue[i].possible_issue & (&operand_ready) & ~issue_hold;
assign unit_issue[i].new_request = issue_to[i] & ~gc.fetch_flush;
assign unit_issue[i].id = issue.id;
end endgenerate
assign issue_ready = unit_needed_issue_stage & unit_ready;
assign issue_valid = issue.stage_valid & operands_ready & ~gc.issue_hold & ~pre_issue_exception_pending;
assign issue_to = {NUM_UNITS{issue_valid & ~gc.fetch_flush}} & issue_ready;
assign instruction_issued = issue_valid & ~gc.fetch_flush & |issue_ready;
assign instruction_issued = |issue_to & ~gc.fetch_flush;
assign instruction_issued_with_rd = instruction_issued & issue.uses_rd;
////////////////////////////////////////////////////
@ -218,6 +216,7 @@ module decode_and_issue
assign rf.single_cycle_or_flush = (instruction_issued_with_rd & |issue.rd_addr & ~issue.is_multicycle) | (issue.stage_valid & issue.uses_rd & |issue.rd_addr & gc.fetch_flush);
////////////////////////////////////////////////////
//Constant ALU:
// provides LUI, AUIPC, JAL, JALR results for ALU
// provides PC+4 for BRANCH unit and ifence in GC unit
@ -226,42 +225,31 @@ module decode_and_issue
constant_alu <= ((decode_instruction.upper_opcode inside {LUI_T}) ? '0 : decode.pc) + ((decode_instruction.upper_opcode inside {LUI_T, AUIPC_T}) ? {decode.instruction[31:12], 12'b0} : 4);
end
////////////////////////////////////////////////////
//Unit EX signals
generate for (i = 0; i < NUM_UNITS; i++) begin : gen_unit_issue_signals
assign unit_issue[i].possible_issue = issue.stage_valid & unit_needed_issue_stage[i] & unit_issue[i].ready;
assign unit_issue[i].new_request = issue_to[i];
assign unit_issue[i].id = issue.id;
end endgenerate
////////////////////////////////////////////////////
//Illegal Instruction check
generate if (CONFIG.INCLUDE_M_MODE) begin : gen_decode_exceptions
logic new_exception;
exception_code_t ecode;
exception_code_t ecall_code;
//ECALL and EBREAK captured here, but seperated out when ecode is set
assign illegal_instruction_pattern = ~|unit_needed;
always_ff @(posedge clk) begin
if (rst)
illegal_instruction_pattern_r <= 0;
else if (issue_stage_ready)
illegal_instruction_pattern_r <= illegal_instruction_pattern;
end
//TODO: Consider ways of parameterizing so that any exception generating unit
//can be automatically added to this expression
always_comb begin
unique case (1'b1)
unit_needed[UNIT_IDS.LS] : decode_exception_unit = LS_EXCEPTION;
unit_needed[UNIT_IDS.BR] : decode_exception_unit = BR_EXCEPTION;
unit_needed[LS_ID] : decode_exception_unit = LS_EXCEPTION;
unit_needed[BR_ID] : decode_exception_unit = BR_EXCEPTION;
default : decode_exception_unit = PRE_ISSUE_EXCEPTION;
endcase
if (illegal_instruction_pattern)
if (~decode.fetch_metadata.ok)
decode_exception_unit = PRE_ISSUE_EXCEPTION;
end
////////////////////////////////////////////////////
//ECALL/EBREAK
//The type of call instruction is depedent on the current privilege level
exception_code_t ecall_code;
always_comb begin
case (current_privilege)
USER_PRIVILEGE : ecall_code = ECALL_U;
@ -271,19 +259,26 @@ module decode_and_issue
endcase
end
always_ff @(posedge clk) begin
if (issue_stage_ready) begin
ecode <=
decode.instruction inside {ECALL} ? ecall_code :
decode.instruction inside {EBREAK} ? BREAK :
illegal_instruction_pattern ? ILLEGAL_INST :
decode.fetch_metadata.error_code; //(~decode.fetch_metadata.ok)
end
end
////////////////////////////////////////////////////
//Exception generation (ecall/ebreak/illegal instruction/propagated fetch error)
logic new_exception;
exception_code_t ecode;
always_ff @(posedge clk) begin
if (rst)
pre_issue_exception_pending <= 0;
else if (issue_stage_ready)
pre_issue_exception_pending <= illegal_instruction_pattern | (~decode.fetch_metadata.ok) | decode.instruction inside {ECALL, EBREAK};
pre_issue_exception_pending <= illegal_instruction_pattern | (~decode.fetch_metadata.ok);
end
assign new_exception = issue.stage_valid & pre_issue_exception_pending & ~(gc.issue_hold | gc.fetch_flush);
assign new_exception = issue.stage_valid & pre_issue_exception_pending & ~(gc.issue_hold | gc.fetch_flush | exception.valid);
always_ff @(posedge clk) begin
if (rst)
@ -292,18 +287,6 @@ module decode_and_issue
exception.valid <= (exception.valid | new_exception) & ~exception.ack;
end
logic is_ecall_r;
always_ff @(posedge clk) begin
if (issue_stage_ready)
is_ecall_r <= (decode_instruction.upper_opcode == SYSTEM_T) & (decode.instruction[31:20] == ECALL_imm);
end
assign ecode =
illegal_instruction_pattern_r ? ILLEGAL_INST :
is_ecall_r ? ecall_code :
~issue.fetch_metadata.ok ? issue.fetch_metadata.error_code :
BREAK;
always_ff @(posedge clk) begin
if (new_exception) begin
exception.code <= ecode;

View file

@ -90,9 +90,19 @@ module csr_unit
logic[1:0] op;
logic reads;
logic writes;
logic [XLEN-1:0] data;
logic [31:0] data;
} csr_inputs_t;
typedef enum logic [2:0] {
MSTATUS_UNCHANGED = 0,
MSTATUS_WRITE = 1,
MSTATUS_INTERRUPT = 2,
MSTATUS_EXCEPTION = 3,
MSTATUS_MRET = 4,
MSTATUS_SRET = 5
} mstatus_cases_t;
mstatus_cases_t mstatus_case;
logic busy;
logic commit;
logic commit_in_progress;
@ -104,23 +114,79 @@ module csr_unit
privilege_t next_privilege_level;
//write_logic
logic supervisor_write;
logic machine_write;
logic swrite;
logic mwrite;
logic [255:0] sub_write_en;
logic [XLEN-1:0] selected_csr;
logic [XLEN-1:0] selected_csr_r;
logic [31:0] selected_csr;
logic [31:0] selected_csr_r;
logic [31:0] updated_csr;
logic swrite;
logic mwrite;
function logic mwrite_en (input csr_addr_t addr);
return mwrite & (csr_inputs_r.addr.sub_addr == addr.sub_addr);
return mwrite & sub_write_en[addr.sub_addr];
endfunction
function logic swrite_en (input csr_addr_t addr);
return swrite & (csr_inputs_r.addr.sub_addr == addr.sub_addr);
return swrite & sub_write_en[addr.sub_addr];
endfunction
////////////////////////////////////////////////////
//Legalization Functions
function logic [31:0] init_medeleg_mask();
init_medeleg_mask = 0;
if (CONFIG.INCLUDE_S_MODE) begin
init_medeleg_mask[INST_ADDR_MISSALIGNED] = 1;
init_medeleg_mask[INST_ACCESS_FAULT] = 1;
init_medeleg_mask[ILLEGAL_INST] = 1;
init_medeleg_mask[BREAK] = 1;
init_medeleg_mask[LOAD_ADDR_MISSALIGNED] = 1;
init_medeleg_mask[LOAD_FAULT] = 1;
init_medeleg_mask[STORE_AMO_ADDR_MISSALIGNED] = 1;
init_medeleg_mask[STORE_AMO_FAULT] = 1;
init_medeleg_mask[ECALL_U] = 1;
init_medeleg_mask[INST_PAGE_FAULT] = 1;
init_medeleg_mask[LOAD_PAGE_FAULT] = 1;
init_medeleg_mask[STORE_OR_AMO_PAGE_FAULT] = 1;
end
endfunction
function logic [31:0] init_mideleg_mask();
init_mideleg_mask = 0;
if (CONFIG.INCLUDE_S_MODE) begin
init_mideleg_mask[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
init_mideleg_mask[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
init_mideleg_mask[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
end
endfunction
function logic [2**ECODE_W-1:0] init_exception_masking_rom();
init_exception_masking_rom = '{default: 0};
init_exception_masking_rom[INST_ADDR_MISSALIGNED] = 1;
init_exception_masking_rom[INST_ACCESS_FAULT] = CONFIG.INCLUDE_S_MODE;
init_exception_masking_rom[ILLEGAL_INST] = 1;
init_exception_masking_rom[BREAK] = 1;
init_exception_masking_rom[LOAD_ADDR_MISSALIGNED] = 1;
init_exception_masking_rom[LOAD_FAULT] = CONFIG.INCLUDE_S_MODE;
init_exception_masking_rom[STORE_AMO_ADDR_MISSALIGNED] = 1;
init_exception_masking_rom[STORE_AMO_FAULT] = CONFIG.INCLUDE_S_MODE;
init_exception_masking_rom[ECALL_U] = CONFIG.INCLUDE_S_MODE;
init_exception_masking_rom[ECALL_S] = CONFIG.INCLUDE_S_MODE;
init_exception_masking_rom[ECALL_M] = 1;
init_exception_masking_rom[INST_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
init_exception_masking_rom[LOAD_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
init_exception_masking_rom[STORE_OR_AMO_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
endfunction
function logic [2**ECODE_W-1:0] init_interrupt_masking_rom();
init_interrupt_masking_rom = '{default: 0};
init_interrupt_masking_rom[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
init_interrupt_masking_rom[M_SOFTWARE_INTERRUPT] = 1;
init_interrupt_masking_rom[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
init_interrupt_masking_rom[M_TIMER_INTERRUPT] = 1;
init_interrupt_masking_rom[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
init_interrupt_masking_rom[M_EXTERNAL_INTERRUPT] = 1;
endfunction
////////////////////////////////////////////////////
//Implementation
@ -134,11 +200,13 @@ module csr_unit
end
////////////////////////////////////////////////////
//Issue
assign csr_inputs.addr = issue_stage.instruction[31:20];
assign csr_inputs.op = issue_stage.fn3[1:0];
assign csr_inputs.data = issue_stage.fn3[2] ? {27'b0, issue_rs_addr[RS1]} : rf[RS1];
assign csr_inputs.reads = ~((issue_stage.fn3[1:0] == CSR_RW) && (issue_stage.rd_addr == 0));
assign csr_inputs.writes = ~((issue_stage.fn3[1:0] == CSR_RC) && (issue_rs_addr[RS1] == 0));
assign csr_inputs = '{
addr : issue_stage.instruction[31:20],
op : issue_stage.fn3[1:0],
data : issue_stage.fn3[2] ? {27'b0, issue_rs_addr[RS1]} : rf[RS1],
reads : ~((issue_stage.fn3[1:0] == CSR_RW) && (issue_stage.rd_addr == 0)),
writes : ~((issue_stage.fn3[1:0] == CSR_RC) && (issue_rs_addr[RS1] == 0))
};
assign processing_csr = busy | issue.new_request;
@ -184,8 +252,9 @@ module csr_unit
assign wb.rd = selected_csr_r;
////////////////////////////////////////////////////
//Shared logic
//Shared logic
always_ff @(posedge clk) begin
sub_write_en <= (1 << csr_inputs_r.addr.sub_addr);
mwrite <= CONFIG.INCLUDE_M_MODE && commit && (csr_inputs_r.addr.rw_bits != CSR_READ_ONLY && csr_inputs_r.addr.privilege == MACHINE_PRIVILEGE);
swrite <= CONFIG.INCLUDE_S_MODE && commit && (csr_inputs_r.addr.rw_bits != CSR_READ_ONLY && csr_inputs_r.addr.privilege == SUPERVISOR_PRIVILEGE);
end
@ -210,87 +279,90 @@ module csr_unit
////////////////////////////////////////////////////
//Machine ISA register
const misa_t misa = '{default:0, mxlen:1, A:(CONFIG.INCLUDE_AMO), I:1, M:(CONFIG.INCLUDE_MUL && CONFIG.INCLUDE_DIV), S:(CONFIG.INCLUDE_S_MODE), U:(CONFIG.INCLUDE_U_MODE)};
localparam misa_t misa = '{
default:0,
mxlen:1,
A:(CONFIG.INCLUDE_AMO),
I:1,
M:(CONFIG.INCLUDE_UNIT.MUL && CONFIG.INCLUDE_UNIT.DIV),
S:(CONFIG.INCLUDE_S_MODE),
U:(CONFIG.INCLUDE_U_MODE)
};
////////////////////////////////////////////////////
//Machine Version Registers
const logic [XLEN-1:0] mvendorid = 0;
const logic [XLEN-1:0] marchid = 0;
const logic [XLEN-1:0] mimpid = CONFIG.CSRS.MACHINE_IMPLEMENTATION_ID;
const logic [XLEN-1:0] mhartid = CONFIG.CSRS.CPU_ID;
localparam logic [31:0] mvendorid = 0;
localparam logic [31:0] marchid = 0;
localparam logic [31:0] mimpid = CONFIG.CSRS.MACHINE_IMPLEMENTATION_ID;
localparam logic [31:0] mhartid = CONFIG.CSRS.CPU_ID;
////////////////////////////////////////////////////
//MSTATUS
const logic [XLEN-1:0] mstatush = 0; //Always little endian
localparam logic [31:0] mstatush = 0; //Always little endian
////////////////////////////////////////////////////
//Non-Constant Registers
mstatus_t mstatus;
logic[XLEN-1:0] mtvec;
logic[XLEN-1:0] medeleg;
logic[XLEN-1:0] mideleg;
mip_t mip, mip_mask, mip_w_mask, mip_new;
mie_t mie, mie_mask;
mip_t sip_mask;
mie_t sie_mask;
logic[XLEN-1:0] mepc;
logic[XLEN-1:0] mtimecmp;
logic[31:0] mtvec;
logic[31:0] medeleg;
logic[31:0] mideleg;
logic[31:0] mepc;
mip_t mip, mip_new;
mie_t mie;
mcause_t mcause;
logic[XLEN-1:0] mtval;
logic[XLEN-1:0] mscratch;
logic[31:0] mtval;
logic[31:0] mscratch;
//Virtualization support: TSR, TW, TVM unused
//Extension context status: SD, FS, XS unused
const mstatus_t mstatus_mask =
'{default:0, mprv:(CONFIG.INCLUDE_U_MODE | CONFIG.INCLUDE_S_MODE), mxr:(CONFIG.INCLUDE_S_MODE),
sum:(CONFIG.INCLUDE_U_MODE & CONFIG.INCLUDE_S_MODE), mpp:'1, spp:(CONFIG.INCLUDE_S_MODE),
mpie:1, spie:(CONFIG.INCLUDE_S_MODE), mie:1, sie:(CONFIG.INCLUDE_S_MODE)};
localparam mstatus_t mstatus_mask = '{
default:0,
mprv:(CONFIG.INCLUDE_U_MODE | CONFIG.INCLUDE_S_MODE),
mxr:(CONFIG.INCLUDE_S_MODE),
sum:(CONFIG.INCLUDE_U_MODE & CONFIG.INCLUDE_S_MODE),
mpp:'1,
spp:(CONFIG.INCLUDE_S_MODE),
mpie:1,
spie:(CONFIG.INCLUDE_S_MODE),
mie:1,
sie:(CONFIG.INCLUDE_S_MODE)
};
const mstatus_t sstatus_mask = '{default:0, mxr:1, sum:1, spp:1, spie:1, sie:1};
localparam mstatus_t sstatus_mask = '{default:0, mxr:1, sum:1, spp:1, spie:1, sie:1};
localparam mip_t sip_mask = '{default:0, seip:CONFIG.INCLUDE_S_MODE, stip:CONFIG.INCLUDE_S_MODE, ssip:CONFIG.INCLUDE_S_MODE};
localparam mie_t sie_mask = '{default:0, seie:CONFIG.INCLUDE_S_MODE, stie:CONFIG.INCLUDE_S_MODE, ssie:CONFIG.INCLUDE_S_MODE};
generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
privilege_t trap_return_privilege_level;
privilege_t exception_privilege_level;
privilege_t interrupt_privilege_level;
mstatus_t mstatus_exception;
mstatus_t mstatus_return;
mstatus_t mstatus_new;
mstatus_t mstatus_write_mask;
logic [ECODE_W-1:0] interrupt_cause_r;
//Interrupt and Exception Delegation
//Can delegate to supervisor if currently in supervisor or user modes
always_comb begin
exception_privilege_level = MACHINE_PRIVILEGE;
interrupt_privilege_level = MACHINE_PRIVILEGE;
if (CONFIG.INCLUDE_S_MODE && privilege_level inside {SUPERVISOR_PRIVILEGE, USER_PRIVILEGE}) begin
if (exception.valid & medeleg[exception.code])
exception_privilege_level = SUPERVISOR_PRIVILEGE;
if (interrupt_taken & mideleg[interrupt_cause_r])
interrupt_privilege_level = SUPERVISOR_PRIVILEGE;
end
end
logic can_delegate;
logic exception_delegated;
logic interrupt_delegated;
//return from trap privilege determination
assign trap_return_privilege_level = mret ? privilege_t'(mstatus.mpp) : privilege_t'({1'b0,mstatus.spp});
assign can_delegate = CONFIG.INCLUDE_S_MODE & privilege_level inside {SUPERVISOR_PRIVILEGE, USER_PRIVILEGE};
assign exception_delegated = can_delegate & exception.valid & medeleg[exception.code];
assign interrupt_delegated = can_delegate & interrupt_taken & mideleg[interrupt_cause_r];
one_hot_to_integer #(6)
mstatus_case_one_hot (
.one_hot ({sret, mret, exception.valid, interrupt_taken, (mwrite_en(MSTATUS) | swrite_en(SSTATUS)), 1'b0}),
.int_out (mstatus_case)
);
always_comb begin
if(mret | sret)
next_privilege_level = trap_return_privilege_level;
else if (interrupt_taken)
next_privilege_level = interrupt_privilege_level;
else if (exception.valid)
next_privilege_level = exception_privilege_level;
else
next_privilege_level = privilege_level;
case (mstatus_case) inside
MSTATUS_MRET : next_privilege_level = privilege_t'(mstatus.mpp);
MSTATUS_SRET : next_privilege_level = privilege_t'({1'b0,mstatus.spp});
MSTATUS_INTERRUPT : next_privilege_level = interrupt_delegated ? SUPERVISOR_PRIVILEGE : MACHINE_PRIVILEGE;
MSTATUS_EXCEPTION : next_privilege_level = exception_delegated ? SUPERVISOR_PRIVILEGE : MACHINE_PRIVILEGE;
default : next_privilege_level = privilege_level;
endcase
end
//Current privilege level
@ -302,51 +374,39 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
end
assign current_privilege = privilege_level;
always_comb begin
mstatus_exception = mstatus;
case (next_privilege_level)
SUPERVISOR_PRIVILEGE: begin
mstatus_exception.spie = (privilege_level == SUPERVISOR_PRIVILEGE) ? mstatus.sie : 0;
mstatus_exception.sie = 0;
mstatus_exception.spp = privilege_level[0]; //one if from supervisor-mode, zero if from user-mode
end
default: begin
mstatus_exception.mpie = (privilege_level == MACHINE_PRIVILEGE) ? mstatus.mie : ((privilege_level == SUPERVISOR_PRIVILEGE) ? mstatus.sie : 0);
mstatus_exception.mie = 0;
mstatus_exception.mpp = privilege_level; //machine,supervisor or user
end
endcase
end
//return from trap
always_comb begin
mstatus_return = mstatus;
if (sret) begin
mstatus_return.sie = mstatus.spie;
mstatus_return.spie = 1;
mstatus_return.spp = USER_PRIVILEGE[0];
mstatus_return.mprv = 0;
end
else if (mret) begin
mstatus_return.mie = mstatus.mpie;
mstatus_return.mpie = 1;
mstatus_return.mpp = CONFIG.INCLUDE_U_MODE ? USER_PRIVILEGE : MACHINE_PRIVILEGE;
if (mstatus.mpp != MACHINE_PRIVILEGE)
mstatus_return.mprv = 0;
end
end
mstatus_t mstatus_write_mask;
assign mstatus_write_mask = swrite ? sstatus_mask : mstatus_mask;
always_comb begin
mstatus_new = mstatus;
if (mwrite_en(MSTATUS) | swrite_en(SSTATUS))
mstatus_new = (mstatus & ~mstatus_write_mask) | (updated_csr & mstatus_write_mask);
else if (interrupt_taken | exception.valid)
mstatus_new = mstatus_exception;
else if (mret | sret)
mstatus_new = mstatus_return;
case (mstatus_case) inside
MSTATUS_WRITE : mstatus_new = (mstatus & ~mstatus_write_mask) | (updated_csr & mstatus_write_mask);
MSTATUS_MRET : begin
mstatus_new.mie = mstatus.mpie;
mstatus_new.mpie = 1;
mstatus_new.mpp = CONFIG.INCLUDE_U_MODE ? USER_PRIVILEGE : MACHINE_PRIVILEGE;
if (mstatus.mpp != MACHINE_PRIVILEGE)
mstatus_new.mprv = 0;
end
MSTATUS_SRET : begin
mstatus_new.sie = mstatus.spie;
mstatus_new.spie = 1;
mstatus_new.spp = USER_PRIVILEGE[0];
mstatus_new.mprv = 0;
end
MSTATUS_INTERRUPT, MSTATUS_EXCEPTION : begin
if (next_privilege_level == SUPERVISOR_PRIVILEGE) begin
mstatus_new.spie = (privilege_level == SUPERVISOR_PRIVILEGE) ? mstatus.sie : 0;
mstatus_new.sie = 0;
mstatus_new.spp = privilege_level[0]; //one if from supervisor-mode, zero if from user-mode
end
else begin
mstatus_new.mpie = (privilege_level == MACHINE_PRIVILEGE) ? mstatus.mie : ((privilege_level == SUPERVISOR_PRIVILEGE) ? mstatus.sie : 0);
mstatus_new.mie = 0;
mstatus_new.mpp = privilege_level; //machine,supervisor or user
end
end
default : mstatus_new = mstatus;
endcase
end
always_ff @(posedge clk) begin
@ -363,31 +423,13 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
always_ff @(posedge clk) begin
mtvec[1:0] <= '0;
if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MTVEC_WRITEABLE & mwrite_en(MTVEC))
mtvec[XLEN-1:2] <= updated_csr[XLEN-1:2];
mtvec[31:2] <= updated_csr[31:2];
end
assign exception_target_pc = mtvec;
////////////////////////////////////////////////////
//MEDELEG
logic [31:0] medeleg_mask;
always_comb begin
medeleg_mask = 0;
if (CONFIG.INCLUDE_S_MODE) begin
medeleg_mask[INST_ADDR_MISSALIGNED] = 1;
medeleg_mask[INST_ACCESS_FAULT] = 1;
medeleg_mask[ILLEGAL_INST] = 1;
medeleg_mask[BREAK] = 1;
medeleg_mask[LOAD_ADDR_MISSALIGNED] = 1;
medeleg_mask[LOAD_FAULT] = 1;
medeleg_mask[STORE_AMO_ADDR_MISSALIGNED] = 1;
medeleg_mask[STORE_AMO_FAULT] = 1;
medeleg_mask[ECALL_U] = 1;
medeleg_mask[INST_PAGE_FAULT] = 1;
medeleg_mask[LOAD_PAGE_FAULT] = 1;
medeleg_mask[STORE_OR_AMO_PAGE_FAULT] = 1;
end
end
localparam logic [31:0] medeleg_mask = init_medeleg_mask();
always_ff @(posedge clk) begin
if (rst)
medeleg <= '0;
@ -397,15 +439,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
////////////////////////////////////////////////////
//MIDELEG
logic [31:0] mideleg_mask;
always_comb begin
mideleg_mask = 0;
if (CONFIG.INCLUDE_S_MODE) begin
mideleg_mask[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
mideleg_mask[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
mideleg_mask[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
end
end
localparam logic [31:0] mideleg_mask = init_mideleg_mask();
always_ff @(posedge clk) begin
if (rst)
mideleg <= '0;
@ -415,8 +449,8 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
////////////////////////////////////////////////////
//MIP
assign mip_mask = '{default:0, meip:1, seip:CONFIG.INCLUDE_S_MODE, mtip:1, stip:CONFIG.INCLUDE_S_MODE, msip:1, ssip:CONFIG.INCLUDE_S_MODE};
assign mip_w_mask = '{default:0, seip:CONFIG.INCLUDE_S_MODE, stip:CONFIG.INCLUDE_S_MODE, ssip:CONFIG.INCLUDE_S_MODE};
localparam mip_t mip_mask = '{default:0, meip:1, seip:CONFIG.INCLUDE_S_MODE, mtip:1, stip:CONFIG.INCLUDE_S_MODE, msip:1, ssip:CONFIG.INCLUDE_S_MODE};
localparam mip_t mip_w_mask = '{default:0, seip:CONFIG.INCLUDE_S_MODE, stip:CONFIG.INCLUDE_S_MODE, ssip:CONFIG.INCLUDE_S_MODE};
always_comb begin
mip_new = '0;
@ -441,9 +475,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
////////////////////////////////////////////////////
//MIE
assign mie_mask = '{default:0, meie:1, seie:CONFIG.INCLUDE_S_MODE, mtie:1, stie:CONFIG.INCLUDE_S_MODE, msie:1, ssie:CONFIG.INCLUDE_S_MODE};
assign sie_mask = '{default:0, seie:1, stie:1, ssie:1};
localparam mie_t mie_mask = '{default:0, meie:1, seie:CONFIG.INCLUDE_S_MODE, mtie:1, stie:CONFIG.INCLUDE_S_MODE, msie:1, ssie:CONFIG.INCLUDE_S_MODE};
always_ff @(posedge clk) begin
if (rst)
mie <= '0;
@ -458,7 +490,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
always_ff @(posedge clk) begin
mepc[1:0] <= '0;
if (mwrite_en(MEPC) | exception.valid | interrupt_taken)
mepc[XLEN-1:2] <= (exception.valid | interrupt_taken) ? exception.pc[XLEN-1:2] : updated_csr[XLEN-1:2];
mepc[31:2] <= (exception.valid | interrupt_taken) ? exception.pc[31:2] : updated_csr[31:2];
end
assign epc = mepc;
@ -468,37 +500,12 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
//As the exception and interrupts codes are sparsely populated,
//to ensure that only legal values are written, a ROM lookup
//is used to validate the CSR write operation
logic M_EXCEPTION_MASKING_ROM [2**ECODE_W];
logic M_INTERRUPT_MASKING_ROM [2**ECODE_W];
always_comb begin
M_EXCEPTION_MASKING_ROM = '{default: 0};
M_EXCEPTION_MASKING_ROM[INST_ADDR_MISSALIGNED] = 1;
M_EXCEPTION_MASKING_ROM[INST_ACCESS_FAULT] = CONFIG.INCLUDE_S_MODE;
M_EXCEPTION_MASKING_ROM[ILLEGAL_INST] = 1;
M_EXCEPTION_MASKING_ROM[BREAK] = 1;
M_EXCEPTION_MASKING_ROM[LOAD_ADDR_MISSALIGNED] = 1;
M_EXCEPTION_MASKING_ROM[LOAD_FAULT] = CONFIG.INCLUDE_S_MODE;
M_EXCEPTION_MASKING_ROM[STORE_AMO_ADDR_MISSALIGNED] = 1;
M_EXCEPTION_MASKING_ROM[STORE_AMO_FAULT] = CONFIG.INCLUDE_S_MODE;
M_EXCEPTION_MASKING_ROM[ECALL_U] = CONFIG.INCLUDE_S_MODE;
M_EXCEPTION_MASKING_ROM[ECALL_S] = CONFIG.INCLUDE_S_MODE;
M_EXCEPTION_MASKING_ROM[ECALL_M] = 1;
M_EXCEPTION_MASKING_ROM[INST_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
M_EXCEPTION_MASKING_ROM[LOAD_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
M_EXCEPTION_MASKING_ROM[STORE_OR_AMO_PAGE_FAULT] = CONFIG.INCLUDE_S_MODE;
M_INTERRUPT_MASKING_ROM = '{default: 0};
M_INTERRUPT_MASKING_ROM[S_SOFTWARE_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
M_INTERRUPT_MASKING_ROM[M_SOFTWARE_INTERRUPT] = 1;
M_INTERRUPT_MASKING_ROM[S_TIMER_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
M_INTERRUPT_MASKING_ROM[M_TIMER_INTERRUPT] = 1;
M_INTERRUPT_MASKING_ROM[S_EXTERNAL_INTERRUPT] = CONFIG.INCLUDE_S_MODE;
M_INTERRUPT_MASKING_ROM[M_EXTERNAL_INTERRUPT] = 1;
end
localparam logic [2**ECODE_W-1:0] M_EXCEPTION_MASKING_ROM = init_exception_masking_rom();
localparam logic [2**ECODE_W-1:0] M_INTERRUPT_MASKING_ROM = init_interrupt_masking_rom();
logic mcause_write_valid;
always_comb begin
if (updated_csr[XLEN-1]) //interrupt
if (updated_csr[31]) //interrupt
mcause_write_valid = M_INTERRUPT_MASKING_ROM[updated_csr[ECODE_W-1:0]];
else
mcause_write_valid = M_EXCEPTION_MASKING_ROM[updated_csr[ECODE_W-1:0]];
@ -508,7 +515,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
logic [5:0] mip_priority_vector;
logic [2:0] mip_cause_sel;
const logic [ECODE_W-1:0] interruput_code_table [7:0] = '{ 0, 0,
localparam logic [ECODE_W-1:0] interruput_code_table [7:0] = '{ 0, 0,
M_EXTERNAL_INTERRUPT, M_TIMER_INTERRUPT, M_SOFTWARE_INTERRUPT,
S_EXTERNAL_INTERRUPT, S_TIMER_INTERRUPT, S_SOFTWARE_INTERRUPT
};
@ -533,7 +540,7 @@ generate if (CONFIG.INCLUDE_M_MODE) begin : gen_csr_m_mode
mcause.code <= 0;
end
else if (CONFIG.CSRS.NON_STANDARD_OPTIONS.INCLUDE_MCAUSE & ((mcause_write_valid & mwrite_en(MCAUSE)) | exception.valid | interrupt_taken)) begin
mcause.is_interrupt <= interrupt_taken | (mwrite_en(MCAUSE) & updated_csr[XLEN-1]);
mcause.is_interrupt <= interrupt_taken | (mwrite_en(MCAUSE) & updated_csr[31]);
mcause.code <= interrupt_taken ? interrupt_cause_r : exception.valid ? exception.code : updated_csr[ECODE_W-1:0];
end
end
@ -573,20 +580,20 @@ endgenerate
////////////////////////////////////////////////////
//BEGIN OF SUPERVISOR REGS
////////////////////////////////////////////////////
logic[XLEN-1:0] sepc;
logic[31:0] sepc;
logic[XLEN-1:0] stime;
logic[XLEN-1:0] stimecmp;
logic[31:0] stime;
logic[31:0] stimecmp;
logic[XLEN-1:0] scause;
logic[XLEN-1:0] stval;
logic[31:0] scause;
logic[31:0] stval;
logic[XLEN-1:0] sstatus;
logic[XLEN-1:0] stvec;
logic[31:0] sstatus;
logic[31:0] stvec;
satp_t satp;
logic[XLEN-1:0] sscratch;
logic[31:0] sscratch;
//TLB status --- used to mux physical/virtual address
assign tlb_on = CONFIG.INCLUDE_S_MODE & satp.mode;
@ -606,21 +613,19 @@ generate if (CONFIG.INCLUDE_S_MODE) begin : gen_csr_s_mode
assign dmmu.satp_ppn = satp.ppn;
////////////////////////////////////////////////////
assign sip_mask = '{default:0, seip:1, stip:1, ssip:1};
////////////////////////////////////////////////////
//STVEC
logic [31:0] stvec_mask = '1;
always_ff @(posedge clk) begin
if (rst)
stvec <= {CONFIG.CSRS.RESET_VEC[XLEN-1:2], 2'b00};
stvec <= {CONFIG.CSRS.RESET_VEC[31:2], 2'b00};
else if (swrite_en(STVEC))
stvec <= (updated_csr & stvec_mask);
end
////////////////////////////////////////////////////
//SATP
logic[XLEN-1:0] satp_mask;
logic[31:0] satp_mask;
assign satp_mask = '1;
always_ff @(posedge clk) begin
if (rst)
@ -648,122 +653,128 @@ endgenerate
//Timers and Counters
//Register increment for instructions completed
//Increments suppressed on writes to these registers
logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] mcycle;
logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] mtime;
logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] minst_ret;
localparam COUNTER_W = CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W;
localparam MCYCLE_WRITEABLE = CONFIG.CSRS.NON_STANDARD_OPTIONS.MCYCLE_WRITEABLE;
localparam MINSTR_WRITEABLE = CONFIG.CSRS.NON_STANDARD_OPTIONS.MINSTR_WRITEABLE;
logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] mcycle_input_next;
logic[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:0] minst_ret_input_next;
logic[COUNTER_W-1:0] mcycle;
logic[COUNTER_W-1:0] mtime;
logic[COUNTER_W-1:0] minst_ret;
logic[COUNTER_W-1:0] mcycle_input_next;
logic[COUNTER_W-1:0] minst_ret_input_next;
logic[LOG2_RETIRE_PORTS:0] minst_ret_inc;
logic mcycle_inc;
always_comb begin
mcycle_input_next = mcycle;
if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MCYCLE_WRITEABLE & mwrite_en(MCYCLE))
mcycle_input_next[31:0] = updated_csr;
if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MCYCLE_WRITEABLE & mwrite_en(MCYCLEH))
mcycle_input_next[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:32] = updated_csr[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-33:0];
end
assign mcycle_inc = ~(CONFIG.CSRS.NON_STANDARD_OPTIONS.MCYCLE_WRITEABLE & (mwrite_en(MCYCLE) | mwrite_en(MCYCLEH)));
assign mcycle_input_next[31:0] = (MCYCLE_WRITEABLE & mwrite_en(MCYCLE)) ? updated_csr : mcycle[31:0];
assign mcycle_input_next[COUNTER_W-1:32] = (MCYCLE_WRITEABLE & mwrite_en(MCYCLE)) ? updated_csr[COUNTER_W-33:0] : mcycle[COUNTER_W-1:32];
assign mcycle_inc = ~(MCYCLE_WRITEABLE & (mwrite_en(MCYCLE) | mwrite_en(MCYCLEH)));
always_ff @(posedge clk) begin
if (rst)
mcycle <= 0;
else
mcycle <= mcycle_input_next + CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W'(mcycle_inc);
mcycle <= mcycle_input_next + COUNTER_W'(mcycle_inc);
end
always_comb begin
minst_ret_input_next = minst_ret;
if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MINSTR_WRITEABLE & mwrite_en(MINSTRET))
minst_ret_input_next[31:0] = updated_csr;
if (CONFIG.CSRS.NON_STANDARD_OPTIONS.MINSTR_WRITEABLE & mwrite_en(MINSTRETH))
minst_ret_input_next[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:32] = updated_csr[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-33:0];
end
assign minst_ret_inc = {(LOG2_RETIRE_PORTS+1){~(CONFIG.CSRS.NON_STANDARD_OPTIONS.MINSTR_WRITEABLE & (mwrite_en(MINSTRET) | mwrite_en(MINSTRETH)))}} & retire_count;
assign minst_ret_input_next[31:0] = (MINSTR_WRITEABLE & mwrite_en(MINSTRET)) ? updated_csr : minst_ret[31:0];
assign minst_ret_input_next[COUNTER_W-1:32] = (MINSTR_WRITEABLE & mwrite_en(MINSTRET)) ? updated_csr[COUNTER_W-33:0] : minst_ret[COUNTER_W-1:32];
assign minst_ret_inc = (MINSTR_WRITEABLE & (mwrite_en(MINSTRET) | mwrite_en(MINSTRETH))) ? '0 : retire_count;
always_ff @(posedge clk) begin
if (rst)
minst_ret <= 0;
else
minst_ret <= minst_ret_input_next + CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W'(minst_ret_inc);
minst_ret <= minst_ret_input_next + COUNTER_W'(minst_ret_inc);
end
////////////////////////////////////////////////////
//CSR mux
logic [31:0] read_mask;
always_comb begin
case (csr_inputs_r.addr) inside
SSTATUS : read_mask = CONFIG.INCLUDE_S_MODE ? sstatus_mask : '1;
SIE : read_mask = CONFIG.INCLUDE_S_MODE ? sie_mask : '1;
SIP : read_mask = CONFIG.INCLUDE_S_MODE ? sip_mask : '1;
default : read_mask = '1;
endcase
end
always_comb begin
case (csr_inputs_r.addr) inside
//Machine info
MISA : selected_csr = CONFIG.INCLUDE_M_MODE ? misa : 0;
MVENDORID : selected_csr = CONFIG.INCLUDE_M_MODE ? mvendorid : 0;
MARCHID : selected_csr = CONFIG.INCLUDE_M_MODE ? marchid : 0;
MIMPID : selected_csr = CONFIG.INCLUDE_M_MODE ? mimpid : 0;
MHARTID : selected_csr = CONFIG.INCLUDE_M_MODE ? mhartid : 0;
MISA : selected_csr = CONFIG.INCLUDE_M_MODE ? misa : '0;
MVENDORID : selected_csr = CONFIG.INCLUDE_M_MODE ? mvendorid : '0;
MARCHID : selected_csr = CONFIG.INCLUDE_M_MODE ? marchid : '0;
MIMPID : selected_csr = CONFIG.INCLUDE_M_MODE ? mimpid : '0;
MHARTID : selected_csr = CONFIG.INCLUDE_M_MODE ? mhartid : '0;
//Machine trap setup
MSTATUS : selected_csr = CONFIG.INCLUDE_M_MODE ? mstatus : 0;
MEDELEG : selected_csr = CONFIG.INCLUDE_M_MODE ? medeleg : 0;
MIDELEG : selected_csr = CONFIG.INCLUDE_M_MODE ? mideleg : 0;
MIE : selected_csr = CONFIG.INCLUDE_M_MODE ? mie : 0;
MTVEC : selected_csr = CONFIG.INCLUDE_M_MODE ? mtvec : 0;
MCOUNTEREN : selected_csr = 0;
MSTATUS : selected_csr = CONFIG.INCLUDE_M_MODE ? mstatus : '0;
MEDELEG : selected_csr = CONFIG.INCLUDE_M_MODE ? medeleg : '0;
MIDELEG : selected_csr = CONFIG.INCLUDE_M_MODE ? mideleg : '0;
MIE : selected_csr = CONFIG.INCLUDE_M_MODE ? mie : '0;
MTVEC : selected_csr = CONFIG.INCLUDE_M_MODE ? mtvec : '0;
MCOUNTEREN : selected_csr = '0;
//Machine trap handling
MSCRATCH : selected_csr = CONFIG.INCLUDE_M_MODE ? mscratch : 0;
MEPC : selected_csr = CONFIG.INCLUDE_M_MODE ? mepc : 0;
MCAUSE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcause : 0;
MTVAL : selected_csr = CONFIG.INCLUDE_M_MODE ? mtval : 0;
MIP : selected_csr = CONFIG.INCLUDE_M_MODE ? mip : 0;
MSCRATCH : selected_csr = CONFIG.INCLUDE_M_MODE ? mscratch : '0;
MEPC : selected_csr = CONFIG.INCLUDE_M_MODE ? mepc : '0;
MCAUSE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcause : '0;
MTVAL : selected_csr = CONFIG.INCLUDE_M_MODE ? mtval : '0;
MIP : selected_csr = CONFIG.INCLUDE_M_MODE ? mip : '0;
//Machine Memory Protection
[12'h3EF : 12'h3A0] : selected_csr = 0;
[12'h3EF : 12'h3A0] : selected_csr = '0;
//Machine Timers and Counters
MCYCLE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcycle[XLEN-1:0] : 0;
MINSTRET : selected_csr = CONFIG.INCLUDE_M_MODE ? minst_ret[XLEN-1:0] : 0;
[12'hB03 : 12'hB1F] : selected_csr = 0;
MCYCLEH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(mcycle[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]) : 0;
MINSTRETH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(minst_ret[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]) : 0;
[12'hB83 : 12'hB9F] : selected_csr = 0;
MCYCLE : selected_csr = CONFIG.INCLUDE_M_MODE ? mcycle[31:0] : '0;
MINSTRET : selected_csr = CONFIG.INCLUDE_M_MODE ? minst_ret[31:0] : '0;
[12'hB03 : 12'hB1F] : selected_csr = '0;
MCYCLEH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(mcycle[COUNTER_W-1:32]) : '0;
MINSTRETH : selected_csr = CONFIG.INCLUDE_M_MODE ? 32'(minst_ret[COUNTER_W-1:32]) : '0;
[12'hB83 : 12'hB9F] : selected_csr = '0;
//Machine Counter Setup
[12'h320 : 12'h33F] : selected_csr = 0;
[12'h320 : 12'h33F] : selected_csr = '0;
//Supervisor Trap Setup
SSTATUS : selected_csr = CONFIG.INCLUDE_S_MODE ? (mstatus & sstatus_mask) : '0;
SEDELEG : selected_csr = 0; //No user-level interrupts/exception handling
SIDELEG : selected_csr = 0;
SIE : selected_csr = CONFIG.INCLUDE_S_MODE ? (mie & sie_mask) : '0;
SSTATUS : selected_csr = CONFIG.INCLUDE_S_MODE ? mstatus : '0;
SEDELEG : selected_csr = '0; //No user-level interrupts/exception handling
SIDELEG : selected_csr = '0;
SIE : selected_csr = CONFIG.INCLUDE_S_MODE ? mie : '0;
STVEC : selected_csr = CONFIG.INCLUDE_S_MODE ? stvec : '0;
SCOUNTEREN : selected_csr = 0;
SCOUNTEREN : selected_csr = '0;
//Supervisor trap handling
SSCRATCH : selected_csr = CONFIG.INCLUDE_S_MODE ? sscratch : '0;
SEPC : selected_csr = CONFIG.INCLUDE_S_MODE ? sscratch : '0;
SCAUSE : selected_csr = CONFIG.INCLUDE_S_MODE ? sscratch : '0;
STVAL : selected_csr = CONFIG.INCLUDE_S_MODE ? sscratch : '0;
SIP : selected_csr = CONFIG.INCLUDE_S_MODE ? (mip & sip_mask) : '0;
SIP : selected_csr = CONFIG.INCLUDE_S_MODE ? mip : '0;
//Supervisor Protection and Translation
SATP : selected_csr = CONFIG.INCLUDE_S_MODE ? satp : '0;
//User status
//Floating point
FFLAGS : selected_csr = 0;
FRM : selected_csr = 0;
FCSR : selected_csr = 0;
FFLAGS : selected_csr = '0;
FRM : selected_csr = '0;
FCSR : selected_csr = '0;
//User Counter Timers
CYCLE : selected_csr = mcycle[XLEN-1:0];
TIME : selected_csr = mcycle[XLEN-1:0];
INSTRET : selected_csr = minst_ret[XLEN-1:0];
[12'hC03 : 12'hC1F] : selected_csr = 0;
CYCLEH : selected_csr = 32'(mcycle[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]);
TIMEH : selected_csr = 32'(mcycle[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]);
INSTRETH : selected_csr = 32'(minst_ret[CONFIG.CSRS.NON_STANDARD_OPTIONS.COUNTER_W-1:XLEN]);
[12'hC83 : 12'hC9F] : selected_csr = 0;
CYCLE : selected_csr = mcycle[31:0];
TIME : selected_csr = mcycle[31:0];
INSTRET : selected_csr = minst_ret[31:0];
[12'hC03 : 12'hC1F] : selected_csr = '0;
CYCLEH : selected_csr = 32'(mcycle[COUNTER_W-1:32]);
TIMEH : selected_csr = 32'(mcycle[COUNTER_W-1:32]);
INSTRETH : selected_csr = 32'(minst_ret[COUNTER_W-1:32]);
[12'hC83 : 12'hC9F] : selected_csr = '0;
default : selected_csr = 0;
default : selected_csr = '0;
endcase
end
always_ff @(posedge clk) begin
if (commit)
selected_csr_r <= selected_csr;
selected_csr_r <= selected_csr & read_mask;
end
////////////////////////////////////////////////////
//Assertions
mstatus_update_assertion:
assert property (@(posedge clk) disable iff (rst) $onehot0({mret,sret,interrupt_taken, exception.valid,(mwrite_en(MSTATUS) | swrite_en(SSTATUS))})) else $error("multiple write to mstatus");
endmodule

View file

@ -71,6 +71,7 @@ module div_unit
logic reuse_result;
id_t id;
} div_attributes_t;
div_attributes_t wb_attr;
typedef struct packed{
logic [XLEN-1:0] unsigned_dividend;
@ -80,17 +81,12 @@ module div_unit
div_attributes_t attr;
} div_fifo_inputs_t;
div_fifo_inputs_t issue_fifo_inputs;
div_fifo_inputs_t div_stage;
div_attributes_t wb_attr;
unsigned_division_interface #(.DATA_WIDTH(32)) div_core();
logic in_progress;
logic div_done;
fifo_interface #(.DATA_WIDTH($bits(div_fifo_inputs_t))) input_fifo();
fifo_interface #(.DATA_WIDTH(XLEN)) wb_fifo();
fifo_interface #(.DATA_TYPE(div_fifo_inputs_t)) input_fifo();
function logic [31:0] negate_if (input logic [31:0] a, logic b);
return ({32{b}} ^ a) + 32'(b);
@ -159,22 +155,11 @@ module div_unit
clz divisor_clz_block (.clz_input(unsigned_divisor), .clz(divisor_CLZ));
assign divisor_is_zero = (&divisor_CLZ) & ~rf[RS2][0];
assign issue_fifo_inputs.unsigned_dividend = unsigned_dividend;
assign issue_fifo_inputs.unsigned_divisor = unsigned_divisor;
assign issue_fifo_inputs.dividend_CLZ = divisor_is_zero ? '0 : dividend_CLZ;
assign issue_fifo_inputs.divisor_CLZ = divisor_CLZ;
assign issue_fifo_inputs.attr.remainder_op = issue_stage.fn3[1];
assign issue_fifo_inputs.attr.negate_result = issue_stage.fn3[1] ? negate_remainder : (negate_quotient & ~divisor_is_zero);
assign issue_fifo_inputs.attr.divisor_is_zero = divisor_is_zero;
assign issue_fifo_inputs.attr.reuse_result = div_op_reuse;
assign issue_fifo_inputs.attr.id = issue.id;
////////////////////////////////////////////////////
//Input FIFO
//Currently just a register (DEPTH=1). As one div instruction can be in-progress
//and one in this input "fifo," we can support two in-flight div ops.
cva5_fifo #(.DATA_WIDTH($bits(div_fifo_inputs_t)), .FIFO_DEPTH(1))
cva5_fifo #(.DATA_TYPE(div_fifo_inputs_t), .FIFO_DEPTH(1))
div_input_fifo (
.clk (clk),
.rst (rst),
@ -184,17 +169,28 @@ module div_unit
logic div_ready;
assign div_ready = (~in_progress) | wb.ack;
assign input_fifo.data_in = issue_fifo_inputs;
assign input_fifo.data_in = '{
unsigned_dividend : unsigned_dividend,
unsigned_divisor : unsigned_divisor,
dividend_CLZ : divisor_is_zero ? '0 : dividend_CLZ,
divisor_CLZ : divisor_CLZ,
attr : '{
remainder_op : issue_stage.fn3[1],
negate_result : (issue_stage.fn3[1] ? negate_remainder : (negate_quotient & ~divisor_is_zero)),
divisor_is_zero : divisor_is_zero,
reuse_result : div_op_reuse,
id : issue.id
}
};
assign input_fifo.push = issue.new_request;
assign input_fifo.potential_push = issue.possible_issue;
assign issue.ready = ~input_fifo.full | (~in_progress);
assign input_fifo.pop = input_fifo.valid & div_ready;
assign div_stage = input_fifo.data_out;
////////////////////////////////////////////////////
//Control Signals
assign div_core.start = input_fifo.pop & ~div_stage.attr.reuse_result;
assign div_done = div_core.done | (input_fifo.pop & div_stage.attr.reuse_result);
assign div_core.start = input_fifo.pop & ~input_fifo.data_out.attr.reuse_result;
assign div_done = div_core.done | (input_fifo.pop & input_fifo.data_out.attr.reuse_result);
//If more than one cycle, set in_progress so that multiple div.start signals are not sent to the div unit.
set_clr_reg_with_rst #(.SET_OVER_CLR(1), .WIDTH(1), .RST_VALUE('0))
@ -206,16 +202,16 @@ module div_unit
);
always_ff @ (posedge clk) begin
if (input_fifo.pop)
wb_attr <= div_stage.attr;
wb_attr <= input_fifo.data_out.attr;
end
////////////////////////////////////////////////////
//Div core
assign div_core.dividend = div_stage.unsigned_dividend;
assign div_core.divisor = div_stage.unsigned_divisor;
assign div_core.dividend_CLZ = div_stage.dividend_CLZ;
assign div_core.divisor_CLZ = div_stage.divisor_CLZ;
assign div_core.divisor_is_zero = div_stage.attr.divisor_is_zero;
assign div_core.dividend = input_fifo.data_out.unsigned_dividend;
assign div_core.divisor = input_fifo.data_out.unsigned_divisor;
assign div_core.dividend_CLZ = input_fifo.data_out.dividend_CLZ;
assign div_core.divisor_CLZ = input_fifo.data_out.divisor_CLZ;
assign div_core.divisor_is_zero = input_fifo.data_out.attr.divisor_is_zero;
div_core #(.DIV_WIDTH(32))
divider_block (

View file

@ -166,7 +166,7 @@ module gc_unit
assign instruction = decode_stage.instruction;
assign unit_needed =
(CONFIG.INCLUDE_M_MODE & decode_stage.instruction inside {ECALL, EBREAK, MRET}) |
(CONFIG.INCLUDE_M_MODE & decode_stage.instruction inside {MRET}) |
(CONFIG.INCLUDE_S_MODE & decode_stage.instruction inside {SRET, SFENCE_VMA}) |
(CONFIG.INCLUDE_IFENCE & decode_stage.instruction inside {FENCE_I});
always_comb begin

View file

@ -68,6 +68,7 @@ module dcache
logic [31:0] addr;
logic [3:0] be;
logic [31:0] data;
logic cache_op;
logic uncacheable;
} store_stage2_t;
store_stage2_t stage2_store;
@ -167,8 +168,8 @@ module dcache
end
always_comb begin
store_state_next[STORE_IDLE] = (store_state[STORE_IDLE] & ~store_request) | (store_l1_arb_ack & ~store_request);
store_state_next[STORE_L1_REQUEST] = (store_state[STORE_L1_REQUEST] & ~store_l1_arb_ack) | store_request;
store_state_next[STORE_IDLE] = (store_state[STORE_IDLE] & (~store_request | (store_request & ls_store.cache_op))) | (store_l1_arb_ack & ~store_request);
store_state_next[STORE_L1_REQUEST] = (store_state[STORE_L1_REQUEST] & ~store_l1_arb_ack) | (store_request & ~ls_store.cache_op);
end
assign store_ready = (store_state[STORE_IDLE] | store_l1_arb_ack) & (load_state[LOAD_IDLE] | load_hit);
@ -180,21 +181,22 @@ module dcache
stage2_store.uncacheable <= uncacheable_store;
stage2_store.be <= ls_store.be;
stage2_store.data <= ls_store.data_in;
stage2_store.cache_op <= ls_store.cache_op;
end
end
////////////////////////////////////////////////////
//L1 Arbiter Interface
//Priority to oldest request
fifo_interface #(.DATA_WIDTH(1)) request_order();
fifo_interface #(.DATA_TYPE(logic)) request_order();
assign request_order.data_in = load_request;
assign request_order.push = load_request | store_request;
assign request_order.push = load_request | (store_request & ~ls_store.cache_op);
assign request_order.potential_push = request_order.push;
assign request_order.pop = l1_request.ack | load_hit;
cva5_fifo #(.DATA_WIDTH(1), .FIFO_DEPTH(2))
cva5_fifo #(.DATA_TYPE(logic), .FIFO_DEPTH(2))
request_order_fifo (
.clk (clk),
.rst (rst),
@ -241,6 +243,7 @@ module dcache
.store_addr (ls_store.addr),
.store_addr_r (stage2_store.addr),
.store_req (store_request),
.cache_op_req (ls_store.cache_op),
.load_tag_hit (load_hit),
.load_tag_hit_way (load_tag_hit_way),
.store_tag_hit (store_hit),
@ -253,7 +256,7 @@ module dcache
assign data_read_addr = load_state[LOAD_FILL] ? {addr_utils.getTagLineAddr(stage2_load.addr), word_count} : addr_utils.getDataLineAddr(ls_load.addr);
generate for (genvar i=0; i < CONFIG.DCACHE.WAYS; i++) begin : data_bank_gen
byte_en_BRAM #(CONFIG.DCACHE.LINES*CONFIG.DCACHE.LINE_W) data_bank (
byte_en_bram #(CONFIG.DCACHE.LINES*CONFIG.DCACHE.LINE_W) data_bank (
.clk(clk),
.addr_a(data_read_addr),
.addr_b(addr_utils.getDataLineAddr(stage2_store.addr)),

View file

@ -48,6 +48,7 @@ module dcache_tag_banks
input logic[31:0] store_addr,
input logic[31:0] store_addr_r,
input logic store_req,
input logic cache_op_req,
output logic load_tag_hit,
output logic store_tag_hit,
@ -76,7 +77,7 @@ module dcache_tag_banks
////////////////////////////////////////////////////
//Implementation
always_ff @ (posedge clk) load_req_r <= load_req;
always_ff @ (posedge clk) store_req_r <= store_req;
always_ff @ (posedge clk) store_req_r <= store_req & ~cache_op_req;
assign external_inv = extern_inv & CONFIG.DCACHE.USE_EXTERNAL_INVALIDATIONS;
@ -90,11 +91,10 @@ module dcache_tag_banks
////////////////////////////////////////////////////
//Memory instantiation and hit detection
generate for (genvar i = 0; i < CONFIG.DCACHE.WAYS; i++) begin : tag_bank_gen
tag_bank #($bits(dtag_entry_t), CONFIG.DCACHE.LINES) dtag_bank (
dual_port_bram #(.WIDTH($bits(dtag_entry_t)), .LINES(CONFIG.DCACHE.LINES)) dtag_bank (
.clk (clk),
.rst (rst),
.en_a (store_req | (miss_req & miss_way[i]) | external_inv),
.wen_a ((miss_req & miss_way[i]) | external_inv),
.wen_a ((miss_req & miss_way[i]) | external_inv | (store_req & cache_op_req)),
.addr_a (porta_addr),
.data_in_a (new_tagline),
.data_out_a (tag_line_a[i]),

View file

@ -52,17 +52,13 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
logic [LOG2_SQ_DEPTH-1:0] sq_index;
} lq_entry_t;
logic [LOG2_SQ_DEPTH-1:0] sq_index;
logic [LOG2_SQ_DEPTH-1:0] sq_oldest;
addr_hash_t addr_hash;
logic potential_store_conflict;
sq_entry_t sq_entry;
lq_entry_t lq_data_in;
lq_entry_t lq_data_out;
fifo_interface #(.DATA_WIDTH($bits(lq_entry_t))) lq();
fifo_interface #(.DATA_TYPE(lq_entry_t)) lq();
store_queue_interface sq();
////////////////////////////////////////////////////
//Implementation
@ -83,7 +79,7 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
////////////////////////////////////////////////////
//Load Queue
cva5_fifo #(.DATA_WIDTH($bits(lq_entry_t)), .FIFO_DEPTH(MAX_IDS))
cva5_fifo #(.DATA_TYPE(lq_entry_t), .FIFO_DEPTH(MAX_IDS))
load_queue_fifo (
.clk(clk),
.rst(rst),
@ -96,18 +92,16 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
assign lq.pop = lsq.load_pop;
//FIFO data ports
assign lq_data_in = '{
assign lq.data_in = '{
addr : lsq.data_in.addr,
fn3 : lsq.data_in.fn3,
id : lsq.data_in.id,
store_collision : potential_store_conflict,
sq_index : sq_index
};
assign lq.data_in = lq_data_in;
assign lq_data_out = lq.data_out;
////////////////////////////////////////////////////
//Store Queue
assign sq.push = lsq.push & lsq.data_in.store;
assign sq.push = lsq.push & (lsq.data_in.store | lsq.data_in.cache_op);
assign sq.pop = lsq.store_pop;
assign sq.data_in = lsq.data_in;
@ -129,25 +123,27 @@ module load_store_queue //ID-based input buffer for Load/Store Unit
//Priority is for loads over stores.
//A store will be selected only if no loads are ready
logic load_blocked;
assign load_blocked = (lq_data_out.store_collision & (lq_data_out.sq_index != sq_oldest));
assign load_blocked = (lq.data_out.store_collision & (lq.data_out.sq_index != sq_oldest));
assign lsq.load_valid = lq.valid & ~load_blocked;
assign lsq.store_valid = sq.valid;
assign lsq.load_data_out = '{
addr : lq_data_out.addr,
addr : lq.data_out.addr,
load : 1,
store : 0,
cache_op : 0,
be : 'x,
fn3 : lq_data_out.fn3,
fn3 : lq.data_out.fn3,
data_in : 'x,
id : lq_data_out.id
id : lq.data_out.id
};
assign lsq.store_data_out = '{
addr : sq.data_out.addr,
load : 0,
store : 1,
cache_op : sq.data_out.cache_op,
be : sq.data_out.be,
fn3 : 'x,
data_in : sq.data_out.data,

View file

@ -137,13 +137,13 @@ module load_store_unit
id_t id;
logic [NUM_SUB_UNITS_W-1:0] subunit_id;
} load_attributes_t;
load_attributes_t mem_attr, wb_attr;
load_attributes_t wb_attr;
common_instruction_t instruction;//rs1_addr, rs2_addr, fn3, fn7, rd_addr, upper/lower opcode
logic [3:0] be;
//FIFOs
fifo_interface #(.DATA_WIDTH($bits(load_attributes_t))) load_attributes();
fifo_interface #(.DATA_TYPE(load_attributes_t)) load_attributes();
load_store_queue_interface lsq();
////////////////////////////////////////////////////
@ -153,73 +153,78 @@ module load_store_unit
//Decode
assign instruction = decode_stage.instruction;
assign unit_needed = decode_stage.instruction inside {LB, LH, LW, LBU, LHU, SB, SH, SW, FENCE};
assign unit_needed = decode_stage.instruction inside {LB, LH, LW, LBU, LHU, SB, SH, SW, FENCE} | (CONFIG.INCLUDE_CBO & decode_stage.instruction inside {CBO_INVAL, CBO_CLEAN, CBO_FLUSH});
always_comb begin
uses_rs = '0;
uses_rs[RS1] = decode_stage.instruction inside {LB, LH, LW, LBU, LHU, SB, SH, SW};
uses_rs[RS1] = decode_stage.instruction inside {LB, LH, LW, LBU, LHU, SB, SH, SW} | (CONFIG.INCLUDE_CBO & decode_stage.instruction inside {CBO_INVAL, CBO_CLEAN, CBO_FLUSH});
uses_rs[RS2] = CONFIG.INCLUDE_FORWARDING_TO_STORES ? 0 : decode_stage.instruction inside {SB, SH, SW};
uses_rd = decode_stage.instruction inside {LB, LH, LW, LBU, LHU};
end
amo_details_t amo;
amo_details_t amo_r;
logic is_load;
logic is_store;
logic is_load_r;
logic is_store_r;
logic is_fence_r;
logic [2:0] fn3_r;
logic [11:0] ls_offset_r;
////////////////////////////////////////////////////
//LS specific decode support
typedef struct packed{
logic is_load;
logic is_store;
logic is_fence;
logic is_cbo;
logic [11:0] offset;
} ls_attr_t;
ls_attr_t decode_attr;
ls_attr_t issue_attr;
assign amo.is_amo = CONFIG.INCLUDE_AMO & (instruction.upper_opcode == AMO_T);
assign amo.op = CONFIG.INCLUDE_AMO ? decode_stage.instruction[31:27] : '0;
assign amo.is_lr = CONFIG.INCLUDE_AMO & (amo.op == AMO_LR_FN5);
assign amo.is_sc = CONFIG.INCLUDE_AMO & (amo.op == AMO_SC_FN5);
logic [11:0] load_offset;
logic [11:0] store_offset;
assign load_offset = decode_stage.instruction[31:20];
assign store_offset = {decode_stage.instruction[31:25], decode_stage.instruction[11:7]};
assign is_load = (instruction.upper_opcode inside {LOAD_T, AMO_T}) & !(amo.is_amo & amo.is_sc); //LR and AMO_ops perform a read operation as well
assign is_store = (instruction.upper_opcode == STORE_T) | (amo.is_amo & amo.is_sc);//Used for LS unit and for ID tracking
assign decode_is_store = is_store;
assign decode_attr = '{
is_load : decode_stage.instruction inside {LB, LH, LW, LBU, LHU},
is_store : decode_stage.instruction inside {SB, SH, SW},
is_fence : decode_stage.instruction inside {FENCE},
is_cbo : CONFIG.INCLUDE_CBO & decode_stage.instruction inside {CBO_INVAL, CBO_CLEAN, CBO_FLUSH},
offset : decode_stage.instruction[5] ? store_offset : ((CONFIG.INCLUDE_CBO & decode_stage.instruction[2]) ? '0 :load_offset)
};
assign decode_is_store = decode_attr.is_store | decode_attr.is_cbo;
always_ff @(posedge clk) begin
if (issue_stage_ready) begin
ls_offset_r <= decode_stage.instruction[5] ? {decode_stage.instruction[31:25], decode_stage.instruction[11:7]} : decode_stage.instruction[31:20];
is_load_r <= is_load;
is_store_r <= is_store;
is_fence_r <= (instruction.upper_opcode == FENCE_T);
amo_r <= amo;
fn3_r <= amo.is_amo ? LS_W_fn3 : instruction.fn3;
end
if (issue_stage_ready)
issue_attr <= decode_attr;
end
(* ramstyle = "MLAB, no_rw_check" *) id_t rd_to_id_table [32];
(* ramstyle = "MLAB, no_rw_check" *) logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] rd_to_wb_group_table [32];
id_t store_forward_id;
logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] store_forward_wb_group;
always_ff @ (posedge clk) begin
if (instruction_issued_with_rd) begin
rd_to_id_table[issue_stage.rd_addr] <= issue_stage.id;
rd_to_wb_group_table[issue_stage.rd_addr] <= issue_rd_wb_group;
end
end
assign store_forward_id = rd_to_id_table[issue_rs_addr[RS2]];
assign store_forward_wb_group = rs2_inuse ? rd_to_wb_group_table[issue_rs_addr[RS2]] : '0;
typedef struct packed{
id_t id;
logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] wb_group;
} rd_attributes_t;
rd_attributes_t rd_attributes;
lutram_1w_1r #(.DATA_TYPE(rd_attributes_t), .DEPTH(32))
rd_to_id_table (
.clk(clk),
.waddr(issue_stage.rd_addr),
.raddr(issue_rs_addr[RS2]),
.ram_write(instruction_issued_with_rd),
.new_ram_data('{
id : issue_stage.id,
wb_group : issue_rd_wb_group
}),
.ram_data_out(rd_attributes)
);
////////////////////////////////////////////////////
//Alignment Exception
generate if (CONFIG.INCLUDE_M_MODE) begin : gen_ls_exceptions
logic new_exception;
always_comb begin
case(fn3_r)
case(issue_stage.fn3)
LS_H_fn3, L_HU_fn3 : unaligned_addr = virtual_address[0];
LS_W_fn3 : unaligned_addr = |virtual_address[1:0];
default : unaligned_addr = 0;
endcase
end
assign new_exception = unaligned_addr & issue.new_request & ~is_fence_r;
assign new_exception = unaligned_addr & issue.new_request & ~issue_attr.is_fence;
always_ff @(posedge clk) begin
if (rst)
exception.valid <= 0;
@ -229,7 +234,7 @@ module load_store_unit
always_ff @(posedge clk) begin
if (new_exception & ~exception.valid) begin
exception.code <= is_store_r ? STORE_AMO_ADDR_MISSALIGNED : LOAD_ADDR_MISSALIGNED;
exception.code <= issue_attr.is_store ? STORE_AMO_ADDR_MISSALIGNED : LOAD_ADDR_MISSALIGNED;
exception.tval <= virtual_address;
exception.id <= issue.id;
end
@ -253,12 +258,12 @@ module load_store_unit
////////////////////////////////////////////////////
//TLB interface
assign virtual_address = rf[RS1] + 32'(signed'(ls_offset_r));
assign virtual_address = rf[RS1] + 32'(signed'(issue_attr.offset));
assign tlb.virtual_address = virtual_address;
assign tlb.new_request = tlb_on & issue.new_request;
assign tlb.execute = 0;
assign tlb.rnw = is_load_r & ~is_store_r;
assign tlb.rnw = issue_attr.is_load & ~issue_attr.is_store;
////////////////////////////////////////////////////
//Byte enable generation
@ -268,7 +273,7 @@ module load_store_unit
// SB: specific byte
always_comb begin
be = 0;
case(fn3_r[1:0])
case(issue_stage.fn3[1:0])
LS_B_fn3[1:0] : be[virtual_address[1:0]] = 1;
LS_H_fn3[1:0] : begin
be[virtual_address[1:0]] = 1;
@ -282,24 +287,25 @@ module load_store_unit
//Load Store Queue
assign lsq.data_in = '{
addr : tlb_on ? tlb.physical_address : virtual_address,
fn3 : fn3_r,
fn3 : issue_stage.fn3,
be : be,
data : rf[RS2],
load : is_load_r,
store : is_store_r,
load : issue_attr.is_load,
store : issue_attr.is_store,
cache_op : issue_attr.is_cbo,
id : issue.id,
id_needed : store_forward_id
id_needed : rd_attributes.id
};
assign lsq.potential_push = issue.possible_issue;
assign lsq.push = issue.new_request & ~unaligned_addr & (~tlb_on | tlb.done) & ~is_fence_r;
assign lsq.push = issue.new_request & ~unaligned_addr & (~tlb_on | tlb.done) & ~issue_attr.is_fence;
load_store_queue # (.CONFIG(CONFIG)) lsq_block (
.clk (clk),
.rst (rst),
.gc (gc),
.lsq (lsq),
.store_forward_wb_group (store_forward_wb_group),
.store_forward_wb_group (rs2_inuse ? rd_attributes.wb_group : '0),
.wb_packet (wb_packet),
.store_retire (store_retire)
);
@ -338,7 +344,7 @@ module load_store_unit
if (rst)
fence_hold <= 0;
else
fence_hold <= (fence_hold & ~load_store_status.idle) | (issue.new_request & is_fence_r);
fence_hold <= (fence_hold & ~load_store_status.idle) | (issue.new_request & issue_attr.is_fence);
end
////////////////////////////////////////////////////
@ -359,7 +365,7 @@ module load_store_unit
endcase
end
assign mem_attr = '{
assign load_attributes.data_in = '{
is_signed : ~|lsq.load_data_out.fn3[2:1],
byte_addr : lsq.load_data_out.addr[1:0],
sign_sel : lsq.load_data_out.addr[1:0] | {1'b0, lsq.load_data_out.fn3[0]},//halfwrord
@ -367,12 +373,10 @@ module load_store_unit
id : lsq.load_data_out.id,
subunit_id : subunit_id
};
assign load_attributes.data_in = mem_attr;
assign load_attributes.push = sub_unit_load_issue;
assign load_attributes.potential_push = load_attributes.push;
cva5_fifo #(.DATA_WIDTH($bits(load_attributes_t)), .FIFO_DEPTH(ATTRIBUTES_DEPTH))
cva5_fifo #(.DATA_TYPE(load_attributes_t), .FIFO_DEPTH(ATTRIBUTES_DEPTH))
attributes_fifo (
.clk (clk),
.rst (rst),
@ -462,7 +466,7 @@ module load_store_unit
.sc_complete (sc_complete),
.sc_success (sc_success),
.clear_reservation (clear_reservation),
.amo (amo_r),
.amo (),
.uncacheable_load (uncacheable_load),
.uncacheable_store (uncacheable_store),
.is_load (sel_load),

View file

@ -59,7 +59,6 @@ module store_queue
logic [$clog2(CONFIG.NUM_WB_GROUPS)-1:0] wb_group;
sq_index_t sq_index;
} retire_table_t;
retire_table_t retire_table_in;
retire_table_t retire_table_out;
wb_packet_t wb_snoop [CONFIG.NUM_WB_GROUPS];
@ -70,9 +69,9 @@ module store_queue
addr_hash_t [CONFIG.SQ_DEPTH-1:0] hashes;
//LUTRAM-based memory blocks
sq_entry_t sq_entry_in;
sq_entry_t output_entry;
sq_entry_t output_entry_r;
logic [1:0] retire_alignment;
sq_index_t sq_index_next;
sq_index_t sq_oldest_next;
@ -82,6 +81,7 @@ module store_queue
logic [CONFIG.SQ_DEPTH-1:0] issued_one_hot;
logic [31:0] data_pre_alignment;
logic [31:0] marshalled_data;
logic [31:0] sq_data_out;
////////////////////////////////////////////////////
//Implementation
@ -116,24 +116,33 @@ module store_queue
assign sq.empty = ~|valid;
//SQ attributes and issue data
assign sq_entry_in = '{
addr : sq.data_in.addr,
be : sq.data_in.be,
data : '0
};
lutram_1w_1r #(.WIDTH($bits(sq_entry_t)), .DEPTH(CONFIG.SQ_DEPTH))
lutram_1w_1r #(.DATA_TYPE(sq_entry_t), .DEPTH(CONFIG.SQ_DEPTH))
store_attr (
.clk(clk),
.waddr(sq_index),
.raddr(sq_oldest_next),
.ram_write(sq.push),
.new_ram_data(sq_entry_in),
.new_ram_data('{
addr : sq.data_in.addr,
be : sq.data_in.be,
cache_op : sq.data_in.cache_op,
data : '0
}),
.ram_data_out(output_entry)
);
always_ff @ (posedge clk) begin
output_entry_r <= output_entry;
end
lutram_1w_1r #(.DATA_TYPE(logic[1:0]), .DEPTH(MAX_IDS))
store_alignment (
.clk(clk),
.waddr(sq.data_in.id),
.raddr(store_retire.id),
.ram_write(sq.push),
.new_ram_data(sq.data_in.addr[1:0]),
.ram_data_out(retire_alignment)
);
//Compare store addr-hashes against new load addr-hash
always_comb begin
potential_store_conflict = 0;
@ -169,21 +178,24 @@ module store_queue
wb_snoop <= wb_packet;
end
assign retire_table_in = '{id_needed : sq.data_in.id_needed, wb_group : store_forward_wb_group, sq_index : sq_index};
lutram_1w_1r #(.WIDTH($bits(retire_table_t)), .DEPTH(MAX_IDS))
lutram_1w_1r #(.DATA_TYPE(retire_table_t), .DEPTH(MAX_IDS))
store_retire_table_lutram (
.clk(clk),
.waddr(sq.data_in.id),
.raddr(store_retire.id),
.ram_write(sq.push),
.new_ram_data(retire_table_in),
.new_ram_data('{
id_needed : sq.data_in.id_needed,
wb_group : store_forward_wb_group,
sq_index : sq_index
}),
.ram_data_out(retire_table_out)
);
logic [31:0] wb_data [NUM_OF_FORWARDING_PORTS+1];
//Data issued with the store can be stored by store-id
lutram_1w_1r #(.WIDTH(32), .DEPTH(MAX_IDS))
lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS))
non_forwarded_port (
.clk(clk),
.waddr(sq.data_in.id),
@ -196,7 +208,7 @@ module store_queue
//Data from wb ports is stored by ID and then accessed by store-id to store-id-needed translation
generate
for (genvar i = 0; i < NUM_OF_FORWARDING_PORTS; i++) begin : lutrams
lutram_1w_1r #(.WIDTH(32), .DEPTH(MAX_IDS))
lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS))
writeback_port (
.clk(clk),
.waddr(wb_snoop[i+1].id),
@ -208,37 +220,41 @@ module store_queue
end
endgenerate
////////////////////////////////////////////////////
//Data Marshalling
assign data_pre_alignment = wb_data[retire_table_out.wb_group];
always_comb begin
//Input: ABCD
//Assuming aligned requests,
//Possible byte selections: (A/C/D, B/D, C/D, D)
marshalled_data[7:0] = data_pre_alignment[7:0];
marshalled_data[15:8] = (retire_alignment[1:0] == 2'b01) ? data_pre_alignment[7:0] : data_pre_alignment[15:8];
marshalled_data[23:16] = (retire_alignment[1:0] == 2'b10) ? data_pre_alignment[7:0] : data_pre_alignment[23:16];
case(retire_alignment[1:0])
2'b10 : marshalled_data[31:24] = data_pre_alignment[15:8];
2'b11 : marshalled_data[31:24] = data_pre_alignment[7:0];
default : marshalled_data[31:24] = data_pre_alignment[31:24];
endcase
end
//Final storage table for the store queue
//SQ-index addressed
lutram_1w_1r #(.WIDTH(32), .DEPTH(CONFIG.SQ_DEPTH))
lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(CONFIG.SQ_DEPTH))
sq_data_lutram (
.clk(clk),
.waddr(retire_table_out.sq_index),
.raddr(sq_oldest),
.ram_write(store_retire.valid),
.new_ram_data(wb_data[retire_table_out.wb_group]),
.ram_data_out(data_pre_alignment)
.new_ram_data(marshalled_data),
.ram_data_out(sq_data_out)
);
////////////////////////////////////////////////////
//Store Transaction Outputs
always_comb begin
//Input: ABCD
//Assuming aligned requests,
//Possible byte selections: (A/C/D, B/D, C/D, D)
sq_data_out[7:0] = data_pre_alignment[7:0];
sq_data_out[15:8] = (output_entry_r.addr[1:0] == 2'b01) ? data_pre_alignment[7:0] : data_pre_alignment[15:8];
sq_data_out[23:16] = (output_entry_r.addr[1:0] == 2'b10) ? data_pre_alignment[7:0] : data_pre_alignment[23:16];
case(output_entry_r.addr[1:0])
2'b10 : sq_data_out[31:24] = data_pre_alignment[15:8];
2'b11 : sq_data_out[31:24] = data_pre_alignment[7:0];
default : sq_data_out[31:24] = data_pre_alignment[31:24];
endcase
end
assign sq.valid = |released_count;
assign sq.data_out = '{
addr : output_entry_r.addr,
be : output_entry_r.be,
cache_op : output_entry_r.cache_op,
data : sq_data_out
};

View file

@ -50,7 +50,7 @@ module mul_unit
logic valid [2];
id_t id [2];
logic rs1_is_signed, rs2_is_signed;
logic rs1_is_signed, rs2_is_signed, is_mulhx;
logic signed [32:0] rs1_ext, rs2_ext;
logic signed [32:0] rs1_r, rs2_r;
@ -68,14 +68,19 @@ module mul_unit
uses_rs[RS2] = unit_needed;
uses_rd = unit_needed;
end
assign instruction = decode_stage.instruction;
always_ff @(posedge clk) begin
if (issue_stage_ready) begin
rs1_is_signed <= instruction.fn3[1:0] inside {MULH_fn3[1:0], MULHSU_fn3[1:0]};
rs2_is_signed <= instruction.fn3[1:0] inside {MULH_fn3[1:0]};
is_mulhx <= instruction.fn3[1:0] inside {MULH_fn3[1:0], MULHSU_fn3[1:0], MULHU_fn3[1:0]};
end
end
////////////////////////////////////////////////////
//Issue
assign rs1_is_signed = issue_stage.fn3[1:0] inside {MULH_fn3[1:0], MULHSU_fn3[1:0]};//MUL doesn't matter
assign rs2_is_signed = issue_stage.fn3[1:0] inside {MUL_fn3[1:0], MULH_fn3[1:0]};//MUL doesn't matter
assign rs1_ext = signed'({rf[RS1][31] & rs1_is_signed, rf[RS1]});
assign rs2_ext = signed'({rf[RS2][31] & rs2_is_signed, rf[RS2]});
assign rs1_ext = signed'({rs1_is_signed & rf[RS1][31], rf[RS1]});
assign rs2_ext = signed'({rs2_is_signed & rf[RS2][31], rf[RS2]});
//Pipeline advancement control signals
assign issue.ready = stage1_advance;
@ -96,7 +101,7 @@ module mul_unit
//Attribute Pipeline
always_ff @ (posedge clk) begin
if (stage1_advance) begin
mulh[0] <= (issue_stage.fn3[1:0] != MUL_fn3[1:0]);
mulh[0] <= is_mulhx;
id[0] <= issue.id;
end
if (stage2_advance) begin

View file

@ -83,8 +83,6 @@ module branch_predictor
logic branch_prediction_used;
logic [CONFIG.BP.WAYS-1:0] branch_predictor_update_way;
} branch_metadata_t;
(* ramstyle = "MLAB, no_rw_check" *) logic [$bits(branch_metadata_t)-1:0] branch_metadata_table [MAX_IDS];
branch_metadata_t branch_metadata_if;
branch_metadata_t branch_metadata_ex;
logic branch_predictor_direction_changed;
@ -106,31 +104,37 @@ module branch_predictor
genvar i;
generate if (CONFIG.INCLUDE_BRANCH_PREDICTOR)
for (i=0; i<CONFIG.BP.WAYS; i++) begin : gen_branch_tag_banks
branch_predictor_ram #(.C_DATA_WIDTH($bits(branch_table_entry_t)), .C_DEPTH(CONFIG.BP.ENTRIES))
dual_port_bram #(.WIDTH($bits(branch_table_entry_t)), .LINES(CONFIG.BP.ENTRIES))
tag_bank (
.clk (clk),
.rst (rst),
.write_addr (addr_utils.getHashedLineAddr(br_results.pc, i)),
.write_en (tag_update_way[i]),
.write_data (ex_entry),
.read_addr (addr_utils.getHashedLineAddr(bp.next_pc, i)),
.read_en (bp.new_mem_request),
.read_data (if_entry[i]));
.en_a (tag_update_way[i]),
.wen_a (tag_update_way[i]),
.addr_a (addr_utils.getHashedLineAddr(br_results.pc, i)),
.data_in_a (ex_entry),
.data_out_a (),
.en_b (bp.new_mem_request),
.wen_b (0),
.addr_b (addr_utils.getHashedLineAddr(bp.next_pc, i)),
.data_in_b ('0),
.data_out_b (if_entry[i]));
end
endgenerate
generate if (CONFIG.INCLUDE_BRANCH_PREDICTOR)
for (i=0; i<CONFIG.BP.WAYS; i++) begin : gen_branch_table_banks
branch_predictor_ram #(.C_DATA_WIDTH(32), .C_DEPTH(CONFIG.BP.ENTRIES))
dual_port_bram #(.WIDTH(32), .LINES(CONFIG.BP.ENTRIES))
addr_table (
.clk (clk),
.rst (rst),
.write_addr (addr_utils.getHashedLineAddr(br_results.pc, i)),
.write_en (target_update_way[i]),
.write_data (br_results.target_pc),
.read_addr (addr_utils.getHashedLineAddr(bp.next_pc, i)),
.read_en (bp.new_mem_request),
.read_data (predicted_pc[i])
.en_a (target_update_way[i]),
.wen_a (target_update_way[i]),
.addr_a (addr_utils.getHashedLineAddr(br_results.pc, i)),
.data_in_a (br_results.target_pc),
.data_out_a (),
.en_b (bp.new_mem_request),
.wen_b (0),
.addr_b (addr_utils.getHashedLineAddr(bp.next_pc, i)),
.data_in_b ('0),
.data_out_b (predicted_pc[i])
);
end
endgenerate
@ -172,15 +176,20 @@ module branch_predictor
.en (1'b1),
.one_hot (replacement_way)
);
assign branch_metadata_if.branch_predictor_metadata = if_entry[hit_way].metadata;
assign branch_metadata_if.branch_prediction_used = use_predicted_pc;
assign branch_metadata_if.branch_predictor_update_way = tag_match ? tag_matches : replacement_way;
always_ff @ (posedge clk) begin
if (bp.pc_id_assigned)
branch_metadata_table[bp.pc_id] <= branch_metadata_if;
end
assign branch_metadata_ex = branch_metadata_table[br_results.id];
lutram_1w_1r #(.DATA_TYPE(branch_metadata_t), .DEPTH(MAX_IDS))
branch_metadata_table (
.clk(clk),
.waddr(bp.pc_id),
.raddr(br_results.id),
.ram_write(bp.pc_id_assigned),
.new_ram_data('{
branch_predictor_metadata : if_entry[hit_way].metadata,
branch_prediction_used : use_predicted_pc,
branch_predictor_update_way : tag_match ? tag_matches : replacement_way
}),
.ram_data_out(branch_metadata_ex)
);
////////////////////////////////////////////////////
//Execution stage update

View file

@ -36,7 +36,6 @@ module fetch
input logic branch_flush,
input gc_outputs_t gc,
input logic tlb_on,
input logic exception,
//ID Support
@ -94,7 +93,6 @@ module fetch
logic mmu_fault;
logic [NUM_SUB_UNITS_W-1:0] subunit_id;
} fetch_attributes_t;
fetch_attributes_t fetch_attr_next;
fetch_attributes_t fetch_attr;
logic [MAX_OUTSTANDING_REQUESTS_W:0] inflight_count;
@ -110,15 +108,13 @@ module fetch
logic [31:0] pc;
logic flush_or_rst;
fifo_interface #(.DATA_WIDTH($bits(fetch_attributes_t))) fetch_attr_fifo();
fifo_interface #(.DATA_TYPE(fetch_attributes_t)) fetch_attr_fifo();
logic update_pc;
logic new_mem_request;
logic exception_pending;
logic internal_fetch_complete;
logic [31:0] translated_address;
genvar i;
////////////////////////////////////////////////////
//Implementation
@ -161,50 +157,55 @@ module fetch
assign bp.pc_id = pc_id;
assign bp.pc_id_assigned = pc_id_assigned;
assign ras.pop = bp.use_prediction & bp.is_return & ~branch_flush & ~gc.pc_override & new_mem_request & (~early_branch_flush);
assign ras.push = bp.use_prediction & bp.is_call & ~branch_flush & ~gc.pc_override & new_mem_request & (~early_branch_flush);
////////////////////////////////////////////////////
//RAS support
logic ras_update_permitted;
assign ras_update_permitted = bp.use_prediction & new_mem_request & ~(branch_flush | gc.pc_override | early_branch_flush);
assign ras.pop = bp.is_return & ras_update_permitted;
assign ras.push = bp.is_call & ras_update_permitted;
assign ras.branch_fetched = bp.is_branch & ras_update_permitted;
assign ras.new_addr = pc_plus_4;
assign ras.branch_fetched = bp.use_prediction & bp.is_branch & new_mem_request & (~early_branch_flush); //flush not needed as FIFO resets inside of RAS
////////////////////////////////////////////////////
//TLB
assign tlb.virtual_address = pc;
assign tlb.execute = 1;
assign tlb.rnw = 0;
assign tlb.new_request = tlb.ready & (CONFIG.INCLUDE_S_MODE & tlb_on);
assign translated_address = (CONFIG.INCLUDE_S_MODE & tlb_on) ? tlb.physical_address : pc;
assign tlb.new_request = tlb.ready;
//////////////////////////////////////////////
//Issue Control Signals
assign flush_or_rst = (rst | gc.fetch_flush | early_branch_flush);
assign new_mem_request = (~tlb_on | tlb.done) & pc_id_available & ~fetch_attr_fifo.full & units_ready & (~gc.fetch_hold) & (~exception_pending);
assign new_mem_request = tlb.done & pc_id_available & ~fetch_attr_fifo.full & units_ready & (~gc.fetch_hold) & (~exception_pending);
assign pc_id_assigned = new_mem_request | tlb.is_fault;
//////////////////////////////////////////////
//Subunit Tracking
assign fetch_attr_fifo.push = pc_id_assigned;
assign fetch_attr_fifo.potential_push = pc_id_assigned;
assign fetch_attr_fifo.pop = internal_fetch_complete;
logic [NUM_SUB_UNITS_W-1:0] subunit_id;
one_hot_to_integer #(NUM_SUB_UNITS)
hit_way_conv (
.one_hot (sub_unit_address_match),
.int_out (fetch_attr_next.subunit_id)
.int_out (subunit_id)
);
assign fetch_attr_next.is_predicted_branch_or_jump = bp.use_prediction;
assign fetch_attr_next.is_branch = bp.use_prediction & bp.is_branch;
assign fetch_attr_next.address_valid = address_valid;
assign fetch_attr_next.mmu_fault = tlb.is_fault;
assign fetch_attr_fifo.data_in = '{
is_predicted_branch_or_jump : bp.use_prediction,
is_branch : (bp.use_prediction & bp.is_branch),
address_valid : address_valid,
mmu_fault : tlb.is_fault,
subunit_id : subunit_id
};
assign fetch_attr_fifo.push = pc_id_assigned;
assign fetch_attr_fifo.potential_push = pc_id_assigned;
assign fetch_attr_fifo.pop = internal_fetch_complete;
assign fetch_attr_fifo.data_in = fetch_attr_next;
cva5_fifo #(.DATA_WIDTH($bits(fetch_attributes_t)), .FIFO_DEPTH(MAX_OUTSTANDING_REQUESTS))
cva5_fifo #(.DATA_TYPE(fetch_attributes_t), .FIFO_DEPTH(MAX_OUTSTANDING_REQUESTS))
attributes_fifo (
.clk (clk),
.rst (rst),
.fifo (fetch_attr_fifo)
);
assign fetch_attr = fetch_attr_fifo.data_out;
assign inflight_count_next = inflight_count + MAX_OUTSTANDING_REQUESTS_W'(fetch_attr_fifo.push) - MAX_OUTSTANDING_REQUESTS_W'(fetch_attr_fifo.pop);
@ -231,7 +232,7 @@ module fetch
//In either case, data_valid must NOT be asserted.
generate for (i=0; i < NUM_SUB_UNITS; i++) begin : gen_fetch_sources
assign sub_unit[i].new_request = fetch_attr_fifo.push & sub_unit_address_match[i];
assign sub_unit[i].addr = translated_address;
assign sub_unit[i].addr = tlb.physical_address;
assign sub_unit[i].re = 1;
assign sub_unit[i].we = 0;
assign sub_unit[i].be = '0;
@ -244,7 +245,7 @@ module fetch
endgenerate
generate if (CONFIG.INCLUDE_ILOCAL_MEM) begin : gen_fetch_local_mem
assign sub_unit_address_match[LOCAL_MEM_ID] = ilocal_mem_addr_utils.address_range_check(translated_address);
assign sub_unit_address_match[LOCAL_MEM_ID] = ilocal_mem_addr_utils.address_range_check(tlb.physical_address);
local_mem_sub_unit i_local_mem (
.clk (clk),
.rst (rst),
@ -255,7 +256,7 @@ module fetch
endgenerate
generate if (CONFIG.INCLUDE_IBUS) begin : gen_fetch_ibus
assign sub_unit_address_match[BUS_ID] = ibus_addr_utils.address_range_check(translated_address);
assign sub_unit_address_match[BUS_ID] = ibus_addr_utils.address_range_check(tlb.physical_address);
wishbone_master iwishbone_bus (
.clk (clk),
.rst (rst),
@ -266,7 +267,7 @@ module fetch
endgenerate
generate if (CONFIG.INCLUDE_ICACHE) begin : gen_fetch_icache
assign sub_unit_address_match[ICACHE_ID] = icache_addr_utils.address_range_check(translated_address);
assign sub_unit_address_match[ICACHE_ID] = icache_addr_utils.address_range_check(tlb.physical_address);
icache #(.CONFIG(CONFIG))
i_cache (
.clk (clk),

View file

@ -68,7 +68,7 @@ module icache
logic second_cycle;
logic [31:0] second_cycle_addr;
fifo_interface #(.DATA_WIDTH(32)) input_fifo();
fifo_interface #(.DATA_TYPE(logic[31:0])) input_fifo();
logic new_request;
logic [31:0] new_request_addr;
@ -88,7 +88,7 @@ module icache
assign new_request_addr = input_fifo.valid ? input_fifo.data_out : fetch_sub.addr;
cva5_fifo #(.DATA_WIDTH(32), .FIFO_DEPTH(2))
cva5_fifo #(.DATA_TYPE(logic[31:0]), .FIFO_DEPTH(2))
cache_input_fifo (
.clk (clk),
.rst (rst),
@ -190,17 +190,17 @@ module icache
//Data Banks
genvar i;
generate for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : idata_bank_gen
byte_en_BRAM #(CONFIG.ICACHE.LINES*CONFIG.ICACHE.LINE_W) idata_bank (
dual_port_bram #(.WIDTH(32), .LINES(CONFIG.ICACHE.LINES*CONFIG.ICACHE.LINE_W)) idata_bank (
.clk(clk),
.addr_a(addr_utils.getDataLineAddr(new_request_addr)),
.addr_b(addr_utils.getDataLineAddr({second_cycle_addr[31:SCONFIG.SUB_LINE_ADDR_W+2], word_count, 2'b0})),
.en_a(new_request),
.en_b(tag_update_way[i] & l1_response.data_valid),
.be_a('0),
.be_b('1),
.wen_a(0),
.addr_a(addr_utils.getDataLineAddr(new_request_addr)),
.data_in_a('0),
.data_in_b(l1_response.data),
.data_out_a(data_out[i]),
.en_b(1),
.wen_b(tag_update_way[i] & l1_response.data_valid),
.addr_b(addr_utils.getDataLineAddr({second_cycle_addr[31:SCONFIG.SUB_LINE_ADDR_W+2], word_count, 2'b0})),
.data_in_b(l1_response.data),
.data_out_b()
);
end endgenerate

View file

@ -63,7 +63,8 @@ module itag_banks
genvar i;
generate
for (i=0; i < CONFIG.ICACHE.WAYS; i++) begin : tag_bank_gen
tag_bank #(SCONFIG.TAG_W+1, CONFIG.ICACHE.LINES) itag_bank (.*,
dual_port_bram #(.WIDTH(SCONFIG.TAG_W+1), .LINES(CONFIG.ICACHE.LINES)) itag_bank (.*,
.clk(clk),
.en_a(stage1_adv),
.wen_a('0),
.addr_a(stage1_line_addr),

View file

@ -38,33 +38,36 @@ module ras
ras_interface.self ras
);
(* ramstyle = "MLAB, no_rw_check" *) logic[31:0] lut_ram [CONFIG.BP.RAS_ENTRIES];
localparam RAS_DEPTH_W = $clog2(CONFIG.BP.RAS_ENTRIES);
logic [RAS_DEPTH_W-1:0] read_index;
logic [RAS_DEPTH_W-1:0] new_index;
fifo_interface #(.DATA_WIDTH(RAS_DEPTH_W)) ri_fifo();
///////////////////////////////////////////////////////
//For simulation purposes
initial lut_ram = '{default: 0};
fifo_interface #(.DATA_TYPE(logic[RAS_DEPTH_W-1:0])) ri_fifo();
///////////////////////////////////////////////////////
assign ras.addr = lut_ram[read_index];
//On a speculative branch, save the current stack pointer
//Restored if branch is misspredicted (gc_fetch_flush)
cva5_fifo #(.DATA_WIDTH(RAS_DEPTH_W), .FIFO_DEPTH(MAX_IDS))
read_index_fifo (.clk, .rst(rst | gc.fetch_flush | early_branch_flush_ras_adjust), .fifo(ri_fifo));
cva5_fifo #(.DATA_TYPE(logic[RAS_DEPTH_W-1:0]), .FIFO_DEPTH(MAX_IDS))
read_index_fifo (
.clk,
.rst(rst | gc.fetch_flush | early_branch_flush_ras_adjust),
.fifo(ri_fifo)
);
assign ri_fifo.data_in = read_index;
assign ri_fifo.push = ras.branch_fetched;
assign ri_fifo.potential_push = ras.branch_fetched;
assign ri_fifo.pop = ras.branch_retired & ri_fifo.valid; //Prevent popping from fifo if reset due to early_branch_flush_ras_adjust
always_ff @ (posedge clk) begin
if (ras.push)
lut_ram[new_index] <= ras.new_addr;
end
lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(CONFIG.BP.RAS_ENTRIES))
ras_stack (
.clk(clk),
.waddr(new_index),
.raddr(read_index),
.ram_write(ras.push),
.new_ram_data(ras.new_addr),
.ram_data_out(ras.addr)
);
//Rolls over when full, most recent calls will be correct, but calls greater than depth
//will be lost.
logic [RAS_DEPTH_W-1:0] new_index_base;

View file

@ -1,209 +0,0 @@
/*
* Copyright © 2020 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
*/
module illegal_instruction_checker
import cva5_config::*;
import riscv_types::*;
# (
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG
)
(
input logic [31:0] instruction,
output logic illegal_instruction
);
////////////////////////////////////////////////////
//Instruction Patterns for Illegal Instruction Checking
//Base ISA
localparam [31:0] BEQ = 32'b?????????????????000?????1100011;
localparam [31:0] BNE = 32'b?????????????????001?????1100011;
localparam [31:0] BLT = 32'b?????????????????100?????1100011;
localparam [31:0] BGE = 32'b?????????????????101?????1100011;
localparam [31:0] BLTU = 32'b?????????????????110?????1100011;
localparam [31:0] BGEU = 32'b?????????????????111?????1100011;
localparam [31:0] JALR = 32'b?????????????????000?????1100111;
localparam [31:0] JAL = 32'b?????????????????????????1101111;
localparam [31:0] LUI = 32'b?????????????????????????0110111;
localparam [31:0] AUIPC = 32'b?????????????????????????0010111;
localparam [31:0] ADDI = 32'b?????????????????000?????0010011;
localparam [31:0] SLLI = 32'b000000???????????001?????0010011;
localparam [31:0] SLTI = 32'b?????????????????010?????0010011;
localparam [31:0] SLTIU = 32'b?????????????????011?????0010011;
localparam [31:0] XORI = 32'b?????????????????100?????0010011;
localparam [31:0] SRLI = 32'b000000???????????101?????0010011;
localparam [31:0] SRAI = 32'b010000???????????101?????0010011;
localparam [31:0] ORI = 32'b?????????????????110?????0010011;
localparam [31:0] ANDI = 32'b?????????????????111?????0010011;
localparam [31:0] ADD = 32'b0000000??????????000?????0110011;
localparam [31:0] SUB = 32'b0100000??????????000?????0110011;
localparam [31:0] SLL = 32'b0000000??????????001?????0110011;
localparam [31:0] SLT = 32'b0000000??????????010?????0110011;
localparam [31:0] SLTU = 32'b0000000??????????011?????0110011;
localparam [31:0] XOR = 32'b0000000??????????100?????0110011;
localparam [31:0] SRL = 32'b0000000??????????101?????0110011;
localparam [31:0] SRA = 32'b0100000??????????101?????0110011;
localparam [31:0] OR = 32'b0000000??????????110?????0110011;
localparam [31:0] AND = 32'b0000000??????????111?????0110011;
localparam [31:0] LB = 32'b?????????????????000?????0000011;
localparam [31:0] LH = 32'b?????????????????001?????0000011;
localparam [31:0] LW = 32'b?????????????????010?????0000011;
localparam [31:0] LBU = 32'b?????????????????100?????0000011;
localparam [31:0] LHU = 32'b?????????????????101?????0000011;
localparam [31:0] SB = 32'b?????????????????000?????0100011;
localparam [31:0] SH = 32'b?????????????????001?????0100011;
localparam [31:0] SW = 32'b?????????????????010?????0100011;
localparam [31:0] FENCE = 32'b?????????????????000?????0001111;
localparam [31:0] FENCE_I = 32'b?????????????????001?????0001111;
localparam [31:0] ECALL = 32'b00000000000000000000000001110011;
localparam [31:0] EBREAK = 32'b00000000000100000000000001110011;
localparam [31:0] CSRRW = 32'b?????????????????001?????1110011;
localparam [31:0] CSRRS = 32'b?????????????????010?????1110011;
localparam [31:0] CSRRC = 32'b?????????????????011?????1110011;
localparam [31:0] CSRRWI = 32'b?????????????????101?????1110011;
localparam [31:0] CSRRSI = 32'b?????????????????110?????1110011;
localparam [31:0] CSRRCI = 32'b?????????????????111?????1110011;
//Mul
localparam [31:0] MUL = 32'b0000001??????????000?????0110011;
localparam [31:0] MULH = 32'b0000001??????????001?????0110011;
localparam [31:0] MULHSU = 32'b0000001??????????010?????0110011;
localparam [31:0] MULHU = 32'b0000001??????????011?????0110011;
//Div
localparam [31:0] DIV = 32'b0000001??????????100?????0110011;
localparam [31:0] DIVU = 32'b0000001??????????101?????0110011;
localparam [31:0] REM = 32'b0000001??????????110?????0110011;
localparam [31:0] REMU = 32'b0000001??????????111?????0110011;
//AMO
localparam [31:0] AMO_ADD = 32'b00000????????????010?????0101111;
localparam [31:0] AMO_XOR = 32'b00100????????????010?????0101111;
localparam [31:0] AMO_OR = 32'b01000????????????010?????0101111;
localparam [31:0] AMO_AND = 32'b01100????????????010?????0101111;
localparam [31:0] AMO_MIN = 32'b10000????????????010?????0101111;
localparam [31:0] AMO_MAX = 32'b10100????????????010?????0101111;
localparam [31:0] AMO_MINU = 32'b11000????????????010?????0101111;
localparam [31:0] AMO_MAXU = 32'b11100????????????010?????0101111;
localparam [31:0] AMO_SWAP = 32'b00001????????????010?????0101111;
localparam [31:0] LR = 32'b00010??00000?????010?????0101111;
localparam [31:0] SC = 32'b00011????????????010?????0101111;
//Machine/Supervisor
localparam [31:0] SRET = 32'b00010000001000000000000001110011;
localparam [31:0] MRET = 32'b00110000001000000000000001110011;
localparam [31:0] SFENCE_VMA = 32'b0001001??????????000000001110011;
localparam [31:0] WFI = 32'b00010000010100000000000001110011;
logic base_legal;
logic csr_legal;
logic csr_addr_base;
logic csr_addr_machine;
logic csr_addr_supervisor;
logic csr_addr_debug;
logic mul_legal;
logic div_legal;
logic ifence_legal;
logic amo_legal;
logic machine_legal;
logic supervisor_legal;
////////////////////////////////////////////////////
//Implementation
assign base_legal = instruction inside {
BEQ, BNE, BLT, BGE, BLTU, BGEU, JALR, JAL, LUI, AUIPC,
ADDI, SLLI, SLTI, SLTIU, XORI, SRLI, SRAI, ORI, ANDI,
ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND,
LB, LH, LW, LBU, LHU, SB, SH, SW,
FENCE
};
assign csr_addr_base = instruction[31:20] inside {
FFLAGS, FRM, FCSR,
CYCLE, TIME, INSTRET, CYCLEH, TIMEH, INSTRETH
};
assign csr_addr_machine = instruction[31:20] inside {
MVENDORID, MARCHID, MIMPID, MHARTID,
MSTATUS, MISA, MEDELEG, MIDELEG, MIE, MTVEC, MCOUNTEREN,
MSCRATCH, MEPC, MCAUSE, MTVAL, MIP,
MCYCLE, MINSTRET, MCYCLEH, MINSTRETH
};
assign csr_addr_supervisor = instruction[31:20] inside {
SSTATUS, SEDELEG, SIDELEG, SIE, STVEC, SCOUNTEREN,
SSCRATCH, SEPC, SCAUSE, STVAL, SIP,
SATP
};
assign csr_addr_debug = instruction[31:20] inside {
DCSR, DPC, DSCRATCH
};
//Privilege check done later on instruction issue
//Here we just check instruction encoding and valid CSR address
assign csr_legal = instruction inside {
CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI
} && (
csr_addr_base |
(CONFIG.INCLUDE_M_MODE & csr_addr_machine) |
(CONFIG.INCLUDE_S_MODE & csr_addr_supervisor)
);
assign mul_legal = instruction inside {
MUL, MULH, MULHSU, MULHU
};
assign div_legal = instruction inside {
DIV, DIVU, REM, REMU
};
assign ifence_legal = instruction inside {FENCE_I};
assign amo_legal = instruction inside {
AMO_ADD, AMO_XOR, AMO_OR, AMO_AND, AMO_MIN, AMO_MAX, AMO_MINU, AMO_MAXU, AMO_SWAP,
LR, SC
};
assign machine_legal = instruction inside {
MRET, ECALL, EBREAK
};
assign supervisor_legal = instruction inside {
SRET, SFENCE_VMA, WFI
};
assign illegal_instruction = ~(
base_legal |
(CONFIG.INCLUDE_CSRS & csr_legal) |
(CONFIG.INCLUDE_MUL & mul_legal) |
(CONFIG.INCLUDE_DIV & div_legal) |
(CONFIG.INCLUDE_AMO & amo_legal) |
(CONFIG.INCLUDE_IFENCE & ifence_legal) |
(CONFIG.INCLUDE_M_MODE & machine_legal) |
(CONFIG.INCLUDE_S_MODE & supervisor_legal)
);
endmodule

View file

@ -81,18 +81,16 @@ module instruction_metadata_and_id_management
output logic [$clog2(NUM_EXCEPTION_SOURCES)-1:0] current_exception_unit
);
//////////////////////////////////////////
(* ramstyle = "MLAB, no_rw_check" *) logic [31:0] pc_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) logic [31:0] instruction_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) logic [0:0] valid_fetch_addr_table [MAX_IDS];
logic [31:0] decode_pc;
logic [31:0] decode_instruction;
fetch_metadata_t decode_fetch_metadata;
(* ramstyle = "MLAB, no_rw_check" *) logic [0:0] uses_rd_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) logic [0:0] is_store_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) phys_addr_t id_to_phys_rd_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) logic [$bits(fetch_metadata_t)-1:0] fetch_metadata_table [MAX_IDS];
(* ramstyle = "MLAB, no_rw_check" *) logic [$bits(exception_sources_t)-1:0] exception_unit_table [MAX_IDS];
typedef struct packed {
logic is_rd;
logic is_store;
} instruction_type_t;
instruction_type_t decode_type;
instruction_type_t retire_type [RETIRE_PORTS];
id_t decode_id;
id_t oldest_pre_issue_id;
@ -115,60 +113,98 @@ module instruction_metadata_and_id_management
////////////////////////////////////////////////////
//Instruction Metadata
//PC table
//Number of read ports = 1 or 2 (decode stage + exception logic (if enabled))
always_ff @ (posedge clk) begin
if (pc_id_assigned)
pc_table[pc_id] <= if_pc;
end
//PC table(s)
lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS))
pc_table (
.clk(clk),
.waddr(pc_id),
.raddr(decode_id),
.ram_write(pc_id_assigned),
.new_ram_data(if_pc),
.ram_data_out(decode_pc)
);
generate if (CONFIG.INCLUDE_M_MODE) begin : gen_pc_id_exception_support
lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS))
pc_table_exception (
.clk(clk),
.waddr(pc_id),
.raddr(retire_ids_next[0]),
.ram_write(pc_id_assigned),
.new_ram_data(if_pc),
.ram_data_out(oldest_pc)
);
end endgenerate
////////////////////////////////////////////////////
//Instruction table
//Number of read ports = 1 (decode stage)
always_ff @ (posedge clk) begin
if (fetch_complete)
instruction_table[fetch_id] <= fetch_instruction;
end
lutram_1w_1r #(.DATA_TYPE(logic[31:0]), .DEPTH(MAX_IDS))
instruction_table (
.clk(clk),
.waddr(fetch_id),
.raddr(decode_id),
.ram_write(fetch_complete),
.new_ram_data(fetch_instruction),
.ram_data_out(decode_instruction)
);
////////////////////////////////////////////////////
//Valid fetched address table
//Number of read ports = 1 (decode stage)
always_ff @ (posedge clk) begin
if (fetch_complete)
fetch_metadata_table[fetch_id] <= fetch_metadata;
end
lutram_1w_1r #(.DATA_TYPE(fetch_metadata_t), .DEPTH(MAX_IDS))
fetch_metadata_table (
.clk(clk),
.waddr(fetch_id),
.raddr(decode_id),
.ram_write(fetch_complete),
.new_ram_data(fetch_metadata),
.ram_data_out(decode_fetch_metadata)
);
////////////////////////////////////////////////////
//Uses rd table
//Retire Instruction Type Table
//Number of read ports = RETIRE_PORTS
always_ff @ (posedge clk) begin
if (decode_advance)
uses_rd_table[decode_id] <= decode_uses_rd & |decode_rd_addr;
end
////////////////////////////////////////////////////
//Is store table
//Number of read ports = RETIRE_PORTS
always_ff @ (posedge clk) begin
if (decode_advance)
is_store_table[decode_id] <= decode_is_store;
end
lutram_1w_mr #(.DATA_TYPE(instruction_type_t), .DEPTH(MAX_IDS), .NUM_READ_PORTS(RETIRE_PORTS))
retire_instruction_type_table (
.clk(clk),
.waddr(decode_id),
.raddr(retire_ids_next),
.ram_write(decode_advance),
.new_ram_data('{
is_rd : (decode_uses_rd & |decode_rd_addr),
is_store : decode_is_store
}),
.ram_data_out(retire_type)
);
////////////////////////////////////////////////////
//id_to_phys_rd_table
//Number of read ports = WB_GROUPS
always_ff @ (posedge clk) begin
if (decode_advance)
id_to_phys_rd_table[decode_id] <= decode_phys_rd_addr;
end
id_t wb_ids [CONFIG.NUM_WB_GROUPS];
always_comb for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++)
wb_ids[i] = wb_packet[i].id;
lutram_1w_mr #(.DATA_TYPE(phys_addr_t), .DEPTH(MAX_IDS), .NUM_READ_PORTS(CONFIG.NUM_WB_GROUPS))
id_to_phys_rd_table (
.clk(clk),
.waddr(decode_id),
.raddr(wb_ids),
.ram_write(decode_advance),
.new_ram_data(decode_phys_rd_addr),
.ram_data_out(wb_phys_addr)
);
////////////////////////////////////////////////////
//Exception unit table
always_ff @ (posedge clk) begin
if (decode_advance)
exception_unit_table[decode_id] <= decode_exception_unit;
end
generate if (CONFIG.INCLUDE_M_MODE) begin : gen_id_exception_support
lutram_1w_1r #(.DATA_TYPE(logic[$bits(exception_sources_t)-1:0]), .DEPTH(MAX_IDS))
exception_unit_table (
.clk(clk),
.waddr(decode_id),
.raddr(retire_ids_next[0]),
.ram_write(decode_advance),
.new_ram_data(decode_exception_unit),
.ram_data_out(current_exception_unit)
);
end endgenerate
////////////////////////////////////////////////////
//ID Management
@ -282,11 +318,6 @@ module instruction_metadata_and_id_management
.in_use (id_waiting_for_writeback)
);
////////////////////////////////////////////////////
//WB phys_addr lookup
always_comb for (int i = 0; i < CONFIG.NUM_WB_GROUPS; i++)
wb_phys_addr[i] = id_to_phys_rd_table[wb_packet[i].id];
////////////////////////////////////////////////////
//Retirer
logic contiguous_retire;
@ -294,15 +325,6 @@ module instruction_metadata_and_id_management
logic id_ready_to_retire [RETIRE_PORTS];
logic [LOG2_RETIRE_PORTS-1:0] retire_with_rd_sel;
logic [LOG2_RETIRE_PORTS-1:0] retire_with_store_sel;
logic [RETIRE_PORTS-1:0] retire_id_uses_rd;
logic [RETIRE_PORTS-1:0] retire_id_is_store;
logic [RETIRE_PORTS-1:0] retire_id_waiting_for_writeback;
generate for (i = 0; i < RETIRE_PORTS; i++) begin : gen_retire_writeback
assign retire_id_uses_rd[i] = uses_rd_table[retire_ids_next[i]];
assign retire_id_is_store[i] = is_store_table[retire_ids_next[i]];
assign retire_id_waiting_for_writeback[i] = id_waiting_for_writeback[i];
end endgenerate
//Supports retiring up to RETIRE_PORTS instructions. The retired block of instructions must be
//contiguous and must start with the first retire port. Additionally, only one register file writing
@ -315,29 +337,36 @@ module instruction_metadata_and_id_management
contiguous_retire = ~gc.retire_hold;
retire_with_rd_found = 0;
retire_with_store_found = 0;
retire_with_rd_sel = 0;
retire_with_store_sel = 0;
for (int i = 0; i < RETIRE_PORTS; i++) begin
id_is_post_issue[i] = post_issue_count > ID_COUNTER_W'(i);
id_ready_to_retire[i] = (id_is_post_issue[i] & contiguous_retire & ~id_waiting_for_writeback[i]);
retire_port_valid_next[i] = id_ready_to_retire[i] & ~((retire_id_uses_rd[i] & retire_with_rd_found) | (retire_id_is_store[i] & retire_with_store_found));
retire_port_valid_next[i] = id_ready_to_retire[i] & ~((retire_type[i].is_rd & retire_with_rd_found) | (retire_type[i].is_store & retire_with_store_found));
retire_with_rd_found |= retire_port_valid_next[i] & retire_id_uses_rd[i];
retire_with_store_found |= retire_port_valid_next[i] & retire_id_is_store[i];
retire_with_rd_found |= retire_port_valid_next[i] & retire_type[i].is_rd;
retire_with_store_found |= retire_port_valid_next[i] & retire_type[i].is_store;
contiguous_retire &= retire_port_valid_next[i] & ~gc.exception_pending;
if (retire_port_valid_next[i] & retire_type[i].is_rd)
retire_with_rd_sel = LOG2_RETIRE_PORTS'(i);
if (retire_port_valid_next[i] & retire_type[i].is_store)
retire_with_store_sel = LOG2_RETIRE_PORTS'(i);
end
end
//retire_next packet
priority_encoder #(.WIDTH(RETIRE_PORTS))
retire_with_rd_sel_encoder (
.priority_vector (retire_id_uses_rd),
.encoded_result (retire_with_rd_sel)
);
//retire_next packets
assign wb_retire_next = '{
id : retire_ids_next[retire_with_rd_sel],
valid : retire_with_rd_found
};
assign store_retire_next = '{
id : retire_ids_next[retire_with_store_sel],
valid : retire_with_store_found
};
assign wb_retire_next.id = retire_ids_next[retire_with_rd_sel];
assign wb_retire_next.valid = retire_with_rd_found;
always_comb begin
retire_count_next = 0;
for (int i = 0; i < RETIRE_PORTS; i++) begin
@ -346,42 +375,27 @@ module instruction_metadata_and_id_management
end
always_ff @ (posedge clk) begin
wb_retire.valid <= wb_retire_next.valid;
wb_retire.id <= wb_retire_next.id;
wb_retire <= wb_retire_next;
store_retire <= store_retire_next;
retire_count <= gc.writeback_supress ? '0 : retire_count_next;
for (int i = 0; i < RETIRE_PORTS; i++)
retire_port_valid[i] <= retire_port_valid_next[i] & ~gc.writeback_supress;
end
priority_encoder #(.WIDTH(RETIRE_PORTS))
retire_with_store_sel_encoder (
.priority_vector (retire_id_is_store),
.encoded_result (retire_with_store_sel)
);
assign store_retire_next.id = retire_ids_next[retire_with_store_sel];
assign store_retire_next.valid = retire_with_store_found;
always_ff @ (posedge clk) begin
store_retire <= store_retire_next;
end
////////////////////////////////////////////////////
//Outputs
assign pc_id_available = ~inflight_count[LOG2_MAX_IDS];
//Decode
assign decode.id = decode_id;
assign decode.valid = fetched_count_neg[LOG2_MAX_IDS];
assign decode.pc = pc_table[decode_id];
assign decode.instruction = instruction_table[decode_id];
assign decode.fetch_metadata = CONFIG.INCLUDE_M_MODE ? fetch_metadata_table[decode_id] : '{ok : 1, error_code : INST_ACCESS_FAULT};
//Exception Support
generate if (CONFIG.INCLUDE_M_MODE) begin : gen_id_exception_support
assign oldest_pc = pc_table[retire_ids_next[0]];
assign current_exception_unit = exception_unit_table[retire_ids_next[0]];
end endgenerate
localparam fetch_metadata_t ADDR_OK = '{ok : 1, error_code : INST_ADDR_MISSALIGNED};
assign decode = '{
id : decode_id,
valid : fetched_count_neg[LOG2_MAX_IDS],
pc : decode_pc,
instruction : decode_instruction,
fetch_metadata : CONFIG.INCLUDE_M_MODE ? decode_fetch_metadata : ADDR_OK
};
////////////////////////////////////////////////////
//End of Implementation

View file

@ -1,69 +0,0 @@
/*
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
*/
module one_hot_occupancy
#(parameter DEPTH = 4)
(
input logic clk,
input logic rst,
input logic push,
input logic pop,
output logic almost_full,
output logic full,
output logic empty,
output logic almost_empty,
output logic valid
);
logic [DEPTH:0] valid_chain;
//Occupancy Tracking
always_ff @ (posedge clk) begin
if (rst) begin
valid_chain[0] <= 1;
valid_chain[DEPTH:1] <= 0;
end
else begin
case({push,pop})
2'b10 : valid_chain <= {valid_chain[DEPTH-1:0], 1'b0};
2'b01 : valid_chain <= {1'b0, valid_chain[DEPTH:1]};
default : valid_chain <= valid_chain;
endcase
end
end
assign empty = valid_chain[0];
assign almost_empty = valid_chain[1];
assign valid = ~valid_chain[0];
assign full = valid_chain[DEPTH];
assign almost_full = valid_chain[DEPTH-1];
////////////////////////////////////////////////////
//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

View file

@ -1,16 +0,0 @@
module placer_randomizer # (
parameter logic [7:0] PLACER_SEED = 8'h2B
)
(
input logic clk,
input logic [7:0] samples,
output logic result
);
always_ff @(posedge clk) begin
result <= |(samples & PLACER_SEED);
end
endmodule

View file

@ -108,7 +108,7 @@ module register_file
//LUTRAM implementation
//Read in decode stage, writeback groups muxed and output registered per regfile read port
generate for (genvar i = 0; i < CONFIG.NUM_WB_GROUPS; i++) begin : register_file_gen
lutram_1w_mr #(.WIDTH(32), .DEPTH(64), .NUM_READ_PORTS(REGFILE_READ_PORTS))
lutram_1w_mr #(.DATA_TYPE(logic[31:0]), .DEPTH(64), .NUM_READ_PORTS(REGFILE_READ_PORTS))
register_file_bank (
.clk,
.waddr(wb_phys_addr[i]),

View file

@ -32,7 +32,7 @@ module register_free_list
import cva5_types::*;
#(
parameter DATA_WIDTH = 70,
parameter type DATA_TYPE = logic,
parameter FIFO_DEPTH = 4
)
(
@ -45,7 +45,7 @@ module register_free_list
localparam LOG2_FIFO_DEPTH = $clog2(FIFO_DEPTH);
//Force FIFO depth to next power of 2
(* ramstyle = "MLAB, no_rw_check" *) logic [DATA_WIDTH-1:0] lut_ram [(2**LOG2_FIFO_DEPTH)];
(* ramstyle = "MLAB, no_rw_check" *) logic [$bits(DATA_TYPE)-1:0] lut_ram [(2**LOG2_FIFO_DEPTH)];
logic [LOG2_FIFO_DEPTH-1:0] write_index;
logic [LOG2_FIFO_DEPTH-1:0] read_index;
logic [LOG2_FIFO_DEPTH:0] inflight_count;

View file

@ -58,7 +58,7 @@ module renamer
logic [5:0] clear_index;
fifo_interface #(.DATA_WIDTH($bits(phys_addr_t))) free_list ();
fifo_interface #(.DATA_TYPE(phys_addr_t)) free_list ();
logic rename_valid;
logic rollback;
@ -83,7 +83,7 @@ module renamer
////////////////////////////////////////////////////
//Free list FIFO
register_free_list #(.DATA_WIDTH($bits(phys_addr_t)), .FIFO_DEPTH(32)) free_list_fifo (
register_free_list #(.DATA_TYPE(phys_addr_t), .FIFO_DEPTH(32)) free_list_fifo (
.clk (clk),
.rst (rst),
.fifo (free_list),
@ -106,7 +106,7 @@ module renamer
previous_wb_group : spec_table_previous_r.wb_group
};
lutram_1w_1r #(.WIDTH($bits(renamer_metadata_t)), .DEPTH(MAX_IDS))
lutram_1w_1r #(.DATA_TYPE(renamer_metadata_t), .DEPTH(MAX_IDS))
inuse_table (
.clk (clk),
.waddr (issue.id),
@ -168,7 +168,7 @@ module renamer
assign spec_table_read_addr[1+:REGFILE_READ_PORTS] = decode.rs_addr;
lutram_1w_mr #(
.WIDTH($bits(spec_table_t)),
.DATA_TYPE(spec_table_t),
.DEPTH(32),
.NUM_READ_PORTS(REGFILE_READ_PORTS+1)
)

View file

@ -1,47 +0,0 @@
/*
* Copyright © 2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
*/
module shift_counter
import cva5_config::*;
import cva5_types::*;
#(parameter DEPTH = 16)
(
input logic clk,
input logic rst,
input logic start,
output logic done
);
logic [DEPTH-1:0] counter;
////////////////////////////////////////////////////
//Implementation
//TLB_CLEAR state shift reg
always_ff @ (posedge clk) begin
counter[0] <= start;
counter[DEPTH-1:1] <= counter[DEPTH-2:0];
end
assign done = counter[DEPTH-1];
endmodule

View file

@ -91,7 +91,7 @@ module tlb_lut_ram
genvar i;
generate
for (i=0; i<WAYS; i=i+1) begin : lut_rams
lutram_1w_1r #(.WIDTH($bits(tlb_entry_t)), .DEPTH(DEPTH))
lutram_1w_1r #(.DATA_TYPE(tlb_entry_t), .DEPTH(DEPTH))
write_port (
.clk(clk),
.waddr(tlb_addr),

View file

@ -99,17 +99,77 @@ package cva5_config;
int unsigned DEPTH;
} tlb_config_t;
////////////////////////////////////////////////////
//Unit IDs
//To add a new unit update:
// - MAX_NUM_UNITS
// - units_t
// - unit_id_enum_t
//ensuring that the bit index in units_t matches the enum value in unit_id_enum_t
//Additionally, writeback units must be grouped before non-writeback units
localparam MAX_NUM_UNITS = 8;
typedef struct packed {
bit IEC;
bit BR;
//End of Write-Back Units
bit CUSTOM;
bit CSR;
bit DIV;
bit MUL;
bit LS;
bit ALU;
} units_t;
typedef enum bit [$clog2(MAX_NUM_UNITS)-1:0] {
IEC_ID = 7,
BR_ID = 6,
//End of Write-Back Units (insert new writeback units here)
CUSTOM_ID = 5,
CSR_ID = 4,
DIV_ID = 3,
MUL_ID = 2,
LS_ID = 1,
ALU_ID = 0
} unit_id_enum_t;
localparam unit_id_enum_t NON_WRITEBACK_ID = BR_ID;
//WB Group config
// First index is write-back port
// Second index is position within the write-back port (Priority selection, with highest priority for index 0)
// See EXAMPLE_WB_GROUP_CONFIG below for an example of how to specify the configuration
typedef unit_id_enum_t [MAX_NUM_UNITS-1:0][MAX_NUM_UNITS-1:0] wb_group_config_t;
//Convenience function for determining how many writeback units are in each writeback group
function int unsigned get_num_wb_units (input unit_id_enum_t [MAX_NUM_UNITS-1:0] ids);
get_num_wb_units = 0;
for (int i = 0; i < MAX_NUM_UNITS; i++)
if (ids[i] != NON_WRITEBACK_ID)
get_num_wb_units++;
endfunction
//Convenience function for turning the enum-based WB grouping into the units_t bit-vector representation
//used in decode stage to determine the writeback group for the current instruction
function units_t [MAX_NUM_UNITS-1:0] get_wb_units_type_representation(input wb_group_config_t ids);
get_wb_units_type_representation = '{default : '0};
for (int i = 0; i < MAX_NUM_UNITS; i++)
for (int j = 0; j < MAX_NUM_UNITS; j++)
if (ids[i][j] != NON_WRITEBACK_ID)
get_wb_units_type_representation[i][ids[i][j]] = 1;
endfunction
typedef struct packed {
//ISA options
bit INCLUDE_M_MODE;
bit INCLUDE_S_MODE;
bit INCLUDE_U_MODE;
bit INCLUDE_MUL;
bit INCLUDE_DIV;
bit INCLUDE_IFENCE; //local mem operations only
bit INCLUDE_CSRS;
bit INCLUDE_AMO; //cache operations only
bit INCLUDE_CUSTOM;
bit INCLUDE_AMO;
bit INCLUDE_CBO; //Data cache invalidation operations
//Units
units_t INCLUDE_UNIT;
//CSR constants
csr_config_t CSRS;
//Memory Options
@ -141,6 +201,7 @@ package cva5_config;
branch_predictor_config_t BP;
//Writeback Options
int unsigned NUM_WB_GROUPS;
wb_group_config_t WB_GROUP;
} cpu_config_t;
//Function to generate derived cache parameters
@ -153,18 +214,41 @@ package cva5_config;
};
endfunction
////////////////////////////////////////////////////
//Example Config
// ALU requires its own WB port
// LS unit must be the first unit on its writeback port (LS unit does not use ack signal for timing considerations)
// Index in group is the priority order (highest priority for index zero)
// For optimal resource usage, there should be no holes in the write-back unit ordering
// (i.e. if a unit is often not included, either remove from the WB config or place at the end of a writeback group)
localparam wb_group_config_t EXAMPLE_WB_GROUP_CONFIG = '{
0 : '{0: ALU_ID, default : NON_WRITEBACK_ID},
1 : '{0: LS_ID, default : NON_WRITEBACK_ID},
2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID},
default : '{default : NON_WRITEBACK_ID}
};
localparam cpu_config_t EXAMPLE_CONFIG = '{
//ISA options
INCLUDE_M_MODE : 1,
INCLUDE_S_MODE : 1,
INCLUDE_U_MODE : 1,
INCLUDE_MUL : 1,
INCLUDE_DIV : 1,
INCLUDE_S_MODE : 0,
INCLUDE_U_MODE : 0,
INCLUDE_UNIT : '{
ALU : 1,
LS : 1,
MUL : 1,
DIV : 1,
CSR : 1,
CUSTOM : 0,
BR : 1,
IEC : 1
},
INCLUDE_IFENCE : 1,
INCLUDE_CSRS : 1,
INCLUDE_AMO : 0,
INCLUDE_CUSTOM : 0,
INCLUDE_CBO : 0,
//CSR constants
CSRS : '{
MACHINE_IMPLEMENTATION_ID : 0,
@ -173,10 +257,10 @@ package cva5_config;
RESET_MTVEC : 32'h80000100,
NON_STANDARD_OPTIONS : '{
COUNTER_W : 33,
MCYCLE_WRITEABLE : 1,
MINSTR_WRITEABLE : 1,
MCYCLE_WRITEABLE : 0,
MINSTR_WRITEABLE : 0,
MTVEC_WRITEABLE : 1,
INCLUDE_MSCRATCH : 1,
INCLUDE_MSCRATCH : 0,
INCLUDE_MCAUSE : 1,
INCLUDE_MTVAL : 1
}
@ -253,31 +337,8 @@ package cva5_config;
RAS_ENTRIES : 8
},
//Writeback Options
NUM_WB_GROUPS : 3
};
////////////////////////////////////////////////////
//Unit IDs
typedef struct packed {
int unsigned ALU;
int unsigned LS;
int unsigned CSR;
int unsigned MUL;
int unsigned DIV;
int unsigned CUSTOM;
int unsigned BR;
int unsigned IEC;
} unit_id_param_t;
localparam unit_id_param_t EXAMPLE_UNIT_IDS = '{
ALU : 0,
LS : 1,
CSR : 2,
MUL : 3,
DIV : 4,
CUSTOM : 5,
BR : 6,
IEC : 7
NUM_WB_GROUPS : 3,
WB_GROUP : EXAMPLE_WB_GROUP_CONFIG
};
////////////////////////////////////////////////////

View file

@ -107,6 +107,7 @@ package cva5_types;
logic [31:0] addr;
logic load;
logic store;
logic cache_op;
logic [3:0] be;
logic [2:0] fn3;
logic [31:0] data;
@ -117,6 +118,7 @@ package cva5_types;
typedef struct packed {
logic [31:0] addr;
logic [3:0] be;
logic cache_op;
logic [31:0] data;
} sq_entry_t;
@ -141,6 +143,7 @@ package cva5_types;
logic [31:0] addr;
logic load;
logic store;
logic cache_op;
logic [3:0] be;
logic [2:0] fn3;
logic [31:0] data_in;

View file

@ -51,21 +51,6 @@ interface branch_predictor_interface;
endinterface
interface unit_decode_interface;
import cva5_types::*;
import cva5_config::*;
logic [31:0] instruction;
logic issue_stage_ready;
logic unit_needed;
logic uses_rs [REGFILE_READ_PORTS];
logic uses_rd;
modport decode (input unit_needed, uses_rs, uses_rd, output instruction, issue_stage_ready);
modport unit (output unit_needed, uses_rs, uses_rd, input instruction, issue_stage_ready);
endinterface
interface unit_issue_interface;
import cva5_types::*;
@ -79,24 +64,19 @@ interface unit_issue_interface;
modport unit (output ready, input possible_issue, new_request, id);
endinterface
interface unit_writeback_interface;
interface unit_writeback_interface #(parameter type PAYLOAD_TYPE = logic);
import riscv_types::*;
import cva5_types::*;
logic ack;
//Handshaking
logic ack;
logic done;
id_t id;
logic done;
logic [XLEN-1:0] rd;
id_t id;
logic [31:0] rd;
modport unit (
input ack,
output id, done, rd
);
modport wb (
output ack,
input id, done, rd
);
modport unit (input ack, output done, id, rd);
modport wb (output ack, input done, id, rd);
endinterface
interface ras_interface;
@ -129,25 +109,11 @@ interface exception_interface;
modport econtrol (input valid, code, id, tval, output ack);
endinterface
interface csr_exception_interface;
import riscv_types::*;
import cva5_types::*;
logic valid;
exception_code_t code;
logic [31:0] tval;
logic [31:0] exception_pc;
logic [31:0] trap_pc;
modport econtrol (output valid, code, tval, exception_pc, input trap_pc);
modport csr (input valid, code, tval, exception_pc, output trap_pc);
endinterface
interface fifo_interface #(parameter DATA_WIDTH = 42);//#(parameter type data_type = logic[31:0]);
interface fifo_interface #(parameter type DATA_TYPE = logic);
logic push;
logic pop;
logic [DATA_WIDTH-1:0] data_in;
logic [DATA_WIDTH-1:0] data_out;
DATA_TYPE data_in;
DATA_TYPE data_out;
logic valid;
logic full;
logic potential_push;
@ -268,28 +234,6 @@ interface store_queue_interface;
);
endinterface
interface writeback_store_interface;
import riscv_types::*;
import cva5_types::*;
id_t id_needed;
logic possibly_waiting;
logic waiting;
logic ack;
logic id_done;
logic [31:0] data;
modport ls (
input id_done, data,
output id_needed, possibly_waiting ,waiting, ack
);
modport wb (
input id_needed, possibly_waiting, waiting, ack,
output id_done, data
);
endinterface
interface cache_functions_interface #(parameter int TAG_W = 8, parameter int LINE_W = 4, parameter int SUB_LINE_W = 2);
function logic [LINE_W-1:0] xor_mask (int WAY);
@ -372,7 +316,7 @@ interface unsigned_division_interface #(parameter DATA_WIDTH = 32);
modport divider (output remainder, quotient, done, input dividend, dividend_CLZ, divisor, divisor_CLZ, divisor_is_zero, start);
endinterface
interface renamer_interface #(parameter NUM_WB_GROUPS = 2);
interface renamer_interface #(parameter NUM_WB_GROUPS = 3);
import cva5_config::*;
import riscv_types::*;
import cva5_types::*;
@ -398,7 +342,7 @@ interface renamer_interface #(parameter NUM_WB_GROUPS = 2);
);
endinterface
interface register_file_issue_interface #(parameter NUM_WB_GROUPS = 2);
interface register_file_issue_interface #(parameter NUM_WB_GROUPS = 3);
import cva5_config::*;
import riscv_types::*;
import cva5_types::*;

View file

@ -101,6 +101,11 @@ package opcodes;
localparam [31:0] SFENCE_VMA = 32'b0001001??????????000000001110011;
localparam [31:0] WFI = 32'b00010000010100000000000001110011;
//Cache
localparam [31:0] CBO_INVAL = 32'b000000000000?????010000000001111;
localparam [31:0] CBO_CLEAN = 32'b000000000001?????010000000001111;
localparam [31:0] CBO_FLUSH = 32'b000000000010?????010000000001111;
localparam [31:0] CUSTOM = 32'b?????????????????????????1111011;

View file

@ -28,39 +28,36 @@ module writeback
# (
parameter cpu_config_t CONFIG = EXAMPLE_CONFIG,
parameter int unsigned NUM_WB_UNITS = 5
parameter int unsigned NUM_WB_UNITS = 5,
parameter unit_id_enum_t [MAX_NUM_UNITS-1:0] WB_INDEX = '{0: ALU_ID, 1: MUL_ID, 2: DIV_ID, 3: LS_ID, 4: CSR_ID, default: NON_WRITEBACK_ID}
)
(
input logic clk,
input logic rst,
//Unit writeback
unit_writeback_interface.wb unit_wb[NUM_WB_UNITS],
unit_writeback_interface.wb unit_wb[MAX_NUM_UNITS],
//WB output
output wb_packet_t wb_packet
);
//Writeback
logic [NUM_WB_UNITS-1:0] unit_ack;
//aliases for write-back-interface signals
id_t [NUM_WB_UNITS-1:0] unit_instruction_id;
logic [NUM_WB_UNITS-1:0] unit_done;
logic [31:0] unit_rd [NUM_WB_UNITS];
logic [NUM_WB_UNITS-1:0] unit_ack;
logic [XLEN-1:0] unit_rd [NUM_WB_UNITS];
localparam int unsigned LOG2_NUM_WB_UNITS = NUM_WB_UNITS == 1 ? 1 : $clog2(NUM_WB_UNITS);
//Per-ID muxes for commit buffer
localparam int unsigned LOG2_NUM_WB_UNITS = (NUM_WB_UNITS == 1) ? 1 : $clog2(NUM_WB_UNITS);
logic [LOG2_NUM_WB_UNITS-1:0] unit_sel;
genvar i;
////////////////////////////////////////////////////
//Implementation
//Re-assigning interface inputs to array types so that they can be dynamically indexed
generate for (i = 0; i < NUM_WB_UNITS; i++) begin : gen_wb_unit_unpacking
assign unit_instruction_id[i] = unit_wb[i].id;
assign unit_done[i] = unit_wb[i].done;
assign unit_wb[i].ack = unit_ack[i];
assign unit_rd[i] = unit_wb[i].rd;
generate for (genvar i = 0; i < NUM_WB_UNITS; i++) begin : gen_wb_unit_unpacking
assign unit_instruction_id[i] = unit_wb[WB_INDEX[i]].id;
assign unit_done[i] = unit_wb[WB_INDEX[i]].done;
assign unit_rd[i] = unit_wb[WB_INDEX[i]].rd;
assign unit_wb[WB_INDEX[i]].ack = unit_ack[i];
end endgenerate
////////////////////////////////////////////////////
@ -72,11 +69,13 @@ module writeback
unit_done_encoder
(
.priority_vector (unit_done),
.encoded_result (unit_sel[LOG2_NUM_WB_UNITS -1 : 0])
.encoded_result (unit_sel)
);
assign wb_packet.valid = |unit_done;
assign wb_packet.id = unit_instruction_id[unit_sel];
assign wb_packet.data = unit_rd[unit_sel];
assign wb_packet = '{
valid : |unit_done,
id : unit_instruction_id[unit_sel],
data : unit_rd[unit_sel]
};
assign unit_ack = NUM_WB_UNITS'(wb_packet.valid) << unit_sel;

View file

@ -37,10 +37,9 @@ module l1_to_wishbone
localparam MAX_REQUESTS = 32;
fifo_interface #(.DATA_WIDTH($bits(l2_request_t))) request_fifo ();
fifo_interface #(.DATA_WIDTH(32)) data_fifo ();
fifo_interface #(.DATA_TYPE(l2_request_t)) request_fifo ();
fifo_interface #(.DATA_TYPE(logic[31:0])) data_fifo ();
l2_request_t request_in;
l2_request_t request;
logic request_complete;
@ -50,17 +49,17 @@ module l1_to_wishbone
assign cpu.data_full = data_fifo.full;
//Repack input attributes
assign request_in.addr = cpu.addr;
assign request_in.be = cpu.be;
assign request_in.rnw = cpu.rnw;
assign request_in.is_amo = cpu.is_amo;
assign request_in.amo_type_or_burst_size = cpu.amo_type_or_burst_size;
assign request_in.sub_id = cpu.sub_id;
assign request_fifo.data_in = '{
addr : cpu.addr,
be : cpu.be,
rnw : cpu.rnw,
is_amo : cpu.is_amo,
amo_type_or_burst_size : cpu.amo_type_or_burst_size,
sub_id : cpu.sub_id
};
assign request_fifo.push = cpu.request_push;
assign request_fifo.potential_push = cpu.request_push;
assign request_fifo.pop = request_complete;
assign request_fifo.data_in = request_in;
assign request = request_fifo.data_out;
assign data_fifo.push = cpu.wr_data_push;
@ -68,13 +67,13 @@ module l1_to_wishbone
assign data_fifo.pop = wishbone.we & wishbone.ack;
assign data_fifo.data_in = cpu.wr_data;
cva5_fifo #(.DATA_WIDTH($bits(l2_request_t)), .FIFO_DEPTH(MAX_REQUESTS))
cva5_fifo #(.DATA_TYPE(l2_request_t), .FIFO_DEPTH(MAX_REQUESTS))
request_fifo_block (
.clk (clk),
.rst (rst),
.fifo (request_fifo)
);
cva5_fifo #(.DATA_WIDTH(32), .FIFO_DEPTH(MAX_REQUESTS))
cva5_fifo #(.DATA_TYPE(logic[31:0]), .FIFO_DEPTH(MAX_REQUESTS))
data_fifo_block (
.clk (clk),
.rst (rst),

View file

@ -74,17 +74,30 @@ module litex_wrapper
input logic idbus_err
);
localparam wb_group_config_t MINIMAL_WB_GROUP_CONFIG = '{
0 : '{0: ALU_ID, default : NON_WRITEBACK_ID},
1 : '{0: LS_ID, 1: CSR_ID, default : NON_WRITEBACK_ID},
default : '{default : NON_WRITEBACK_ID}
};
localparam cpu_config_t MINIMAL_CONFIG = '{
//ISA options
INCLUDE_M_MODE : 1,
INCLUDE_S_MODE : 0,
INCLUDE_U_MODE : 0,
INCLUDE_MUL : 0,
INCLUDE_DIV : 0,
INCLUDE_UNIT : '{
ALU : 1,
LS : 1,
MUL : 0,
DIV : 0,
CSR : 1,
CUSTOM : 0,
BR : 1,
IEC : 1
},
INCLUDE_IFENCE : 0,
INCLUDE_CSRS : 1,
INCLUDE_AMO : 0,
INCLUDE_CUSTOM : 0,
//CSR constants
CSRS : '{
MACHINE_IMPLEMENTATION_ID : 0,
@ -173,7 +186,15 @@ module litex_wrapper
RAS_ENTRIES : 8
},
//Writeback Options
NUM_WB_GROUPS : 2
NUM_WB_GROUPS : 2,
WB_GROUP : MINIMAL_WB_GROUP_CONFIG
};
localparam wb_group_config_t STANDARD_WB_GROUP_CONFIG = '{
0 : '{0: ALU_ID, default : NON_WRITEBACK_ID},
1 : '{0: LS_ID, default : NON_WRITEBACK_ID},
2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID},
default : '{default : NON_WRITEBACK_ID}
};
localparam cpu_config_t STANDARD_CONFIG = '{
@ -181,12 +202,18 @@ module litex_wrapper
INCLUDE_M_MODE : 1,
INCLUDE_S_MODE : 0,
INCLUDE_U_MODE : 0,
INCLUDE_MUL : 1,
INCLUDE_DIV : 1,
INCLUDE_UNIT : '{
ALU : 1,
LS : 1,
MUL : 1,
DIV : 1,
CSR : 1,
CUSTOM : 0,
BR : 1,
IEC : 1
},
INCLUDE_IFENCE : 0,
INCLUDE_CSRS : 1,
INCLUDE_AMO : 0,
INCLUDE_CUSTOM : 0,
//CSR constants
CSRS : '{
MACHINE_IMPLEMENTATION_ID : 0,
@ -275,7 +302,8 @@ module litex_wrapper
RAS_ENTRIES : 8
},
//Writeback Options
NUM_WB_GROUPS : 3
NUM_WB_GROUPS : 3,
WB_GROUP : STANDARD_WB_GROUP_CONFIG
};
function cpu_config_t config_select (input integer variant);

View file

@ -37,10 +37,9 @@ module l1_to_axi
localparam MAX_REQUESTS = 16;
fifo_interface #(.DATA_WIDTH($bits(l2_request_t))) request_fifo ();
fifo_interface #(.DATA_WIDTH(32)) data_fifo ();
fifo_interface #(.DATA_TYPE(l2_request_t)) request_fifo ();
fifo_interface #(.DATA_TYPE(logic[31:0])) data_fifo ();
l2_request_t request_in;
l2_request_t request;
logic write_request;
@ -58,17 +57,17 @@ module l1_to_axi
assign cpu.data_full = data_fifo.full;
//Repack input attributes
assign request_in.addr = cpu.addr;
assign request_in.be = cpu.be;
assign request_in.rnw = cpu.rnw;
assign request_in.is_amo = cpu.is_amo;
assign request_in.amo_type_or_burst_size = cpu.amo_type_or_burst_size;
assign request_in.sub_id = cpu.sub_id;
assign request_fifo.data_in = '{
addr : cpu.addr,
be : cpu.be,
rnw : cpu.rnw,
is_amo : cpu.is_amo,
amo_type_or_burst_size : cpu.amo_type_or_burst_size,
sub_id : cpu.sub_id
};
assign request_fifo.push = cpu.request_push;
assign request_fifo.potential_push = cpu.request_push;
assign request_fifo.pop = read_pop | write_pop;
assign request_fifo.data_in = request_in;
assign request = request_fifo.data_out;
assign data_fifo.push = cpu.wr_data_push;
@ -76,13 +75,13 @@ module l1_to_axi
assign data_fifo.pop = write_pop;
assign data_fifo.data_in = cpu.wr_data;
cva5_fifo #(.DATA_WIDTH($bits(l2_request_t)), .FIFO_DEPTH(MAX_REQUESTS))
cva5_fifo #(.DATA_TYPE(l2_request_t), .FIFO_DEPTH(MAX_REQUESTS))
request_fifo_block (
.clk (clk),
.rst (rst),
.fifo (request_fifo)
);
cva5_fifo #(.DATA_WIDTH(32), .FIFO_DEPTH(MAX_REQUESTS))
cva5_fifo #(.DATA_TYPE(logic[31:0]), .FIFO_DEPTH(MAX_REQUESTS))
data_fifo_block (
.clk (clk),
.rst (rst),

View file

@ -0,0 +1,146 @@
/*
* Copyright © 2023 Eric Matthews
*
* 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>
*/
package nexys_config;
import cva5_config::*;
localparam wb_group_config_t NEXYS_WB_GROUP_CONFIG = '{
0 : '{0: ALU_ID, default : NON_WRITEBACK_ID},
1 : '{0: LS_ID, default : NON_WRITEBACK_ID},
2 : '{0: MUL_ID, 1: DIV_ID, 2: CSR_ID, 3: CUSTOM_ID, default : NON_WRITEBACK_ID},
default : '{default : NON_WRITEBACK_ID}
};
localparam cpu_config_t NEXYS_CONFIG = '{
//ISA options
INCLUDE_M_MODE : 1,
INCLUDE_S_MODE : 0,
INCLUDE_U_MODE : 0,
INCLUDE_UNIT : '{
ALU : 1,
LS : 1,
MUL : 1,
DIV : 1,
CSR : 1,
CUSTOM : 0,
BR : 1,
IEC : 1
},
INCLUDE_IFENCE : 0,
INCLUDE_AMO : 0,
INCLUDE_CBO : 0,
//CSR constants
CSRS : '{
MACHINE_IMPLEMENTATION_ID : 0,
CPU_ID : 0,
RESET_VEC : 32'h80000000,
RESET_MTVEC : 32'h80000000,
NON_STANDARD_OPTIONS : '{
COUNTER_W : 33,
MCYCLE_WRITEABLE : 0,
MINSTR_WRITEABLE : 0,
MTVEC_WRITEABLE : 1,
INCLUDE_MSCRATCH : 0,
INCLUDE_MCAUSE : 1,
INCLUDE_MTVAL : 1
}
},
//Memory Options
SQ_DEPTH : 8,
INCLUDE_FORWARDING_TO_STORES : 1,
INCLUDE_ICACHE : 1,
ICACHE_ADDR : '{
L : 32'h80000000,
H : 32'h87FFFFFF
},
ICACHE : '{
LINES : 256,
LINE_W : 8,
WAYS : 2,
USE_EXTERNAL_INVALIDATIONS : 0,
USE_NON_CACHEABLE : 0,
NON_CACHEABLE : '{
L : 32'h88000000,
H : 32'h8FFFFFFF
}
},
ITLB : '{
WAYS : 2,
DEPTH : 64
},
INCLUDE_DCACHE : 1,
DCACHE_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
DCACHE : '{
LINES : 512,
LINE_W : 8,
WAYS : 1,
USE_EXTERNAL_INVALIDATIONS : 0,
USE_NON_CACHEABLE : 1,
NON_CACHEABLE : '{
L : 32'h88000000,
H : 32'h8FFFFFFF
}
},
DTLB : '{
WAYS : 2,
DEPTH : 64
},
INCLUDE_ILOCAL_MEM : 0,
ILOCAL_MEM_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
INCLUDE_DLOCAL_MEM : 0,
DLOCAL_MEM_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
INCLUDE_IBUS : 0,
IBUS_ADDR : '{
L : 32'h00000000,
H : 32'hFFFFFFFF
},
INCLUDE_PERIPHERAL_BUS : 0,
PERIPHERAL_BUS_ADDR : '{
L : 32'h00000000,
H : 32'hFFFFFFFF
},
PERIPHERAL_BUS_TYPE : AXI_BUS,
//Branch Predictor Options
INCLUDE_BRANCH_PREDICTOR : 1,
BP : '{
WAYS : 2,
ENTRIES : 512,
RAS_ENTRIES : 8
},
//Writeback Options
NUM_WB_GROUPS : 3,
WB_GROUP : NEXYS_WB_GROUP_CONFIG
};
endpackage

View file

@ -26,9 +26,10 @@ module cva5_sim
import l2_config_and_types::*;
import riscv_types::*;
import cva5_types::*;
import nexys_config::*;
# (
parameter MEMORY_FILE = "/home/ematthew/Research/RISCV/software/riscv-tools/riscv-tests/benchmarks/dhrystone.riscv.hw_init" //change this to appropriate location "/home/ematthew/Downloads/dhrystone.riscv.sim_init"
parameter MEMORY_FILE = "<path to executable>.hw_init" //change this to appropriate location
)
(
input logic clk,
@ -101,108 +102,6 @@ module cva5_sim
output logic store_queue_empty
);
localparam cpu_config_t NEXYS_CONFIG = '{
//ISA options
INCLUDE_M_MODE : 1,
INCLUDE_S_MODE : 0,
INCLUDE_U_MODE : 0,
INCLUDE_MUL : 1,
INCLUDE_DIV : 1,
INCLUDE_IFENCE : 0,
INCLUDE_CSRS : 1,
INCLUDE_AMO : 0,
INCLUDE_CUSTOM : 0,
//CSR constants
CSRS : '{
MACHINE_IMPLEMENTATION_ID : 0,
CPU_ID : 0,
RESET_VEC : 32'h80000000,
RESET_MTVEC : 32'h80000000,
NON_STANDARD_OPTIONS : '{
COUNTER_W : 33,
MCYCLE_WRITEABLE : 0,
MINSTR_WRITEABLE : 0,
MTVEC_WRITEABLE : 1,
INCLUDE_MSCRATCH : 0,
INCLUDE_MCAUSE : 1,
INCLUDE_MTVAL : 1
}
},
//Memory Options
SQ_DEPTH : 8,
INCLUDE_FORWARDING_TO_STORES : 1,
INCLUDE_ICACHE : 1,
ICACHE_ADDR : '{
L : 32'h80000000,
H : 32'h87FFFFFF
},
ICACHE : '{
LINES : 256,
LINE_W : 8,
WAYS : 2,
USE_EXTERNAL_INVALIDATIONS : 0,
USE_NON_CACHEABLE : 0,
NON_CACHEABLE : '{
L : 32'h88000000,
H : 32'h8FFFFFFF
}
},
ITLB : '{
WAYS : 2,
DEPTH : 64
},
INCLUDE_DCACHE : 1,
DCACHE_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
DCACHE : '{
LINES : 512,
LINE_W : 8,
WAYS : 1,
USE_EXTERNAL_INVALIDATIONS : 0,
USE_NON_CACHEABLE : 1,
NON_CACHEABLE : '{
L : 32'h88000000,
H : 32'h8FFFFFFF
}
},
DTLB : '{
WAYS : 2,
DEPTH : 64
},
INCLUDE_ILOCAL_MEM : 0,
ILOCAL_MEM_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
INCLUDE_DLOCAL_MEM : 0,
DLOCAL_MEM_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
INCLUDE_IBUS : 0,
IBUS_ADDR : '{
L : 32'h00000000,
H : 32'hFFFFFFFF
},
INCLUDE_PERIPHERAL_BUS : 0,
PERIPHERAL_BUS_ADDR : '{
L : 32'h88000000,
H : 32'h8FFFFFFF
},
PERIPHERAL_BUS_TYPE : AXI_BUS,
//Branch Predictor Options
INCLUDE_BRANCH_PREDICTOR : 1,
BP : '{
WAYS : 2,
ENTRIES : 512,
RAS_ENTRIES : 8
},
//Writeback Options
NUM_WB_GROUPS : 3
};
parameter SCRATCH_MEM_KB = 128;
parameter MEM_LINES = (SCRATCH_MEM_KB*1024)/4;
parameter UART_ADDR = 32'h88001000;
@ -348,7 +247,7 @@ module cva5_sim
//Issue rd_addr to unit mem
//Used for determining what outputs an operand stall is waiting on
logic [`ISSUE_P.NUM_UNITS-1:0] rd_addr_table [32];
logic [MAX_NUM_UNITS-1:0] rd_addr_table [32];
always_ff @(posedge clk) begin
if (cpu.instruction_issued_with_rd)
@ -367,6 +266,11 @@ module cva5_sim
assign darb_stall = cpu.l1_request[L1_DCACHE_ID].request & ~cpu.l1_request[L1_DCACHE_ID].ack;
end endgenerate
logic [MAX_NUM_UNITS-1:0] unit_ready;
generate for (i=0; i<MAX_NUM_UNITS; i++)
assign unit_ready[i] = cpu.unit_issue[i].ready;
endgenerate
always_comb begin
stats = '{default: '0};
//Fetch
@ -387,9 +291,9 @@ module cva5_sim
base_no_instruction_stall = ~`ISSUE_P.issue.stage_valid | cpu.gc.fetch_flush;
base_no_id_sub_stall = (`METADATA_P.post_issue_count == MAX_IDS);
base_flush_sub_stall = cpu.gc.fetch_flush;
base_unit_busy_stall = `ISSUE_P.issue.stage_valid & ~|`ISSUE_P.issue_ready;
base_operands_stall = `ISSUE_P.issue.stage_valid & ~`ISSUE_P.operands_ready;
base_hold_stall = `ISSUE_P.issue.stage_valid & (cpu.gc.issue_hold | `ISSUE_P.pre_issue_exception_pending);
base_unit_busy_stall = `ISSUE_P.issue.stage_valid & ~|(`ISSUE_P.unit_needed_issue_stage & unit_ready);
base_operands_stall = `ISSUE_P.issue.stage_valid & ~(&`ISSUE_P.operand_ready);
base_hold_stall = `ISSUE_P.issue.stage_valid & `ISSUE_P.issue_hold;
stall_source_count = 4'(base_no_instruction_stall) + 4'(base_unit_busy_stall) + 4'(base_operands_stall) + 4'(base_hold_stall);
single_source_issue_stall = (stall_source_count == 1);
@ -404,15 +308,15 @@ module cva5_sim
stats[ISSUE_MULTI_SOURCE_STAT] = (base_no_instruction_stall | base_unit_busy_stall | base_operands_stall | base_hold_stall) & ~single_source_issue_stall;
//Misc Issue stats
stats[ISSUE_OPERAND_STALL_FOR_BRANCH_STAT] = stats[ISSUE_OPERANDS_NOT_READY_STAT] & `ISSUE_P.unit_needed_issue_stage[`ISSUE_P.UNIT_IDS.BR];
stats[ISSUE_STORE_WITH_FORWARDED_DATA_STAT] = `ISSUE_P.issue_to[`ISSUE_P.UNIT_IDS.LS] & `LS_P.is_store_r & `LS_P.rs2_inuse;
stats[ISSUE_DIVIDER_RESULT_REUSE_STAT] = `ISSUE_P.issue_to[`ISSUE_P.UNIT_IDS.DIV] & `DIV_P.div_op_reuse;
stats[ISSUE_OPERAND_STALL_FOR_BRANCH_STAT] = stats[ISSUE_OPERANDS_NOT_READY_STAT] & `ISSUE_P.unit_needed_issue_stage[BR_ID];
stats[ISSUE_STORE_WITH_FORWARDED_DATA_STAT] = `ISSUE_P.issue_to[LS_ID] & `LS_P.issue_attr.is_store & `LS_P.rs2_inuse;
stats[ISSUE_DIVIDER_RESULT_REUSE_STAT] = `ISSUE_P.issue_to[DIV_ID] & `DIV_P.div_op_reuse;
//Issue Stall Source
for (int i = 0; i < REGFILE_READ_PORTS; i++) begin
stats[ISSUE_OPERAND_STALL_ON_LOAD_STAT] |= `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][`ISSUE_P.UNIT_IDS.LS] & `ISSUE_P.rs_conflict[i] ;
stats[ISSUE_OPERAND_STALL_ON_MULTIPLY_STAT] |= EXAMPLE_CONFIG.INCLUDE_MUL & `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][`ISSUE_P.UNIT_IDS.MUL] & `ISSUE_P.rs_conflict[i] ;
stats[ISSUE_OPERAND_STALL_ON_DIVIDE_STAT] |= EXAMPLE_CONFIG.INCLUDE_DIV & `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][`ISSUE_P.UNIT_IDS.DIV] & `ISSUE_P.rs_conflict[i] ;
stats[ISSUE_OPERAND_STALL_ON_LOAD_STAT] |= `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][LS_ID] & ~`ISSUE_P.operand_ready[i] ;
stats[ISSUE_OPERAND_STALL_ON_MULTIPLY_STAT] |= EXAMPLE_CONFIG.INCLUDE_UNIT.MUL & `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][MUL_ID] & ~`ISSUE_P.operand_ready[i] ;
stats[ISSUE_OPERAND_STALL_ON_DIVIDE_STAT] |= EXAMPLE_CONFIG.INCLUDE_UNIT.DIV & `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][DIV_ID] & ~`ISSUE_P.operand_ready[i] ;
end
//LS Stats
@ -477,8 +381,8 @@ module cva5_sim
assign NUM_RETIRE_PORTS = RETIRE_PORTS;
generate for (genvar i = 0; i < RETIRE_PORTS; i++) begin
assign retire_ports_pc[i] = cpu.id_block.pc_table[cpu.retire_ids[i]];
assign retire_ports_instruction[i] = cpu.id_block.instruction_table[cpu.retire_ids[i]];
assign retire_ports_pc[i] = cpu.id_block.pc_table.ram[cpu.retire_ids[i]];
assign retire_ports_instruction[i] = cpu.id_block.instruction_table.ram[cpu.retire_ids[i]];
assign retire_ports_valid[i] = cpu.retire_port_valid[i];
end endgenerate

View file

@ -27,6 +27,7 @@ module nexys_wrapper
import cva5_config::*;
import cva5_types::*;
import l2_config_and_types::*;
import nexys_config::*;
(
input logic clk,
@ -75,108 +76,6 @@ module nexys_wrapper
input logic [5:0] m_axi_bid
);
localparam cpu_config_t NEXYS_CONFIG = '{
//ISA options
INCLUDE_M_MODE : 1,
INCLUDE_S_MODE : 0,
INCLUDE_U_MODE : 0,
INCLUDE_MUL : 1,
INCLUDE_DIV : 1,
INCLUDE_IFENCE : 0,
INCLUDE_CSRS : 1,
INCLUDE_AMO : 0,
INCLUDE_CUSTOM : 0,
//CSR constants
CSRS : '{
MACHINE_IMPLEMENTATION_ID : 0,
CPU_ID : 0,
RESET_VEC : 32'h80000000,
RESET_MTVEC : 32'h80000000,
NON_STANDARD_OPTIONS : '{
COUNTER_W : 33,
MCYCLE_WRITEABLE : 0,
MINSTR_WRITEABLE : 0,
MTVEC_WRITEABLE : 1,
INCLUDE_MSCRATCH : 0,
INCLUDE_MCAUSE : 1,
INCLUDE_MTVAL : 1
}
},
//Memory Options
SQ_DEPTH : 8,
INCLUDE_FORWARDING_TO_STORES : 1,
INCLUDE_ICACHE : 1,
ICACHE_ADDR : '{
L : 32'h80000000,
H : 32'h87FFFFFF
},
ICACHE : '{
LINES : 256,
LINE_W : 8,
WAYS : 2,
USE_EXTERNAL_INVALIDATIONS : 0,
USE_NON_CACHEABLE : 0,
NON_CACHEABLE : '{
L : 32'h88000000,
H : 32'h8FFFFFFF
}
},
ITLB : '{
WAYS : 2,
DEPTH : 64
},
INCLUDE_DCACHE : 1,
DCACHE_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
DCACHE : '{
LINES : 512,
LINE_W : 8,
WAYS : 1,
USE_EXTERNAL_INVALIDATIONS : 0,
USE_NON_CACHEABLE : 1,
NON_CACHEABLE : '{
L : 32'h88000000,
H : 32'h8FFFFFFF
}
},
DTLB : '{
WAYS : 2,
DEPTH : 64
},
INCLUDE_ILOCAL_MEM : 0,
ILOCAL_MEM_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
INCLUDE_DLOCAL_MEM : 0,
DLOCAL_MEM_ADDR : '{
L : 32'h80000000,
H : 32'h8FFFFFFF
},
INCLUDE_IBUS : 0,
IBUS_ADDR : '{
L : 32'h00000000,
H : 32'hFFFFFFFF
},
INCLUDE_PERIPHERAL_BUS : 0,
PERIPHERAL_BUS_ADDR : '{
L : 32'h00000000,
H : 32'hFFFFFFFF
},
PERIPHERAL_BUS_TYPE : AXI_BUS,
//Branch Predictor Options
INCLUDE_BRANCH_PREDICTOR : 1,
BP : '{
WAYS : 2,
ENTRIES : 512,
RAS_ENTRIES : 8
},
//Writeback Options
NUM_WB_GROUPS : 3
};
//Unused outputs
local_memory_interface instruction_bram ();
local_memory_interface data_bram ();

View file

@ -25,14 +25,15 @@ if {[string equal [get_filesets -quiet sources_1] ""]} {
}
#import sources needed for blackbox packaging
import_files -norecurse $sources_dir/examples/nexys/nexys_config.sv
import_files -norecurse $sources_dir/examples/nexys/nexys_wrapper.sv
import_files -norecurse $sources_dir/l2_arbiter/l2_external_interfaces.sv
import_files -norecurse $sources_dir/local_memory/local_memory_interface.sv
import_files -norecurse $sources_dir/core/external_interfaces.sv
import_files -norecurse $sources_dir/core/cva5_config.sv
import_files -norecurse $sources_dir/core/riscv_types.sv
import_files -norecurse $sources_dir/core/cva5_types.sv
import_files -norecurse $sources_dir/core/csr_types.sv
import_files -norecurse $sources_dir/core/types_and_interfaces/external_interfaces.sv
import_files -norecurse $sources_dir/core/types_and_interfaces/cva5_config.sv
import_files -norecurse $sources_dir/core/types_and_interfaces/riscv_types.sv
import_files -norecurse $sources_dir/core/types_and_interfaces/cva5_types.sv
import_files -norecurse $sources_dir/core/types_and_interfaces/csr_types.sv
import_files -norecurse $sources_dir/l2_arbiter/l2_config_and_types.sv
# Set IP repository paths

View file

@ -243,7 +243,7 @@ module cva5_wrapper (
endgenerate
//arm proc(.*);
byte_en_BRAM #(MEM_LINES, "/home/ematthew/Research/RISCV/software2/riscv-tools/riscv-tests/benchmarks/fft.riscv.hw_init", 1) inst_data_ram (
byte_en_bram #(MEM_LINES, "/home/ematthew/Research/RISCV/software2/riscv-tools/riscv-tests/benchmarks/fft.riscv.hw_init", 1) inst_data_ram (
.clk(clk),
.addr_a(instruction_bram.addr[$clog2(MEM_LINES)- 1:0]),
.en_a(instruction_bram.en),

View file

@ -37,17 +37,17 @@ module l2_arbiter
l2_arbitration_interface arb();
//FIFO interfaces
fifo_interface #(.DATA_WIDTH($bits(l2_request_t))) input_fifos [L2_NUM_PORTS-1:0]();
fifo_interface #(.DATA_WIDTH(32)) input_data_fifos [L2_NUM_PORTS-1:0]();
fifo_interface #(.DATA_WIDTH(30)) inv_response_fifos [L2_NUM_PORTS-1:0]();
fifo_interface #(.DATA_WIDTH(32 + L2_SUB_ID_W)) returndata_fifos [L2_NUM_PORTS-1:0]();
fifo_interface #(.DATA_TYPE(l2_request_t)) input_fifos [L2_NUM_PORTS-1:0]();
fifo_interface #(.DATA_TYPE(logic[31:0])) input_data_fifos [L2_NUM_PORTS-1:0]();
fifo_interface #(.DATA_TYPE(logic[29:0])) inv_response_fifos [L2_NUM_PORTS-1:0]();
fifo_interface #(.DATA_TYPE(l2_return_data_t)) returndata_fifos [L2_NUM_PORTS-1:0]();
fifo_interface #(.DATA_WIDTH($bits(l2_mem_request_t))) mem_addr_fifo();
fifo_interface #(.DATA_WIDTH(32)) mem_data_fifo();
fifo_interface #(.DATA_TYPE(l2_mem_request_t)) mem_addr_fifo();
fifo_interface #(.DATA_TYPE(logic[31:0])) mem_data_fifo();
fifo_interface #(.DATA_WIDTH($bits(l2_data_attributes_t))) data_attributes();
fifo_interface #(.DATA_WIDTH(32 + L2_ID_W)) mem_returndata_fifo();
fifo_interface #(.DATA_TYPE(l2_data_attributes_t)) data_attributes();
fifo_interface #(.DATA_TYPE(l2_mem_return_data_t)) mem_returndata_fifo();
l2_mem_request_t mem_addr_fifo_data_out;
l2_request_t requests_in[L2_NUM_PORTS-1:0];
@ -105,7 +105,7 @@ module l2_arbiter
assign request[i].request_full = input_fifos[i].full;
//FIFO instantiation
cva5_fifo #(.DATA_WIDTH($bits(l2_request_t)), .FIFO_DEPTH(L2_INPUT_FIFO_DEPTHS)) input_fifo (.*, .fifo(input_fifos[i]));
cva5_fifo #(.DATA_TYPE(l2_request_t), .FIFO_DEPTH(L2_INPUT_FIFO_DEPTHS)) input_fifo (.*, .fifo(input_fifos[i]));
//Arbiter FIFO side
assign requests[i] = input_fifos[i].data_out;
@ -126,7 +126,7 @@ module l2_arbiter
assign request[i].data_full = input_data_fifos[i].full;
//FIFO instantiation
cva5_fifo #(.DATA_WIDTH(32), .FIFO_DEPTH(L2_INPUT_FIFO_DEPTHS)) input_data_fifo (.*, .fifo(input_data_fifos[i]));
cva5_fifo #(.DATA_TYPE(logic[31:0]), .FIFO_DEPTH(L2_INPUT_FIFO_DEPTHS)) input_data_fifo (.*, .fifo(input_data_fifos[i]));
//Arbiter FIFO side
assign input_data_fifos[i].pop = (data_attributes.valid && (current_attr.id == i) && ~mem_data_fifo.full);
@ -169,7 +169,7 @@ module l2_arbiter
assign mem.amo_type_or_burst_size = mem_addr_fifo_data_out.amo_type_or_burst_size;
assign mem.id = mem_addr_fifo_data_out.id;
cva5_fifo #(.DATA_WIDTH($bits(l2_mem_request_t)), .FIFO_DEPTH(L2_MEM_ADDR_FIFO_DEPTH)) input_fifo (.*, .fifo(mem_addr_fifo));
cva5_fifo #(.DATA_TYPE(l2_mem_request_t), .FIFO_DEPTH(L2_MEM_ADDR_FIFO_DEPTH)) input_fifo (.*, .fifo(mem_addr_fifo));
/*************************************
@ -226,7 +226,7 @@ module l2_arbiter
assign request[i].inv_valid = inv_response_fifos[i].valid;
//FIFO instantiation
cva5_fifo #(.DATA_WIDTH(30), .FIFO_DEPTH(L2_INVALIDATION_FIFO_DEPTHS)) inv_response_fifo (.*, .fifo(inv_response_fifos[i]));
cva5_fifo #(.DATA_TYPE(logic[29:0]), .FIFO_DEPTH(L2_INVALIDATION_FIFO_DEPTHS)) inv_response_fifo (.*, .fifo(inv_response_fifos[i]));
//Arbiter side
assign inv_response_fifos[i].push = reserv_valid & reserv_store & ~reserv_id_v[i];
assign inv_response_fifos[i].potential_push = reserv_valid & reserv_store & ~reserv_id_v[i];
@ -245,7 +245,7 @@ module l2_arbiter
assign data_attributes.push = reserv_valid & ~reserv_request.rnw & ~mem.abort_request;
assign data_attributes.potential_push = reserv_valid & ~reserv_request.rnw & ~mem.abort_request;
cva5_fifo #(.DATA_WIDTH($bits(l2_data_attributes_t)), .FIFO_DEPTH(L2_DATA_ATTRIBUTES_FIFO_DEPTH)) data_attributes_fifo (.*, .fifo(data_attributes));
cva5_fifo #(.DATA_TYPE(l2_data_attributes_t), .FIFO_DEPTH(L2_DATA_ATTRIBUTES_FIFO_DEPTH)) data_attributes_fifo (.*, .fifo(data_attributes));
assign data_attributes.pop = write_done;
assign current_attr = data_attributes.data_out;
@ -261,7 +261,7 @@ module l2_arbiter
assign write_done = data_attributes.valid & ~mem_data_fifo.full & (burst_count == current_attr.burst_size);
cva5_fifo #(.DATA_WIDTH($bits(32)), .FIFO_DEPTH(L2_MEM_ADDR_FIFO_DEPTH)) mem_data (.*, .fifo(mem_data_fifo));
cva5_fifo #(.DATA_TYPE(logic[31:0]), .FIFO_DEPTH(L2_MEM_ADDR_FIFO_DEPTH)) mem_data (.*, .fifo(mem_data_fifo));
assign mem_data_fifo.push = data_attributes.valid & ~mem_data_fifo.full & ~current_attr.abort_request;
assign mem_data_fifo.potential_push = data_attributes.valid & ~mem_data_fifo.full & ~current_attr.abort_request;
@ -276,7 +276,7 @@ module l2_arbiter
/*************************************
* Read response
*************************************/
cva5_fifo # (.DATA_WIDTH(32 + L2_ID_W), .FIFO_DEPTH(L2_MEM_ADDR_FIFO_DEPTH)) mem_returndata (.*, .fifo(mem_returndata_fifo));
cva5_fifo # (.DATA_TYPE(l2_mem_return_data_t), .FIFO_DEPTH(L2_MEM_ADDR_FIFO_DEPTH)) mem_returndata (.*, .fifo(mem_returndata_fifo));
assign mem_returndata_fifo.push = mem.rd_data_valid;
assign mem_returndata_fifo.potential_push = mem.rd_data_valid;
@ -298,7 +298,7 @@ module l2_arbiter
assign request[i].rd_data_valid = returndata_fifos[i].valid;
//FIFO instantiation
cva5_fifo #(.DATA_WIDTH(32 + L2_SUB_ID_W), .FIFO_DEPTH(L2_READ_RETURN_FIFO_DEPTHS)) returndata_fifo (.*, .fifo(returndata_fifos[i]));
cva5_fifo #(.DATA_TYPE(l2_return_data_t), .FIFO_DEPTH(L2_READ_RETURN_FIFO_DEPTHS)) returndata_fifo (.*, .fifo(returndata_fifos[i]));
//Arbiter side
assign returndata_fifos[i].push = return_push[i];
assign returndata_fifos[i].potential_push = return_push[i];

View file

@ -36,7 +36,7 @@ module local_mem
localparam LINES = (RAM_SIZE/4)*1024; //RAM width is 32-bits, so for RAM_SIZE in KB, divide by 4 and multiply by 1024.
byte_en_BRAM #(LINES, preload_file, USE_PRELOAD_FILE) inst_data_ram (
byte_en_bram #(LINES, preload_file, USE_PRELOAD_FILE) inst_data_ram (
.clk(clk),
.addr_a(portA.addr[$clog2(LINES)- 1:0]),
.en_a(portA.en),

View file

@ -117,14 +117,14 @@ if {[string equal [get_filesets -quiet sources_1] ""]} {
#import_files -fileset [get_filesets sources_1] $origin_dir/l2_arbiter
#import_files -fileset [get_filesets sources_1] $origin_dir/local_memory
import_files -norecurse $origin_dir/../../core/xilinx/cva5_wrapper_xilinx.sv -force
import_files -norecurse $origin_dir/../../core/common_components/vendor_support/xilinx/cva5_wrapper_xilinx.sv -force
import_files -norecurse $origin_dir/../../l2_arbiter/l2_external_interfaces.sv -force
import_files -norecurse $origin_dir/../../local_memory/local_memory_interface.sv -force
import_files -norecurse $origin_dir/../../core/external_interfaces.sv -force
import_files -norecurse $origin_dir/../../core/cva5_config.sv -force
import_files -norecurse $origin_dir/../../core/riscv_types.sv -force
import_files -norecurse $origin_dir/../../core/cva5_types.sv -force
import_files -norecurse $origin_dir/../../core/csr_types.sv -force
import_files -norecurse $origin_dir/../../core/types_and_interfaces/external_interfaces.sv -force
import_files -norecurse $origin_dir/../../core/types_and_interfaces/cva5_config.sv -force
import_files -norecurse $origin_dir/../../core/types_and_interfaces/riscv_types.sv -force
import_files -norecurse $origin_dir/../../core/types_and_interfaces/cva5_types.sv -force
import_files -norecurse $origin_dir/../../core/types_and_interfaces/csr_types.sv -force
import_files -norecurse $origin_dir/../../l2_arbiter/l2_config_and_types.sv -force
# Set IP repository paths

View file

@ -483,7 +483,7 @@ module cva5_sim
//Issue phys_rd to unit mem
//Used for determining what outputs an operand stall is waiting on
logic [`ISSUE_P.NUM_UNITS-1:0] rd_addr_table [32];
logic [MAX_NUM_UNITS-1:0] rd_addr_table [32];
always_ff @(posedge clk) begin
if (cpu.instruction_issued_with_rd)
@ -502,6 +502,11 @@ module cva5_sim
assign darb_stall = cpu.l1_request[L1_DCACHE_ID].request & ~cpu.l1_request[L1_DCACHE_ID].ack;
end endgenerate
logic [MAX_NUM_UNITS-1:0] unit_ready;
generate for (i=0; i<MAX_NUM_UNITS; i++)
assign unit_ready[i] = cpu.unit_issue[i].ready;
endgenerate
always_comb begin
stats = '{default: '0};
//Fetch
@ -522,9 +527,9 @@ module cva5_sim
base_no_instruction_stall = ~`ISSUE_P.issue.stage_valid | cpu.gc.fetch_flush;
base_no_id_sub_stall = (`METADATA_P.post_issue_count == MAX_IDS);
base_flush_sub_stall = cpu.gc.fetch_flush;
base_unit_busy_stall = `ISSUE_P.issue.stage_valid & ~|`ISSUE_P.issue_ready;
base_operands_stall = `ISSUE_P.issue.stage_valid & ~`ISSUE_P.operands_ready;
base_hold_stall = `ISSUE_P.issue.stage_valid & (cpu.gc.issue_hold | `ISSUE_P.pre_issue_exception_pending);
base_unit_busy_stall = `ISSUE_P.issue.stage_valid & ~|(`ISSUE_P.unit_needed_issue_stage & unit_ready);
base_operands_stall = `ISSUE_P.issue.stage_valid & ~(&`ISSUE_P.operand_ready);
base_hold_stall = `ISSUE_P.issue.stage_valid & `ISSUE_P.issue_hold;
stall_source_count = 4'(base_no_instruction_stall) + 4'(base_unit_busy_stall) + 4'(base_operands_stall) + 4'(base_hold_stall);
single_source_issue_stall = (stall_source_count == 1);
@ -539,15 +544,15 @@ module cva5_sim
stats[ISSUE_MULTI_SOURCE_STAT] = (base_no_instruction_stall | base_unit_busy_stall | base_operands_stall | base_hold_stall) & ~single_source_issue_stall;
//Misc Issue stats
stats[ISSUE_OPERAND_STALL_FOR_BRANCH_STAT] = stats[ISSUE_OPERANDS_NOT_READY_STAT] & `ISSUE_P.unit_needed_issue_stage[`ISSUE_P.UNIT_IDS.BR];
stats[ISSUE_STORE_WITH_FORWARDED_DATA_STAT] = `ISSUE_P.issue_to[`ISSUE_P.UNIT_IDS.LS] & `LS_P.is_store_r & `LS_P.rs2_inuse;
stats[ISSUE_DIVIDER_RESULT_REUSE_STAT] = `ISSUE_P.issue_to[`ISSUE_P.UNIT_IDS.DIV] & `DIV_P.div_op_reuse;
stats[ISSUE_OPERAND_STALL_FOR_BRANCH_STAT] = stats[ISSUE_OPERANDS_NOT_READY_STAT] & `ISSUE_P.unit_needed_issue_stage[BR_ID];
stats[ISSUE_STORE_WITH_FORWARDED_DATA_STAT] = `ISSUE_P.issue_to[LS_ID] & `LS_P.issue_attr.is_store & `LS_P.rs2_inuse;
stats[ISSUE_DIVIDER_RESULT_REUSE_STAT] = `ISSUE_P.issue_to[DIV_ID] & `DIV_P.div_op_reuse;
//Issue Stall Source
for (int i = 0; i < REGFILE_READ_PORTS; i++) begin
stats[ISSUE_OPERAND_STALL_ON_LOAD_STAT] |= `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][`ISSUE_P.UNIT_IDS.LS] & `ISSUE_P.rs_conflict[i] ;
stats[ISSUE_OPERAND_STALL_ON_MULTIPLY_STAT] |= EXAMPLE_CONFIG.INCLUDE_MUL & `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][`ISSUE_P.UNIT_IDS.MUL] & `ISSUE_P.rs_conflict[i] ;
stats[ISSUE_OPERAND_STALL_ON_DIVIDE_STAT] |= EXAMPLE_CONFIG.INCLUDE_DIV & `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][`ISSUE_P.UNIT_IDS.DIV] & `ISSUE_P.rs_conflict[i] ;
stats[ISSUE_OPERAND_STALL_ON_LOAD_STAT] |= `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][LS_ID] & ~`ISSUE_P.operand_ready[i] ;
stats[ISSUE_OPERAND_STALL_ON_MULTIPLY_STAT] |= EXAMPLE_CONFIG.INCLUDE_UNIT.MUL & `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][MUL_ID] & ~`ISSUE_P.operand_ready[i] ;
stats[ISSUE_OPERAND_STALL_ON_DIVIDE_STAT] |= EXAMPLE_CONFIG.INCLUDE_UNIT.DIV & `ISSUE_P.issue.stage_valid & rd_addr_table[`ISSUE_P.issue_rs_addr[i]][DIV_ID] & ~`ISSUE_P.operand_ready[i] ;
end
//LS Stats
@ -612,8 +617,8 @@ module cva5_sim
assign NUM_RETIRE_PORTS = RETIRE_PORTS;
generate for (genvar i = 0; i < RETIRE_PORTS; i++) begin
assign retire_ports_pc[i] = cpu.id_block.pc_table[cpu.retire_ids[i]];
assign retire_ports_instruction[i] = cpu.id_block.instruction_table[cpu.retire_ids[i]];
assign retire_ports_pc[i] = cpu.id_block.pc_table.ram[cpu.retire_ids[i]];
assign retire_ports_instruction[i] = cpu.id_block.instruction_table.ram[cpu.retire_ids[i]];
assign retire_ports_valid[i] = cpu.retire_port_valid[i];
end endgenerate

View file

@ -1,98 +1,89 @@
core/cva5_config.sv
core/riscv_types.sv
core/csr_types.sv
core/cva5_types.sv
core/opcodes.sv
core/types_and_interfaces/cva5_config.sv
core/types_and_interfaces/riscv_types.sv
core/types_and_interfaces/csr_types.sv
core/types_and_interfaces/cva5_types.sv
core/types_and_interfaces/opcodes.sv
l2_arbiter/l2_config_and_types.sv
l2_arbiter/l2_config_and_types.sv
l2_arbiter/l2_interfaces.sv
l2_arbiter/l2_external_interfaces.sv
local_memory/local_memory_interface.sv
local_memory/local_memory_interface.sv
local_memory/local_mem.sv
core/internal_interfaces.sv
core/external_interfaces.sv
core/types_and_interfaces/internal_interfaces.sv
core/types_and_interfaces/external_interfaces.sv
core/lutrams/lutram_1w_1r.sv
core/lutrams/lutram_1w_mr.sv
core/common_components/lutram_1w_1r.sv
core/common_components/lutram_1w_mr.sv
core/common_components/dual_port_bram.sv
core/common_components/set_clr_reg_with_rst.sv
core/common_components/one_hot_to_integer.sv
core/common_components/cycler.sv
core/common_components/lfsr.sv
core/common_components/cva5_fifo.sv
core/common_components/priority_encoder.sv
core/common_components/toggle_memory.sv
core/common_components/toggle_memory_set.sv
core/set_clr_reg_with_rst.sv
core/one_hot_occupancy.sv
core/binary_occupancy.sv
core/one_hot_to_integer.sv
core/cycler.sv
core/lfsr.sv
core/cva5_fifo.sv
core/shift_counter.sv
core/priority_encoder.sv
core/common_components/vendor_support/intel/intel_byte_enable_ram.sv
core/common_components/vendor_support/xilinx/xilinx_byte_enable_ram.sv
core/common_components/byte_en_bram.sv
core/toggle_memory.sv
core/toggle_memory_set.sv
core/execution_units/csr_unit.sv
core/execution_units/gc_unit.sv
core/intel/intel_byte_enable_ram.sv
core/xilinx/xilinx_byte_enable_ram.sv
core/byte_en_BRAM.sv
core/execution_units/branch_comparator.sv
core/execution_units/branch_unit.sv
core/csr_unit.sv
core/gc_unit.sv
core/execution_units/barrel_shifter.sv
core/execution_units/alu_unit.sv
core/branch_comparator.sv
core/branch_unit.sv
core/memory_sub_units/local_mem_sub_unit.sv
core/memory_sub_units/axi_master.sv
core/memory_sub_units/avalon_master.sv
core/memory_sub_units/wishbone_master.sv
core/barrel_shifter.sv
core/alu_unit.sv
core/execution_units/load_store_unit/dcache_tag_banks.sv
core/execution_units/load_store_unit/amo_alu.sv
core/execution_units/load_store_unit/dcache.sv
core/execution_units/load_store_unit/addr_hash.sv
core/execution_units/load_store_unit/store_queue.sv
core/execution_units/load_store_unit/load_store_queue.sv
core/execution_units/load_store_unit/load_store_unit.sv
core/local_mem_sub_unit.sv
core/axi_master.sv
core/avalon_master.sv
core/wishbone_master.sv
core/execution_units/mul_unit.sv
core/execution_units/custom_unit.sv
core/tag_bank.sv
core/dcache_tag_banks.sv
core/amo_alu.sv
core/dcache.sv
core/addr_hash.sv
core/store_queue.sv
core/load_store_queue.sv
core/load_store_unit.sv
core/common_components/clz.sv
core/execution_units/div_core.sv
core/execution_units/div_unit.sv
core/icache_tag_banks.sv
core/icache.sv
core/fetch_stage/ras.sv
core/fetch_stage/branch_predictor.sv
core/fetch_stage/icache_tag_banks.sv
core/fetch_stage/icache.sv
core/fetch_stage/fetch.sv
core/clz.sv
core/div_core.sv
core/div_unit.sv
core/instruction_metadata_and_id_management.sv
core/tlb_lut_ram.sv
core/mmu.sv
core/tlb_lut_ram.sv
core/mmu.sv
core/mul_unit.sv
core/custom_unit.sv
core/ras.sv
core/branch_predictor_ram.sv
core/branch_predictor.sv
core/fetch.sv
core/illegal_instruction_checker.sv
core/decode_and_issue.sv
core/register_free_list.sv
core/renamer.sv
core/register_file.sv
core/writeback.sv
core/l1_arbiter.sv
l2_arbiter/l2_fifo.sv
l2_arbiter/l2_reservation_logic.sv
l2_arbiter/l2_round_robin.sv
l2_arbiter/l2_arbiter.sv
core/axi_to_arb.sv
core/instruction_metadata_and_id_management.sv
core/l1_arbiter.sv
core/cva5.sv
l2_arbiter/axi_to_arb.sv
core/cva5.sv

View file

@ -93,7 +93,7 @@ $(CVA5_SIM): $(CVA5_HW_SRCS) $(CVA5_SIM_SRCS)
-o cva5-sim \
$(VERILATOR_LINT_IGNORE) $(VERILATOR_CFLAGS) \
$(CVA5_SIM_SRCS) \
$(CVA5_HW_SRCS) $(CVA5_DIR)/test_benches/sim_stats.sv $(CVA5_DIR)/examples/nexys/l1_to_axi.sv $(CVA5_DIR)/examples/nexys/nexys_sim.sv --top-module cva5_sim
$(CVA5_HW_SRCS) $(CVA5_DIR)/test_benches/sim_stats.sv $(CVA5_DIR)/examples/nexys/nexys_config.sv $(CVA5_DIR)/examples/nexys/l1_to_axi.sv $(CVA5_DIR)/examples/nexys/nexys_sim.sv --top-module cva5_sim
$(MAKE) -C $(CVA5_SIM_DIR) -f Vcva5_sim.mk
.PHONY: clean-cva5-sim