mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 05:07:21 -04:00
👕 Resolving lint warnings, fix issue #21
This commit is contained in:
parent
74d7810a7d
commit
764beb2af5
13 changed files with 156 additions and 128 deletions
|
@ -42,7 +42,7 @@ module fifo #(
|
|||
// actual memory
|
||||
dtype [DEPTH-1:0] mem_n, mem_q;
|
||||
|
||||
assign full_o = (status_cnt_q == DEPTH-1);
|
||||
assign full_o = (status_cnt_q == DEPTH);
|
||||
assign empty_o = (status_cnt_q == 0);
|
||||
assign single_element_o = (status_cnt_q == 1);
|
||||
// read and write queue logic
|
||||
|
|
|
@ -55,7 +55,7 @@ module id_stage #(
|
|||
|
||||
|
||||
logic full_o;
|
||||
logic [31:0][$bits(fu_t)-1:0] rd_clobber_o;
|
||||
fu_t [31:0] rd_clobber_o;
|
||||
logic [4:0] rs1_i;
|
||||
logic [63:0] rs1_o;
|
||||
logic rs1_valid_o;
|
||||
|
|
|
@ -28,7 +28,7 @@ module issue_read_operands (
|
|||
input logic [63:0] rs2_i,
|
||||
input logic rs2_valid_i,
|
||||
// get clobber input
|
||||
input logic [31:0][$bits(fu_t)-1:0] rd_clobber_i,
|
||||
input fu_t [31:0] rd_clobber_i,
|
||||
// To FU, just single issue for now
|
||||
output fu_op operator_o,
|
||||
output logic [63:0] operand_a_o,
|
||||
|
|
155
src/lsu.sv
155
src/lsu.sv
|
@ -63,7 +63,6 @@ module lsu #(
|
|||
// byte enable based on operation to perform
|
||||
// data is misaligned
|
||||
logic data_misaligned;
|
||||
assign lsu_valid_o = 1'b0;
|
||||
|
||||
enum logic [3:0] { IDLE, STORE, LOAD_WAIT_TRANSLATION, LOAD_WAIT_GNT, LOAD_WAIT_RVALID } CS, NS;
|
||||
|
||||
|
@ -195,7 +194,7 @@ module lsu #(
|
|||
// LSU Control
|
||||
// ------------------
|
||||
// is the operation a load or store or nothing of relevance for the LSU
|
||||
enum logic [1:0] { NONE, LD, ST } op;
|
||||
enum logic [1:0] { NONE, LD_OP, ST_OP } op;
|
||||
|
||||
always_comb begin : lsu_control
|
||||
// default assignment
|
||||
|
@ -213,7 +212,9 @@ module lsu #(
|
|||
// as a default we won't take the operands from the internal
|
||||
// registers
|
||||
get_from_register = 1'b0;
|
||||
|
||||
// LSU result is valid
|
||||
// we need to give the valid result even to stores
|
||||
lsu_valid_o = 1'b0;
|
||||
unique case (CS)
|
||||
// we can freely accept new request
|
||||
IDLE: begin
|
||||
|
@ -222,7 +223,7 @@ module lsu #(
|
|||
// 2. stores can be placed in the store buffer if it is empty
|
||||
// in any case we need to do address translation beforehand
|
||||
// LOAD
|
||||
if (op == LD & lsu_valid_i) begin
|
||||
if (op == LD_OP & lsu_valid_i) begin
|
||||
translation_req = 1'b1;
|
||||
// we can never handle a load in a single cycle
|
||||
// but at least on a tlb hit we can output it to the memory
|
||||
|
@ -246,7 +247,7 @@ module lsu #(
|
|||
lsu_ready_o = 1'b0;
|
||||
|
||||
// STORE
|
||||
end else if (op == ST & lsu_valid_i) begin
|
||||
end else if (op == ST_OP & lsu_valid_i) begin
|
||||
translation_req = 1'b1;
|
||||
// we can handle this store in this cycle if
|
||||
// a. the storebuffer is not full
|
||||
|
@ -254,7 +255,8 @@ module lsu #(
|
|||
if (st_ready & translation_valid) begin
|
||||
NS = IDLE;
|
||||
// and commit to the store buffer
|
||||
st_valid = 1'b1;
|
||||
st_valid = 1'b1;
|
||||
lsu_valid_o = 1'b1;
|
||||
// make a dummy writeback so we
|
||||
// tell the scoreboard that we processed the instruction accordingly
|
||||
|
||||
|
@ -278,6 +280,8 @@ module lsu #(
|
|||
st_valid = 1'b1;
|
||||
// go back to the IDLE state
|
||||
NS = IDLE;
|
||||
// and tell the scoreboard that the result is valid
|
||||
lsu_valid_o = 1'b1;
|
||||
end else begin // we can't accept a new request and stay in the store state
|
||||
stall = 1'b1;
|
||||
end
|
||||
|
@ -331,12 +335,14 @@ module lsu #(
|
|||
lsu_trans_id_o = trans_id_q;
|
||||
// we got a rvalid so we can accept a new store/load request
|
||||
lsu_ready_o = 1'b1;
|
||||
// the result is valid if we got the rvalid
|
||||
lsu_valid_o = 1'b1;
|
||||
// did we get a new request?
|
||||
|
||||
// essentially the same part as in IDLE but we can't accept a new store
|
||||
// as the store could immediately be performed and we would collide on the
|
||||
// trans id part (e.g.: a structural hazard)
|
||||
if (op == LD & lsu_valid_i) begin
|
||||
if (op == LD_OP & lsu_valid_i) begin
|
||||
translation_req = 1'b1;
|
||||
// we can never handle a load in a single cycle
|
||||
// but at least on a tlb hit we can output it to the memory
|
||||
|
@ -357,7 +363,7 @@ module lsu #(
|
|||
NS = LOAD_WAIT_TRANSLATION;
|
||||
end
|
||||
// STORE
|
||||
end else if (op == ST & lsu_valid_i) begin
|
||||
end else if (op == ST_OP & lsu_valid_i) begin
|
||||
NS = STORE;
|
||||
end else begin
|
||||
NS = IDLE;
|
||||
|
@ -378,9 +384,9 @@ module lsu #(
|
|||
always_comb begin : which_op
|
||||
unique case (operator_i)
|
||||
// all loads go here
|
||||
LD, LW, LWU, LH, LHU, LB, LBU: op = LD;
|
||||
LD, LW, LWU, LH, LHU, LB, LBU: op = LD_OP;
|
||||
// all stores go here
|
||||
SD, SW, SH, SB, SBU: op = ST;
|
||||
SD, SW, SH, SB, SBU: op = ST_OP;
|
||||
// not relevant for the lsu
|
||||
default: op = NONE;
|
||||
endcase
|
||||
|
@ -479,31 +485,17 @@ module lsu #(
|
|||
|
||||
// double words
|
||||
always_comb begin : sign_extend_double_word
|
||||
case (vaddr[2:0])
|
||||
default: rdata_d_ext = rdata[63:0];
|
||||
// this is for misaligned accesse only
|
||||
// 3'b001: rdata_d_ext = {data_rdata_i[7:0], rdata_q[63:8]};
|
||||
// 3'b010: rdata_d_ext = {data_rdata_i[15:0], rdata_q[63:16]};
|
||||
// 3'b011: rdata_d_ext = {data_rdata_i[23:0], rdata_q[63:24]};
|
||||
// 3'b100: rdata_d_ext = {data_rdata_i[31:0], rdata_q[63:32]};
|
||||
// 3'b101: rdata_d_ext = {data_rdata_i[39:0], rdata_q[63:40]};
|
||||
// 3'b110: rdata_d_ext = {data_rdata_i[47:0], rdata_q[63:48]};
|
||||
// 3'b111: rdata_d_ext = {data_rdata_i[55:0], rdata_q[63:56]};
|
||||
endcase
|
||||
rdata_d_ext = rdata[63:0];
|
||||
end
|
||||
|
||||
// sign extension for words
|
||||
always_comb begin : sign_extend_word
|
||||
case (vaddr[2:0])
|
||||
default: rdata_w_ext = (operator == LW) ? {{32{rdata[31]}}, rdata[31:0]} : {32'h0, rdata[31:0]};
|
||||
3'b001: rdata_w_ext = (operator == LW) ? {{32{rdata[39]}}, rdata[39:8]} : {32'h0, rdata[39:8]};
|
||||
3'b010: rdata_w_ext = (operator == LW) ? {{32{rdata[47]}}, rdata[47:16]} : {32'h0, rdata[47:16]};
|
||||
3'b011: rdata_w_ext = (operator == LW) ? {{32{rdata[55]}}, rdata[55:24]} : {32'h0, rdata[55:24]};
|
||||
3'b100: rdata_w_ext = (operator == LW) ? {{32{rdata[63]}}, rdata[63:32]} : {32'h0, rdata[63:32]};
|
||||
// miss-aligned access
|
||||
// 3'b101: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[63:40]} : {32'h0, data_rdata_i[7:0], rdata_q[63:40]};
|
||||
// 3'b110: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[15]}}, data_rdata_i[15:0], rdata_q[63:48]} : {32'h0, data_rdata_i[15:0], rdata_q[63:48]};
|
||||
// 3'b111: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[23]}}, data_rdata_i[23:0], rdata_q[63:56]} : {32'h0, data_rdata_i[23:0], rdata_q[63:56]};
|
||||
3'b001: rdata_w_ext = (operator == LW) ? {{32{rdata[39]}}, rdata[39:8]} : {32'h0, rdata[39:8]};
|
||||
3'b010: rdata_w_ext = (operator == LW) ? {{32{rdata[47]}}, rdata[47:16]} : {32'h0, rdata[47:16]};
|
||||
3'b011: rdata_w_ext = (operator == LW) ? {{32{rdata[55]}}, rdata[55:24]} : {32'h0, rdata[55:24]};
|
||||
3'b100: rdata_w_ext = (operator == LW) ? {{32{rdata[63]}}, rdata[63:32]} : {32'h0, rdata[63:32]};
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -511,28 +503,26 @@ module lsu #(
|
|||
always_comb begin : sign_extend_half_word
|
||||
case (vaddr[2:0])
|
||||
default: rdata_h_ext = (operator == LH) ? {{48{rdata[15]}}, rdata[15:0]} : {48'h0, rdata[15:0]};
|
||||
3'b001: rdata_h_ext = (operator == LH) ? {{48{rdata[23]}}, rdata[23:8]} : {48'h0, rdata[23:8]};
|
||||
3'b010: rdata_h_ext = (operator == LH) ? {{48{rdata[31]}}, rdata[31:16]} : {48'h0, rdata[31:16]};
|
||||
3'b011: rdata_h_ext = (operator == LH) ? {{48{rdata[39]}}, rdata[39:24]} : {48'h0, rdata[39:24]};
|
||||
3'b100: rdata_h_ext = (operator == LH) ? {{48{rdata[47]}}, rdata[47:32]} : {48'h0, rdata[47:32]};
|
||||
3'b101: rdata_h_ext = (operator == LH) ? {{48{rdata[55]}}, rdata[55:40]} : {48'h0, rdata[55:40]};
|
||||
3'b110: rdata_h_ext = (operator == LH) ? {{48{rdata[63]}}, rdata[63:48]} : {48'h0, rdata[63:48]};
|
||||
// miss-aligned access
|
||||
// 3'b111: rdata_h_ext = (data_sign_ext_q) ? {{48{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[31:24]} : {48'h0, data_rdata_i[7:0], rdata_q[31:24]};
|
||||
3'b001: rdata_h_ext = (operator == LH) ? {{48{rdata[23]}}, rdata[23:8]} : {48'h0, rdata[23:8]};
|
||||
3'b010: rdata_h_ext = (operator == LH) ? {{48{rdata[31]}}, rdata[31:16]} : {48'h0, rdata[31:16]};
|
||||
3'b011: rdata_h_ext = (operator == LH) ? {{48{rdata[39]}}, rdata[39:24]} : {48'h0, rdata[39:24]};
|
||||
3'b100: rdata_h_ext = (operator == LH) ? {{48{rdata[47]}}, rdata[47:32]} : {48'h0, rdata[47:32]};
|
||||
3'b101: rdata_h_ext = (operator == LH) ? {{48{rdata[55]}}, rdata[55:40]} : {48'h0, rdata[55:40]};
|
||||
3'b110: rdata_h_ext = (operator == LH) ? {{48{rdata[63]}}, rdata[63:48]} : {48'h0, rdata[63:48]};
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin : sign_extend_byte
|
||||
case (vaddr[2:0])
|
||||
default: rdata_b_ext = (operator == LB) ? {{56{rdata[7]}}, rdata[7:0]} : {56'h0, rdata[7:0]};
|
||||
3'b001: rdata_b_ext = (operator == LB) ? {{56{rdata[15]}}, rdata[15:8]} : {56'h0, rdata[15:8]};
|
||||
3'b010: rdata_b_ext = (operator == LB) ? {{56{rdata[23]}}, rdata[23:16]} : {56'h0, rdata[23:16]};
|
||||
3'b011: rdata_b_ext = (operator == LB) ? {{56{rdata[31]}}, rdata[31:24]} : {56'h0, rdata[31:24]};
|
||||
3'b100: rdata_b_ext = (operator == LB) ? {{56{rdata[39]}}, rdata[39:32]} : {56'h0, rdata[39:32]};
|
||||
3'b101: rdata_b_ext = (operator == LB) ? {{56{rdata[47]}}, rdata[47:40]} : {56'h0, rdata[47:40]};
|
||||
3'b110: rdata_b_ext = (operator == LB) ? {{56{rdata[55]}}, rdata[55:48]} : {56'h0, rdata[55:48]};
|
||||
3'b111: rdata_b_ext = (operator == LB) ? {{56{rdata[63]}}, rdata[63:56]} : {56'h0, rdata[63:56]};
|
||||
endcase // case (rdata_offset_q)
|
||||
3'b001: rdata_b_ext = (operator == LB) ? {{56{rdata[15]}}, rdata[15:8]} : {56'h0, rdata[15:8]};
|
||||
3'b010: rdata_b_ext = (operator == LB) ? {{56{rdata[23]}}, rdata[23:16]} : {56'h0, rdata[23:16]};
|
||||
3'b011: rdata_b_ext = (operator == LB) ? {{56{rdata[31]}}, rdata[31:24]} : {56'h0, rdata[31:24]};
|
||||
3'b100: rdata_b_ext = (operator == LB) ? {{56{rdata[39]}}, rdata[39:32]} : {56'h0, rdata[39:32]};
|
||||
3'b101: rdata_b_ext = (operator == LB) ? {{56{rdata[47]}}, rdata[47:40]} : {56'h0, rdata[47:40]};
|
||||
3'b110: rdata_b_ext = (operator == LB) ? {{56{rdata[55]}}, rdata[55:48]} : {56'h0, rdata[55:48]};
|
||||
3'b111: rdata_b_ext = (operator == LB) ? {{56{rdata[63]}}, rdata[63:56]} : {56'h0, rdata[63:56]};
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
|
@ -541,7 +531,7 @@ module lsu #(
|
|||
LH, LHU: lsu_result_o = rdata_h_ext;
|
||||
LB, LBU: lsu_result_o = rdata_b_ext;
|
||||
default: lsu_result_o = rdata_d_ext;
|
||||
endcase //~case(rdata_type_q)
|
||||
endcase
|
||||
end
|
||||
|
||||
// ------------------
|
||||
|
@ -550,7 +540,7 @@ module lsu #(
|
|||
// misaligned detector
|
||||
// page fault, privilege exception
|
||||
// we can detect a misaligned exception immediately
|
||||
always_comb begin : exception_control
|
||||
always_comb begin : data_misaligned_detection
|
||||
data_misaligned = 1'b0;
|
||||
|
||||
if(lsu_valid_i) begin
|
||||
|
@ -574,6 +564,29 @@ module lsu #(
|
|||
end
|
||||
end
|
||||
|
||||
always_comb begin : exception_control
|
||||
lsu_exception_o = {
|
||||
64'b0,
|
||||
64'b0,
|
||||
1'b0
|
||||
};
|
||||
if (data_misaligned) begin
|
||||
if (op == LD_OP) begin
|
||||
lsu_exception_o = {
|
||||
64'b0,
|
||||
LD_ADDR_MISALIGNED,
|
||||
1'b1
|
||||
};
|
||||
end else if (op == ST_OP) begin
|
||||
lsu_exception_o = {
|
||||
64'b0,
|
||||
ST_ADDR_MISALIGNED,
|
||||
1'b1
|
||||
};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// this process selects the input based on the current state of the LSU
|
||||
// it can either be feedthrough from the issue stage or from the internal register
|
||||
always_comb begin : input_select
|
||||
|
@ -610,30 +623,36 @@ module lsu #(
|
|||
end
|
||||
end
|
||||
|
||||
// // ------------
|
||||
// // Assertions
|
||||
// // ------------
|
||||
// ------------
|
||||
// Assertions
|
||||
// ------------
|
||||
|
||||
// // make sure there is no new request when the old one is not yet completely done
|
||||
// // i.e. it should not be possible to get a grant without an rvalid for the
|
||||
// // last request
|
||||
// `ifndef VERILATOR
|
||||
// assert property (
|
||||
// @(posedge clk) ((CS == WAIT_RVALID) && (data_gnt_i == 1'b1)) |-> (data_rvalid_i == 1'b1) )
|
||||
// else begin $error("data grant without rvalid"); $stop(); end
|
||||
// // make sure there is no new request when the old one is not yet completely done
|
||||
// // i.e. it should not be possible to get a grant without an rvalid for the
|
||||
// // last request
|
||||
`ifndef SYNTHESIS
|
||||
`ifndef VERILATOR
|
||||
// assert property (
|
||||
// @(posedge clk) ((CS == WAIT_RVALID) && (data_gnt_i == 1'b1)) |-> (data_rvalid_i == 1'b1) )
|
||||
// else begin $error("data grant without rvalid"); $stop(); end
|
||||
|
||||
// // there should be no rvalid when we are in IDLE
|
||||
// assert property (
|
||||
// @(posedge clk) (CS == IDLE) |-> (data_rvalid_i == 1'b0) )
|
||||
// else begin $error("Received rvalid while in IDLE state"); $stop(); end
|
||||
// // there should be no rvalid when we are in IDLE
|
||||
// assert property (
|
||||
// @(posedge clk) (CS == IDLE) |-> (data_rvalid_i == 1'b0) )
|
||||
// else begin $error("Received rvalid while in IDLE state"); $stop(); end
|
||||
|
||||
// // assert that errors are only sent at the same time as grant or rvalid
|
||||
// assert property ( @(posedge clk) (data_err_i) |-> (data_gnt_i || data_rvalid_i) )
|
||||
// else begin $error("Error without data grant or rvalid"); $stop(); end
|
||||
// // assert that errors are only sent at the same time as grant or rvalid
|
||||
// assert property ( @(posedge clk) (data_err_i) |-> (data_gnt_i || data_rvalid_i) )
|
||||
// else begin $error("Error without data grant or rvalid"); $stop(); end
|
||||
|
||||
// // assert that the address does not contain X when request is sent
|
||||
// assert property ( @(posedge clk) (data_req_o) |-> (!$isunknown(data_addr_o)) )
|
||||
// else begin $error("address contains X when request is set"); $stop(); end
|
||||
// `endif
|
||||
// assert that errors are only sent at the same time as grant or rvalid
|
||||
// assert that we only get a valid in if we said that we are ready
|
||||
// assert property ( @(posedge clk_i) lsu_valid_i |-> lsu_ready_o)
|
||||
// else begin $error("[LSU] We got a valid but didn't say we were ready."); $stop(); end
|
||||
|
||||
// // assert that the address does not contain X when request is sent
|
||||
// assert property ( @(posedge clk) (data_req_o) |-> (!$isunknown(data_addr_o)) )
|
||||
// else begin $error("address contains X when request is set"); $stop(); end
|
||||
`endif
|
||||
`endif
|
||||
endmodule
|
|
@ -90,7 +90,7 @@ module mem_arbiter #(
|
|||
data_gnt_o[i] = 1'b0;
|
||||
// only go for a new request if we can wait for the valid e.g.: we have enough space in the buffer
|
||||
if (~full_o) begin
|
||||
for (int i = 0; i < NR_PORTS; i++) begin
|
||||
for (int unsigned i = 0; i < NR_PORTS; i++) begin
|
||||
if (data_req_i[i] == 1'b1) begin
|
||||
// pass through all signals from the correct slave port
|
||||
data_req_o = data_req_i[i];
|
||||
|
|
103
src/mmu.sv
103
src/mmu.sv
|
@ -81,8 +81,6 @@ module mmu #(
|
|||
|
||||
logic itlb_update;
|
||||
logic itlb_lu_access;
|
||||
logic [0:0] lu_asid_i;
|
||||
logic [63:0] lu_vaddr_i;
|
||||
pte_t itlb_content;
|
||||
|
||||
logic itlb_is_2M;
|
||||
|
@ -112,8 +110,8 @@ module mmu #(
|
|||
.update_tlb_i ( itlb_update ),
|
||||
|
||||
.lu_access_i ( itlb_lu_access ),
|
||||
.lu_asid_i ( lu_asid_i ),
|
||||
.lu_vaddr_i ( lu_vaddr_i ),
|
||||
.lu_asid_i ( asid_i ),
|
||||
.lu_vaddr_i ( fetch_vaddr_i ),
|
||||
.lu_content_o ( itlb_content ),
|
||||
.lu_is_2M_o ( itlb_is_2M ),
|
||||
.lu_is_1G_o ( itlb_is_1G ),
|
||||
|
@ -135,8 +133,8 @@ module mmu #(
|
|||
.update_tlb_i ( dtlb_update ),
|
||||
|
||||
.lu_access_i ( dtlb_lu_access ),
|
||||
.lu_asid_i ( lu_asid_i ),
|
||||
.lu_vaddr_i ( lu_vaddr_i ),
|
||||
.lu_asid_i ( asid_i ),
|
||||
.lu_vaddr_i ( lsu_vaddr_i ),
|
||||
.lu_content_o ( dtlb_content ),
|
||||
.lu_is_2M_o ( dtlb_is_2M ),
|
||||
.lu_is_1G_o ( dtlb_is_1G ),
|
||||
|
@ -183,8 +181,9 @@ module mmu #(
|
|||
.*
|
||||
);
|
||||
|
||||
|
||||
assign iaccess_err = fetch_req_i & (
|
||||
assign itlb_lu_access = fetch_req_i;
|
||||
assign dtlb_lu_access = lsu_req_i;
|
||||
assign iaccess_err = fetch_req_i & (
|
||||
((priv_lvl_i == PRIV_LVL_U) & ~itlb_content.u)
|
||||
| (flag_pum_i & (priv_lvl_i == PRIV_LVL_S) & itlb_content.u)
|
||||
);
|
||||
|
@ -193,53 +192,53 @@ assign iaccess_err = fetch_req_i & (
|
|||
// Instruction interface
|
||||
//-----------------------
|
||||
always_comb begin : instr_interface
|
||||
// MMU disabled: just pass through
|
||||
automatic logic fetch_valid = instr_if.data_rvalid;
|
||||
fetch_req = fetch_req_i;
|
||||
fetch_paddr = fetch_vaddr_i;
|
||||
fetch_gnt_o = instr_if.data_gnt;
|
||||
fetch_err_o = 1'b0;
|
||||
ierr_valid_n = 1'b0;
|
||||
// MMU disabled: just pass through
|
||||
automatic logic fetch_valid = instr_if.data_rvalid;
|
||||
fetch_req = fetch_req_i;
|
||||
fetch_paddr = fetch_vaddr_i;
|
||||
fetch_gnt_o = instr_if.data_gnt;
|
||||
fetch_err_o = 1'b0;
|
||||
ierr_valid_n = 1'b0;
|
||||
|
||||
// MMU enabled: address from TLB, request delayed until hit. Error when TLB
|
||||
// hit and no access right or TLB hit and translated address not valid (e.g.
|
||||
// AXI decode error), or when PTW performs walk due to itlb miss and raises
|
||||
// an error.
|
||||
if (enable_translation_i) begin
|
||||
fetch_req = 1'b0;
|
||||
fetch_paddr = {itlb_content.ppn, fetch_vaddr_i[11:0]};
|
||||
// MMU enabled: address from TLB, request delayed until hit. Error when TLB
|
||||
// hit and no access right or TLB hit and translated address not valid (e.g.
|
||||
// AXI decode error), or when PTW performs walk due to itlb miss and raises
|
||||
// an error.
|
||||
if (enable_translation_i) begin
|
||||
fetch_req = 1'b0;
|
||||
fetch_paddr = {itlb_content.ppn, fetch_vaddr_i[11:0]};
|
||||
|
||||
if (itlb_is_2M) begin
|
||||
fetch_paddr[20:12] = fetch_vaddr_i[20:12];
|
||||
if (itlb_is_2M) begin
|
||||
fetch_paddr[20:12] = fetch_vaddr_i[20:12];
|
||||
end
|
||||
|
||||
if (itlb_is_1G) begin
|
||||
fetch_paddr[29:12] = fetch_vaddr_i[29:12];
|
||||
end
|
||||
|
||||
fetch_gnt_o = instr_if.data_gnt;
|
||||
|
||||
// TODO the following two ifs should be mutually exclusive
|
||||
if (itlb_lu_hit) begin
|
||||
fetch_req = fetch_req_i;
|
||||
if (iaccess_err) begin
|
||||
// Play through an instruction fetch with error signaled with rvalid
|
||||
fetch_req = 1'b0;
|
||||
fetch_gnt_o = 1'b1; // immediate grant
|
||||
//fetch_valid = 1'b0; NOTE: valid from previous fetch: pass through
|
||||
// NOTE: back-to-back transfers: We only get a request if previous
|
||||
// transfer is completed, or completes in this cycle)
|
||||
ierr_valid_n = 1'b1; // valid signaled in next cycle
|
||||
end
|
||||
end
|
||||
if (ptw_active & walking_instr) begin
|
||||
// On error pass through fetch with error signaled with valid
|
||||
fetch_gnt_o = ptw_error;
|
||||
ierr_valid_n = ptw_error; // signal valid/error on next cycle
|
||||
end
|
||||
end
|
||||
|
||||
if (itlb_is_1G) begin
|
||||
fetch_paddr[29:12] = fetch_vaddr_i[29:12];
|
||||
end
|
||||
|
||||
fetch_gnt_o = instr_if.data_gnt;
|
||||
|
||||
// TODO the following two ifs should be mutually exclusive
|
||||
if (itlb_lu_hit) begin
|
||||
fetch_req = fetch_req_i;
|
||||
if (iaccess_err) begin
|
||||
// Play through an instruction fetch with error signaled with rvalid
|
||||
fetch_req = 1'b0;
|
||||
fetch_gnt_o = 1'b1; // immediate grant
|
||||
//fetch_valid = 1'b0; NOTE: valid from previous fetch: pass through
|
||||
// NOTE: back-to-back transfers: We only get a request if previous
|
||||
// transfer is completed, or completes in this cycle)
|
||||
ierr_valid_n = 1'b1; // valid signaled in next cycle
|
||||
end
|
||||
end
|
||||
if (ptw_active & walking_instr) begin
|
||||
// On error pass through fetch with error signaled with valid
|
||||
fetch_gnt_o = ptw_error;
|
||||
ierr_valid_n = ptw_error; // signal valid/error on next cycle
|
||||
end
|
||||
end
|
||||
fetch_err_o = ierr_valid_q;
|
||||
fetch_valid_o = fetch_valid || ierr_valid_q;
|
||||
fetch_err_o = ierr_valid_q;
|
||||
fetch_valid_o = fetch_valid || ierr_valid_q;
|
||||
end
|
||||
|
||||
// registers
|
||||
|
|
|
@ -130,7 +130,11 @@ module ptw #(
|
|||
// - pa.ppn[LEVELS-1:i] = pte.ppn[LEVELS-1:i].
|
||||
always_comb begin : ptw
|
||||
// default assignments
|
||||
// PTW memory interface
|
||||
data_req_o = 1'b0;
|
||||
data_be_o = 8'hFF;
|
||||
data_we_o = 1'b0;
|
||||
data_wdata_o = 64'b0;
|
||||
ptw_error_o = 1'b0;
|
||||
itlb_update_o = 1'b0;
|
||||
dtlb_update_o = 1'b0;
|
||||
|
|
|
@ -18,7 +18,7 @@ module scoreboard #(
|
|||
output logic full_o, // We can't take anymore data
|
||||
input logic flush_i,
|
||||
// list of clobbered registers to issue stage
|
||||
output logic [31:0][$bits(fu_t)-1:0] rd_clobber_o,
|
||||
output fu_t [31:0] rd_clobber_o,
|
||||
|
||||
// regfile like interface to operand read stage
|
||||
input logic [4:0] rs1_i,
|
||||
|
@ -77,7 +77,7 @@ assign empty = (pointer_overflow) ? 1'b0 : (commit_pointer_q == top_p
|
|||
// |_________________________|<- top pointer |_________________________|
|
||||
//
|
||||
always_comb begin : clobber_output
|
||||
rd_clobber_o = '{default: 0};
|
||||
rd_clobber_o = '{default: NONE};
|
||||
// excluding issue, the issue pointer points to the instruction which is currently not issued
|
||||
// but might be issued as soon as the issue unit acknowledges
|
||||
if (commit_pointer_q < issue_pointer_q) begin
|
||||
|
|
|
@ -35,11 +35,13 @@ interface lsu_if #(
|
|||
|
||||
// FU interface configured as master
|
||||
clocking mck @(posedge clk);
|
||||
default input #1ns output #1ns;
|
||||
output operator, operand_a, operand_b, imm, source_valid, commit, lsu_trans_id_id;
|
||||
input result, lsu_trans_id_wb, result_valid, ready, exception;
|
||||
endclocking
|
||||
// FU interface configured as slave
|
||||
clocking sck @(posedge clk);
|
||||
default input #1ns output #1ns;
|
||||
input operator, operand_a, operand_b, imm, source_valid, commit, lsu_trans_id_id;
|
||||
output result, lsu_trans_id_wb, result_valid, ready, exception;
|
||||
endclocking
|
||||
|
|
|
@ -56,6 +56,8 @@ class lsu_if_driver extends uvm_driver #(lsu_if_seq_item);
|
|||
m_vif.mck.operand_a <= cmd.operandA;
|
||||
m_vif.mck.operand_b <= cmd.operandB;
|
||||
|
||||
@(m_vif.mck);
|
||||
m_vif.mck.source_valid <= 1'b0;
|
||||
seq_item_port.item_done();
|
||||
end else
|
||||
m_vif.mck.source_valid <= 1'b0;
|
||||
|
|
|
@ -15,7 +15,7 @@ import ariane_pkg::*;
|
|||
interface scoreboard_if #(parameter int NR_WB_PORTS = 1)(input clk);
|
||||
wire full;
|
||||
wire flush;
|
||||
wire [31:0][$bits(fu_t)-1:0] rd_clobber;
|
||||
wire [31:0] rd_clobber;
|
||||
wire [4:0] rs1_address;
|
||||
wire [63:0] rs1;
|
||||
wire rs1_valid;
|
||||
|
|
|
@ -68,6 +68,8 @@ module lsu_tb;
|
|||
|
||||
// hack to not get a grant without a request
|
||||
assign slave.data_gnt = slave.data_req & slave.data_gnt;
|
||||
// hack to get a combinatorial path between ready and source valid
|
||||
// assign lsu.source_valid = lsu.source_valid & lsu.ready;
|
||||
|
||||
initial begin
|
||||
clk = 1'b0;
|
||||
|
|
|
@ -28,7 +28,7 @@ module scoreboard_tb;
|
|||
.rst_ni ( rst_ni ),
|
||||
.full_o ( scoreboard_if.full ),
|
||||
.flush_i ( scoreboard_if.flush ),
|
||||
.rd_clobber_o ( scoreboard_if.rd_clobber ),
|
||||
.rd_clobber_o ( fu_t'(scoreboard_if.rd_clobber) ),
|
||||
.rs1_i ( scoreboard_if.rs1_address ),
|
||||
.rs1_o ( scoreboard_if.rs1 ),
|
||||
.rs1_valid_o ( scoreboard_if.rs1_valid ),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue