2019-06-04 22:57:48 +08:00
// 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 ,
2019-08-14 03:48:48 +08:00
input logic rst_l , // reset
2019-06-04 22:57:48 +08:00
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
2019-08-14 03:48:48 +08:00
input logic scan_mode
2019-06-04 22:57:48 +08:00
) ;
`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 ;
2019-08-14 03:48:48 +08:00
logic start_addr_in_dccm_dc1 , end_addr_in_dccm_dc1 ;
2019-06-04 22:57:48 +08:00
logic start_addr_in_dccm_region_dc1 , end_addr_in_dccm_region_dc1 ;
2019-08-14 03:48:48 +08:00
logic start_addr_in_pic_dc1 , end_addr_in_pic_dc1 ;
2019-06-04 22:57:48 +08:00
logic start_addr_in_pic_region_dc1 , end_addr_in_pic_region_dc1 ;
2019-08-14 03:48:48 +08:00
logic [ 4 : 0 ] csr_idx ;
2019-06-04 22:57:48 +08:00
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 )
) ;
2019-08-14 03:48:48 +08:00
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 ) ;
2019-06-04 22:57:48 +08:00
2019-08-14 03:48:48 +08:00
assign addr_external_dc1 = ~ ( addr_in_dccm_dc1 | addr_in_pic_dc1 ) ; //~addr_in_dccm_region_dc1;
2019-06-04 22:57:48 +08:00
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 ) ) |
2019-08-14 03:48:48 +08:00
( `RV_DATA_ACCESS_ENABLE3 & ( ( start_addr_dc1 [ 31 : 0 ] | `RV_DATA_ACCESS_MASK3 ) ) = = ( `RV_DATA_ACCESS_ADDR3 | `RV_DATA_ACCESS_MASK3 ) ) |
2019-06-04 22:57:48 +08:00
( `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_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_dc1 [ 27 : 18 ] ! = end_addr_dc1 [ 27 : 18 ] ) & start_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 # ( . WIDTH ( 1 ) ) is_sideeffects_dc2ff ( . din ( is_sideeffects_dc1 ) , . dout ( is_sideeffects_dc2 ) , . clk ( lsu_freeze_c2_dc2_clk ) , . * ) ;
rvdff # ( . WIDTH ( 1 ) ) is_sideeffects_dc3ff ( . din ( is_sideeffects_dc2 ) , . dout ( is_sideeffects_dc3 ) , . clk ( lsu_freeze_c2_dc3_clk ) , . * ) ;
2019-08-14 03:48:48 +08:00
2019-06-04 22:57:48 +08:00
endmodule // lsu_addrcheck