abstractaccelerator/Cores-SweRV/design/lsu/lsu_addrcheck.sv

189 lines
10 KiB
Systemverilog

// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
//
// 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.
//********************************************************************************
// $Id$
//
//
// Owner:
// Function: Checks the memory map for the address
// Comments:
//
//********************************************************************************
module lsu_addrcheck
import swerv_types::*;
(
input logic lsu_freeze_c2_dc2_clk, // clock
input logic lsu_freeze_c2_dc3_clk,
input logic lsu_freeze_c2_dc2_clken,
input logic lsu_freeze_c2_dc3_clken,
input logic rst_l, // reset
input logic clk,
input logic [31:0] start_addr_dc1, // start address for lsu
input logic [31:0] end_addr_dc1, // end address for lsu
input lsu_pkt_t lsu_pkt_dc1, // packet in dc1
input logic [31:0] dec_tlu_mrac_ff, // CSR read
output logic is_sideeffects_dc2, // is sideffects space
output logic is_sideeffects_dc3,
output logic addr_in_dccm_dc1, // address in dccm
output logic addr_in_pic_dc1, // address in pic
output logic addr_external_dc1, // address in external
output logic access_fault_dc1, // access fault
output logic misaligned_fault_dc1, // misaligned
input logic scan_mode
);
`include "global.h"
localparam DCCM_REGION = `RV_DCCM_REGION;
localparam PIC_REGION = `RV_PIC_REGION;
localparam ICCM_REGION = `RV_ICCM_REGION;
`ifdef RV_ICCM_ENABLE
localparam ICCM_ENABLE = 1'b1;
`else
localparam ICCM_ENABLE = 1'b0;
`endif
`ifdef RV_DCCM_ENABLE
localparam DCCM_ENABLE = 1'b1;
`else
localparam DCCM_ENABLE = 1'b0;
`endif
logic is_sideeffects_dc1, is_aligned_dc1;
logic start_addr_in_dccm_dc1, end_addr_in_dccm_dc1;
logic start_addr_in_dccm_region_dc1, end_addr_in_dccm_region_dc1;
logic start_addr_in_pic_dc1, end_addr_in_pic_dc1;
logic start_addr_in_pic_region_dc1, end_addr_in_pic_region_dc1;
logic [4:0] csr_idx;
logic addr_in_iccm;
logic non_dccm_access_ok;
if (DCCM_ENABLE == 1) begin: Gen_dccm_enable
// Start address check
rvrangecheck #(.CCM_SADR(`RV_DCCM_SADR),
.CCM_SIZE(`RV_DCCM_SIZE)) start_addr_dccm_rangecheck (
.addr(start_addr_dc1[31:0]),
.in_range(start_addr_in_dccm_dc1),
.in_region(start_addr_in_dccm_region_dc1)
);
// End address check
rvrangecheck #(.CCM_SADR(`RV_DCCM_SADR),
.CCM_SIZE(`RV_DCCM_SIZE)) end_addr_dccm_rangecheck (
.addr(end_addr_dc1[31:0]),
.in_range(end_addr_in_dccm_dc1),
.in_region(end_addr_in_dccm_region_dc1)
);
end else begin: Gen_dccm_disable // block: Gen_dccm_enable
assign start_addr_in_dccm_dc1 = '0;
assign start_addr_in_dccm_region_dc1 = '0;
assign end_addr_in_dccm_dc1 = '0;
assign end_addr_in_dccm_region_dc1 = '0;
end
if (ICCM_ENABLE == 1) begin : check_iccm
assign addr_in_iccm = (start_addr_dc1[31:28] == ICCM_REGION);
end
else begin
assign addr_in_iccm = 1'b0;
end
// PIC memory check
// Start address check
rvrangecheck #(.CCM_SADR(`RV_PIC_BASE_ADDR),
.CCM_SIZE(`RV_PIC_SIZE)) start_addr_pic_rangecheck (
.addr(start_addr_dc1[31:0]),
.in_range(start_addr_in_pic_dc1),
.in_region(start_addr_in_pic_region_dc1)
);
// End address check
rvrangecheck #(.CCM_SADR(`RV_PIC_BASE_ADDR),
.CCM_SIZE(`RV_PIC_SIZE)) end_addr_pic_rangecheck (
.addr(end_addr_dc1[31:0]),
.in_range(end_addr_in_pic_dc1),
.in_region(end_addr_in_pic_region_dc1)
);
assign addr_in_dccm_dc1 = (start_addr_in_dccm_dc1 & end_addr_in_dccm_dc1);
assign addr_in_pic_dc1 = (start_addr_in_pic_dc1 & end_addr_in_pic_dc1);
assign addr_external_dc1 = ~(addr_in_dccm_dc1 | addr_in_pic_dc1); //~addr_in_dccm_region_dc1;
assign csr_idx[4:0] = {start_addr_dc1[31:28], 1'b1};
assign is_sideeffects_dc1 = dec_tlu_mrac_ff[csr_idx] & ~(start_addr_in_dccm_region_dc1 | start_addr_in_pic_region_dc1 | addr_in_iccm); //every region has the 2 LSB indicating ( 1: sideeffects/no_side effects, and 0: cacheable ). Ignored in internal regions
assign is_aligned_dc1 = (lsu_pkt_dc1.word & (start_addr_dc1[1:0] == 2'b0)) |
(lsu_pkt_dc1.half & (start_addr_dc1[0] == 1'b0)) |
lsu_pkt_dc1.by;
assign non_dccm_access_ok = (~(|{`RV_DATA_ACCESS_ENABLE0,`RV_DATA_ACCESS_ENABLE1,`RV_DATA_ACCESS_ENABLE2,`RV_DATA_ACCESS_ENABLE3,`RV_DATA_ACCESS_ENABLE4,`RV_DATA_ACCESS_ENABLE5,`RV_DATA_ACCESS_ENABLE6,`RV_DATA_ACCESS_ENABLE7})) |
(((`RV_DATA_ACCESS_ENABLE0 & ((start_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK0)) == (`RV_DATA_ACCESS_ADDR0 | `RV_DATA_ACCESS_MASK0)) |
(`RV_DATA_ACCESS_ENABLE1 & ((start_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK1)) == (`RV_DATA_ACCESS_ADDR1 | `RV_DATA_ACCESS_MASK1)) |
(`RV_DATA_ACCESS_ENABLE2 & ((start_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK2)) == (`RV_DATA_ACCESS_ADDR2 | `RV_DATA_ACCESS_MASK2)) |
(`RV_DATA_ACCESS_ENABLE3 & ((start_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK3)) == (`RV_DATA_ACCESS_ADDR3 | `RV_DATA_ACCESS_MASK3)) |
(`RV_DATA_ACCESS_ENABLE4 & ((start_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK4)) == (`RV_DATA_ACCESS_ADDR4 | `RV_DATA_ACCESS_MASK4)) |
(`RV_DATA_ACCESS_ENABLE5 & ((start_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK5)) == (`RV_DATA_ACCESS_ADDR5 | `RV_DATA_ACCESS_MASK5)) |
(`RV_DATA_ACCESS_ENABLE6 & ((start_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK6)) == (`RV_DATA_ACCESS_ADDR6 | `RV_DATA_ACCESS_MASK6)) |
(`RV_DATA_ACCESS_ENABLE7 & ((start_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK7)) == (`RV_DATA_ACCESS_ADDR7 | `RV_DATA_ACCESS_MASK7))) &
((`RV_DATA_ACCESS_ENABLE0 & ((end_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK0)) == (`RV_DATA_ACCESS_ADDR0 | `RV_DATA_ACCESS_MASK0)) |
(`RV_DATA_ACCESS_ENABLE1 & ((end_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK1)) == (`RV_DATA_ACCESS_ADDR1 | `RV_DATA_ACCESS_MASK1)) |
(`RV_DATA_ACCESS_ENABLE2 & ((end_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK2)) == (`RV_DATA_ACCESS_ADDR2 | `RV_DATA_ACCESS_MASK2)) |
(`RV_DATA_ACCESS_ENABLE3 & ((end_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK3)) == (`RV_DATA_ACCESS_ADDR3 | `RV_DATA_ACCESS_MASK3)) |
(`RV_DATA_ACCESS_ENABLE4 & ((end_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK4)) == (`RV_DATA_ACCESS_ADDR4 | `RV_DATA_ACCESS_MASK4)) |
(`RV_DATA_ACCESS_ENABLE5 & ((end_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK5)) == (`RV_DATA_ACCESS_ADDR5 | `RV_DATA_ACCESS_MASK5)) |
(`RV_DATA_ACCESS_ENABLE6 & ((end_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK6)) == (`RV_DATA_ACCESS_ADDR6 | `RV_DATA_ACCESS_MASK6)) |
(`RV_DATA_ACCESS_ENABLE7 & ((end_addr_dc1[31:0] | `RV_DATA_ACCESS_MASK7)) == (`RV_DATA_ACCESS_ADDR7 | `RV_DATA_ACCESS_MASK7))));
// Access fault logic
// 1. Addr in dccm region but not in dccm offset
// 2. Addr in picm region but not in picm offset
// 3. DCCM -> PIC offset cross when DCCM/PIC in same region (PIC access are always word aligned so no cross possible from PIC->DCCM)
// 4. Ld/St access to picm are not word aligned
// 5. Address not in protected space or dccm/pic region
if (DCCM_ENABLE & (DCCM_REGION == PIC_REGION)) begin
assign access_fault_dc1 = ((start_addr_in_dccm_region_dc1 & ~(start_addr_in_dccm_dc1 | start_addr_in_pic_dc1)) |
(end_addr_in_dccm_region_dc1 & ~(end_addr_in_dccm_dc1 | end_addr_in_pic_dc1)) |
(start_addr_in_dccm_dc1 & end_addr_in_pic_dc1) |
(start_addr_in_pic_dc1 & end_addr_in_dccm_dc1) |
((addr_in_pic_dc1 & ((start_addr_dc1[1:0] != 2'b0) | ~lsu_pkt_dc1.word))) |
(~start_addr_in_dccm_region_dc1 & ~non_dccm_access_ok)) & lsu_pkt_dc1.valid & ~lsu_pkt_dc1.dma;
end else begin
assign access_fault_dc1 = ((start_addr_in_dccm_region_dc1 & ~start_addr_in_dccm_dc1) |
(end_addr_in_dccm_region_dc1 & ~end_addr_in_dccm_dc1) |
(start_addr_in_pic_region_dc1 & ~start_addr_in_pic_dc1) |
(end_addr_in_pic_region_dc1 & ~end_addr_in_pic_dc1) |
((addr_in_pic_dc1 & ((start_addr_dc1[1:0] != 2'b0) | ~lsu_pkt_dc1.word))) |
(~start_addr_in_pic_region_dc1 & ~start_addr_in_dccm_region_dc1 & ~non_dccm_access_ok)) & lsu_pkt_dc1.valid & ~lsu_pkt_dc1.dma;
end
// Misaligned happens due to 2 reasons
// 1. Region cross
// 2. sideeffects access which are not aligned
assign misaligned_fault_dc1 = ((start_addr_dc1[31:28] != end_addr_dc1[31:28]) |
(is_sideeffects_dc1 & ~is_aligned_dc1)) & addr_external_dc1 & lsu_pkt_dc1.valid & ~lsu_pkt_dc1.dma;
rvdff_fpga #(.WIDTH(1)) is_sideeffects_dc2ff (.din(is_sideeffects_dc1), .dout(is_sideeffects_dc2), .clk(lsu_freeze_c2_dc2_clk), .clken(lsu_freeze_c2_dc2_clken), .rawclk(clk), .*);
rvdff_fpga #(.WIDTH(1)) is_sideeffects_dc3ff (.din(is_sideeffects_dc2), .dout(is_sideeffects_dc3), .clk(lsu_freeze_c2_dc3_clk), .clken(lsu_freeze_c2_dc3_clken), .rawclk(clk), .*);
endmodule // lsu_addrcheck