mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-23 21:47:15 -04:00
commit
041d5c7809
79 changed files with 1298 additions and 1906 deletions
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
|
||||
|
||||
module byte_en_BRAM
|
||||
module byte_en_bram
|
||||
|
||||
import cva5_config::*;
|
||||
import cva5_types::*;
|
|
@ -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),
|
47
core/tag_bank.sv → core/common_components/dual_port_bram.sv
Executable file → Normal file
47
core/tag_bank.sv → core/common_components/dual_port_bram.sv
Executable file → Normal 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
|
|
@ -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
|
|
@ -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),
|
|
@ -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)
|
||||
)
|
184
core/cva5.sv
184
core/cva5.sv
|
@ -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
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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 (
|
|
@ -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
|
|
@ -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)),
|
|
@ -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]),
|
|
@ -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,
|
|
@ -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),
|
|
@ -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
|
||||
};
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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),
|
|
@ -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
|
|
@ -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),
|
|
@ -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;
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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]),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
|
|
@ -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
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////
|
|
@ -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;
|
|
@ -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::*;
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
146
examples/nexys/nexys_config.sv
Normal file
146
examples/nexys/nexys_config.sv
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue