mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 21:27:10 -04:00
Cvvdev/dev/formating4 (#920)
Several format cleanings: - split load_store_unit.sv to create lsu_bypass.sv - add several "begin" and "end"
This commit is contained in:
parent
767c465cfb
commit
a9c7b4f1e1
13 changed files with 153 additions and 122 deletions
|
@ -105,6 +105,7 @@ ${CVA6_REPO_DIR}/core/issue_read_operands.sv
|
|||
${CVA6_REPO_DIR}/core/issue_stage.sv
|
||||
${CVA6_REPO_DIR}/core/load_unit.sv
|
||||
${CVA6_REPO_DIR}/core/load_store_unit.sv
|
||||
${CVA6_REPO_DIR}/core/lsu_bypass.sv
|
||||
${CVA6_REPO_DIR}/core/mult.sv
|
||||
${CVA6_REPO_DIR}/core/multiplier.sv
|
||||
${CVA6_REPO_DIR}/core/serdiv.sv
|
||||
|
|
|
@ -105,6 +105,7 @@ ${CVA6_REPO_DIR}/core/issue_read_operands.sv
|
|||
${CVA6_REPO_DIR}/core/issue_stage.sv
|
||||
${CVA6_REPO_DIR}/core/load_unit.sv
|
||||
${CVA6_REPO_DIR}/core/load_store_unit.sv
|
||||
${CVA6_REPO_DIR}/core/lsu_bypass.sv
|
||||
${CVA6_REPO_DIR}/core/mult.sv
|
||||
${CVA6_REPO_DIR}/core/multiplier.sv
|
||||
${CVA6_REPO_DIR}/core/serdiv.sv
|
||||
|
|
|
@ -105,6 +105,7 @@ ${CVA6_REPO_DIR}/core/issue_read_operands.sv
|
|||
${CVA6_REPO_DIR}/core/issue_stage.sv
|
||||
${CVA6_REPO_DIR}/core/load_unit.sv
|
||||
${CVA6_REPO_DIR}/core/load_store_unit.sv
|
||||
${CVA6_REPO_DIR}/core/lsu_bypass.sv
|
||||
${CVA6_REPO_DIR}/core/mult.sv
|
||||
${CVA6_REPO_DIR}/core/multiplier.sv
|
||||
${CVA6_REPO_DIR}/core/serdiv.sv
|
||||
|
|
|
@ -105,6 +105,7 @@ ${CVA6_REPO_DIR}/core/issue_read_operands.sv
|
|||
${CVA6_REPO_DIR}/core/issue_stage.sv
|
||||
${CVA6_REPO_DIR}/core/load_unit.sv
|
||||
${CVA6_REPO_DIR}/core/load_store_unit.sv
|
||||
${CVA6_REPO_DIR}/core/lsu_bypass.sv
|
||||
${CVA6_REPO_DIR}/core/mult.sv
|
||||
${CVA6_REPO_DIR}/core/multiplier.sv
|
||||
${CVA6_REPO_DIR}/core/serdiv.sv
|
||||
|
|
|
@ -112,6 +112,7 @@ ${CVA6_REPO_DIR}/core/issue_read_operands.sv
|
|||
${CVA6_REPO_DIR}/core/issue_stage.sv
|
||||
${CVA6_REPO_DIR}/core/load_unit.sv
|
||||
${CVA6_REPO_DIR}/core/load_store_unit.sv
|
||||
${CVA6_REPO_DIR}/core/lsu_bypass.sv
|
||||
${CVA6_REPO_DIR}/core/mult.sv
|
||||
${CVA6_REPO_DIR}/core/multiplier.sv
|
||||
${CVA6_REPO_DIR}/core/serdiv.sv
|
||||
|
|
|
@ -1180,10 +1180,11 @@ module csr_regfile import ariane_pkg::*; #(
|
|||
for(int i = 0; i < 16; i++) begin
|
||||
if(i < NrPMPEntries) begin
|
||||
// We only support >=8-byte granularity, NA4 is disabled
|
||||
if(pmpcfg_d[i].addr_mode != riscv::NA4 && !(pmpcfg_d[i].access_type.r == '0 && pmpcfg_d[i].access_type.w == '1))
|
||||
if(pmpcfg_d[i].addr_mode != riscv::NA4 && !(pmpcfg_d[i].access_type.r == '0 && pmpcfg_d[i].access_type.w == '1)) begin
|
||||
pmpcfg_q[i] <= pmpcfg_d[i];
|
||||
else
|
||||
end else begin
|
||||
pmpcfg_q[i] <= pmpcfg_q[i];
|
||||
end
|
||||
pmpaddr_q[i] <= pmpaddr_d[i];
|
||||
end else begin
|
||||
pmpcfg_q[i] <= '0;
|
||||
|
|
|
@ -927,7 +927,7 @@ module cva6 import ariane_pkg::*; #(
|
|||
//pragma translate_on
|
||||
|
||||
`ifdef RVFI_TRACE
|
||||
always_comb
|
||||
always_comb begin
|
||||
for (int i = 0; i < NR_COMMIT_PORTS; i++) begin
|
||||
logic exception, mem_exception;
|
||||
exception = commit_instr_id_commit[i].valid && ex_commit.valid;
|
||||
|
@ -958,6 +958,7 @@ module cva6 import ariane_pkg::*; #(
|
|||
rvfi_o[i].rd_wdata = ariane_pkg::is_rd_fpr(commit_instr_id_commit[i].op) == 0 ? wdata_commit_id[i] : commit_instr_id_commit[i].result;
|
||||
rvfi_o[i].pc_rdata = commit_instr_id_commit[i].pc;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
endmodule // ariane
|
||||
|
|
|
@ -129,7 +129,7 @@ module frontend import ariane_pkg::*; #(
|
|||
// the prediction we saved from the previous fetch
|
||||
assign bht_prediction_shifted[0] = (serving_unaligned) ? bht_q : bht_prediction[addr[0][1]];
|
||||
assign btb_prediction_shifted[0] = (serving_unaligned) ? btb_q : btb_prediction[addr[0][1]];
|
||||
|
||||
|
||||
if (ariane_pkg::RVC) begin : gen_btb_prediction_shifted
|
||||
// for all other predictions we can use the generated address to index
|
||||
// into the branch prediction data structures
|
||||
|
@ -138,7 +138,7 @@ module frontend import ariane_pkg::*; #(
|
|||
assign btb_prediction_shifted[i] = btb_prediction[addr[i][$clog2(INSTR_PER_FETCH):1]];
|
||||
end
|
||||
end;
|
||||
|
||||
|
||||
// for the return address stack it doens't matter as we have the
|
||||
// address of the call/return already
|
||||
logic bp_valid;
|
||||
|
@ -361,7 +361,9 @@ module frontend import ariane_pkg::*; #(
|
|||
icache_ex_valid_q <= ariane_pkg::FE_INSTR_PAGE_FAULT;
|
||||
end else if (icache_dreq_i.ex.cause == riscv::INSTR_ACCESS_FAULT) begin
|
||||
icache_ex_valid_q <= ariane_pkg::FE_INSTR_ACCESS_FAULT;
|
||||
end else icache_ex_valid_q <= ariane_pkg::FE_NONE;
|
||||
end else begin
|
||||
icache_ex_valid_q <= ariane_pkg::FE_NONE;
|
||||
end
|
||||
// save the uppermost prediction
|
||||
btb_q <= btb_prediction[INSTR_PER_FETCH-1];
|
||||
bht_q <= bht_prediction[INSTR_PER_FETCH-1];
|
||||
|
|
|
@ -40,11 +40,12 @@ module id_stage (
|
|||
input logic tsr_i
|
||||
);
|
||||
// ID/ISSUE register stage
|
||||
struct packed {
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
ariane_pkg::scoreboard_entry_t sbe;
|
||||
logic is_ctrl_flow;
|
||||
} issue_n, issue_q;
|
||||
} issue_struct_t;
|
||||
issue_struct_t issue_n, issue_q;
|
||||
|
||||
logic is_control_flow_instr;
|
||||
ariane_pkg::scoreboard_entry_t decoded_instruction;
|
||||
|
|
|
@ -212,11 +212,12 @@ module issue_read_operands import ariane_pkg::*; #(
|
|||
operand_b_n = operand_b_regfile;
|
||||
// immediates are the third operands in the store case
|
||||
// for FP operations, the imm field can also be the third operand from the regfile
|
||||
if (NR_RGPR_PORTS == 3)
|
||||
if (NR_RGPR_PORTS == 3) begin
|
||||
imm_n = is_imm_fpr(issue_instr_i.op) ? {{riscv::XLEN-FLEN{1'b0}}, operand_c_regfile} :
|
||||
issue_instr_i.op == OFFLOAD ? operand_c_regfile : issue_instr_i.result;
|
||||
else
|
||||
end else begin
|
||||
imm_n = is_imm_fpr(issue_instr_i.op) ? {{riscv::XLEN-FLEN{1'b0}}, operand_c_regfile} : issue_instr_i.result;
|
||||
end
|
||||
trans_id_n = issue_instr_i.trans_id;
|
||||
fu_n = issue_instr_i.fu;
|
||||
operator_n = issue_instr_i.op;
|
||||
|
@ -276,12 +277,15 @@ module issue_read_operands import ariane_pkg::*; #(
|
|||
// we do not want to issue this instruction
|
||||
if (!issue_instr_i.ex.valid && issue_instr_valid_i && issue_ack_o) begin
|
||||
case (issue_instr_i.fu)
|
||||
ALU:
|
||||
ALU: begin
|
||||
alu_valid_q <= 1'b1;
|
||||
CTRL_FLOW:
|
||||
end
|
||||
CTRL_FLOW: begin
|
||||
branch_valid_q <= 1'b1;
|
||||
MULT:
|
||||
end
|
||||
MULT: begin
|
||||
mult_valid_q <= 1'b1;
|
||||
end
|
||||
FPU : begin
|
||||
fpu_valid_q <= 1'b1;
|
||||
fpu_fmt_q <= orig_instr.rftype.fmt; // fmt bits from instruction
|
||||
|
@ -292,10 +296,12 @@ module issue_read_operands import ariane_pkg::*; #(
|
|||
fpu_fmt_q <= orig_instr.rvftype.vfmt; // vfmt bits from instruction
|
||||
fpu_rm_q <= {2'b0, orig_instr.rvftype.repl}; // repl bit from instruction
|
||||
end
|
||||
LOAD, STORE:
|
||||
LOAD, STORE: begin
|
||||
lsu_valid_q <= 1'b1;
|
||||
CSR:
|
||||
end
|
||||
CSR: begin
|
||||
csr_valid_q <= 1'b1;
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
@ -443,7 +449,7 @@ module issue_read_operands import ariane_pkg::*; #(
|
|||
.raddr_i ( fp_raddr_pack ),
|
||||
.rdata_o ( fprdata ),
|
||||
.waddr_i ( waddr_pack ),
|
||||
.wdata_i ( wdata_pack ),
|
||||
.wdata_i ( fp_wdata_pack ),
|
||||
.we_i ( we_fpr_i ),
|
||||
.*
|
||||
);
|
||||
|
|
|
@ -462,107 +462,3 @@ module load_store_unit import ariane_pkg::*; #(
|
|||
|
||||
endmodule
|
||||
|
||||
// ------------------
|
||||
// LSU Control
|
||||
// ------------------
|
||||
// The LSU consists of two independent block which share a common address translation block.
|
||||
// The one block is the load unit, the other one is the store unit. They will signal their readiness
|
||||
// with separate signals. If they are not ready the LSU control should keep the last applied signals stable.
|
||||
// Furthermore it can be the case that another request for one of the two store units arrives in which case
|
||||
// the LSU control should sample it and store it for later application to the units. It does so, by storing it in a
|
||||
// two element FIFO. This is necessary as we only know very late in the cycle whether the load/store will succeed (address check,
|
||||
// TLB hit mainly). So we better unconditionally allow another request to arrive and store this request in case we need to.
|
||||
module lsu_bypass import ariane_pkg::*; (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic flush_i,
|
||||
|
||||
input lsu_ctrl_t lsu_req_i,
|
||||
input logic lsu_req_valid_i,
|
||||
input logic pop_ld_i,
|
||||
input logic pop_st_i,
|
||||
|
||||
output lsu_ctrl_t lsu_ctrl_o,
|
||||
output logic ready_o
|
||||
);
|
||||
|
||||
lsu_ctrl_t [1:0] mem_n, mem_q;
|
||||
logic read_pointer_n, read_pointer_q;
|
||||
logic write_pointer_n, write_pointer_q;
|
||||
logic [1:0] status_cnt_n, status_cnt_q;
|
||||
|
||||
logic empty;
|
||||
assign empty = (status_cnt_q == 0);
|
||||
assign ready_o = empty;
|
||||
|
||||
always_comb begin
|
||||
automatic logic [1:0] status_cnt;
|
||||
automatic logic write_pointer;
|
||||
automatic logic read_pointer;
|
||||
|
||||
status_cnt = status_cnt_q;
|
||||
write_pointer = write_pointer_q;
|
||||
read_pointer = read_pointer_q;
|
||||
|
||||
mem_n = mem_q;
|
||||
// we've got a valid LSU request
|
||||
if (lsu_req_valid_i) begin
|
||||
mem_n[write_pointer_q] = lsu_req_i;
|
||||
write_pointer++;
|
||||
status_cnt++;
|
||||
end
|
||||
|
||||
if (pop_ld_i) begin
|
||||
// invalidate the result
|
||||
mem_n[read_pointer_q].valid = 1'b0;
|
||||
read_pointer++;
|
||||
status_cnt--;
|
||||
end
|
||||
|
||||
if (pop_st_i) begin
|
||||
// invalidate the result
|
||||
mem_n[read_pointer_q].valid = 1'b0;
|
||||
read_pointer++;
|
||||
status_cnt--;
|
||||
end
|
||||
|
||||
if (pop_st_i && pop_ld_i)
|
||||
mem_n = '0;
|
||||
|
||||
if (flush_i) begin
|
||||
status_cnt = '0;
|
||||
write_pointer = '0;
|
||||
read_pointer = '0;
|
||||
mem_n = '0;
|
||||
end
|
||||
// default assignments
|
||||
read_pointer_n = read_pointer;
|
||||
write_pointer_n = write_pointer;
|
||||
status_cnt_n = status_cnt;
|
||||
end
|
||||
|
||||
// output assignment
|
||||
always_comb begin : output_assignments
|
||||
if (empty) begin
|
||||
lsu_ctrl_o = lsu_req_i;
|
||||
end else begin
|
||||
lsu_ctrl_o = mem_q[read_pointer_q];
|
||||
end
|
||||
end
|
||||
|
||||
// registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
mem_q <= '0;
|
||||
status_cnt_q <= '0;
|
||||
write_pointer_q <= '0;
|
||||
read_pointer_q <= '0;
|
||||
end else begin
|
||||
mem_q <= mem_n;
|
||||
status_cnt_q <= status_cnt_n;
|
||||
write_pointer_q <= write_pointer_n;
|
||||
read_pointer_q <= read_pointer_n;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
|
119
core/lsu_bypass.sv
Normal file
119
core/lsu_bypass.sv
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this 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.
|
||||
//
|
||||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 19.04.2017
|
||||
// Description: Load Store Unit, handles address calculation and memory interface signals
|
||||
|
||||
|
||||
// ------------------
|
||||
// LSU Control
|
||||
// ------------------
|
||||
// The LSU consists of two independent block which share a common address translation block.
|
||||
// The one block is the load unit, the other one is the store unit. They will signal their readiness
|
||||
// with separate signals. If they are not ready the LSU control should keep the last applied signals stable.
|
||||
// Furthermore it can be the case that another request for one of the two store units arrives in which case
|
||||
// the LSU control should sample it and store it for later application to the units. It does so, by storing it in a
|
||||
// two element FIFO. This is necessary as we only know very late in the cycle whether the load/store will succeed (address check,
|
||||
// TLB hit mainly). So we better unconditionally allow another request to arrive and store this request in case we need to.
|
||||
module lsu_bypass import ariane_pkg::*; (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic flush_i,
|
||||
|
||||
input lsu_ctrl_t lsu_req_i,
|
||||
input logic lsu_req_valid_i,
|
||||
input logic pop_ld_i,
|
||||
input logic pop_st_i,
|
||||
|
||||
output lsu_ctrl_t lsu_ctrl_o,
|
||||
output logic ready_o
|
||||
);
|
||||
|
||||
lsu_ctrl_t [1:0] mem_n, mem_q;
|
||||
logic read_pointer_n, read_pointer_q;
|
||||
logic write_pointer_n, write_pointer_q;
|
||||
logic [1:0] status_cnt_n, status_cnt_q;
|
||||
|
||||
logic empty;
|
||||
assign empty = (status_cnt_q == 0);
|
||||
assign ready_o = empty;
|
||||
|
||||
always_comb begin
|
||||
automatic logic [1:0] status_cnt;
|
||||
automatic logic write_pointer;
|
||||
automatic logic read_pointer;
|
||||
|
||||
status_cnt = status_cnt_q;
|
||||
write_pointer = write_pointer_q;
|
||||
read_pointer = read_pointer_q;
|
||||
|
||||
mem_n = mem_q;
|
||||
// we've got a valid LSU request
|
||||
if (lsu_req_valid_i) begin
|
||||
mem_n[write_pointer_q] = lsu_req_i;
|
||||
write_pointer++;
|
||||
status_cnt++;
|
||||
end
|
||||
|
||||
if (pop_ld_i) begin
|
||||
// invalidate the result
|
||||
mem_n[read_pointer_q].valid = 1'b0;
|
||||
read_pointer++;
|
||||
status_cnt--;
|
||||
end
|
||||
|
||||
if (pop_st_i) begin
|
||||
// invalidate the result
|
||||
mem_n[read_pointer_q].valid = 1'b0;
|
||||
read_pointer++;
|
||||
status_cnt--;
|
||||
end
|
||||
|
||||
if (pop_st_i && pop_ld_i)
|
||||
mem_n = '0;
|
||||
|
||||
if (flush_i) begin
|
||||
status_cnt = '0;
|
||||
write_pointer = '0;
|
||||
read_pointer = '0;
|
||||
mem_n = '0;
|
||||
end
|
||||
// default assignments
|
||||
read_pointer_n = read_pointer;
|
||||
write_pointer_n = write_pointer;
|
||||
status_cnt_n = status_cnt;
|
||||
end
|
||||
|
||||
// output assignment
|
||||
always_comb begin : output_assignments
|
||||
if (empty) begin
|
||||
lsu_ctrl_o = lsu_req_i;
|
||||
end else begin
|
||||
lsu_ctrl_o = mem_q[read_pointer_q];
|
||||
end
|
||||
end
|
||||
|
||||
// registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
mem_q <= '0;
|
||||
status_cnt_q <= '0;
|
||||
write_pointer_q <= '0;
|
||||
read_pointer_q <= '0;
|
||||
end else begin
|
||||
mem_q <= mem_n;
|
||||
status_cnt_q <= status_cnt_n;
|
||||
write_pointer_q <= write_pointer_n;
|
||||
read_pointer_q <= read_pointer_n;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -69,9 +69,9 @@ module re_name import ariane_pkg::*; (
|
|||
issue_instr_o.rs2 = { ENABLE_RENAME & name_bit_rs2, issue_instr_i.rs2[4:0] };
|
||||
|
||||
// re-name the third operand in imm if it's actually an operand
|
||||
if (is_imm_fpr(issue_instr_i.op))
|
||||
if (is_imm_fpr(issue_instr_i.op)) begin
|
||||
issue_instr_o.result = { ENABLE_RENAME & name_bit_rs3, issue_instr_i.result[4:0]};
|
||||
|
||||
end
|
||||
// re-name the destination register
|
||||
issue_instr_o.rd = { ENABLE_RENAME & name_bit_rd, issue_instr_i.rd[4:0] };
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue