SweRV 1.1
This commit is contained in:
parent
6ccfce0957
commit
c0f7e509cc
|
@ -0,0 +1,14 @@
|
|||
# SweRV RISC-V core from Western Digital
|
||||
|
||||
## Configuration
|
||||
|
||||
### Contents
|
||||
Name | Description
|
||||
---------------------- | ------------------------------
|
||||
swerv.config | Configuration script for SweRV
|
||||
|
||||
|
||||
This script will generate a consistent st of `defines/#defines needed for the design and testbench.
|
||||
A perl hash (*perl_configs.pl*) and a JSON format for SweRV-iss are also generated.
|
||||
|
||||
While the defines fines may be modified by hand, it is recommended that this script be used to generate a consistent set.
|
|
@ -0,0 +1,170 @@
|
|||
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
|
||||
// This is an automatically generated file by joseph.rahmeh on Tue Jun 4 07:50:46 PDT 2019
|
||||
//
|
||||
// cmd: swerv -snapshot=default -ahb_lite
|
||||
//
|
||||
`define RV_INST_ACCESS_MASK5 'hffffffff
|
||||
`define RV_DATA_ACCESS_ENABLE4 1'h0
|
||||
`define RV_INST_ACCESS_ENABLE3 1'h0
|
||||
`define RV_INST_ACCESS_ENABLE0 1'h0
|
||||
`define RV_INST_ACCESS_MASK3 'hffffffff
|
||||
`define RV_DATA_ACCESS_ENABLE5 1'h0
|
||||
`define RV_DATA_ACCESS_MASK5 'hffffffff
|
||||
`define RV_DATA_ACCESS_ADDR3 'h00000000
|
||||
`define RV_INST_ACCESS_ENABLE7 1'h0
|
||||
`define RV_DATA_ACCESS_ADDR6 'h00000000
|
||||
`define RV_INST_ACCESS_MASK7 'hffffffff
|
||||
`define RV_INST_ACCESS_ENABLE6 1'h0
|
||||
`define RV_INST_ACCESS_ENABLE5 1'h0
|
||||
`define RV_DATA_ACCESS_ADDR4 'h00000000
|
||||
`define RV_DATA_ACCESS_ADDR7 'h00000000
|
||||
`define RV_DATA_ACCESS_MASK3 'hffffffff
|
||||
`define RV_INST_ACCESS_MASK4 'hffffffff
|
||||
`define RV_DATA_ACCESS_ADDR1 'h00000000
|
||||
`define RV_INST_ACCESS_ADDR4 'h00000000
|
||||
`define RV_INST_ACCESS_ADDR3 'h00000000
|
||||
`define RV_DATA_ACCESS_ENABLE1 1'h0
|
||||
`define RV_DATA_ACCESS_ADDR0 'h00000000
|
||||
`define RV_DATA_ACCESS_MASK0 'hffffffff
|
||||
`define RV_DATA_ACCESS_MASK6 'hffffffff
|
||||
`define RV_INST_ACCESS_ADDR7 'h00000000
|
||||
`define RV_INST_ACCESS_MASK0 'hffffffff
|
||||
`define RV_DATA_ACCESS_ADDR5 'h00000000
|
||||
`define RV_DATA_ACCESS_ADDR2 'h00000000
|
||||
`define RV_DATA_ACCESS_MASK4 'hffffffff
|
||||
`define RV_DATA_ACCESS_MASK1 'hffffffff
|
||||
`define RV_INST_ACCESS_ADDR0 'h00000000
|
||||
`define RV_INST_ACCESS_ADDR2 'h00000000
|
||||
`define RV_DATA_ACCESS_ENABLE0 1'h0
|
||||
`define RV_DATA_ACCESS_ENABLE2 1'h0
|
||||
`define RV_DATA_ACCESS_ENABLE7 1'h0
|
||||
`define RV_INST_ACCESS_ENABLE4 1'h0
|
||||
`define RV_DATA_ACCESS_MASK7 'hffffffff
|
||||
`define RV_INST_ACCESS_ADDR5 'h00000000
|
||||
`define RV_INST_ACCESS_ENABLE1 1'h0
|
||||
`define RV_DATA_ACCESS_MASK2 'hffffffff
|
||||
`define RV_INST_ACCESS_MASK6 'hffffffff
|
||||
`define RV_DATA_ACCESS_ENABLE3 1'h0
|
||||
`define RV_INST_ACCESS_ADDR6 'h00000000
|
||||
`define RV_INST_ACCESS_MASK2 'hffffffff
|
||||
`define RV_INST_ACCESS_ENABLE2 1'h0
|
||||
`define RV_DATA_ACCESS_ENABLE6 1'h0
|
||||
`define RV_INST_ACCESS_ADDR1 'h00000000
|
||||
`define RV_INST_ACCESS_MASK1 'hffffffff
|
||||
`define RV_DEC_INSTBUF_DEPTH 4
|
||||
`define RV_DMA_BUF_DEPTH 4
|
||||
`define RV_LSU_NUM_NBLOAD 8
|
||||
`define RV_LSU_STBUF_DEPTH 8
|
||||
`define RV_LSU_NUM_NBLOAD_WIDTH 3
|
||||
`define RV_IFU_BUS_TAG 3
|
||||
`define RV_LSU_BUS_TAG 4
|
||||
`define RV_SB_BUS_TAG 1
|
||||
`define RV_DMA_BUS_TAG 1
|
||||
`define RV_DCCM_WIDTH_BITS 2
|
||||
`define RV_DCCM_REGION 4'hf
|
||||
`define RV_DCCM_RESERVED 'h1000
|
||||
`define RV_DCCM_SIZE 64
|
||||
`define RV_DCCM_DATA_WIDTH 32
|
||||
`define RV_DCCM_NUM_BANKS_8
|
||||
`define RV_DCCM_FDATA_WIDTH 39
|
||||
`define RV_DCCM_BYTE_WIDTH 4
|
||||
`define RV_DCCM_DATA_CELL ram_2048x39
|
||||
`define RV_DCCM_ENABLE 1
|
||||
`define RV_DCCM_BITS 16
|
||||
`define RV_DCCM_OFFSET 28'h40000
|
||||
`define RV_DCCM_ECC_WIDTH 7
|
||||
`define RV_DCCM_SIZE_64
|
||||
`define RV_DCCM_ROWS 2048
|
||||
`define RV_DCCM_BANK_BITS 3
|
||||
`define RV_DCCM_NUM_BANKS 8
|
||||
`define RV_DCCM_INDEX_BITS 11
|
||||
`define RV_LSU_SB_BITS 16
|
||||
`define RV_DCCM_EADR 32'hf004ffff
|
||||
`define RV_DCCM_SADR 32'hf0040000
|
||||
`define RV_RESET_VEC 'h80000000
|
||||
`define RV_RET_STACK_SIZE 4
|
||||
`define RV_XLEN 32
|
||||
`define RV_TARGET default
|
||||
`define RV_BTB_BTAG_FOLD 1
|
||||
`define RV_BTB_INDEX3_HI 9
|
||||
`define RV_BTB_INDEX1_LO 4
|
||||
`define RV_BTB_ADDR_HI 5
|
||||
`define RV_BTB_ADDR_LO 4
|
||||
`define RV_BTB_INDEX1_HI 5
|
||||
`define RV_BTB_INDEX2_HI 7
|
||||
`define RV_BTB_INDEX2_LO 6
|
||||
`define RV_BTB_ARRAY_DEPTH 4
|
||||
`define RV_BTB_BTAG_SIZE 9
|
||||
`define RV_BTB_SIZE 32
|
||||
`define RV_BTB_INDEX3_LO 8
|
||||
`define RV_ICCM_NUM_BANKS 8
|
||||
`define RV_ICCM_BITS 19
|
||||
`define RV_ICCM_BANK_BITS 3
|
||||
`define RV_ICCM_ROWS 16384
|
||||
`define RV_ICCM_OFFSET 10'he000000
|
||||
`define RV_ICCM_REGION 4'he
|
||||
`define RV_ICCM_SADR 32'hee000000
|
||||
`define RV_ICCM_RESERVED 'h1000
|
||||
`define RV_ICCM_DATA_CELL ram_16384x39
|
||||
`define RV_ICCM_INDEX_BITS 14
|
||||
`define RV_ICCM_NUM_BANKS_8
|
||||
`define RV_ICCM_SIZE 512
|
||||
`define RV_ICCM_EADR 32'hee07ffff
|
||||
`define RV_ICCM_SIZE_512
|
||||
`define RV_ICACHE_SIZE 16
|
||||
`define RV_ICACHE_TAG_HIGH 12
|
||||
`define RV_ICACHE_IC_ROWS 256
|
||||
`define RV_ICACHE_TADDR_HIGH 5
|
||||
`define RV_ICACHE_TAG_LOW 6
|
||||
`define RV_ICACHE_TAG_CELL ram_64x21
|
||||
`define RV_ICACHE_IC_DEPTH 8
|
||||
`define RV_ICACHE_IC_INDEX 8
|
||||
`define RV_ICACHE_ENABLE 1
|
||||
`define RV_ICACHE_DATA_CELL ram_256x34
|
||||
`define RV_ICACHE_TAG_DEPTH 64
|
||||
`define RV_EXTERNAL_PROG 'hb0000000
|
||||
`define RV_EXTERNAL_DATA_1 'h00000000
|
||||
`define RV_DEBUG_SB_MEM 'hb0580000
|
||||
`define RV_EXTERNAL_DATA 'hc0580000
|
||||
`define RV_SERIALIO 'hd0580000
|
||||
`define RV_NMI_VEC 'h11110000
|
||||
`define RV_BHT_HASH_STRING {ghr[3:2] ^ {ghr[3+1], {4-1-2{1'b0} } },hashin[5:4]^ghr[2-1:0]}
|
||||
`define RV_BHT_ADDR_HI 7
|
||||
`define RV_BHT_GHR_RANGE 4:0
|
||||
`define RV_BHT_GHR_SIZE 5
|
||||
`define RV_BHT_GHR_PAD2 fghr[4:3],2'b0
|
||||
`define RV_BHT_SIZE 128
|
||||
`define RV_BHT_ADDR_LO 4
|
||||
`define RV_BHT_ARRAY_DEPTH 16
|
||||
`define RV_BHT_GHR_PAD fghr[4],3'b0
|
||||
`define RV_NUMIREGS 32
|
||||
`define RV_PIC_BITS 15
|
||||
`define RV_PIC_REGION 4'hf
|
||||
`define RV_PIC_INT_WORDS 1
|
||||
`define RV_PIC_TOTAL_INT_PLUS1 9
|
||||
`define RV_PIC_MEIP_OFFSET 'h1000
|
||||
`define RV_PIC_BASE_ADDR 32'hf00c0000
|
||||
`define RV_PIC_MEIGWCTRL_OFFSET 'h4000
|
||||
`define RV_PIC_MEIPL_OFFSET 'h0000
|
||||
`define RV_PIC_TOTAL_INT 8
|
||||
`define RV_PIC_SIZE 32
|
||||
`define RV_PIC_MEIE_OFFSET 'h2000
|
||||
`define RV_PIC_OFFSET 10'hc0000
|
||||
`define RV_PIC_MEIPT_OFFSET 'h3004
|
||||
`define RV_PIC_MPICCFG_OFFSET 'h3000
|
||||
`define RV_PIC_MEIGWCLR_OFFSET 'h5000
|
||||
`define CLOCK_PERIOD 100
|
||||
`define CPU_TOP `RV_TOP.swerv
|
||||
`define TOP tb_top
|
||||
`define RV_BUILD_AHB_LITE 1
|
||||
`define RV_TOP `TOP.rvtop
|
||||
`define DATAWIDTH 64
|
||||
`define RV_STERR_ROLLBACK 0
|
||||
`define RV_EXT_ADDRWIDTH 32
|
||||
`define RV_EXT_DATAWIDTH 64
|
||||
`define SDVT_AHB 1
|
||||
`define RV_LDERR_ROLLBACK 1
|
||||
`define ASSERT_ON
|
||||
`define TEC_RV_ICG clockhdr
|
||||
`define REGWIDTH 32
|
||||
`undef ASSERT_ON
|
|
@ -0,0 +1,132 @@
|
|||
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
|
||||
// This is an automatically generated file by joseph.rahmeh on Tue Jun 4 07:50:46 PDT 2019
|
||||
//
|
||||
// cmd: swerv -snapshot=default -ahb_lite
|
||||
//
|
||||
#define RV_INST_ACCESS_MASK5 0xffffffff
|
||||
#define RV_DATA_ACCESS_ENABLE4 0x0
|
||||
#define RV_INST_ACCESS_ENABLE3 0x0
|
||||
#define RV_INST_ACCESS_ENABLE0 0x0
|
||||
#define RV_INST_ACCESS_MASK3 0xffffffff
|
||||
#define RV_DATA_ACCESS_ENABLE5 0x0
|
||||
#define RV_DATA_ACCESS_MASK5 0xffffffff
|
||||
#define RV_DATA_ACCESS_ADDR3 0x00000000
|
||||
#define RV_INST_ACCESS_ENABLE7 0x0
|
||||
#define RV_DATA_ACCESS_ADDR6 0x00000000
|
||||
#define RV_INST_ACCESS_MASK7 0xffffffff
|
||||
#define RV_INST_ACCESS_ENABLE6 0x0
|
||||
#define RV_INST_ACCESS_ENABLE5 0x0
|
||||
#define RV_DATA_ACCESS_ADDR4 0x00000000
|
||||
#define RV_DATA_ACCESS_ADDR7 0x00000000
|
||||
#define RV_DATA_ACCESS_MASK3 0xffffffff
|
||||
#define RV_INST_ACCESS_MASK4 0xffffffff
|
||||
#define RV_DATA_ACCESS_ADDR1 0x00000000
|
||||
#define RV_INST_ACCESS_ADDR4 0x00000000
|
||||
#define RV_INST_ACCESS_ADDR3 0x00000000
|
||||
#define RV_DATA_ACCESS_ENABLE1 0x0
|
||||
#define RV_DATA_ACCESS_ADDR0 0x00000000
|
||||
#define RV_DATA_ACCESS_MASK0 0xffffffff
|
||||
#define RV_DATA_ACCESS_MASK6 0xffffffff
|
||||
#define RV_INST_ACCESS_ADDR7 0x00000000
|
||||
#define RV_INST_ACCESS_MASK0 0xffffffff
|
||||
#define RV_DATA_ACCESS_ADDR5 0x00000000
|
||||
#define RV_DATA_ACCESS_ADDR2 0x00000000
|
||||
#define RV_DATA_ACCESS_MASK4 0xffffffff
|
||||
#define RV_DATA_ACCESS_MASK1 0xffffffff
|
||||
#define RV_INST_ACCESS_ADDR0 0x00000000
|
||||
#define RV_INST_ACCESS_ADDR2 0x00000000
|
||||
#define RV_DATA_ACCESS_ENABLE0 0x0
|
||||
#define RV_DATA_ACCESS_ENABLE2 0x0
|
||||
#define RV_DATA_ACCESS_ENABLE7 0x0
|
||||
#define RV_INST_ACCESS_ENABLE4 0x0
|
||||
#define RV_DATA_ACCESS_MASK7 0xffffffff
|
||||
#define RV_INST_ACCESS_ADDR5 0x00000000
|
||||
#define RV_INST_ACCESS_ENABLE1 0x0
|
||||
#define RV_DATA_ACCESS_MASK2 0xffffffff
|
||||
#define RV_INST_ACCESS_MASK6 0xffffffff
|
||||
#define RV_DATA_ACCESS_ENABLE3 0x0
|
||||
#define RV_INST_ACCESS_ADDR6 0x00000000
|
||||
#define RV_INST_ACCESS_MASK2 0xffffffff
|
||||
#define RV_INST_ACCESS_ENABLE2 0x0
|
||||
#define RV_DATA_ACCESS_ENABLE6 0x0
|
||||
#define RV_INST_ACCESS_ADDR1 0x00000000
|
||||
#define RV_INST_ACCESS_MASK1 0xffffffff
|
||||
#define RV_IFU_BUS_TAG 3
|
||||
#define RV_LSU_BUS_TAG 4
|
||||
#define RV_SB_BUS_TAG 1
|
||||
#define RV_DMA_BUS_TAG 1
|
||||
#define RV_DCCM_WIDTH_BITS 2
|
||||
#define RV_DCCM_REGION 0xf
|
||||
#define RV_DCCM_RESERVED 0x1000
|
||||
#define RV_DCCM_SIZE 64
|
||||
#define RV_DCCM_DATA_WIDTH 32
|
||||
#define RV_DCCM_NUM_BANKS_8
|
||||
#define RV_DCCM_FDATA_WIDTH 39
|
||||
#define RV_DCCM_BYTE_WIDTH 4
|
||||
#define RV_DCCM_DATA_CELL ram_2048x39
|
||||
#define RV_DCCM_ENABLE 1
|
||||
#define RV_DCCM_BITS 16
|
||||
#define RV_DCCM_OFFSET 0x40000
|
||||
#define RV_DCCM_ECC_WIDTH 7
|
||||
#define RV_DCCM_SIZE_64
|
||||
#define RV_DCCM_ROWS 2048
|
||||
#define RV_DCCM_BANK_BITS 3
|
||||
#define RV_DCCM_NUM_BANKS 8
|
||||
#define RV_DCCM_INDEX_BITS 11
|
||||
#define RV_LSU_SB_BITS 16
|
||||
#define RV_DCCM_EADR 0xf004ffff
|
||||
#define RV_DCCM_SADR 0xf0040000
|
||||
#ifndef RV_RESET_VEC
|
||||
#define RV_RESET_VEC 0x80000000
|
||||
#endif
|
||||
#define RV_XLEN 32
|
||||
#define RV_TARGET default
|
||||
#define RV_ICCM_NUM_BANKS 8
|
||||
#define RV_ICCM_BITS 19
|
||||
#define RV_ICCM_BANK_BITS 3
|
||||
#define RV_ICCM_ROWS 16384
|
||||
#define RV_ICCM_OFFSET 0xe000000
|
||||
#define RV_ICCM_REGION 0xe
|
||||
#define RV_ICCM_SADR 0xee000000
|
||||
#define RV_ICCM_RESERVED 0x1000
|
||||
#define RV_ICCM_DATA_CELL ram_16384x39
|
||||
#define RV_ICCM_INDEX_BITS 14
|
||||
#define RV_ICCM_NUM_BANKS_8
|
||||
#define RV_ICCM_SIZE 512
|
||||
#define RV_ICCM_EADR 0xee07ffff
|
||||
#define RV_ICCM_SIZE_512
|
||||
#define RV_EXTERNAL_PROG 0xb0000000
|
||||
#define RV_EXTERNAL_DATA_1 0x00000000
|
||||
#define RV_DEBUG_SB_MEM 0xb0580000
|
||||
#define RV_EXTERNAL_DATA 0xc0580000
|
||||
#define RV_SERIALIO 0xd0580000
|
||||
#ifndef RV_NMI_VEC
|
||||
#define RV_NMI_VEC 0x11110000
|
||||
#endif
|
||||
#define RV_PIC_BITS 15
|
||||
#define RV_PIC_REGION 0xf
|
||||
#define RV_PIC_INT_WORDS 1
|
||||
#define RV_PIC_TOTAL_INT_PLUS1 9
|
||||
#define RV_PIC_MEIP_OFFSET 0x1000
|
||||
#define RV_PIC_BASE_ADDR 0xf00c0000
|
||||
#define RV_PIC_MEIGWCTRL_OFFSET 0x4000
|
||||
#define RV_PIC_MEIPL_OFFSET 0x0000
|
||||
#define RV_PIC_TOTAL_INT 8
|
||||
#define RV_PIC_SIZE 32
|
||||
#define RV_PIC_MEIE_OFFSET 0x2000
|
||||
#define RV_PIC_OFFSET 0xc0000
|
||||
#define RV_PIC_MEIPT_OFFSET 0x3004
|
||||
#define RV_PIC_MPICCFG_OFFSET 0x3000
|
||||
#define RV_PIC_MEIGWCLR_OFFSET 0x5000
|
||||
#define CLOCK_PERIOD 100
|
||||
#define CPU_TOP `RV_TOP.swerv
|
||||
#define TOP tb_top
|
||||
#define RV_BUILD_AHB_LITE 1
|
||||
#define RV_TOP `TOP.rvtop
|
||||
#define DATAWIDTH 64
|
||||
#define RV_STERR_ROLLBACK 0
|
||||
#define RV_EXT_ADDRWIDTH 32
|
||||
#define RV_EXT_DATAWIDTH 64
|
||||
#define SDVT_AHB 1
|
||||
#define RV_LDERR_ROLLBACK 1
|
||||
#define ASSERT_ON
|
|
@ -0,0 +1,11 @@
|
|||
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
|
||||
// This is an automatically generated file by joseph.rahmeh on Tue Jun 4 07:50:46 PDT 2019
|
||||
//
|
||||
// cmd: swerv -snapshot=default -ahb_lite
|
||||
//
|
||||
|
||||
`include "common_defines.vh"
|
||||
`undef ASSERT_ON
|
||||
`undef TEC_RV_ICG
|
||||
`define TEC_RV_ICG CKLNQD12BWP35P140
|
||||
`define PHYSICAL 1
|
|
@ -0,0 +1,566 @@
|
|||
# NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
|
||||
# This is an automatically generated file by joseph.rahmeh on Tue Jun 4 07:50:46 PDT 2019
|
||||
#
|
||||
# cmd: swerv -snapshot=default -ahb_lite
|
||||
#
|
||||
# To use this in a perf script, use 'require $RV_ROOT/configs/config.pl'
|
||||
# Reference the hash via $config{name}..
|
||||
|
||||
|
||||
%config = (
|
||||
'protection' => {
|
||||
'inst_access_mask5' => '0xffffffff',
|
||||
'data_access_enable4' => '0x0',
|
||||
'inst_access_enable3' => '0x0',
|
||||
'inst_access_enable0' => '0x0',
|
||||
'inst_access_mask3' => '0xffffffff',
|
||||
'data_access_enable5' => '0x0',
|
||||
'data_access_mask5' => '0xffffffff',
|
||||
'data_access_addr3' => '0x00000000',
|
||||
'inst_access_enable7' => '0x0',
|
||||
'data_access_addr6' => '0x00000000',
|
||||
'inst_access_mask7' => '0xffffffff',
|
||||
'inst_access_enable6' => '0x0',
|
||||
'inst_access_enable5' => '0x0',
|
||||
'data_access_addr4' => '0x00000000',
|
||||
'data_access_addr7' => '0x00000000',
|
||||
'data_access_mask3' => '0xffffffff',
|
||||
'inst_access_mask4' => '0xffffffff',
|
||||
'data_access_addr1' => '0x00000000',
|
||||
'inst_access_addr4' => '0x00000000',
|
||||
'inst_access_addr3' => '0x00000000',
|
||||
'data_access_enable1' => '0x0',
|
||||
'data_access_addr0' => '0x00000000',
|
||||
'data_access_mask0' => '0xffffffff',
|
||||
'data_access_mask6' => '0xffffffff',
|
||||
'inst_access_addr7' => '0x00000000',
|
||||
'inst_access_mask0' => '0xffffffff',
|
||||
'data_access_addr5' => '0x00000000',
|
||||
'data_access_addr2' => '0x00000000',
|
||||
'data_access_mask4' => '0xffffffff',
|
||||
'data_access_mask1' => '0xffffffff',
|
||||
'inst_access_addr0' => '0x00000000',
|
||||
'inst_access_addr2' => '0x00000000',
|
||||
'data_access_enable0' => '0x0',
|
||||
'data_access_enable2' => '0x0',
|
||||
'data_access_enable7' => '0x0',
|
||||
'inst_access_enable4' => '0x0',
|
||||
'data_access_mask7' => '0xffffffff',
|
||||
'inst_access_addr5' => '0x00000000',
|
||||
'inst_access_enable1' => '0x0',
|
||||
'data_access_mask2' => '0xffffffff',
|
||||
'inst_access_mask6' => '0xffffffff',
|
||||
'data_access_enable3' => '0x0',
|
||||
'inst_access_addr6' => '0x00000000',
|
||||
'inst_access_mask2' => '0xffffffff',
|
||||
'inst_access_enable2' => '0x0',
|
||||
'data_access_enable6' => '0x0',
|
||||
'inst_access_addr1' => '0x00000000',
|
||||
'inst_access_mask1' => '0xffffffff'
|
||||
},
|
||||
'core' => {
|
||||
'dec_instbuf_depth' => '4',
|
||||
'dma_buf_depth' => '4',
|
||||
'lsu_num_nbload' => '8',
|
||||
'lsu_stbuf_depth' => '8',
|
||||
'lsu_num_nbload_width' => '3'
|
||||
},
|
||||
'bus' => {
|
||||
'ifu_bus_tag' => '3',
|
||||
'lsu_bus_tag' => 4,
|
||||
'sb_bus_tag' => '1',
|
||||
'dma_bus_tag' => '1'
|
||||
},
|
||||
'dccm' => {
|
||||
'dccm_width_bits' => 2,
|
||||
'dccm_region' => '0xf',
|
||||
'dccm_reserved' => '0x1000',
|
||||
'dccm_size' => 64,
|
||||
'dccm_data_width' => 32,
|
||||
'dccm_num_banks_8' => '',
|
||||
'dccm_fdata_width' => 39,
|
||||
'dccm_byte_width' => '4',
|
||||
'dccm_data_cell' => 'ram_2048x39',
|
||||
'dccm_enable' => '1',
|
||||
'dccm_bits' => 16,
|
||||
'dccm_offset' => '0x40000',
|
||||
'dccm_ecc_width' => 7,
|
||||
'dccm_size_64' => '',
|
||||
'dccm_rows' => '2048',
|
||||
'dccm_bank_bits' => 3,
|
||||
'dccm_num_banks' => '8',
|
||||
'dccm_index_bits' => 11,
|
||||
'lsu_sb_bits' => 16,
|
||||
'dccm_eadr' => '0xf004ffff',
|
||||
'dccm_sadr' => '0xf0040000'
|
||||
},
|
||||
'reset_vec' => '0x80000000',
|
||||
'retstack' => {
|
||||
'ret_stack_size' => '4'
|
||||
},
|
||||
'triggers' => [
|
||||
{
|
||||
'poke_mask' => [
|
||||
'0x081818c7',
|
||||
'0xffffffff',
|
||||
'0x00000000'
|
||||
],
|
||||
'reset' => [
|
||||
'0x23e00000',
|
||||
'0x00000000',
|
||||
'0x00000000'
|
||||
],
|
||||
'mask' => [
|
||||
'0x081818c7',
|
||||
'0xffffffff',
|
||||
'0x00000000'
|
||||
]
|
||||
},
|
||||
{
|
||||
'poke_mask' => [
|
||||
'0x081818c7',
|
||||
'0xffffffff',
|
||||
'0x00000000'
|
||||
],
|
||||
'reset' => [
|
||||
'0x23e00000',
|
||||
'0x00000000',
|
||||
'0x00000000'
|
||||
],
|
||||
'mask' => [
|
||||
'0x081818c7',
|
||||
'0xffffffff',
|
||||
'0x00000000'
|
||||
]
|
||||
},
|
||||
{
|
||||
'poke_mask' => [
|
||||
'0x081818c7',
|
||||
'0xffffffff',
|
||||
'0x00000000'
|
||||
],
|
||||
'reset' => [
|
||||
'0x23e00000',
|
||||
'0x00000000',
|
||||
'0x00000000'
|
||||
],
|
||||
'mask' => [
|
||||
'0x081818c7',
|
||||
'0xffffffff',
|
||||
'0x00000000'
|
||||
]
|
||||
},
|
||||
{
|
||||
'poke_mask' => [
|
||||
'0x081818c7',
|
||||
'0xffffffff',
|
||||
'0x00000000'
|
||||
],
|
||||
'reset' => [
|
||||
'0x23e00000',
|
||||
'0x00000000',
|
||||
'0x00000000'
|
||||
],
|
||||
'mask' => [
|
||||
'0x081818c7',
|
||||
'0xffffffff',
|
||||
'0x00000000'
|
||||
]
|
||||
}
|
||||
],
|
||||
'xlen' => 32,
|
||||
'verilator' => '',
|
||||
'target' => 'default',
|
||||
'max_mmode_perf_event' => '50',
|
||||
'btb' => {
|
||||
'btb_btag_fold' => 1,
|
||||
'btb_index3_hi' => 9,
|
||||
'btb_index1_lo' => '4',
|
||||
'btb_addr_hi' => 5,
|
||||
'btb_addr_lo' => '4',
|
||||
'btb_index1_hi' => 5,
|
||||
'btb_index2_hi' => 7,
|
||||
'btb_index2_lo' => 6,
|
||||
'btb_array_depth' => 4,
|
||||
'btb_btag_size' => 9,
|
||||
'btb_size' => 32,
|
||||
'btb_index3_lo' => 8
|
||||
},
|
||||
'iccm' => {
|
||||
'iccm_num_banks' => '8',
|
||||
'iccm_bits' => 19,
|
||||
'iccm_bank_bits' => 3,
|
||||
'iccm_rows' => '16384',
|
||||
'iccm_offset' => '0xe000000',
|
||||
'iccm_region' => '0xe',
|
||||
'iccm_sadr' => '0xee000000',
|
||||
'iccm_reserved' => '0x1000',
|
||||
'iccm_data_cell' => 'ram_16384x39',
|
||||
'iccm_index_bits' => 14,
|
||||
'iccm_num_banks_8' => '',
|
||||
'iccm_size' => 512,
|
||||
'iccm_eadr' => '0xee07ffff',
|
||||
'iccm_size_512' => ''
|
||||
},
|
||||
'icache' => {
|
||||
'icache_size' => 16,
|
||||
'icache_tag_high' => 12,
|
||||
'icache_ic_rows' => '256',
|
||||
'icache_taddr_high' => 5,
|
||||
'icache_tag_low' => '6',
|
||||
'icache_tag_cell' => 'ram_64x21',
|
||||
'icache_ic_depth' => 8,
|
||||
'icache_ic_index' => 8,
|
||||
'icache_enable' => '1',
|
||||
'icache_data_cell' => 'ram_256x34',
|
||||
'icache_tag_depth' => 64
|
||||
},
|
||||
'physical' => '1',
|
||||
'memmap' => {
|
||||
'external_prog' => '0xb0000000',
|
||||
'external_data_1' => '0x00000000',
|
||||
'debug_sb_mem' => '0xb0580000',
|
||||
'external_data' => '0xc0580000',
|
||||
'serialio' => '0xd0580000'
|
||||
},
|
||||
'nmi_vec' => '0x11110000',
|
||||
'num_mmode_perf_regs' => '4',
|
||||
'bht' => {
|
||||
'bht_hash_string' => '{ghr[3:2] ^ {ghr[3+1], {4-1-2{1\'b0} } },hashin[5:4]^ghr[2-1:0]}',
|
||||
'bht_addr_hi' => 7,
|
||||
'bht_ghr_range' => '4:0',
|
||||
'bht_ghr_size' => 5,
|
||||
'bht_ghr_pad2' => 'fghr[4:3],2\'b0',
|
||||
'bht_size' => 128,
|
||||
'bht_addr_lo' => '4',
|
||||
'bht_array_depth' => 16,
|
||||
'bht_ghr_pad' => 'fghr[4],3\'b0'
|
||||
},
|
||||
'numiregs' => '32',
|
||||
'even_odd_trigger_chains' => 'true',
|
||||
'pic' => {
|
||||
'pic_bits' => 15,
|
||||
'pic_region' => '0xf',
|
||||
'pic_int_words' => 1,
|
||||
'pic_total_int_plus1' => 9,
|
||||
'pic_meip_offset' => '0x1000',
|
||||
'pic_base_addr' => '0xf00c0000',
|
||||
'pic_meigwctrl_offset' => '0x4000',
|
||||
'pic_meipl_offset' => '0x0000',
|
||||
'pic_total_int' => 8,
|
||||
'pic_size' => 32,
|
||||
'pic_meie_offset' => '0x2000',
|
||||
'pic_offset' => '0xc0000',
|
||||
'pic_meipt_offset' => '0x3004',
|
||||
'pic_mpiccfg_offset' => '0x3000',
|
||||
'pic_meigwclr_offset' => '0x5000'
|
||||
},
|
||||
'testbench' => {
|
||||
'clock_period' => '100',
|
||||
'CPU_TOP' => '`RV_TOP.swerv',
|
||||
'TOP' => 'tb_top',
|
||||
'build_ahb_lite' => '1',
|
||||
'RV_TOP' => '`TOP.rvtop',
|
||||
'datawidth' => '64',
|
||||
'sterr_rollback' => '0',
|
||||
'ext_addrwidth' => '32',
|
||||
'ext_datawidth' => '64',
|
||||
'SDVT_AHB' => '1',
|
||||
'lderr_rollback' => '1',
|
||||
'assert_on' => ''
|
||||
},
|
||||
'tec_rv_icg' => 'clockhdr',
|
||||
'csr' => {
|
||||
'pmpaddr9' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'dicad1' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7ca',
|
||||
'comment' => 'Cache diagnostics.',
|
||||
'debug' => 'true',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x3'
|
||||
},
|
||||
'pmpcfg0' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'mhpmcounter4h' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'dicago' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7cb',
|
||||
'comment' => 'Cache diagnostics.',
|
||||
'debug' => 'true',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'mie' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x40000888'
|
||||
},
|
||||
'misa' => {
|
||||
'reset' => '0x40001104',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'mhpmcounter6h' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'meicpct' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0xbca',
|
||||
'comment' => 'External claim id/priority capture.',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'mimpid' => {
|
||||
'reset' => '0x1',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'mcpc' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7c2',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'mhpmevent4' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'pmpaddr8' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpcfg3' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'marchid' => {
|
||||
'reset' => '0x0000000b',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'pmpaddr5' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'mfdc' => {
|
||||
'reset' => '0x00070000',
|
||||
'number' => '0x7f9',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x000707ff'
|
||||
},
|
||||
'mhpmevent6' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'mvendorid' => {
|
||||
'reset' => '0x45',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'pmpaddr4' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'dcsr' => {
|
||||
'poke_mask' => '0x00008dcc',
|
||||
'reset' => '0x40000003',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x00008c04'
|
||||
},
|
||||
'cycle' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpaddr12' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpaddr3' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'mhpmcounter3h' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'time' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'meicidpl' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0xbcb',
|
||||
'comment' => 'External interrupt claim id priority level.',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xf'
|
||||
},
|
||||
'pmpaddr14' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpaddr13' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpaddr1' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'mhpmcounter6' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'dicad0' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7c9',
|
||||
'comment' => 'Cache diagnostics.',
|
||||
'debug' => 'true',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'meipt' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0xbc9',
|
||||
'comment' => 'External interrupt priority threshold.',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xf'
|
||||
},
|
||||
'pmpaddr15' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'mhpmcounter5' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'pmpcfg1' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpaddr10' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpaddr0' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpcfg2' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpaddr2' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'mpmc' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7c6',
|
||||
'comment' => 'Core pause: Implemented as read only.',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'dmst' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7c4',
|
||||
'comment' => 'Memory synch trigger: Flush caches in debug mode.',
|
||||
'debug' => 'true',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'instret' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'mhpmevent3' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'dicawics' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7c8',
|
||||
'comment' => 'Cache diagnostics.',
|
||||
'debug' => 'true',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0130fffc'
|
||||
},
|
||||
'mip' => {
|
||||
'poke_mask' => '0x40000888',
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x0'
|
||||
},
|
||||
'mhpmcounter5h' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'micect' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7f0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'miccmect' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7f1',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'mhpmevent5' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'mhpmcounter3' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'pmpaddr6' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'pmpaddr11' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'mcgc' => {
|
||||
'poke_mask' => '0x000001ff',
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7f8',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x000001ff'
|
||||
},
|
||||
'mhpmcounter4' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'mdccmect' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0x7f2',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xffffffff'
|
||||
},
|
||||
'pmpaddr7' => {
|
||||
'exists' => 'false'
|
||||
},
|
||||
'meicurpl' => {
|
||||
'reset' => '0x0',
|
||||
'number' => '0xbcc',
|
||||
'comment' => 'External interrupt current priority level.',
|
||||
'exists' => 'true',
|
||||
'mask' => '0xf'
|
||||
},
|
||||
'mstatus' => {
|
||||
'reset' => '0x1800',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x88'
|
||||
},
|
||||
'tselect' => {
|
||||
'reset' => '0x0',
|
||||
'exists' => 'true',
|
||||
'mask' => '0x3'
|
||||
}
|
||||
},
|
||||
'regwidth' => '32',
|
||||
'harts' => 1
|
||||
);
|
||||
1;
|
|
@ -0,0 +1,173 @@
|
|||
// argv=9
|
||||
// TOTAL_INT=9 NUM_LEVELS=4
|
||||
`ifdef RV_PIC_2CYCLE
|
||||
// LEVEL0
|
||||
logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_1;
|
||||
logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_1;
|
||||
for (m=0; m<=(TOTAL_INT)/(2**(1)) ; m++) begin : COMPARE0
|
||||
if ( m == (TOTAL_INT)/(2**(1))) begin
|
||||
assign level_intpend_w_prior_en_1[m+1] = '0 ;
|
||||
assign level_intpend_id_1[m+1] = '0 ;
|
||||
end
|
||||
cmp_and_mux #(
|
||||
.ID_BITS(ID_BITS),
|
||||
.INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l1 (
|
||||
.a_id(level_intpend_id[0][2*m]),
|
||||
.a_priority(level_intpend_w_prior_en[0][2*m]),
|
||||
.b_id(level_intpend_id[0][2*m+1]),
|
||||
.b_priority(level_intpend_w_prior_en[0][2*m+1]),
|
||||
.out_id(level_intpend_id_1[m]),
|
||||
.out_priority(level_intpend_w_prior_en_1[m])) ;
|
||||
|
||||
end
|
||||
|
||||
// LEVEL1
|
||||
logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_2;
|
||||
logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_2;
|
||||
for (m=0; m<=(TOTAL_INT)/(2**(2)) ; m++) begin : COMPARE1
|
||||
if ( m == (TOTAL_INT)/(2**(2))) begin
|
||||
assign level_intpend_w_prior_en_2[m+1] = '0 ;
|
||||
assign level_intpend_id_2[m+1] = '0 ;
|
||||
end
|
||||
cmp_and_mux #(
|
||||
.ID_BITS(ID_BITS),
|
||||
.INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l2 (
|
||||
.a_id(level_intpend_id_1[2*m]),
|
||||
.a_priority(level_intpend_w_prior_en_1[2*m]),
|
||||
.b_id(level_intpend_id_1[2*m+1]),
|
||||
.b_priority(level_intpend_w_prior_en_1[2*m+1]),
|
||||
.out_id(level_intpend_id_2[m]),
|
||||
.out_priority(level_intpend_w_prior_en_2[m])) ;
|
||||
|
||||
end
|
||||
|
||||
for (i=0; i<=TOTAL_INT/2**(NUM_LEVELS/2) ; i++) begin : MIDDLE_FLOPS
|
||||
rvdff #(INTPRIORITY_BITS) level2_intpend_prior_reg (.*, .din (level_intpend_w_prior_en_2[i]), .dout(l2_intpend_w_prior_en_ff[i]), .clk(active_clk));
|
||||
rvdff #(ID_BITS) level2_intpend_id_reg (.*, .din (level_intpend_id_2[i]), .dout(l2_intpend_id_ff[i]), .clk(active_clk));
|
||||
end
|
||||
// LEVEL2
|
||||
logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] levelx_intpend_w_prior_en_3;
|
||||
logic [TOTAL_INT+2:0] [ID_BITS-1:0] levelx_intpend_id_3;
|
||||
for (m=0; m<=(TOTAL_INT)/(2**(3)) ; m++) begin : COMPARE2
|
||||
if ( m == (TOTAL_INT)/(2**(3))) begin
|
||||
assign levelx_intpend_w_prior_en_3[m+1] = '0 ;
|
||||
assign levelx_intpend_id_3[m+1] = '0 ;
|
||||
end
|
||||
cmp_and_mux #(
|
||||
.ID_BITS(ID_BITS),
|
||||
.INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l3 (
|
||||
.a_id(levelx_intpend_id[2][2*m]),
|
||||
.a_priority(levelx_intpend_w_prior_en[2][2*m]),
|
||||
.b_id(levelx_intpend_id[2][2*m+1]),
|
||||
.b_priority(levelx_intpend_w_prior_en[2][2*m+1]),
|
||||
.out_id(levelx_intpend_id_3[m]),
|
||||
.out_priority(levelx_intpend_w_prior_en_3[m])) ;
|
||||
|
||||
end
|
||||
|
||||
// LEVEL3
|
||||
logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] levelx_intpend_w_prior_en_4;
|
||||
logic [TOTAL_INT+2:0] [ID_BITS-1:0] levelx_intpend_id_4;
|
||||
for (m=0; m<=(TOTAL_INT)/(2**(4)) ; m++) begin : COMPARE3
|
||||
if ( m == (TOTAL_INT)/(2**(4))) begin
|
||||
assign levelx_intpend_w_prior_en_4[m+1] = '0 ;
|
||||
assign levelx_intpend_id_4[m+1] = '0 ;
|
||||
end
|
||||
cmp_and_mux #(
|
||||
.ID_BITS(ID_BITS),
|
||||
.INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l4 (
|
||||
.a_id(levelx_intpend_id_3[2*m]),
|
||||
.a_priority(levelx_intpend_w_prior_en_3[2*m]),
|
||||
.b_id(levelx_intpend_id_3[2*m+1]),
|
||||
.b_priority(levelx_intpend_w_prior_en_3[2*m+1]),
|
||||
.out_id(levelx_intpend_id_4[m]),
|
||||
.out_priority(levelx_intpend_w_prior_en_4[m])) ;
|
||||
|
||||
end
|
||||
|
||||
assign claimid_in[ID_BITS-1:0] = levelx_intpend_id_4[0] ; // This is the last level output
|
||||
assign selected_int_priority[INTPRIORITY_BITS-1:0] = levelx_intpend_w_prior_en_4[0] ;
|
||||
`else
|
||||
// LEVEL0
|
||||
logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_1;
|
||||
logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_1;
|
||||
for (m=0; m<=(TOTAL_INT)/(2**(1)) ; m++) begin : COMPARE0
|
||||
if ( m == (TOTAL_INT)/(2**(1))) begin
|
||||
assign level_intpend_w_prior_en_1[m+1] = '0 ;
|
||||
assign level_intpend_id_1[m+1] = '0 ;
|
||||
end
|
||||
cmp_and_mux #(
|
||||
.ID_BITS(ID_BITS),
|
||||
.INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l1 (
|
||||
.a_id(level_intpend_id[0][2*m]),
|
||||
.a_priority(level_intpend_w_prior_en[0][2*m]),
|
||||
.b_id(level_intpend_id[0][2*m+1]),
|
||||
.b_priority(level_intpend_w_prior_en[0][2*m+1]),
|
||||
.out_id(level_intpend_id_1[m]),
|
||||
.out_priority(level_intpend_w_prior_en_1[m])) ;
|
||||
|
||||
end
|
||||
|
||||
// LEVEL1
|
||||
logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_2;
|
||||
logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_2;
|
||||
for (m=0; m<=(TOTAL_INT)/(2**(2)) ; m++) begin : COMPARE1
|
||||
if ( m == (TOTAL_INT)/(2**(2))) begin
|
||||
assign level_intpend_w_prior_en_2[m+1] = '0 ;
|
||||
assign level_intpend_id_2[m+1] = '0 ;
|
||||
end
|
||||
cmp_and_mux #(
|
||||
.ID_BITS(ID_BITS),
|
||||
.INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l2 (
|
||||
.a_id(level_intpend_id_1[2*m]),
|
||||
.a_priority(level_intpend_w_prior_en_1[2*m]),
|
||||
.b_id(level_intpend_id_1[2*m+1]),
|
||||
.b_priority(level_intpend_w_prior_en_1[2*m+1]),
|
||||
.out_id(level_intpend_id_2[m]),
|
||||
.out_priority(level_intpend_w_prior_en_2[m])) ;
|
||||
|
||||
end
|
||||
|
||||
// LEVEL2
|
||||
logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_3;
|
||||
logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_3;
|
||||
for (m=0; m<=(TOTAL_INT)/(2**(3)) ; m++) begin : COMPARE2
|
||||
if ( m == (TOTAL_INT)/(2**(3))) begin
|
||||
assign level_intpend_w_prior_en_3[m+1] = '0 ;
|
||||
assign level_intpend_id_3[m+1] = '0 ;
|
||||
end
|
||||
cmp_and_mux #(
|
||||
.ID_BITS(ID_BITS),
|
||||
.INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l3 (
|
||||
.a_id(level_intpend_id_2[2*m]),
|
||||
.a_priority(level_intpend_w_prior_en_2[2*m]),
|
||||
.b_id(level_intpend_id_2[2*m+1]),
|
||||
.b_priority(level_intpend_w_prior_en_2[2*m+1]),
|
||||
.out_id(level_intpend_id_3[m]),
|
||||
.out_priority(level_intpend_w_prior_en_3[m])) ;
|
||||
|
||||
end
|
||||
|
||||
// LEVEL3
|
||||
logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_4;
|
||||
logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_4;
|
||||
for (m=0; m<=(TOTAL_INT)/(2**(4)) ; m++) begin : COMPARE3
|
||||
if ( m == (TOTAL_INT)/(2**(4))) begin
|
||||
assign level_intpend_w_prior_en_4[m+1] = '0 ;
|
||||
assign level_intpend_id_4[m+1] = '0 ;
|
||||
end
|
||||
cmp_and_mux #(
|
||||
.ID_BITS(ID_BITS),
|
||||
.INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l4 (
|
||||
.a_id(level_intpend_id_3[2*m]),
|
||||
.a_priority(level_intpend_w_prior_en_3[2*m]),
|
||||
.b_id(level_intpend_id_3[2*m+1]),
|
||||
.b_priority(level_intpend_w_prior_en_3[2*m+1]),
|
||||
.out_id(level_intpend_id_4[m]),
|
||||
.out_priority(level_intpend_w_prior_en_4[m])) ;
|
||||
|
||||
end
|
||||
|
||||
assign claimid_in[ID_BITS-1:0] = level_intpend_id_4[0] ; // This is the last level output
|
||||
assign selected_int_priority[INTPRIORITY_BITS-1:0] = level_intpend_w_prior_en_4[0] ;
|
||||
`endif
|
|
@ -0,0 +1,31 @@
|
|||
// mask[3:0] = { 4'b1000 - 30b mask,4'b0100 - 31b mask, 4'b0010 - 28b mask, 4'b0001 - 32b mask }
|
||||
always_comb begin
|
||||
case (address[14:0])
|
||||
15'b011000000000000 : mask[3:0] = 4'b0100;
|
||||
15'b100000000000100 : mask[3:0] = 4'b1000;
|
||||
15'b100000000001000 : mask[3:0] = 4'b1000;
|
||||
15'b100000000001100 : mask[3:0] = 4'b1000;
|
||||
15'b100000000010000 : mask[3:0] = 4'b1000;
|
||||
15'b100000000010100 : mask[3:0] = 4'b1000;
|
||||
15'b100000000011000 : mask[3:0] = 4'b1000;
|
||||
15'b100000000011100 : mask[3:0] = 4'b1000;
|
||||
15'b100000000100000 : mask[3:0] = 4'b1000;
|
||||
15'b010000000000100 : mask[3:0] = 4'b0100;
|
||||
15'b010000000001000 : mask[3:0] = 4'b0100;
|
||||
15'b010000000001100 : mask[3:0] = 4'b0100;
|
||||
15'b010000000010000 : mask[3:0] = 4'b0100;
|
||||
15'b010000000010100 : mask[3:0] = 4'b0100;
|
||||
15'b010000000011000 : mask[3:0] = 4'b0100;
|
||||
15'b010000000011100 : mask[3:0] = 4'b0100;
|
||||
15'b010000000100000 : mask[3:0] = 4'b0100;
|
||||
15'b000000000000100 : mask[3:0] = 4'b0010;
|
||||
15'b000000000001000 : mask[3:0] = 4'b0010;
|
||||
15'b000000000001100 : mask[3:0] = 4'b0010;
|
||||
15'b000000000010000 : mask[3:0] = 4'b0010;
|
||||
15'b000000000010100 : mask[3:0] = 4'b0010;
|
||||
15'b000000000011000 : mask[3:0] = 4'b0010;
|
||||
15'b000000000011100 : mask[3:0] = 4'b0010;
|
||||
15'b000000000100000 : mask[3:0] = 4'b0010;
|
||||
default : mask[3:0] = 4'b0001;
|
||||
endcase
|
||||
end
|
|
@ -0,0 +1,395 @@
|
|||
{
|
||||
"memmap" : {
|
||||
"cosnoleio" : "0xd0580000"
|
||||
},
|
||||
"nmi_vec" : "0x11110000",
|
||||
"dccm" : {
|
||||
"region" : "0xf",
|
||||
"offset" : "0x40000",
|
||||
"size" : "0x10000"
|
||||
},
|
||||
"num_mmode_perf_regs" : "4",
|
||||
"load_error_rollback" : "1",
|
||||
"reset_vec" : "0x80000000",
|
||||
"triggers" : [
|
||||
{
|
||||
"poke_mask" : [
|
||||
"0x081818c7",
|
||||
"0xffffffff",
|
||||
"0x00000000"
|
||||
],
|
||||
"reset" : [
|
||||
"0x23e00000",
|
||||
"0x00000000",
|
||||
"0x00000000"
|
||||
],
|
||||
"mask" : [
|
||||
"0x081818c7",
|
||||
"0xffffffff",
|
||||
"0x00000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"poke_mask" : [
|
||||
"0x081818c7",
|
||||
"0xffffffff",
|
||||
"0x00000000"
|
||||
],
|
||||
"reset" : [
|
||||
"0x23e00000",
|
||||
"0x00000000",
|
||||
"0x00000000"
|
||||
],
|
||||
"mask" : [
|
||||
"0x081818c7",
|
||||
"0xffffffff",
|
||||
"0x00000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"poke_mask" : [
|
||||
"0x081818c7",
|
||||
"0xffffffff",
|
||||
"0x00000000"
|
||||
],
|
||||
"reset" : [
|
||||
"0x23e00000",
|
||||
"0x00000000",
|
||||
"0x00000000"
|
||||
],
|
||||
"mask" : [
|
||||
"0x081818c7",
|
||||
"0xffffffff",
|
||||
"0x00000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"poke_mask" : [
|
||||
"0x081818c7",
|
||||
"0xffffffff",
|
||||
"0x00000000"
|
||||
],
|
||||
"reset" : [
|
||||
"0x23e00000",
|
||||
"0x00000000",
|
||||
"0x00000000"
|
||||
],
|
||||
"mask" : [
|
||||
"0x081818c7",
|
||||
"0xffffffff",
|
||||
"0x00000000"
|
||||
]
|
||||
}
|
||||
],
|
||||
"xlen" : 32,
|
||||
"pic" : {
|
||||
"meigwctrl_offset" : "0x4000",
|
||||
"region" : "0xf",
|
||||
"total_int" : 8,
|
||||
"size" : "0x8000",
|
||||
"mpiccfg_offset" : "0x3000",
|
||||
"meigwclr_offset" : "0x5000",
|
||||
"total_int_plus1" : 9,
|
||||
"meipt_offset" : "0x3004",
|
||||
"int_words" : 1,
|
||||
"meie_offset" : "0x2000",
|
||||
"bits" : 15,
|
||||
"meip_offset" : "0x1000",
|
||||
"meipl_offset" : "0x0000",
|
||||
"offset" : "0xc0000"
|
||||
},
|
||||
"store_error_rollback" : "0",
|
||||
"even_odd_trigger_chains" : "true",
|
||||
"max_mmode_perf_event" : "50",
|
||||
"csr" : {
|
||||
"pmpaddr9" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"dicad1" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7ca",
|
||||
"comment" : "Cache diagnostics.",
|
||||
"debug" : "true",
|
||||
"exists" : "true",
|
||||
"mask" : "0x3"
|
||||
},
|
||||
"pmpcfg0" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"mhpmcounter4h" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"dicago" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7cb",
|
||||
"comment" : "Cache diagnostics.",
|
||||
"debug" : "true",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"mie" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0x40000888"
|
||||
},
|
||||
"misa" : {
|
||||
"reset" : "0x40001104",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"mhpmcounter6h" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"meicpct" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0xbca",
|
||||
"comment" : "External claim id/priority capture.",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"mimpid" : {
|
||||
"reset" : "0x1",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"mcpc" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7c2",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"mhpmevent4" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"pmpaddr8" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpcfg3" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"marchid" : {
|
||||
"reset" : "0x0000000b",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"pmpaddr5" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"mfdc" : {
|
||||
"reset" : "0x00070000",
|
||||
"number" : "0x7f9",
|
||||
"exists" : "true",
|
||||
"mask" : "0x000707ff"
|
||||
},
|
||||
"mhpmevent6" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"mvendorid" : {
|
||||
"reset" : "0x45",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"pmpaddr4" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"dcsr" : {
|
||||
"poke_mask" : "0x00008dcc",
|
||||
"reset" : "0x40000003",
|
||||
"exists" : "true",
|
||||
"mask" : "0x00008c04"
|
||||
},
|
||||
"cycle" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpaddr12" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpaddr3" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"mhpmcounter3h" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"time" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"meicidpl" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0xbcb",
|
||||
"comment" : "External interrupt claim id priority level.",
|
||||
"exists" : "true",
|
||||
"mask" : "0xf"
|
||||
},
|
||||
"pmpaddr14" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpaddr13" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpaddr1" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"mhpmcounter6" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"dicad0" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7c9",
|
||||
"comment" : "Cache diagnostics.",
|
||||
"debug" : "true",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"meipt" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0xbc9",
|
||||
"comment" : "External interrupt priority threshold.",
|
||||
"exists" : "true",
|
||||
"mask" : "0xf"
|
||||
},
|
||||
"pmpaddr15" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"mhpmcounter5" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"pmpcfg1" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpaddr10" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpaddr0" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpcfg2" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpaddr2" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"mpmc" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7c6",
|
||||
"comment" : "Core pause: Implemented as read only.",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"dmst" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7c4",
|
||||
"comment" : "Memory synch trigger: Flush caches in debug mode.",
|
||||
"debug" : "true",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"instret" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"mhpmevent3" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"dicawics" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7c8",
|
||||
"comment" : "Cache diagnostics.",
|
||||
"debug" : "true",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0130fffc"
|
||||
},
|
||||
"mip" : {
|
||||
"poke_mask" : "0x40000888",
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0x0"
|
||||
},
|
||||
"mhpmcounter5h" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"micect" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7f0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"miccmect" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7f1",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"mhpmevent5" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"mhpmcounter3" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"pmpaddr6" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"pmpaddr11" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"mcgc" : {
|
||||
"poke_mask" : "0x000001ff",
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7f8",
|
||||
"exists" : "true",
|
||||
"mask" : "0x000001ff"
|
||||
},
|
||||
"mhpmcounter4" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"mdccmect" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0x7f2",
|
||||
"exists" : "true",
|
||||
"mask" : "0xffffffff"
|
||||
},
|
||||
"pmpaddr7" : {
|
||||
"exists" : "false"
|
||||
},
|
||||
"meicurpl" : {
|
||||
"reset" : "0x0",
|
||||
"number" : "0xbcc",
|
||||
"comment" : "External interrupt current priority level.",
|
||||
"exists" : "true",
|
||||
"mask" : "0xf"
|
||||
},
|
||||
"mstatus" : {
|
||||
"reset" : "0x1800",
|
||||
"exists" : "true",
|
||||
"mask" : "0x88"
|
||||
},
|
||||
"tselect" : {
|
||||
"reset" : "0x0",
|
||||
"exists" : "true",
|
||||
"mask" : "0x3"
|
||||
}
|
||||
},
|
||||
"harts" : 1
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,626 @@
|
|||
// 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$
|
||||
//
|
||||
// Function: Top level SWERV core file to control the debug mode
|
||||
// Comments: Responsible to put the rest of the core in quiesce mode,
|
||||
// Send the commands/address. sends WrData and Recieve read Data.
|
||||
// And then Resume the core to do the normal mode
|
||||
// Author :
|
||||
//********************************************************************************
|
||||
module dbg (
|
||||
// outputs to the core for command and data interface
|
||||
output logic [31:0] dbg_cmd_addr,
|
||||
output logic [31:0] dbg_cmd_wrdata,
|
||||
output logic dbg_cmd_valid,
|
||||
output logic dbg_cmd_write, // 1: write command, 0: read_command
|
||||
output logic [1:0] dbg_cmd_type, // 0:gpr 1:csr 2: memory
|
||||
output logic [1:0] dbg_cmd_size, // size of the abstract mem access debug command
|
||||
output logic dbg_core_rst_l, // core reset from dm
|
||||
|
||||
// inputs back from the core/dec
|
||||
input logic [31:0] core_dbg_rddata,
|
||||
input logic core_dbg_cmd_done, // This will be treated like a valid signal
|
||||
input logic core_dbg_cmd_fail, // Exception during command run
|
||||
|
||||
// Signals to dma to get a bubble
|
||||
output logic dbg_dma_bubble, // Debug needs a bubble to send a valid
|
||||
input logic dma_dbg_ready, // DMA is ready to accept debug request
|
||||
|
||||
// interface with the rest of the core to halt/resume handshaking
|
||||
output logic dbg_halt_req, // This is a pulse
|
||||
output logic dbg_resume_req, // Debug sends a resume requests. Pulse
|
||||
input logic dec_tlu_debug_mode, // Core is in debug mode
|
||||
input logic dec_tlu_dbg_halted, // The core has finished the queiscing sequence. Core is halted now
|
||||
input logic dec_tlu_mpc_halted_only, // Only halted due to MPC
|
||||
input logic dec_tlu_resume_ack, // core sends back an ack for the resume (pulse)
|
||||
|
||||
// inputs from the JTAG
|
||||
input logic dmi_reg_en, // read or write
|
||||
input logic [6:0] dmi_reg_addr, // address of DM register
|
||||
input logic dmi_reg_wr_en, // write instruction
|
||||
input logic [31:0] dmi_reg_wdata, // write data
|
||||
// output
|
||||
output logic [31:0] dmi_reg_rdata, // read data
|
||||
// output logic dmi_reg_ack,
|
||||
|
||||
// AXI signals
|
||||
// AXI Write Channels
|
||||
output logic sb_axi_awvalid,
|
||||
input logic sb_axi_awready,
|
||||
output logic [`RV_SB_BUS_TAG-1:0] sb_axi_awid,
|
||||
output logic [31:0] sb_axi_awaddr,
|
||||
output logic [3:0] sb_axi_awregion,
|
||||
output logic [7:0] sb_axi_awlen,
|
||||
output logic [2:0] sb_axi_awsize,
|
||||
output logic [1:0] sb_axi_awburst,
|
||||
output logic sb_axi_awlock,
|
||||
output logic [3:0] sb_axi_awcache,
|
||||
output logic [2:0] sb_axi_awprot,
|
||||
output logic [3:0] sb_axi_awqos,
|
||||
|
||||
output logic sb_axi_wvalid,
|
||||
input logic sb_axi_wready,
|
||||
output logic [63:0] sb_axi_wdata,
|
||||
output logic [7:0] sb_axi_wstrb,
|
||||
output logic sb_axi_wlast,
|
||||
|
||||
input logic sb_axi_bvalid,
|
||||
output logic sb_axi_bready,
|
||||
input logic [1:0] sb_axi_bresp,
|
||||
input logic [`RV_SB_BUS_TAG-1:0] sb_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic sb_axi_arvalid,
|
||||
input logic sb_axi_arready,
|
||||
output logic [`RV_SB_BUS_TAG-1:0] sb_axi_arid,
|
||||
output logic [31:0] sb_axi_araddr,
|
||||
output logic [3:0] sb_axi_arregion,
|
||||
output logic [7:0] sb_axi_arlen,
|
||||
output logic [2:0] sb_axi_arsize,
|
||||
output logic [1:0] sb_axi_arburst,
|
||||
output logic sb_axi_arlock,
|
||||
output logic [3:0] sb_axi_arcache,
|
||||
output logic [2:0] sb_axi_arprot,
|
||||
output logic [3:0] sb_axi_arqos,
|
||||
|
||||
input logic sb_axi_rvalid,
|
||||
output logic sb_axi_rready,
|
||||
input logic [`RV_SB_BUS_TAG-1:0] sb_axi_rid,
|
||||
input logic [63:0] sb_axi_rdata,
|
||||
input logic [1:0] sb_axi_rresp,
|
||||
input logic sb_axi_rlast,
|
||||
|
||||
input logic dbg_bus_clk_en,
|
||||
|
||||
// general inputs
|
||||
input logic clk,
|
||||
input logic free_clk,
|
||||
input logic rst_l,
|
||||
input logic clk_override,
|
||||
input logic scan_mode
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
typedef enum logic [2:0] {IDLE=3'b000, HALTING=3'b001, HALTED=3'b010, CMD_START=3'b011, CMD_WAIT=3'b100, CMD_DONE=3'b101, RESUMING=3'b110} state_t;
|
||||
typedef enum logic [3:0] {SBIDLE=4'b0, WAIT=4'b1, CMD_RD=4'b10, CMD_WR=4'b11, CMD_WR_ADDR=4'b100, CMD_WR_DATA=4'b101, RSP_RD=4'b110, RSP_WR=4'b111, DONE=4'b1000} sb_state_t;
|
||||
|
||||
state_t dbg_state;
|
||||
state_t dbg_nxtstate;
|
||||
logic dbg_state_en;
|
||||
// these are the registers that the debug module implements
|
||||
logic [31:0] dmstatus_reg; // [26:24]-dmerr, [17:16]-resume ack, [9:8]-halted, [3:0]-version
|
||||
logic [31:0] dmcontrol_reg; // dmcontrol register has only 6 bits implemented. 31: haltreq, 30: resumereq, 29: haltreset, 28: ackhavereset, 1: ndmreset, 0: dmactive.
|
||||
logic [31:0] command_reg;
|
||||
logic [31:0] abstractcs_reg; // bits implemted are [12] - busy and [10:8]= command error
|
||||
logic [31:0] haltsum0_reg;
|
||||
logic [31:0] data0_reg;
|
||||
logic [31:0] data1_reg;
|
||||
|
||||
// data 0
|
||||
logic [31:0] data0_din;
|
||||
logic data0_reg_wren, data0_reg_wren0, data0_reg_wren1;
|
||||
// data 1
|
||||
logic [31:0] data1_din;
|
||||
logic data1_reg_wren, data1_reg_wren0, data1_reg_wren1;
|
||||
// abstractcs
|
||||
logic abstractcs_busy_wren;
|
||||
logic abstractcs_busy_din;
|
||||
logic [2:0] abstractcs_error_din;
|
||||
logic abstractcs_error_sel0, abstractcs_error_sel1, abstractcs_error_sel2, abstractcs_error_sel3, abstractcs_error_sel4, abstractcs_error_sel5;
|
||||
logic abstractcs_error_selor;
|
||||
// dmstatus
|
||||
//logic dmstatus_wren;
|
||||
logic dmstatus_dmerr_wren;
|
||||
logic dmstatus_resumeack_wren;
|
||||
logic dmstatus_resumeack_din;
|
||||
logic dmstatus_havereset_wren;
|
||||
logic dmstatus_havereset_rst;
|
||||
logic dmstatus_resumeack;
|
||||
logic dmstatus_halted;
|
||||
logic dmstatus_havereset;
|
||||
|
||||
// dmcontrol
|
||||
logic dmcontrol_wren, dmcontrol_wren_Q;
|
||||
// command
|
||||
logic command_wren;
|
||||
// needed to send the read data back for dmi reads
|
||||
logic [31:0] dmi_reg_rdata_din;
|
||||
|
||||
sb_state_t sb_state;
|
||||
sb_state_t sb_nxtstate;
|
||||
logic sb_state_en;
|
||||
|
||||
//System bus section
|
||||
logic sbcs_wren;
|
||||
logic sbcs_sbbusy_wren;
|
||||
logic sbcs_sbbusy_din;
|
||||
logic sbcs_sbbusyerror_wren;
|
||||
logic sbcs_sbbusyerror_din;
|
||||
|
||||
logic sbcs_sberror_wren;
|
||||
logic [2:0] sbcs_sberror_din;
|
||||
logic sbcs_unaligned;
|
||||
logic sbcs_illegal_size;
|
||||
|
||||
// data
|
||||
logic sbdata0_reg_wren0;
|
||||
logic sbdata0_reg_wren1;
|
||||
logic sbdata0_reg_wren;
|
||||
logic [31:0] sbdata0_din;
|
||||
|
||||
logic sbdata1_reg_wren0;
|
||||
logic sbdata1_reg_wren1;
|
||||
logic sbdata1_reg_wren;
|
||||
logic [31:0] sbdata1_din;
|
||||
|
||||
logic sbaddress0_reg_wren0;
|
||||
logic sbaddress0_reg_wren1;
|
||||
logic sbaddress0_reg_wren;
|
||||
logic [31:0] sbaddress0_reg_din;
|
||||
logic [3:0] sbaddress0_incr;
|
||||
logic sbreadonaddr_access;
|
||||
logic sbreadondata_access;
|
||||
logic sbdata0wr_access;
|
||||
|
||||
logic sb_axi_awvalid_q, sb_axi_awready_q;
|
||||
logic sb_axi_wvalid_q, sb_axi_wready_q;
|
||||
logic sb_axi_arvalid_q, sb_axi_arready_q;
|
||||
logic sb_axi_bvalid_q, sb_axi_bready_q;
|
||||
logic sb_axi_rvalid_q, sb_axi_rready_q;
|
||||
logic [1:0] sb_axi_bresp_q, sb_axi_rresp_q;
|
||||
logic [63:0] sb_axi_rdata_q;
|
||||
|
||||
logic [63:0] sb_bus_rdata;
|
||||
|
||||
//registers
|
||||
logic [31:0] sbcs_reg;
|
||||
logic [31:0] sbaddress0_reg;
|
||||
logic [31:0] sbdata0_reg;
|
||||
logic [31:0] sbdata1_reg;
|
||||
|
||||
logic dbg_dm_rst_l;
|
||||
|
||||
//clken
|
||||
logic dbg_free_clken;
|
||||
logic dbg_free_clk;
|
||||
|
||||
logic sb_free_clken;
|
||||
logic sb_free_clk;
|
||||
|
||||
logic bus_clken;
|
||||
logic bus_clk;
|
||||
|
||||
// clocking
|
||||
// used for the abstract commands.
|
||||
assign dbg_free_clken = dmi_reg_en | (dbg_state != IDLE) | dbg_state_en | dec_tlu_dbg_halted | clk_override;
|
||||
|
||||
// used for the system bus
|
||||
assign sb_free_clken = dmi_reg_en | sb_state_en | (sb_state != SBIDLE) | clk_override;
|
||||
assign bus_clken = (sb_axi_awvalid | sb_axi_wvalid | sb_axi_arvalid | sb_axi_bvalid | sb_axi_rvalid | clk_override) & dbg_bus_clk_en;
|
||||
|
||||
rvclkhdr dbg_free_cgc (.en(dbg_free_clken), .l1clk(dbg_free_clk), .*);
|
||||
rvclkhdr sb_free_cgc (.en(sb_free_clken), .l1clk(sb_free_clk), .*);
|
||||
rvclkhdr bus_cgc (.en(bus_clken), .l1clk(bus_clk), .*);
|
||||
|
||||
// end clocking section
|
||||
|
||||
// Reset logic
|
||||
assign dbg_dm_rst_l = rst_l & (dmcontrol_reg[0] | scan_mode);
|
||||
assign dbg_core_rst_l = ~dmcontrol_reg[1];
|
||||
|
||||
// system bus register
|
||||
// sbcs[31:29], sbcs - [22]:sbbusyerror, [21]: sbbusy, [20]:sbreadonaddr, [19:17]:sbaccess, [16]:sbautoincrement, [15]:sbreadondata, [14:12]:sberror, sbsize=32, 128=0, 64/32/16/8 are legal
|
||||
assign sbcs_reg[31:29] = 3'b1;
|
||||
assign sbcs_reg[28:23] = '0;
|
||||
assign sbcs_reg[11:5] = 7'h20;
|
||||
assign sbcs_reg[4:0] = 5'b01111;
|
||||
assign sbcs_wren = (dmi_reg_addr == 7'h38) & dmi_reg_en & dmi_reg_wr_en & (sb_state == SBIDLE); // & (sbcs_reg[14:12] == 3'b000);
|
||||
assign sbcs_sbbusyerror_wren = (sbcs_wren & dmi_reg_wdata[22]) |
|
||||
((sb_state != SBIDLE) & dmi_reg_en & ((dmi_reg_addr == 7'h39) | (dmi_reg_addr == 7'h3c) | (dmi_reg_addr == 7'h3d)));
|
||||
assign sbcs_sbbusyerror_din = ~(sbcs_wren & dmi_reg_wdata[22]); // Clear when writing one
|
||||
|
||||
rvdffs #(1) sbcs_sbbusyerror_reg (.din(sbcs_sbbusyerror_din), .dout(sbcs_reg[22]), .en(sbcs_sbbusyerror_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
|
||||
rvdffs #(1) sbcs_sbbusy_reg (.din(sbcs_sbbusy_din), .dout(sbcs_reg[21]), .en(sbcs_sbbusy_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
|
||||
rvdffs #(1) sbcs_sbreadonaddr_reg (.din(dmi_reg_wdata[20]), .dout(sbcs_reg[20]), .en(sbcs_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
|
||||
rvdffs #(5) sbcs_misc_reg (.din(dmi_reg_wdata[19:15]), .dout(sbcs_reg[19:15]), .en(sbcs_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
|
||||
rvdffs #(3) sbcs_error_reg (.din(sbcs_sberror_din[2:0]), .dout(sbcs_reg[14:12]), .en(sbcs_sberror_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
|
||||
|
||||
assign sbcs_unaligned = ((sbcs_reg[19:17] == 3'b001) & sbaddress0_reg[0]) |
|
||||
((sbcs_reg[19:17] == 3'b010) & (|sbaddress0_reg[1:0])) |
|
||||
((sbcs_reg[19:17] == 3'b011) & (|sbaddress0_reg[2:0]));
|
||||
|
||||
assign sbcs_illegal_size = sbcs_reg[19]; // Anything bigger than 64 bits is illegal
|
||||
|
||||
assign sbaddress0_incr[3:0] = ({4{(sbcs_reg[19:17] == 3'b000)}} & 4'b0001) |
|
||||
({4{(sbcs_reg[19:17] == 3'b001)}} & 4'b0010) |
|
||||
({4{(sbcs_reg[19:17] == 3'b010)}} & 4'b0100) |
|
||||
({4{(sbcs_reg[19:17] == 3'b100)}} & 4'b1000);
|
||||
|
||||
// sbdata
|
||||
//assign sbdata0_reg_wren0 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 32'h3c);
|
||||
assign sbdata0_reg_wren0 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h3c); // write data only when single read is 0
|
||||
assign sbdata0_reg_wren1 = (sb_state == RSP_RD) & sb_state_en & ~sbcs_sberror_wren;
|
||||
assign sbdata0_reg_wren = sbdata0_reg_wren0 | sbdata0_reg_wren1;
|
||||
|
||||
assign sbdata1_reg_wren0 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h3d); // write data only when single read is 0;
|
||||
assign sbdata1_reg_wren1 = (sb_state == RSP_RD) & sb_state_en & ~sbcs_sberror_wren;
|
||||
assign sbdata1_reg_wren = sbdata1_reg_wren0 | sbdata1_reg_wren1;
|
||||
|
||||
assign sbdata0_din[31:0] = ({32{sbdata0_reg_wren0}} & dmi_reg_wdata[31:0]) |
|
||||
({32{sbdata0_reg_wren1}} & sb_bus_rdata[31:0]);
|
||||
assign sbdata1_din[31:0] = ({32{sbdata1_reg_wren0}} & dmi_reg_wdata[31:0]) |
|
||||
({32{sbdata1_reg_wren1}} & sb_bus_rdata[63:32]);
|
||||
|
||||
rvdffe #(32) dbg_sbdata0_reg (.*, .din(sbdata0_din[31:0]), .dout(sbdata0_reg[31:0]), .en(sbdata0_reg_wren), .rst_l(dbg_dm_rst_l));
|
||||
rvdffe #(32) dbg_sbdata1_reg (.*, .din(sbdata1_din[31:0]), .dout(sbdata1_reg[31:0]), .en(sbdata1_reg_wren), .rst_l(dbg_dm_rst_l));
|
||||
|
||||
// sbaddress
|
||||
assign sbaddress0_reg_wren0 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h39);
|
||||
assign sbaddress0_reg_wren = sbaddress0_reg_wren0 | sbaddress0_reg_wren1;
|
||||
assign sbaddress0_reg_din[31:0]= ({32{sbaddress0_reg_wren0}} & dmi_reg_wdata[31:0]) |
|
||||
({32{sbaddress0_reg_wren1}} & (sbaddress0_reg[31:0] + {28'b0,sbaddress0_incr[3:0]}));
|
||||
rvdffe #(32) dbg_sbaddress0_reg (.*, .din(sbaddress0_reg_din[31:0]), .dout(sbaddress0_reg[31:0]), .en(sbaddress0_reg_wren), .rst_l(dbg_dm_rst_l));
|
||||
|
||||
assign sbreadonaddr_access = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h39) & sbcs_reg[20]; // if readonaddr is set the next command will start upon writing of addr0
|
||||
assign sbreadondata_access = dmi_reg_en & ~dmi_reg_wr_en & (dmi_reg_addr == 7'h3c) & sbcs_reg[15]; // if readondata is set the next command will start upon reading of data0
|
||||
assign sbdata0wr_access = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h3c); // write to sbdata0 will start write command to system bus
|
||||
|
||||
// memory mapped registers
|
||||
// dmcontrol register has only 6 bits implemented. 31: haltreq, 30: resumereq, 29: haltreset, 28: ackhavereset, 1: ndmreset, 0: dmactive.
|
||||
// rest all the bits are zeroed out
|
||||
// dmactive flop is reset based on core rst_l, all other flops use dm_rst_l
|
||||
assign dmcontrol_wren = (dmi_reg_addr == 7'h10) & dmi_reg_en & dmi_reg_wr_en;
|
||||
assign dmcontrol_reg[27:2] = '0;
|
||||
rvdffs #(5) dmcontrolff (.din({dmi_reg_wdata[31:28],dmi_reg_wdata[1]}), .dout({dmcontrol_reg[31:28], dmcontrol_reg[1]}), .en(dmcontrol_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
rvdffs #(1) dmcontrol_dmactive_ff (.din(dmi_reg_wdata[0]), .dout(dmcontrol_reg[0]), .en(dmcontrol_wren), .rst_l(rst_l), .clk(dbg_free_clk));
|
||||
rvdff #(1) dmcontrol_wrenff(.din(dmcontrol_wren), .dout(dmcontrol_wren_Q), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
|
||||
// dmstatus register bits that are implemented
|
||||
// [19:18]-havereset,[17:16]-resume ack, [9:8]-halted, [3:0]-version
|
||||
// rest all the bits are zeroed out
|
||||
//assign dmstatus_wren = (dmi_reg_addr == 32'h11) & dmi_reg_en;
|
||||
assign dmstatus_reg[31:20] = '0;
|
||||
assign dmstatus_reg[19:18] = {2{dmstatus_havereset}};
|
||||
assign dmstatus_reg[15:10] = '0;
|
||||
assign dmstatus_reg[7] = '1;
|
||||
assign dmstatus_reg[6:4] = '0;
|
||||
assign dmstatus_reg[17:16] = {2{dmstatus_resumeack}};
|
||||
assign dmstatus_reg[9:8] = {2{dmstatus_halted}};
|
||||
assign dmstatus_reg[3:0] = 4'h2;
|
||||
|
||||
assign dmstatus_resumeack_wren = ((dbg_state == RESUMING) & dec_tlu_resume_ack) | (dmstatus_resumeack & ~dmcontrol_reg[30]);
|
||||
assign dmstatus_resumeack_din = (dbg_state == RESUMING) & dec_tlu_resume_ack;
|
||||
|
||||
assign dmstatus_havereset_wren = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[1] & dmi_reg_en & dmi_reg_wr_en;
|
||||
assign dmstatus_havereset_rst = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[28] & dmi_reg_en & dmi_reg_wr_en;
|
||||
|
||||
rvdffs #(1) dmstatus_resumeack_reg (.din(dmstatus_resumeack_din), .dout(dmstatus_resumeack), .en(dmstatus_resumeack_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
rvdff #(1) dmstatus_halted_reg (.din(dec_tlu_dbg_halted & ~dec_tlu_mpc_halted_only), .dout(dmstatus_halted), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
rvdffsc #(1) dmstatus_havereset_reg (.din(1'b1), .dout(dmstatus_havereset), .en(dmstatus_havereset_wren), .clear(dmstatus_havereset_rst), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
|
||||
// haltsum0 register
|
||||
assign haltsum0_reg[31:1] = '0;
|
||||
assign haltsum0_reg[0] = dmstatus_halted;
|
||||
|
||||
// abstractcs register
|
||||
// bits implemted are [12] - busy and [10:8]= command error
|
||||
assign abstractcs_reg[31:13] = '0;
|
||||
assign abstractcs_reg[11] = '0;
|
||||
assign abstractcs_reg[7:4] = '0;
|
||||
assign abstractcs_reg[3:0] = 4'h2; // One data register
|
||||
assign abstractcs_error_sel0 = abstractcs_reg[12] & dmi_reg_en & ((dmi_reg_wr_en & ( (dmi_reg_addr == 7'h16) | (dmi_reg_addr == 7'h17))) | (dmi_reg_addr == 7'h4));
|
||||
assign abstractcs_error_sel1 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h17) & ~((dmi_reg_wdata[31:24] == 8'b0) | (dmi_reg_wdata[31:24] == 8'h2));
|
||||
assign abstractcs_error_sel2 = core_dbg_cmd_done & core_dbg_cmd_fail;
|
||||
assign abstractcs_error_sel3 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h17) & (dbg_state != HALTED);
|
||||
assign abstractcs_error_sel4 = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en &
|
||||
( ((dmi_reg_wdata[22:20] == 3'b001) & data1_reg[0]) |
|
||||
((dmi_reg_wdata[22:20] == 3'b010) & (|data1_reg[1:0])) |
|
||||
dmi_reg_wdata[22] | (dmi_reg_wdata[22:20] == 3'b011)
|
||||
);
|
||||
|
||||
assign abstractcs_error_sel5 = (dmi_reg_addr == 7'h16) & dmi_reg_en & dmi_reg_wr_en;
|
||||
|
||||
assign abstractcs_error_selor = abstractcs_error_sel0 | abstractcs_error_sel1 | abstractcs_error_sel2 | abstractcs_error_sel3 | abstractcs_error_sel4 | abstractcs_error_sel5;
|
||||
|
||||
assign abstractcs_error_din[2:0] = ({3{abstractcs_error_sel0}} & 3'b001) | // writing command or abstractcs while a command was executing. Or accessing data0
|
||||
({3{abstractcs_error_sel1}} & 3'b010) | // writing a non-zero command to cmd field of command
|
||||
({3{abstractcs_error_sel2}} & 3'b011) | // exception while running command
|
||||
({3{abstractcs_error_sel3}} & 3'b100) | // writing a comnand when not in the halted state
|
||||
({3{abstractcs_error_sel4}} & 3'b111) | // unaligned abstract memory command
|
||||
({3{abstractcs_error_sel5}} & ~dmi_reg_wdata[10:8] & abstractcs_reg[10:8]) | // W1C
|
||||
({3{~abstractcs_error_selor}} & abstractcs_reg[10:8]); // hold
|
||||
|
||||
rvdffs #(1) dmabstractcs_busy_reg (.din(abstractcs_busy_din), .dout(abstractcs_reg[12]), .en(abstractcs_busy_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
rvdff #(3) dmabstractcs_error_reg (.din(abstractcs_error_din[2:0]), .dout(abstractcs_reg[10:8]), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
|
||||
|
||||
// command register - implemented all the bits in this register
|
||||
// command[16] = 1: write, 0: read
|
||||
assign command_wren = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en & (dbg_state == HALTED);
|
||||
rvdffe #(32) dmcommand_reg (.*, .din(dmi_reg_wdata[31:0]), .dout(command_reg[31:0]), .en(command_wren), .rst_l(dbg_dm_rst_l));
|
||||
|
||||
// data0 reg
|
||||
assign data0_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h4) & (dbg_state == HALTED));
|
||||
assign data0_reg_wren1 = core_dbg_cmd_done & (dbg_state == CMD_WAIT) & ~command_reg[16];
|
||||
assign data0_reg_wren = data0_reg_wren0 | data0_reg_wren1;
|
||||
|
||||
assign data0_din[31:0] = ({32{data0_reg_wren0}} & dmi_reg_wdata[31:0]) |
|
||||
({32{data0_reg_wren1}} & core_dbg_rddata[31:0]);
|
||||
|
||||
rvdffe #(32) dbg_data0_reg (.*, .din(data0_din[31:0]), .dout(data0_reg[31:0]), .en(data0_reg_wren), .rst_l(dbg_dm_rst_l));
|
||||
|
||||
// data 1
|
||||
assign data1_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h5) & (dbg_state == HALTED));
|
||||
assign data1_reg_wren1 = 1'b0; // core_dbg_cmd_done & (dbg_state == CMD_WAIT) & ~command_reg[16];
|
||||
assign data1_reg_wren = data1_reg_wren0 | data1_reg_wren1;
|
||||
|
||||
assign data1_din[31:0] = ({32{data1_reg_wren0}} & dmi_reg_wdata[31:0]);
|
||||
//({32{data0_reg_wren1}} & core_dbg_rddata[31:0]);
|
||||
|
||||
rvdffe #(32) dbg_data1_reg (.*, .din(data1_din[31:0]), .dout(data1_reg[31:0]), .en(data1_reg_wren), .rst_l(dbg_dm_rst_l));
|
||||
|
||||
|
||||
// FSM to control the debug mode entry, command send/recieve, and Resume flow.
|
||||
always_comb begin
|
||||
dbg_nxtstate = IDLE;
|
||||
dbg_state_en = 1'b0;
|
||||
abstractcs_busy_wren = 1'b0;
|
||||
abstractcs_busy_din = 1'b0;
|
||||
dbg_halt_req = dmcontrol_wren_Q & dmcontrol_reg[31]; // single pulse output to the core
|
||||
dbg_resume_req = 1'b0; // single pulse output to the core
|
||||
|
||||
case (dbg_state)
|
||||
IDLE: begin
|
||||
dbg_nxtstate = (dmstatus_reg[9] | dec_tlu_mpc_halted_only) ? HALTED : HALTING; // initiate the halt command to the core
|
||||
dbg_state_en = ((dmcontrol_reg[31] & ~dec_tlu_debug_mode) | dmstatus_reg[9] | dec_tlu_mpc_halted_only) & ~dmcontrol_reg[1]; // when the jtag writes the halt bit in the DM register, OR when the status indicates Halted
|
||||
dbg_halt_req = dmcontrol_reg[31]; // Removed debug mode qualification during MPC changes
|
||||
//dbg_halt_req = dmcontrol_reg[31] & ~dec_tlu_debug_mode; // only when jtag has written the halt_req bit in the control
|
||||
end
|
||||
HALTING : begin
|
||||
dbg_nxtstate = HALTED; // Goto HALTED once the core sends an ACK
|
||||
dbg_state_en = dmstatus_reg[9]; // core indicates halted
|
||||
end
|
||||
HALTED: begin
|
||||
// wait for halted to go away before send to resume. Else start of new command
|
||||
dbg_nxtstate = (dmstatus_reg[9] & ~dmcontrol_reg[1]) ? ((dmcontrol_reg[30] & ~dmcontrol_reg[31]) ? RESUMING : CMD_START) :
|
||||
(dmcontrol_reg[31] ? HALTING : IDLE); // This is MPC halted case
|
||||
//dbg_nxtstate = dmcontrol_reg[1] ? IDLE : (dmcontrol_reg[30] & ~dmcontrol_reg[31]) ? RESUMING : CMD_START; // wait for halted to go away before send to resume. Else start of new command
|
||||
dbg_state_en = (dmstatus_reg[9] & dmcontrol_reg[30] & ~dmcontrol_reg[31] & dmcontrol_wren_Q) | command_wren | dmcontrol_reg[1] | ~(dmstatus_reg[9] | dec_tlu_mpc_halted_only);
|
||||
abstractcs_busy_wren = dbg_state_en & (dbg_nxtstate == CMD_START); // write busy when a new command was written by jtag
|
||||
abstractcs_busy_din = 1'b1;
|
||||
dbg_resume_req = dbg_state_en & (dbg_nxtstate == RESUMING); // single cycle pulse to core if resuming
|
||||
end
|
||||
CMD_START: begin
|
||||
dbg_nxtstate = (|abstractcs_reg[10:8]) ? CMD_DONE : CMD_WAIT; // new command sent to the core
|
||||
dbg_state_en = dbg_cmd_valid | (|abstractcs_reg[10:8]);
|
||||
end
|
||||
CMD_WAIT: begin
|
||||
dbg_nxtstate = CMD_DONE;
|
||||
dbg_state_en = core_dbg_cmd_done; // go to done state for one cycle after completing current command
|
||||
end
|
||||
CMD_DONE: begin
|
||||
dbg_nxtstate = HALTED;
|
||||
dbg_state_en = 1'b1;
|
||||
abstractcs_busy_wren = dbg_state_en; // remove the busy bit from the abstracts ( bit 12 )
|
||||
abstractcs_busy_din = 1'b0;
|
||||
end
|
||||
RESUMING : begin
|
||||
dbg_nxtstate = IDLE;
|
||||
dbg_state_en = dmstatus_reg[17]; // resume ack has been updated in the dmstatus register
|
||||
end
|
||||
default : begin
|
||||
dbg_nxtstate = IDLE;
|
||||
dbg_state_en = 1'b0;
|
||||
abstractcs_busy_wren = 1'b0;
|
||||
abstractcs_busy_din = 1'b0;
|
||||
dbg_halt_req = 1'b0; // single pulse output to the core
|
||||
dbg_resume_req = 1'b0; // single pulse output to the core
|
||||
end
|
||||
endcase
|
||||
end // always_comb begin
|
||||
|
||||
assign dmi_reg_rdata_din[31:0] = ({32{dmi_reg_addr == 7'h4}} & data0_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h5}} & data1_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h10}} & dmcontrol_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h11}} & dmstatus_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h16}} & abstractcs_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h17}} & command_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h40}} & haltsum0_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h38}} & sbcs_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h39}} & sbaddress0_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h3c}} & sbdata0_reg[31:0]) |
|
||||
({32{dmi_reg_addr == 7'h3d}} & sbdata1_reg[31:0]);
|
||||
|
||||
|
||||
rvdffs #($bits(state_t)) dbg_state_reg (.din(dbg_nxtstate), .dout({dbg_state}), .en(dbg_state_en), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
// Ack will use the power on reset only otherwise there won't be any ack until dmactive is 1
|
||||
// rvdff #(1) dmi_ack_reg (.din(dmi_reg_en), .dout(dmi_reg_ack), .rst_l(rst_l), .clk(free_clk));
|
||||
rvdffs #(32) dmi_rddata_reg(.din(dmi_reg_rdata_din), .dout(dmi_reg_rdata), .en(dmi_reg_en), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
||||
|
||||
// interface for the core
|
||||
assign dbg_cmd_addr[31:0] = (command_reg[31:24] == 8'h2) ? {data1_reg[31:2],2'b0} : {20'b0, command_reg[11:0]}; // Only word addresses for abstract memory
|
||||
assign dbg_cmd_wrdata[31:0] = data0_reg[31:0];
|
||||
assign dbg_cmd_valid = (dbg_state == CMD_START) & ~(|abstractcs_reg[10:8]) & dma_dbg_ready;
|
||||
assign dbg_cmd_write = command_reg[16];
|
||||
assign dbg_cmd_type[1:0] = (command_reg[31:24] == 8'h2) ? 2'b10 : {1'b0, (command_reg[15:12] == 4'b0)};
|
||||
assign dbg_cmd_size[1:0] = command_reg[21:20];
|
||||
|
||||
// Ask DMA to stop taking bus trxns since debug request is done
|
||||
assign dbg_dma_bubble = ((dbg_state == CMD_START) & ~(|abstractcs_reg[10:8])) | (dbg_state == CMD_WAIT);
|
||||
|
||||
// system bus FSM
|
||||
always_comb begin
|
||||
sb_nxtstate = SBIDLE;
|
||||
sb_state_en = 1'b0;
|
||||
sbcs_sbbusy_wren = 1'b0;
|
||||
sbcs_sbbusy_din = 1'b0;
|
||||
sbcs_sberror_wren = 1'b0;
|
||||
sbcs_sberror_din[2:0] = 3'b0;
|
||||
sbaddress0_reg_wren1 = 1'b0;
|
||||
case (sb_state)
|
||||
SBIDLE: begin
|
||||
sb_nxtstate = WAIT;
|
||||
sb_state_en = sbdata0wr_access | sbreadondata_access | sbreadonaddr_access;
|
||||
sbcs_sbbusy_wren = sb_state_en; // set the single read bit if it is a singlread command
|
||||
sbcs_sbbusy_din = 1'b1;
|
||||
sbcs_sberror_wren = sbcs_wren & (|dmi_reg_wdata[14:12]); // write to clear the error bits
|
||||
sbcs_sberror_din[2:0] = ~dmi_reg_wdata[14:12] & sbcs_reg[14:12];
|
||||
end
|
||||
WAIT: begin
|
||||
sb_nxtstate = (sbcs_unaligned | sbcs_illegal_size) ? DONE : (sbcs_reg[15] | sbcs_reg[20]) ? CMD_RD : CMD_WR;
|
||||
sb_state_en = dbg_bus_clk_en | sbcs_unaligned | sbcs_illegal_size;
|
||||
sbcs_sberror_wren = sbcs_unaligned | sbcs_illegal_size;
|
||||
sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100;
|
||||
end
|
||||
CMD_RD : begin
|
||||
sb_nxtstate = RSP_RD;
|
||||
sb_state_en = sb_axi_arvalid_q & sb_axi_arready_q & dbg_bus_clk_en;
|
||||
end
|
||||
CMD_WR : begin
|
||||
sb_nxtstate = (sb_axi_awready_q & sb_axi_wready_q) ? RSP_WR : (sb_axi_awready_q ? CMD_WR_DATA : CMD_WR_ADDR);
|
||||
sb_state_en = ((sb_axi_awvalid_q & sb_axi_awready_q) | (sb_axi_wvalid_q & sb_axi_wready_q)) & dbg_bus_clk_en;
|
||||
end
|
||||
CMD_WR_ADDR : begin
|
||||
sb_nxtstate = RSP_WR;
|
||||
sb_state_en = sb_axi_awvalid_q & sb_axi_awready_q & dbg_bus_clk_en;
|
||||
end
|
||||
CMD_WR_DATA : begin
|
||||
sb_nxtstate = RSP_WR;
|
||||
sb_state_en = sb_axi_wvalid_q & sb_axi_wready_q & dbg_bus_clk_en;
|
||||
end
|
||||
RSP_RD: begin
|
||||
sb_nxtstate = DONE;
|
||||
sb_state_en = sb_axi_rvalid_q & sb_axi_rready_q & dbg_bus_clk_en;
|
||||
sbcs_sberror_wren = sb_state_en & sb_axi_rresp_q[1];
|
||||
sbcs_sberror_din[2:0] = 3'b010;
|
||||
end
|
||||
RSP_WR: begin
|
||||
sb_nxtstate = DONE;
|
||||
sb_state_en = sb_axi_bvalid_q & sb_axi_bready_q & dbg_bus_clk_en;
|
||||
sbcs_sberror_wren = sb_state_en & sb_axi_bresp_q[1];
|
||||
sbcs_sberror_din[2:0] = 3'b010;
|
||||
end
|
||||
DONE: begin
|
||||
sb_nxtstate = SBIDLE;
|
||||
sb_state_en = 1'b1;
|
||||
sbcs_sbbusy_wren = 1'b1; // reset the single read
|
||||
sbcs_sbbusy_din = 1'b0;
|
||||
sbaddress0_reg_wren1 = sbcs_reg[16]; // auto increment was set. Update to new address after completing the current command
|
||||
end
|
||||
default : begin
|
||||
sb_nxtstate = SBIDLE;
|
||||
sb_state_en = 1'b0;
|
||||
sbcs_sbbusy_wren = 1'b0;
|
||||
sbcs_sbbusy_din = 1'b0;
|
||||
sbcs_sberror_wren = 1'b0;
|
||||
sbcs_sberror_din[2:0] = 3'b0;
|
||||
sbaddress0_reg_wren1 = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end // always_comb begin
|
||||
|
||||
rvdffs #($bits(sb_state_t)) sb_state_reg (.din(sb_nxtstate), .dout({sb_state}), .en(sb_state_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk));
|
||||
|
||||
//rvdff #(.WIDTH(1)) bus_clken_ff (.din(dbg_bus_clk_en), .dout(dbg_bus_clk_en_q), .rst_l(dbg_dm_rst_l), .clk(dbg_sb_c2_free_clk), .*);
|
||||
|
||||
rvdffs #(.WIDTH(1)) axi_awvalid_ff (.din(sb_axi_awvalid), .dout(sb_axi_awvalid_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) axi_awready_ff (.din(sb_axi_awready), .dout(sb_axi_awready_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) axi_wvalid_ff (.din(sb_axi_wvalid), .dout(sb_axi_wvalid_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) axi_wready_ff (.din(sb_axi_wready), .dout(sb_axi_wready_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) axi_arvalid_ff (.din(sb_axi_arvalid), .dout(sb_axi_arvalid_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) axi_arready_ff (.din(sb_axi_arready), .dout(sb_axi_arready_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
|
||||
rvdffs #(.WIDTH(1)) axi_bvalid_ff (.din(sb_axi_bvalid), .dout(sb_axi_bvalid_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) axi_bready_ff (.din(sb_axi_bready), .dout(sb_axi_bready_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdff #(.WIDTH(2)) axi_bresp_ff (.din(sb_axi_bresp[1:0]), .dout(sb_axi_bresp_q[1:0]), .rst_l(dbg_dm_rst_l), .clk(bus_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) axi_rvalid_ff (.din(sb_axi_rvalid), .dout(sb_axi_rvalid_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) axi_rready_ff (.din(sb_axi_rready), .dout(sb_axi_rready_q), .en(dbg_bus_clk_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk), .*);
|
||||
rvdff #(.WIDTH(2)) axi_rresp_ff (.din(sb_axi_rresp[1:0]), .dout(sb_axi_rresp_q[1:0]), .rst_l(dbg_dm_rst_l), .clk(bus_clk), .*);
|
||||
rvdff #(.WIDTH(64)) axi_rdata_ff (.din(sb_axi_rdata[63:0]), .dout(sb_axi_rdata_q[63:0]), .rst_l(dbg_dm_rst_l), .clk(bus_clk), .*);
|
||||
|
||||
// AXI Request signals
|
||||
assign sb_axi_awvalid = ((sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR)) & ~(sb_axi_awvalid_q & sb_axi_awready_q);
|
||||
assign sb_axi_awaddr[31:0] = sbaddress0_reg[31:0];
|
||||
assign sb_axi_awid[SB_BUS_TAG-1:0] = '0;
|
||||
assign sb_axi_awsize[2:0] = sbcs_reg[19:17];
|
||||
assign sb_axi_awprot[2:0] = '0;
|
||||
assign sb_axi_awcache[3:0] = 4'b1111;
|
||||
assign sb_axi_awregion[3:0] = sbaddress0_reg[31:28];
|
||||
assign sb_axi_awlen[7:0] = '0;
|
||||
assign sb_axi_awburst[1:0] = 2'b01;
|
||||
assign sb_axi_awqos[3:0] = '0;
|
||||
assign sb_axi_awlock = '0;
|
||||
|
||||
assign sb_axi_wvalid = ((sb_state == CMD_WR) | (sb_state == CMD_WR_DATA)) & ~(sb_axi_wvalid_q & sb_axi_wready_q);
|
||||
assign sb_axi_wdata[63:0] = ({64{(sbcs_reg[19:17] == 3'h0)}} & {8{sbdata0_reg[7:0]}}) |
|
||||
({64{(sbcs_reg[19:17] == 3'h1)}} & {4{sbdata0_reg[15:0]}}) |
|
||||
({64{(sbcs_reg[19:17] == 3'h2)}} & {2{sbdata0_reg[31:0]}}) |
|
||||
({64{(sbcs_reg[19:17] == 3'h3)}} & {sbdata1_reg[31:0],sbdata0_reg[31:0]});
|
||||
assign sb_axi_wstrb[7:0] = ({8{(sbcs_reg[19:17] == 3'h0)}} & (8'h1 << sbaddress0_reg[2:0])) |
|
||||
({8{(sbcs_reg[19:17] == 3'h1)}} & (8'h3 << {sbaddress0_reg[2:1],1'b0})) |
|
||||
({8{(sbcs_reg[19:17] == 3'h2)}} & (8'hf << {sbaddress0_reg[2],2'b0})) |
|
||||
({8{(sbcs_reg[19:17] == 3'h3)}} & 8'hff);
|
||||
assign sb_axi_wlast = '1;
|
||||
|
||||
assign sb_axi_arvalid = (sb_state == CMD_RD) & ~(sb_axi_arvalid_q & sb_axi_arready_q);
|
||||
assign sb_axi_araddr[31:0] = {sbaddress0_reg[31:3],3'b0};
|
||||
assign sb_axi_arid[SB_BUS_TAG-1:0] = '0;
|
||||
assign sb_axi_arsize[2:0] = 3'b011;
|
||||
assign sb_axi_arprot[2:0] = '0;
|
||||
assign sb_axi_arcache[3:0] = 4'b0;
|
||||
assign sb_axi_arregion[3:0] = sbaddress0_reg[31:28];
|
||||
assign sb_axi_arlen[7:0] = '0;
|
||||
assign sb_axi_arburst[1:0] = 2'b01;
|
||||
assign sb_axi_arqos[3:0] = '0;
|
||||
assign sb_axi_arlock = '0;
|
||||
|
||||
// AXI Response signals
|
||||
assign sb_axi_bready = 1'b1;
|
||||
|
||||
assign sb_axi_rready = 1'b1;
|
||||
assign sb_bus_rdata[63:0] = ({64{sbcs_reg[19:17] == 3'h0}} & ((sb_axi_rdata_q[63:0] >> 8*sbaddress0_reg[2:0]) & 64'hff)) |
|
||||
({64{sbcs_reg[19:17] == 3'h1}} & ((sb_axi_rdata_q[63:0] >> 16*sbaddress0_reg[2:1]) & 64'hffff)) |
|
||||
({64{sbcs_reg[19:17] == 3'h2}} & ((sb_axi_rdata_q[63:0] >> 32*sbaddress0_reg[2]) & 64'hffff_ffff)) |
|
||||
({64{sbcs_reg[19:17] == 3'h3}} & sb_axi_rdata_q[63:0]);
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
// assertion.
|
||||
// when the resume_ack is asserted then the dec_tlu_dbg_halted should be 0
|
||||
dm_check_resume_and_halted: assert property (@(posedge clk) disable iff(~rst_l) (~dec_tlu_resume_ack | ~dec_tlu_dbg_halted));
|
||||
`endif
|
||||
endmodule
|
|
@ -0,0 +1,254 @@
|
|||
|
||||
.definition
|
||||
|
||||
|
||||
|
||||
# invalid rs2=0
|
||||
c.add0 = [1001.....1....10]
|
||||
c.add1 = [1001......1...10]
|
||||
c.add2 = [1001.......1..10]
|
||||
c.add3 = [1001........1.10]
|
||||
c.add4 = [1001.........110]
|
||||
|
||||
# invalid rs2=0
|
||||
c.mv0 = [1000.....1....10]
|
||||
c.mv1 = [1000......1...10]
|
||||
c.mv2 = [1000.......1..10]
|
||||
c.mv3 = [1000........1.10]
|
||||
c.mv4 = [1000.........110]
|
||||
|
||||
|
||||
# invalid if rs1=0
|
||||
c.jalr0 = [10011....0000010]
|
||||
c.jalr1 = [1001.1...0000010]
|
||||
c.jalr2 = [1001..1..0000010]
|
||||
c.jalr3 = [1001...1.0000010]
|
||||
c.jalr4 = [1001....10000010]
|
||||
|
||||
c.addi = [000...........01]
|
||||
|
||||
# invalid imm=0
|
||||
c.addi16sp0 = [011100010.....01]
|
||||
c.addi16sp1 = [011.000101....01]
|
||||
c.addi16sp2 = [011.00010.1...01]
|
||||
c.addi16sp3 = [011.00010..1..01]
|
||||
c.addi16sp4 = [011.00010...1.01]
|
||||
c.addi16sp5 = [011.00010....101]
|
||||
|
||||
# invalid uimm=0
|
||||
c.addi4spn0 = [0001..........00]
|
||||
c.addi4spn1 = [000.1.........00]
|
||||
c.addi4spn2 = [000..1........00]
|
||||
c.addi4spn3 = [000...1.......00]
|
||||
c.addi4spn4 = [000....1......00]
|
||||
c.addi4spn5 = [000.....1.....00]
|
||||
c.addi4spn6 = [000......1....00]
|
||||
c.addi4spn7 = [000.......1...00]
|
||||
|
||||
|
||||
c.and = [100011...11...01]
|
||||
c.andi = [100.10........01]
|
||||
c.beqz = [110...........01]
|
||||
c.bnez = [111...........01]
|
||||
c.ebreak = [1001000000000010]
|
||||
c.j = [101...........01]
|
||||
c.jal = [001...........01]
|
||||
|
||||
|
||||
c.jr0 = [10001....0000010]
|
||||
c.jr1 = [1000.1...0000010]
|
||||
c.jr2 = [1000..1..0000010]
|
||||
c.jr3 = [1000...1.0000010]
|
||||
c.jr4 = [1000....10000010]
|
||||
|
||||
c.li = [010...........01]
|
||||
|
||||
# invalid rd=x2 or imm=0
|
||||
c.lui0 = [01111.........01]
|
||||
c.lui1 = [0111.1........01]
|
||||
c.lui2 = [0111..1.......01]
|
||||
c.lui3 = [0111...0......01]
|
||||
c.lui4 = [0111....1.....01]
|
||||
c.lui5 = [011.1....1....01]
|
||||
c.lui6 = [011..1...1....01]
|
||||
c.lui7 = [011...1..1....01]
|
||||
c.lui8 = [011....0.1....01]
|
||||
c.lui9 = [011.....11....01]
|
||||
c.lui10= [011.1.....1...01]
|
||||
c.lui11= [011..1....1...01]
|
||||
c.lui12 = [011...1...1...01]
|
||||
c.lui13 = [011....0..1...01]
|
||||
c.lui14 = [011.....1.1...01]
|
||||
c.lui15 = [011.1......1..01]
|
||||
c.lui16 = [011..1.....1..01]
|
||||
c.lui17 = [011...1....1..01]
|
||||
c.lui18 = [011....0...1..01]
|
||||
c.lui19 = [011.....1..1..01]
|
||||
c.lui20 = [011.1.......1.01]
|
||||
c.lui21 = [011..1......1.01]
|
||||
c.lui22 = [011...1.....1.01]
|
||||
c.lui23 = [011....0....1.01]
|
||||
c.lui24 = [011.....1...1.01]
|
||||
c.lui25 = [011.1........101]
|
||||
c.lui26 = [011..1.......101]
|
||||
c.lui27 = [011...1......101]
|
||||
c.lui28 = [011....0.....101]
|
||||
c.lui29 = [011.....1....101]
|
||||
|
||||
|
||||
c.lw = [010...........00]
|
||||
|
||||
|
||||
c.lwsp = [010...........10]
|
||||
|
||||
c.or = [100011...10...01]
|
||||
|
||||
# bit 5 of the shift must be 0 to be legal
|
||||
c.slli = [0000..........10]
|
||||
|
||||
c.srai = [100001........01]
|
||||
|
||||
c.srli = [100000........01]
|
||||
|
||||
c.sub = [100011...00...01]
|
||||
c.sw = [110...........00]
|
||||
c.swsp = [110...........10]
|
||||
c.xor = [100011...01...01]
|
||||
|
||||
|
||||
.input
|
||||
rv32c = {
|
||||
i[15]
|
||||
i[14]
|
||||
i[13]
|
||||
i[12]
|
||||
i[11]
|
||||
i[10]
|
||||
i[9]
|
||||
i[8]
|
||||
i[7]
|
||||
i[6]
|
||||
i[5]
|
||||
i[4]
|
||||
i[3]
|
||||
i[2]
|
||||
i[1]
|
||||
i[0]
|
||||
}
|
||||
|
||||
.output
|
||||
rv32c = {
|
||||
rdrd
|
||||
rdrs1
|
||||
rs2rs2
|
||||
rdprd
|
||||
rdprs1
|
||||
rs2prs2
|
||||
rs2prd
|
||||
uimm9_2
|
||||
ulwimm6_2
|
||||
ulwspimm7_2
|
||||
rdeq2
|
||||
rdeq1
|
||||
rs1eq2
|
||||
sbroffset8_1
|
||||
simm9_4
|
||||
simm5_0
|
||||
sjaloffset11_1
|
||||
sluimm17_12
|
||||
uimm5_0
|
||||
uswimm6_2
|
||||
uswspimm7_2
|
||||
o[31]
|
||||
o[30]
|
||||
o[29]
|
||||
o[28]
|
||||
o[27]
|
||||
o[26]
|
||||
o[25]
|
||||
o[24]
|
||||
o[23]
|
||||
o[22]
|
||||
o[21]
|
||||
o[20]
|
||||
o[19]
|
||||
o[18]
|
||||
o[17]
|
||||
o[16]
|
||||
o[15]
|
||||
o[14]
|
||||
o[13]
|
||||
o[12]
|
||||
o[11]
|
||||
o[10]
|
||||
o[9]
|
||||
o[8]
|
||||
o[7]
|
||||
o[6]
|
||||
o[5]
|
||||
o[4]
|
||||
o[3]
|
||||
o[2]
|
||||
o[1]
|
||||
o[0]
|
||||
}
|
||||
|
||||
# assign rs2d[4:0] = i[6:2];
|
||||
#
|
||||
# assign rdd[4:0] = i[11:7];
|
||||
#
|
||||
# assign rdpd[4:0] = {2'b01, i[9:7]};
|
||||
#
|
||||
# assign rs2pd[4:0] = {2'b01, i[4:2]};
|
||||
|
||||
.decode
|
||||
|
||||
|
||||
|
||||
|
||||
rv32c[c.add{0-4}] = { rdrd rdrs1 rs2rs2 o[5] o[4] o[1] o[0] }
|
||||
|
||||
rv32c[c.mv{0-4}] = { rdrd rs2rs2 o[5] o[4] o[1] o[0] }
|
||||
|
||||
rv32c[c.addi] = { rdrd rdrs1 simm5_0 o[4] o[1] o[0] }
|
||||
|
||||
rv32c[c.addi16sp{0-5}] = { rdeq2 rs1eq2 simm9_4 o[4] o[1] o[0] }
|
||||
rv32c[c.addi4spn{0-7}] = { rs2prd rs1eq2 uimm9_2 o[4] o[1] o[0] }
|
||||
|
||||
|
||||
rv32c[c.and] = { rdprd rdprs1 rs2prs2 o[14] o[13] o[12] o[5] o[4] o[1] o[0] }
|
||||
rv32c[c.andi] = { rdprd rdprs1 simm5_0 o[14] o[13] o[12] o[4] o[1] o[0] }
|
||||
rv32c[c.beqz] = { rdprs1 sbroffset8_1 o[6] o[5] o[1] o[0] }
|
||||
rv32c[c.bnez] = { rdprs1 sbroffset8_1 o[12] o[6] o[5] o[1] o[0] }
|
||||
|
||||
|
||||
rv32c[c.ebreak] = { o[20] o[6] o[5] o[4] o[1] o[0] }
|
||||
|
||||
rv32c[c.j] = { sjaloffset11_1 o[6] o[5] o[3] o[2] o[1] o[0] }
|
||||
rv32c[c.jal] = { sjaloffset11_1 rdeq1 o[6] o[5] o[3] o[2] o[1] o[0] }
|
||||
|
||||
|
||||
rv32c[c.jalr{0-4}] = { rdeq1 rdrs1 o[6] o[5] o[2] o[1] o[0] }
|
||||
rv32c[c.jr{0-4}] = { rdrs1 o[6] o[5] o[2] o[1] o[0] }
|
||||
rv32c[c.li] = { rdrd simm5_0 o[4] o[1] o[0] }
|
||||
|
||||
rv32c[c.lui{0-29}] = { rdrd sluimm17_12 o[5] o[4] o[2] o[1] o[0] }
|
||||
rv32c[c.lw] = { rs2prd rdprs1 ulwimm6_2 o[13] o[1] o[0] }
|
||||
rv32c[c.lwsp] = { rdrd rs1eq2 ulwspimm7_2 o[13] o[1] o[0] }
|
||||
|
||||
|
||||
rv32c[c.or] = { rdprd rdprs1 rs2prs2 o[14] o[13] o[5] o[4] o[1] o[0] }
|
||||
|
||||
rv32c[c.slli] = { rdrd rdrs1 uimm5_0 o[12] o[4] o[1] o[0] }
|
||||
rv32c[c.srai] = { rdprd rdprs1 uimm5_0 o[30] o[14] o[12] o[4] o[1] o[0] }
|
||||
rv32c[c.srli] = { rdprd rdprs1 uimm5_0 o[14] o[12] o[4] o[1] o[0] }
|
||||
|
||||
|
||||
rv32c[c.sub] = { rdprd rdprs1 rs2prs2 o[30] o[5] o[4] o[1] o[0] }
|
||||
rv32c[c.sw] = { rdprs1 rs2prs2 uswimm6_2 o[13] o[5] o[1] o[0] }
|
||||
rv32c[c.swsp] = { rs2rs2 rs1eq2 uswspimm7_2 o[13] o[5] o[1] o[0] }
|
||||
rv32c[c.xor] = { rdprd rdprs1 rs2prs2 o[14] o[5] o[4] o[1] o[0] }
|
||||
|
||||
|
||||
|
||||
.end
|
|
@ -0,0 +1,229 @@
|
|||
.definition
|
||||
|
||||
csr_misa = [001100000001]
|
||||
csr_mvendorid = [111100010001]
|
||||
csr_marchid = [111100010010]
|
||||
csr_mimpid = [111100010011]
|
||||
csr_mhartid = [111100010100]
|
||||
csr_mstatus = [001100000000]
|
||||
csr_mtvec = [001100000101]
|
||||
csr_mip = [001101000100]
|
||||
csr_mie = [001100000100]
|
||||
csr_mcyclel = [101100000000]
|
||||
csr_mcycleh = [101110000000]
|
||||
csr_minstretl = [101100000010]
|
||||
csr_minstreth = [101110000010]
|
||||
csr_mscratch = [001101000000]
|
||||
csr_mepc = [001101000001]
|
||||
csr_mcause = [001101000010]
|
||||
csr_mtval = [001101000011]
|
||||
csr_mrac = [011111000000]
|
||||
csr_dmst = [011111000100]
|
||||
csr_mdeau = [101111000000]
|
||||
csr_mdseac = [111111000000]
|
||||
csr_meivt = [101111001000]
|
||||
csr_meihap = [111111001000]
|
||||
csr_meipt = [101111001001]
|
||||
csr_meipt = [101111001001]
|
||||
csr_meicpct = [101111001010]
|
||||
csr_meicurpl = [101111001100]
|
||||
csr_meicidpl = [101111001011]
|
||||
csr_dcsr = [011110110000]
|
||||
csr_dpc = [011110110001]
|
||||
csr_dicawics = [011111001000]
|
||||
csr_dicad0 = [011111001001]
|
||||
csr_dicad1 = [011111001010]
|
||||
csr_dicago = [011111001011]
|
||||
csr_mtsel = [011110100000]
|
||||
csr_mtdata1 = [011110100001]
|
||||
csr_mtdata2 = [011110100010]
|
||||
csr_mhpmc3 = [101100000011]
|
||||
csr_mhpmc4 = [101100000100]
|
||||
csr_mhpmc5 = [101100000101]
|
||||
csr_mhpmc6 = [101100000110]
|
||||
csr_mhpmc3h = [101110000011]
|
||||
csr_mhpmc4h = [101110000100]
|
||||
csr_mhpmc5h = [101110000101]
|
||||
csr_mhpmc6h = [101110000110]
|
||||
csr_mhpme3 = [001100100011]
|
||||
csr_mhpme4 = [001100100100]
|
||||
csr_mhpme5 = [001100100101]
|
||||
csr_mhpme6 = [001100100110]
|
||||
csr_micect = [011111110000]
|
||||
csr_miccmect = [011111110001]
|
||||
csr_mdccmect = [011111110010]
|
||||
csr_mpmc = [011111000110]
|
||||
csr_mcgc = [011111111000]
|
||||
csr_mcpc = [011111000010]
|
||||
csr_mfdc = [011111111001]
|
||||
csr_mgpmc = [011111010000]
|
||||
csr_perfva = [101100000111]
|
||||
csr_perfvb = [101100001...]
|
||||
csr_perfvc = [10110001....]
|
||||
csr_perfvd = [101110000111]
|
||||
csr_perfve = [101110001...]
|
||||
csr_perfvf = [10111001....]
|
||||
csr_perfvg = [001100100111]
|
||||
csr_perfvh = [001100101...]
|
||||
csr_perfvi = [00110011....]
|
||||
|
||||
.input
|
||||
|
||||
csr = {
|
||||
dec_csr_rdaddr_d[11]
|
||||
dec_csr_rdaddr_d[10]
|
||||
dec_csr_rdaddr_d[9]
|
||||
dec_csr_rdaddr_d[8]
|
||||
dec_csr_rdaddr_d[7]
|
||||
dec_csr_rdaddr_d[6]
|
||||
dec_csr_rdaddr_d[5]
|
||||
dec_csr_rdaddr_d[4]
|
||||
dec_csr_rdaddr_d[3]
|
||||
dec_csr_rdaddr_d[2]
|
||||
dec_csr_rdaddr_d[1]
|
||||
dec_csr_rdaddr_d[0]
|
||||
}
|
||||
|
||||
.output
|
||||
|
||||
csr = {
|
||||
csr_misa
|
||||
csr_mvendorid
|
||||
csr_marchid
|
||||
csr_mimpid
|
||||
csr_mhartid
|
||||
csr_mstatus
|
||||
csr_mtvec
|
||||
csr_mip
|
||||
csr_mie
|
||||
csr_mcyclel
|
||||
csr_mcycleh
|
||||
csr_minstretl
|
||||
csr_minstreth
|
||||
csr_mscratch
|
||||
csr_mepc
|
||||
csr_mcause
|
||||
csr_mtval
|
||||
csr_mrac
|
||||
csr_dmst
|
||||
csr_mdeau
|
||||
csr_mdseac
|
||||
csr_meihap
|
||||
csr_meivt
|
||||
csr_meipt
|
||||
csr_meicpct
|
||||
csr_meicurpl
|
||||
csr_meicidpl
|
||||
csr_dcsr
|
||||
csr_mpmc
|
||||
csr_mcgc
|
||||
csr_mcpc
|
||||
csr_mfdc
|
||||
csr_dpc
|
||||
csr_mtsel
|
||||
csr_mtdata1
|
||||
csr_mtdata2
|
||||
csr_mhpmc3
|
||||
csr_mhpmc4
|
||||
csr_mhpmc5
|
||||
csr_mhpmc6
|
||||
csr_mhpmc3h
|
||||
csr_mhpmc4h
|
||||
csr_mhpmc5h
|
||||
csr_mhpmc6h
|
||||
csr_mhpme3
|
||||
csr_mhpme4
|
||||
csr_mhpme5
|
||||
csr_mhpme6
|
||||
csr_mgpmc
|
||||
csr_perfva
|
||||
csr_perfvb
|
||||
csr_perfvc
|
||||
csr_perfvd
|
||||
csr_perfve
|
||||
csr_perfvf
|
||||
csr_perfvg
|
||||
csr_perfvh
|
||||
csr_perfvi
|
||||
csr_micect
|
||||
csr_miccmect
|
||||
csr_mdccmect
|
||||
csr_dicawics
|
||||
csr_dicad0
|
||||
csr_dicad1
|
||||
csr_dicago
|
||||
valid_only
|
||||
presync
|
||||
postsync
|
||||
}
|
||||
|
||||
.decode
|
||||
|
||||
csr[ csr_misa ] = { csr_misa }
|
||||
csr[ csr_mvendorid ] = { csr_mvendorid }
|
||||
csr[ csr_marchid ] = { csr_marchid }
|
||||
csr[ csr_mimpid ] = { csr_mimpid }
|
||||
csr[ csr_mhartid ] = { csr_mhartid }
|
||||
csr[ csr_mstatus ] = { csr_mstatus postsync }
|
||||
csr[ csr_mtvec ] = { csr_mtvec postsync}
|
||||
csr[ csr_mip ] = { csr_mip }
|
||||
csr[ csr_mie ] = { csr_mie }
|
||||
csr[ csr_mcyclel ] = { csr_mcyclel }
|
||||
csr[ csr_mcycleh ] = { csr_mcycleh }
|
||||
csr[ csr_minstretl ] = { csr_minstretl presync }
|
||||
csr[ csr_minstreth ] = { csr_minstreth presync }
|
||||
csr[ csr_mscratch ] = { csr_mscratch }
|
||||
csr[ csr_mepc ] = { csr_mepc postsync}
|
||||
csr[ csr_mcause ] = { csr_mcause }
|
||||
csr[ csr_mtval ] = { csr_mtval }
|
||||
csr[ csr_mrac ] = { csr_mrac postsync }
|
||||
csr[ csr_dmst ] = { csr_dmst postsync}
|
||||
csr[ csr_mdeau ] = { csr_mdeau }
|
||||
csr[ csr_mdseac ] = { csr_mdseac }
|
||||
csr[ csr_meipt ] = { csr_meipt }
|
||||
csr[ csr_meihap ] = { csr_meihap }
|
||||
csr[ csr_meivt ] = { csr_meivt }
|
||||
csr[ csr_meicurpl ] = { csr_meicurpl }
|
||||
csr[ csr_meicpct ] = { csr_meicpct }
|
||||
csr[ csr_meicidpl ] = { csr_meicidpl }
|
||||
csr[ csr_mpmc ] = { csr_mpmc }
|
||||
csr[ csr_mcgc ] = { csr_mcgc }
|
||||
csr[ csr_mgpmc ] = { csr_mgpmc presync postsync }
|
||||
csr[ csr_mcpc ] = { csr_mcpc presync postsync }
|
||||
csr[ csr_mfdc ] = { csr_mfdc presync postsync }
|
||||
csr[ csr_dcsr ] = { csr_dcsr }
|
||||
csr[ csr_dpc ] = { csr_dpc }
|
||||
csr[ csr_mtsel ] = { csr_mtsel }
|
||||
csr[ csr_mtdata1 ] = { csr_mtdata1 postsync }
|
||||
csr[ csr_mtdata2 ] = { csr_mtdata2 postsync }
|
||||
csr[ csr_mhpmc3 ] = { csr_mhpmc3 presync }
|
||||
csr[ csr_mhpmc4 ] = { csr_mhpmc4 presync }
|
||||
csr[ csr_mhpmc5 ] = { csr_mhpmc5 presync }
|
||||
csr[ csr_mhpmc6 ] = { csr_mhpmc6 presync }
|
||||
csr[ csr_mhpmc3h ] = { csr_mhpmc3h presync }
|
||||
csr[ csr_mhpmc4h ] = { csr_mhpmc4h presync }
|
||||
csr[ csr_mhpmc5h ] = { csr_mhpmc5h presync }
|
||||
csr[ csr_mhpmc6h ] = { csr_mhpmc6h presync }
|
||||
csr[ csr_mhpme3 ] = { csr_mhpme3 }
|
||||
csr[ csr_mhpme4 ] = { csr_mhpme4 }
|
||||
csr[ csr_mhpme5 ] = { csr_mhpme5 }
|
||||
csr[ csr_mhpme6 ] = { csr_mhpme6 }
|
||||
csr[ csr_micect ] = { csr_micect }
|
||||
csr[ csr_miccmect ] = { csr_miccmect }
|
||||
csr[ csr_mdccmect ] = { csr_mdccmect }
|
||||
csr[ csr_dicawics ] = { csr_dicawics }
|
||||
csr[ csr_dicad0 ] = { csr_dicad0 }
|
||||
csr[ csr_dicad1 ] = { csr_dicad1 }
|
||||
csr[ csr_dicago ] = { csr_dicago }
|
||||
|
||||
csr[ csr_perfva ] = { valid_only }
|
||||
csr[ csr_perfvb ] = { valid_only }
|
||||
csr[ csr_perfvc ] = { valid_only }
|
||||
csr[ csr_perfvd ] = { valid_only }
|
||||
csr[ csr_perfve ] = { valid_only }
|
||||
csr[ csr_perfvf ] = { valid_only }
|
||||
csr[ csr_perfvg ] = { valid_only }
|
||||
csr[ csr_perfvh ] = { valid_only }
|
||||
csr[ csr_perfvi ] = { valid_only }
|
||||
|
||||
.end
|
|
@ -0,0 +1,579 @@
|
|||
// 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.
|
||||
|
||||
// dec: decode unit - decode, bypassing, ARF, interrupts
|
||||
//
|
||||
//********************************************************************************
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Function: Decode
|
||||
// Comments: Decode, dependency scoreboard, ARF
|
||||
//
|
||||
//
|
||||
// A -> D -> EX1 ... WB
|
||||
//
|
||||
//********************************************************************************
|
||||
|
||||
module dec
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk,
|
||||
input logic free_clk,
|
||||
input logic active_clk,
|
||||
|
||||
|
||||
output logic dec_pause_state_cg, // pause state for clock-gating
|
||||
|
||||
input logic rst_l, // reset, active low
|
||||
input logic [31:1] rst_vec, // reset vector, from core pins
|
||||
|
||||
input logic nmi_int, // NMI pin
|
||||
input logic [31:1] nmi_vec, // NMI vector, from pins
|
||||
|
||||
input logic i_cpu_halt_req, // Asynchronous Halt request to CPU
|
||||
input logic i_cpu_run_req, // Asynchronous Restart request to CPU
|
||||
|
||||
output logic o_cpu_halt_status, // Halt status of core (pmu/fw)
|
||||
output logic o_cpu_halt_ack, // Halt request ack
|
||||
output logic o_cpu_run_ack, // Run request ack
|
||||
output logic o_debug_mode_status, // Core to the PMU that core is in debug mode. When core is in debug mode, the PMU should refrain from sendng a halt or run request
|
||||
|
||||
// external MPC halt/run interface
|
||||
input logic mpc_debug_halt_req, // Async halt request
|
||||
input logic mpc_debug_run_req, // Async run request
|
||||
input logic mpc_reset_run_req, // Run/halt after reset
|
||||
output logic mpc_debug_halt_ack, // Halt ack
|
||||
output logic mpc_debug_run_ack, // Run ack
|
||||
output logic debug_brkpt_status, // debug breakpoint
|
||||
|
||||
|
||||
output logic dec_ib0_valid_eff_d, // effective valid taking decode into account
|
||||
output logic dec_ib1_valid_eff_d,
|
||||
|
||||
input logic exu_pmu_i0_br_misp, // slot 0 branch misp
|
||||
input logic exu_pmu_i0_br_ataken, // slot 0 branch actual taken
|
||||
input logic exu_pmu_i0_pc4, // slot 0 4 byte branch
|
||||
input logic exu_pmu_i1_br_misp, // slot 1 branch misp
|
||||
input logic exu_pmu_i1_br_ataken, // slot 1 branch actual taken
|
||||
input logic exu_pmu_i1_pc4, // slot 1 4 byte branch
|
||||
|
||||
|
||||
input logic lsu_nonblock_load_valid_dc3, // valid nonblock load at dc3
|
||||
input logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_dc3, // -> corresponding tag
|
||||
input logic lsu_nonblock_load_inv_dc5, // invalidate request for nonblock load dc5
|
||||
input logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_dc5, // -> corresponding tag
|
||||
input logic lsu_nonblock_load_data_valid, // valid nonblock load data back
|
||||
input logic lsu_nonblock_load_data_error, // nonblock load bus error
|
||||
input logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // -> corresponding tag
|
||||
input logic [31:0] lsu_nonblock_load_data, // nonblock load data
|
||||
|
||||
input logic lsu_pmu_bus_trxn, // D side bus transaction
|
||||
input logic lsu_pmu_bus_misaligned, // D side bus misaligned
|
||||
input logic lsu_pmu_bus_error, // D side bus error
|
||||
input logic lsu_pmu_bus_busy, // D side bus busy
|
||||
input logic lsu_pmu_misaligned_dc3, // D side load or store misaligned
|
||||
|
||||
input logic [1:0] ifu_pmu_instr_aligned, // aligned instructions
|
||||
input logic ifu_pmu_align_stall, // aligner stalled
|
||||
input logic ifu_pmu_fetch_stall, // fetch unit stalled
|
||||
input logic ifu_pmu_ic_miss, // icache miss
|
||||
input logic ifu_pmu_ic_hit, // icache hit
|
||||
input logic ifu_pmu_bus_error, // Instruction side bus error
|
||||
input logic ifu_pmu_bus_busy, // Instruction side bus busy
|
||||
input logic ifu_pmu_bus_trxn, // Instruction side bus transaction
|
||||
|
||||
input logic [3:0] lsu_trigger_match_dc3,
|
||||
input logic dbg_cmd_valid, // debugger abstract command valid
|
||||
input logic [1:0] dbg_cmd_size, // size of the abstract mem access debug command
|
||||
input logic dbg_cmd_write, // command is a write
|
||||
input logic [1:0] dbg_cmd_type, // command type
|
||||
input logic [31:0] dbg_cmd_addr, // command address
|
||||
input logic [1:0] dbg_cmd_wrdata, // command write data, for fence/fence_i
|
||||
|
||||
|
||||
input logic ifu_i0_icaf, // icache access fault
|
||||
input logic ifu_i1_icaf,
|
||||
input logic ifu_i0_icaf_f1, // i0 has access fault on second fetch group
|
||||
input logic ifu_i1_icaf_f1,
|
||||
input logic ifu_i0_perr, // icache parity error
|
||||
input logic ifu_i1_perr,
|
||||
input logic ifu_i0_sbecc, // icache/iccm single-bit error
|
||||
input logic ifu_i1_sbecc,
|
||||
input logic ifu_i0_dbecc, // icache/iccm double-bit error
|
||||
input logic ifu_i1_dbecc,
|
||||
|
||||
input logic lsu_freeze_dc3, // freeze pipe: decode -> dc3
|
||||
input logic lsu_idle_any, // lsu idle for fence instructions
|
||||
input logic lsu_halt_idle_any, // lsu idle for halting
|
||||
|
||||
input br_pkt_t i0_brp, // branch packet
|
||||
input br_pkt_t i1_brp,
|
||||
|
||||
input lsu_error_pkt_t lsu_error_pkt_dc3, // LSU exception/error packet
|
||||
|
||||
input logic lsu_imprecise_error_load_any, // LSU imprecise load bus error
|
||||
input logic lsu_imprecise_error_store_any, // LSU imprecise store bus error
|
||||
input logic [31:0] lsu_imprecise_error_addr_any, // LSU imprecise bus error address
|
||||
input logic lsu_freeze_external_ints_dc3, // load to side effect region
|
||||
|
||||
input logic exu_i0_flush_lower_e4, // slot 0 flush for mp
|
||||
input logic exu_i1_flush_lower_e4, // slot 1 flush for mp
|
||||
input logic [31:1] exu_i0_flush_path_e4, // slot 0 flush target for mp
|
||||
input logic [31:1] exu_i1_flush_path_e4, // slot 1 flush target for mp
|
||||
|
||||
input logic [15:0] ifu_illegal_inst, // 16b opcode for illegal inst
|
||||
|
||||
input logic exu_div_stall, // stall decode for div executing
|
||||
input logic [31:0] exu_div_result, // final div result
|
||||
input logic exu_div_finish, // cycle div finishes
|
||||
|
||||
input logic [31:0] exu_mul_result_e3, // 32b mul result
|
||||
|
||||
input logic [31:0] exu_csr_rs1_e1, // rs1 for csr instruction
|
||||
|
||||
input logic [31:0] lsu_result_dc3, // load result
|
||||
input logic [31:0] lsu_result_corr_dc4, // corrected load result
|
||||
|
||||
input logic lsu_load_stall_any, // This is for blocking loads
|
||||
input logic lsu_store_stall_any, // This is for blocking stores
|
||||
input logic dma_dccm_stall_any, // stall any load/store at decode, pmu event
|
||||
input logic dma_iccm_stall_any, // iccm stalled, pmu event
|
||||
|
||||
input logic iccm_dma_sb_error, // ICCM DMA single bit error
|
||||
|
||||
input logic exu_i0_flush_final, // slot0 flush
|
||||
input logic exu_i1_flush_final, // slot1 flush
|
||||
|
||||
input logic [31:1] exu_npc_e4, // next PC
|
||||
|
||||
input logic exu_flush_final, // final flush
|
||||
|
||||
input logic [31:0] exu_i0_result_e1, // alu result e1
|
||||
input logic [31:0] exu_i1_result_e1,
|
||||
|
||||
input logic [31:0] exu_i0_result_e4, // alu result e4
|
||||
input logic [31:0] exu_i1_result_e4,
|
||||
|
||||
|
||||
input logic ifu_i0_valid, ifu_i1_valid, // fetch valids to instruction buffer
|
||||
input logic [31:0] ifu_i0_instr, ifu_i1_instr, // fetch inst's to instruction buffer
|
||||
input logic [31:1] ifu_i0_pc, ifu_i1_pc, // pc's for instruction buffer
|
||||
input logic ifu_i0_pc4, ifu_i1_pc4, // indication of 4B or 2B for corresponding inst
|
||||
input logic [31:1] exu_i0_pc_e1, // pc's for e1 from the alu's
|
||||
input logic [31:1] exu_i1_pc_e1,
|
||||
|
||||
input logic mexintpend, // External interrupt pending
|
||||
input logic timer_int, // Timer interrupt pending (from pin)
|
||||
|
||||
input logic [7:0] pic_claimid, // PIC claimid
|
||||
input logic [3:0] pic_pl, // PIC priv level
|
||||
input logic mhwakeup, // High priority wakeup
|
||||
|
||||
output logic [3:0] dec_tlu_meicurpl, // to PIC, Current priv level
|
||||
output logic [3:0] dec_tlu_meipt, // to PIC
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
input logic [41:0] ifu_ic_debug_rd_data, // diagnostic icache read data
|
||||
`else
|
||||
input logic [33:0] ifu_ic_debug_rd_data, // diagnostic icache read data
|
||||
`endif
|
||||
input logic ifu_ic_debug_rd_data_valid, // diagnostic icache read data valid
|
||||
output cache_debug_pkt_t dec_tlu_ic_diag_pkt, // packet of DICAWICS, DICAD0/1, DICAGO info for icache diagnostics
|
||||
|
||||
|
||||
// Debug start
|
||||
input logic dbg_halt_req, // DM requests a halt
|
||||
input logic dbg_resume_req, // DM requests a resume
|
||||
input logic ifu_miss_state_idle, // I-side miss buffer empty
|
||||
|
||||
output logic dec_tlu_flush_noredir_wb , // Tell fetch to idle on this flush
|
||||
output logic dec_tlu_mpc_halted_only, // Core is halted only due to MPC
|
||||
output logic dec_tlu_dbg_halted, // Core is halted and ready for debug command
|
||||
output logic dec_tlu_pmu_fw_halted, // Core is halted due to Power management unit or firmware halt
|
||||
output logic dec_tlu_debug_mode, // Core is in debug mode
|
||||
output logic dec_tlu_resume_ack, // Resume acknowledge
|
||||
output logic dec_tlu_flush_leak_one_wb, // single step
|
||||
output logic dec_tlu_flush_err_wb, // iside perr/ecc rfpc
|
||||
output logic dec_tlu_stall_dma, // stall dma access when there's a halt request
|
||||
|
||||
output logic dec_debug_wdata_rs1_d, // insert debug write data into rs1 at decode
|
||||
|
||||
output logic [31:0] dec_dbg_rddata, // debug command read data
|
||||
|
||||
output logic dec_dbg_cmd_done, // abstract command is done
|
||||
output logic dec_dbg_cmd_fail, // abstract command failed (illegal reg address)
|
||||
|
||||
output trigger_pkt_t [3:0] trigger_pkt_any, // info needed by debug trigger blocks
|
||||
|
||||
// Debug end
|
||||
// branch info from pipe0 for errors or counter updates
|
||||
input logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] exu_i0_br_index_e4, // index
|
||||
input logic [1:0] exu_i0_br_hist_e4, // history
|
||||
input logic [1:0] exu_i0_br_bank_e4, // bank
|
||||
input logic exu_i0_br_error_e4, // error
|
||||
input logic exu_i0_br_start_error_e4, // start error
|
||||
input logic exu_i0_br_valid_e4, // valid
|
||||
input logic exu_i0_br_mp_e4, // mispredict
|
||||
input logic exu_i0_br_middle_e4, // middle of bank
|
||||
input logic [`RV_BHT_GHR_RANGE] exu_i0_br_fghr_e4, // FGHR when predicted
|
||||
|
||||
// branch info from pipe1 for errors or counter updates
|
||||
input logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] exu_i1_br_index_e4, // index
|
||||
input logic [1:0] exu_i1_br_hist_e4, // history
|
||||
input logic [1:0] exu_i1_br_bank_e4, // bank
|
||||
input logic exu_i1_br_error_e4, // error
|
||||
input logic exu_i1_br_start_error_e4, // start error
|
||||
input logic exu_i1_br_valid_e4, // valid
|
||||
input logic exu_i1_br_mp_e4, // mispredict
|
||||
input logic exu_i1_br_middle_e4, // middle of bank
|
||||
input logic [`RV_BHT_GHR_RANGE] exu_i1_br_fghr_e4, // FGHR when predicted
|
||||
|
||||
|
||||
`ifdef RV_BTB_48
|
||||
input logic [1:0] exu_i1_br_way_e4, // way hit or repl
|
||||
input logic [1:0] exu_i0_br_way_e4, // way hit or repl
|
||||
`else
|
||||
input logic exu_i1_br_way_e4, // way hit or repl
|
||||
input logic exu_i0_br_way_e4, // way hit or repl
|
||||
`endif
|
||||
|
||||
output logic [31:0] gpr_i0_rs1_d, // gpr rs1 data
|
||||
output logic [31:0] gpr_i0_rs2_d, // gpr rs2 data
|
||||
output logic [31:0] gpr_i1_rs1_d,
|
||||
output logic [31:0] gpr_i1_rs2_d,
|
||||
|
||||
output logic [31:0] dec_i0_immed_d, // immediate data
|
||||
output logic [31:0] dec_i1_immed_d,
|
||||
|
||||
output logic [12:1] dec_i0_br_immed_d, // br immediate data
|
||||
output logic [12:1] dec_i1_br_immed_d,
|
||||
|
||||
output alu_pkt_t i0_ap, // alu packet
|
||||
output alu_pkt_t i1_ap,
|
||||
|
||||
output logic dec_i0_alu_decode_d, // alu schedule on primary alu
|
||||
output logic dec_i1_alu_decode_d,
|
||||
|
||||
output logic dec_i0_select_pc_d, // select pc onto rs1 for jal's
|
||||
output logic dec_i1_select_pc_d,
|
||||
|
||||
output logic [31:1] dec_i0_pc_d, dec_i1_pc_d, // pc's at decode
|
||||
output logic dec_i0_rs1_bypass_en_d, // rs1 bypass enable
|
||||
output logic dec_i0_rs2_bypass_en_d, // rs2 bypass enable
|
||||
output logic dec_i1_rs1_bypass_en_d,
|
||||
output logic dec_i1_rs2_bypass_en_d,
|
||||
|
||||
output logic [31:0] i0_rs1_bypass_data_d, // rs1 bypass data
|
||||
output logic [31:0] i0_rs2_bypass_data_d, // rs2 bypass data
|
||||
output logic [31:0] i1_rs1_bypass_data_d,
|
||||
output logic [31:0] i1_rs2_bypass_data_d,
|
||||
output logic dec_ib3_valid_d, // ib3 buffer valid
|
||||
output logic dec_ib2_valid_d, // ib2 buffer valid
|
||||
|
||||
output lsu_pkt_t lsu_p, // lsu packet
|
||||
output mul_pkt_t mul_p, // mul packet
|
||||
output div_pkt_t div_p, // div packet
|
||||
|
||||
output logic [11:0] dec_lsu_offset_d, // 12b offset for load/store addresses
|
||||
output logic dec_i0_lsu_d, // is load/store
|
||||
output logic dec_i1_lsu_d,
|
||||
|
||||
output logic flush_final_e3, // final flush
|
||||
output logic i0_flush_final_e3, // final flush from i0
|
||||
|
||||
output logic dec_csr_ren_d, // csr read enable
|
||||
|
||||
output logic dec_tlu_cancel_e4, // Cancel lsu op at DC4 due to future trigger hit
|
||||
|
||||
output logic dec_tlu_flush_lower_wb, // tlu flush due to late mp, exception, rfpc, or int
|
||||
output logic [31:1] dec_tlu_flush_path_wb, // tlu flush target
|
||||
output logic dec_tlu_i0_kill_writeb_wb, // I0 is flushed, don't writeback any results to arch state
|
||||
output logic dec_tlu_i1_kill_writeb_wb, // I1 is flushed, don't writeback any results to arch state
|
||||
output logic dec_tlu_fence_i_wb, // flush is a fence_i rfnpc, flush icache
|
||||
|
||||
output logic dec_i0_mul_d, // chose which gpr value to use
|
||||
output logic dec_i1_mul_d,
|
||||
output logic dec_i0_div_d, // chose which gpr value to use
|
||||
output logic dec_i1_div_d,
|
||||
output logic dec_i1_valid_e1, // i1 valid at e1 stage
|
||||
output logic dec_div_decode_e4, // div at e4 stage
|
||||
output logic [31:1] pred_correct_npc_e2, // npc if prediction is correct at e2 stage
|
||||
|
||||
output logic dec_i0_rs1_bypass_en_e3, // rs1 bypass enable e3
|
||||
output logic dec_i0_rs2_bypass_en_e3, // rs2 bypass enable e3
|
||||
output logic dec_i1_rs1_bypass_en_e3,
|
||||
output logic dec_i1_rs2_bypass_en_e3,
|
||||
output logic [31:0] i0_rs1_bypass_data_e3, // rs1 bypass data e3
|
||||
output logic [31:0] i0_rs2_bypass_data_e3, // rs2 bypass data e3
|
||||
output logic [31:0] i1_rs1_bypass_data_e3,
|
||||
output logic [31:0] i1_rs2_bypass_data_e3,
|
||||
output logic dec_i0_sec_decode_e3, // secondary decode e3
|
||||
output logic dec_i1_sec_decode_e3,
|
||||
output logic [31:1] dec_i0_pc_e3, // pc at e3
|
||||
output logic [31:1] dec_i1_pc_e3,
|
||||
|
||||
output logic dec_i0_rs1_bypass_en_e2, // rs1 bypass enable e2
|
||||
output logic dec_i0_rs2_bypass_en_e2, // rs2 bypass enable e2
|
||||
output logic dec_i1_rs1_bypass_en_e2,
|
||||
output logic dec_i1_rs2_bypass_en_e2,
|
||||
output logic [31:0] i0_rs1_bypass_data_e2, // rs1 bypass data e2
|
||||
output logic [31:0] i0_rs2_bypass_data_e2, // rs2 bypass data e2
|
||||
output logic [31:0] i1_rs1_bypass_data_e2,
|
||||
output logic [31:0] i1_rs2_bypass_data_e2,
|
||||
|
||||
output br_tlu_pkt_t dec_tlu_br0_wb_pkt, // slot 0 branch predictor update packet
|
||||
output br_tlu_pkt_t dec_tlu_br1_wb_pkt, // slot 1 branch predictor update packet
|
||||
|
||||
output logic [1:0] dec_tlu_perfcnt0, // toggles when perf counter 0 has an event inc
|
||||
output logic [1:0] dec_tlu_perfcnt1, // toggles when perf counter 1 has an event inc
|
||||
output logic [1:0] dec_tlu_perfcnt2, // toggles when perf counter 2 has an event inc
|
||||
output logic [1:0] dec_tlu_perfcnt3, // toggles when perf counter 3 has an event inc
|
||||
|
||||
output predict_pkt_t i0_predict_p_d, // prediction packet to alus
|
||||
output predict_pkt_t i1_predict_p_d,
|
||||
|
||||
output logic dec_i0_lsu_decode_d, // load/store decode
|
||||
|
||||
output logic [31:0] i0_result_e4_eff, // alu result e4
|
||||
output logic [31:0] i1_result_e4_eff,
|
||||
|
||||
output logic dec_tlu_i0_valid_e4, // slot 0 instruction is valid at e4
|
||||
output logic dec_tlu_i1_valid_e4, // slot 1 instruction is valid at e4, implies i0_valid_e4
|
||||
|
||||
output logic [31:0] i0_result_e2, // i0 result data e2
|
||||
output logic [31:0] dec_tlu_mrac_ff, // CSR for memory region control
|
||||
|
||||
output logic [31:1] dec_tlu_i0_pc_e4, // pc e4
|
||||
output logic [31:1] dec_tlu_i1_pc_e4,
|
||||
|
||||
output logic [4:2] dec_i0_data_en, // clock-gate control logic
|
||||
output logic [4:1] dec_i0_ctl_en,
|
||||
output logic [4:2] dec_i1_data_en,
|
||||
output logic [4:1] dec_i1_ctl_en,
|
||||
|
||||
output logic dec_nonblock_load_freeze_dc2, // lsu must freeze nonblock load due to younger dependency in pipe
|
||||
|
||||
input logic [15:0] ifu_i0_cinst, // 16b compressed instruction
|
||||
input logic [15:0] ifu_i1_cinst,
|
||||
|
||||
output trace_pkt_t trace_rv_trace_pkt, // trace packet
|
||||
|
||||
// feature disable from mfdc
|
||||
output logic dec_tlu_sideeffect_posted_disable, // disable posted writes to side-effect address
|
||||
output logic dec_tlu_core_ecc_disable, // disable core ECC
|
||||
output logic dec_tlu_sec_alu_disable, // disable secondary ALU
|
||||
output logic dec_tlu_non_blocking_disable, // disable non blocking loads
|
||||
output logic dec_tlu_fast_div_disable, // disable fast divider
|
||||
output logic dec_tlu_bpred_disable, // disable branch prediction
|
||||
output logic dec_tlu_wb_coalescing_disable, // disable writebuffer coalescing
|
||||
output logic dec_tlu_ld_miss_byp_wb_disable, // disable loads miss bypass write buffer
|
||||
output logic [2:0] dec_tlu_dma_qos_prty, // DMA QoS priority coming from MFDC [18:16]
|
||||
|
||||
// clock gating overrides from mcgc
|
||||
output logic dec_tlu_misc_clk_override, // override misc clock domain gating
|
||||
output logic dec_tlu_exu_clk_override, // override exu clock domain gating
|
||||
output logic dec_tlu_ifu_clk_override, // override fetch clock domain gating
|
||||
output logic dec_tlu_lsu_clk_override, // override load/store clock domain gating
|
||||
output logic dec_tlu_bus_clk_override, // override bus clock domain gating
|
||||
output logic dec_tlu_pic_clk_override, // override PIC clock domain gating
|
||||
output logic dec_tlu_dccm_clk_override, // override DCCM clock domain gating
|
||||
output logic dec_tlu_icm_clk_override, // override ICCM clock domain gating
|
||||
|
||||
input logic scan_mode
|
||||
|
||||
);
|
||||
|
||||
localparam GPR_BANKS = 1;
|
||||
localparam GPR_BANKS_LOG2 = (GPR_BANKS == 1) ? 1 : $clog2(GPR_BANKS);
|
||||
|
||||
logic dec_tlu_dec_clk_override; // to and from dec blocks
|
||||
logic clk_override;
|
||||
|
||||
logic dec_ib1_valid_d;
|
||||
logic dec_ib0_valid_d;
|
||||
|
||||
logic [1:0] dec_pmu_instr_decoded;
|
||||
logic dec_pmu_decode_stall;
|
||||
logic dec_pmu_presync_stall;
|
||||
logic dec_pmu_postsync_stall;
|
||||
|
||||
logic dec_tlu_wr_pause_wb; // CSR write to pause reg is at WB.
|
||||
|
||||
logic dec_i0_rs1_en_d;
|
||||
logic dec_i0_rs2_en_d;
|
||||
logic dec_fence_pending; // tell TLU to stall DMA
|
||||
|
||||
logic [4:0] dec_i0_rs1_d;
|
||||
logic [4:0] dec_i0_rs2_d;
|
||||
|
||||
|
||||
logic dec_i1_rs1_en_d;
|
||||
logic dec_i1_rs2_en_d;
|
||||
|
||||
logic [4:0] dec_i1_rs1_d;
|
||||
logic [4:0] dec_i1_rs2_d;
|
||||
|
||||
|
||||
logic [31:0] dec_i0_instr_d, dec_i1_instr_d;
|
||||
|
||||
logic dec_tlu_pipelining_disable;
|
||||
logic dec_tlu_dual_issue_disable;
|
||||
|
||||
|
||||
logic [4:0] dec_i0_waddr_wb;
|
||||
logic dec_i0_wen_wb;
|
||||
logic [31:0] dec_i0_wdata_wb;
|
||||
|
||||
logic [4:0] dec_i1_waddr_wb;
|
||||
logic dec_i1_wen_wb;
|
||||
logic [31:0] dec_i1_wdata_wb;
|
||||
|
||||
logic dec_csr_wen_wb; // csr write enable at wb
|
||||
logic [11:0] dec_csr_rdaddr_d; // read address for csr
|
||||
logic [11:0] dec_csr_wraddr_wb; // write address for csryes
|
||||
|
||||
logic [31:0] dec_csr_wrdata_wb; // csr write data at wb
|
||||
|
||||
logic [31:0] dec_csr_rddata_d; // csr read data at wb
|
||||
logic dec_csr_legal_d; // csr indicates legal operation
|
||||
|
||||
logic dec_csr_wen_unq_d; // valid csr with write - for csr legal
|
||||
logic dec_csr_any_unq_d; // valid csr - for csr legal
|
||||
logic dec_csr_stall_int_ff; // csr is mie/mstatus
|
||||
|
||||
|
||||
|
||||
trap_pkt_t dec_tlu_packet_e4;
|
||||
|
||||
logic dec_i0_pc4_d, dec_i1_pc4_d;
|
||||
logic dec_tlu_presync_d;
|
||||
logic dec_tlu_postsync_d;
|
||||
logic dec_tlu_debug_stall;
|
||||
|
||||
logic [31:0] dec_illegal_inst;
|
||||
|
||||
|
||||
// GPR Bank ID write signals
|
||||
logic wen_bank_id;
|
||||
logic [GPR_BANKS_LOG2-1:0] wr_bank_id;
|
||||
|
||||
logic dec_i0_icaf_d;
|
||||
logic dec_i1_icaf_d;
|
||||
logic dec_i0_perr_d;
|
||||
logic dec_i1_perr_d;
|
||||
logic dec_i0_sbecc_d;
|
||||
logic dec_i1_sbecc_d;
|
||||
logic dec_i0_dbecc_d;
|
||||
logic dec_i1_dbecc_d;
|
||||
|
||||
logic dec_i0_icaf_f1_d;
|
||||
|
||||
logic dec_i0_decode_d;
|
||||
logic dec_i1_decode_d;
|
||||
|
||||
logic [3:0] dec_i0_trigger_match_d;
|
||||
logic [3:0] dec_i1_trigger_match_d;
|
||||
|
||||
|
||||
logic dec_debug_fence_d;
|
||||
|
||||
logic dec_nonblock_load_wen;
|
||||
logic [4:0] dec_nonblock_load_waddr;
|
||||
logic dec_tlu_flush_pause_wb;
|
||||
|
||||
logic dec_i0_load_e4;
|
||||
|
||||
logic dec_pause_state;
|
||||
|
||||
br_pkt_t dec_i0_brp;
|
||||
br_pkt_t dec_i1_brp;
|
||||
|
||||
assign clk_override = dec_tlu_dec_clk_override;
|
||||
|
||||
|
||||
assign dec_dbg_rddata[31:0] = dec_i0_wdata_wb[31:0];
|
||||
|
||||
dec_ib_ctl instbuff (.*
|
||||
);
|
||||
|
||||
dec_decode_ctl decode (.*);
|
||||
|
||||
dec_tlu_ctl tlu (.*);
|
||||
|
||||
// Temp hookups
|
||||
assign wen_bank_id = '0;
|
||||
assign wr_bank_id = '0;
|
||||
|
||||
|
||||
|
||||
dec_gpr_ctl #(.GPR_BANKS(GPR_BANKS),
|
||||
.GPR_BANKS_LOG2(GPR_BANKS_LOG2)) arf (.*,
|
||||
// inputs
|
||||
.raddr0(dec_i0_rs1_d[4:0]), .rden0(dec_i0_rs1_en_d),
|
||||
.raddr1(dec_i0_rs2_d[4:0]), .rden1(dec_i0_rs2_en_d),
|
||||
.raddr2(dec_i1_rs1_d[4:0]), .rden2(dec_i1_rs1_en_d),
|
||||
.raddr3(dec_i1_rs2_d[4:0]), .rden3(dec_i1_rs2_en_d),
|
||||
|
||||
.waddr0(dec_i0_waddr_wb[4:0]), .wen0(dec_i0_wen_wb), .wd0(dec_i0_wdata_wb[31:0]),
|
||||
.waddr1(dec_i1_waddr_wb[4:0]), .wen1(dec_i1_wen_wb), .wd1(dec_i1_wdata_wb[31:0]),
|
||||
.waddr2(dec_nonblock_load_waddr[4:0]), .wen2(dec_nonblock_load_wen), .wd2(lsu_nonblock_load_data[31:0]),
|
||||
|
||||
// outputs
|
||||
.rd0(gpr_i0_rs1_d[31:0]), .rd1(gpr_i0_rs2_d[31:0]),
|
||||
.rd2(gpr_i1_rs1_d[31:0]), .rd3(gpr_i1_rs2_d[31:0])
|
||||
);
|
||||
|
||||
// Trigger
|
||||
|
||||
dec_trigger dec_trigger (.*);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// trace
|
||||
logic [15:0] dec_i0_cinst_d;
|
||||
logic [15:0] dec_i1_cinst_d;
|
||||
logic [31:0] dec_i0_inst_wb1;
|
||||
logic [31:0] dec_i1_inst_wb1;
|
||||
logic [31:1] dec_i0_pc_wb1;
|
||||
logic [31:1] dec_i1_pc_wb1;
|
||||
logic dec_tlu_i1_valid_wb1, dec_tlu_i0_valid_wb1, dec_tlu_int_valid_wb1;
|
||||
logic [4:0] dec_tlu_exc_cause_wb1;
|
||||
logic [31:0] dec_tlu_mtval_wb1;
|
||||
|
||||
logic dec_tlu_i0_exc_valid_wb1, dec_tlu_i1_exc_valid_wb1;
|
||||
|
||||
// also need retires_p==3
|
||||
|
||||
assign trace_rv_trace_pkt.trace_rv_i_insn_ip = { 32'b0, dec_i1_inst_wb1[31:0], dec_i0_inst_wb1[31:0] };
|
||||
assign trace_rv_trace_pkt.trace_rv_i_address_ip = { 32'b0, dec_i1_pc_wb1[31:1], 1'b0, dec_i0_pc_wb1[31:1], 1'b0 };
|
||||
|
||||
assign trace_rv_trace_pkt.trace_rv_i_valid_ip = {dec_tlu_int_valid_wb1, // always int
|
||||
dec_tlu_i1_valid_wb1 | dec_tlu_i1_exc_valid_wb1, // not interrupts
|
||||
dec_tlu_i0_valid_wb1 | dec_tlu_i0_exc_valid_wb1
|
||||
};
|
||||
assign trace_rv_trace_pkt.trace_rv_i_exception_ip = {dec_tlu_int_valid_wb1, dec_tlu_i1_exc_valid_wb1, dec_tlu_i0_exc_valid_wb1};
|
||||
assign trace_rv_trace_pkt.trace_rv_i_ecause_ip = dec_tlu_exc_cause_wb1[4:0]; // replicate across ports
|
||||
assign trace_rv_trace_pkt.trace_rv_i_interrupt_ip = {dec_tlu_int_valid_wb1,2'b0};
|
||||
assign trace_rv_trace_pkt.trace_rv_i_tval_ip = dec_tlu_mtval_wb1[31:0]; // replicate across ports
|
||||
|
||||
|
||||
|
||||
// end trace
|
||||
|
||||
endmodule // dec
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,113 @@
|
|||
// 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.
|
||||
|
||||
module dec_gpr_ctl #(parameter GPR_BANKS = 1,
|
||||
GPR_BANKS_LOG2 = 1) (
|
||||
input logic active_clk,
|
||||
|
||||
input logic [4:0] raddr0, // logical read addresses
|
||||
input logic [4:0] raddr1,
|
||||
input logic [4:0] raddr2,
|
||||
input logic [4:0] raddr3,
|
||||
|
||||
input logic rden0, // read enables
|
||||
input logic rden1,
|
||||
input logic rden2,
|
||||
input logic rden3,
|
||||
|
||||
input logic [4:0] waddr0, // logical write addresses
|
||||
input logic [4:0] waddr1,
|
||||
input logic [4:0] waddr2,
|
||||
|
||||
input logic wen0, // write enables
|
||||
input logic wen1,
|
||||
input logic wen2,
|
||||
|
||||
input logic [31:0] wd0, // write data
|
||||
input logic [31:0] wd1,
|
||||
input logic [31:0] wd2,
|
||||
|
||||
input logic wen_bank_id, // write enable for banks
|
||||
input logic [GPR_BANKS_LOG2-1:0] wr_bank_id, // read enable for banks
|
||||
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
|
||||
output logic [31:0] rd0, // read data
|
||||
output logic [31:0] rd1,
|
||||
output logic [31:0] rd2,
|
||||
output logic [31:0] rd3,
|
||||
|
||||
input logic scan_mode
|
||||
);
|
||||
|
||||
logic [GPR_BANKS-1:0][31:1] [31:0] gpr_out; // 31 x 32 bit GPRs
|
||||
logic [31:1] [31:0] gpr_in;
|
||||
logic [31:1] w0v,w1v,w2v;
|
||||
logic [31:1] gpr_wr_en;
|
||||
logic [GPR_BANKS-1:0][31:1] gpr_bank_wr_en;
|
||||
logic [GPR_BANKS_LOG2-1:0] gpr_bank_id;
|
||||
|
||||
//assign gpr_bank_id[GPR_BANKS_LOG2-1:0] = '0;
|
||||
rvdffs #(GPR_BANKS_LOG2) bankid_ff (.*, .clk(active_clk), .en(wen_bank_id), .din(wr_bank_id[GPR_BANKS_LOG2-1:0]), .dout(gpr_bank_id[GPR_BANKS_LOG2-1:0]));
|
||||
|
||||
// GPR Write Enables for power savings
|
||||
assign gpr_wr_en[31:1] = (w0v[31:1] | w1v[31:1] | w2v[31:1]);
|
||||
for (genvar i=0; i<GPR_BANKS; i++) begin: gpr_banks
|
||||
assign gpr_bank_wr_en[i][31:1] = gpr_wr_en[31:1] & {31{gpr_bank_id[GPR_BANKS_LOG2-1:0] == i}};
|
||||
for ( genvar j=1; j<32; j++ ) begin : gpr
|
||||
rvdffe #(32) gprff (.*, .en(gpr_bank_wr_en[i][j]), .din(gpr_in[j][31:0]), .dout(gpr_out[i][j][31:0]));
|
||||
end : gpr
|
||||
end: gpr_banks
|
||||
|
||||
// the read out
|
||||
always_comb begin
|
||||
rd0[31:0] = 32'b0;
|
||||
rd1[31:0] = 32'b0;
|
||||
rd2[31:0] = 32'b0;
|
||||
rd3[31:0] = 32'b0;
|
||||
w0v[31:1] = 31'b0;
|
||||
w1v[31:1] = 31'b0;
|
||||
w2v[31:1] = 31'b0;
|
||||
gpr_in[31:1] = '0;
|
||||
|
||||
// GPR Read logic
|
||||
for (int i=0; i<GPR_BANKS; i++) begin
|
||||
for (int j=1; j<32; j++ ) begin
|
||||
rd0[31:0] |= ({32{rden0 & (raddr0[4:0]== 5'(j)) & (gpr_bank_id[GPR_BANKS_LOG2-1:0] == 1'(i))}} & gpr_out[i][j][31:0]);
|
||||
rd1[31:0] |= ({32{rden1 & (raddr1[4:0]== 5'(j)) & (gpr_bank_id[GPR_BANKS_LOG2-1:0] == 1'(i))}} & gpr_out[i][j][31:0]);
|
||||
rd2[31:0] |= ({32{rden2 & (raddr2[4:0]== 5'(j)) & (gpr_bank_id[GPR_BANKS_LOG2-1:0] == 1'(i))}} & gpr_out[i][j][31:0]);
|
||||
rd3[31:0] |= ({32{rden3 & (raddr3[4:0]== 5'(j)) & (gpr_bank_id[GPR_BANKS_LOG2-1:0] == 1'(i))}} & gpr_out[i][j][31:0]);
|
||||
end
|
||||
end
|
||||
|
||||
// GPR Write logic
|
||||
for (int j=1; j<32; j++ ) begin
|
||||
w0v[j] = wen0 & (waddr0[4:0]== 5'(j) );
|
||||
w1v[j] = wen1 & (waddr1[4:0]== 5'(j) );
|
||||
w2v[j] = wen2 & (waddr2[4:0]== 5'(j) );
|
||||
gpr_in[j] = ({32{w0v[j]}} & wd0[31:0]) |
|
||||
({32{w1v[j]}} & wd1[31:0]) |
|
||||
({32{w2v[j]}} & wd2[31:0]);
|
||||
end
|
||||
end // always_comb begin
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
// asserting that no 2 ports will write to the same gpr simultaneously
|
||||
assert_multiple_wen_to_same_gpr: assert #0 (~( ((w0v[31:1] == w1v[31:1]) & wen0 & wen1) | ((w0v[31:1] == w2v[31:1]) & wen0 & wen2) | ((w1v[31:1] == w2v[31:1]) & wen1 & wen2) ) );
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,463 @@
|
|||
// 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.
|
||||
|
||||
module dec_ib_ctl
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic free_clk, // free clk
|
||||
input logic active_clk, // active clk if not halt / pause
|
||||
|
||||
input logic dbg_cmd_valid, // valid dbg cmd
|
||||
|
||||
input logic dbg_cmd_write, // dbg cmd is write
|
||||
input logic [1:0] dbg_cmd_type, // dbg type
|
||||
input logic [1:0] dbg_cmd_size, // 00 - 1B, 01 - 2B, 10 - 4B, 11 - reserved
|
||||
input logic [31:0] dbg_cmd_addr, // expand to 31:0
|
||||
|
||||
input logic exu_flush_final, // all flush sources: primary/secondary alu's, trap
|
||||
|
||||
input logic dec_ib0_valid_eff_d, // effective valid taking decode into account
|
||||
input logic dec_ib1_valid_eff_d,
|
||||
|
||||
input br_pkt_t i0_brp, // i0 branch packet from aligner
|
||||
input br_pkt_t i1_brp,
|
||||
|
||||
input logic ifu_i0_pc4, // i0 is 4B inst else 2B
|
||||
input logic ifu_i1_pc4,
|
||||
|
||||
input logic ifu_i0_valid, // i0 valid from ifu
|
||||
input logic ifu_i1_valid,
|
||||
|
||||
input logic ifu_i0_icaf, // i0 instruction access fault
|
||||
input logic ifu_i1_icaf,
|
||||
input logic ifu_i0_icaf_f1, // i0 has access fault on second fetch group
|
||||
input logic ifu_i1_icaf_f1,
|
||||
input logic ifu_i0_perr, // i0 instruction parity error
|
||||
input logic ifu_i1_perr,
|
||||
input logic ifu_i0_sbecc, // i0 single-bit error
|
||||
input logic ifu_i1_sbecc,
|
||||
input logic ifu_i0_dbecc, // i0 double-bit error
|
||||
input logic ifu_i1_dbecc,
|
||||
|
||||
input logic [31:0] ifu_i0_instr, // i0 instruction from the aligner
|
||||
input logic [31:0] ifu_i1_instr,
|
||||
|
||||
input logic [31:1] ifu_i0_pc, // i0 pc from the aligner
|
||||
input logic [31:1] ifu_i1_pc,
|
||||
|
||||
input logic dec_i0_decode_d, // i0 decode
|
||||
input logic dec_i1_decode_d,
|
||||
|
||||
|
||||
input logic rst_l, // test stuff
|
||||
input logic clk,
|
||||
|
||||
|
||||
output logic dec_ib3_valid_d, // ib3 valid
|
||||
output logic dec_ib2_valid_d, // ib2 valid
|
||||
output logic dec_ib1_valid_d, // ib1 valid
|
||||
output logic dec_ib0_valid_d, // ib0 valid
|
||||
|
||||
|
||||
output logic [31:0] dec_i0_instr_d, // i0 inst at decode
|
||||
output logic [31:0] dec_i1_instr_d, // i1 inst at decode
|
||||
|
||||
output logic [31:1] dec_i0_pc_d, // i0 pc at decode
|
||||
output logic [31:1] dec_i1_pc_d,
|
||||
|
||||
output logic dec_i0_pc4_d, // i0 is 4B inst else 2B
|
||||
output logic dec_i1_pc4_d,
|
||||
|
||||
output br_pkt_t dec_i0_brp, // i0 branch packet at decode
|
||||
output br_pkt_t dec_i1_brp,
|
||||
|
||||
output logic dec_i0_icaf_d, // i0 instruction access fault at decode
|
||||
output logic dec_i1_icaf_d,
|
||||
output logic dec_i0_icaf_f1_d, // i0 instruction access fault at decode for f1 fetch group
|
||||
output logic dec_i0_perr_d, // i0 instruction parity error at decode
|
||||
output logic dec_i1_perr_d,
|
||||
output logic dec_i0_sbecc_d, // i0 single-bit error at decode
|
||||
output logic dec_i1_sbecc_d,
|
||||
output logic dec_i0_dbecc_d, // i0 double-bit error at decode
|
||||
output logic dec_i1_dbecc_d,
|
||||
output logic dec_debug_wdata_rs1_d, // put debug write data onto rs1 source: machine is halted
|
||||
|
||||
output logic dec_debug_fence_d, // debug fence inst
|
||||
|
||||
input logic [15:0] ifu_i0_cinst, // 16b compressed inst from aligner
|
||||
input logic [15:0] ifu_i1_cinst,
|
||||
|
||||
output logic [15:0] dec_i0_cinst_d, // 16b compress inst at decode
|
||||
output logic [15:0] dec_i1_cinst_d,
|
||||
|
||||
input logic scan_mode
|
||||
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
logic flush_final;
|
||||
|
||||
logic [3:0] ibval_in, ibval;
|
||||
|
||||
logic [31:0] ib3_in, ib2_in, ib1_in, ib0_in;
|
||||
logic [31:0] ib3, ib2, ib1, ib0;
|
||||
|
||||
logic [36:0] pc3_in, pc2_in, pc1_in, pc0_in;
|
||||
logic [36:0] pc3, pc2, pc1, pc0;
|
||||
|
||||
logic [15:0] cinst3_in, cinst2_in, cinst1_in, cinst0_in;
|
||||
logic [15:0] cinst3, cinst2, cinst1, cinst0;
|
||||
|
||||
logic write_i1_ib3, write_i0_ib3;
|
||||
logic write_i1_ib2, write_i0_ib2;
|
||||
logic write_i1_ib1, write_i0_ib1;
|
||||
logic write_i0_ib0;
|
||||
|
||||
logic shift2, shift1, shift0;
|
||||
|
||||
logic shift_ib1_ib0, shift_ib2_ib1, shift_ib3_ib2;
|
||||
logic shift_ib2_ib0;
|
||||
logic shift_ib3_ib1;
|
||||
|
||||
|
||||
logic ifu_i0_val, ifu_i1_val;
|
||||
logic debug_valid;
|
||||
logic [4:0] dreg;
|
||||
logic [11:0] dcsr;
|
||||
logic [31:0] ib0_debug_in;
|
||||
|
||||
// logic debug_read_mem;
|
||||
// logic debug_write_mem;
|
||||
logic debug_read;
|
||||
logic debug_write;
|
||||
logic debug_read_gpr;
|
||||
logic debug_write_gpr;
|
||||
logic debug_read_csr;
|
||||
logic debug_write_csr;
|
||||
|
||||
|
||||
|
||||
rvdff #(1) flush_upperff (.*, .clk(free_clk), .din(exu_flush_final), .dout(flush_final));
|
||||
|
||||
logic [3:0] ibvalid;
|
||||
|
||||
logic [3:0] i0_wen;
|
||||
logic [3:1] i1_wen;
|
||||
logic [3:0] shift_ibval;
|
||||
logic [3:0] ibwrite;
|
||||
|
||||
assign ibvalid[3:0] = ibval[3:0] | i0_wen[3:0] | {i1_wen[3:1],1'b0};
|
||||
|
||||
assign ibval_in[3:0] = (({4{shift0}} & ibvalid[3:0]) |
|
||||
({4{shift1}} & {1'b0, ibvalid[3:1]}) |
|
||||
({4{shift2}} & {2'b0, ibvalid[3:2]})) & ~{4{flush_final}};
|
||||
|
||||
rvdff #(4) ibvalff (.*, .clk(active_clk), .din(ibval_in[3:0]), .dout(ibval[3:0]));
|
||||
|
||||
// only valid if there is room
|
||||
if (DEC_INSTBUF_DEPTH==4) begin
|
||||
assign ifu_i0_val = ifu_i0_valid & ~ibval[3] & ~flush_final;
|
||||
assign ifu_i1_val = ifu_i1_valid & ~ibval[2] & ~flush_final;
|
||||
end
|
||||
else begin
|
||||
assign ifu_i0_val = ifu_i0_valid & (~dec_ib0_valid_eff_d | ~dec_ib1_valid_eff_d) & ~flush_final;
|
||||
assign ifu_i1_val = ifu_i1_valid & (~dec_ib0_valid_eff_d & ~dec_ib1_valid_eff_d) & ~flush_final;
|
||||
end
|
||||
|
||||
|
||||
assign i0_wen[0] = ~ibval[0] & (ifu_i0_val | debug_valid);
|
||||
assign i0_wen[1] = ibval[0] & ~ibval[1] & ifu_i0_val;
|
||||
assign i0_wen[2] = ibval[1] & ~ibval[2] & ifu_i0_val;
|
||||
assign i0_wen[3] = ibval[2] & ~ibval[3] & ifu_i0_val;
|
||||
|
||||
assign i1_wen[1] = ~ibval[0] & ifu_i1_val;
|
||||
assign i1_wen[2] = ibval[0] & ~ibval[1] & ifu_i1_val;
|
||||
assign i1_wen[3] = ibval[1] & ~ibval[2] & ifu_i1_val;
|
||||
|
||||
|
||||
// start trace
|
||||
|
||||
if (DEC_INSTBUF_DEPTH==4) begin
|
||||
assign cinst3_in[15:0] = ({16{write_i0_ib3}} & ifu_i0_cinst[15:0]) |
|
||||
({16{write_i1_ib3}} & ifu_i1_cinst[15:0]);
|
||||
|
||||
rvdffe #(16) cinst3ff (.*, .en(ibwrite[3]), .din(cinst3_in[15:0]), .dout(cinst3[15:0]));
|
||||
|
||||
assign cinst2_in[15:0] = ({16{write_i0_ib2}} & ifu_i0_cinst[15:0]) |
|
||||
({16{write_i1_ib2}} & ifu_i1_cinst[15:0]) |
|
||||
({16{shift_ib3_ib2}} & cinst3[15:0]);
|
||||
|
||||
rvdffe #(16) cinst2ff (.*, .en(ibwrite[2]), .din(cinst2_in[15:0]), .dout(cinst2[15:0]));
|
||||
end // if (DEC_INSTBUF_DEPTH==4)
|
||||
else begin
|
||||
assign cinst3 = '0;
|
||||
assign cinst2 = '0;
|
||||
end
|
||||
|
||||
assign cinst1_in[15:0] = ({16{write_i0_ib1}} & ifu_i0_cinst[15:0]) |
|
||||
({16{write_i1_ib1}} & ifu_i1_cinst[15:0]) |
|
||||
({16{shift_ib2_ib1}} & cinst2[15:0]) |
|
||||
({16{shift_ib3_ib1}} & cinst3[15:0]);
|
||||
|
||||
rvdffe #(16) cinst1ff (.*, .en(ibwrite[1]), .din(cinst1_in[15:0]), .dout(cinst1[15:0]));
|
||||
|
||||
|
||||
assign cinst0_in[15:0] = ({16{write_i0_ib0}} & ifu_i0_cinst[15:0]) |
|
||||
({16{shift_ib1_ib0}} & cinst1[15:0]) |
|
||||
({16{shift_ib2_ib0}} & cinst2[15:0]);
|
||||
|
||||
rvdffe #(16) cinst0ff (.*, .en(ibwrite[0]), .din(cinst0_in[15:0]), .dout(cinst0[15:0]));
|
||||
|
||||
assign dec_i0_cinst_d[15:0] = cinst0[15:0];
|
||||
|
||||
assign dec_i1_cinst_d[15:0] = cinst1[15:0];
|
||||
|
||||
// end trace
|
||||
|
||||
|
||||
// pc tracking
|
||||
|
||||
|
||||
assign ibwrite[3:0] = { write_i0_ib3 | write_i1_ib3,
|
||||
write_i0_ib2 | write_i1_ib2 | shift_ib3_ib2,
|
||||
write_i0_ib1 | write_i1_ib1 | shift_ib2_ib1 | shift_ib3_ib1,
|
||||
write_i0_ib0 | shift_ib1_ib0 | shift_ib2_ib0
|
||||
};
|
||||
|
||||
logic [36:0] ifu_i1_pcdata, ifu_i0_pcdata;
|
||||
|
||||
assign ifu_i1_pcdata[36:0] = { ifu_i1_icaf_f1, ifu_i1_dbecc, ifu_i1_sbecc, ifu_i1_perr, ifu_i1_icaf,
|
||||
ifu_i1_pc[31:1], ifu_i1_pc4 };
|
||||
assign ifu_i0_pcdata[36:0] = { ifu_i0_icaf_f1, ifu_i0_dbecc, ifu_i0_sbecc, ifu_i0_perr, ifu_i0_icaf,
|
||||
ifu_i0_pc[31:1], ifu_i0_pc4 };
|
||||
|
||||
if (DEC_INSTBUF_DEPTH==4) begin
|
||||
assign pc3_in[36:0] = ({37{write_i0_ib3}} & ifu_i0_pcdata[36:0]) |
|
||||
({37{write_i1_ib3}} & ifu_i1_pcdata[36:0]);
|
||||
|
||||
rvdffe #(37) pc3ff (.*, .en(ibwrite[3]), .din(pc3_in[36:0]), .dout(pc3[36:0]));
|
||||
|
||||
assign pc2_in[36:0] = ({37{write_i0_ib2}} & ifu_i0_pcdata[36:0]) |
|
||||
({37{write_i1_ib2}} & ifu_i1_pcdata[36:0]) |
|
||||
({37{shift_ib3_ib2}} & pc3[36:0]);
|
||||
|
||||
rvdffe #(37) pc2ff (.*, .en(ibwrite[2]), .din(pc2_in[36:0]), .dout(pc2[36:0]));
|
||||
end // if (DEC_INSTBUF_DEPTH==4)
|
||||
else begin
|
||||
assign pc3 = '0;
|
||||
assign pc2 = '0;
|
||||
end
|
||||
|
||||
assign pc1_in[36:0] = ({37{write_i0_ib1}} & ifu_i0_pcdata[36:0]) |
|
||||
({37{write_i1_ib1}} & ifu_i1_pcdata[36:0]) |
|
||||
({37{shift_ib2_ib1}} & pc2[36:0]) |
|
||||
({37{shift_ib3_ib1}} & pc3[36:0]);
|
||||
|
||||
rvdffe #(37) pc1ff (.*, .en(ibwrite[1]), .din(pc1_in[36:0]), .dout(pc1[36:0]));
|
||||
|
||||
|
||||
assign pc0_in[36:0] = ({37{write_i0_ib0}} & ifu_i0_pcdata[36:0]) |
|
||||
({37{shift_ib1_ib0}} & pc1[36:0]) |
|
||||
({37{shift_ib2_ib0}} & pc2[36:0]);
|
||||
|
||||
rvdffe #(37) pc0ff (.*, .en(ibwrite[0]), .din(pc0_in[36:0]), .dout(pc0[36:0]));
|
||||
|
||||
assign dec_i0_icaf_f1_d = pc0[36]; // icaf's can only decode as i0
|
||||
|
||||
assign dec_i1_dbecc_d = pc1[35];
|
||||
assign dec_i0_dbecc_d = pc0[35];
|
||||
|
||||
assign dec_i1_sbecc_d = pc1[34];
|
||||
assign dec_i0_sbecc_d = pc0[34];
|
||||
|
||||
assign dec_i1_perr_d = pc1[33];
|
||||
assign dec_i0_perr_d = pc0[33];
|
||||
|
||||
assign dec_i1_icaf_d = pc1[32];
|
||||
assign dec_i0_icaf_d = pc0[32];
|
||||
|
||||
assign dec_i1_pc_d[31:1] = pc1[31:1];
|
||||
assign dec_i0_pc_d[31:1] = pc0[31:1];
|
||||
|
||||
assign dec_i1_pc4_d = pc1[0];
|
||||
assign dec_i0_pc4_d = pc0[0];
|
||||
|
||||
// branch prediction
|
||||
|
||||
logic [$bits(br_pkt_t)-1:0] bp3_in,bp3,bp2_in,bp2,bp1_in,bp1,bp0_in,bp0;
|
||||
|
||||
if (DEC_INSTBUF_DEPTH==4) begin
|
||||
assign bp3_in = ({$bits(br_pkt_t){write_i0_ib3}} & i0_brp) |
|
||||
({$bits(br_pkt_t){write_i1_ib3}} & i1_brp);
|
||||
|
||||
rvdffe #($bits(br_pkt_t)) bp3ff (.*, .en(ibwrite[3]), .din(bp3_in), .dout(bp3));
|
||||
|
||||
assign bp2_in = ({$bits(br_pkt_t){write_i0_ib2}} & i0_brp) |
|
||||
({$bits(br_pkt_t){write_i1_ib2}} & i1_brp) |
|
||||
({$bits(br_pkt_t){shift_ib3_ib2}} & bp3);
|
||||
|
||||
rvdffe #($bits(br_pkt_t)) bp2ff (.*, .en(ibwrite[2]), .din(bp2_in), .dout(bp2));
|
||||
end // if (DEC_INSTBUF_DEPTH==4)
|
||||
else begin
|
||||
assign bp3 = '0;
|
||||
assign bp2 = '0;
|
||||
end
|
||||
|
||||
assign bp1_in = ({$bits(br_pkt_t){write_i0_ib1}} & i0_brp) |
|
||||
({$bits(br_pkt_t){write_i1_ib1}} & i1_brp) |
|
||||
({$bits(br_pkt_t){shift_ib2_ib1}} & bp2) |
|
||||
({$bits(br_pkt_t){shift_ib3_ib1}} & bp3);
|
||||
|
||||
rvdffe #($bits(br_pkt_t)) bp1ff (.*, .en(ibwrite[1]), .din(bp1_in), .dout(bp1));
|
||||
|
||||
|
||||
|
||||
assign bp0_in = ({$bits(br_pkt_t){write_i0_ib0}} & i0_brp) |
|
||||
({$bits(br_pkt_t){shift_ib1_ib0}} & bp1) |
|
||||
({$bits(br_pkt_t){shift_ib2_ib0}} & bp2);
|
||||
|
||||
rvdffe #($bits(br_pkt_t)) bp0ff (.*, .en(ibwrite[0]), .din(bp0_in), .dout(bp0));
|
||||
|
||||
// instruction buffers
|
||||
|
||||
if (DEC_INSTBUF_DEPTH==4) begin
|
||||
assign ib3_in[31:0] = ({32{write_i0_ib3}} & ifu_i0_instr[31:0]) |
|
||||
({32{write_i1_ib3}} & ifu_i1_instr[31:0]);
|
||||
|
||||
rvdffe #(32) ib3ff (.*, .en(ibwrite[3]), .din(ib3_in[31:0]), .dout(ib3[31:0]));
|
||||
|
||||
assign ib2_in[31:0] = ({32{write_i0_ib2}} & ifu_i0_instr[31:0]) |
|
||||
({32{write_i1_ib2}} & ifu_i1_instr[31:0]) |
|
||||
({32{shift_ib3_ib2}} & ib3[31:0]);
|
||||
|
||||
rvdffe #(32) ib2ff (.*, .en(ibwrite[2]), .din(ib2_in[31:0]), .dout(ib2[31:0]));
|
||||
end // if (DEC_INSTBUF_DEPTH==4)
|
||||
else begin
|
||||
assign ib3 = '0;
|
||||
assign ib2 = '0;
|
||||
end
|
||||
|
||||
assign ib1_in[31:0] = ({32{write_i0_ib1}} & ifu_i0_instr[31:0]) |
|
||||
({32{write_i1_ib1}} & ifu_i1_instr[31:0]) |
|
||||
({32{shift_ib2_ib1}} & ib2[31:0]) |
|
||||
({32{shift_ib3_ib1}} & ib3[31:0]);
|
||||
|
||||
rvdffe #(32) ib1ff (.*, .en(ibwrite[1]), .din(ib1_in[31:0]), .dout(ib1[31:0]));
|
||||
|
||||
|
||||
// GPR accesses
|
||||
|
||||
// put reg to read on rs1
|
||||
// read -> or %x0, %reg,%x0 {000000000000,reg[4:0],110000000110011}
|
||||
|
||||
// put write date on rs1
|
||||
// write -> or %reg, %x0, %x0 {00000000000000000110,reg[4:0],0110011}
|
||||
|
||||
|
||||
// CSR accesses
|
||||
// csr is of form rd, csr, rs1
|
||||
|
||||
// read -> csrrs %x0, %csr, %x0 {csr[11:0],00000010000001110011}
|
||||
|
||||
// put write data on rs1
|
||||
// write -> csrrw %x0, %csr, %x0 {csr[11:0],00000001000001110011}
|
||||
|
||||
// abstract memory command not done here
|
||||
assign debug_valid = dbg_cmd_valid & (dbg_cmd_type[1:0] != 2'h2);
|
||||
|
||||
|
||||
assign debug_read = debug_valid & ~dbg_cmd_write;
|
||||
assign debug_write = debug_valid & dbg_cmd_write;
|
||||
|
||||
assign debug_read_gpr = debug_read & (dbg_cmd_type[1:0]==2'h0);
|
||||
assign debug_write_gpr = debug_write & (dbg_cmd_type[1:0]==2'h0);
|
||||
assign debug_read_csr = debug_read & (dbg_cmd_type[1:0]==2'h1);
|
||||
assign debug_write_csr = debug_write & (dbg_cmd_type[1:0]==2'h1);
|
||||
|
||||
assign dreg[4:0] = dbg_cmd_addr[4:0];
|
||||
assign dcsr[11:0] = dbg_cmd_addr[11:0];
|
||||
|
||||
|
||||
assign ib0_debug_in[31:0] = ({32{debug_read_gpr}} & {12'b000000000000,dreg[4:0],15'b110000000110011}) |
|
||||
({32{debug_write_gpr}} & {20'b00000000000000000110,dreg[4:0],7'b0110011}) |
|
||||
({32{debug_read_csr}} & {dcsr[11:0],20'b00000010000001110011}) |
|
||||
({32{debug_write_csr}} & {dcsr[11:0],20'b00000001000001110011});
|
||||
|
||||
|
||||
// machine is in halted state, pipe empty, write will always happen next cycle
|
||||
rvdff #(1) debug_wdata_rs1ff (.*, .clk(free_clk), .din(debug_write_gpr | debug_write_csr), .dout(dec_debug_wdata_rs1_d));
|
||||
|
||||
|
||||
// special fence csr for use only in debug mode
|
||||
|
||||
logic debug_fence_in;
|
||||
|
||||
assign debug_fence_in = debug_write_csr & (dcsr[11:0] == 12'h7c4);
|
||||
|
||||
rvdff #(1) debug_fence_ff (.*, .clk(free_clk), .din(debug_fence_in), .dout(dec_debug_fence_d));
|
||||
|
||||
|
||||
assign ib0_in[31:0] = ({32{write_i0_ib0}} & ((debug_valid) ? ib0_debug_in[31:0] : ifu_i0_instr[31:0])) |
|
||||
({32{shift_ib1_ib0}} & ib1[31:0]) |
|
||||
({32{shift_ib2_ib0}} & ib2[31:0]);
|
||||
|
||||
rvdffe #(32) ib0ff (.*, .en(ibwrite[0]), .din(ib0_in[31:0]), .dout(ib0[31:0]));
|
||||
|
||||
assign dec_ib3_valid_d = ibval[3];
|
||||
assign dec_ib2_valid_d = ibval[2];
|
||||
assign dec_ib1_valid_d = ibval[1];
|
||||
assign dec_ib0_valid_d = ibval[0];
|
||||
|
||||
assign dec_i0_instr_d[31:0] = ib0[31:0];
|
||||
|
||||
assign dec_i1_instr_d[31:0] = ib1[31:0];
|
||||
|
||||
assign dec_i0_brp = bp0;
|
||||
assign dec_i1_brp = bp1;
|
||||
|
||||
|
||||
assign shift1 = dec_i0_decode_d & ~dec_i1_decode_d;
|
||||
|
||||
assign shift2 = dec_i0_decode_d & dec_i1_decode_d;
|
||||
|
||||
assign shift0 = ~dec_i0_decode_d;
|
||||
|
||||
|
||||
// compute shifted ib valids to determine where to write
|
||||
assign shift_ibval[3:0] = ({4{shift1}} & {1'b0, ibval[3:1] }) |
|
||||
({4{shift2}} & {2'b0, ibval[3:2]}) |
|
||||
({4{shift0}} & ibval[3:0]);
|
||||
|
||||
assign write_i0_ib0 = ~shift_ibval[0] & (ifu_i0_val | debug_valid);
|
||||
assign write_i0_ib1 = shift_ibval[0] & ~shift_ibval[1] & ifu_i0_val;
|
||||
assign write_i0_ib2 = shift_ibval[1] & ~shift_ibval[2] & ifu_i0_val;
|
||||
assign write_i0_ib3 = shift_ibval[2] & ~shift_ibval[3] & ifu_i0_val;
|
||||
|
||||
assign write_i1_ib1 = ~shift_ibval[0] & ifu_i1_val;
|
||||
assign write_i1_ib2 = shift_ibval[0] & ~shift_ibval[1] & ifu_i1_val;
|
||||
assign write_i1_ib3 = shift_ibval[1] & ~shift_ibval[2] & ifu_i1_val;
|
||||
|
||||
|
||||
assign shift_ib1_ib0 = shift1 & ibval[1];
|
||||
assign shift_ib2_ib1 = shift1 & ibval[2];
|
||||
assign shift_ib3_ib2 = shift1 & ibval[3];
|
||||
|
||||
assign shift_ib2_ib0 = shift2 & ibval[2];
|
||||
assign shift_ib3_ib1 = shift2 & ibval[3];
|
||||
|
||||
|
||||
|
||||
endmodule
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,57 @@
|
|||
// 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: DEC Trigger Logic
|
||||
// Comments:
|
||||
//
|
||||
//********************************************************************************
|
||||
module dec_trigger
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
|
||||
input trigger_pkt_t [3:0] trigger_pkt_any, // Packet from tlu. 'select':0-pc,1-Opcode 'Execute' needs to be set for dec triggers to fire. 'match'-1 do mask, 0: full match
|
||||
input logic [31:1] dec_i0_pc_d, // i0 pc
|
||||
input logic [31:1] dec_i1_pc_d, // i1 pc
|
||||
|
||||
output logic [3:0] dec_i0_trigger_match_d,
|
||||
output logic [3:0] dec_i1_trigger_match_d
|
||||
);
|
||||
|
||||
logic [3:0][31:0] dec_i0_match_data;
|
||||
logic [3:0] dec_i0_trigger_data_match;
|
||||
logic [3:0][31:0] dec_i1_match_data;
|
||||
logic [3:0] dec_i1_trigger_data_match;
|
||||
|
||||
for (genvar i=0; i<4; i++) begin
|
||||
assign dec_i0_match_data[i][31:0] = ({32{~trigger_pkt_any[i].select & trigger_pkt_any[i].execute}} & {dec_i0_pc_d[31:1], trigger_pkt_any[i].tdata2[0]}); // select=0; do a PC match
|
||||
|
||||
assign dec_i1_match_data[i][31:0] = ({32{~trigger_pkt_any[i].select & trigger_pkt_any[i].execute}} & {dec_i1_pc_d[31:1], trigger_pkt_any[i].tdata2[0]} ); // select=0; do a PC match
|
||||
|
||||
rvmaskandmatch trigger_i0_match (.mask(trigger_pkt_any[i].tdata2[31:0]), .data(dec_i0_match_data[i][31:0]), .masken(trigger_pkt_any[i].match), .match(dec_i0_trigger_data_match[i]));
|
||||
rvmaskandmatch trigger_i1_match (.mask(trigger_pkt_any[i].tdata2[31:0]), .data(dec_i1_match_data[i][31:0]), .masken(trigger_pkt_any[i].match), .match(dec_i1_trigger_data_match[i]));
|
||||
|
||||
assign dec_i0_trigger_match_d[i] = trigger_pkt_any[i].execute & trigger_pkt_any[i].m & dec_i0_trigger_data_match[i];
|
||||
assign dec_i1_trigger_match_d[i] = trigger_pkt_any[i].execute & trigger_pkt_any[i].m & dec_i1_trigger_data_match[i];
|
||||
end
|
||||
|
||||
endmodule // dec_trigger
|
||||
|
|
@ -0,0 +1,322 @@
|
|||
|
||||
.definition
|
||||
|
||||
add = [0000000..........000.....0110011]
|
||||
addi = [.................000.....0010011]
|
||||
|
||||
sub = [0100000..........000.....0110011]
|
||||
|
||||
and = [0000000..........111.....0110011]
|
||||
andi = [.................111.....0010011]
|
||||
|
||||
or = [0000000..........110.....0110011]
|
||||
ori = [.................110.....0010011]
|
||||
|
||||
xor = [0000000..........100.....0110011]
|
||||
xori = [.................100.....0010011]
|
||||
|
||||
sll = [0000000..........001.....0110011]
|
||||
slli = [0000000..........001.....0010011]
|
||||
|
||||
sra = [0100000..........101.....0110011]
|
||||
srai = [0100000..........101.....0010011]
|
||||
|
||||
srl = [0000000..........101.....0110011]
|
||||
srli = [0000000..........101.....0010011]
|
||||
|
||||
lui = [.........................0110111]
|
||||
auipc= [.........................0010111]
|
||||
|
||||
slt = [0000000..........010.....0110011]
|
||||
sltu = [0000000..........011.....0110011]
|
||||
slti = [.................010.....0010011]
|
||||
sltiu= [.................011.....0010011]
|
||||
|
||||
beq = [.................000.....1100011]
|
||||
bne = [.................001.....1100011]
|
||||
bge = [.................101.....1100011]
|
||||
blt = [.................100.....1100011]
|
||||
bgeu = [.................111.....1100011]
|
||||
bltu = [.................110.....1100011]
|
||||
|
||||
jal = [.........................1101111]
|
||||
jalr = [.................000.....1100111]
|
||||
|
||||
lb = [.................000.....0000011]
|
||||
lh = [.................001.....0000011]
|
||||
lw = [.................010.....0000011]
|
||||
|
||||
sb = [.................000.....0100011]
|
||||
sh = [.................001.....0100011]
|
||||
sw = [.................010.....0100011]
|
||||
|
||||
lbu = [.................100.....0000011]
|
||||
lhu = [.................101.....0000011]
|
||||
|
||||
fence = [0000........00000000000000001111]
|
||||
fence.i = [00000000000000000001000000001111]
|
||||
|
||||
ebreak = [00000000000100000000000001110011]
|
||||
ecall = [00000000000000000000000001110011]
|
||||
|
||||
mret = [00110000001000000000000001110011]
|
||||
|
||||
wfi = [00010000010100000000000001110011]
|
||||
|
||||
csrrc_ro = [............00000011.....1110011]
|
||||
csrrc_rw0 = [............1....011.....1110011]
|
||||
csrrc_rw1 = [.............1...011.....1110011]
|
||||
csrrc_rw2 = [..............1..011.....1110011]
|
||||
csrrc_rw3 = [...............1.011.....1110011]
|
||||
csrrc_rw4 = [................1011.....1110011]
|
||||
|
||||
csrrci_ro = [............00000111.....1110011]
|
||||
csrrci_rw0 = [............1....111.....1110011]
|
||||
csrrci_rw1 = [.............1...111.....1110011]
|
||||
csrrci_rw2 = [..............1..111.....1110011]
|
||||
csrrci_rw3 = [...............1.111.....1110011]
|
||||
csrrci_rw4 = [................1111.....1110011]
|
||||
|
||||
csrrs_ro = [............00000010.....1110011]
|
||||
csrrs_rw0 = [............1....010.....1110011]
|
||||
csrrs_rw1 = [.............1...010.....1110011]
|
||||
csrrs_rw2 = [..............1..010.....1110011]
|
||||
csrrs_rw3 = [...............1.010.....1110011]
|
||||
csrrs_rw4 = [................1010.....1110011]
|
||||
|
||||
csrrsi_ro = [............00000110.....1110011]
|
||||
csrrsi_rw0 = [............1....110.....1110011]
|
||||
csrrsi_rw1 = [.............1...110.....1110011]
|
||||
csrrsi_rw2 = [..............1..110.....1110011]
|
||||
csrrsi_rw3 = [...............1.110.....1110011]
|
||||
csrrsi_rw4 = [................1110.....1110011]
|
||||
|
||||
|
||||
csrw = [.................001000001110011]
|
||||
csrrw0 = [.................001....11110011]
|
||||
csrrw1 = [.................001...1.1110011]
|
||||
csrrw2 = [.................001..1..1110011]
|
||||
csrrw3 = [.................001.1...1110011]
|
||||
csrrw4 = [.................0011....1110011]
|
||||
|
||||
csrwi = [.................101000001110011]
|
||||
csrrwi0 = [.................101....11110011]
|
||||
csrrwi1 = [.................101...1.1110011]
|
||||
csrrwi2 = [.................101..1..1110011]
|
||||
csrrwi3 = [.................101.1...1110011]
|
||||
csrrwi4 = [.................1011....1110011]
|
||||
|
||||
mul = [0000001..........000.....0110011]
|
||||
mulh = [0000001..........001.....0110011]
|
||||
mulhsu = [0000001..........010.....0110011]
|
||||
mulhu = [0000001..........011.....0110011]
|
||||
|
||||
div = [0000001..........100.....0110011]
|
||||
divu = [0000001..........101.....0110011]
|
||||
rem = [0000001..........110.....0110011]
|
||||
remu = [0000001..........111.....0110011]
|
||||
|
||||
|
||||
.input
|
||||
|
||||
rv32i = {
|
||||
i[31]
|
||||
i[30]
|
||||
i[29]
|
||||
i[28]
|
||||
i[27]
|
||||
i[26]
|
||||
i[25]
|
||||
i[24]
|
||||
i[23]
|
||||
i[22]
|
||||
i[21]
|
||||
i[20]
|
||||
i[19]
|
||||
i[18]
|
||||
i[17]
|
||||
i[16]
|
||||
i[15]
|
||||
i[14]
|
||||
i[13]
|
||||
i[12]
|
||||
i[11]
|
||||
i[10]
|
||||
i[9]
|
||||
i[8]
|
||||
i[7]
|
||||
i[6]
|
||||
i[5]
|
||||
i[4]
|
||||
i[3]
|
||||
i[2]
|
||||
i[1]
|
||||
i[0]
|
||||
}
|
||||
|
||||
|
||||
.output
|
||||
|
||||
rv32i = {
|
||||
alu
|
||||
rs1
|
||||
rs2
|
||||
imm12
|
||||
rd
|
||||
shimm5
|
||||
imm20
|
||||
pc
|
||||
load
|
||||
store
|
||||
lsu
|
||||
add
|
||||
sub
|
||||
land
|
||||
lor
|
||||
lxor
|
||||
sll
|
||||
sra
|
||||
srl
|
||||
slt
|
||||
unsign
|
||||
condbr
|
||||
beq
|
||||
bne
|
||||
bge
|
||||
blt
|
||||
jal
|
||||
by
|
||||
half
|
||||
word
|
||||
csr_read
|
||||
csr_clr
|
||||
csr_set
|
||||
csr_write
|
||||
csr_imm
|
||||
presync
|
||||
postsync
|
||||
ebreak
|
||||
ecall
|
||||
mret
|
||||
mul
|
||||
rs1_sign
|
||||
rs2_sign
|
||||
low
|
||||
div
|
||||
rem
|
||||
fence
|
||||
fence_i
|
||||
pm_alu
|
||||
}
|
||||
|
||||
.decode
|
||||
|
||||
rv32i[mul] = { mul rs1 rs2 rd low }
|
||||
rv32i[mulh] = { mul rs1 rs2 rd rs1_sign rs2_sign }
|
||||
rv32i[mulhu] = { mul rs1 rs2 rd }
|
||||
rv32i[mulhsu] = { mul rs1 rs2 rd rs1_sign }
|
||||
|
||||
rv32i[div] = { div rs1 rs2 rd presync postsync}
|
||||
rv32i[divu] = { div rs1 rs2 rd unsign presync postsync}
|
||||
rv32i[rem] = { div rs1 rs2 rd presync postsync rem}
|
||||
rv32i[remu] = { div rs1 rs2 rd unsign presync postsync rem}
|
||||
|
||||
rv32i[add] = { alu rs1 rs2 rd add pm_alu }
|
||||
rv32i[addi] = { alu rs1 imm12 rd add pm_alu }
|
||||
|
||||
rv32i[sub] = { alu rs1 rs2 rd sub pm_alu }
|
||||
|
||||
rv32i[and] = { alu rs1 rs2 rd land pm_alu }
|
||||
rv32i[andi] = { alu rs1 imm12 rd land pm_alu }
|
||||
|
||||
rv32i[or] = { alu rs1 rs2 rd lor pm_alu }
|
||||
rv32i[ori] = { alu rs1 imm12 rd lor pm_alu }
|
||||
|
||||
rv32i[xor] = { alu rs1 rs2 rd lxor pm_alu }
|
||||
rv32i[xori] = { alu rs1 imm12 rd lxor pm_alu }
|
||||
|
||||
rv32i[sll] = { alu rs1 rs2 rd sll pm_alu }
|
||||
rv32i[slli] = { alu rs1 shimm5 rd sll pm_alu }
|
||||
|
||||
rv32i[sra] = { alu rs1 rs2 rd sra pm_alu }
|
||||
rv32i[srai] = { alu rs1 shimm5 rd sra pm_alu }
|
||||
|
||||
rv32i[srl] = { alu rs1 rs2 rd srl pm_alu }
|
||||
rv32i[srli] = { alu rs1 shimm5 rd srl pm_alu }
|
||||
|
||||
rv32i[lui] = { alu imm20 rd lor pm_alu }
|
||||
rv32i[auipc] = { alu imm20 pc rd add pm_alu }
|
||||
|
||||
|
||||
rv32i[slt] = { alu rs1 rs2 rd sub slt pm_alu }
|
||||
rv32i[sltu] = { alu rs1 rs2 rd sub slt unsign pm_alu }
|
||||
rv32i[slti] = { alu rs1 imm12 rd sub slt pm_alu }
|
||||
rv32i[sltiu] = { alu rs1 imm12 rd sub slt unsign pm_alu }
|
||||
|
||||
rv32i[beq] = { alu rs1 rs2 sub condbr beq }
|
||||
rv32i[bne] = { alu rs1 rs2 sub condbr bne }
|
||||
rv32i[bge] = { alu rs1 rs2 sub condbr bge }
|
||||
rv32i[blt] = { alu rs1 rs2 sub condbr blt }
|
||||
rv32i[bgeu] = { alu rs1 rs2 sub condbr bge unsign }
|
||||
rv32i[bltu] = { alu rs1 rs2 sub condbr blt unsign }
|
||||
|
||||
rv32i[jal] = { alu imm20 rd pc jal }
|
||||
rv32i[jalr] = { alu rs1 rd imm12 jal }
|
||||
|
||||
rv32i[lb] = { lsu load rs1 rd by }
|
||||
rv32i[lh] = { lsu load rs1 rd half }
|
||||
rv32i[lw] = { lsu load rs1 rd word }
|
||||
rv32i[lbu] = { lsu load rs1 rd by unsign }
|
||||
rv32i[lhu] = { lsu load rs1 rd half unsign }
|
||||
|
||||
rv32i[sb] = { lsu store rs1 rs2 by }
|
||||
rv32i[sh] = { lsu store rs1 rs2 half }
|
||||
rv32i[sw] = { lsu store rs1 rs2 word }
|
||||
|
||||
|
||||
rv32i[fence] = { alu lor fence presync}
|
||||
|
||||
# fence.i has fence effect in addtion to flush I$ and redirect
|
||||
rv32i[fence.i] = { alu lor fence fence_i presync postsync}
|
||||
|
||||
# nops for now
|
||||
|
||||
rv32i[ebreak] = { alu rs1 imm12 rd lor ebreak postsync}
|
||||
rv32i[ecall] = { alu rs1 imm12 rd lor ecall postsync}
|
||||
rv32i[mret] = { alu rs1 imm12 rd lor mret postsync}
|
||||
|
||||
rv32i[wfi] = { alu rs1 imm12 rd lor pm_alu }
|
||||
|
||||
# csr means read
|
||||
|
||||
# csr_read - put csr on rs2 and rs1 0's
|
||||
rv32i[csrrc_ro] = { alu rd csr_read lor }
|
||||
|
||||
# put csr on rs2 and make rs1 0's into alu. Save rs1 for csr_clr later
|
||||
rv32i[csrrc_rw{0-4}] = { alu rd csr_read rs1 csr_clr lor presync postsync }
|
||||
|
||||
rv32i[csrrci_ro] = { alu rd csr_read lor }
|
||||
|
||||
rv32i[csrrci_rw{0-4}] = { alu rd csr_read rs1 csr_clr csr_imm lor presync postsync }
|
||||
|
||||
rv32i[csrrs_ro] = { alu rd csr_read lor }
|
||||
|
||||
rv32i[csrrs_rw{0-4}] = { alu rd csr_read rs1 csr_set lor presync postsync }
|
||||
|
||||
rv32i[csrrsi_ro] = { alu rd csr_read lor }
|
||||
|
||||
rv32i[csrrsi_rw{0-4}] = { alu rd csr_read rs1 csr_set csr_imm lor presync postsync }
|
||||
|
||||
rv32i[csrrw{0-4}] = { alu rd csr_read rs1 csr_write lor presync postsync }
|
||||
|
||||
|
||||
rv32i[csrrwi{0-4}] = { alu rd csr_read rs1 csr_write csr_imm lor presync postsync }
|
||||
|
||||
# optimize csr write only - pipelined
|
||||
rv32i[csrw] = { alu rd rs1 csr_write }
|
||||
|
||||
rv32i[csrwi] = { alu rd csr_write csr_imm }
|
||||
|
||||
|
||||
.end
|
||||
|
|
@ -0,0 +1,697 @@
|
|||
// 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$
|
||||
//
|
||||
// Function: Top level SWERV core file
|
||||
// Comments:
|
||||
//
|
||||
//********************************************************************************
|
||||
|
||||
module dma_ctrl (
|
||||
input logic clk,
|
||||
input logic free_clk,
|
||||
input logic rst_l,
|
||||
input logic dma_bus_clk_en, // slave bus clock enable
|
||||
input logic clk_override,
|
||||
|
||||
// AXI signals
|
||||
// AXI Write Channels
|
||||
input logic dma_axi_awvalid,
|
||||
output logic dma_axi_awready,
|
||||
input logic [`RV_DMA_BUS_TAG-1:0] dma_axi_awid,
|
||||
input logic [31:0] dma_axi_awaddr,
|
||||
input logic [2:0] dma_axi_awsize,
|
||||
input logic [2:0] dma_axi_awprot,
|
||||
input logic [7:0] dma_axi_awlen,
|
||||
input logic [1:0] dma_axi_awburst,
|
||||
|
||||
input logic dma_axi_wvalid,
|
||||
output logic dma_axi_wready,
|
||||
input logic [63:0] dma_axi_wdata,
|
||||
input logic [7:0] dma_axi_wstrb,
|
||||
input logic dma_axi_wlast,
|
||||
|
||||
output logic dma_axi_bvalid,
|
||||
input logic dma_axi_bready,
|
||||
output logic [1:0] dma_axi_bresp,
|
||||
output logic [`RV_DMA_BUS_TAG-1:0] dma_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
input logic dma_axi_arvalid,
|
||||
output logic dma_axi_arready,
|
||||
input logic [`RV_DMA_BUS_TAG-1:0] dma_axi_arid,
|
||||
input logic [31:0] dma_axi_araddr,
|
||||
input logic [2:0] dma_axi_arsize,
|
||||
input logic [2:0] dma_axi_arprot,
|
||||
input logic [7:0] dma_axi_arlen,
|
||||
input logic [1:0] dma_axi_arburst,
|
||||
|
||||
output logic dma_axi_rvalid,
|
||||
input logic dma_axi_rready,
|
||||
output logic [`RV_DMA_BUS_TAG-1:0] dma_axi_rid,
|
||||
output logic [63:0] dma_axi_rdata,
|
||||
output logic [1:0] dma_axi_rresp,
|
||||
output logic dma_axi_rlast,
|
||||
|
||||
output logic dma_slv_algn_err,
|
||||
// Debug signals
|
||||
input logic [31:0] dbg_cmd_addr,
|
||||
input logic [31:0] dbg_cmd_wrdata,
|
||||
input logic dbg_cmd_valid,
|
||||
input logic dbg_cmd_write, // 1: write command, 0: read_command
|
||||
input logic [1:0] dbg_cmd_type, // 0:gpr 1:csr 2: memory
|
||||
input logic [1:0] dbg_cmd_size, // size of the abstract mem access debug command
|
||||
|
||||
input logic dbg_dma_bubble, // Debug needs a bubble to send a valid
|
||||
output logic dma_dbg_ready, // DMA is ready to accept debug request
|
||||
|
||||
output logic dma_dbg_cmd_done,
|
||||
output logic dma_dbg_cmd_fail,
|
||||
output logic [31:0] dma_dbg_rddata,
|
||||
|
||||
// Core side signals
|
||||
output logic dma_dccm_req, // DMA dccm request (only one of dccm/iccm will be set)
|
||||
output logic dma_iccm_req, // DMA iccm request
|
||||
output logic [31:0] dma_mem_addr, // DMA request address
|
||||
output logic [2:0] dma_mem_sz, // DMA request size
|
||||
output logic dma_mem_write, // DMA write to dccm/iccm
|
||||
output logic [63:0] dma_mem_wdata, // DMA write data
|
||||
|
||||
input logic dccm_dma_rvalid, // dccm data valid for DMA read
|
||||
input logic dccm_dma_ecc_error, // ECC error on DMA read
|
||||
input logic [63:0] dccm_dma_rdata, // dccm data for DMA read
|
||||
input logic iccm_dma_rvalid, // iccm data valid for DMA read
|
||||
input logic iccm_dma_ecc_error, // ECC error on DMA read
|
||||
input logic [63:0] iccm_dma_rdata, // iccm data for DMA read
|
||||
|
||||
output logic dma_dccm_stall_any, // stall dccm pipe (bubble) so that DMA can proceed
|
||||
output logic dma_iccm_stall_any, // stall iccm pipe (bubble) so that DMA can proceed
|
||||
input logic dccm_ready, // dccm ready to accept DMA request
|
||||
input logic iccm_ready, // iccm ready to accept DMA request
|
||||
input logic dec_tlu_stall_dma, // stall dma accesses, tlu is attempting to enter halt/debug mode
|
||||
input logic [2:0] dec_tlu_dma_qos_prty, // DMA QoS priority coming from MFDC [18:15]
|
||||
|
||||
input logic scan_mode
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
localparam DEPTH = DMA_BUF_DEPTH;
|
||||
localparam DEPTH_PTR = $clog2(DEPTH);
|
||||
localparam NACK_COUNT = 7;
|
||||
|
||||
logic [DEPTH-1:0] fifo_valid;
|
||||
logic [DEPTH-1:0][1:0] fifo_error;
|
||||
logic [DEPTH-1:0] fifo_dccm_valid;
|
||||
logic [DEPTH-1:0] fifo_iccm_valid;
|
||||
logic [DEPTH-1:0] fifo_data_valid;
|
||||
logic [DEPTH-1:0] fifo_data_bus_valid;
|
||||
logic [DEPTH-1:0] fifo_error_bus;
|
||||
logic [DEPTH-1:0] fifo_rpend;
|
||||
logic [DEPTH-1:0] fifo_done; // DMA trxn is done in core
|
||||
logic [DEPTH-1:0] fifo_done_bus; // DMA trxn is done in core synced to bus
|
||||
logic [DEPTH-1:0] fifo_rsp_done; // DMA response sent to bus
|
||||
logic [DEPTH-1:0][31:0] fifo_addr;
|
||||
logic [DEPTH-1:0][2:0] fifo_sz;
|
||||
logic [DEPTH-1:0] fifo_write;
|
||||
logic [DEPTH-1:0] fifo_posted_write;
|
||||
logic [DEPTH-1:0] fifo_dbg;
|
||||
logic [DEPTH-1:0][63:0] fifo_data;
|
||||
logic [DEPTH-1:0][DMA_BUS_TAG-1:0] fifo_tag;
|
||||
|
||||
logic [DEPTH-1:0] fifo_cmd_en;
|
||||
logic [DEPTH-1:0] fifo_valid_en;
|
||||
logic [DEPTH-1:0] fifo_data_en;
|
||||
logic [DEPTH-1:0] fifo_data_bus_en;
|
||||
logic [DEPTH-1:0] fifo_pend_en;
|
||||
logic [DEPTH-1:0] fifo_done_en;
|
||||
logic [DEPTH-1:0] fifo_done_bus_en;
|
||||
logic [DEPTH-1:0] fifo_error_en;
|
||||
logic [DEPTH-1:0] fifo_error_bus_en;
|
||||
//logic [DEPTH-1:0] fifo_rsp_done_en;
|
||||
logic [DEPTH-1:0] fifo_reset;
|
||||
logic [DEPTH-1:0][1:0] fifo_error_in;
|
||||
logic [DEPTH-1:0][63:0] fifo_data_in;
|
||||
|
||||
logic fifo_write_in;
|
||||
logic fifo_posted_write_in;
|
||||
logic fifo_dbg_in;
|
||||
logic [31:0] fifo_addr_in;
|
||||
logic [2:0] fifo_sz_in;
|
||||
|
||||
logic [DEPTH_PTR-1:0] RspPtr, PrevRspPtr, NxtRspPtr;
|
||||
logic [DEPTH_PTR-1:0] WrPtr, NxtWrPtr;
|
||||
logic [DEPTH_PTR-1:0] RdPtr, NxtRdPtr;
|
||||
logic [DEPTH_PTR-1:0] RdPtr_Q1, RdPtr_Q2, RdPtr_Q3;
|
||||
logic WrPtrEn, RdPtrEn, RspPtrEn;
|
||||
|
||||
logic dma_dbg_cmd_error_in;
|
||||
logic dma_dbg_cmd_done_q;
|
||||
|
||||
logic fifo_full, fifo_full_spec, fifo_empty;
|
||||
logic dma_address_error, dma_alignment_error;
|
||||
logic [3:0] num_fifo_vld;
|
||||
logic dma_mem_req;
|
||||
logic dma_addr_in_dccm;
|
||||
logic dma_addr_in_iccm;
|
||||
logic dma_addr_in_pic;
|
||||
logic dma_addr_in_pic_region_nc;
|
||||
logic dma_addr_in_dccm_region_nc;
|
||||
logic dma_addr_in_iccm_region_nc;
|
||||
|
||||
logic [2:0] dma_nack_count_csr;
|
||||
logic [2:0] dma_nack_count, dma_nack_count_d;
|
||||
|
||||
logic dma_buffer_c1_clken;
|
||||
logic dma_free_clken;
|
||||
logic dma_buffer_c1_clk;
|
||||
logic dma_free_clk;
|
||||
logic dma_bus_clk;
|
||||
|
||||
|
||||
logic wrbuf_en, wrbuf_data_en;
|
||||
logic wrbuf_cmd_sent, wrbuf_rst, wrbuf_data_rst;
|
||||
logic wrbuf_vld;
|
||||
logic wrbuf_data_vld;
|
||||
logic wrbuf_posted;
|
||||
logic [DMA_BUS_TAG-1:0] wrbuf_tag;
|
||||
logic [2:0] wrbuf_size;
|
||||
logic [31:0] wrbuf_addr;
|
||||
logic [63:0] wrbuf_data;
|
||||
logic [7:0] wrbuf_byteen;
|
||||
|
||||
logic rdbuf_en;
|
||||
logic rdbuf_cmd_sent, rdbuf_rst;
|
||||
logic rdbuf_vld;
|
||||
logic [DMA_BUS_TAG-1:0] rdbuf_tag;
|
||||
logic [2:0] rdbuf_size;
|
||||
logic [31:0] rdbuf_addr;
|
||||
|
||||
|
||||
logic axi_mstr_valid, axi_mstr_valid_q;
|
||||
logic axi_mstr_write;
|
||||
logic axi_mstr_posted_write;
|
||||
logic [DMA_BUS_TAG-1:0] axi_mstr_tag;
|
||||
logic [31:0] axi_mstr_addr;
|
||||
logic [2:0] axi_mstr_size;
|
||||
logic [63:0] axi_mstr_wdata;
|
||||
logic [7:0] axi_mstr_wstrb;
|
||||
|
||||
logic axi_mstr_prty_in, axi_mstr_prty_en;
|
||||
logic axi_mstr_priority;
|
||||
logic axi_mstr_sel;
|
||||
|
||||
logic axi_slv_valid;
|
||||
logic axi_slv_sent, axi_slv_sent_q;
|
||||
logic axi_slv_write;
|
||||
logic axi_slv_posted_write;
|
||||
logic [DMA_BUS_TAG-1:0] axi_slv_tag;
|
||||
logic [1:0] axi_slv_error;
|
||||
logic [63:0] axi_slv_rdata;
|
||||
|
||||
logic dma_bus_clk_en_q;
|
||||
logic fifo_full_spec_bus;
|
||||
logic dbg_dma_bubble_bus;
|
||||
logic dec_tlu_stall_dma_bus;
|
||||
logic dma_fifo_ready;
|
||||
|
||||
//------------------------LOGIC STARTS HERE---------------------------------
|
||||
|
||||
// FIFO inputs
|
||||
assign fifo_addr_in[31:0] = dbg_cmd_valid ? dbg_cmd_addr[31:0] : axi_mstr_addr[31:0];
|
||||
assign fifo_sz_in[2:0] = dbg_cmd_valid ? {1'b0,dbg_cmd_size[1:0]} : axi_mstr_size[2:0];
|
||||
assign fifo_write_in = dbg_cmd_valid ? dbg_cmd_write : axi_mstr_write;
|
||||
assign fifo_posted_write_in = axi_mstr_valid & axi_mstr_posted_write;
|
||||
assign fifo_dbg_in = dbg_cmd_valid;
|
||||
//assign fifo_error_in[1:0] = dccm_dma_rvalid ? {1'b0,dccm_dma_ecc_error} : iccm_dma_rvalid ? {1'b0,iccm_dma_ecc_error} : {(dma_address_error | dma_alignment_error | dma_dbg_cmd_error_in), dma_alignment_error};
|
||||
//assign fifo_data_in[63:0] = dccm_dma_rvalid ? dccm_dma_rdata[63:0] : (iccm_dma_rvalid ? iccm_dma_rdata[63:0] :
|
||||
// (dbg_cmd_valid ? {2{dbg_cmd_wrdata[31:0]}} : axi_mstr_wdata[63:0]));
|
||||
|
||||
for (genvar i=0 ;i<DEPTH; i++) begin: GenFifo
|
||||
assign fifo_valid_en[i] = axi_mstr_valid & (i == WrPtr[DEPTH_PTR-1:0]);
|
||||
assign fifo_cmd_en[i] = ((axi_mstr_valid & dma_bus_clk_en) | (dbg_cmd_valid & dbg_cmd_type[1])) &
|
||||
(i == WrPtr[DEPTH_PTR-1:0]);
|
||||
assign fifo_data_en[i] = (((axi_mstr_valid & (axi_mstr_write | dma_address_error | dma_alignment_error) & dma_bus_clk_en) |
|
||||
(dbg_cmd_valid & dbg_cmd_type[1] & dbg_cmd_write)) & (i == WrPtr[DEPTH_PTR-1:0])) |
|
||||
((dccm_dma_rvalid & (i == RdPtr_Q3[DEPTH_PTR-1:0]))| (iccm_dma_rvalid & (i == RdPtr_Q2[DEPTH_PTR-1:0])));
|
||||
assign fifo_data_bus_en[i] = (fifo_data_en[i] | fifo_data_valid[i]) & dma_bus_clk_en;
|
||||
assign fifo_pend_en[i] = (dma_dccm_req | dma_iccm_req) & ~dma_mem_write & (i == RdPtr[DEPTH_PTR-1:0]);
|
||||
assign fifo_error_en[i] = fifo_cmd_en[i] | (((dccm_dma_rvalid & dccm_dma_ecc_error & (i == RdPtr_Q3[DEPTH_PTR-1:0])) | (iccm_dma_rvalid & iccm_dma_ecc_error & (i == RdPtr_Q2[DEPTH_PTR-1:0]))));
|
||||
assign fifo_error_bus_en[i] = (((|fifo_error_in[i][1:0]) & fifo_error_en[i]) | (|fifo_error[i])) & dma_bus_clk_en;
|
||||
assign fifo_done_en[i] = (((|fifo_error[i]) | ((dma_dccm_req | dma_iccm_req) & dma_mem_write)) & (i == RdPtr[DEPTH_PTR-1:0])) |
|
||||
((dccm_dma_rvalid & (i == RdPtr_Q3[DEPTH_PTR-1:0])) | (iccm_dma_rvalid & (i == RdPtr_Q2[DEPTH_PTR-1:0])));
|
||||
assign fifo_done_bus_en[i] = (fifo_done_en[i] | fifo_done[i]) & dma_bus_clk_en;
|
||||
//assign fifo_rsp_done_en[i] = fifo_valid[i] & ((axi_slv_sent & dma_bus_clk_en) | dma_dbg_cmd_done) & (i == RspPtr[DEPTH_PTR-1:0]);
|
||||
//assign fifo_reset[i] = (fifo_done[i] | fifo_done_en[i]) & (fifo_rsp_done[i] | fifo_rsp_done_en[i]);
|
||||
assign fifo_reset[i] = ((axi_slv_sent & dma_bus_clk_en) | dma_dbg_cmd_done) & (i == RspPtr[DEPTH_PTR-1:0]);
|
||||
assign fifo_error_in[i] = (dccm_dma_rvalid & (i == RdPtr_Q3[DEPTH_PTR-1:0])) ? {1'b0,dccm_dma_ecc_error} : (iccm_dma_rvalid & (i == RdPtr_Q2[DEPTH_PTR-1:0])) ? {1'b0,iccm_dma_ecc_error} :
|
||||
{(dma_address_error | dma_alignment_error | dma_dbg_cmd_error_in), dma_alignment_error};
|
||||
assign fifo_data_in[i] = (fifo_error_en[i] & (|fifo_error_in[i])) ? (fifo_cmd_en[i] ? {32'b0,axi_mstr_addr[31:0]} : {32'b0,fifo_addr[i]}) :
|
||||
((dccm_dma_rvalid & (i == RdPtr_Q3[DEPTH_PTR-1:0])) ? dccm_dma_rdata[63:0] : (iccm_dma_rvalid & (i == RdPtr_Q2[DEPTH_PTR-1:0])) ? iccm_dma_rdata[63:0] :
|
||||
(dbg_cmd_valid ? {2{dbg_cmd_wrdata[31:0]}} : axi_mstr_wdata[63:0]));
|
||||
|
||||
rvdffsc #(1) fifo_valid_dff (.din(1'b1), .dout(fifo_valid[i]), .en(fifo_cmd_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
rvdffsc #(2) fifo_error_dff (.din(fifo_error_in[i]), .dout(fifo_error[i]), .en(fifo_error_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
rvdffsc #(1) fifo_error_bus_dff (.din(1'b1), .dout(fifo_error_bus[i]), .en(fifo_error_bus_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
rvdffs #(1) fifo_dccm_valid_dff (.din((dma_addr_in_dccm | dma_addr_in_pic)), .dout(fifo_dccm_valid[i]), .en(fifo_cmd_en[i]), .clk(dma_buffer_c1_clk), .*);
|
||||
rvdffs #(1) fifo_iccm_valid_dff (.din(dma_addr_in_iccm), .dout(fifo_iccm_valid[i]), .en(fifo_cmd_en[i]), .clk(dma_buffer_c1_clk), .*);
|
||||
rvdffsc #(1) fifo_data_valid_dff (.din(1'b1), .dout(fifo_data_valid[i]), .en(fifo_data_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
rvdffsc #(1) fifo_data_bus_valid_dff (.din(1'b1), .dout(fifo_data_bus_valid[i]), .en(fifo_data_bus_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
rvdffsc #(1) fifo_rpend_dff (.din(1'b1), .dout(fifo_rpend[i]), .en(fifo_pend_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
rvdffsc #(1) fifo_done_dff (.din(1'b1), .dout(fifo_done[i]), .en(fifo_done_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
rvdffsc #(1) fifo_done_bus_dff (.din(1'b1), .dout(fifo_done_bus[i]), .en(fifo_done_bus_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
//rvdffsc #(1) fifo_rsp_done_dff (.din(1'b1), .dout(fifo_rsp_done[i]), .en(fifo_rsp_done_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||
rvdffe #(32) fifo_addr_dff (.din(fifo_addr_in[31:0]), .dout(fifo_addr[i]), .en(fifo_cmd_en[i]), .*);
|
||||
rvdffs #(3) fifo_sz_dff (.din(fifo_sz_in[2:0]), .dout(fifo_sz[i]), .en(fifo_cmd_en[i]), .clk(dma_buffer_c1_clk), .*);
|
||||
rvdffs #(1) fifo_write_dff (.din(fifo_write_in), .dout(fifo_write[i]), .en(fifo_cmd_en[i]), .clk(dma_buffer_c1_clk), .*);
|
||||
rvdffs #(1) fifo_posted_write_dff (.din(fifo_posted_write_in), .dout(fifo_posted_write[i]), .en(fifo_cmd_en[i]), .clk(dma_buffer_c1_clk), .*);
|
||||
rvdffs #(1) fifo_dbg_dff (.din(fifo_dbg_in), .dout(fifo_dbg[i]), .en(fifo_cmd_en[i]), .clk(dma_buffer_c1_clk), .*);
|
||||
rvdffe #(64) fifo_data_dff (.din(fifo_data_in[i]), .dout(fifo_data[i]), .en(fifo_data_en[i]), .*);
|
||||
rvdffs #(DMA_BUS_TAG) fifo_tag_dff(.din(axi_mstr_tag[DMA_BUS_TAG-1:0]), .dout(fifo_tag[i][DMA_BUS_TAG-1:0]), .en(fifo_cmd_en[i]), .clk(dma_buffer_c1_clk), .*);
|
||||
end
|
||||
|
||||
// Pointer logic
|
||||
assign NxtWrPtr[DEPTH_PTR-1:0] = WrPtr[DEPTH_PTR-1:0] + 1'b1;
|
||||
assign NxtRdPtr[DEPTH_PTR-1:0] = RdPtr[DEPTH_PTR-1:0] + 1'b1;
|
||||
assign NxtRspPtr[DEPTH_PTR-1:0] = RspPtr[DEPTH_PTR-1:0] + 1'b1;
|
||||
|
||||
// Don't increment the ptr for posted writes if 1)fifo error (it will increment only with response) 2) response done (this is the full case)
|
||||
//assign RspPtr[DEPTH_PTR-1:0] = (dma_dbg_cmd_done_q | axi_slv_sent_q) ? (PrevRspPtr[DEPTH_PTR-1:0] + 1'b1) : PrevRspPtr[DEPTH_PTR-1:0];
|
||||
//assign RspPtr[DEPTH_PTR-1:0] = (dma_dbg_cmd_done_q | axi_slv_sent_q |
|
||||
// (fifo_valid[PrevRspPtr] & fifo_write[PrevRspPtr] & fifo_posted_write[PrevRspPtr] & ~(|fifo_error[PrevRspPtr]) & ~fifo_rsp_done[PrevRspPtr])) ? (PrevRspPtr[DEPTH_PTR-1:0] + 1'b1) : PrevRspPtr[DEPTH_PTR-1:0];
|
||||
|
||||
assign WrPtrEn = |fifo_cmd_en[DEPTH-1:0];
|
||||
assign RdPtrEn = (dma_dccm_req | dma_iccm_req) | ((|fifo_error[RdPtr]) & ~fifo_done[RdPtr]);
|
||||
//assign RdPtrEn = |(fifo_done_en[DEPTH-1:0] & ~fifo_done[DEPTH-1:0]);
|
||||
assign RspPtrEn = (dma_dbg_cmd_done | (axi_slv_sent & dma_bus_clk_en));
|
||||
//assign RspPtrEn = dma_bus_clk_en | dma_dbg_cmd_done_q;
|
||||
|
||||
rvdffs #(DEPTH_PTR) WrPtr_dff(.din(NxtWrPtr[DEPTH_PTR-1:0]), .dout(WrPtr[DEPTH_PTR-1:0]), .en(WrPtrEn), .clk(dma_free_clk), .*);
|
||||
rvdffs #(DEPTH_PTR) RdPtr_dff(.din(NxtRdPtr[DEPTH_PTR-1:0]), .dout(RdPtr[DEPTH_PTR-1:0]), .en(RdPtrEn), .clk(dma_free_clk), .*);
|
||||
rvdffs #(DEPTH_PTR) RspPtr_dff(.din(NxtRspPtr[DEPTH_PTR-1:0]), .dout(RspPtr[DEPTH_PTR-1:0]), .en(RspPtrEn), .clk(dma_free_clk), .*);
|
||||
//rvdffs #(DEPTH_PTR) RspPtr_dff(.din(RspPtr[DEPTH_PTR-1:0]), .dout(PrevRspPtr[DEPTH_PTR-1:0]), .en(RspPtrEn), .clk(dma_free_clk), .*);
|
||||
|
||||
rvdff #(DEPTH_PTR) RdPtrQ1_dff(.din(RdPtr[DEPTH_PTR-1:0]), .dout(RdPtr_Q1[DEPTH_PTR-1:0]), .clk(dma_free_clk), .*);
|
||||
rvdff #(DEPTH_PTR) RdPtrQ2_dff(.din(RdPtr_Q1[DEPTH_PTR-1:0]), .dout(RdPtr_Q2[DEPTH_PTR-1:0]), .clk(dma_free_clk), .*);
|
||||
rvdff #(DEPTH_PTR) RdPtrQ3_dff(.din(RdPtr_Q2[DEPTH_PTR-1:0]), .dout(RdPtr_Q3[DEPTH_PTR-1:0]), .clk(dma_free_clk), .*);
|
||||
|
||||
// Miscellaneous signals
|
||||
assign fifo_full = fifo_full_spec_bus;
|
||||
|
||||
always_comb begin
|
||||
num_fifo_vld[3:0] = 4'b0;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
num_fifo_vld[3:0] += {3'b0,(fifo_valid_en[i] | fifo_valid[i])};
|
||||
end
|
||||
end
|
||||
assign fifo_full_spec = ((num_fifo_vld[3:0] == DEPTH) & ~(|fifo_reset[DEPTH-1:0]));
|
||||
|
||||
assign dma_fifo_ready = ~(fifo_full | dbg_dma_bubble_bus | dec_tlu_stall_dma_bus);
|
||||
|
||||
// Error logic
|
||||
assign dma_address_error = axi_mstr_valid & (~(dma_addr_in_dccm | dma_addr_in_iccm)); // request not for ICCM or DCCM
|
||||
assign dma_alignment_error = axi_mstr_valid & ~dma_address_error &
|
||||
(((axi_mstr_size[2:0] == 3'h1) & (axi_mstr_addr[0] | (axi_mstr_write & (axi_mstr_wstrb[axi_mstr_addr[2:0]+:2] != 2'b11)))) | // HW size but unaligned
|
||||
((axi_mstr_size[2:0] == 3'h2) & ((|axi_mstr_addr[1:0]) | (axi_mstr_write & (axi_mstr_wstrb[axi_mstr_addr[2:0]+:4] != 4'hf)))) | // W size but unaligned
|
||||
((axi_mstr_size[2:0] == 3'h3) & ((|axi_mstr_addr[2:0]) | (axi_mstr_write & (axi_mstr_wstrb[7:0] != 8'hff)))) | // DW size but unaligned
|
||||
(dma_addr_in_iccm & ~((axi_mstr_size[1:0] == 2'b10) | (axi_mstr_size[1:0] == 2'b11))) | // ICCM access not word size
|
||||
(dma_addr_in_dccm & axi_mstr_write & ~((axi_mstr_size[1:0] == 2'b10) | (axi_mstr_size[1:0] == 2'b11)))); // DCCM write not word size
|
||||
|
||||
//Dbg outputs
|
||||
assign dma_dbg_ready = fifo_empty & dbg_dma_bubble;
|
||||
assign dma_dbg_cmd_done = (fifo_valid[RspPtr] & fifo_dbg[RspPtr] & (fifo_write[RspPtr] | fifo_data_valid[RspPtr] | (|fifo_error[RspPtr])));
|
||||
assign dma_dbg_rddata[31:0] = fifo_addr[RspPtr][2] ? fifo_data[RspPtr][63:32] : fifo_data[RspPtr][31:0];
|
||||
assign dma_dbg_cmd_fail = |fifo_error[RspPtr];
|
||||
|
||||
assign dma_dbg_cmd_error_in = dbg_cmd_valid & (dbg_cmd_type[1:0] == 2'b10) &
|
||||
((~(dma_addr_in_dccm | dma_addr_in_iccm | dma_addr_in_pic)) | (dbg_cmd_size[1:0] != 2'b10)); // Only word accesses allowed
|
||||
//(dma_addr_in_iccm & ~((dbg_cmd_size[1:0] == 2'b10) | (dbg_cmd_size[1:0] == 2'b11))));
|
||||
|
||||
|
||||
// Block the decode if fifo full
|
||||
assign dma_dccm_stall_any = dma_mem_req & fifo_dccm_valid[RdPtr] & (dma_nack_count >= dma_nack_count_csr);
|
||||
assign dma_iccm_stall_any = dma_mem_req & fifo_iccm_valid[RdPtr] & (dma_nack_count >= dma_nack_count_csr);
|
||||
|
||||
// Used to indicate ready to debug
|
||||
assign fifo_empty = ~(|(fifo_valid_en[DEPTH-1:0] | fifo_valid[DEPTH-1:0]) | axi_mstr_valid | axi_slv_sent_q); // We want RspPtr to settle before accepting debug command
|
||||
|
||||
// Nack counter, stall the lsu pipe if 7 nacks
|
||||
assign dma_nack_count_csr[2:0] = dec_tlu_dma_qos_prty[2:0];
|
||||
assign dma_nack_count_d[2:0] = (dma_nack_count[2:0] >= dma_nack_count_csr[2:0]) ? ({3{~(dma_dccm_req | dma_iccm_req)}} & dma_nack_count[2:0]) :
|
||||
(dma_mem_req & ~(dma_dccm_req | dma_iccm_req)) ? (dma_nack_count[2:0] + 1'b1) : 3'b0;
|
||||
|
||||
rvdffs #(3) nack_count_dff(.din(dma_nack_count_d[2:0]), .dout(dma_nack_count[2:0]), .en(dma_mem_req), .clk(dma_free_clk), .*);
|
||||
|
||||
// Core outputs
|
||||
assign dma_mem_req = fifo_valid[RdPtr] & ~fifo_rpend[RdPtr] & ~fifo_done[RdPtr] & ~(|fifo_error[RdPtr]) & (~fifo_write[RdPtr] | fifo_data_valid[RdPtr]);
|
||||
assign dma_dccm_req = dma_mem_req & fifo_dccm_valid[RdPtr] & dccm_ready;
|
||||
assign dma_iccm_req = dma_mem_req & fifo_iccm_valid[RdPtr] & iccm_ready;
|
||||
assign dma_mem_addr[31:0] = fifo_addr[RdPtr];
|
||||
assign dma_mem_sz[2:0] = fifo_sz[RdPtr];
|
||||
assign dma_mem_write = fifo_write[RdPtr];
|
||||
assign dma_mem_wdata[63:0] = fifo_data[RdPtr];
|
||||
|
||||
// Address check dccm
|
||||
rvrangecheck #(.CCM_SADR(`RV_DCCM_SADR),
|
||||
.CCM_SIZE(`RV_DCCM_SIZE)) addr_dccm_rangecheck (
|
||||
.addr(fifo_addr_in[31:0]),
|
||||
.in_range(dma_addr_in_dccm),
|
||||
.in_region(dma_addr_in_dccm_region_nc)
|
||||
);
|
||||
|
||||
// Address check iccm
|
||||
`ifdef RV_ICCM_ENABLE
|
||||
rvrangecheck #(.CCM_SADR(`RV_ICCM_SADR),
|
||||
.CCM_SIZE(`RV_ICCM_SIZE)) addr_iccm_rangecheck (
|
||||
.addr(fifo_addr_in[31:0]),
|
||||
.in_range(dma_addr_in_iccm),
|
||||
.in_region(dma_addr_in_iccm_region_nc)
|
||||
);
|
||||
`else
|
||||
assign dma_addr_in_iccm = '0;
|
||||
assign dma_addr_in_iccm_region_nc = '0;
|
||||
`endif
|
||||
|
||||
// PIC memory address check
|
||||
rvrangecheck #(.CCM_SADR(`RV_PIC_BASE_ADDR),
|
||||
.CCM_SIZE(`RV_PIC_SIZE)) addr_pic_rangecheck (
|
||||
.addr(fifo_addr_in[31:0]),
|
||||
.in_range(dma_addr_in_pic),
|
||||
.in_region(dma_addr_in_pic_region_nc)
|
||||
);
|
||||
|
||||
// Inputs
|
||||
rvdff #(1) ahbs_bus_clken_ff (.din(dma_bus_clk_en), .dout(dma_bus_clk_en_q), .clk(free_clk), .*);
|
||||
rvdff #(1) fifo_full_bus_ff (.din(fifo_full_spec), .dout(fifo_full_spec_bus), .clk(dma_bus_clk), .*);
|
||||
rvdff #(1) dbg_dma_bubble_ff (.din(dbg_dma_bubble), .dout(dbg_dma_bubble_bus), .clk(dma_bus_clk), .*);
|
||||
rvdff #(1) dec_tlu_stall_dma_ff (.din(dec_tlu_stall_dma), .dout(dec_tlu_stall_dma_bus), .clk(dma_bus_clk), .*);
|
||||
rvdff #(1) dma_dbg_cmd_doneff (.din(dma_dbg_cmd_done), .dout(dma_dbg_cmd_done_q), .clk(free_clk), .*);
|
||||
|
||||
// Clock Gating logic
|
||||
assign dma_buffer_c1_clken = (axi_mstr_valid & dma_bus_clk_en) | dbg_cmd_valid | dec_tlu_stall_dma | clk_override;
|
||||
assign dma_free_clken = (axi_mstr_valid | axi_mstr_valid_q | axi_slv_valid | axi_slv_sent_q | dbg_cmd_valid | dma_dbg_cmd_done | dma_dbg_cmd_done_q | (|fifo_valid[DEPTH-1:0]) | wrbuf_vld | rdbuf_vld | dec_tlu_stall_dma | clk_override);
|
||||
|
||||
rvclkhdr dma_buffer_c1cgc ( .en(dma_buffer_c1_clken), .l1clk(dma_buffer_c1_clk), .* );
|
||||
rvclkhdr dma_free_cgc (.en(dma_free_clken), .l1clk(dma_free_clk), .*);
|
||||
rvclkhdr dma_bus_cgc (.en(dma_bus_clk_en), .l1clk(dma_bus_clk), .*);
|
||||
|
||||
// Write channel buffer
|
||||
assign wrbuf_en = dma_axi_awvalid & dma_axi_awready;
|
||||
assign wrbuf_data_en = dma_axi_wvalid & dma_axi_wready;
|
||||
assign wrbuf_cmd_sent = axi_mstr_valid & axi_mstr_write;
|
||||
assign wrbuf_rst = wrbuf_cmd_sent & ~wrbuf_en;
|
||||
assign wrbuf_data_rst = wrbuf_cmd_sent & ~wrbuf_data_en;
|
||||
|
||||
rvdffsc #(.WIDTH(1)) wrbuf_vldff(.din(1'b1), .dout(wrbuf_vld), .en(wrbuf_en), .clear(wrbuf_rst), .clk(dma_bus_clk), .*);
|
||||
rvdffsc #(.WIDTH(1)) wrbuf_data_vldff(.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_data_rst), .clk(dma_bus_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) wrbuf_postedff(.din(1'b0), .dout(wrbuf_posted), .en(wrbuf_en), .clk(dma_bus_clk), .*);
|
||||
rvdffs #(.WIDTH(DMA_BUS_TAG)) wrbuf_tagff(.din(dma_axi_awid[DMA_BUS_TAG-1:0]), .dout(wrbuf_tag[DMA_BUS_TAG-1:0]), .en(wrbuf_en), .clk(dma_bus_clk), .*);
|
||||
rvdffs #(.WIDTH(3)) wrbuf_sizeff(.din(dma_axi_awsize[2:0]), .dout(wrbuf_size[2:0]), .en(wrbuf_en), .clk(dma_bus_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) wrbuf_addrff(.din(dma_axi_awaddr[31:0]), .dout(wrbuf_addr[31:0]), .en(wrbuf_en & dma_bus_clk_en), .*);
|
||||
rvdffe #(.WIDTH(64)) wrbuf_dataff(.din(dma_axi_wdata[63:0]), .dout(wrbuf_data[63:0]), .en(wrbuf_data_en & dma_bus_clk_en), .*);
|
||||
rvdffs #(.WIDTH(8)) wrbuf_byteenff(.din(dma_axi_wstrb[7:0]), .dout(wrbuf_byteen[7:0]), .en(wrbuf_data_en), .clk(dma_bus_clk), .*);
|
||||
// Read channel buffer
|
||||
assign rdbuf_en = dma_axi_arvalid & dma_axi_arready;
|
||||
assign rdbuf_cmd_sent = axi_mstr_valid & ~axi_mstr_write & dma_fifo_ready;
|
||||
assign rdbuf_rst = rdbuf_cmd_sent & ~rdbuf_en;
|
||||
|
||||
rvdffsc #(.WIDTH(1)) rdbuf_vldff(.din(1'b1), .dout(rdbuf_vld), .en(rdbuf_en), .clear(rdbuf_rst), .clk(dma_bus_clk), .*);
|
||||
rvdffs #(.WIDTH(DMA_BUS_TAG)) rdbuf_tagff(.din(dma_axi_arid[DMA_BUS_TAG-1:0]), .dout(rdbuf_tag[DMA_BUS_TAG-1:0]), .en(rdbuf_en), .clk(dma_bus_clk), .*);
|
||||
rvdffs #(.WIDTH(3)) rdbuf_sizeff(.din(dma_axi_arsize[2:0]), .dout(rdbuf_size[2:0]), .en(rdbuf_en), .clk(dma_bus_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) rdbuf_addrff(.din(dma_axi_araddr[31:0]), .dout(rdbuf_addr[31:0]), .en(rdbuf_en & dma_bus_clk_en), .*);
|
||||
|
||||
assign dma_axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent);
|
||||
assign dma_axi_wready = ~(wrbuf_data_vld & ~wrbuf_cmd_sent);
|
||||
assign dma_axi_arready = ~(rdbuf_vld & ~rdbuf_cmd_sent);
|
||||
|
||||
//Generate a single request from read/write channel
|
||||
assign axi_mstr_valid = ((wrbuf_vld & wrbuf_data_vld) | rdbuf_vld) & dma_fifo_ready;
|
||||
assign axi_mstr_tag[DMA_BUS_TAG-1:0] = axi_mstr_sel ? wrbuf_tag[DMA_BUS_TAG-1:0] : rdbuf_tag[DMA_BUS_TAG-1:0];
|
||||
assign axi_mstr_write = axi_mstr_sel;
|
||||
assign axi_mstr_posted_write = axi_mstr_sel & wrbuf_posted;
|
||||
assign axi_mstr_addr[31:0] = axi_mstr_sel ? wrbuf_addr[31:0] : rdbuf_addr[31:0];
|
||||
assign axi_mstr_size[2:0] = axi_mstr_sel ? wrbuf_size[2:0] : rdbuf_size[2:0];
|
||||
assign axi_mstr_wdata[63:0] = wrbuf_data[63:0];
|
||||
assign axi_mstr_wstrb[7:0] = wrbuf_byteen[7:0];
|
||||
|
||||
// Sel=1 -> write has higher priority
|
||||
assign axi_mstr_sel = (wrbuf_vld & wrbuf_data_vld & rdbuf_vld) ? axi_mstr_priority : (wrbuf_vld & wrbuf_data_vld);
|
||||
assign axi_mstr_prty_in = ~axi_mstr_priority;
|
||||
assign axi_mstr_prty_en = axi_mstr_valid;
|
||||
rvdffs #(.WIDTH(1)) mstr_prtyff(.din(axi_mstr_prty_in), .dout(axi_mstr_priority), .en(axi_mstr_prty_en), .clk(dma_bus_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) axi_mstr_validff (.din(axi_mstr_valid), .dout(axi_mstr_valid_q), .clk(dma_bus_clk), .*);
|
||||
rvdff #(.WIDTH(1)) axi_slv_sentff (.din(axi_slv_sent), .dout(axi_slv_sent_q), .clk(dma_bus_clk), .*);
|
||||
|
||||
//assign axi_slv_valid = fifo_valid[RspPtr] & ~fifo_rsp_done[RspPtr] & ~fifo_dbg[RspPtr] &
|
||||
// ((fifo_write[RspPtr] & fifo_done_bus[RspPtr]) | (~fifo_write[RspPtr] & fifo_data_bus_valid[RspPtr]) | fifo_error_bus[RspPtr]);
|
||||
assign axi_slv_valid = fifo_valid[RspPtr] & ~fifo_dbg[RspPtr] & fifo_done_bus[RspPtr];
|
||||
assign axi_slv_tag[DMA_BUS_TAG-1:0] = fifo_tag[RspPtr];
|
||||
//assign axi_slv_rdata[63:0] = (|fifo_error[RspPtr]) ? {32'b0,fifo_addr[RspPtr]} : fifo_data[RspPtr];
|
||||
assign axi_slv_rdata[63:0] = fifo_data[RspPtr];
|
||||
assign axi_slv_write = fifo_write[RspPtr];
|
||||
assign axi_slv_posted_write = axi_slv_write & fifo_posted_write[RspPtr];
|
||||
assign axi_slv_error[1:0] = fifo_error[RspPtr][0] ? 2'b10 : (fifo_error[RspPtr][1] ? 2'b11 : 2'b0);
|
||||
|
||||
|
||||
// AXI response channel signals
|
||||
assign dma_axi_bvalid = axi_slv_valid & axi_slv_write;
|
||||
assign dma_axi_bresp[1:0] = axi_slv_error[1:0];
|
||||
assign dma_axi_bid[DMA_BUS_TAG-1:0] = axi_slv_tag[DMA_BUS_TAG-1:0];
|
||||
|
||||
assign dma_axi_rvalid = axi_slv_valid & ~axi_slv_write;
|
||||
assign dma_axi_rresp[1:0] = axi_slv_error;
|
||||
assign dma_axi_rid[DMA_BUS_TAG-1:0] = axi_slv_tag[DMA_BUS_TAG-1:0];
|
||||
assign dma_axi_rdata[63:0] = axi_slv_rdata[63:0];
|
||||
assign dma_axi_rlast = 1'b1;
|
||||
|
||||
assign axi_slv_sent = (dma_axi_bvalid & dma_axi_bready) | (dma_axi_rvalid & dma_axi_rready);
|
||||
assign dma_slv_algn_err = fifo_error[RspPtr][1];
|
||||
`ifdef ASSERT_ON
|
||||
|
||||
//assert_nack_count: assert #0 (dma_nack_count[2:0] < 3'h4);
|
||||
|
||||
for (genvar i=0; i<DEPTH; i++) begin
|
||||
//assert_picm_rspdone_and_novalid: assert #0 (~fifo_rsp_done[i] | fifo_valid[i]);
|
||||
assert_done_and_novalid: assert #0 (~fifo_done[i] | fifo_valid[i]);
|
||||
end
|
||||
|
||||
// Assertion to check AXI write address is aligned to size
|
||||
property dma_axi_write_trxn_aligned;
|
||||
@(posedge dma_bus_clk) dma_axi_awvalid |-> ((dma_axi_awsize[2:0] == 3'h0) |
|
||||
((dma_axi_awsize[2:0] == 3'h1) & (dma_axi_awaddr[0] == 1'b0)) |
|
||||
((dma_axi_awsize[2:0] == 3'h2) & (dma_axi_awaddr[1:0] == 2'b0)) |
|
||||
((dma_axi_awsize[2:0] == 3'h3) & (dma_axi_awaddr[2:0] == 3'b0)));
|
||||
endproperty
|
||||
// assert_dma_write_trxn_aligned: assert property (dma_axi_write_trxn_aligned) else
|
||||
// $display("Assertion dma_axi_write_trxn_aligned failed: dma_axi_awvalid=1'b%b, dma_axi_awsize=3'h%h, dma_axi_awaddr=32'h%h",dma_axi_awvalid, dma_axi_awsize[2:0], dma_axi_awaddr[31:0]);
|
||||
|
||||
// Assertion to check AXI read address is aligned to size
|
||||
property dma_axi_read_trxn_aligned;
|
||||
@(posedge dma_bus_clk) dma_axi_arvalid |-> ((dma_axi_arsize[2:0] == 3'h0) |
|
||||
((dma_axi_arsize[2:0] == 3'h1) & (dma_axi_araddr[0] == 1'b0)) |
|
||||
((dma_axi_arsize[2:0] == 3'h2) & (dma_axi_araddr[1:0] == 2'b0)) |
|
||||
((dma_axi_arsize[2:0] == 3'h3) & (dma_axi_araddr[2:0] == 3'b0)));
|
||||
endproperty
|
||||
// assert_dma_read_trxn_aligned: assert property (dma_axi_read_trxn_aligned) else
|
||||
// $display("Assertion dma_axi_read_trxn_aligned failed: dma_axi_arvalid=1'b%b, dma_axi_arsize=3'h%h, dma_axi_araddr=32'h%h",dma_axi_arvalid, dma_axi_arsize[2:0], dma_axi_araddr[31:0]);
|
||||
|
||||
// Assertion to check write size is 8 byte or less
|
||||
property dma_axi_awsize_check;
|
||||
@(posedge dma_bus_clk) disable iff(~rst_l) (dma_axi_awvalid & dma_axi_awready) |-> (dma_axi_awsize[2] == 1'b0);
|
||||
endproperty
|
||||
assert_dma_axi_awsize_check: assert property (dma_axi_awsize_check) else
|
||||
$display("DMA AXI awsize is illegal. Size greater than 8B not supported");
|
||||
|
||||
// Assertion to check there are no burst commands
|
||||
property dma_axi_awlen_check;
|
||||
@(posedge dma_bus_clk) disable iff(~rst_l) (dma_axi_awvalid & dma_axi_awready) |-> (dma_axi_awlen[7:0] == 8'b0);
|
||||
endproperty
|
||||
assert_dma_axi_awlen_check: assert property (dma_axi_awlen_check) else
|
||||
$display("DMA AXI awlen is illegal. Length greater than 0 not supported");
|
||||
|
||||
// Assertion to check write size is 8 byte or less
|
||||
property dma_axi_arsize_check;
|
||||
@(posedge dma_bus_clk) disable iff(~rst_l) (dma_axi_arvalid & dma_axi_arready) |-> (dma_axi_arsize[2] == 1'b0);
|
||||
endproperty
|
||||
assert_dma_axi_arsize_check: assert property (dma_axi_arsize_check) else
|
||||
$display("DMA AXI arsize is illegal, Size bigger than 8B not supported");
|
||||
|
||||
// Assertion to check there are no burst commands
|
||||
property dma_axi_arlen_check;
|
||||
@(posedge dma_bus_clk) disable iff(~rst_l) (dma_axi_arvalid & dma_axi_arready) |-> (dma_axi_arlen[7:0] == 8'b0);
|
||||
endproperty
|
||||
assert_dma_axi_arlen_check: assert property (dma_axi_arlen_check) else
|
||||
$display("DMA AXI arlen greater than 0 not supported.");
|
||||
|
||||
// Assertion to check cmd valid stays stable during entire bus clock
|
||||
property dma_axi_awvalid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_awvalid != $past(dma_axi_awvalid)) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_awvalid_stable: assert property (dma_axi_awvalid_stable) else
|
||||
$display("DMA AXI awvalid changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd ready stays stable during entire bus clock
|
||||
property dma_axi_awready_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_awready != $past(dma_axi_awready)) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_awready_stable: assert property (dma_axi_awready_stable) else
|
||||
$display("DMA AXI awready changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd tag stays stable during entire bus clock
|
||||
property dma_axi_awid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_awvalid & (dma_axi_awid[DMA_BUS_TAG-1:0] != $past(dma_axi_awid[DMA_BUS_TAG-1:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_awid_stable: assert property (dma_axi_awid_stable) else
|
||||
$display("DMA AXI awid changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd addr stays stable during entire bus clock
|
||||
property dma_axi_awaddr_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_awvalid & (dma_axi_awaddr[31:0] != $past(dma_axi_awaddr[31:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_awaddr_stable: assert property (dma_axi_awaddr_stable) else
|
||||
$display("DMA AXI awaddr changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd length stays stable during entire bus clock
|
||||
property dma_axi_awsize_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_awvalid & (dma_axi_awsize[2:0] != $past(dma_axi_awsize[2:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_awsize_stable: assert property (dma_axi_awsize_stable) else
|
||||
$display("DMA AXI awsize changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd valid stays stable during entire bus clock
|
||||
property dma_axi_wvalid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_wvalid != $past(dma_axi_wvalid)) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_wvalid_stable: assert property (dma_axi_wvalid_stable) else
|
||||
$display("DMA AXI wvalid changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd ready stays stable during entire bus clock
|
||||
property dma_axi_wready_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_wready != $past(dma_axi_wready)) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_wready_stable: assert property (dma_axi_wready_stable) else
|
||||
$display("DMA AXI wready changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd wbe stays stable during entire bus clock
|
||||
property dma_axi_wstrb_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_wvalid & (dma_axi_wstrb[7:0] != $past(dma_axi_wstrb[7:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_wstrb_stable: assert property (dma_axi_wstrb_stable) else
|
||||
$display("DMA AXI wstrb changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd wdata stays stable during entire bus clock
|
||||
property dma_axi_wdata_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_wvalid & (dma_axi_wdata[63:0] != $past(dma_axi_wdata[63:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_wdata_stable: assert property (dma_axi_wdata_stable) else
|
||||
$display("DMA AXI wdata changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd valid stays stable during entire bus clock
|
||||
property dma_axi_arvalid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_arvalid != $past(dma_axi_arvalid)) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_arvalid_stable: assert property (dma_axi_arvalid_stable) else
|
||||
$display("DMA AXI arvalid changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd ready stays stable during entire bus clock
|
||||
property dma_axi_arready_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_arready != $past(dma_axi_arready)) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_arready_stable: assert property (dma_axi_arready_stable) else
|
||||
$display("DMA AXI arready changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd tag stays stable during entire bus clock
|
||||
property dma_axi_arid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_arvalid & (dma_axi_arid[DMA_BUS_TAG-1:0] != $past(dma_axi_arid[DMA_BUS_TAG-1:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_arid_stable: assert property (dma_axi_arid_stable) else
|
||||
$display("DMA AXI arid changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd addr stays stable during entire bus clock
|
||||
property dma_axi_araddr_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_arvalid & (dma_axi_araddr[31:0] != $past(dma_axi_araddr[31:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_araddr_stable: assert property (dma_axi_araddr_stable) else
|
||||
$display("DMA AXI araddr changed in middle of bus clock");
|
||||
|
||||
// Assertion to check cmd length stays stable during entire bus clock
|
||||
property dma_axi_arsize_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_arvalid & (dma_axi_arsize[2:0] != $past(dma_axi_arsize[2:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_arsize_stable: assert property (dma_axi_arsize_stable) else
|
||||
$display("DMA AXI arsize changed in middle of bus clock");
|
||||
|
||||
//Assertion to check write rsp valid stays stable during entire bus clock
|
||||
property dma_axi_bvalid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_bvalid != $past(dma_axi_bvalid)) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_bvalid_stable: assert property (dma_axi_bvalid_stable) else
|
||||
$display("DMA AXI bvalid changed in middle of bus clock");
|
||||
|
||||
// //Assertion to check write rsp ready stays stable during entire bus clock
|
||||
// property dma_axi_bready_stable;
|
||||
// @(posedge clk) (dma_axi_bready != $past(dma_axi_bready)) |-> $past(dma_bus_clk_en);
|
||||
// endproperty
|
||||
// assert_dma_axi_bready_stable: assert property (dma_axi_bready_stable) else
|
||||
// $display("DMA AXI bready changed in middle of bus clock");
|
||||
|
||||
//Assertion to check write rsp stays stable during entire bus clock
|
||||
property dma_axi_bresp_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_bvalid & (dma_axi_bresp[1:0] != $past(dma_axi_bresp[1:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_bresp_stable: assert property (dma_axi_bresp_stable) else
|
||||
$display("DMA AXI bvalid changed in middle of bus clock");
|
||||
|
||||
// Assertion to check write rsp tag stays stable during entire bus clock
|
||||
property dma_axi_bid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_bvalid & (dma_axi_bid[DMA_BUS_TAG-1:0] != $past(dma_axi_bid[DMA_BUS_TAG-1:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_bid_stable: assert property (dma_axi_bid_stable) else
|
||||
$display("DMA AXI bid changed in middle of bus clock");
|
||||
|
||||
//Assertion to check write rsp valid stays stable during entire bus clock
|
||||
property dma_axi_rvalid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_rvalid != $past(dma_axi_rvalid)) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_rvalid_stable: assert property (dma_axi_rvalid_stable) else
|
||||
$display("DMA AXI bvalid changed in middle of bus clock");
|
||||
|
||||
// //Assertion to check write rsp ready stays stable during entire bus clock
|
||||
// property dma_axi_rready_stable;
|
||||
// @(posedge clk) (dma_axi_rready != $past(dma_axi_rready)) |-> $past(dma_bus_clk_en);
|
||||
// endproperty
|
||||
// assert_dma_axi_rready_stable: assert property (dma_axi_rready_stable) else
|
||||
// $display("DMA AXI bready changed in middle of bus clock");
|
||||
|
||||
//Assertion to check write rsp stays stable during entire bus clock
|
||||
property dma_axi_rresp_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_rvalid & (dma_axi_rresp[1:0] != $past(dma_axi_rresp[1:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_rresp_stable: assert property (dma_axi_rresp_stable) else
|
||||
$display("DMA AXI bvalid changed in middle of bus clock");
|
||||
|
||||
// Assertion to check write rsp tag stays stable during entire bus clock
|
||||
property dma_axi_rid_stable;
|
||||
@(posedge clk) disable iff(~rst_l) (dma_axi_rvalid & (dma_axi_rid[DMA_BUS_TAG-1:0] != $past(dma_axi_rid[DMA_BUS_TAG-1:0]))) |-> $past(dma_bus_clk_en);
|
||||
endproperty
|
||||
assert_dma_axi_rid_stable: assert property (dma_axi_rid_stable) else
|
||||
$display("DMA AXI bid changed in middle of bus clock");
|
||||
|
||||
`endif
|
||||
|
||||
endmodule // dma_ctrl
|
|
@ -0,0 +1,65 @@
|
|||
// 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.
|
||||
//------------------------------------------------------------------------------------
|
||||
// This module Synchronizes the signals between JTAG (TCK) and
|
||||
// processor (clk)
|
||||
//
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
module dmi_jtag_to_core_sync (
|
||||
// JTAG signals
|
||||
input rd_en, // 1 bit Read Enable
|
||||
input wr_en, // 1 bit Write enable
|
||||
|
||||
|
||||
// Processor Signals
|
||||
input rst_n, // Core clock
|
||||
input clk, // Core reset
|
||||
|
||||
output reg_en, // 1 bit Write interface bit to Processor
|
||||
output reg_wr_en // 1 bit Write enable to Processor
|
||||
);
|
||||
|
||||
|
||||
|
||||
wire c_rd_en;
|
||||
wire c_wr_en;
|
||||
|
||||
|
||||
//Assign statements
|
||||
|
||||
assign reg_en = c_wr_en | c_rd_en;
|
||||
assign reg_wr_en = c_wr_en;
|
||||
|
||||
reg [2:0] rden, wren;
|
||||
|
||||
// synchronizers
|
||||
always @ ( posedge clk or negedge rst_n) begin
|
||||
if(!rst_n) begin
|
||||
rden <= '0;
|
||||
wren <= '0;
|
||||
end
|
||||
else begin
|
||||
rden <= {rden[1:0], rd_en};
|
||||
wren <= {wren[1:0], wr_en};
|
||||
end
|
||||
end
|
||||
|
||||
assign c_rd_en = rden[1] & ~rden[2];
|
||||
assign c_wr_en = wren[1] & ~wren[2];
|
||||
|
||||
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,91 @@
|
|||
// 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.
|
||||
//------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright Western Digital, 2019
|
||||
// Owner : Anusha Narayanamoorthy
|
||||
// Description:
|
||||
// Wrapper module for JTAG_TAP and DMI synchronizer
|
||||
//
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
module dmi_wrapper(
|
||||
input scan_mode, // scan mode
|
||||
|
||||
// JTAG signals
|
||||
input trst_n, // JTAG reset
|
||||
input tck, // JTAG clock
|
||||
input tms, // Test mode select
|
||||
input tdi, // Test Data Input
|
||||
output tdo, // Test Data Output
|
||||
output tdoEnable, // Test Data Output enable
|
||||
|
||||
// Processor Signals
|
||||
input core_rst_n, // Core reset
|
||||
input core_clk, // Core clock
|
||||
input [31:1] jtag_id, // JTAG ID
|
||||
input [31:0] rd_data, // 32 bit Read data from Processor
|
||||
output [31:0] reg_wr_data, // 32 bit Write data to Processor
|
||||
output [6:0] reg_wr_addr, // 7 bit reg address to Processor
|
||||
output reg_en, // 1 bit Read enable to Processor
|
||||
output reg_wr_en, // 1 bit Write enable to Processor
|
||||
output dmi_hard_reset
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Wire Declaration
|
||||
wire rd_en;
|
||||
wire wr_en;
|
||||
wire dmireset;
|
||||
|
||||
|
||||
//jtag_tap instantiation
|
||||
rvjtag_tap i_jtag_tap(
|
||||
.trst(trst_n), // dedicated JTAG TRST (active low) pad signal or asynchronous active low power on reset
|
||||
.tck(tck), // dedicated JTAG TCK pad signal
|
||||
.tms(tms), // dedicated JTAG TMS pad signal
|
||||
.tdi(tdi), // dedicated JTAG TDI pad signal
|
||||
.tdo(tdo), // dedicated JTAG TDO pad signal
|
||||
.tdoEnable(tdoEnable), // enable for TDO pad
|
||||
.wr_data(reg_wr_data), // 32 bit Write data
|
||||
.wr_addr(reg_wr_addr), // 7 bit Write address
|
||||
.rd_en(rd_en), // 1 bit read enable
|
||||
.wr_en(wr_en), // 1 bit Write enable
|
||||
.rd_data(rd_data), // 32 bit Read data
|
||||
.rd_status(2'b0),
|
||||
.idle(3'h0), // no need to wait to sample data
|
||||
.dmi_stat(2'b0), // no need to wait or error possible
|
||||
.version(4'h1), // debug spec 0.13 compliant
|
||||
.jtag_id(jtag_id),
|
||||
.dmi_hard_reset(dmi_hard_reset),
|
||||
.dmi_reset(dmireset)
|
||||
);
|
||||
|
||||
|
||||
// dmi_jtag_to_core_sync instantiation
|
||||
dmi_jtag_to_core_sync i_dmi_jtag_to_core_sync(
|
||||
.wr_en(wr_en), // 1 bit Write enable
|
||||
.rd_en(rd_en), // 1 bit Read enable
|
||||
|
||||
.rst_n(core_rst_n),
|
||||
.clk(core_clk),
|
||||
.reg_en(reg_en), // 1 bit Write interface bit
|
||||
.reg_wr_en(reg_wr_en) // 1 bit Write enable
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,223 @@
|
|||
// 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
|
||||
|
||||
module rvjtag_tap #(
|
||||
parameter AWIDTH = 7
|
||||
)
|
||||
(
|
||||
input trst,
|
||||
input tck,
|
||||
input tms,
|
||||
input tdi,
|
||||
output reg tdo,
|
||||
output tdoEnable,
|
||||
|
||||
output [31:0] wr_data,
|
||||
output [AWIDTH-1:0] wr_addr,
|
||||
output wr_en,
|
||||
output rd_en,
|
||||
|
||||
input [31:0] rd_data,
|
||||
input [1:0] rd_status,
|
||||
|
||||
output reg dmi_reset,
|
||||
output reg dmi_hard_reset,
|
||||
|
||||
input [2:0] idle,
|
||||
input [1:0] dmi_stat,
|
||||
/*
|
||||
-- revisionCode : 4'h0;
|
||||
-- manufacturersIdCode : 11'h45;
|
||||
-- deviceIdCode : 16'h0001;
|
||||
-- order MSB .. LSB -> [4 bit version or revision] [16 bit part number] [11 bit manufacturer id] [value of 1'b1 in LSB]
|
||||
*/
|
||||
input [31:1] jtag_id,
|
||||
input [3:0] version
|
||||
);
|
||||
|
||||
localparam USER_DR_LENGTH = AWIDTH + 34;
|
||||
|
||||
|
||||
reg [USER_DR_LENGTH-1:0] sr, nsr, dr;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Tap controller
|
||||
///////////////////////////////////////////////////////
|
||||
logic[3:0] state, nstate;
|
||||
logic [4:0] ir;
|
||||
wire jtag_reset;
|
||||
wire shift_dr;
|
||||
wire pause_dr;
|
||||
wire update_dr;
|
||||
wire capture_dr;
|
||||
wire shift_ir;
|
||||
wire pause_ir ;
|
||||
wire update_ir ;
|
||||
wire capture_ir;
|
||||
wire[1:0] dr_en;
|
||||
wire devid_sel;
|
||||
wire [5:0] abits;
|
||||
|
||||
assign abits = AWIDTH[5:0];
|
||||
|
||||
|
||||
localparam TEST_LOGIC_RESET_STATE = 0;
|
||||
localparam RUN_TEST_IDLE_STATE = 1;
|
||||
localparam SELECT_DR_SCAN_STATE = 2;
|
||||
localparam CAPTURE_DR_STATE = 3;
|
||||
localparam SHIFT_DR_STATE = 4;
|
||||
localparam EXIT1_DR_STATE = 5;
|
||||
localparam PAUSE_DR_STATE = 6;
|
||||
localparam EXIT2_DR_STATE = 7;
|
||||
localparam UPDATE_DR_STATE = 8;
|
||||
localparam SELECT_IR_SCAN_STATE = 9;
|
||||
localparam CAPTURE_IR_STATE = 10;
|
||||
localparam SHIFT_IR_STATE = 11;
|
||||
localparam EXIT1_IR_STATE = 12;
|
||||
localparam PAUSE_IR_STATE = 13;
|
||||
localparam EXIT2_IR_STATE = 14;
|
||||
localparam UPDATE_IR_STATE = 15;
|
||||
|
||||
always_comb begin
|
||||
nstate = state;
|
||||
case(state)
|
||||
TEST_LOGIC_RESET_STATE: nstate = tms ? TEST_LOGIC_RESET_STATE : RUN_TEST_IDLE_STATE;
|
||||
RUN_TEST_IDLE_STATE: nstate = tms ? SELECT_DR_SCAN_STATE : RUN_TEST_IDLE_STATE;
|
||||
SELECT_DR_SCAN_STATE: nstate = tms ? SELECT_IR_SCAN_STATE : CAPTURE_DR_STATE;
|
||||
CAPTURE_DR_STATE: nstate = tms ? EXIT1_DR_STATE : SHIFT_DR_STATE;
|
||||
SHIFT_DR_STATE: nstate = tms ? EXIT1_DR_STATE : SHIFT_DR_STATE;
|
||||
EXIT1_DR_STATE: nstate = tms ? UPDATE_DR_STATE : PAUSE_DR_STATE;
|
||||
PAUSE_DR_STATE: nstate = tms ? EXIT2_DR_STATE : PAUSE_DR_STATE;
|
||||
EXIT2_DR_STATE: nstate = tms ? UPDATE_DR_STATE : SHIFT_DR_STATE;
|
||||
UPDATE_DR_STATE: nstate = tms ? SELECT_DR_SCAN_STATE : RUN_TEST_IDLE_STATE;
|
||||
SELECT_IR_SCAN_STATE: nstate = tms ? TEST_LOGIC_RESET_STATE : CAPTURE_IR_STATE;
|
||||
CAPTURE_IR_STATE: nstate = tms ? EXIT1_IR_STATE : SHIFT_IR_STATE;
|
||||
SHIFT_IR_STATE: nstate = tms ? EXIT1_IR_STATE : SHIFT_IR_STATE;
|
||||
EXIT1_IR_STATE: nstate = tms ? UPDATE_IR_STATE : PAUSE_IR_STATE;
|
||||
PAUSE_IR_STATE: nstate = tms ? EXIT2_IR_STATE : PAUSE_IR_STATE;
|
||||
EXIT2_IR_STATE: nstate = tms ? UPDATE_IR_STATE : SHIFT_IR_STATE;
|
||||
UPDATE_IR_STATE: nstate = tms ? SELECT_DR_SCAN_STATE : RUN_TEST_IDLE_STATE;
|
||||
default: nstate = TEST_LOGIC_RESET_STATE;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @ (posedge tck or negedge trst) begin
|
||||
if(!trst) state <= TEST_LOGIC_RESET_STATE;
|
||||
else state <= nstate;
|
||||
end
|
||||
|
||||
assign jtag_reset = state == TEST_LOGIC_RESET_STATE;
|
||||
assign shift_dr = state == SHIFT_DR_STATE;
|
||||
assign pause_dr = state == PAUSE_DR_STATE;
|
||||
assign update_dr = state == UPDATE_DR_STATE;
|
||||
assign capture_dr = state == CAPTURE_DR_STATE;
|
||||
assign shift_ir = state == SHIFT_IR_STATE;
|
||||
assign pause_ir = state == PAUSE_IR_STATE;
|
||||
assign update_ir = state == UPDATE_IR_STATE;
|
||||
assign capture_ir = state == CAPTURE_IR_STATE;
|
||||
|
||||
assign tdoEnable = shift_dr | shift_ir;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// IR register
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
always @ (negedge tck or negedge trst) begin
|
||||
if (!trst) ir <= 5'b1;
|
||||
else begin
|
||||
if (jtag_reset) ir <= 5'b1;
|
||||
else if (update_ir) ir <= (sr[4:0] == '0) ? 5'h1f :sr[4:0];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
assign devid_sel = ir == 5'b00001;
|
||||
assign dr_en[0] = ir == 5'b10000;
|
||||
assign dr_en[1] = ir == 5'b10001;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Shift register
|
||||
///////////////////////////////////////////////////////
|
||||
always @ (posedge tck or negedge trst) begin
|
||||
if(!trst)begin
|
||||
sr <= '0;
|
||||
end
|
||||
else begin
|
||||
sr <= nsr;
|
||||
end
|
||||
end
|
||||
|
||||
// SR next value
|
||||
always_comb begin
|
||||
nsr = sr;
|
||||
case(1)
|
||||
shift_dr: begin
|
||||
case(1)
|
||||
dr_en[1]: nsr = {tdi, sr[USER_DR_LENGTH-1:1]};
|
||||
|
||||
dr_en[0],
|
||||
devid_sel: nsr = {{USER_DR_LENGTH-32{1'b0}},tdi, sr[31:1]};
|
||||
default: nsr = {{USER_DR_LENGTH-1{1'b0}},tdi}; // bypass
|
||||
endcase
|
||||
end
|
||||
capture_dr: begin
|
||||
case(1)
|
||||
dr_en[0]: nsr = {{USER_DR_LENGTH-15{1'b0}}, idle, dmi_stat, abits, version};
|
||||
dr_en[1]: nsr = {{AWIDTH{1'b0}}, rd_data, rd_status};
|
||||
devid_sel: nsr = {{USER_DR_LENGTH-32{1'b0}}, jtag_id, 1'b1};
|
||||
endcase
|
||||
end
|
||||
shift_ir: nsr = {{USER_DR_LENGTH-5{1'b0}},tdi, sr[4:1]};
|
||||
capture_ir: nsr = {{USER_DR_LENGTH-1{1'b0}},1'b1};
|
||||
endcase
|
||||
end
|
||||
|
||||
// TDO retiming
|
||||
always @ (negedge tck ) tdo <= sr[0];
|
||||
|
||||
// DMI CS register
|
||||
always @ (posedge tck or negedge trst) begin
|
||||
if(!trst) begin
|
||||
dmi_hard_reset <= 1'b0;
|
||||
dmi_reset <= 1'b0;
|
||||
end
|
||||
else if (update_dr & dr_en[0]) begin
|
||||
dmi_hard_reset <= sr[17];
|
||||
dmi_reset <= sr[16];
|
||||
end
|
||||
else begin
|
||||
dmi_hard_reset <= 1'b0;
|
||||
dmi_reset <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// DR register
|
||||
always @ (posedge tck or negedge trst) begin
|
||||
if(!trst)
|
||||
dr <= '0;
|
||||
else begin
|
||||
if (update_dr & dr_en[1])
|
||||
dr <= sr;
|
||||
else
|
||||
dr <= {dr[USER_DR_LENGTH-1:2],2'b0};
|
||||
end
|
||||
end
|
||||
|
||||
assign {wr_addr, wr_data, wr_en, rd_en} = dr;
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,839 @@
|
|||
// 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.
|
||||
|
||||
|
||||
module exu
|
||||
import swerv_types::*;
|
||||
(
|
||||
|
||||
input logic clk, // Top level clock
|
||||
input logic active_clk, // Level 1 active clock
|
||||
input logic clk_override, // Override multiply clock enables
|
||||
input logic rst_l, // Reset
|
||||
input logic scan_mode, // Scan control
|
||||
input logic lsu_freeze_dc3, // Freeze pipe from D to DC3
|
||||
|
||||
input logic dec_tlu_fast_div_disable, // Disable divide small number optimization
|
||||
|
||||
input logic [4:2] dec_i0_data_en, // Slot I0 clock enable {e1, e2, e3 }, one cycle pulse
|
||||
input logic [4:1] dec_i0_ctl_en, // Slot I0 clock enable {e1, e2, e3, e4}, two cycle pulse
|
||||
input logic [4:2] dec_i1_data_en, // Slot I1 clock enable {e1, e2, e3 }, one cycle pulse
|
||||
input logic [4:1] dec_i1_ctl_en, // Slot I1 clock enable {e1, e2, e3, e4}, two cycle pulse
|
||||
|
||||
input logic dec_debug_wdata_rs1_d, // Debug select to primary I0 RS1
|
||||
|
||||
input logic [31:0] dbg_cmd_wrdata, // Debug data to primary I0 RS1
|
||||
|
||||
input logic [31:0] lsu_result_dc3, // Load result
|
||||
|
||||
input predict_pkt_t i0_predict_p_d, // DEC branch predict packet
|
||||
input predict_pkt_t i1_predict_p_d, // DEC branch predict packet
|
||||
|
||||
input logic dec_i0_rs1_bypass_en_e2, // DEC bypass bus select for E2 stage
|
||||
input logic dec_i0_rs2_bypass_en_e2, // DEC bypass bus select for E2 stage
|
||||
input logic dec_i1_rs1_bypass_en_e2, // DEC bypass bus select for E2 stage
|
||||
input logic dec_i1_rs2_bypass_en_e2, // DEC bypass bus select for E2 stage
|
||||
input logic [31:0] i0_rs1_bypass_data_e2, // DEC bypass bus
|
||||
input logic [31:0] i0_rs2_bypass_data_e2, // DEC bypass bus
|
||||
input logic [31:0] i1_rs1_bypass_data_e2, // DEC bypass bus
|
||||
input logic [31:0] i1_rs2_bypass_data_e2, // DEC bypass bus
|
||||
|
||||
input logic dec_i0_rs1_bypass_en_e3, // DEC bypass bus select for E3 stage
|
||||
input logic dec_i0_rs2_bypass_en_e3, // DEC bypass bus select for E3 stage
|
||||
input logic dec_i1_rs1_bypass_en_e3, // DEC bypass bus select for E3 stage
|
||||
input logic dec_i1_rs2_bypass_en_e3, // DEC bypass bus select for E3 stage
|
||||
input logic [31:0] i0_rs1_bypass_data_e3, // DEC bypass bus
|
||||
input logic [31:0] i0_rs2_bypass_data_e3, // DEC bypass bus
|
||||
input logic [31:0] i1_rs1_bypass_data_e3, // DEC bypass bus
|
||||
input logic [31:0] i1_rs2_bypass_data_e3, // DEC bypass bus
|
||||
|
||||
input logic dec_i0_sec_decode_e3, // Secondary ALU valid
|
||||
input logic dec_i1_sec_decode_e3, // Secondary ALU valid
|
||||
input logic [31:1] dec_i0_pc_e3, // Secondary ALU PC
|
||||
input logic [31:1] dec_i1_pc_e3, // Secondary ALU PC
|
||||
|
||||
input logic [31:1] pred_correct_npc_e2, // DEC NPC for correctly predicted branch
|
||||
|
||||
input logic dec_i1_valid_e1, // I1 valid E1
|
||||
|
||||
input logic dec_i0_mul_d, // Select for Multiply GPR value
|
||||
input logic dec_i1_mul_d, // Select for Multiply GPR value
|
||||
|
||||
input logic dec_i0_div_d, // Select for Divide GPR value
|
||||
input logic dec_i1_div_d, // Select for Divide GPR value
|
||||
|
||||
input logic [31:0] gpr_i0_rs1_d, // DEC data gpr
|
||||
input logic [31:0] gpr_i0_rs2_d, // DEC data gpr
|
||||
input logic [31:0] dec_i0_immed_d, // DEC data immediate
|
||||
|
||||
input logic [31:0] gpr_i1_rs1_d, // DEC data gpr
|
||||
input logic [31:0] gpr_i1_rs2_d, // DEC data gpr
|
||||
input logic [31:0] dec_i1_immed_d, // DEC data immediate
|
||||
|
||||
input logic [31:0] i0_rs1_bypass_data_d, // DEC bypass data
|
||||
input logic [31:0] i0_rs2_bypass_data_d, // DEC bypass data
|
||||
input logic [31:0] i1_rs1_bypass_data_d, // DEC bypass data
|
||||
input logic [31:0] i1_rs2_bypass_data_d, // DEC bypass data
|
||||
|
||||
input logic [12:1] dec_i0_br_immed_d, // Branch immediate
|
||||
input logic [12:1] dec_i1_br_immed_d, // Branch immediate
|
||||
|
||||
input alu_pkt_t i0_ap, // DEC alu {valid,predecodes}
|
||||
input alu_pkt_t i1_ap, // DEC alu {valid,predecodes}
|
||||
|
||||
input logic dec_i0_alu_decode_d, // Valid to Primary ALU
|
||||
input logic dec_i1_alu_decode_d, // Valid to Primary ALU
|
||||
|
||||
input logic dec_i0_select_pc_d, // PC select to RS1
|
||||
input logic dec_i1_select_pc_d, // PC select to RS1
|
||||
|
||||
input logic [31:1] dec_i0_pc_d, dec_i1_pc_d, // Instruction PC
|
||||
|
||||
input logic dec_i0_rs1_bypass_en_d, // DEC bypass select
|
||||
input logic dec_i0_rs2_bypass_en_d, // DEC bypass select
|
||||
input logic dec_i1_rs1_bypass_en_d, // DEC bypass select
|
||||
input logic dec_i1_rs2_bypass_en_d, // DEC bypass select
|
||||
|
||||
input logic dec_tlu_flush_lower_wb, // Flush divide and secondary ALUs
|
||||
input logic [31:1] dec_tlu_flush_path_wb, // Redirect target
|
||||
|
||||
input logic dec_tlu_i0_valid_e4, // Valid for GHR
|
||||
input logic dec_tlu_i1_valid_e4, // Valid for GHR
|
||||
|
||||
output logic [31:0] exu_i0_result_e1, // Primary ALU result to DEC
|
||||
output logic [31:0] exu_i1_result_e1, // Primary ALU result to DEC
|
||||
output logic [31:1] exu_i0_pc_e1, // Primary PC result to DEC
|
||||
output logic [31:1] exu_i1_pc_e1, // Primary PC result to DEC
|
||||
|
||||
|
||||
output logic [31:0] exu_i0_result_e4, // Secondary ALU result
|
||||
output logic [31:0] exu_i1_result_e4, // Secondary ALU result
|
||||
|
||||
|
||||
output logic exu_i0_flush_final, // I0 flush to DEC
|
||||
output logic exu_i1_flush_final, // I1 flush to DEC
|
||||
|
||||
|
||||
|
||||
input mul_pkt_t mul_p, // DEC {valid, operand signs, low, operand bypass}
|
||||
|
||||
input div_pkt_t div_p, // DEC {valid, unsigned, rem}
|
||||
|
||||
input logic dec_i0_lsu_d, // Bypass control for LSU operand bus
|
||||
input logic dec_i1_lsu_d, // Bypass control for LSU operand bus
|
||||
|
||||
input logic dec_csr_ren_d, // Clear I0 RS1 primary
|
||||
|
||||
output logic [31:0] exu_lsu_rs1_d, // LSU operand
|
||||
output logic [31:0] exu_lsu_rs2_d, // LSU operand
|
||||
|
||||
output logic [31:0] exu_csr_rs1_e1, // RS1 source for a CSR instruction
|
||||
|
||||
output logic exu_flush_final, // Pipe is being flushed this cycle
|
||||
output logic [31:1] exu_flush_path_final, // Target for the oldest flush source
|
||||
|
||||
output logic [31:0] exu_mul_result_e3, // Multiply result
|
||||
|
||||
output logic [31:0] exu_div_result, // Divide result
|
||||
output logic exu_div_finish, // Divide is finished
|
||||
output logic exu_div_stall, // Divide is running
|
||||
output logic [31:1] exu_npc_e4, // Divide NPC
|
||||
|
||||
output logic exu_i0_flush_lower_e4, // to TLU - lower branch flush
|
||||
output logic exu_i1_flush_lower_e4, // to TLU - lower branch flush
|
||||
output logic [31:1] exu_i0_flush_path_e4, // to TLU - lower branch flush path
|
||||
output logic [31:1] exu_i1_flush_path_e4, // to TLU - lower branch flush path
|
||||
|
||||
output predict_pkt_t exu_mp_pkt, // Mispredict branch packet
|
||||
|
||||
output logic [`RV_BHT_GHR_RANGE] exu_mp_eghr, // Mispredict global history
|
||||
|
||||
output logic [1:0] exu_i0_br_hist_e4, // to DEC I0 branch history
|
||||
output logic [1:0] exu_i0_br_bank_e4, // to DEC I0 branch bank
|
||||
output logic exu_i0_br_error_e4, // to DEC I0 branch error
|
||||
output logic exu_i0_br_start_error_e4, // to DEC I0 branch start error
|
||||
output logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] exu_i0_br_index_e4, // to DEC I0 branch index
|
||||
output logic exu_i0_br_valid_e4, // to DEC I0 branch valid
|
||||
output logic exu_i0_br_mp_e4, // to DEC I0 branch mispredict
|
||||
`ifdef RV_BTB_48
|
||||
output logic [1:0] exu_i0_br_way_e4, // to DEC I0 branch way
|
||||
`else
|
||||
output logic exu_i0_br_way_e4, // to DEC I0 branch way
|
||||
`endif
|
||||
output logic exu_i0_br_middle_e4, // to DEC I0 branch middle
|
||||
output logic [`RV_BHT_GHR_RANGE] exu_i0_br_fghr_e4, // to DEC I0 branch fghr
|
||||
output logic exu_i0_br_ret_e4, // to DEC I0 branch return
|
||||
output logic exu_i0_br_call_e4, // to DEC I0 branch call
|
||||
|
||||
output logic [1:0] exu_i1_br_hist_e4, // to DEC I1 branch history
|
||||
output logic [1:0] exu_i1_br_bank_e4, // to DEC I1 branch bank
|
||||
output logic exu_i1_br_error_e4, // to DEC I1 branch error
|
||||
output logic exu_i1_br_start_error_e4, // to DEC I1 branch start error
|
||||
output logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] exu_i1_br_index_e4, // to DEC I1 branch index
|
||||
output logic exu_i1_br_valid_e4, // to DEC I1 branch valid
|
||||
output logic exu_i1_br_mp_e4, // to DEC I1 branch mispredict
|
||||
`ifdef RV_BTB_48
|
||||
output logic [1:0] exu_i1_br_way_e4, // to DEC I1 branch way
|
||||
`else
|
||||
output logic exu_i1_br_way_e4, // to DEC I1 branch way
|
||||
`endif
|
||||
output logic exu_i1_br_middle_e4, // to DEC I1 branch middle
|
||||
output logic [`RV_BHT_GHR_RANGE] exu_i1_br_fghr_e4, // to DEC I1 branch fghr
|
||||
output logic exu_i1_br_ret_e4, // to DEC I1 branch return
|
||||
output logic exu_i1_br_call_e4, // to DEC I1 branch call
|
||||
output logic exu_flush_upper_e2, // flush upper, either i0 or i1
|
||||
|
||||
output rets_pkt_t exu_rets_e1_pkt, // to IFU - I0+I1 {call, return, pc}
|
||||
output rets_pkt_t exu_rets_e4_pkt, // to IFU - I0+I1 {call, return, pc}
|
||||
|
||||
output logic exu_pmu_i0_br_misp, // to PMU - I0 E4 branch mispredict
|
||||
output logic exu_pmu_i0_br_ataken, // to PMU - I0 E4 taken
|
||||
output logic exu_pmu_i0_pc4, // to PMU - I0 E4 PC
|
||||
output logic exu_pmu_i1_br_misp, // to PMU - I1 E4 branch mispredict
|
||||
output logic exu_pmu_i1_br_ataken, // to PMU - I1 E4 taken
|
||||
output logic exu_pmu_i1_pc4 // to PMU - I1 E4 PC
|
||||
|
||||
);
|
||||
|
||||
|
||||
logic [31:0] i0_rs1_d,i0_rs2_d,i1_rs1_d,i1_rs2_d;
|
||||
|
||||
|
||||
|
||||
logic exu_i0_flush_upper_e1;
|
||||
logic [31:1] exu_i0_flush_path_e1;
|
||||
|
||||
logic exu_i1_flush_upper_e1;
|
||||
logic [31:1] exu_i1_flush_path_e1;
|
||||
|
||||
logic [31:0] i0_rs1_final_d;
|
||||
|
||||
logic [31:1] exu_flush_path_e2;
|
||||
logic [31:0] mul_rs1_d, mul_rs2_d;
|
||||
|
||||
logic [31:0] div_rs1_d, div_rs2_d;
|
||||
|
||||
logic i1_valid_e2;
|
||||
logic [31:1] npc_e4;
|
||||
logic [31:1] div_npc;
|
||||
|
||||
logic [31:0] i0_rs1_e1, i0_rs2_e1;
|
||||
logic [31:0] i0_rs1_e2, i0_rs2_e2;
|
||||
logic [31:0] i0_rs1_e3, i0_rs2_e3;
|
||||
logic [12:1] i0_br_immed_e1, i0_br_immed_e2, i0_br_immed_e3;
|
||||
|
||||
logic [31:0] i1_rs1_e1, i1_rs2_e1;
|
||||
logic [31:0] i1_rs1_e2, i1_rs2_e2;
|
||||
logic [31:0] i1_rs1_e3, i1_rs2_e3;
|
||||
|
||||
logic [12:1] i1_br_immed_e1, i1_br_immed_e2, i1_br_immed_e3;
|
||||
|
||||
logic [31:0] i0_rs1_e2_final, i0_rs2_e2_final;
|
||||
logic [31:0] i1_rs1_e2_final, i1_rs2_e2_final;
|
||||
logic [31:0] i0_rs1_e3_final, i0_rs2_e3_final;
|
||||
logic [31:0] i1_rs1_e3_final, i1_rs2_e3_final;
|
||||
logic [31:1] i0_alu_pc_nc, i1_alu_pc_nc;
|
||||
logic [31:1] exu_flush_path_e1;
|
||||
logic exu_i0_flush_upper_e2, exu_i1_flush_upper_e2;
|
||||
logic i1_valid_e3, i1_valid_e4;
|
||||
logic [31:1] pred_correct_npc_e3, pred_correct_npc_e4;
|
||||
logic exu_i0_flush_upper_e3;
|
||||
logic exu_i0_flush_upper_e4;
|
||||
logic i1_pred_correct_upper_e1, i0_pred_correct_upper_e1;
|
||||
logic i1_pred_correct_upper_e2, i0_pred_correct_upper_e2;
|
||||
logic i1_pred_correct_upper_e3, i0_pred_correct_upper_e3;
|
||||
logic i1_pred_correct_upper_e4, i0_pred_correct_upper_e4;
|
||||
logic i1_pred_correct_lower_e4, i0_pred_correct_lower_e4;
|
||||
|
||||
|
||||
logic i1_valid_e4_eff;
|
||||
logic i1_sec_decode_e4, i0_sec_decode_e4;
|
||||
logic i1_pred_correct_e4_eff, i0_pred_correct_e4_eff;
|
||||
logic [31:1] i1_flush_path_e4_eff, i0_flush_path_e4_eff;
|
||||
logic [31:0] csr_rs1_in_d;
|
||||
logic [31:1] i1_flush_path_upper_e2, i0_flush_path_upper_e2;
|
||||
logic [31:1] i1_flush_path_upper_e3, i0_flush_path_upper_e3;
|
||||
logic [31:1] i1_flush_path_upper_e4, i0_flush_path_upper_e4;
|
||||
|
||||
logic div_valid_e1;
|
||||
logic div_finish_early;
|
||||
logic freeze;
|
||||
|
||||
|
||||
alu_pkt_t i0_ap_e1, i0_ap_e2, i0_ap_e3, i0_ap_e4;
|
||||
alu_pkt_t i1_ap_e1, i1_ap_e2, i1_ap_e3, i1_ap_e4;
|
||||
assign freeze = lsu_freeze_dc3;
|
||||
|
||||
assign i0_rs1_d[31:0] = ({32{~dec_i0_rs1_bypass_en_d}} & ((dec_debug_wdata_rs1_d) ? dbg_cmd_wrdata[31:0] : gpr_i0_rs1_d[31:0])) |
|
||||
({32{~dec_i0_rs1_bypass_en_d & dec_i0_select_pc_d}} & { dec_i0_pc_d[31:1], 1'b0}) | // for jal's
|
||||
({32{ dec_i0_rs1_bypass_en_d}} & i0_rs1_bypass_data_d[31:0]);
|
||||
|
||||
|
||||
assign i0_rs1_final_d[31:0] = ({32{~dec_csr_ren_d}} & i0_rs1_d[31:0]);
|
||||
|
||||
assign i0_rs2_d[31:0] = ({32{~dec_i0_rs2_bypass_en_d}} & gpr_i0_rs2_d[31:0]) |
|
||||
({32{~dec_i0_rs2_bypass_en_d}} & dec_i0_immed_d[31:0]) |
|
||||
({32{ dec_i0_rs2_bypass_en_d}} & i0_rs2_bypass_data_d[31:0]);
|
||||
|
||||
assign i1_rs1_d[31:0] = ({32{~dec_i1_rs1_bypass_en_d}} & gpr_i1_rs1_d[31:0]) |
|
||||
({32{~dec_i1_rs1_bypass_en_d & dec_i1_select_pc_d}} & { dec_i1_pc_d[31:1], 1'b0}) | // pc orthogonal with rs1
|
||||
({32{ dec_i1_rs1_bypass_en_d}} & i1_rs1_bypass_data_d[31:0]);
|
||||
|
||||
assign i1_rs2_d[31:0] = ({32{~dec_i1_rs2_bypass_en_d}} & gpr_i1_rs2_d[31:0]) |
|
||||
({32{~dec_i1_rs2_bypass_en_d}} & dec_i1_immed_d[31:0]) |
|
||||
({32{ dec_i1_rs2_bypass_en_d}} & i1_rs2_bypass_data_d[31:0]);
|
||||
|
||||
assign exu_lsu_rs1_d[31:0] = ({32{ ~dec_i0_rs1_bypass_en_d & dec_i0_lsu_d }} & gpr_i0_rs1_d[31:0] ) |
|
||||
({32{ ~dec_i1_rs1_bypass_en_d & ~dec_i0_lsu_d & dec_i1_lsu_d}} & gpr_i1_rs1_d[31:0] ) |
|
||||
({32{ dec_i0_rs1_bypass_en_d & dec_i0_lsu_d }} & i0_rs1_bypass_data_d[31:0]) |
|
||||
({32{ dec_i1_rs1_bypass_en_d & ~dec_i0_lsu_d & dec_i1_lsu_d}} & i1_rs1_bypass_data_d[31:0]);
|
||||
|
||||
assign exu_lsu_rs2_d[31:0] = ({32{ ~dec_i0_rs2_bypass_en_d & dec_i0_lsu_d }} & gpr_i0_rs2_d[31:0] ) |
|
||||
({32{ ~dec_i1_rs2_bypass_en_d & ~dec_i0_lsu_d & dec_i1_lsu_d}} & gpr_i1_rs2_d[31:0] ) |
|
||||
({32{ dec_i0_rs2_bypass_en_d & dec_i0_lsu_d }} & i0_rs2_bypass_data_d[31:0]) |
|
||||
({32{ dec_i1_rs2_bypass_en_d & ~dec_i0_lsu_d & dec_i1_lsu_d}} & i1_rs2_bypass_data_d[31:0]);
|
||||
|
||||
assign mul_rs1_d[31:0] = ({32{ ~dec_i0_rs1_bypass_en_d & dec_i0_mul_d }} & gpr_i0_rs1_d[31:0] ) |
|
||||
({32{ ~dec_i1_rs1_bypass_en_d & ~dec_i0_mul_d & dec_i1_mul_d}} & gpr_i1_rs1_d[31:0] ) |
|
||||
({32{ dec_i0_rs1_bypass_en_d & dec_i0_mul_d }} & i0_rs1_bypass_data_d[31:0]) |
|
||||
({32{ dec_i1_rs1_bypass_en_d & ~dec_i0_mul_d & dec_i1_mul_d}} & i1_rs1_bypass_data_d[31:0]);
|
||||
|
||||
assign mul_rs2_d[31:0] = ({32{ ~dec_i0_rs2_bypass_en_d & dec_i0_mul_d }} & gpr_i0_rs2_d[31:0] ) |
|
||||
({32{ ~dec_i1_rs2_bypass_en_d & ~dec_i0_mul_d & dec_i1_mul_d}} & gpr_i1_rs2_d[31:0] ) |
|
||||
({32{ dec_i0_rs2_bypass_en_d & dec_i0_mul_d }} & i0_rs2_bypass_data_d[31:0]) |
|
||||
({32{ dec_i1_rs2_bypass_en_d & ~dec_i0_mul_d & dec_i1_mul_d}} & i1_rs2_bypass_data_d[31:0]);
|
||||
|
||||
|
||||
|
||||
assign div_rs1_d[31:0] = ({32{ ~dec_i0_rs1_bypass_en_d & dec_i0_div_d }} & gpr_i0_rs1_d[31:0]) |
|
||||
({32{ ~dec_i1_rs1_bypass_en_d & ~dec_i0_div_d & dec_i1_div_d}} & gpr_i1_rs1_d[31:0]) |
|
||||
({32{ dec_i0_rs1_bypass_en_d & dec_i0_div_d }} & i0_rs1_bypass_data_d[31:0]) |
|
||||
({32{ dec_i1_rs1_bypass_en_d & ~dec_i0_div_d & dec_i1_div_d}} & i1_rs1_bypass_data_d[31:0]);
|
||||
|
||||
assign div_rs2_d[31:0] = ({32{ ~dec_i0_rs2_bypass_en_d & dec_i0_div_d }} & gpr_i0_rs2_d[31:0]) |
|
||||
({32{ ~dec_i1_rs2_bypass_en_d & ~dec_i0_div_d & dec_i1_div_d}} & gpr_i1_rs2_d[31:0]) |
|
||||
({32{ dec_i0_rs2_bypass_en_d & dec_i0_div_d }} & i0_rs2_bypass_data_d[31:0]) |
|
||||
({32{ dec_i1_rs2_bypass_en_d & ~dec_i0_div_d & dec_i1_div_d}} & i1_rs2_bypass_data_d[31:0]);
|
||||
|
||||
|
||||
assign csr_rs1_in_d[31:0] = (dec_csr_ren_d) ? i0_rs1_d[31:0] : exu_csr_rs1_e1[31:0];
|
||||
|
||||
logic i0_e1_data_en, i0_e2_data_en, i0_e3_data_en;
|
||||
logic i0_e1_ctl_en, i0_e2_ctl_en, i0_e3_ctl_en, i0_e4_ctl_en;
|
||||
|
||||
assign {i0_e1_data_en, i0_e2_data_en, i0_e3_data_en } = dec_i0_data_en[4:2];
|
||||
assign {i0_e1_ctl_en, i0_e2_ctl_en, i0_e3_ctl_en, i0_e4_ctl_en } = dec_i0_ctl_en[4:1];
|
||||
|
||||
logic i1_e1_data_en, i1_e2_data_en, i1_e3_data_en;
|
||||
logic i1_e1_ctl_en, i1_e2_ctl_en, i1_e3_ctl_en, i1_e4_ctl_en;
|
||||
|
||||
assign {i1_e1_data_en, i1_e2_data_en, i1_e3_data_en} = dec_i1_data_en[4:2];
|
||||
assign {i1_e1_ctl_en, i1_e2_ctl_en, i1_e3_ctl_en, i1_e4_ctl_en} = dec_i1_ctl_en[4:1];
|
||||
|
||||
|
||||
|
||||
|
||||
rvdffe #(32) csr_rs1_ff (.*, .en(i0_e1_data_en), .din(csr_rs1_in_d[31:0]), .dout(exu_csr_rs1_e1[31:0]));
|
||||
|
||||
|
||||
exu_mul_ctl mul_e1 (.*,
|
||||
.clk_override ( clk_override ), // I
|
||||
.freeze ( freeze ), // I
|
||||
.mp ( mul_p ), // I
|
||||
.a ( mul_rs1_d[31:0] ), // I
|
||||
.b ( mul_rs2_d[31:0] ), // I
|
||||
.out ( exu_mul_result_e3[31:0] )); // O
|
||||
|
||||
|
||||
exu_div_ctl div_e1 (.*,
|
||||
.flush_lower ( dec_tlu_flush_lower_wb ), // I
|
||||
.dp ( div_p ), // I
|
||||
.dividend ( div_rs1_d[31:0] ), // I
|
||||
.divisor ( div_rs2_d[31:0] ), // I
|
||||
.valid_ff_e1 ( div_valid_e1 ), // O
|
||||
.div_stall ( exu_div_stall ), // O
|
||||
.finish_early ( div_finish_early ), // O
|
||||
.finish ( exu_div_finish ), // O
|
||||
.out ( exu_div_result[31:0] )); // O
|
||||
|
||||
|
||||
predict_pkt_t i0_predict_newp_d, i1_predict_newp_d;
|
||||
|
||||
always_comb begin
|
||||
i0_predict_newp_d = i0_predict_p_d;
|
||||
i0_predict_newp_d.boffset = dec_i0_pc_d[1]; // from the start of inst
|
||||
|
||||
i0_predict_newp_d.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] = i0_predict_p_d.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO]; // from the end of inst
|
||||
i0_predict_newp_d.bank[1:0] = i0_predict_p_d.bank[1:0];
|
||||
|
||||
i1_predict_newp_d = i1_predict_p_d;
|
||||
i1_predict_newp_d.boffset = dec_i1_pc_d[1];
|
||||
|
||||
i1_predict_newp_d.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] = i1_predict_p_d.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO];
|
||||
i1_predict_newp_d.bank[1:0] = i1_predict_p_d.bank[1:0];
|
||||
|
||||
end
|
||||
|
||||
|
||||
predict_pkt_t i0_predict_p_e1, i0_predict_p_e4;
|
||||
predict_pkt_t i1_predict_p_e1, i1_predict_p_e4;
|
||||
|
||||
assign exu_pmu_i0_br_misp = i0_predict_p_e4.misp & ~exu_div_finish; // qual with divide
|
||||
assign exu_pmu_i0_br_ataken = i0_predict_p_e4.ataken & ~exu_div_finish; // qual with divide
|
||||
assign exu_pmu_i0_pc4 = i0_predict_p_e4.pc4 | exu_div_finish; // divides are always 4B
|
||||
assign exu_pmu_i1_br_misp = i1_predict_p_e4.misp;
|
||||
assign exu_pmu_i1_br_ataken = i1_predict_p_e4.ataken;
|
||||
assign exu_pmu_i1_pc4 = i1_predict_p_e4.pc4;
|
||||
|
||||
|
||||
exu_alu_ctl i0_alu_e1 (.*,
|
||||
.freeze ( freeze ), // I
|
||||
.enable ( i0_e1_ctl_en ), // I
|
||||
.predict_p ( i0_predict_newp_d ), // I
|
||||
.valid ( dec_i0_alu_decode_d ), // I
|
||||
.flush ( exu_flush_final ), // I
|
||||
.a ( i0_rs1_final_d[31:0] ), // I
|
||||
.b ( i0_rs2_d[31:0] ), // I
|
||||
.pc ( dec_i0_pc_d[31:1] ), // I
|
||||
.brimm ( dec_i0_br_immed_d[12:1] ), // I
|
||||
.ap ( i0_ap_e1 ), // I
|
||||
.out ( exu_i0_result_e1[31:0] ), // O
|
||||
.flush_upper ( exu_i0_flush_upper_e1 ), // O : will be 0 if freeze this cycle
|
||||
.flush_path ( exu_i0_flush_path_e1[31:1] ), // O
|
||||
.predict_p_ff ( i0_predict_p_e1 ), // O
|
||||
.pc_ff ( exu_i0_pc_e1[31:1] ), // O
|
||||
.pred_correct ( i0_pred_correct_upper_e1 ) // O
|
||||
);
|
||||
|
||||
|
||||
exu_alu_ctl i1_alu_e1 (.*,
|
||||
.freeze ( freeze ), // I
|
||||
.enable ( i1_e1_ctl_en ), // I
|
||||
.predict_p ( i1_predict_newp_d ), // I
|
||||
.valid ( dec_i1_alu_decode_d ), // I
|
||||
.flush ( exu_flush_final ), // I
|
||||
.a ( i1_rs1_d[31:0] ), // I
|
||||
.b ( i1_rs2_d[31:0] ), // I
|
||||
.pc ( dec_i1_pc_d[31:1] ), // I
|
||||
.brimm ( dec_i1_br_immed_d[12:1] ), // I
|
||||
.ap ( i1_ap_e1 ), // I
|
||||
.out ( exu_i1_result_e1[31:0] ), // O
|
||||
.flush_upper ( exu_i1_flush_upper_e1 ), // O : will be 0 if freeze this cycle
|
||||
.flush_path ( exu_i1_flush_path_e1[31:1] ), // O
|
||||
.predict_p_ff ( i1_predict_p_e1 ), // O
|
||||
.pc_ff ( exu_i1_pc_e1[31:1] ), // O
|
||||
.pred_correct ( i1_pred_correct_upper_e1 ) // O
|
||||
);
|
||||
|
||||
predict_pkt_t i0_pp_e2, i0_pp_e3, i0_pp_e4_in;
|
||||
|
||||
rvdffe #($bits(predict_pkt_t)) i0_pp_e2_ff (.*, .en(i0_e2_ctl_en), .din(i0_predict_p_e1),.dout(i0_pp_e2) );
|
||||
rvdffe #($bits(predict_pkt_t)) i0_pp_e3_ff (.*, .en(i0_e3_ctl_en), .din(i0_pp_e2),.dout(i0_pp_e3) );
|
||||
|
||||
predict_pkt_t i1_pp_e2, i1_pp_e3, i1_pp_e4_in;
|
||||
|
||||
rvdffe #($bits(predict_pkt_t)) i1_pp_e2_ff (.*, .en(i1_e2_ctl_en), .din(i1_predict_p_e1),.dout(i1_pp_e2) );
|
||||
rvdffe #($bits(predict_pkt_t)) i1_pp_e3_ff (.*, .en(i1_e3_ctl_en), .din(i1_pp_e2),.dout(i1_pp_e3) );
|
||||
|
||||
// set the predict_pkt to 0's if freeze, goes to secondary alu's
|
||||
assign i0_pp_e4_in = (freeze) ? '0 : i0_pp_e3;
|
||||
assign i1_pp_e4_in = (freeze) ? '0 : i1_pp_e3;
|
||||
|
||||
rvdffe #($bits(alu_pkt_t)) i0_ap_e1_ff (.*, .en(i0_e1_ctl_en), .din(i0_ap), .dout(i0_ap_e1) );
|
||||
rvdffe #($bits(alu_pkt_t)) i0_ap_e2_ff (.*, .en(i0_e2_ctl_en), .din(i0_ap_e1),.dout(i0_ap_e2) );
|
||||
rvdffe #($bits(alu_pkt_t)) i0_ap_e3_ff (.*, .en(i0_e3_ctl_en), .din(i0_ap_e2),.dout(i0_ap_e3) );
|
||||
rvdffe #($bits(alu_pkt_t)) i0_ap_e4_ff (.*, .en(i0_e4_ctl_en), .din(i0_ap_e3),.dout(i0_ap_e4) );
|
||||
|
||||
|
||||
rvdffe #($bits(alu_pkt_t)) i1_ap_e1_ff (.*, .en(i1_e1_ctl_en), .din(i1_ap), .dout(i1_ap_e1) );
|
||||
rvdffe #($bits(alu_pkt_t)) i1_ap_e2_ff (.*, .en(i1_e2_ctl_en), .din(i1_ap_e1),.dout(i1_ap_e2) );
|
||||
rvdffe #($bits(alu_pkt_t)) i1_ap_e3_ff (.*, .en(i1_e3_ctl_en), .din(i1_ap_e2),.dout(i1_ap_e3) );
|
||||
rvdffe #($bits(alu_pkt_t)) i1_ap_e4_ff (.*, .en(i1_e4_ctl_en), .din(i1_ap_e3),.dout(i1_ap_e4) );
|
||||
|
||||
assign exu_rets_e1_pkt.pc0_call = i0_predict_p_e1.pcall & i0_predict_p_e1.valid & ~i0_predict_p_e1.br_error;
|
||||
assign exu_rets_e1_pkt.pc1_call = i1_predict_p_e1.pcall & i1_predict_p_e1.valid & ~i1_predict_p_e1.br_error;
|
||||
assign exu_rets_e1_pkt.pc0_ret = i0_predict_p_e1.pret & i0_predict_p_e1.valid & ~i0_predict_p_e1.br_error;
|
||||
assign exu_rets_e1_pkt.pc1_ret = i1_predict_p_e1.pret & i1_predict_p_e1.valid & ~i1_predict_p_e1.br_error;
|
||||
assign exu_rets_e1_pkt.pc0_pc4 = i0_predict_p_e1.pc4;
|
||||
assign exu_rets_e1_pkt.pc1_pc4 = i1_predict_p_e1.pc4;
|
||||
|
||||
|
||||
|
||||
rvdffe #(76) i0_src_e1_ff (.*,
|
||||
.en(i0_e1_data_en),
|
||||
.din( {i0_rs1_d[31:0], i0_rs2_d[31:0], dec_i0_br_immed_d[12:1]}),
|
||||
.dout({i0_rs1_e1[31:0], i0_rs2_e1[31:0], i0_br_immed_e1[12:1]})
|
||||
);
|
||||
|
||||
rvdffe #(76) i0_src_e2_ff (.*,
|
||||
.en(i0_e2_data_en),
|
||||
.din( {i0_rs1_e1[31:0], i0_rs2_e1[31:0], i0_br_immed_e1[12:1]}),
|
||||
.dout({i0_rs1_e2[31:0], i0_rs2_e2[31:0], i0_br_immed_e2[12:1]})
|
||||
);
|
||||
|
||||
rvdffe #(76) i0_src_e3_ff (.*,
|
||||
.en(i0_e3_data_en),
|
||||
.din( {i0_rs1_e2_final[31:0], i0_rs2_e2_final[31:0], i0_br_immed_e2[12:1]}),
|
||||
.dout({i0_rs1_e3[31:0], i0_rs2_e3[31:0], i0_br_immed_e3[12:1]})
|
||||
);
|
||||
|
||||
|
||||
|
||||
rvdffe #(76) i1_src_e1_ff (.*,
|
||||
.en(i1_e1_data_en),
|
||||
.din( {i1_rs1_d[31:0], i1_rs2_d[31:0], dec_i1_br_immed_d[12:1]}),
|
||||
.dout({i1_rs1_e1[31:0], i1_rs2_e1[31:0], i1_br_immed_e1[12:1]})
|
||||
);
|
||||
|
||||
rvdffe #(76) i1_src_e2_ff (.*,
|
||||
.en(i1_e2_data_en),
|
||||
.din( {i1_rs1_e1[31:0], i1_rs2_e1[31:0], i1_br_immed_e1[12:1]}),
|
||||
.dout({i1_rs1_e2[31:0], i1_rs2_e2[31:0], i1_br_immed_e2[12:1]})
|
||||
);
|
||||
|
||||
rvdffe #(76) i1_src_e3_ff (.*,
|
||||
.en(i1_e3_data_en),
|
||||
.din( {i1_rs1_e2_final[31:0], i1_rs2_e2_final[31:0], i1_br_immed_e2[12:1]}),
|
||||
.dout({i1_rs1_e3[31:0], i1_rs2_e3[31:0], i1_br_immed_e3[12:1]})
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
assign i0_rs1_e2_final[31:0] = (dec_i0_rs1_bypass_en_e2) ? i0_rs1_bypass_data_e2[31:0] : i0_rs1_e2[31:0];
|
||||
assign i0_rs2_e2_final[31:0] = (dec_i0_rs2_bypass_en_e2) ? i0_rs2_bypass_data_e2[31:0] : i0_rs2_e2[31:0];
|
||||
assign i1_rs1_e2_final[31:0] = (dec_i1_rs1_bypass_en_e2) ? i1_rs1_bypass_data_e2[31:0] : i1_rs1_e2[31:0];
|
||||
assign i1_rs2_e2_final[31:0] = (dec_i1_rs2_bypass_en_e2) ? i1_rs2_bypass_data_e2[31:0] : i1_rs2_e2[31:0];
|
||||
|
||||
|
||||
assign i0_rs1_e3_final[31:0] = (dec_i0_rs1_bypass_en_e3) ? i0_rs1_bypass_data_e3[31:0] : i0_rs1_e3[31:0];
|
||||
assign i0_rs2_e3_final[31:0] = (dec_i0_rs2_bypass_en_e3) ? i0_rs2_bypass_data_e3[31:0] : i0_rs2_e3[31:0];
|
||||
assign i1_rs1_e3_final[31:0] = (dec_i1_rs1_bypass_en_e3) ? i1_rs1_bypass_data_e3[31:0] : i1_rs1_e3[31:0];
|
||||
assign i1_rs2_e3_final[31:0] = (dec_i1_rs2_bypass_en_e3) ? i1_rs2_bypass_data_e3[31:0] : i1_rs2_e3[31:0];
|
||||
|
||||
// E1 GHR
|
||||
// fill in the ptaken for secondary branches.
|
||||
|
||||
logic [`RV_BHT_GHR_RANGE] ghr_e4_ns, ghr_e4;
|
||||
logic [`RV_BHT_GHR_RANGE] ghr_e1_ns, ghr_e1;
|
||||
logic i0_taken_e1, i1_taken_e1, dec_i0_alu_decode_e1, dec_i1_alu_decode_e1, i0_valid_e1, i1_valid_e1, i0_ataken_e1, i1_ataken_e1, exu_flush_final_f;
|
||||
assign i0_valid_e1 = ~exu_flush_final & ~exu_flush_final_f & (i0_predict_p_e1.valid | i0_predict_p_e1.misp);
|
||||
assign i1_valid_e1 = ~exu_flush_final & ~exu_flush_final_f & (i1_predict_p_e1.valid | i1_predict_p_e1.misp) & ~exu_i0_flush_upper_e1;
|
||||
assign i0_ataken_e1 = i0_predict_p_e1.ataken;
|
||||
assign i1_ataken_e1 = i1_predict_p_e1.ataken;
|
||||
|
||||
assign i0_taken_e1 = (i0_ataken_e1 & dec_i0_alu_decode_e1) | (i0_predict_p_e1.hist[1] & ~dec_i0_alu_decode_e1);
|
||||
assign i1_taken_e1= (i1_ataken_e1 & dec_i1_alu_decode_e1) | (i1_predict_p_e1.hist[1] & ~dec_i1_alu_decode_e1);
|
||||
|
||||
assign ghr_e1_ns[`RV_BHT_GHR_RANGE] = ( ({`RV_BHT_GHR_SIZE{~dec_tlu_flush_lower_wb & i0_valid_e1 & (i0_predict_p_e1.misp | ~i1_valid_e1)}} & {ghr_e1[`RV_BHT_GHR_SIZE-2:0], i0_taken_e1}) |
|
||||
`ifdef RV_BHT_GHR_SIZE_2
|
||||
({`RV_BHT_GHR_SIZE{~dec_tlu_flush_lower_wb & i0_valid_e1 & ~i0_predict_p_e1.misp & i1_valid_e1}} & { i0_taken_e1, i1_taken_e1}) |
|
||||
`else
|
||||
({`RV_BHT_GHR_SIZE{~dec_tlu_flush_lower_wb & i0_valid_e1 & ~i0_predict_p_e1.misp & i1_valid_e1}} & {ghr_e1[`RV_BHT_GHR_SIZE-3:0], i0_taken_e1, i1_taken_e1}) |
|
||||
`endif
|
||||
({`RV_BHT_GHR_SIZE{~dec_tlu_flush_lower_wb & ~i0_valid_e1 & ~i0_predict_p_e1.br_error & i1_valid_e1}} & {ghr_e1[`RV_BHT_GHR_SIZE-2:0], i1_taken_e1}) |
|
||||
({`RV_BHT_GHR_SIZE{dec_tlu_flush_lower_wb}} & ghr_e4[`RV_BHT_GHR_RANGE]) |
|
||||
({`RV_BHT_GHR_SIZE{~dec_tlu_flush_lower_wb & ~i0_valid_e1 & ~i1_valid_e1}} & ghr_e1[`RV_BHT_GHR_RANGE]) );
|
||||
|
||||
rvdffs #(`RV_BHT_GHR_SIZE) e1ghrff (.*, .clk(active_clk), .en(~freeze), .din({ghr_e1_ns[`RV_BHT_GHR_RANGE]}), .dout({ghr_e1[`RV_BHT_GHR_RANGE]}));
|
||||
rvdffs #(2) e1ghrdecff (.*, .clk(active_clk), .en(~freeze), .din({dec_i0_alu_decode_d, dec_i1_alu_decode_d}), .dout({dec_i0_alu_decode_e1, dec_i1_alu_decode_e1}));
|
||||
|
||||
// E4 GHR
|
||||
// the ataken is filled in by e1 stage if e1 stage executes the branch, otherwise by e4 stage.
|
||||
logic i0_valid_e4, i1_pred_valid_e4;
|
||||
assign i0_valid_e4 = dec_tlu_i0_valid_e4 & ((i0_predict_p_e4.valid) | i0_predict_p_e4.misp);
|
||||
assign i1_pred_valid_e4 = dec_tlu_i1_valid_e4 & ((i1_predict_p_e4.valid) | i1_predict_p_e4.misp) & ~exu_i0_flush_upper_e4;
|
||||
assign ghr_e4_ns[`RV_BHT_GHR_RANGE] = ( ({`RV_BHT_GHR_SIZE{i0_valid_e4 & (i0_predict_p_e4.misp | ~i1_pred_valid_e4)}} & {ghr_e4[`RV_BHT_GHR_SIZE-2:0], i0_predict_p_e4.ataken}) |
|
||||
`ifdef RV_BHT_GHR_SIZE_2
|
||||
({`RV_BHT_GHR_SIZE{i0_valid_e4 & ~i0_predict_p_e4.misp & i1_pred_valid_e4}} & { i0_predict_p_e4.ataken, i1_predict_p_e4.ataken}) |
|
||||
`else
|
||||
({`RV_BHT_GHR_SIZE{i0_valid_e4 & ~i0_predict_p_e4.misp & i1_pred_valid_e4}} & {ghr_e4[`RV_BHT_GHR_SIZE-3:0], i0_predict_p_e4.ataken, i1_predict_p_e4.ataken}) |
|
||||
`endif
|
||||
({`RV_BHT_GHR_SIZE{~i0_valid_e4 & ~i0_predict_p_e4.br_error & i1_pred_valid_e4}} & {ghr_e4[`RV_BHT_GHR_SIZE-2:0], i1_predict_p_e4.ataken}) |
|
||||
({`RV_BHT_GHR_SIZE{~i0_valid_e4 & ~i1_pred_valid_e4}} & ghr_e4[`RV_BHT_GHR_RANGE]) );
|
||||
|
||||
rvdff #(`RV_BHT_GHR_SIZE) e4ghrff (.*, .clk(active_clk), .din({ghr_e4_ns[`RV_BHT_GHR_RANGE]}),
|
||||
.dout({ghr_e4[`RV_BHT_GHR_RANGE]}));
|
||||
rvdff #(1) e4ghrflushff (.*, .clk(active_clk), .din({exu_flush_final}),
|
||||
.dout({exu_flush_final_f}));
|
||||
|
||||
// RV_NO_SECONDARY_ALU {{
|
||||
`ifdef RV_NO_SECONDARY_ALU
|
||||
|
||||
rvdffe #($bits(predict_pkt_t)) i0_pp_e4_ff (.*, .en(i0_e4_ctl_en), .din(i0_pp_e4_in),.dout(i0_predict_p_e4) );
|
||||
rvdffe #($bits(predict_pkt_t)) i1_pp_e4_ff (.*, .en(i1_e4_ctl_en), .din(i1_pp_e4_in),.dout(i1_predict_p_e4) );
|
||||
|
||||
assign exu_i0_result_e4[31:0] = '0;
|
||||
assign exu_i0_flush_lower_e4 = '0;
|
||||
assign exu_i0_flush_path_e4[31:1] = '0;
|
||||
assign i0_alu_pc_nc[31:1] = '0;
|
||||
assign i0_pred_correct_lower_e4 = '0;
|
||||
|
||||
assign exu_i1_result_e4[31:0] = '0;
|
||||
assign exu_i1_flush_lower_e4 = '0;
|
||||
assign exu_i1_flush_path_e4[31:1] = '0;
|
||||
assign i1_alu_pc_nc[31:1] = '0;
|
||||
assign i1_pred_correct_lower_e4 = '0;
|
||||
|
||||
`else
|
||||
|
||||
exu_alu_ctl i0_alu_e4 (.*,
|
||||
.freeze ( 1'b0 ), // I
|
||||
.enable ( i0_e4_ctl_en ), // I
|
||||
.predict_p ( i0_pp_e4_in ), // I
|
||||
.valid ( dec_i0_sec_decode_e3 ), // I
|
||||
.flush ( dec_tlu_flush_lower_wb ), // I
|
||||
.a ( i0_rs1_e3_final[31:0] ), // I
|
||||
.b ( i0_rs2_e3_final[31:0] ), // I
|
||||
.pc ( dec_i0_pc_e3[31:1] ), // I
|
||||
.brimm ( i0_br_immed_e3[12:1] ), // I
|
||||
.ap ( i0_ap_e4 ), // I
|
||||
.out ( exu_i0_result_e4[31:0] ), // O
|
||||
.flush_upper ( exu_i0_flush_lower_e4 ), // O
|
||||
.flush_path ( exu_i0_flush_path_e4[31:1] ), // O
|
||||
.predict_p_ff ( i0_predict_p_e4 ), // O
|
||||
.pc_ff ( i0_alu_pc_nc[31:1] ), // O
|
||||
.pred_correct ( i0_pred_correct_lower_e4 ) // O
|
||||
);
|
||||
|
||||
|
||||
exu_alu_ctl i1_alu_e4 (.*,
|
||||
.freeze ( 1'b0 ), // I
|
||||
.enable ( i1_e4_ctl_en ), // I
|
||||
.predict_p ( i1_pp_e4_in ), // I
|
||||
.valid ( dec_i1_sec_decode_e3 ), // I
|
||||
.flush ( dec_tlu_flush_lower_wb ), // I
|
||||
.a ( i1_rs1_e3_final[31:0] ), // I
|
||||
.b ( i1_rs2_e3_final[31:0] ), // I
|
||||
.pc ( dec_i1_pc_e3[31:1] ), // I
|
||||
.brimm ( i1_br_immed_e3[12:1] ), // I
|
||||
.ap ( i1_ap_e4 ), // I
|
||||
.out ( exu_i1_result_e4[31:0] ), // O
|
||||
.flush_upper ( exu_i1_flush_lower_e4 ), // O
|
||||
.flush_path ( exu_i1_flush_path_e4[31:1] ), // O
|
||||
.predict_p_ff ( i1_predict_p_e4 ), // O
|
||||
.pc_ff ( i1_alu_pc_nc[31:1] ), // O
|
||||
.pred_correct ( i1_pred_correct_lower_e4 ) // O
|
||||
);
|
||||
|
||||
`endif // RV_NO_SECONDARY_ALU }}
|
||||
|
||||
|
||||
assign exu_i0_br_hist_e4[1:0] = i0_predict_p_e4.hist[1:0];
|
||||
assign exu_i0_br_bank_e4[1:0] = i0_predict_p_e4.bank[1:0];
|
||||
assign exu_i0_br_error_e4 = i0_predict_p_e4.br_error;
|
||||
assign exu_i0_br_fghr_e4[`RV_BHT_GHR_RANGE] = i0_predict_p_e4.fghr[`RV_BHT_GHR_RANGE];
|
||||
assign exu_i0_br_middle_e4 = i0_predict_p_e4.pc4 ^ i0_predict_p_e4.boffset;
|
||||
assign exu_i0_br_start_error_e4 = i0_predict_p_e4.br_start_error;
|
||||
assign exu_i0_br_index_e4[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] = i0_predict_p_e4.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO];
|
||||
|
||||
assign exu_i0_br_valid_e4 = i0_predict_p_e4.valid;
|
||||
assign exu_i0_br_mp_e4 = i0_predict_p_e4.misp; // needed to squash i1 error
|
||||
assign exu_i0_br_ret_e4 = i0_predict_p_e4.pret;
|
||||
assign exu_i0_br_call_e4 = i0_predict_p_e4.pcall;
|
||||
assign exu_i0_br_way_e4 = i0_predict_p_e4.way;
|
||||
|
||||
assign exu_i1_br_hist_e4[1:0] = i1_predict_p_e4.hist[1:0];
|
||||
assign exu_i1_br_bank_e4[1:0] = i1_predict_p_e4.bank[1:0];
|
||||
assign exu_i1_br_fghr_e4[`RV_BHT_GHR_RANGE] = i1_predict_p_e4.fghr[`RV_BHT_GHR_RANGE];
|
||||
assign exu_i1_br_middle_e4 = i1_predict_p_e4.pc4 ^ i1_predict_p_e4.boffset;
|
||||
assign exu_i1_br_error_e4 = i1_predict_p_e4.br_error;
|
||||
assign exu_i1_br_index_e4[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] = i1_predict_p_e4.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO];
|
||||
|
||||
assign exu_i1_br_start_error_e4 = i1_predict_p_e4.br_start_error;
|
||||
assign exu_i1_br_valid_e4 = i1_predict_p_e4.valid;
|
||||
assign exu_i1_br_mp_e4 = i1_predict_p_e4.misp;
|
||||
assign exu_i1_br_way_e4 = i1_predict_p_e4.way;
|
||||
|
||||
assign exu_i1_br_ret_e4 = i1_predict_p_e4.pret;
|
||||
assign exu_i1_br_call_e4 = i1_predict_p_e4.pcall;
|
||||
|
||||
assign exu_rets_e4_pkt.pc0_call = i0_predict_p_e4.pcall & i0_predict_p_e4.valid & ~i0_predict_p_e4.br_error;
|
||||
assign exu_rets_e4_pkt.pc1_call = i1_predict_p_e4.pcall & i1_predict_p_e4.valid & ~i1_predict_p_e4.br_error;
|
||||
assign exu_rets_e4_pkt.pc0_ret = i0_predict_p_e4.pret & i0_predict_p_e4.valid & ~i0_predict_p_e4.br_error;
|
||||
assign exu_rets_e4_pkt.pc1_ret = i1_predict_p_e4.pret & i1_predict_p_e4.valid & ~i1_predict_p_e4.br_error;
|
||||
assign exu_rets_e4_pkt.pc0_pc4 = i0_predict_p_e4.pc4;
|
||||
assign exu_rets_e4_pkt.pc1_pc4 = i1_predict_p_e4.pc4;
|
||||
|
||||
predict_pkt_t final_predict_mp, final_predict_mp_ff;
|
||||
|
||||
logic fp_enable, fp_enable_ff;
|
||||
|
||||
assign fp_enable = exu_i0_flush_lower_e4 | exu_i1_flush_lower_e4 |
|
||||
exu_i0_flush_upper_e1 | exu_i1_flush_upper_e1;
|
||||
|
||||
rvdff #(1) final_predict_ff (.*, .clk(active_clk), .din(fp_enable), .dout(fp_enable_ff));
|
||||
|
||||
|
||||
// flush_upper_e1's below take freeze into account
|
||||
assign final_predict_mp = (exu_i0_flush_lower_e4) ? i0_predict_p_e4 :
|
||||
(exu_i1_flush_lower_e4) ? i1_predict_p_e4 :
|
||||
(exu_i0_flush_upper_e1) ? i0_predict_p_e1 :
|
||||
(exu_i1_flush_upper_e1) ? i1_predict_p_e1 : '0;
|
||||
|
||||
rvdffe #($bits(predict_pkt_t)) predict_mp_ff (.*, .en(fp_enable | fp_enable_ff), .din(final_predict_mp), .dout(final_predict_mp_ff));
|
||||
|
||||
logic [`RV_BHT_GHR_RANGE] final_eghr, after_flush_eghr;
|
||||
assign final_eghr[`RV_BHT_GHR_RANGE] = ((exu_i0_flush_upper_e1 | exu_i1_flush_upper_e1) & ~dec_tlu_flush_lower_wb & ~exu_i0_flush_lower_e4 & ~exu_i1_flush_lower_e4 ) ? ghr_e1[`RV_BHT_GHR_RANGE] : ghr_e4[`RV_BHT_GHR_RANGE];
|
||||
|
||||
assign after_flush_eghr[`RV_BHT_GHR_RANGE] = ((exu_i0_flush_upper_e2 | exu_i1_flush_upper_e2) & ~dec_tlu_flush_lower_wb) ? ghr_e1[`RV_BHT_GHR_RANGE] : ghr_e4[`RV_BHT_GHR_RANGE];
|
||||
|
||||
|
||||
assign exu_mp_pkt.way = final_predict_mp_ff.way;
|
||||
assign exu_mp_pkt.misp = final_predict_mp_ff.misp;
|
||||
assign exu_mp_pkt.pcall = final_predict_mp_ff.pcall;
|
||||
assign exu_mp_pkt.pja = final_predict_mp_ff.pja;
|
||||
assign exu_mp_pkt.pret = final_predict_mp_ff.pret;
|
||||
assign exu_mp_pkt.ataken = final_predict_mp_ff.ataken;
|
||||
assign exu_mp_pkt.boffset = final_predict_mp_ff.boffset;
|
||||
assign exu_mp_pkt.pc4 = final_predict_mp_ff.pc4;
|
||||
assign exu_mp_pkt.hist[1:0] = final_predict_mp_ff.hist[1:0];
|
||||
assign exu_mp_pkt.toffset[11:0] = final_predict_mp_ff.toffset[11:0];
|
||||
assign exu_mp_pkt.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] = final_predict_mp_ff.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO];
|
||||
assign exu_mp_pkt.bank[1:0] = final_predict_mp_ff.bank[1:0];
|
||||
assign exu_mp_pkt.btag[`RV_BTB_BTAG_SIZE-1:0] = final_predict_mp_ff.btag[`RV_BTB_BTAG_SIZE-1:0];
|
||||
assign exu_mp_pkt.fghr[`RV_BHT_GHR_RANGE] = after_flush_eghr[`RV_BHT_GHR_RANGE]; // fghr repair value
|
||||
|
||||
assign exu_mp_eghr[`RV_BHT_GHR_RANGE] = final_predict_mp_ff.fghr[`RV_BHT_GHR_RANGE]; // mp ghr for bht write
|
||||
|
||||
|
||||
|
||||
rvdffe #(32) i0_upper_flush_e2_ff (.*,
|
||||
.en(i0_e2_ctl_en),
|
||||
.din({
|
||||
exu_i0_flush_path_e1[31:1],
|
||||
exu_i0_flush_upper_e1}),
|
||||
|
||||
.dout({
|
||||
i0_flush_path_upper_e2[31:1],
|
||||
exu_i0_flush_upper_e2})
|
||||
);
|
||||
|
||||
rvdffe #(33) i1_upper_flush_e2_ff (.*,
|
||||
.en(i1_e2_ctl_en),
|
||||
.din({dec_i1_valid_e1,
|
||||
exu_i1_flush_path_e1[31:1],
|
||||
exu_i1_flush_upper_e1}),
|
||||
.dout({i1_valid_e2,
|
||||
i1_flush_path_upper_e2[31:1],
|
||||
exu_i1_flush_upper_e2})
|
||||
);
|
||||
|
||||
assign exu_flush_path_e2[31:1] = (exu_i0_flush_upper_e2) ? i0_flush_path_upper_e2[31:1] : i1_flush_path_upper_e2[31:1];
|
||||
|
||||
assign exu_i0_flush_final = dec_tlu_flush_lower_wb | (exu_i0_flush_upper_e2 & ~freeze);
|
||||
|
||||
assign exu_i1_flush_final = dec_tlu_flush_lower_wb | (exu_i1_flush_upper_e2 & ~freeze);
|
||||
|
||||
assign exu_flush_upper_e2 = (exu_i0_flush_upper_e2 | exu_i1_flush_upper_e2) & ~freeze;
|
||||
|
||||
assign exu_flush_final = dec_tlu_flush_lower_wb | exu_flush_upper_e2;
|
||||
|
||||
assign exu_flush_path_final[31:1] = (dec_tlu_flush_lower_wb) ? dec_tlu_flush_path_wb[31:1] : exu_flush_path_e2[31:1];
|
||||
|
||||
|
||||
rvdffe #(63) i0_upper_flush_e3_ff (.*,
|
||||
.en(i0_e3_ctl_en),
|
||||
.din({i0_flush_path_upper_e2[31:1],
|
||||
pred_correct_npc_e2[31:1],
|
||||
exu_i0_flush_upper_e2}),
|
||||
.dout({
|
||||
i0_flush_path_upper_e3[31:1],
|
||||
pred_correct_npc_e3[31:1],
|
||||
exu_i0_flush_upper_e3})
|
||||
);
|
||||
|
||||
rvdffe #(32) i1_upper_flush_e3_ff (.*,
|
||||
.en(i1_e3_ctl_en),
|
||||
.din({i1_valid_e2,
|
||||
i1_flush_path_upper_e2[31:1]
|
||||
}),
|
||||
.dout({i1_valid_e3,
|
||||
i1_flush_path_upper_e3[31:1]})
|
||||
);
|
||||
|
||||
rvdffe #(63) i0_upper_flush_e4_ff (.*,
|
||||
.en(i0_e4_ctl_en),
|
||||
.din({
|
||||
i0_flush_path_upper_e3[31:1],
|
||||
pred_correct_npc_e3[31:1],
|
||||
exu_i0_flush_upper_e3 & ~freeze}),
|
||||
.dout({
|
||||
i0_flush_path_upper_e4[31:1],
|
||||
pred_correct_npc_e4[31:1],
|
||||
exu_i0_flush_upper_e4})
|
||||
);
|
||||
|
||||
rvdffe #(32) i1_upper_flush_e4_ff (.*,
|
||||
.en(i1_e4_ctl_en),
|
||||
.din({i1_valid_e3 & ~freeze,
|
||||
i1_flush_path_upper_e3[31:1]}),
|
||||
.dout({i1_valid_e4,
|
||||
i1_flush_path_upper_e4[31:1]})
|
||||
);
|
||||
|
||||
|
||||
// npc logic for commit
|
||||
|
||||
rvdffs #(2) pred_correct_upper_e2_ff (.*,
|
||||
.clk(active_clk),
|
||||
.en(~freeze),
|
||||
.din({i1_pred_correct_upper_e1,i0_pred_correct_upper_e1}),
|
||||
.dout({i1_pred_correct_upper_e2,i0_pred_correct_upper_e2})
|
||||
);
|
||||
|
||||
rvdffs #(2) pred_correct_upper_e3_ff (.*,
|
||||
.clk(active_clk),
|
||||
.en(~freeze),
|
||||
.din({i1_pred_correct_upper_e2,i0_pred_correct_upper_e2}),
|
||||
.dout({i1_pred_correct_upper_e3,i0_pred_correct_upper_e3})
|
||||
);
|
||||
|
||||
rvdff #(2) pred_correct_upper_e4_ff (.*,
|
||||
.clk(active_clk),
|
||||
.din({i1_pred_correct_upper_e3,i0_pred_correct_upper_e3}),
|
||||
.dout({i1_pred_correct_upper_e4,i0_pred_correct_upper_e4})
|
||||
);
|
||||
|
||||
rvdff #(2) sec_decode_e4_ff (.*,
|
||||
.clk(active_clk),
|
||||
.din({dec_i0_sec_decode_e3,dec_i1_sec_decode_e3}),
|
||||
.dout({i0_sec_decode_e4,i1_sec_decode_e4})
|
||||
);
|
||||
|
||||
|
||||
|
||||
assign i1_valid_e4_eff = i1_valid_e4 & ~((i0_sec_decode_e4) ? exu_i0_flush_lower_e4 : exu_i0_flush_upper_e4);
|
||||
|
||||
assign i1_pred_correct_e4_eff = (i1_sec_decode_e4) ? i1_pred_correct_lower_e4 : i1_pred_correct_upper_e4;
|
||||
assign i0_pred_correct_e4_eff = (i0_sec_decode_e4) ? i0_pred_correct_lower_e4 : i0_pred_correct_upper_e4;
|
||||
|
||||
assign i1_flush_path_e4_eff[31:1] = (i1_sec_decode_e4) ? exu_i1_flush_path_e4[31:1] : i1_flush_path_upper_e4[31:1];
|
||||
assign i0_flush_path_e4_eff[31:1] = (i0_sec_decode_e4) ? exu_i0_flush_path_e4[31:1] : i0_flush_path_upper_e4[31:1];
|
||||
|
||||
|
||||
assign npc_e4[31:1] = (i1_valid_e4_eff) ? ((i1_pred_correct_e4_eff) ? pred_correct_npc_e4[31:1] : i1_flush_path_e4_eff[31:1]) :
|
||||
((i0_pred_correct_e4_eff) ? pred_correct_npc_e4[31:1] : i0_flush_path_e4_eff[31:1]);
|
||||
|
||||
|
||||
assign exu_npc_e4[31:1] = (div_finish_early) ? exu_i0_flush_path_e1[31:1] :
|
||||
(exu_div_finish) ? div_npc[31:1] :
|
||||
npc_e4[31:1];
|
||||
|
||||
// remember the npc of the divide
|
||||
rvdffe #(31) npc_any_ff (.*, .en(div_valid_e1), .din(exu_i0_flush_path_e1[31:1]), .dout(div_npc[31:1]));
|
||||
|
||||
|
||||
endmodule // exu
|
|
@ -0,0 +1,275 @@
|
|||
// 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.
|
||||
|
||||
|
||||
module exu_alu_ctl
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk, // Top level clock
|
||||
input logic active_clk, // Level 1 free clock
|
||||
input logic rst_l, // Reset
|
||||
input logic scan_mode, // Scan control
|
||||
|
||||
input predict_pkt_t predict_p, // Predicted branch structure
|
||||
|
||||
input logic freeze, // Clock enable for valid
|
||||
|
||||
input logic [31:0] a, // A operand
|
||||
input logic [31:0] b, // B operand
|
||||
input logic [31:1] pc, // for pc=pc+2,4 calculations
|
||||
|
||||
input logic valid, // Valid
|
||||
input logic flush, // Flush pipeline
|
||||
|
||||
input logic [12:1] brimm, // Branch offset
|
||||
|
||||
input alu_pkt_t ap, // {valid,predecodes}
|
||||
|
||||
input logic enable, // Clock enable
|
||||
|
||||
|
||||
output logic [31:0] out, // final result
|
||||
|
||||
output logic flush_upper, // Branch flush
|
||||
output logic [31:1] flush_path, // Branch flush PC
|
||||
|
||||
output logic [31:1] pc_ff, // flopped PC
|
||||
|
||||
output logic pred_correct, // NPC control
|
||||
output predict_pkt_t predict_p_ff // Predicted branch structure
|
||||
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
logic [31:0] aout,bm;
|
||||
logic cout,ov,neg;
|
||||
|
||||
logic [3:1] logic_sel;
|
||||
|
||||
logic [31:0] lout;
|
||||
logic [31:0] sout;
|
||||
logic sel_logic,sel_shift,sel_adder;
|
||||
|
||||
logic slt_one;
|
||||
|
||||
logic actual_taken;
|
||||
|
||||
logic signed [31:0] a_ff;
|
||||
|
||||
logic [31:0] b_ff;
|
||||
|
||||
logic [12:1] brimm_ff;
|
||||
|
||||
logic [31:1] pcout;
|
||||
|
||||
logic valid_ff;
|
||||
|
||||
logic [31:0] ashift;
|
||||
logic cond_mispredict;
|
||||
logic target_mispredict;
|
||||
|
||||
logic eq, ne, lt, ge;
|
||||
|
||||
|
||||
rvdffs #(1) validff (.*, .clk(active_clk), .en(~freeze), .din(valid & ~flush), .dout(valid_ff));
|
||||
|
||||
rvdffe #(32) aff (.*, .en(enable & valid), .din(a[31:0]), .dout(a_ff[31:0]));
|
||||
|
||||
rvdffe #(32) bff (.*, .en(enable & valid), .din(b[31:0]), .dout(b_ff[31:0]));
|
||||
|
||||
// any PC is run through here - doesn't have to be alu
|
||||
rvdffe #(31) pcff (.*, .en(enable), .din(pc[31:1]), .dout(pc_ff[31:1]));
|
||||
|
||||
rvdffe #(12) brimmff (.*, .en(enable), .din(brimm[12:1]), .dout(brimm_ff[12:1]));
|
||||
|
||||
predict_pkt_t pp_ff;
|
||||
|
||||
rvdffe #($bits(predict_pkt_t)) predictpacketff (.*,
|
||||
.en(enable),
|
||||
.din(predict_p),
|
||||
.dout(pp_ff)
|
||||
);
|
||||
|
||||
|
||||
// immediates are just muxed into rs2
|
||||
|
||||
// add => add=1;
|
||||
// sub => add=1; sub=1;
|
||||
|
||||
// and => lctl=3
|
||||
// or => lctl=2
|
||||
// xor => lctl=1
|
||||
|
||||
// sll => sctl=3
|
||||
// srl => sctl=2
|
||||
// sra => sctl=1
|
||||
|
||||
// slt => slt
|
||||
|
||||
// lui => lctl=2; or x0, imm20 previously << 12
|
||||
// auipc => add; add pc, imm20 previously << 12
|
||||
|
||||
// beq => bctl=4; add; add x0, pc, sext(offset[12:1])
|
||||
// bne => bctl=3; add; add x0, pc, sext(offset[12:1])
|
||||
// blt => bctl=2; add; add x0, pc, sext(offset[12:1])
|
||||
// bge => bctl=1; add; add x0, pc, sext(offset[12:1])
|
||||
|
||||
// jal => rs1=pc {pc[31:1],1'b0}, rs2=sext(offset20:1]); rd=pc+[2,4]
|
||||
// jalr => rs1=rs1, rs2=sext(offset20:1]); rd=pc+[2,4]
|
||||
|
||||
|
||||
assign bm[31:0] = ( ap.sub ) ? ~b_ff[31:0] : b_ff[31:0];
|
||||
|
||||
|
||||
assign {cout, aout[31:0]} = {1'b0, a_ff[31:0]} + {1'b0, bm[31:0]} + {32'b0, ap.sub};
|
||||
|
||||
assign ov = (~a_ff[31] & ~bm[31] & aout[31]) |
|
||||
( a_ff[31] & bm[31] & ~aout[31] );
|
||||
|
||||
assign neg = aout[31];
|
||||
|
||||
assign eq = a_ff[31:0] == b_ff[31:0];
|
||||
|
||||
assign ne = ~eq;
|
||||
|
||||
assign logic_sel[3] = ap.land | ap.lor;
|
||||
assign logic_sel[2] = ap.lor | ap.lxor;
|
||||
assign logic_sel[1] = ap.lor | ap.lxor;
|
||||
|
||||
|
||||
|
||||
assign lout[31:0] = ( a_ff[31:0] & b_ff[31:0] & {32{logic_sel[3]}} ) |
|
||||
( a_ff[31:0] & ~b_ff[31:0] & {32{logic_sel[2]}} ) |
|
||||
( ~a_ff[31:0] & b_ff[31:0] & {32{logic_sel[1]}} );
|
||||
|
||||
|
||||
|
||||
assign ashift[31:0] = a_ff >>> b_ff[4:0];
|
||||
|
||||
assign sout[31:0] = ( {32{ap.sll}} & (a_ff[31:0] << b_ff[4:0]) ) |
|
||||
( {32{ap.srl}} & (a_ff[31:0] >> b_ff[4:0]) ) |
|
||||
( {32{ap.sra}} & ashift[31:0] );
|
||||
|
||||
|
||||
assign sel_logic = |{ap.land,ap.lor,ap.lxor};
|
||||
|
||||
assign sel_shift = |{ap.sll,ap.srl,ap.sra};
|
||||
|
||||
assign sel_adder = (ap.add | ap.sub) & ~ap.slt;
|
||||
|
||||
|
||||
|
||||
|
||||
assign lt = (~ap.unsign & (neg ^ ov)) |
|
||||
( ap.unsign & ~cout);
|
||||
|
||||
assign ge = ~lt;
|
||||
|
||||
|
||||
assign slt_one = (ap.slt & lt);
|
||||
|
||||
assign out[31:0] = ({32{sel_logic}} & lout[31:0]) |
|
||||
({32{sel_shift}} & sout[31:0]) |
|
||||
({32{sel_adder}} & aout[31:0]) |
|
||||
({32{ap.jal | pp_ff.pcall | pp_ff.pja | pp_ff.pret}} & {pcout[31:1],1'b0}) |
|
||||
({32{ap.csr_write}} & ((ap.csr_imm) ? b_ff[31:0] : a_ff[31:0])) | // csr_write: if csr_imm rs2 else rs1
|
||||
({31'b0, slt_one});
|
||||
|
||||
// branch handling
|
||||
|
||||
logic any_jal;
|
||||
|
||||
assign any_jal = ap.jal |
|
||||
pp_ff.pcall |
|
||||
pp_ff.pja |
|
||||
pp_ff.pret;
|
||||
|
||||
|
||||
assign actual_taken = (ap.beq & eq) |
|
||||
(ap.bne & ne) |
|
||||
(ap.blt & lt) |
|
||||
(ap.bge & ge) |
|
||||
(any_jal);
|
||||
|
||||
// for a conditional br pcout[] will be the opposite of the branch prediction
|
||||
// for jal or pcall, it will be the link address pc+2 or pc+4
|
||||
|
||||
rvbradder ibradder (
|
||||
.pc(pc_ff[31:1]),
|
||||
.offset(brimm_ff[12:1]),
|
||||
.dout(pcout[31:1])
|
||||
);
|
||||
|
||||
// pred_correct is for the npc logic
|
||||
// pred_correct indicates not to use the flush_path
|
||||
// for any_jal pred_correct==0
|
||||
|
||||
assign pred_correct = ((ap.predict_nt & ~actual_taken) |
|
||||
(ap.predict_t & actual_taken)) & ~any_jal;
|
||||
|
||||
|
||||
// for any_jal adder output is the flush path
|
||||
assign flush_path[31:1] = (any_jal) ? aout[31:1] : pcout[31:1];
|
||||
|
||||
|
||||
// pcall and pret are included here
|
||||
assign cond_mispredict = (ap.predict_t & ~actual_taken) |
|
||||
(ap.predict_nt & actual_taken);
|
||||
|
||||
// target mispredicts on ret's
|
||||
|
||||
assign target_mispredict = pp_ff.pret & (pp_ff.prett[31:1] != aout[31:1]);
|
||||
|
||||
assign flush_upper = ( ap.jal | cond_mispredict | target_mispredict) & valid_ff & ~flush & ~freeze;
|
||||
|
||||
|
||||
// .i 3
|
||||
// .o 2
|
||||
// .ilb hist[1] hist[0] taken
|
||||
// .ob newhist[1] newhist[0]
|
||||
// .type fd
|
||||
//
|
||||
// 00 0 01
|
||||
// 01 0 01
|
||||
// 10 0 00
|
||||
// 11 0 10
|
||||
// 00 1 10
|
||||
// 01 1 00
|
||||
// 10 1 11
|
||||
// 11 1 11
|
||||
|
||||
logic [1:0] newhist;
|
||||
|
||||
assign newhist[1] = (pp_ff.hist[1]&pp_ff.hist[0]) | (!pp_ff.hist[0]&actual_taken);
|
||||
|
||||
assign newhist[0] = (!pp_ff.hist[1]&!actual_taken) | (pp_ff.hist[1]&actual_taken);
|
||||
|
||||
|
||||
|
||||
always_comb begin
|
||||
predict_p_ff = pp_ff;
|
||||
|
||||
predict_p_ff.misp = (valid_ff) ? (cond_mispredict | target_mispredict) & ~flush : pp_ff.misp;
|
||||
predict_p_ff.ataken = (valid_ff) ? actual_taken : pp_ff.ataken;
|
||||
predict_p_ff.hist[1] = (valid_ff) ? newhist[1] : pp_ff.hist[1];
|
||||
predict_p_ff.hist[0] = (valid_ff) ? newhist[0] : pp_ff.hist[0];
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule // exu_alu_ctl
|
|
@ -0,0 +1,315 @@
|
|||
// 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.
|
||||
|
||||
|
||||
module exu_div_ctl
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk, // Top level clock
|
||||
input logic active_clk, // Level 1 active clock
|
||||
input logic rst_l, // Reset
|
||||
input logic scan_mode, // Scan mode
|
||||
|
||||
input logic dec_tlu_fast_div_disable, // Disable small number optimization
|
||||
|
||||
input logic [31:0] dividend, // Numerator
|
||||
input logic [31:0] divisor, // Denominator
|
||||
|
||||
input div_pkt_t dp, // valid, sign, rem
|
||||
|
||||
input logic flush_lower, // Flush pipeline
|
||||
|
||||
|
||||
output logic valid_ff_e1, // Valid E1 stage
|
||||
output logic finish_early, // Finish smallnum
|
||||
output logic finish, // Finish smallnum or normal divide
|
||||
output logic div_stall, // Divide is running
|
||||
|
||||
output logic [31:0] out // Result
|
||||
);
|
||||
|
||||
|
||||
logic run_in, run_state;
|
||||
logic [5:0] count_in, count;
|
||||
logic [32:0] m_ff;
|
||||
logic qff_enable;
|
||||
logic aff_enable;
|
||||
logic [32:0] q_in, q_ff;
|
||||
logic [32:0] a_in, a_ff;
|
||||
logic [32:0] m_eff;
|
||||
logic [32:0] a_shift;
|
||||
logic dividend_neg_ff, divisor_neg_ff;
|
||||
logic [31:0] dividend_comp;
|
||||
logic [31:0] dividend_eff;
|
||||
logic [31:0] q_ff_comp;
|
||||
logic [31:0] q_ff_eff;
|
||||
logic [31:0] a_ff_comp;
|
||||
logic [31:0] a_ff_eff;
|
||||
logic sign_ff, sign_eff;
|
||||
logic rem_ff;
|
||||
logic add;
|
||||
logic [32:0] a_eff;
|
||||
logic [64:0] a_eff_shift;
|
||||
logic rem_correct;
|
||||
logic flush_lower_ff;
|
||||
logic valid_e1;
|
||||
|
||||
logic smallnum_case, smallnum_case_ff;
|
||||
logic [3:0] smallnum, smallnum_ff;
|
||||
logic m_already_comp;
|
||||
|
||||
|
||||
|
||||
rvdff #(1) flush_any_ff (.*, .clk(active_clk), .din(flush_lower), .dout(flush_lower_ff));
|
||||
rvdff #(1) e1val_ff (.*, .clk(active_clk), .din(dp.valid & ~flush_lower_ff), .dout(valid_ff_e1));
|
||||
rvdff #(1) runff (.*, .clk(active_clk), .din(run_in), .dout(run_state));
|
||||
rvdff #(6) countff (.*, .clk(active_clk), .din(count_in[5:0]), .dout(count[5:0]));
|
||||
rvdffs #(4) miscf (.*, .clk(active_clk), .din({dividend[31],divisor[31],sign_eff,dp.rem}), .dout({dividend_neg_ff,divisor_neg_ff,sign_ff,rem_ff}), .en(dp.valid));
|
||||
rvdff #(5) smallnumff (.*, .clk(active_clk), .din({smallnum_case,smallnum[3:0]}), .dout({smallnum_case_ff,smallnum_ff[3:0]}));
|
||||
rvdffe #(33) mff (.*, .en(dp.valid), .din({ ~dp.unsign & divisor[31], divisor[31:0]}), .dout(m_ff[32:0]));
|
||||
rvdffe #(33) qff (.*, .en(qff_enable), .din(q_in[32:0]), .dout(q_ff[32:0]));
|
||||
rvdffe #(33) aff (.*, .en(aff_enable), .din(a_in[32:0]), .dout(a_ff[32:0]));
|
||||
|
||||
rvtwoscomp #(32) dividend_c (.din(q_ff[31:0]), .dout(dividend_comp[31:0]));
|
||||
rvtwoscomp #(32) q_ff_c (.din(q_ff[31:0]), .dout(q_ff_comp[31:0]));
|
||||
rvtwoscomp #(32) a_ff_c (.din(a_ff[31:0]), .dout(a_ff_comp[31:0]));
|
||||
|
||||
|
||||
assign valid_e1 = valid_ff_e1 & ~flush_lower_ff;
|
||||
|
||||
|
||||
// START - short circuit logic for small numbers {{
|
||||
|
||||
// small number divides - any 4b / 4b is done in 1 cycle (divisor != 0)
|
||||
// to generate espresso equations:
|
||||
// 1) smalldiv > smalldiv.e
|
||||
// 2) espresso -Dso -oeqntott smalldiv.e | addassign > smalldiv
|
||||
|
||||
// smallnum case does not cover divide by 0
|
||||
assign smallnum_case = ((q_ff[31:4] == 28'b0) & (m_ff[31:4] == 28'b0) & (m_ff[31:0] != 32'b0) & ~rem_ff & valid_e1 & ~dec_tlu_fast_div_disable) |
|
||||
((q_ff[31:0] == 32'b0) & (m_ff[31:0] != 32'b0) & ~rem_ff & valid_e1 & ~dec_tlu_fast_div_disable);
|
||||
|
||||
|
||||
assign smallnum[3] = ( q_ff[3] & ~m_ff[3] & ~m_ff[2] & ~m_ff[1] );
|
||||
|
||||
|
||||
assign smallnum[2] = ( q_ff[3] & ~m_ff[3] & ~m_ff[2] & ~m_ff[0]) |
|
||||
( q_ff[2] & ~m_ff[3] & ~m_ff[2] & ~m_ff[1] ) |
|
||||
( q_ff[3] & q_ff[2] & ~m_ff[3] & ~m_ff[2] );
|
||||
|
||||
|
||||
assign smallnum[1] = ( q_ff[2] & ~m_ff[3] & ~m_ff[2] & ~m_ff[0]) |
|
||||
( q_ff[1] & ~m_ff[3] & ~m_ff[2] & ~m_ff[1] ) |
|
||||
( q_ff[3] & ~m_ff[3] & ~m_ff[1] & ~m_ff[0]) |
|
||||
( q_ff[3] & ~q_ff[2] & ~m_ff[3] & ~m_ff[2] & m_ff[1] & m_ff[0]) |
|
||||
(~q_ff[3] & q_ff[2] & q_ff[1] & ~m_ff[3] & ~m_ff[2] ) |
|
||||
( q_ff[3] & q_ff[2] & ~m_ff[3] & ~m_ff[0]) |
|
||||
( q_ff[3] & q_ff[2] & ~m_ff[3] & m_ff[2] & ~m_ff[1] ) |
|
||||
( q_ff[3] & q_ff[1] & ~m_ff[3] & ~m_ff[1] ) |
|
||||
( q_ff[3] & q_ff[2] & q_ff[1] & ~m_ff[3] & m_ff[2] );
|
||||
|
||||
|
||||
assign smallnum[0] = ( q_ff[2] & q_ff[1] & q_ff[0] & ~m_ff[3] & ~m_ff[1] ) |
|
||||
( q_ff[3] & ~q_ff[2] & q_ff[0] & ~m_ff[3] & m_ff[1] & m_ff[0]) |
|
||||
( q_ff[2] & ~m_ff[3] & ~m_ff[1] & ~m_ff[0]) |
|
||||
( q_ff[1] & ~m_ff[3] & ~m_ff[2] & ~m_ff[0]) |
|
||||
( q_ff[0] & ~m_ff[3] & ~m_ff[2] & ~m_ff[1] ) |
|
||||
(~q_ff[3] & q_ff[2] & ~q_ff[1] & ~m_ff[3] & ~m_ff[2] & m_ff[1] & m_ff[0]) |
|
||||
(~q_ff[3] & q_ff[2] & q_ff[1] & ~m_ff[3] & ~m_ff[0]) |
|
||||
( q_ff[3] & ~m_ff[2] & ~m_ff[1] & ~m_ff[0]) |
|
||||
( q_ff[3] & ~q_ff[2] & ~m_ff[3] & m_ff[2] & m_ff[1] ) |
|
||||
(~q_ff[3] & q_ff[2] & q_ff[1] & ~m_ff[3] & m_ff[2] & ~m_ff[1] ) |
|
||||
(~q_ff[3] & q_ff[2] & q_ff[0] & ~m_ff[3] & ~m_ff[1] ) |
|
||||
( q_ff[3] & ~q_ff[2] & ~q_ff[1] & ~m_ff[3] & m_ff[2] & m_ff[0]) |
|
||||
( ~q_ff[2] & q_ff[1] & q_ff[0] & ~m_ff[3] & ~m_ff[2] ) |
|
||||
( q_ff[3] & q_ff[2] & ~m_ff[1] & ~m_ff[0]) |
|
||||
( q_ff[3] & q_ff[1] & ~m_ff[2] & ~m_ff[0]) |
|
||||
(~q_ff[3] & q_ff[2] & q_ff[1] & q_ff[0] & ~m_ff[3] & m_ff[2] ) |
|
||||
( q_ff[3] & q_ff[2] & m_ff[3] & ~m_ff[2] ) |
|
||||
( q_ff[3] & q_ff[1] & m_ff[3] & ~m_ff[2] & ~m_ff[1] ) |
|
||||
( q_ff[3] & q_ff[0] & ~m_ff[2] & ~m_ff[1] ) |
|
||||
( q_ff[3] & ~q_ff[1] & ~m_ff[3] & m_ff[2] & m_ff[1] & m_ff[0]) |
|
||||
( q_ff[3] & q_ff[2] & q_ff[1] & m_ff[3] & ~m_ff[0]) |
|
||||
( q_ff[3] & q_ff[2] & q_ff[1] & m_ff[3] & ~m_ff[1] ) |
|
||||
( q_ff[3] & q_ff[2] & q_ff[0] & m_ff[3] & ~m_ff[1] ) |
|
||||
( q_ff[3] & ~q_ff[2] & q_ff[1] & ~m_ff[3] & m_ff[1] ) |
|
||||
( q_ff[3] & q_ff[1] & q_ff[0] & ~m_ff[2] ) |
|
||||
( q_ff[3] & q_ff[2] & q_ff[1] & q_ff[0] & m_ff[3] );
|
||||
|
||||
|
||||
|
||||
// END - short circuit logic for small numbers }}
|
||||
|
||||
|
||||
// *** Start Short Q *** {{
|
||||
|
||||
logic [4:0] a_cls;
|
||||
logic [4:0] b_cls;
|
||||
logic [5:0] shortq;
|
||||
logic [5:0] shortq_shift;
|
||||
logic [5:0] shortq_shift_ff;
|
||||
logic shortq_enable;
|
||||
logic shortq_enable_ff;
|
||||
logic [32:0] short_dividend;
|
||||
|
||||
assign short_dividend[31:0] = q_ff[31:0];
|
||||
assign short_dividend[32] = sign_ff & q_ff[31];
|
||||
|
||||
|
||||
// A B
|
||||
// 210 210 SH
|
||||
// --- --- --
|
||||
// 1xx 000 0
|
||||
// 1xx 001 8
|
||||
// 1xx 01x 16
|
||||
// 1xx 1xx 24
|
||||
// 01x 000 8
|
||||
// 01x 001 16
|
||||
// 01x 01x 24
|
||||
// 01x 1xx 32
|
||||
// 001 000 16
|
||||
// 001 001 24
|
||||
// 001 01x 32
|
||||
// 001 1xx 32
|
||||
// 000 000 24
|
||||
// 000 001 32
|
||||
// 000 01x 32
|
||||
// 000 1xx 32
|
||||
|
||||
logic [3:0] shortq_raw;
|
||||
logic [3:0] shortq_shift_xx;
|
||||
|
||||
assign a_cls[4:3] = 2'b0;
|
||||
assign a_cls[2] = (~short_dividend[32] & (short_dividend[31:24] != {8{1'b0}})) | ( short_dividend[32] & (short_dividend[31:23] != {9{1'b1}}));
|
||||
assign a_cls[1] = (~short_dividend[32] & (short_dividend[23:16] != {8{1'b0}})) | ( short_dividend[32] & (short_dividend[22:15] != {8{1'b1}}));
|
||||
assign a_cls[0] = (~short_dividend[32] & (short_dividend[15:08] != {8{1'b0}})) | ( short_dividend[32] & (short_dividend[14:07] != {8{1'b1}}));
|
||||
|
||||
assign b_cls[4:3] = 2'b0;
|
||||
assign b_cls[2] = (~m_ff[32] & ( m_ff[31:24] != {8{1'b0}})) | ( m_ff[32] & ( m_ff[31:24] != {8{1'b1}}));
|
||||
assign b_cls[1] = (~m_ff[32] & ( m_ff[23:16] != {8{1'b0}})) | ( m_ff[32] & ( m_ff[23:16] != {8{1'b1}}));
|
||||
assign b_cls[0] = (~m_ff[32] & ( m_ff[15:08] != {8{1'b0}})) | ( m_ff[32] & ( m_ff[15:08] != {8{1'b1}}));
|
||||
|
||||
assign shortq_raw[3] = ( (a_cls[2:1] == 2'b01 ) & (b_cls[2] == 1'b1 ) ) | // Shift by 32
|
||||
( (a_cls[2:0] == 3'b001) & (b_cls[2] == 1'b1 ) ) |
|
||||
( (a_cls[2:0] == 3'b000) & (b_cls[2] == 1'b1 ) ) |
|
||||
( (a_cls[2:0] == 3'b001) & (b_cls[2:1] == 2'b01 ) ) |
|
||||
( (a_cls[2:0] == 3'b000) & (b_cls[2:1] == 2'b01 ) ) |
|
||||
( (a_cls[2:0] == 3'b000) & (b_cls[2:0] == 3'b001) );
|
||||
|
||||
assign shortq_raw[2] = ( (a_cls[2] == 1'b1 ) & (b_cls[2] == 1'b1 ) ) | // Shift by 24
|
||||
( (a_cls[2:1] == 2'b01 ) & (b_cls[2:1] == 2'b01 ) ) |
|
||||
( (a_cls[2:0] == 3'b001) & (b_cls[2:0] == 3'b001) ) |
|
||||
( (a_cls[2:0] == 3'b000) & (b_cls[2:0] == 3'b000) );
|
||||
|
||||
assign shortq_raw[1] = ( (a_cls[2] == 1'b1 ) & (b_cls[2:1] == 2'b01 ) ) | // Shift by 16
|
||||
( (a_cls[2:1] == 2'b01 ) & (b_cls[2:0] == 3'b001) ) |
|
||||
( (a_cls[2:0] == 3'b001) & (b_cls[2:0] == 3'b000) );
|
||||
|
||||
assign shortq_raw[0] = ( (a_cls[2] == 1'b1 ) & (b_cls[2:0] == 3'b001) ) | // Shift by 8
|
||||
( (a_cls[2:1] == 2'b01 ) & (b_cls[2:0] == 3'b000) );
|
||||
|
||||
|
||||
assign shortq_enable = valid_ff_e1 & (m_ff[31:0] != 32'b0) & (shortq_raw[3:0] != 4'b0);
|
||||
|
||||
assign shortq_shift[3:0] = ({4{shortq_enable}} & shortq_raw[3:0]);
|
||||
|
||||
rvdff #(5) i_shortq_ff (.*, .clk(active_clk), .din({shortq_enable,shortq_shift[3:0]}), .dout({shortq_enable_ff,shortq_shift_xx[3:0]}));
|
||||
|
||||
assign shortq_shift_ff[5:0] = ({6{shortq_shift_xx[3]}} & 6'b01_1111) | // 31
|
||||
({6{shortq_shift_xx[2]}} & 6'b01_1000) | // 24
|
||||
({6{shortq_shift_xx[1]}} & 6'b01_0000) | // 16
|
||||
({6{shortq_shift_xx[0]}} & 6'b00_1000); // 8
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
|
||||
logic div_assert_fail;
|
||||
|
||||
assign div_assert_fail = (shortq_shift_xx[3] & shortq_shift_xx[2]) |
|
||||
(shortq_shift_xx[3] & shortq_shift_xx[1]) |
|
||||
(shortq_shift_xx[3] & shortq_shift_xx[0]) |
|
||||
(shortq_shift_xx[2] & shortq_shift_xx[1]) |
|
||||
(shortq_shift_xx[2] & shortq_shift_xx[0]) |
|
||||
(shortq_shift_xx[1] & shortq_shift_xx[0]);
|
||||
|
||||
assert_exu_div_shortq_shift_error: assert #0 (~div_assert_fail) else $display("ERROR: SHORTQ_SHIFT_XX with multiple shifts ON!");
|
||||
|
||||
`endif
|
||||
|
||||
// *** End Short Q *** }}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
assign div_stall = run_state;
|
||||
|
||||
assign run_in = (dp.valid | run_state) & ~finish & ~flush_lower_ff;
|
||||
|
||||
assign count_in[5:0] = {6{run_state & ~finish & ~flush_lower_ff & ~shortq_enable}} & (count[5:0] + shortq_shift_ff[5:0] + 6'd1);
|
||||
|
||||
|
||||
assign finish_early = smallnum_case;
|
||||
|
||||
assign finish = (smallnum_case | ((~rem_ff) ? (count[5:0] == 6'd32) : (count[5:0] == 6'd33))) & ~flush_lower & ~flush_lower_ff;
|
||||
|
||||
assign sign_eff = ~dp.unsign & (divisor[31:0] != 32'b0);
|
||||
|
||||
|
||||
assign q_in[32:0] = ({33{~run_state }} & {1'b0,dividend[31:0]}) |
|
||||
({33{ run_state & (valid_ff_e1 | shortq_enable_ff)}} & ({dividend_eff[31:0], ~a_in[32]} << shortq_shift_ff[5:0])) |
|
||||
({33{ run_state & ~(valid_ff_e1 | shortq_enable_ff)}} & {q_ff[31:0], ~a_in[32]});
|
||||
|
||||
assign qff_enable = dp.valid | (run_state & ~shortq_enable);
|
||||
|
||||
|
||||
|
||||
|
||||
assign dividend_eff[31:0] = (sign_ff & dividend_neg_ff) ? dividend_comp[31:0] : q_ff[31:0];
|
||||
|
||||
|
||||
assign m_eff[32:0] = (add) ? m_ff[32:0] : ~m_ff[32:0];
|
||||
|
||||
assign a_eff_shift[64:0] = {33'b0, dividend_eff[31:0]} << shortq_shift_ff[5:0];
|
||||
|
||||
assign a_eff[32:0] = ({33{ rem_correct }} & a_ff[32:0] ) |
|
||||
({33{~rem_correct & ~shortq_enable_ff}} & {a_ff[31:0], q_ff[32]}) |
|
||||
({33{~rem_correct & shortq_enable_ff}} & a_eff_shift[64:32] );
|
||||
|
||||
assign a_shift[32:0] = {33{run_state}} & a_eff[32:0];
|
||||
|
||||
assign a_in[32:0] = {33{run_state}} & (a_shift[32:0] + m_eff[32:0] + {32'b0,~add});
|
||||
|
||||
assign aff_enable = dp.valid | (run_state & ~shortq_enable & (count[5:0]!=6'd33)) | rem_correct;
|
||||
|
||||
|
||||
assign m_already_comp = (divisor_neg_ff & sign_ff);
|
||||
|
||||
// if m already complemented, then invert operation add->sub, sub->add
|
||||
assign add = (a_ff[32] | rem_correct) ^ m_already_comp;
|
||||
|
||||
assign rem_correct = (count[5:0] == 6'd33) & rem_ff & a_ff[32];
|
||||
|
||||
|
||||
|
||||
assign q_ff_eff[31:0] = (sign_ff & (dividend_neg_ff ^ divisor_neg_ff)) ? q_ff_comp[31:0] : q_ff[31:0];
|
||||
|
||||
assign a_ff_eff[31:0] = (sign_ff & dividend_neg_ff) ? a_ff_comp[31:0] : a_ff[31:0];
|
||||
|
||||
assign out[31:0] = ({32{ smallnum_case_ff }} & {28'b0, smallnum_ff[3:0]}) |
|
||||
({32{ rem_ff}} & a_ff_eff[31:0] ) |
|
||||
({32{~smallnum_case_ff & ~rem_ff}} & q_ff_eff[31:0] );
|
||||
|
||||
|
||||
endmodule // exu_div_ctl
|
|
@ -0,0 +1,118 @@
|
|||
// 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.
|
||||
|
||||
|
||||
module exu_mul_ctl
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk, // Top level clock
|
||||
input logic active_clk, // Level 1 active clock
|
||||
input logic clk_override, // Override clock enables
|
||||
input logic rst_l, // Reset
|
||||
input logic scan_mode, // Scan mode
|
||||
|
||||
input logic [31:0] a, // A operand
|
||||
input logic [31:0] b, // B operand
|
||||
|
||||
input logic [31:0] lsu_result_dc3, // Load result used in E1 bypass
|
||||
|
||||
input logic freeze, // Pipeline freeze
|
||||
|
||||
input mul_pkt_t mp, // valid, rs1_sign, rs2_sign, low, load_mul_rs1_bypass_e1, load_mul_rs2_bypass_e1
|
||||
|
||||
|
||||
output logic [31:0] out // Result
|
||||
|
||||
);
|
||||
|
||||
|
||||
logic valid_e1, valid_e2;
|
||||
logic mul_c1_e1_clken, mul_c1_e2_clken, mul_c1_e3_clken;
|
||||
logic exu_mul_c1_e1_clk, exu_mul_c1_e2_clk, exu_mul_c1_e3_clk;
|
||||
|
||||
logic [31:0] a_ff_e1, a_e1;
|
||||
logic [31:0] b_ff_e1, b_e1;
|
||||
logic load_mul_rs1_bypass_e1, load_mul_rs2_bypass_e1;
|
||||
logic rs1_sign_e1, rs1_neg_e1;
|
||||
logic rs2_sign_e1, rs2_neg_e1;
|
||||
logic signed [32:0] a_ff_e2, b_ff_e2;
|
||||
logic [63:0] prod_e3;
|
||||
logic low_e1, low_e2, low_e3;
|
||||
|
||||
|
||||
// --------------------------- Clock gating ----------------------------------
|
||||
|
||||
// C1 clock enables
|
||||
assign mul_c1_e1_clken = (mp.valid | clk_override) & ~freeze;
|
||||
assign mul_c1_e2_clken = (valid_e1 | clk_override) & ~freeze;
|
||||
assign mul_c1_e3_clken = (valid_e2 | clk_override) & ~freeze;
|
||||
|
||||
// C1 - 1 clock pulse for data
|
||||
rvclkhdr exu_mul_c1e1_cgc (.*, .en(mul_c1_e1_clken), .l1clk(exu_mul_c1_e1_clk));
|
||||
rvclkhdr exu_mul_c1e2_cgc (.*, .en(mul_c1_e2_clken), .l1clk(exu_mul_c1_e2_clk));
|
||||
rvclkhdr exu_mul_c1e3_cgc (.*, .en(mul_c1_e3_clken), .l1clk(exu_mul_c1_e3_clk));
|
||||
|
||||
|
||||
// --------------------------- Input flops ----------------------------------
|
||||
|
||||
rvdffs #(1) valid_e1_ff (.*, .din(mp.valid), .dout(valid_e1), .clk(active_clk), .en(~freeze));
|
||||
rvdff #(1) rs1_sign_e1_ff (.*, .din(mp.rs1_sign), .dout(rs1_sign_e1), .clk(exu_mul_c1_e1_clk));
|
||||
rvdff #(1) rs2_sign_e1_ff (.*, .din(mp.rs2_sign), .dout(rs2_sign_e1), .clk(exu_mul_c1_e1_clk));
|
||||
rvdff #(1) low_e1_ff (.*, .din(mp.low), .dout(low_e1), .clk(exu_mul_c1_e1_clk));
|
||||
rvdff #(1) ld_rs1_byp_e1_ff (.*, .din(mp.load_mul_rs1_bypass_e1), .dout(load_mul_rs1_bypass_e1), .clk(exu_mul_c1_e1_clk));
|
||||
rvdff #(1) ld_rs2_byp_e1_ff (.*, .din(mp.load_mul_rs2_bypass_e1), .dout(load_mul_rs2_bypass_e1), .clk(exu_mul_c1_e1_clk));
|
||||
|
||||
rvdff #(32) a_e1_ff (.*, .din(a[31:0]), .dout(a_ff_e1[31:0]), .clk(exu_mul_c1_e1_clk));
|
||||
rvdff #(32) b_e1_ff (.*, .din(b[31:0]), .dout(b_ff_e1[31:0]), .clk(exu_mul_c1_e1_clk));
|
||||
|
||||
|
||||
|
||||
// --------------------------- E1 Logic Stage ----------------------------------
|
||||
|
||||
assign a_e1[31:0] = (load_mul_rs1_bypass_e1) ? lsu_result_dc3[31:0] : a_ff_e1[31:0];
|
||||
assign b_e1[31:0] = (load_mul_rs2_bypass_e1) ? lsu_result_dc3[31:0] : b_ff_e1[31:0];
|
||||
|
||||
assign rs1_neg_e1 = rs1_sign_e1 & a_e1[31];
|
||||
assign rs2_neg_e1 = rs2_sign_e1 & b_e1[31];
|
||||
|
||||
|
||||
rvdffs #(1) valid_e2_ff (.*, .din(valid_e1), .dout(valid_e2), .clk(active_clk), .en(~freeze));
|
||||
rvdff #(1) low_e2_ff (.*, .din(low_e1), .dout(low_e2), .clk(exu_mul_c1_e2_clk));
|
||||
|
||||
rvdff #(33) a_e2_ff (.*, .din({rs1_neg_e1, a_e1[31:0]}), .dout(a_ff_e2[32:0]), .clk(exu_mul_c1_e2_clk));
|
||||
rvdff #(33) b_e2_ff (.*, .din({rs2_neg_e1, b_e1[31:0]}), .dout(b_ff_e2[32:0]), .clk(exu_mul_c1_e2_clk));
|
||||
|
||||
|
||||
|
||||
// ---------------------- E2 Logic Stage --------------------------
|
||||
|
||||
|
||||
logic signed [65:0] prod_e2;
|
||||
|
||||
assign prod_e2[65:0] = a_ff_e2 * b_ff_e2;
|
||||
|
||||
|
||||
rvdff #(1) low_e3_ff (.*, .din(low_e2), .dout(low_e3), .clk(exu_mul_c1_e3_clk));
|
||||
rvdff #(64) prod_e3_ff (.*, .din(prod_e2[63:0]), .dout(prod_e3[63:0]), .clk(exu_mul_c1_e3_clk));
|
||||
|
||||
|
||||
|
||||
// ----------------------- E3 Logic Stage -------------------------
|
||||
|
||||
|
||||
assign out[31:0] = low_e3 ? prod_e3[31:0] : prod_e3[63:32];
|
||||
|
||||
|
||||
endmodule // exu_mul_ctl
|
|
@ -0,0 +1,52 @@
|
|||
$RV_ROOT/workspace/work/snapshots/default/common_defines.vh
|
||||
$RV_ROOT/design/include/def.sv
|
||||
+incdir+$RV_ROOT/workspace/work/snapshots/default
|
||||
+incdir+$RV_ROOT/design/lib
|
||||
+incdir+$RV_ROOT/design/include
|
||||
+incdir+$RV_ROOT/design/dmi
|
||||
$RV_ROOT/design/swerv_wrapper.sv
|
||||
$RV_ROOT/design/mem.sv
|
||||
$RV_ROOT/design/pic_ctrl.sv
|
||||
$RV_ROOT/design/swerv.sv
|
||||
$RV_ROOT/design/dma_ctrl.sv
|
||||
$RV_ROOT/design/ifu/ifu_aln_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_compress_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ifc_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_bp_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ic_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu_mem_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_iccm_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu.sv
|
||||
$RV_ROOT/design/dec/dec_decode_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_gpr_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_ib_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_tlu_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_trigger.sv
|
||||
$RV_ROOT/design/dec/dec.sv
|
||||
$RV_ROOT/design/exu/exu_alu_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_mul_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_div_ctl.sv
|
||||
$RV_ROOT/design/exu/exu.sv
|
||||
$RV_ROOT/design/lsu/lsu.sv
|
||||
$RV_ROOT/design/lsu/lsu_clkdomain.sv
|
||||
$RV_ROOT/design/lsu/lsu_addrcheck.sv
|
||||
$RV_ROOT/design/lsu/lsu_lsc_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_stbuf.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_buffer.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_intf.sv
|
||||
$RV_ROOT/design/lsu/lsu_ecc.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_mem.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_trigger.sv
|
||||
$RV_ROOT/design/dbg/dbg.sv
|
||||
$RV_ROOT/design/dmi/dmi_wrapper.v
|
||||
$RV_ROOT/design/dmi/dmi_jtag_to_core_sync.v
|
||||
$RV_ROOT/design/dmi/rvjtag_tap.sv
|
||||
$RV_ROOT/design/lib/beh_lib.sv
|
||||
$RV_ROOT/design/lib/mem_lib.sv
|
||||
$RV_ROOT/design/lib/svci_to_ahb.sv
|
||||
$RV_ROOT/design/lib/ahb_to_svci.sv
|
||||
$RV_ROOT/design/lib/svci_to_axi4.sv
|
||||
$RV_ROOT/design/lib/axi4_to_svci.sv
|
||||
$RV_ROOT/design/lib/ahb_to_axi4.sv
|
||||
$RV_ROOT/design/lib/axi4_to_ahb.sv
|
|
@ -0,0 +1,406 @@
|
|||
//********************************************************************************
|
||||
// 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.
|
||||
//********************************************************************************
|
||||
//********************************************************************************
|
||||
// Function: Top level file for Icache, Fetch, Branch prediction & Aligner
|
||||
// BFF -> F1 -> F2 -> A
|
||||
//********************************************************************************
|
||||
|
||||
module ifu
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic free_clk,
|
||||
input logic active_clk,
|
||||
input logic clk,
|
||||
input logic clk_override,
|
||||
input logic rst_l,
|
||||
|
||||
input logic dec_ib3_valid_d, dec_ib2_valid_d, // mass balance for decode buffer
|
||||
|
||||
input logic dec_ib0_valid_eff_d, // effective valid taking decode into account
|
||||
input logic dec_ib1_valid_eff_d, // effective valid taking decode into account
|
||||
|
||||
input logic exu_i0_br_ret_e4, // i0 branch commit is a ret
|
||||
input logic exu_i1_br_ret_e4, // i1 branch commit is a ret
|
||||
input logic exu_i0_br_call_e4, // i0 branch commit is a call
|
||||
input logic exu_i1_br_call_e4, // i1 branch commit is a call
|
||||
|
||||
input logic exu_flush_final, // flush, includes upper and lower
|
||||
input logic dec_tlu_flush_err_wb , // flush due to parity error.
|
||||
input logic dec_tlu_flush_noredir_wb, // don't fetch, validated with exu_flush_final
|
||||
input logic dec_tlu_dbg_halted, // halted, used for leaving IDLE state
|
||||
input logic dec_tlu_pmu_fw_halted, // Core is halted
|
||||
input logic [31:1] exu_flush_path_final, // flush fetch address
|
||||
input logic exu_flush_upper_e2, // flush upper, either i0 or i1
|
||||
|
||||
input logic [31:0] dec_tlu_mrac_ff ,// Side_effect , cacheable for each region
|
||||
input logic dec_tlu_fence_i_wb, // fence.i, invalidate icache, validated with exu_flush_final
|
||||
input logic dec_tlu_flush_leak_one_wb, // ignore bp for leak one fetches
|
||||
|
||||
input logic dec_tlu_bpred_disable, // disable all branch prediction
|
||||
input logic dec_tlu_core_ecc_disable, // disable ecc checking and flagging
|
||||
|
||||
// AXI Write Channels - IFU never writes. So, 0 out mostly
|
||||
output logic ifu_axi_awvalid,
|
||||
input logic ifu_axi_awready,
|
||||
output logic [`RV_IFU_BUS_TAG-1:0] ifu_axi_awid,
|
||||
output logic [31:0] ifu_axi_awaddr,
|
||||
output logic [3:0] ifu_axi_awregion,
|
||||
output logic [7:0] ifu_axi_awlen,
|
||||
output logic [2:0] ifu_axi_awsize,
|
||||
output logic [1:0] ifu_axi_awburst,
|
||||
output logic ifu_axi_awlock,
|
||||
output logic [3:0] ifu_axi_awcache,
|
||||
output logic [2:0] ifu_axi_awprot,
|
||||
output logic [3:0] ifu_axi_awqos,
|
||||
|
||||
output logic ifu_axi_wvalid,
|
||||
input logic ifu_axi_wready,
|
||||
output logic [63:0] ifu_axi_wdata,
|
||||
output logic [7:0] ifu_axi_wstrb,
|
||||
output logic ifu_axi_wlast,
|
||||
|
||||
input logic ifu_axi_bvalid,
|
||||
output logic ifu_axi_bready,
|
||||
input logic [1:0] ifu_axi_bresp,
|
||||
input logic [`RV_IFU_BUS_TAG-1:0] ifu_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic ifu_axi_arvalid,
|
||||
input logic ifu_axi_arready,
|
||||
output logic [`RV_IFU_BUS_TAG-1:0] ifu_axi_arid,
|
||||
output logic [31:0] ifu_axi_araddr,
|
||||
output logic [3:0] ifu_axi_arregion,
|
||||
output logic [7:0] ifu_axi_arlen,
|
||||
output logic [2:0] ifu_axi_arsize,
|
||||
output logic [1:0] ifu_axi_arburst,
|
||||
output logic ifu_axi_arlock,
|
||||
output logic [3:0] ifu_axi_arcache,
|
||||
output logic [2:0] ifu_axi_arprot,
|
||||
output logic [3:0] ifu_axi_arqos,
|
||||
|
||||
input logic ifu_axi_rvalid,
|
||||
output logic ifu_axi_rready,
|
||||
input logic [`RV_IFU_BUS_TAG-1:0] ifu_axi_rid,
|
||||
input logic [63:0] ifu_axi_rdata,
|
||||
input logic [1:0] ifu_axi_rresp,
|
||||
input logic ifu_axi_rlast,
|
||||
|
||||
//// AHB LITE BUS
|
||||
//`ifdef RV_BUILD_AHB_LITE
|
||||
input logic ifu_bus_clk_en,
|
||||
|
||||
|
||||
input logic dma_iccm_req,
|
||||
input logic dma_iccm_stall_any,
|
||||
input logic [31:0] dma_mem_addr,
|
||||
input logic [2:0] dma_mem_sz,
|
||||
input logic dma_mem_write,
|
||||
input logic [63:0] dma_mem_wdata,
|
||||
|
||||
output logic iccm_dma_ecc_error,
|
||||
output logic iccm_dma_rvalid,
|
||||
output logic [63:0] iccm_dma_rdata,
|
||||
output logic iccm_ready,
|
||||
|
||||
//`endif
|
||||
|
||||
output logic [1:0] ifu_pmu_instr_aligned,
|
||||
output logic ifu_pmu_align_stall,
|
||||
output logic ifu_pmu_fetch_stall,
|
||||
|
||||
// I$ & ITAG Ports
|
||||
output logic [31:3] ic_rw_addr, // Read/Write addresss to the Icache.
|
||||
output logic [3:0] ic_wr_en, // Icache write enable, when filling the Icache.
|
||||
output logic ic_rd_en, // Icache read enable.
|
||||
`ifdef RV_ICACHE_ECC
|
||||
output logic [83:0] ic_wr_data, // Data to fill to the Icache. With ECC
|
||||
input logic [167:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
|
||||
input logic [24:0] ictag_debug_rd_data,// Debug icache tag.
|
||||
output logic [41:0] ic_debug_wr_data, // Debug wr cache.
|
||||
output logic [41:0] ifu_ic_debug_rd_data,
|
||||
`else
|
||||
output logic [67:0] ic_wr_data, // Data to fill to the Icache. With Parity
|
||||
input logic [135:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With Parity
|
||||
input logic [20:0] ictag_debug_rd_data,// Debug icache tag.
|
||||
output logic [33:0] ic_debug_wr_data, // Debug wr cache.
|
||||
output logic [33:0] ifu_ic_debug_rd_data,
|
||||
`endif
|
||||
|
||||
|
||||
output logic [127:0] ic_premux_data, // Premux data to be muxed with each way of the Icache.
|
||||
output logic ic_sel_premux_data, // Select the premux data.
|
||||
|
||||
output logic [15:2] ic_debug_addr, // Read/Write addresss to the Icache.
|
||||
output logic ic_debug_rd_en, // Icache debug rd
|
||||
output logic ic_debug_wr_en, // Icache debug wr
|
||||
output logic ic_debug_tag_array, // Debug tag array
|
||||
output logic [3:0] ic_debug_way, // Debug way. Rd or Wr.
|
||||
|
||||
|
||||
output logic [3:0] ic_tag_valid, // Valid bits when accessing the Icache. One valid bit per way. F2 stage
|
||||
|
||||
input logic [3:0] ic_rd_hit, // Compare hits from Icache tags. Per way. F2 stage
|
||||
input logic ic_tag_perr, // Icache Tag parity error
|
||||
|
||||
|
||||
`ifdef RV_ICCM_ENABLE
|
||||
// ICCM ports
|
||||
output logic [`RV_ICCM_BITS-1:2] iccm_rw_addr, // ICCM read/write address.
|
||||
output logic iccm_wren, // ICCM write enable (through the DMA)
|
||||
output logic iccm_rden, // ICCM read enable.
|
||||
output logic [77:0] iccm_wr_data, // ICCM write data.
|
||||
output logic [2:0] iccm_wr_size, // ICCM write location within DW.
|
||||
|
||||
input logic [155:0] iccm_rd_data, // Data read from ICCM.
|
||||
`endif
|
||||
|
||||
// Perf counter sigs
|
||||
output logic ifu_pmu_ic_miss, // ic miss
|
||||
output logic ifu_pmu_ic_hit, // ic hit
|
||||
output logic ifu_pmu_bus_error, // iside bus error
|
||||
output logic ifu_pmu_bus_busy, // iside bus busy
|
||||
output logic ifu_pmu_bus_trxn, // iside bus transactions
|
||||
|
||||
|
||||
output logic ifu_i0_valid, // Instruction 0 valid. From Aligner to Decode
|
||||
output logic ifu_i1_valid, // Instruction 1 valid. From Aligner to Decode
|
||||
output logic ifu_i0_icaf, // Instruction 0 access fault. From Aligner to Decode
|
||||
output logic ifu_i1_icaf, // Instruction 1 access fault. From Aligner to Decode
|
||||
output logic ifu_i0_icaf_f1, // Instruction 0 has access fault on second fetch group
|
||||
output logic ifu_i1_icaf_f1, // Instruction 1 has access fault on second fetch group
|
||||
output logic ifu_i0_perr, // Instruction 0 parity error. From Aligner to Decode
|
||||
output logic ifu_i1_perr, // Instruction 1 parity error. From Aligner to Decode
|
||||
output logic ifu_i0_sbecc, // Instruction 0 has single bit ecc error
|
||||
output logic ifu_i1_sbecc, // Instruction 1 has single bit ecc error
|
||||
output logic ifu_i0_dbecc, // Instruction 0 has double bit ecc error
|
||||
output logic ifu_i1_dbecc, // Instruction 1 has double bit ecc error
|
||||
output logic iccm_dma_sb_error, // Single Bit ECC error from a DMA access
|
||||
output logic[31:0] ifu_i0_instr, // Instruction 0 . From Aligner to Decode
|
||||
output logic[31:0] ifu_i1_instr, // Instruction 1 . From Aligner to Decode
|
||||
output logic[31:1] ifu_i0_pc, // Instruction 0 pc. From Aligner to Decode
|
||||
output logic[31:1] ifu_i1_pc, // Instruction 1 pc. From Aligner to Decode
|
||||
output logic ifu_i0_pc4, // Instruction 0 is 4 byte. From Aligner to Decode
|
||||
output logic ifu_i1_pc4, // Instruction 1 is 4 byte. From Aligner to Decode
|
||||
output logic [15:0] ifu_illegal_inst, // Illegal instruction.
|
||||
|
||||
output logic ifu_miss_state_idle, // There is no outstanding miss. Cache miss state is idle.
|
||||
|
||||
|
||||
output br_pkt_t i0_brp, // Instruction 0 branch packet. From Aligner to Decode
|
||||
output br_pkt_t i1_brp, // Instruction 1 branch packet. From Aligner to Decode
|
||||
|
||||
input predict_pkt_t exu_mp_pkt, // mispredict packet
|
||||
input logic [`RV_BHT_GHR_RANGE] exu_mp_eghr, // execute ghr
|
||||
|
||||
input br_tlu_pkt_t dec_tlu_br0_wb_pkt, // slot0 update/error pkt
|
||||
input br_tlu_pkt_t dec_tlu_br1_wb_pkt, // slot1 update/error pkt
|
||||
input dec_tlu_flush_lower_wb,
|
||||
|
||||
input rets_pkt_t exu_rets_e1_pkt, // E1 return stack packet
|
||||
input rets_pkt_t exu_rets_e4_pkt, // E4 return stack packet
|
||||
|
||||
// pc's used to maintain and update the BP RET stacks
|
||||
`ifdef REAL_COMM_RS
|
||||
input logic [31:1] exu_i0_pc_e1,
|
||||
input logic [31:1] exu_i1_pc_e1,
|
||||
input logic [31:1] dec_tlu_i0_pc_e4,
|
||||
input logic [31:1] dec_tlu_i1_pc_e4,
|
||||
`endif
|
||||
|
||||
output logic [15:0] ifu_i0_cinst,
|
||||
output logic [15:0] ifu_i1_cinst,
|
||||
|
||||
|
||||
/// Icache debug
|
||||
input cache_debug_pkt_t dec_tlu_ic_diag_pkt ,
|
||||
output logic ifu_ic_debug_rd_data_valid,
|
||||
|
||||
|
||||
|
||||
input logic scan_mode
|
||||
);
|
||||
|
||||
localparam TAGWIDTH = 2 ;
|
||||
localparam IDWIDTH = 2 ;
|
||||
|
||||
logic ifu_fb_consume1, ifu_fb_consume2;
|
||||
logic [31:1] ifc_fetch_addr_f2;
|
||||
logic ifc_fetch_uncacheable_f1;
|
||||
|
||||
logic [7:0] ifu_fetch_val; // valids on a 2B boundary, left justified [7] implies valid fetch
|
||||
logic [31:1] ifu_fetch_pc; // starting pc of fetch
|
||||
|
||||
logic [31:1] ifc_fetch_addr_f1;
|
||||
|
||||
logic ic_crit_wd_rdy;
|
||||
logic ic_write_stall;
|
||||
logic ic_dma_active;
|
||||
logic ifc_dma_access_ok;
|
||||
logic ifc_iccm_access_f1;
|
||||
logic ifc_region_acc_fault_f1;
|
||||
logic ic_access_fault_f2;
|
||||
logic ifu_ic_mb_empty;
|
||||
|
||||
|
||||
logic ic_hit_f2;
|
||||
|
||||
// fetch control
|
||||
ifu_ifc_ctl ifc (.*
|
||||
);
|
||||
|
||||
|
||||
`ifdef RV_BTB_48
|
||||
logic [7:0][1:0] ifu_bp_way_f2; // way indication; right justified
|
||||
`else
|
||||
logic [7:0] ifu_bp_way_f2; // way indication; right justified
|
||||
`endif
|
||||
logic ifu_bp_kill_next_f2; // kill next fetch; taken target found
|
||||
logic [31:1] ifu_bp_btb_target_f2; // predicted target PC
|
||||
logic [7:1] ifu_bp_inst_mask_f2; // tell ic which valids to kill because of a taken branch; right justified
|
||||
logic [7:0] ifu_bp_hist1_f2; // history counters for all 4 potential branches; right justified
|
||||
logic [7:0] ifu_bp_hist0_f2; // history counters for all 4 potential branches; right justified
|
||||
logic [11:0] ifu_bp_poffset_f2; // predicted target
|
||||
logic [7:0] ifu_bp_ret_f2; // predicted ret ; right justified
|
||||
logic [7:0] ifu_bp_pc4_f2; // pc4 indication; right justified
|
||||
logic [7:0] ifu_bp_valid_f2; // branch valid, right justified
|
||||
logic [`RV_BHT_GHR_RANGE] ifu_bp_fghr_f2;
|
||||
|
||||
// branch predictor
|
||||
ifu_bp_ctl bp (.*);
|
||||
|
||||
|
||||
logic [7:0] ic_fetch_val_f2;
|
||||
logic [127:0] ic_data_f2;
|
||||
logic [127:0] ifu_fetch_data;
|
||||
logic ifc_fetch_req_f1_raw, ifc_fetch_req_f1, ifc_fetch_req_f2;
|
||||
logic ic_rd_parity_final_err; // This fetch has a data_cache or tag parity error.
|
||||
logic iccm_rd_ecc_single_err; // This fetch has an iccm single error.
|
||||
logic iccm_rd_ecc_double_err; // This fetch has an iccm double error.
|
||||
|
||||
icache_err_pkt_t ic_error_f2;
|
||||
|
||||
logic ifu_icache_fetch_f2 ;
|
||||
logic [16:2] ifu_icache_error_index; // Index with parity error
|
||||
logic ifu_icache_error_val; // Parity error
|
||||
logic ifu_icache_sb_error_val;
|
||||
|
||||
assign ifu_fetch_data[127:0] = ic_data_f2[127:0];
|
||||
assign ifu_fetch_val[7:0] = ic_fetch_val_f2[7:0];
|
||||
assign ifu_fetch_pc[31:1] = ifc_fetch_addr_f2[31:1];
|
||||
|
||||
// aligner
|
||||
ifu_aln_ctl aln (.*);
|
||||
|
||||
// icache
|
||||
ifu_mem_ctl mem_ctl
|
||||
(.*,
|
||||
.fetch_addr_f1(ifc_fetch_addr_f1),
|
||||
.ifu_icache_error_index(ifu_icache_error_index[16:6]),
|
||||
.ic_hit_f2(ic_hit_f2),
|
||||
.ic_data_f2(ic_data_f2[127:0])
|
||||
);
|
||||
|
||||
|
||||
|
||||
// Performance debug info
|
||||
//
|
||||
//
|
||||
`ifdef DUMP_BTB_ON
|
||||
logic exu_mp_valid; // conditional branch mispredict
|
||||
logic exu_mp_way; // conditional branch mispredict
|
||||
logic exu_mp_ataken; // direction is actual taken
|
||||
logic exu_mp_boffset; // branch offsett
|
||||
logic exu_mp_pc4; // branch is a 4B inst
|
||||
logic exu_mp_call; // branch is a call inst
|
||||
logic exu_mp_ret; // branch is a ret inst
|
||||
logic exu_mp_ja; // branch is a jump always
|
||||
logic [1:0] exu_mp_hist; // new history
|
||||
logic [11:0] exu_mp_tgt; // target offset
|
||||
logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] exu_mp_addr; // BTB/BHT address
|
||||
logic [1:0] exu_mp_bank; // write bank; based on branch PC[3:2]
|
||||
logic [`RV_BTB_BTAG_SIZE-1:0] exu_mp_btag; // branch tag
|
||||
logic [`RV_BHT_GHR_RANGE] exu_mp_fghr; // original fetch ghr (for correcting dir)
|
||||
|
||||
assign exu_mp_valid = exu_mp_pkt.misp; // conditional branch mispredict
|
||||
assign exu_mp_ataken = exu_mp_pkt.ataken; // direction is actual taken
|
||||
assign exu_mp_boffset = exu_mp_pkt.boffset; // branch offset
|
||||
assign exu_mp_pc4 = exu_mp_pkt.pc4; // branch is a 4B inst
|
||||
assign exu_mp_call = exu_mp_pkt.pcall; // branch is a call inst
|
||||
assign exu_mp_ret = exu_mp_pkt.pret; // branch is a ret inst
|
||||
assign exu_mp_ja = exu_mp_pkt.pja; // branch is a jump always
|
||||
assign exu_mp_way = exu_mp_pkt.way; // branch is a jump always
|
||||
assign exu_mp_hist[1:0] = exu_mp_pkt.hist[1:0]; // new history
|
||||
assign exu_mp_tgt[11:0] = exu_mp_pkt.toffset[11:0] ; // target offset
|
||||
assign exu_mp_addr[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] = exu_mp_pkt.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] ; // BTB/BHT address
|
||||
assign exu_mp_bank[1:0] = exu_mp_pkt.bank[1:0] ; // write bank = exu_mp_pkt.; based on branch PC[3:2]
|
||||
assign exu_mp_btag = exu_mp_pkt.btag[`RV_BTB_BTAG_SIZE-1:0] ; // branch tag
|
||||
assign exu_mp_fghr[`RV_BHT_GHR_RANGE] = exu_mp_pkt.fghr[`RV_BHT_GHR_RANGE] ; // original fetch ghr (for correcting dir)
|
||||
|
||||
logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] btb_rd_addr_f2;
|
||||
`define DEC `CPU_TOP.dec
|
||||
`define EXU `CPU_TOP.exu
|
||||
rvbtb_addr_hash f2hash(.pc(ifc_fetch_addr_f2[31:1]), .hash(btb_rd_addr_f2[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO]));
|
||||
logic [31:0] mppc_ns, mppc;
|
||||
assign mppc_ns[31:1] = `EXU.exu_i0_flush_upper_e1 ? `DEC.decode.i0_pc_e1[31:1] : (`EXU.exu_i1_flush_upper_e1 ? `DEC.decode.i1_pc_e1[31:1] : (`EXU.exu_i0_flush_lower_e4 ? `DEC.decode.i0_pc_e4[31:1] : `DEC.decode.i1_pc_e4[31:1]));
|
||||
assign mppc_ns[0] = 1'b0;
|
||||
logic [3:0] ic_rd_hit_f2;
|
||||
rvdff #(36) mdseal_ff (.*, .din({mppc_ns[31:0], mem_ctl.ic_rd_hit[3:0]}), .dout({mppc[31:0],ic_rd_hit_f2[3:0]}));
|
||||
logic [2:0] tmp_bnk;
|
||||
assign tmp_bnk[2:0] = encode8_3(bp.btb_sel_f2[7:0]);
|
||||
always @(negedge clk) begin
|
||||
if(`DEC.tlu.mcyclel[31:0] == 32'h0000_0010) begin
|
||||
$display("BTB_CONFIG: %d",`RV_BTB_ARRAY_DEPTH*4);
|
||||
`ifndef BP_NOGSHARE
|
||||
$display("BHT_CONFIG: %d gshare: 1",`RV_BHT_ARRAY_DEPTH*4);
|
||||
`else
|
||||
$display("BHT_CONFIG: %d gshare: 0",`RV_BHT_ARRAY_DEPTH*4);
|
||||
`endif
|
||||
$display("RS_CONFIG: %d", `RV_RET_STACK_SIZE);
|
||||
end
|
||||
if(exu_flush_final & ~(dec_tlu_br0_wb_pkt.br_error | dec_tlu_br0_wb_pkt.br_start_error | dec_tlu_br1_wb_pkt.br_error | dec_tlu_br1_wb_pkt.br_start_error) & (exu_mp_pkt.misp | exu_mp_pkt.ataken))
|
||||
$display("%7d BTB_MP : index: %0h bank: %0h call: %b ret: %b ataken: %b hist: %h valid: %b tag: %h targ: %h eghr: %b pred: %b ghr_index: %h brpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha, exu_mp_addr[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO], exu_mp_bank[1:0], exu_mp_call, exu_mp_ret, exu_mp_ataken, exu_mp_hist[1:0], exu_mp_valid, exu_mp_pkt.btag[`RV_BTB_BTAG_SIZE-1:0], {exu_flush_path_final[31:1], 1'b0}, exu_mp_eghr[`RV_BHT_GHR_RANGE], exu_mp_valid, bp.bht_wr_addr0, mppc[31:0], exu_mp_pkt.way);
|
||||
for(int i = 0; i < 8; i++) begin
|
||||
if(ifu_bp_valid_f2[i] & ifc_fetch_req_f2)
|
||||
$display("%7d BTB_HIT : index: %0h bank: %0h call: %b ret: %b taken: %b strength: %b tag: %h targ: %h ghr: %4b ghr_index: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,btb_rd_addr_f2[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO],encode8_3(bp.btb_sel_f2[7:0]), bp.btb_rd_call_f2, bp.btb_rd_ret_f2, ifu_bp_hist1_f2[tmp_bnk], ifu_bp_hist0_f2[tmp_bnk], bp.fetch_rd_tag_f2[`RV_BTB_BTAG_SIZE-1:0], {ifu_bp_btb_target_f2[31:1], 1'b0}, bp.fghr[`RV_BHT_GHR_RANGE], bp.bht_rd_addr_f1, ifu_bp_way_f2[tmp_bnk]);
|
||||
end
|
||||
`ifdef RV_BTB_48
|
||||
for(int y = 0; y < 4; y++) begin
|
||||
for(int z = 0; z < 4; z++) begin
|
||||
if(bp.lru_bank_sel[y][z])
|
||||
$display("%7d BTB_LRU: index: %0h bank: %0h newlru %h", `DEC.tlu.mcyclel[31:0]+32'ha, z,y,bp.lru_bank_wr_data[y][z]);
|
||||
end
|
||||
end
|
||||
`endif
|
||||
if(dec_tlu_br0_wb_pkt.valid & ~(dec_tlu_br0_wb_pkt.br_error | dec_tlu_br0_wb_pkt.br_start_error))
|
||||
$display("%7d BTB_UPD0: ghr_index: %0h bank: %0h hist: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,bp.br0_hashed_wb[`RV_BHT_ADDR_HI:`RV_BHT_ADDR_LO],{dec_tlu_br0_wb_pkt.bank[1:0],dec_tlu_br0_wb_pkt.middle}, dec_tlu_br0_wb_pkt.hist, dec_tlu_br0_wb_pkt.way);
|
||||
if(dec_tlu_br1_wb_pkt.valid & ~(dec_tlu_br1_wb_pkt.br_error | dec_tlu_br1_wb_pkt.br_start_error))
|
||||
$display("%7d BTB_UPD1: ghr_index: %0h bank: %0h hist: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,bp.br1_hashed_wb[`RV_BHT_ADDR_HI:`RV_BHT_ADDR_LO],{dec_tlu_br1_wb_pkt.bank[1:0],dec_tlu_br1_wb_pkt.middle}, dec_tlu_br1_wb_pkt.hist, dec_tlu_br1_wb_pkt.way);
|
||||
if(dec_tlu_br0_wb_pkt.br_error | dec_tlu_br0_wb_pkt.br_start_error)
|
||||
$display("%7d BTB_ERR0: index: %0h bank: %0h start: %b rfpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,dec_tlu_br0_wb_pkt.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO],dec_tlu_br0_wb_pkt.bank[1:0], dec_tlu_br0_wb_pkt.br_start_error, {exu_flush_path_final[31:1], 1'b0}, dec_tlu_br0_wb_pkt.way);
|
||||
if(dec_tlu_br1_wb_pkt.br_error | dec_tlu_br1_wb_pkt.br_start_error)
|
||||
$display("%7d BTB_ERR1: index: %0h bank: %0h start: %b rfpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,dec_tlu_br1_wb_pkt.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO],dec_tlu_br1_wb_pkt.bank[1:0], dec_tlu_br1_wb_pkt.br_start_error, {exu_flush_path_final[31:1], 1'b0}, dec_tlu_br1_wb_pkt.way);
|
||||
end // always @ (negedge clk)
|
||||
function [2:0] encode8_3;
|
||||
input [7:0] in;
|
||||
|
||||
encode8_3[2] = |in[7:4];
|
||||
encode8_3[1] = in[7] | in[6] | in[3] | in[2];
|
||||
encode8_3[0] = in[7] | in[5] | in[3] | in[1];
|
||||
|
||||
endfunction
|
||||
`endif
|
||||
endmodule // ifu
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,379 @@
|
|||
//********************************************************************************
|
||||
// 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.
|
||||
//********************************************************************************
|
||||
|
||||
// purpose of this file is to convert 16b RISCV compressed instruction into 32b equivalent
|
||||
|
||||
module ifu_compress_ctl
|
||||
(
|
||||
input logic [15:0] din,
|
||||
output logic [31:0] dout,
|
||||
output logic legal
|
||||
);
|
||||
|
||||
|
||||
|
||||
logic [15:0] i;
|
||||
|
||||
logic [31:0] o,l1,l2,l3;
|
||||
|
||||
|
||||
assign i[15:0] = din[15:0];
|
||||
|
||||
|
||||
logic [4:0] rs2d,rdd,rdpd,rs2pd;
|
||||
|
||||
logic rdrd;
|
||||
logic rdrs1;
|
||||
logic rs2rs2;
|
||||
logic rdprd;
|
||||
logic rdprs1;
|
||||
logic rs2prs2;
|
||||
logic rs2prd;
|
||||
logic uimm9_2;
|
||||
logic ulwimm6_2;
|
||||
logic ulwspimm7_2;
|
||||
logic rdeq2;
|
||||
logic rdeq1;
|
||||
logic rs1eq2;
|
||||
logic sbroffset8_1;
|
||||
logic simm9_4;
|
||||
logic simm5_0;
|
||||
logic sjaloffset11_1;
|
||||
logic sluimm17_12;
|
||||
logic uimm5_0;
|
||||
logic uswimm6_2;
|
||||
logic uswspimm7_2;
|
||||
|
||||
|
||||
|
||||
// form the opcodes
|
||||
|
||||
// formats
|
||||
//
|
||||
// c.add rd 11:7 rs2 6:2
|
||||
// c.and rdp 9:7 rs2p 4:2
|
||||
//
|
||||
// add rs2 24:20 rs1 19:15 rd 11:7
|
||||
|
||||
assign rs2d[4:0] = i[6:2];
|
||||
|
||||
assign rdd[4:0] = i[11:7];
|
||||
|
||||
assign rdpd[4:0] = {2'b01, i[9:7]};
|
||||
|
||||
assign rs2pd[4:0] = {2'b01, i[4:2]};
|
||||
|
||||
|
||||
|
||||
// merge in rd, rs1, rs2
|
||||
|
||||
|
||||
// rd
|
||||
assign l1[6:0] = o[6:0];
|
||||
|
||||
assign l1[11:7] = o[11:7] |
|
||||
({5{rdrd}} & rdd[4:0]) |
|
||||
({5{rdprd}} & rdpd[4:0]) |
|
||||
({5{rs2prd}} & rs2pd[4:0]) |
|
||||
({5{rdeq1}} & 5'd1) |
|
||||
({5{rdeq2}} & 5'd2);
|
||||
|
||||
|
||||
// rs1
|
||||
assign l1[14:12] = o[14:12];
|
||||
assign l1[19:15] = o[19:15] |
|
||||
({5{rdrs1}} & rdd[4:0]) |
|
||||
({5{rdprs1}} & rdpd[4:0]) |
|
||||
({5{rs1eq2}} & 5'd2);
|
||||
|
||||
|
||||
// rs2
|
||||
assign l1[24:20] = o[24:20] |
|
||||
({5{rs2rs2}} & rs2d[4:0]) |
|
||||
({5{rs2prs2}} & rs2pd[4:0]);
|
||||
|
||||
assign l1[31:25] = o[31:25];
|
||||
|
||||
logic [5:0] simm5d;
|
||||
logic [9:2] uimm9d;
|
||||
|
||||
logic [9:4] simm9d;
|
||||
logic [6:2] ulwimm6d;
|
||||
logic [7:2] ulwspimm7d;
|
||||
logic [5:0] uimm5d;
|
||||
logic [20:1] sjald;
|
||||
|
||||
logic [31:12] sluimmd;
|
||||
|
||||
// merge in immediates + jal offset
|
||||
|
||||
assign simm5d[5:0] = { i[12], i[6:2] };
|
||||
|
||||
assign uimm9d[9:2] = { i[10:7], i[12:11], i[5], i[6] };
|
||||
|
||||
assign simm9d[9:4] = { i[12], i[4:3], i[5], i[2], i[6] };
|
||||
|
||||
assign ulwimm6d[6:2] = { i[5], i[12:10], i[6] };
|
||||
|
||||
assign ulwspimm7d[7:2] = { i[3:2], i[12], i[6:4] };
|
||||
|
||||
assign uimm5d[5:0] = { i[12], i[6:2] };
|
||||
|
||||
assign sjald[11:1] = { i[12], i[8], i[10:9], i[6], i[7], i[2], i[11], i[5:4], i[3] };
|
||||
|
||||
assign sjald[20:12] = {9{i[12]}};
|
||||
|
||||
|
||||
|
||||
assign sluimmd[31:12] = { {15{i[12]}}, i[6:2] };
|
||||
|
||||
|
||||
assign l2[31:20] = ( l1[31:20] ) |
|
||||
( {12{simm5_0}} & {{7{simm5d[5]}},simm5d[4:0]} ) |
|
||||
( {12{uimm9_2}} & {2'b0,uimm9d[9:2],2'b0} ) |
|
||||
( {12{simm9_4}} & {{3{simm9d[9]}},simm9d[8:4],4'b0} ) |
|
||||
( {12{ulwimm6_2}} & {5'b0,ulwimm6d[6:2],2'b0} ) |
|
||||
( {12{ulwspimm7_2}} & {4'b0,ulwspimm7d[7:2],2'b0} ) |
|
||||
( {12{uimm5_0}} & {6'b0,uimm5d[5:0]} ) |
|
||||
( {12{sjaloffset11_1}} & {sjald[20],sjald[10:1],sjald[11]} ) |
|
||||
( {12{sluimm17_12}} & sluimmd[31:20] );
|
||||
|
||||
|
||||
|
||||
assign l2[19:12] = ( l1[19:12] ) |
|
||||
( {8{sjaloffset11_1}} & sjald[19:12] ) |
|
||||
( {8{sluimm17_12}} & sluimmd[19:12] );
|
||||
|
||||
|
||||
assign l2[11:0] = l1[11:0];
|
||||
|
||||
|
||||
// merge in branch offset and store immediates
|
||||
|
||||
logic [8:1] sbr8d;
|
||||
logic [6:2] uswimm6d;
|
||||
logic [7:2] uswspimm7d;
|
||||
|
||||
|
||||
assign sbr8d[8:1] = { i[12], i[6], i[5], i[2], i[11], i[10], i[4], i[3] };
|
||||
|
||||
assign uswimm6d[6:2] = { i[5], i[12:10], i[6] };
|
||||
|
||||
assign uswspimm7d[7:2] = { i[8:7], i[12:9] };
|
||||
|
||||
assign l3[31:25] = ( l2[31:25] ) |
|
||||
( {7{sbroffset8_1}} & { {4{sbr8d[8]}},sbr8d[7:5] } ) |
|
||||
( {7{uswimm6_2}} & { 5'b0, uswimm6d[6:5] } ) |
|
||||
( {7{uswspimm7_2}} & { 4'b0, uswspimm7d[7:5] } );
|
||||
|
||||
|
||||
assign l3[24:12] = l2[24:12];
|
||||
|
||||
assign l3[11:7] = ( l2[11:7] ) |
|
||||
( {5{sbroffset8_1}} & { sbr8d[4:1], sbr8d[8] } ) |
|
||||
( {5{uswimm6_2}} & { uswimm6d[4:2], 2'b0 } ) |
|
||||
( {5{uswspimm7_2}} & { uswspimm7d[4:2], 2'b0 } );
|
||||
|
||||
assign l3[6:0] = l2[6:0];
|
||||
|
||||
|
||||
assign dout[31:0] = l3[31:0] & {32{legal}};
|
||||
|
||||
|
||||
// file "cdecode" is human readable file that has all of the compressed instruction decodes defined and is part of git repo
|
||||
// modify this file as needed
|
||||
|
||||
// to generate all the equations below from "cdecode" except legal equation:
|
||||
|
||||
// 1) coredecode -in cdecode > cdecode.e
|
||||
|
||||
// 2) espresso -Dso -oeqntott cdecode.e | addassign > compress_equations
|
||||
|
||||
// to generate the legal (16b compressed instruction is legal) equation below:
|
||||
|
||||
// 1) coredecode -in cdecode -legal > clegal.e
|
||||
|
||||
// 2) espresso -Dso -oeqntott clegal.e | addassign > clegal_equation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// espresso decodes
|
||||
assign rdrd = (!i[14]&i[6]&i[1]) | (!i[15]&i[14]&i[11]&i[0]) | (!i[14]&i[5]&i[1]) | (
|
||||
!i[15]&i[14]&i[10]&i[0]) | (!i[14]&i[4]&i[1]) | (!i[15]&i[14]&i[9]
|
||||
&i[0]) | (!i[14]&i[3]&i[1]) | (!i[15]&i[14]&!i[8]&i[0]) | (!i[14]
|
||||
&i[2]&i[1]) | (!i[15]&i[14]&i[7]&i[0]) | (!i[15]&i[1]) | (!i[15]
|
||||
&!i[13]&i[0]);
|
||||
|
||||
assign rdrs1 = (!i[14]&i[12]&i[11]&i[1]) | (!i[14]&i[12]&i[10]&i[1]) | (!i[14]
|
||||
&i[12]&i[9]&i[1]) | (!i[14]&i[12]&i[8]&i[1]) | (!i[14]&i[12]&i[7]
|
||||
&i[1]) | (!i[14]&!i[12]&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]
|
||||
&i[12]&i[6]&i[1]) | (!i[14]&i[12]&i[5]&i[1]) | (!i[14]&i[12]&i[4]
|
||||
&i[1]) | (!i[14]&i[12]&i[3]&i[1]) | (!i[14]&i[12]&i[2]&i[1]) | (
|
||||
!i[15]&!i[14]&!i[13]&i[0]) | (!i[15]&!i[14]&i[1]);
|
||||
|
||||
assign rs2rs2 = (i[15]&i[6]&i[1]) | (i[15]&i[5]&i[1]) | (i[15]&i[4]&i[1]) | (
|
||||
i[15]&i[3]&i[1]) | (i[15]&i[2]&i[1]) | (i[15]&i[14]&i[1]);
|
||||
|
||||
assign rdprd = (i[15]&!i[14]&!i[13]&i[0]);
|
||||
|
||||
assign rdprs1 = (i[15]&!i[13]&i[0]) | (i[15]&i[14]&i[0]) | (i[14]&!i[1]&!i[0]);
|
||||
|
||||
assign rs2prs2 = (i[15]&!i[14]&!i[13]&i[11]&i[10]&i[0]) | (i[15]&!i[1]&!i[0]);
|
||||
|
||||
assign rs2prd = (!i[15]&!i[1]&!i[0]);
|
||||
|
||||
assign uimm9_2 = (!i[14]&!i[1]&!i[0]);
|
||||
|
||||
assign ulwimm6_2 = (!i[15]&i[14]&!i[1]&!i[0]);
|
||||
|
||||
assign ulwspimm7_2 = (!i[15]&i[14]&i[1]);
|
||||
|
||||
assign rdeq2 = (!i[15]&i[14]&i[13]&!i[11]&!i[10]&!i[9]&i[8]&!i[7]);
|
||||
|
||||
assign rdeq1 = (!i[14]&i[12]&i[11]&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]
|
||||
&i[12]&i[10]&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]&i[12]&i[9]
|
||||
&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]&i[12]&i[8]&!i[6]&!i[5]
|
||||
&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]&i[12]&i[7]&!i[6]&!i[5]&!i[4]&!i[3]
|
||||
&!i[2]&i[1]) | (!i[15]&!i[14]&i[13]);
|
||||
|
||||
assign rs1eq2 = (!i[15]&i[14]&i[13]&!i[11]&!i[10]&!i[9]&i[8]&!i[7]) | (i[14]
|
||||
&i[1]) | (!i[14]&!i[1]&!i[0]);
|
||||
|
||||
assign sbroffset8_1 = (i[15]&i[14]&i[0]);
|
||||
|
||||
assign simm9_4 = (!i[15]&i[14]&i[13]&!i[11]&!i[10]&!i[9]&i[8]&!i[7]);
|
||||
|
||||
assign simm5_0 = (!i[14]&!i[13]&i[11]&!i[10]&i[0]) | (!i[15]&!i[13]&i[0]);
|
||||
|
||||
assign sjaloffset11_1 = (!i[14]&i[13]);
|
||||
|
||||
assign sluimm17_12 = (!i[15]&i[14]&i[13]&i[7]) | (!i[15]&i[14]&i[13]&!i[8]) | (
|
||||
!i[15]&i[14]&i[13]&i[9]) | (!i[15]&i[14]&i[13]&i[10]) | (!i[15]&i[14]
|
||||
&i[13]&i[11]);
|
||||
|
||||
assign uimm5_0 = (i[15]&!i[14]&!i[13]&!i[11]&i[0]) | (!i[15]&!i[14]&i[1]);
|
||||
|
||||
assign uswimm6_2 = (i[15]&!i[1]&!i[0]);
|
||||
|
||||
assign uswspimm7_2 = (i[15]&i[14]&i[1]);
|
||||
|
||||
assign o[31] = 1'b0;
|
||||
|
||||
assign o[30] = (i[15]&!i[14]&!i[13]&i[10]&!i[6]&!i[5]&i[0]) | (i[15]&!i[14]
|
||||
&!i[13]&!i[11]&i[10]&i[0]);
|
||||
|
||||
assign o[29] = 1'b0;
|
||||
|
||||
assign o[28] = 1'b0;
|
||||
|
||||
assign o[27] = 1'b0;
|
||||
|
||||
assign o[26] = 1'b0;
|
||||
|
||||
assign o[25] = 1'b0;
|
||||
|
||||
assign o[24] = 1'b0;
|
||||
|
||||
assign o[23] = 1'b0;
|
||||
|
||||
assign o[22] = 1'b0;
|
||||
|
||||
assign o[21] = 1'b0;
|
||||
|
||||
assign o[20] = (!i[14]&i[12]&!i[11]&!i[10]&!i[9]&!i[8]&!i[7]&!i[6]&!i[5]&!i[4]
|
||||
&!i[3]&!i[2]&i[1]);
|
||||
|
||||
assign o[19] = 1'b0;
|
||||
|
||||
assign o[18] = 1'b0;
|
||||
|
||||
assign o[17] = 1'b0;
|
||||
|
||||
assign o[16] = 1'b0;
|
||||
|
||||
assign o[15] = 1'b0;
|
||||
|
||||
assign o[14] = (i[15]&!i[14]&!i[13]&!i[11]&i[0]) | (i[15]&!i[14]&!i[13]&!i[10]
|
||||
&i[0]) | (i[15]&!i[14]&!i[13]&i[6]&i[0]) | (i[15]&!i[14]&!i[13]&i[5]
|
||||
&i[0]);
|
||||
|
||||
assign o[13] = (i[15]&!i[14]&!i[13]&i[11]&!i[10]&i[0]) | (i[15]&!i[14]&!i[13]
|
||||
&i[11]&i[6]&i[0]) | (i[14]&!i[0]);
|
||||
|
||||
assign o[12] = (i[15]&!i[14]&!i[13]&i[6]&i[5]&i[0]) | (i[15]&!i[14]&!i[13]&!i[11]
|
||||
&i[0]) | (i[15]&!i[14]&!i[13]&!i[10]&i[0]) | (!i[15]&!i[14]&i[1]) | (
|
||||
i[15]&i[14]&i[13]);
|
||||
|
||||
assign o[11] = 1'b0;
|
||||
|
||||
assign o[10] = 1'b0;
|
||||
|
||||
assign o[9] = 1'b0;
|
||||
|
||||
assign o[8] = 1'b0;
|
||||
|
||||
assign o[7] = 1'b0;
|
||||
|
||||
assign o[6] = (i[15]&!i[14]&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]&!i[0]) | (!i[14]&i[13]) | (
|
||||
i[15]&i[14]&i[0]);
|
||||
|
||||
assign o[5] = (i[15]&!i[0]) | (i[15]&i[11]&i[10]) | (i[13]&!i[8]) | (i[13]&i[7]) | (
|
||||
i[13]&i[9]) | (i[13]&i[10]) | (i[13]&i[11]) | (!i[14]&i[13]) | (
|
||||
i[15]&i[14]);
|
||||
|
||||
assign o[4] = (!i[14]&!i[11]&!i[10]&!i[9]&!i[8]&!i[7]&!i[0]) | (!i[15]&!i[14]
|
||||
&!i[0]) | (!i[14]&i[6]&!i[0]) | (!i[15]&i[14]&i[0]) | (!i[14]&i[5]
|
||||
&!i[0]) | (!i[14]&i[4]&!i[0]) | (!i[14]&!i[13]&i[0]) | (!i[14]&i[3]
|
||||
&!i[0]) | (!i[14]&i[2]&!i[0]);
|
||||
|
||||
assign o[3] = (!i[14]&i[13]);
|
||||
|
||||
assign o[2] = (!i[14]&i[12]&i[11]&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]
|
||||
&i[12]&i[10]&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]&i[12]&i[9]
|
||||
&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]&i[12]&i[8]&!i[6]&!i[5]
|
||||
&!i[4]&!i[3]&!i[2]&i[1]) | (!i[14]&i[12]&i[7]&!i[6]&!i[5]&!i[4]&!i[3]
|
||||
&!i[2]&i[1]) | (i[15]&!i[14]&!i[12]&!i[6]&!i[5]&!i[4]&!i[3]&!i[2]
|
||||
&!i[0]) | (!i[15]&i[13]&!i[8]) | (!i[15]&i[13]&i[7]) | (!i[15]&i[13]
|
||||
&i[9]) | (!i[15]&i[13]&i[10]) | (!i[15]&i[13]&i[11]) | (!i[14]&i[13]);
|
||||
|
||||
// 32b instruction has lower two bits 2'b11
|
||||
|
||||
assign o[1] = 1'b1;
|
||||
|
||||
assign o[0] = 1'b1;
|
||||
|
||||
assign legal = (!i[13]&!i[12]&i[11]&i[1]&!i[0]) | (!i[13]&!i[12]&i[6]&i[1]&!i[0]) | (
|
||||
!i[15]&!i[13]&i[11]&!i[1]) | (!i[13]&!i[12]&i[5]&i[1]&!i[0]) | (
|
||||
!i[13]&!i[12]&i[10]&i[1]&!i[0]) | (!i[15]&!i[13]&i[6]&!i[1]) | (
|
||||
i[15]&!i[12]&!i[1]&i[0]) | (!i[13]&!i[12]&i[9]&i[1]&!i[0]) | (!i[12]
|
||||
&i[6]&!i[1]&i[0]) | (!i[15]&!i[13]&i[5]&!i[1]) | (!i[13]&!i[12]&i[8]
|
||||
&i[1]&!i[0]) | (!i[12]&i[5]&!i[1]&i[0]) | (!i[15]&!i[13]&i[10]&!i[1]) | (
|
||||
!i[13]&!i[12]&i[7]&i[1]&!i[0]) | (i[12]&i[11]&!i[10]&!i[1]&i[0]) | (
|
||||
!i[15]&!i[13]&i[9]&!i[1]) | (!i[13]&!i[12]&i[4]&i[1]&!i[0]) | (i[13]
|
||||
&i[12]&!i[1]&i[0]) | (!i[15]&!i[13]&i[8]&!i[1]) | (!i[13]&!i[12]&i[3]
|
||||
&i[1]&!i[0]) | (i[13]&i[4]&!i[1]&i[0]) | (!i[13]&!i[12]&i[2]&i[1]
|
||||
&!i[0]) | (!i[15]&!i[13]&i[7]&!i[1]) | (i[13]&i[3]&!i[1]&i[0]) | (
|
||||
i[13]&i[2]&!i[1]&i[0]) | (i[14]&!i[13]&!i[1]) | (!i[14]&!i[12]&!i[1]
|
||||
&i[0]) | (i[15]&!i[13]&i[12]&i[1]&!i[0]) | (!i[15]&!i[13]&!i[12]&i[1]
|
||||
&!i[0]) | (!i[15]&!i[13]&i[12]&!i[1]) | (i[14]&!i[13]&!i[0]);
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,559 @@
|
|||
//********************************************************************************
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2019 Western Digital Corporation or it's 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.
|
||||
//********************************************************************************
|
||||
////////////////////////////////////////////////////
|
||||
// ICACHE DATA & TAG MODULE WRAPPER //
|
||||
/////////////////////////////////////////////////////
|
||||
module ifu_ic_mem
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic clk_override,
|
||||
input logic dec_tlu_core_ecc_disable,
|
||||
|
||||
input logic [31:3] ic_rw_addr,
|
||||
input logic [3:0] ic_wr_en , // Which way to write
|
||||
input logic ic_rd_en , // Read enable
|
||||
|
||||
input logic [15:2] ic_debug_addr, // Read/Write addresss to the Icache.
|
||||
input logic ic_debug_rd_en, // Icache debug rd
|
||||
input logic ic_debug_wr_en, // Icache debug wr
|
||||
input logic ic_debug_tag_array, // Debug tag array
|
||||
input logic [3:0] ic_debug_way, // Debug way. Rd or Wr.
|
||||
input logic [127:0] ic_premux_data, // Premux data to be muxed with each way of the Icache.
|
||||
input logic ic_sel_premux_data, // Select the pre_muxed data
|
||||
|
||||
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
input logic [83:0] ic_wr_data, // Data to fill to the Icache. With ECC
|
||||
output logic [167:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
|
||||
output logic [24:0] ictag_debug_rd_data,// Debug icache tag.
|
||||
input logic [41:0] ic_debug_wr_data, // Debug wr cache.
|
||||
`else
|
||||
input logic [67:0] ic_wr_data, // Data to fill to the Icache. With Parity
|
||||
output logic [135:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With Parity
|
||||
output logic [20:0] ictag_debug_rd_data,// Debug icache tag.
|
||||
input logic [33:0] ic_debug_wr_data, // Debug wr cache.
|
||||
`endif
|
||||
|
||||
|
||||
input logic [3:0] ic_tag_valid, // Valid from the I$ tag valid outside (in flops).
|
||||
|
||||
output logic [3:0] ic_rd_hit, // ic_rd_hit[3:0]
|
||||
output logic ic_tag_perr, // Tag Parity error
|
||||
input logic scan_mode
|
||||
) ;
|
||||
|
||||
`include "global.h"
|
||||
|
||||
IC_TAG #( .ICACHE_TAG_HIGH(ICACHE_TAG_HIGH) ,
|
||||
.ICACHE_TAG_LOW(ICACHE_TAG_LOW) ,
|
||||
.ICACHE_TAG_DEPTH(ICACHE_TAG_DEPTH)
|
||||
) ic_tag_inst
|
||||
(
|
||||
.*,
|
||||
.ic_wr_en (ic_wr_en[3:0]),
|
||||
.ic_debug_addr(ic_debug_addr[ICACHE_TAG_HIGH-1:2]),
|
||||
.ic_rw_addr (ic_rw_addr[31:3])
|
||||
) ;
|
||||
|
||||
IC_DATA #( .ICACHE_TAG_HIGH(ICACHE_TAG_HIGH) ,
|
||||
.ICACHE_TAG_LOW(ICACHE_TAG_LOW) ,
|
||||
.ICACHE_IC_DEPTH(ICACHE_IC_DEPTH)
|
||||
) ic_data_inst
|
||||
(
|
||||
.*,
|
||||
.ic_wr_en (ic_wr_en[3:0]),
|
||||
.ic_debug_addr(ic_debug_addr[ICACHE_TAG_HIGH-1:2]),
|
||||
.ic_rw_addr (ic_rw_addr[ICACHE_TAG_HIGH-1:3])
|
||||
) ;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
////// ICACHE DATA MODULE ////////////////////
|
||||
/////////////////////////////////////////////////
|
||||
module IC_DATA #(parameter ICACHE_TAG_HIGH = 16 ,
|
||||
ICACHE_TAG_LOW=6 ,
|
||||
ICACHE_IC_DEPTH=1024
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic clk_override,
|
||||
|
||||
input logic [ICACHE_TAG_HIGH-1:3] ic_rw_addr,
|
||||
input logic [3:0] ic_wr_en,
|
||||
input logic ic_rd_en, // Read enable
|
||||
`ifdef RV_ICACHE_ECC
|
||||
input logic [83:0] ic_wr_data, // Data to fill to the Icache. With ECC
|
||||
output logic [167:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
|
||||
input logic [41:0] ic_debug_wr_data, // Debug wr cache.
|
||||
`else
|
||||
input logic [67:0] ic_wr_data, // Data to fill to the Icache. With Parity
|
||||
output logic [135:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With Parity
|
||||
input logic [33:0] ic_debug_wr_data, // Debug wr cache.
|
||||
`endif
|
||||
|
||||
|
||||
input logic [ICACHE_TAG_HIGH-1:2] ic_debug_addr, // Read/Write addresss to the Icache.
|
||||
input logic ic_debug_rd_en, // Icache debug rd
|
||||
input logic ic_debug_wr_en, // Icache debug wr
|
||||
input logic ic_debug_tag_array, // Debug tag array
|
||||
input logic [3:0] ic_debug_way, // Debug way. Rd or Wr.
|
||||
input logic [127:0] ic_premux_data, // Premux data to be muxed with each way of the Icache.
|
||||
input logic ic_sel_premux_data, // Select the pre_muxed data
|
||||
|
||||
input logic [3:0] ic_rd_hit,
|
||||
|
||||
input logic scan_mode
|
||||
|
||||
) ;
|
||||
|
||||
logic [5:4] ic_rw_addr_ff;
|
||||
|
||||
|
||||
logic [3:0][3:0] ic_b_sb_wren; // way, bank
|
||||
|
||||
logic ic_debug_sel_sb0 ;
|
||||
logic ic_debug_sel_sb1 ;
|
||||
logic ic_debug_sel_sb2 ;
|
||||
logic ic_debug_sel_sb3 ;
|
||||
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
logic [3:0] [167:0] bank_set_dout;
|
||||
logic [3:0][167:0] wb_dout ; //
|
||||
logic [3:0][41:0] ic_sb_wr_data;
|
||||
`else
|
||||
logic [3:0] [135:0] bank_set_dout;
|
||||
logic [3:0] [135:0] wb_dout ; // bank , way , size
|
||||
logic [3:0] [33:0] ic_sb_wr_data;
|
||||
`endif
|
||||
|
||||
logic [3:0] ic_bank_way_clken; // bank , way
|
||||
logic [3:0] ic_bank_way_clk ; // bank , way
|
||||
logic ic_b_rden;
|
||||
logic [3:0] ic_debug_rd_way_en; // debug wr_way
|
||||
logic [3:0] ic_debug_rd_way_en_ff; // debug wr_way
|
||||
logic [3:0] ic_debug_wr_way_en; // debug wr_way
|
||||
logic [ICACHE_TAG_HIGH-1:4] ic_rw_addr_q;
|
||||
|
||||
assign ic_debug_rd_way_en[3:0] = {4{ic_debug_rd_en & ~ic_debug_tag_array}} & ic_debug_way[3:0] ;
|
||||
assign ic_debug_wr_way_en[3:0] = {4{ic_debug_wr_en & ~ic_debug_tag_array}} & ic_debug_way[3:0] ;
|
||||
|
||||
assign ic_b_sb_wren[0][3:0] = (ic_wr_en[3:0] & {4{~ic_rw_addr[3]}} ) |
|
||||
(ic_debug_wr_way_en[3:0] & {4{ic_debug_addr[3:2] == 2'b00}}) ;
|
||||
assign ic_b_sb_wren[1][3:0] = (ic_wr_en[3:0] & {4{~ic_rw_addr[3]}} ) |
|
||||
(ic_debug_wr_way_en[3:0] & {4{ic_debug_addr[3:2] == 2'b01}}) ;
|
||||
assign ic_b_sb_wren[2][3:0] = (ic_wr_en[3:0] & {4{ic_rw_addr[3]}} ) |
|
||||
(ic_debug_wr_way_en[3:0] & {4{ic_debug_addr[3:2] == 2'b10}}) ;
|
||||
assign ic_b_sb_wren[3][3:0] = (ic_wr_en[3:0] & {4{ic_rw_addr[3]}} ) |
|
||||
(ic_debug_wr_way_en[3:0] & {4{ic_debug_addr[3:2] == 2'b11}}) ;
|
||||
|
||||
assign ic_debug_sel_sb0 = (ic_debug_addr[3:2] == 2'b00 ) ;
|
||||
assign ic_debug_sel_sb1 = (ic_debug_addr[3:2] == 2'b01 ) ;
|
||||
assign ic_debug_sel_sb2 = (ic_debug_addr[3:2] == 2'b10 ) ;
|
||||
assign ic_debug_sel_sb3 = (ic_debug_addr[3:2] == 2'b11 ) ;
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
|
||||
assign ic_sb_wr_data[0][41:0] = (ic_debug_sel_sb0 & ic_debug_wr_en) ? {ic_debug_wr_data[41:0]} :
|
||||
ic_wr_data[41:0] ;
|
||||
assign ic_sb_wr_data[1][41:0] = (ic_debug_sel_sb1 & ic_debug_wr_en) ? {ic_debug_wr_data[41:0]} :
|
||||
ic_wr_data[83:42] ;
|
||||
assign ic_sb_wr_data[2][41:0] = (ic_debug_sel_sb2 & ic_debug_wr_en) ? {ic_debug_wr_data[41:0]} :
|
||||
ic_wr_data[41:0] ;
|
||||
assign ic_sb_wr_data[3][41:0] = (ic_debug_sel_sb3 & ic_debug_wr_en) ? {ic_debug_wr_data[41:0]} :
|
||||
ic_wr_data[83:42] ;
|
||||
`else
|
||||
assign ic_sb_wr_data[0][33:0] = (ic_debug_sel_sb0 & ic_debug_wr_en) ? ic_debug_wr_data[33:0] :
|
||||
ic_wr_data[33:0] ;
|
||||
assign ic_sb_wr_data[1][33:0] = (ic_debug_sel_sb1 & ic_debug_wr_en) ? ic_debug_wr_data[33:0] :
|
||||
ic_wr_data[67:34] ;
|
||||
assign ic_sb_wr_data[2][33:0] = (ic_debug_sel_sb2 & ic_debug_wr_en) ? ic_debug_wr_data[33:0] :
|
||||
ic_wr_data[33:0] ;
|
||||
assign ic_sb_wr_data[3][33:0] = (ic_debug_sel_sb3 & ic_debug_wr_en) ? ic_debug_wr_data[33:0] :
|
||||
ic_wr_data[67:34] ;
|
||||
`endif
|
||||
|
||||
|
||||
// bank read enables
|
||||
|
||||
assign ic_b_rden = (ic_rd_en | ic_debug_rd_en );
|
||||
|
||||
assign ic_bank_way_clken[3:0] = ({4{ic_b_rden | clk_override }}) |
|
||||
ic_b_sb_wren[0][3:0] |
|
||||
ic_b_sb_wren[1][3:0] |
|
||||
ic_b_sb_wren[2][3:0] |
|
||||
ic_b_sb_wren[3][3:0] ;
|
||||
|
||||
|
||||
|
||||
assign ic_rw_addr_q[ICACHE_TAG_HIGH-1:4] = (ic_debug_rd_en | ic_debug_wr_en) ?
|
||||
ic_debug_addr[ICACHE_TAG_HIGH-1:4] :
|
||||
ic_rw_addr[ICACHE_TAG_HIGH-1:4] ;
|
||||
|
||||
logic ic_debug_rd_en_ff;
|
||||
|
||||
rvdff #(2) adr_ff (.*,
|
||||
.din ({ic_rw_addr_q[5:4]}),
|
||||
.dout({ic_rw_addr_ff[5:4]}));
|
||||
|
||||
rvdff #(5) debug_rd_wy_ff (.*,
|
||||
.din ({ic_debug_rd_way_en[3:0], ic_debug_rd_en}),
|
||||
.dout({ic_debug_rd_way_en_ff[3:0], ic_debug_rd_en_ff}));
|
||||
|
||||
localparam NUM_WAYS=4 ;
|
||||
localparam NUM_SUBBANKS=4 ;
|
||||
|
||||
|
||||
for (genvar i=0; i<NUM_WAYS; i++) begin: WAYS
|
||||
|
||||
rvclkhdr bank_way_c1_cgc ( .en(ic_bank_way_clken[i]), .l1clk(ic_bank_way_clk[i]), .* );
|
||||
|
||||
for (genvar k=0; k<NUM_SUBBANKS; k++) begin: SUBBANKS // 16B subbank
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
`RV_ICACHE_DATA_CELL ic_bank_sb_way_data (
|
||||
.CLK(ic_bank_way_clk[i]),
|
||||
.WE (ic_b_sb_wren[k][i]),
|
||||
.D (ic_sb_wr_data[k][41:0]),
|
||||
.ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:4]),
|
||||
.Q (wb_dout[i][(k+1)*42-1:k*42])
|
||||
);
|
||||
`else
|
||||
`RV_ICACHE_DATA_CELL ic_bank_sb_way_data (
|
||||
.CLK(ic_bank_way_clk[i]),
|
||||
.WE (ic_b_sb_wren[k][i]),
|
||||
.D (ic_sb_wr_data[k][33:0]),
|
||||
.ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:4]),
|
||||
.Q (wb_dout[i][(k+1)*34-1:k*34])
|
||||
);
|
||||
`endif
|
||||
end // block: SUBBANKS
|
||||
|
||||
end
|
||||
|
||||
|
||||
logic [3:0] ic_rd_hit_q;
|
||||
assign ic_rd_hit_q[3:0] = ic_debug_rd_en_ff ? ic_debug_rd_way_en_ff[3:0] : ic_rd_hit[3:0] ;
|
||||
|
||||
// set mux
|
||||
`ifdef RV_ICACHE_ECC
|
||||
logic [167:0] ic_premux_data_ext;
|
||||
logic [3:0] [167:0] wb_dout_way;
|
||||
logic [3:0] [167:0] wb_dout_way_with_premux;
|
||||
|
||||
assign ic_premux_data_ext[167:0] = {10'b0,ic_premux_data[127:96],10'b0,ic_premux_data[95:64] ,10'b0,ic_premux_data[63:32],10'b0,ic_premux_data[31:0]};
|
||||
assign wb_dout_way[0][167:0] = wb_dout[0][167:0];
|
||||
assign wb_dout_way[1][167:0] = wb_dout[1][167:0];
|
||||
assign wb_dout_way[2][167:0] = wb_dout[2][167:0];
|
||||
assign wb_dout_way[3][167:0] = wb_dout[3][167:0];
|
||||
|
||||
|
||||
assign wb_dout_way_with_premux[0][167:0] = ic_sel_premux_data ? ic_premux_data_ext[167:0] : wb_dout_way[0][167:0] ;
|
||||
assign wb_dout_way_with_premux[1][167:0] = ic_sel_premux_data ? ic_premux_data_ext[167:0] : wb_dout_way[1][167:0] ;
|
||||
assign wb_dout_way_with_premux[2][167:0] = ic_sel_premux_data ? ic_premux_data_ext[167:0] : wb_dout_way[2][167:0] ;
|
||||
assign wb_dout_way_with_premux[3][167:0] = ic_sel_premux_data ? ic_premux_data_ext[167:0] : wb_dout_way[3][167:0] ;
|
||||
|
||||
assign ic_rd_data[167:0] = ({168{ic_rd_hit_q[0] | ic_sel_premux_data}} & wb_dout_way_with_premux[0][167:0]) |
|
||||
({168{ic_rd_hit_q[1] | ic_sel_premux_data}} & wb_dout_way_with_premux[1][167:0]) |
|
||||
({168{ic_rd_hit_q[2] | ic_sel_premux_data}} & wb_dout_way_with_premux[2][167:0]) |
|
||||
({168{ic_rd_hit_q[3] | ic_sel_premux_data}} & wb_dout_way_with_premux[3][167:0]) ;
|
||||
|
||||
`else
|
||||
logic [135:0] ic_premux_data_ext;
|
||||
logic [3:0] [135:0] wb_dout_way;
|
||||
logic [3:0] [135:0] wb_dout_way_with_premux;
|
||||
|
||||
assign ic_premux_data_ext[135:0] = {2'b0,ic_premux_data[127:96],2'b0,ic_premux_data[95:64] ,2'b0,ic_premux_data[63:32],2'b0,ic_premux_data[31:0]};
|
||||
assign wb_dout_way[0][135:0] = wb_dout[0][135:0];
|
||||
assign wb_dout_way[1][135:0] = wb_dout[1][135:0];
|
||||
assign wb_dout_way[2][135:0] = wb_dout[2][135:0];
|
||||
assign wb_dout_way[3][135:0] = wb_dout[3][135:0];
|
||||
|
||||
assign wb_dout_way_with_premux[0][135:0] = ic_sel_premux_data ? ic_premux_data_ext[135:0] : wb_dout_way[0][135:0] ;
|
||||
assign wb_dout_way_with_premux[1][135:0] = ic_sel_premux_data ? ic_premux_data_ext[135:0] : wb_dout_way[1][135:0] ;
|
||||
assign wb_dout_way_with_premux[2][135:0] = ic_sel_premux_data ? ic_premux_data_ext[135:0] : wb_dout_way[2][135:0] ;
|
||||
assign wb_dout_way_with_premux[3][135:0] = ic_sel_premux_data ? ic_premux_data_ext[135:0] : wb_dout_way[3][135:0] ;
|
||||
|
||||
assign ic_rd_data[135:0] = ({136{ic_rd_hit_q[0] | ic_sel_premux_data}} & wb_dout_way_with_premux[0][135:0]) |
|
||||
({136{ic_rd_hit_q[1] | ic_sel_premux_data}} & wb_dout_way_with_premux[1][135:0]) |
|
||||
({136{ic_rd_hit_q[2] | ic_sel_premux_data}} & wb_dout_way_with_premux[2][135:0]) |
|
||||
({136{ic_rd_hit_q[3] | ic_sel_premux_data}} & wb_dout_way_with_premux[3][135:0]) ;
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
////// ICACHE TAG MODULE ////////////////////
|
||||
/////////////////////////////////////////////////
|
||||
module IC_TAG #(parameter ICACHE_TAG_HIGH = 16 ,
|
||||
ICACHE_TAG_LOW=6 ,
|
||||
ICACHE_TAG_DEPTH=1024
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic clk_override,
|
||||
input logic dec_tlu_core_ecc_disable,
|
||||
|
||||
input logic [31:3] ic_rw_addr,
|
||||
|
||||
input logic [3:0] ic_wr_en, // way
|
||||
input logic [3:0] ic_tag_valid,
|
||||
input logic ic_rd_en,
|
||||
|
||||
input logic [ICACHE_TAG_HIGH-1:2] ic_debug_addr, // Read/Write addresss to the Icache.
|
||||
input logic ic_debug_rd_en, // Icache debug rd
|
||||
input logic ic_debug_wr_en, // Icache debug wr
|
||||
input logic ic_debug_tag_array, // Debug tag array
|
||||
input logic [3:0] ic_debug_way, // Debug way. Rd or Wr.
|
||||
|
||||
|
||||
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
output logic [24:0] ictag_debug_rd_data,
|
||||
input logic [41:0] ic_debug_wr_data, // Debug wr cache.
|
||||
`else
|
||||
output logic [20:0] ictag_debug_rd_data,
|
||||
input logic [33:0] ic_debug_wr_data, // Debug wr cache.
|
||||
`endif
|
||||
output logic [3:0] ic_rd_hit,
|
||||
output logic ic_tag_perr,
|
||||
input logic scan_mode
|
||||
|
||||
) ;
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
logic [3:0] [24:0] ic_tag_data_raw;
|
||||
logic [3:0] [37:ICACHE_TAG_HIGH] w_tout;
|
||||
logic [24:0] ic_tag_wr_data ;
|
||||
logic [3:0] [31:0] ic_tag_corrected_data_unc;
|
||||
logic [3:0] [06:0] ic_tag_corrected_ecc_unc;
|
||||
logic [3:0] ic_tag_single_ecc_error;
|
||||
logic [3:0] ic_tag_double_ecc_error;
|
||||
`else
|
||||
logic [3:0] [20:0] ic_tag_data_raw;
|
||||
logic [3:0] [32:ICACHE_TAG_HIGH] w_tout;
|
||||
logic [20:0] ic_tag_wr_data ;
|
||||
`endif
|
||||
|
||||
logic [3:0] ic_tag_way_perr ;
|
||||
logic [3:0] ic_debug_rd_way_en ;
|
||||
logic [3:0] ic_debug_rd_way_en_ff ;
|
||||
|
||||
logic [ICACHE_TAG_HIGH-1:6] ic_rw_addr_q;
|
||||
logic [31:4] ic_rw_addr_ff;
|
||||
logic [3:0] ic_tag_wren ; // way
|
||||
logic [3:0] ic_tag_wren_q ; // way
|
||||
logic [3:0] ic_tag_clk ;
|
||||
logic [3:0] ic_tag_clken ;
|
||||
logic [3:0] ic_debug_wr_way_en; // debug wr_way
|
||||
|
||||
assign ic_tag_wren [3:0] = ic_wr_en[3:0] & {4{ic_rw_addr[5:3] == 3'b111}} ;
|
||||
assign ic_tag_clken[3:0] = {4{ic_rd_en | clk_override}} | ic_wr_en[3:0] | ic_debug_wr_way_en[3:0] | ic_debug_rd_way_en[3:0];
|
||||
|
||||
rvdff #(32-ICACHE_TAG_HIGH) adr_ff (.*,
|
||||
.din ({ic_rw_addr[31:ICACHE_TAG_HIGH]}),
|
||||
.dout({ic_rw_addr_ff[31:ICACHE_TAG_HIGH]}));
|
||||
|
||||
|
||||
localparam TOP_BITS = 21+ICACHE_TAG_HIGH-33 ;
|
||||
localparam NUM_WAYS=4 ;
|
||||
// tags
|
||||
|
||||
|
||||
|
||||
assign ic_debug_rd_way_en[3:0] = {4{ic_debug_rd_en & ic_debug_tag_array}} & ic_debug_way[3:0] ;
|
||||
assign ic_debug_wr_way_en[3:0] = {4{ic_debug_wr_en & ic_debug_tag_array}} & ic_debug_way[3:0] ;
|
||||
|
||||
assign ic_tag_wren_q[3:0] = ic_tag_wren[3:0] |
|
||||
ic_debug_wr_way_en[3:0] ;
|
||||
|
||||
if (ICACHE_TAG_HIGH == 12) begin: SMALLEST
|
||||
`ifdef RV_ICACHE_ECC
|
||||
logic [6:0] ic_tag_ecc;
|
||||
rvecc_encode tag_ecc_encode (
|
||||
.din ({{ICACHE_TAG_HIGH{1'b0}}, ic_rw_addr[31:ICACHE_TAG_HIGH]}),
|
||||
.ecc_out({ ic_tag_ecc[6:0]}));
|
||||
|
||||
assign ic_tag_wr_data[24:0] = (ic_debug_wr_en & ic_debug_tag_array) ?
|
||||
{ic_debug_wr_data[36:32], ic_debug_wr_data[31:12]} :
|
||||
{ic_tag_ecc[4:0], ic_rw_addr[31:ICACHE_TAG_HIGH]} ;
|
||||
`else
|
||||
logic ic_tag_parity ;
|
||||
rveven_paritygen #(32-ICACHE_TAG_HIGH) pargen (.data_in (ic_rw_addr[31:ICACHE_TAG_HIGH]),
|
||||
.parity_out(ic_tag_parity));
|
||||
|
||||
assign ic_tag_wr_data[20:0] = (ic_debug_wr_en & ic_debug_tag_array) ?
|
||||
{ic_debug_wr_data[32], ic_debug_wr_data[31:12]} :
|
||||
{ic_tag_parity, ic_rw_addr[31:ICACHE_TAG_HIGH]} ;
|
||||
`endif
|
||||
end else begin: OTHERS
|
||||
`ifdef RV_ICACHE_ECC
|
||||
logic [6:0] ic_tag_ecc;
|
||||
rvecc_encode tag_ecc_encode (
|
||||
.din ({{ICACHE_TAG_HIGH{1'b0}}, ic_rw_addr[31:ICACHE_TAG_HIGH]}),
|
||||
.ecc_out({ ic_tag_ecc[6:0]}));
|
||||
|
||||
assign ic_tag_wr_data[24:0] = (ic_debug_wr_en & ic_debug_tag_array) ?
|
||||
{ic_debug_wr_data[36:32], ic_debug_wr_data[31:12]} :
|
||||
{ic_tag_ecc[4:0], {TOP_BITS{1'b0}},ic_rw_addr[31:ICACHE_TAG_HIGH]} ;
|
||||
|
||||
`else
|
||||
logic ic_tag_parity ;
|
||||
rveven_paritygen #(32-ICACHE_TAG_HIGH) pargen (.data_in (ic_rw_addr[31:ICACHE_TAG_HIGH]),
|
||||
.parity_out(ic_tag_parity));
|
||||
assign ic_tag_wr_data[20:0] = (ic_debug_wr_en & ic_debug_tag_array) ?
|
||||
{ic_debug_wr_data[32], ic_debug_wr_data[31:12]} :
|
||||
{ic_tag_parity, {TOP_BITS{1'b0}},ic_rw_addr[31:ICACHE_TAG_HIGH]} ;
|
||||
`endif
|
||||
end
|
||||
|
||||
assign ic_rw_addr_q[ICACHE_TAG_HIGH-1:6] = (ic_debug_rd_en | ic_debug_wr_en) ?
|
||||
ic_debug_addr[ICACHE_TAG_HIGH-1:6] :
|
||||
ic_rw_addr[ICACHE_TAG_HIGH-1:6] ;
|
||||
|
||||
|
||||
rvdff #(4) tag_rd_wy_ff (.*,
|
||||
.din ({ic_debug_rd_way_en[3:0]}),
|
||||
.dout({ic_debug_rd_way_en_ff[3:0]}));
|
||||
|
||||
|
||||
|
||||
|
||||
for (genvar i=0; i<NUM_WAYS; i++) begin: WAYS
|
||||
rvclkhdr ic_tag_c1_cgc ( .en(ic_tag_clken[i]), .l1clk(ic_tag_clk[i]), .* );
|
||||
if (ICACHE_TAG_DEPTH == 64 ) begin : ICACHE_SZ_16
|
||||
`ifdef RV_ICACHE_ECC
|
||||
ram_64x25 ic_way_tag (
|
||||
.CLK(ic_tag_clk[i]),
|
||||
.WE (ic_tag_wren_q[i]),
|
||||
.D (ic_tag_wr_data[24:0]),
|
||||
.ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:ICACHE_TAG_LOW]),
|
||||
.Q (ic_tag_data_raw[i][24:0])
|
||||
);
|
||||
|
||||
|
||||
assign w_tout[i][31:ICACHE_TAG_HIGH] = ic_tag_data_raw[i][31-ICACHE_TAG_HIGH:0] ;
|
||||
assign w_tout[i][36:32] = ic_tag_data_raw[i][24:20] ;
|
||||
|
||||
rvecc_decode ecc_decode (
|
||||
.en(~dec_tlu_core_ecc_disable),
|
||||
.sed_ded ( 1'b1 ), // 1 : means only detection
|
||||
.din({12'b0,ic_tag_data_raw[i][19:0]}),
|
||||
.ecc_in({2'b0, ic_tag_data_raw[i][24:20]}),
|
||||
.dout(ic_tag_corrected_data_unc[i][31:0]),
|
||||
.ecc_out(ic_tag_corrected_ecc_unc[i][6:0]),
|
||||
.single_ecc_error(ic_tag_single_ecc_error[i]),
|
||||
.double_ecc_error(ic_tag_double_ecc_error[i]));
|
||||
|
||||
assign ic_tag_way_perr[i]= ic_tag_single_ecc_error[i] | ic_tag_double_ecc_error[i] ;
|
||||
`else
|
||||
ram_64x21 ic_way_tag (
|
||||
.CLK(ic_tag_clk[i]),
|
||||
.WE (ic_tag_wren_q[i]),
|
||||
.D (ic_tag_wr_data[20:0]),
|
||||
.ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:ICACHE_TAG_LOW]),
|
||||
.Q (ic_tag_data_raw[i][20:0])
|
||||
);
|
||||
|
||||
assign w_tout[i][31:ICACHE_TAG_HIGH] = ic_tag_data_raw[i][31-ICACHE_TAG_HIGH:0] ;
|
||||
assign w_tout[i][32] = ic_tag_data_raw[i][20] ;
|
||||
|
||||
rveven_paritycheck #(32-ICACHE_TAG_HIGH) parcheck(.data_in (w_tout[i][31:ICACHE_TAG_HIGH]),
|
||||
.parity_in (w_tout[i][32]),
|
||||
.parity_err(ic_tag_way_perr[i]));
|
||||
`endif
|
||||
|
||||
end // block: ICACHE_SZ_16
|
||||
|
||||
else begin : tag_not_64
|
||||
`ifdef RV_ICACHE_ECC
|
||||
`RV_ICACHE_TAG_CELL ic_way_tag (
|
||||
.CLK(ic_tag_clk[i]),
|
||||
.WE (ic_tag_wren_q[i]),
|
||||
.D (ic_tag_wr_data[24:0]),
|
||||
.ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:ICACHE_TAG_LOW]),
|
||||
.Q (ic_tag_data_raw[i][24:0])
|
||||
);
|
||||
|
||||
assign w_tout[i][31:ICACHE_TAG_HIGH] = ic_tag_data_raw[i][31-ICACHE_TAG_HIGH:0] ;
|
||||
assign w_tout[i][36:32] = ic_tag_data_raw[i][24:20] ;
|
||||
|
||||
rvecc_decode ecc_decode (
|
||||
.en(~dec_tlu_core_ecc_disable),
|
||||
.sed_ded ( 1'b1 ), // 1 : if only need detection
|
||||
.din({12'b0,ic_tag_data_raw[i][19:0]}),
|
||||
.ecc_in({2'b0, ic_tag_data_raw[i][24:20]}),
|
||||
.dout(ic_tag_corrected_data_unc[i][31:0]),
|
||||
.ecc_out(ic_tag_corrected_ecc_unc[i][6:0]),
|
||||
.single_ecc_error(ic_tag_single_ecc_error[i]),
|
||||
.double_ecc_error(ic_tag_double_ecc_error[i]));
|
||||
|
||||
assign ic_tag_way_perr[i]= ic_tag_single_ecc_error[i] | ic_tag_double_ecc_error[i] ;
|
||||
|
||||
`else
|
||||
`RV_ICACHE_TAG_CELL ic_way_tag (
|
||||
.CLK(ic_tag_clk[i]),
|
||||
.WE (ic_tag_wren_q[i]),
|
||||
.D (ic_tag_wr_data[20:0]),
|
||||
.ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:ICACHE_TAG_LOW]),
|
||||
.Q ({ic_tag_data_raw[i][20:0]})
|
||||
);
|
||||
|
||||
assign w_tout[i][31:ICACHE_TAG_HIGH] = ic_tag_data_raw[i][31-ICACHE_TAG_HIGH:0] ;
|
||||
assign w_tout[i][32] = ic_tag_data_raw[i][20] ;
|
||||
|
||||
rveven_paritycheck #(32-ICACHE_TAG_HIGH) parcheck(.data_in (w_tout[i][31:ICACHE_TAG_HIGH]),
|
||||
.parity_in (w_tout[i][32]),
|
||||
.parity_err(ic_tag_way_perr[i]));
|
||||
|
||||
`endif
|
||||
end // block: tag_not_64
|
||||
end // block: WAYS
|
||||
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
assign ictag_debug_rd_data[24:0] = ({25{ic_debug_rd_way_en_ff[0]}} & ic_tag_data_raw[0] ) |
|
||||
({25{ic_debug_rd_way_en_ff[1]}} & ic_tag_data_raw[1] ) |
|
||||
({25{ic_debug_rd_way_en_ff[2]}} & ic_tag_data_raw[2] ) |
|
||||
({25{ic_debug_rd_way_en_ff[3]}} & ic_tag_data_raw[3] ) ;
|
||||
|
||||
`else
|
||||
assign ictag_debug_rd_data[20:0] = ({21{ic_debug_rd_way_en_ff[0]}} & ic_tag_data_raw[0] ) |
|
||||
({21{ic_debug_rd_way_en_ff[1]}} & ic_tag_data_raw[1] ) |
|
||||
({21{ic_debug_rd_way_en_ff[2]}} & ic_tag_data_raw[2] ) |
|
||||
({21{ic_debug_rd_way_en_ff[3]}} & ic_tag_data_raw[3] ) ;
|
||||
|
||||
`endif
|
||||
assign ic_rd_hit[0] = (w_tout[0][31:ICACHE_TAG_HIGH] == ic_rw_addr_ff[31:ICACHE_TAG_HIGH]) & ic_tag_valid[0];
|
||||
assign ic_rd_hit[1] = (w_tout[1][31:ICACHE_TAG_HIGH] == ic_rw_addr_ff[31:ICACHE_TAG_HIGH]) & ic_tag_valid[1];
|
||||
assign ic_rd_hit[2] = (w_tout[2][31:ICACHE_TAG_HIGH] == ic_rw_addr_ff[31:ICACHE_TAG_HIGH]) & ic_tag_valid[2];
|
||||
assign ic_rd_hit[3] = (w_tout[3][31:ICACHE_TAG_HIGH] == ic_rw_addr_ff[31:ICACHE_TAG_HIGH]) & ic_tag_valid[3];
|
||||
|
||||
assign ic_tag_perr = | (ic_tag_way_perr[3:0] & ic_tag_valid[3:0] ) ;
|
||||
endmodule
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
//********************************************************************************
|
||||
// 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.
|
||||
//********************************************************************************
|
||||
|
||||
//********************************************************************************
|
||||
// Icache closely coupled memory --- ICCM
|
||||
//********************************************************************************
|
||||
|
||||
module ifu_iccm_mem
|
||||
import swerv_types::*;
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic clk_override,
|
||||
|
||||
input logic iccm_wren,
|
||||
input logic iccm_rden,
|
||||
input logic [`RV_ICCM_BITS-1:2] iccm_rw_addr,
|
||||
|
||||
input logic [2:0] iccm_wr_size,
|
||||
input logic [77:0] iccm_wr_data,
|
||||
|
||||
|
||||
output logic [155:0] iccm_rd_data,
|
||||
input logic scan_mode
|
||||
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
|
||||
logic [ICCM_NUM_BANKS/4-1:0] wren_bank;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] rden_bank;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] iccm_hi0_clken;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] iccm_hi1_clken;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] iccm_lo0_clken;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] iccm_lo1_clken;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] iccm_hi0_clk ;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] iccm_hi1_clk ;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] iccm_lo0_clk ;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] iccm_lo1_clk ;
|
||||
|
||||
|
||||
logic [ICCM_NUM_BANKS/4-1:0] wren_bank_hi0;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] wren_bank_lo0;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] wren_bank_hi1;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] wren_bank_lo1;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] [ICCM_INDEX_BITS-1:0] addr_bank;
|
||||
|
||||
|
||||
|
||||
logic [ICCM_NUM_BANKS/4-1:0] [77:0] iccm_bank_dout_hi;
|
||||
logic [ICCM_NUM_BANKS/4-1:0] [77:0] iccm_bank_dout_lo;
|
||||
logic [5:4] iccm_rw_addr_q;
|
||||
// assign CLK = clk ;
|
||||
|
||||
|
||||
for (genvar i=0; i<ICCM_NUM_BANKS/4; i++) begin: mem_bank
|
||||
assign wren_bank[i] = iccm_wren & ( (iccm_rw_addr[ICCM_BANK_HI:4] == i) | (ICCM_BANK_BITS == 2));
|
||||
assign rden_bank[i] = iccm_rden & ( (iccm_rw_addr[ICCM_BANK_HI:4] == i) | (ICCM_BANK_BITS == 2));
|
||||
assign wren_bank_hi0[i] = wren_bank[i] & iccm_rw_addr[3] & (~iccm_rw_addr[2] | (iccm_wr_size[1:0] == 2'b11));
|
||||
assign wren_bank_hi1[i] = wren_bank[i] & iccm_rw_addr[3] & ( iccm_rw_addr[2] | (iccm_wr_size[1:0] == 2'b11));
|
||||
assign wren_bank_lo0[i] = wren_bank[i] & ~iccm_rw_addr[3] & (~iccm_rw_addr[2] | (iccm_wr_size[1:0] == 2'b11));
|
||||
assign wren_bank_lo1[i] = wren_bank[i] & ~iccm_rw_addr[3] & ( iccm_rw_addr[2] | (iccm_wr_size[1:0] == 2'b11));
|
||||
|
||||
assign iccm_hi0_clken[i] = wren_bank_hi0[i] | (rden_bank[i] | clk_override); // Do not override the writes
|
||||
assign iccm_hi1_clken[i] = wren_bank_hi1[i] | (rden_bank[i] | clk_override); // Do not override the writes
|
||||
assign iccm_lo0_clken[i] = wren_bank_lo0[i] | (rden_bank[i] | clk_override); // Do not override the writes
|
||||
assign iccm_lo1_clken[i] = wren_bank_lo1[i] | (rden_bank[i] | clk_override); // Do not override the writes
|
||||
|
||||
rvclkhdr iccm_hi0_c1_cgc ( .en(iccm_hi0_clken[i]), .l1clk(iccm_hi0_clk[i]), .* );
|
||||
rvclkhdr iccm_hi1_c1_cgc ( .en(iccm_hi1_clken[i]), .l1clk(iccm_hi1_clk[i]), .* );
|
||||
rvclkhdr iccm_lo0_c1_cgc ( .en(iccm_lo0_clken[i]), .l1clk(iccm_lo0_clk[i]), .* );
|
||||
rvclkhdr iccm_lo1_c1_cgc ( .en(iccm_lo1_clken[i]), .l1clk(iccm_lo1_clk[i]), .* );
|
||||
|
||||
|
||||
assign addr_bank[i][ICCM_INDEX_BITS-1:0] = iccm_rw_addr[ICCM_BITS-1:(ICCM_BANK_BITS+2)];
|
||||
|
||||
`RV_ICCM_DATA_CELL iccm_bank_hi0 (
|
||||
// Primary ports
|
||||
.CLK(iccm_hi0_clk[i]),
|
||||
.WE(wren_bank_hi0[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_wr_data[38:0]),
|
||||
.Q(iccm_bank_dout_hi[i][38:0])
|
||||
);
|
||||
`RV_ICCM_DATA_CELL iccm_bank_hi1 (
|
||||
// Primary ports
|
||||
.CLK(iccm_hi1_clk[i]),
|
||||
.WE(wren_bank_hi1[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_wr_data[77:39]),
|
||||
.Q(iccm_bank_dout_hi[i][77:39])
|
||||
);
|
||||
`RV_ICCM_DATA_CELL iccm_bank_lo0 (
|
||||
// Primary ports
|
||||
.CLK(iccm_lo0_clk[i]),
|
||||
.WE(wren_bank_lo0[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_wr_data[38:0]),
|
||||
.Q(iccm_bank_dout_lo[i][38:0])
|
||||
);
|
||||
`RV_ICCM_DATA_CELL iccm_bank_lo1 (
|
||||
// Primary ports
|
||||
.CLK(iccm_lo1_clk[i]),
|
||||
.WE(wren_bank_lo1[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_wr_data[77:39]),
|
||||
.Q(iccm_bank_dout_lo[i][77:39])
|
||||
);
|
||||
|
||||
|
||||
end : mem_bank
|
||||
|
||||
|
||||
assign iccm_rd_data[155:0] = (ICCM_BANK_BITS == 2) ? {iccm_bank_dout_hi[0][77:0], iccm_bank_dout_lo[0][77:0]} :
|
||||
{ iccm_bank_dout_hi[iccm_rw_addr_q[ICCM_BANK_HI:4]][77:0], iccm_bank_dout_lo[iccm_rw_addr_q[ICCM_BANK_HI:4]][77:0] };
|
||||
|
||||
|
||||
if (ICCM_BANK_BITS == 2) begin
|
||||
assign iccm_rw_addr_q[5:4] = '0;
|
||||
end
|
||||
// 8 banks, each bank 8B, we index as 4 banks
|
||||
else begin
|
||||
rvdff #(2) rd_addr_ff (.*, .din(iccm_rw_addr[5:4]), .dout(iccm_rw_addr_q[5:4]) );
|
||||
end
|
||||
endmodule // ifu_iccm_mem
|
||||
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
// 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.
|
||||
|
||||
//********************************************************************************
|
||||
// ifu_ifc_ctl.sv
|
||||
// Function: Fetch pipe control
|
||||
//
|
||||
// Comments:
|
||||
//********************************************************************************
|
||||
|
||||
module ifu_ifc_ctl
|
||||
(
|
||||
input logic clk,
|
||||
input logic free_clk,
|
||||
input logic active_clk,
|
||||
|
||||
input logic clk_override, // overrides clock gating
|
||||
input logic rst_l, // reset enable, from core pin
|
||||
input logic scan_mode, // scan
|
||||
|
||||
input logic ic_hit_f2, // Icache hit
|
||||
input logic ic_crit_wd_rdy, // Crit word ready to be forwarded
|
||||
input logic ifu_ic_mb_empty, // Miss buffer empty
|
||||
|
||||
input logic ifu_fb_consume1, // Aligner consumed 1 fetch buffer
|
||||
input logic ifu_fb_consume2, // Aligner consumed 2 fetch buffers
|
||||
|
||||
input logic dec_tlu_flush_noredir_wb, // Don't fetch on flush
|
||||
input logic dec_tlu_dbg_halted, // Core is halted
|
||||
input logic dec_tlu_pmu_fw_halted, // Core is halted
|
||||
input logic exu_flush_final, // FLush
|
||||
input logic [31:1] exu_flush_path_final, // Flush path
|
||||
|
||||
input logic ifu_bp_kill_next_f2, // kill next fetch, taken target found
|
||||
input logic [31:1] ifu_bp_btb_target_f2, // predicted target PC
|
||||
|
||||
input logic ic_dma_active, // IC DMA active, stop fetching
|
||||
input logic ic_write_stall, // IC is writing, stop fetching
|
||||
input logic dma_iccm_stall_any, // force a stall in the fetch pipe for DMA ICCM access
|
||||
|
||||
input logic [31:0] dec_tlu_mrac_ff , // side_effect and cacheable for each region
|
||||
|
||||
output logic ifc_fetch_uncacheable_f1, // fetch to uncacheable address as determined by MRAC
|
||||
|
||||
output logic [31:1] ifc_fetch_addr_f1, // fetch addr F1
|
||||
output logic [31:1] ifc_fetch_addr_f2, // fetch addr F2
|
||||
|
||||
output logic ifc_fetch_req_f1, // fetch request valid F1
|
||||
output logic ifc_fetch_req_f1_raw, // for clock-gating in mem_ctl
|
||||
output logic ifc_fetch_req_f2, // fetch request valid F2
|
||||
|
||||
output logic ifu_pmu_fetch_stall, // pmu event measuring fetch stall
|
||||
|
||||
output logic ifc_iccm_access_f1, // fetch to ICCM region
|
||||
output logic ifc_region_acc_fault_f1, // fetch access fault
|
||||
output logic ifc_dma_access_ok // fetch is not accessing the ICCM, DMA can proceed
|
||||
|
||||
);
|
||||
|
||||
|
||||
logic [31:1] fetch_addr_bf, miss_addr, ifc_fetch_addr_f1_raw;
|
||||
logic [31:1] fetch_addr_next;
|
||||
logic [31:1] miss_addr_ns;
|
||||
logic [4:0] cacheable_select;
|
||||
logic [3:0] fb_write_f1, fb_write_ns;
|
||||
|
||||
logic ifc_fetch_req_bf;
|
||||
logic overflow_nc;
|
||||
logic fb_full_f1_ns, fb_full_f1;
|
||||
logic fb_right, fb_right2, fb_right3, fb_left, wfm, fetch_ns, idle;
|
||||
logic fetch_req_f2_ns;
|
||||
logic missff_en;
|
||||
logic fetch_crit_word, ic_crit_wd_rdy_d1, fetch_crit_word_d1, fetch_crit_word_d2;
|
||||
logic reset_delayed, reset_detect, reset_detected;
|
||||
logic sel_last_addr_bf, sel_miss_addr_bf, sel_btb_addr_bf, sel_next_addr_bf;
|
||||
logic miss_f2, miss_a;
|
||||
logic flush_fb, dma_iccm_stall_any_f;
|
||||
logic dec_tlu_halted_f;
|
||||
logic mb_empty_mod, goto_idle, leave_idle;
|
||||
logic ic_crit_wd_rdy_mod;
|
||||
logic miss_sel_flush;
|
||||
logic miss_sel_f2;
|
||||
logic miss_sel_f1;
|
||||
logic miss_sel_bf;
|
||||
logic fetch_bf_en;
|
||||
logic ifc_fetch_req_f2_raw;
|
||||
|
||||
logic ifc_f2_clk;
|
||||
rvclkhdr ifu_fa2_cgc ( .en(ifc_fetch_req_f1 | clk_override), .l1clk(ifc_f2_clk), .* );
|
||||
|
||||
// FSM assignment
|
||||
typedef enum logic [1:0] { IDLE=2'b00, FETCH=2'b01, STALL=2'b10, WFM=2'b11} state_t;
|
||||
state_t state, next_state;
|
||||
|
||||
logic dma_stall;
|
||||
assign dma_stall = ic_dma_active | dma_iccm_stall_any_f;
|
||||
|
||||
// detect a reset and start fetching the reset vector
|
||||
rvdff #(2) reset_ff (.*, .clk(free_clk), .din({1'b1, reset_detect}), .dout({reset_detect, reset_detected}));
|
||||
|
||||
assign reset_delayed = reset_detect ^ reset_detected;
|
||||
|
||||
rvdff #(3) ran_ff (.*, .clk(free_clk), .din({dma_iccm_stall_any, dec_tlu_dbg_halted | dec_tlu_pmu_fw_halted, miss_f2}), .dout({dma_iccm_stall_any_f, dec_tlu_halted_f, miss_a}));
|
||||
|
||||
// If crit word fetch is blocked, try again
|
||||
assign ic_crit_wd_rdy_mod = ic_crit_wd_rdy & ~(fetch_crit_word_d2 & ~ifc_fetch_req_f2);
|
||||
|
||||
// For Ifills, we fetch the critical word. Needed for perf and for rom bypass
|
||||
assign fetch_crit_word = ic_crit_wd_rdy_mod & ~ic_crit_wd_rdy_d1 & ~exu_flush_final & ~ic_write_stall;
|
||||
|
||||
assign missff_en = exu_flush_final | (~ic_hit_f2 & ifc_fetch_req_f2) | ifu_bp_kill_next_f2 | fetch_crit_word_d1 | ifu_bp_kill_next_f2 | (ifc_fetch_req_f2 & ~ifc_fetch_req_f1 & ~fetch_crit_word_d2);
|
||||
assign miss_sel_flush = exu_flush_final & (((wfm | idle) & ~fetch_crit_word_d1) | dma_stall | ic_write_stall);
|
||||
assign miss_sel_f2 = ~exu_flush_final & ~ic_hit_f2 & ifc_fetch_req_f2;
|
||||
assign miss_sel_f1 = ~exu_flush_final & ~miss_sel_f2 & ~ifc_fetch_req_f1 & ifc_fetch_req_f2 & ~fetch_crit_word_d2 & ~ifu_bp_kill_next_f2;
|
||||
assign miss_sel_bf = ~miss_sel_f2 & ~miss_sel_f1 & ~miss_sel_flush;
|
||||
|
||||
assign miss_addr_ns[31:1] = ( ({31{miss_sel_flush}} & exu_flush_path_final[31:1]) |
|
||||
({31{miss_sel_f2}} & ifc_fetch_addr_f2[31:1]) |
|
||||
({31{miss_sel_f1}} & ifc_fetch_addr_f1[31:1]) |
|
||||
({31{miss_sel_bf}} & fetch_addr_bf[31:1]));
|
||||
|
||||
|
||||
|
||||
rvdffe #(31) faddmiss_ff (.*, .en(missff_en), .din(miss_addr_ns[31:1]), .dout(miss_addr[31:1]));
|
||||
|
||||
|
||||
// Fetch address mux
|
||||
// - flush
|
||||
// - Miss *or* flush during WFM (icache miss buffer is blocking)
|
||||
// - Sequential
|
||||
|
||||
assign sel_last_addr_bf = ~miss_sel_flush & ~ifc_fetch_req_f1 & ifc_fetch_req_f2 & ~ifu_bp_kill_next_f2;
|
||||
assign sel_miss_addr_bf = ~miss_sel_flush & ~ifu_bp_kill_next_f2 & ~ifc_fetch_req_f1 & ~ifc_fetch_req_f2;
|
||||
assign sel_btb_addr_bf = ~miss_sel_flush & ifu_bp_kill_next_f2;
|
||||
assign sel_next_addr_bf = ~miss_sel_flush & ifc_fetch_req_f1;
|
||||
|
||||
|
||||
assign fetch_addr_bf[31:1] = ( ({31{miss_sel_flush}} & exu_flush_path_final[31:1]) | // FLUSH path
|
||||
({31{sel_miss_addr_bf}} & miss_addr[31:1]) | // MISS path
|
||||
({31{sel_btb_addr_bf}} & {ifu_bp_btb_target_f2[31:1]})| // BTB target
|
||||
({31{sel_last_addr_bf}} & {ifc_fetch_addr_f1[31:1]})| // Last cycle
|
||||
({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path
|
||||
|
||||
assign {overflow_nc, fetch_addr_next[31:1]} = {({1'b0, ifc_fetch_addr_f1[31:4]} + 29'b1), 3'b0};
|
||||
|
||||
assign ifc_fetch_req_bf = (fetch_ns | fetch_crit_word) ;
|
||||
assign fetch_bf_en = (fetch_ns | fetch_crit_word);
|
||||
|
||||
assign miss_f2 = ifc_fetch_req_f2 & ~ic_hit_f2;
|
||||
|
||||
assign mb_empty_mod = (ifu_ic_mb_empty | exu_flush_final) & ~dma_stall & ~miss_f2 & ~miss_a;
|
||||
|
||||
// Halt flushes and takes us to IDLE
|
||||
assign goto_idle = exu_flush_final & dec_tlu_flush_noredir_wb;
|
||||
// If we're in IDLE, and we get a flush, goto FETCH
|
||||
assign leave_idle = exu_flush_final & ~dec_tlu_flush_noredir_wb & idle;
|
||||
|
||||
//.i 7
|
||||
//.o 2
|
||||
//.ilb state[1] state[0] reset_delayed miss_f2 mb_empty_mod goto_idle leave_idle
|
||||
//.ob next_state[1] next_state[0]
|
||||
//.type fr
|
||||
//
|
||||
//# fetch 01, stall 10, wfm 11, idle 00
|
||||
//-- 1---- 01
|
||||
//-- 0--1- 00
|
||||
//00 0--00 00
|
||||
//00 0--01 01
|
||||
//
|
||||
//01 01-0- 11
|
||||
//01 00-0- 01
|
||||
//
|
||||
//11 0-10- 01
|
||||
//11 0-00- 11
|
||||
|
||||
assign next_state[1] = (~state[1] & state[0] & ~reset_delayed & miss_f2 & ~goto_idle) |
|
||||
(state[1] & ~reset_delayed & ~mb_empty_mod & ~goto_idle);
|
||||
|
||||
assign next_state[0] = (~goto_idle & leave_idle) | (state[0] & ~goto_idle) |
|
||||
(reset_delayed);
|
||||
|
||||
assign flush_fb = exu_flush_final;
|
||||
|
||||
// model fb write logic to mass balance the fetch buffers
|
||||
assign fb_right = (~ifu_fb_consume1 & ~ifu_fb_consume2 & miss_f2) | // F2 cache miss, repair mass balance
|
||||
( ifu_fb_consume1 & ~ifu_fb_consume2 & ~ifc_fetch_req_f1 & ~miss_f2) | // Consumed and no new fetch
|
||||
(ifu_fb_consume2 & ifc_fetch_req_f1 & ~miss_f2); // Consumed 2 and new fetch
|
||||
|
||||
|
||||
assign fb_right2 = (ifu_fb_consume1 & ~ifu_fb_consume2 & miss_f2) | // consume 1 and miss 1
|
||||
(ifu_fb_consume2 & ~ifc_fetch_req_f1); // Consumed 2 and no new fetch
|
||||
|
||||
assign fb_right3 = (ifu_fb_consume2 & miss_f2); // consume 2 and miss
|
||||
|
||||
assign fb_left = ifc_fetch_req_f1 & ~(ifu_fb_consume1 | ifu_fb_consume2) & ~miss_f2;
|
||||
|
||||
assign fb_write_ns[3:0] = ( ({4{(flush_fb & ~ifc_fetch_req_f1)}} & 4'b0001) |
|
||||
({4{(flush_fb & ifc_fetch_req_f1)}} & 4'b0010) |
|
||||
({4{~flush_fb & fb_right }} & {1'b0, fb_write_f1[3:1]}) |
|
||||
({4{~flush_fb & fb_right2}} & {2'b0, fb_write_f1[3:2]}) |
|
||||
({4{~flush_fb & fb_right3}} & {3'b0, fb_write_f1[3]} ) |
|
||||
({4{~flush_fb & fb_left }} & {fb_write_f1[2:0], 1'b0}) |
|
||||
({4{~flush_fb & ~fb_right & ~fb_right2 & ~fb_left & ~fb_right3}} & fb_write_f1[3:0]));
|
||||
|
||||
|
||||
assign fb_full_f1_ns = fb_write_ns[3];
|
||||
|
||||
assign idle = state[1:0] == IDLE;
|
||||
assign wfm = state[1:0] == WFM;
|
||||
assign fetch_ns = next_state[1:0] == FETCH;
|
||||
|
||||
rvdff #(2) fsm_ff (.*, .clk(active_clk), .din({next_state[1:0]}), .dout({state[1:0]}));
|
||||
rvdff #(5) fbwrite_ff (.*, .clk(active_clk), .din({fb_full_f1_ns, fb_write_ns[3:0]}), .dout({fb_full_f1, fb_write_f1[3:0]}));
|
||||
|
||||
assign ifu_pmu_fetch_stall = wfm |
|
||||
(ifc_fetch_req_f1_raw &
|
||||
( (fb_full_f1 & ~(ifu_fb_consume2 | ifu_fb_consume1 | exu_flush_final)) |
|
||||
dma_stall));
|
||||
// BTB hit kills this fetch
|
||||
assign ifc_fetch_req_f1 = ( ifc_fetch_req_f1_raw &
|
||||
~ifu_bp_kill_next_f2 &
|
||||
~(fb_full_f1 & ~(ifu_fb_consume2 | ifu_fb_consume1 | exu_flush_final)) &
|
||||
~dma_stall &
|
||||
~ic_write_stall &
|
||||
~dec_tlu_flush_noredir_wb );
|
||||
|
||||
// kill F2 request if we flush or if the prior fetch missed the cache/mem
|
||||
assign fetch_req_f2_ns = ifc_fetch_req_f1 & ~miss_f2;
|
||||
|
||||
rvdff #(2) req_ff (.*, .clk(active_clk), .din({ifc_fetch_req_bf, fetch_req_f2_ns}), .dout({ifc_fetch_req_f1_raw, ifc_fetch_req_f2_raw}));
|
||||
|
||||
assign ifc_fetch_req_f2 = ifc_fetch_req_f2_raw & ~exu_flush_final;
|
||||
|
||||
rvdffe #(31) faddrf1_ff (.*, .en(fetch_bf_en), .din(fetch_addr_bf[31:1]), .dout(ifc_fetch_addr_f1_raw[31:1]));
|
||||
rvdff #(31) faddrf2_ff (.*, .clk(ifc_f2_clk), .din(ifc_fetch_addr_f1[31:1]), .dout(ifc_fetch_addr_f2[31:1]));
|
||||
|
||||
assign ifc_fetch_addr_f1[31:1] = ( ({31{exu_flush_final}} & exu_flush_path_final[31:1]) |
|
||||
({31{~exu_flush_final}} & ifc_fetch_addr_f1_raw[31:1]));
|
||||
|
||||
rvdff #(3) iccrit_ff (.*, .clk(active_clk), .din({ic_crit_wd_rdy_mod, fetch_crit_word, fetch_crit_word_d1}),
|
||||
.dout({ic_crit_wd_rdy_d1, fetch_crit_word_d1, fetch_crit_word_d2}));
|
||||
|
||||
`ifdef RV_ICCM_ENABLE
|
||||
logic iccm_acc_in_region_f1;
|
||||
logic iccm_acc_in_range_f1;
|
||||
rvrangecheck #( .CCM_SADR (`RV_ICCM_SADR),
|
||||
.CCM_SIZE (`RV_ICCM_SIZE) ) iccm_rangecheck (
|
||||
.addr ({ifc_fetch_addr_f1[31:1],1'b0}) ,
|
||||
.in_range (iccm_acc_in_range_f1) ,
|
||||
.in_region(iccm_acc_in_region_f1)
|
||||
);
|
||||
|
||||
assign ifc_iccm_access_f1 = iccm_acc_in_range_f1 ;
|
||||
|
||||
assign ifc_dma_access_ok = ( (~ifc_iccm_access_f1 |
|
||||
(fb_full_f1 & ~(ifu_fb_consume2 | ifu_fb_consume1)) |
|
||||
wfm |
|
||||
idle ) & ~exu_flush_final) |
|
||||
dma_iccm_stall_any_f;
|
||||
|
||||
assign ifc_region_acc_fault_f1 = ~iccm_acc_in_range_f1 & iccm_acc_in_region_f1 ;
|
||||
`else
|
||||
assign ifc_iccm_access_f1 = 1'b0 ;
|
||||
assign ifc_dma_access_ok = 1'b0 ;
|
||||
assign ifc_region_acc_fault_f1 = 1'b0 ;
|
||||
`endif
|
||||
|
||||
assign cacheable_select[4:0] = {ifc_fetch_addr_f1[31:28] , 1'b0 } ;
|
||||
assign ifc_fetch_uncacheable_f1 = ~dec_tlu_mrac_ff[cacheable_select] ; // bit 0 of each region description is the cacheable bit
|
||||
|
||||
endmodule // ifu_ifc_ctl
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,65 @@
|
|||
// 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.
|
||||
|
||||
// BUILD_ICACHE_SIZE = { 32, 64, 128, 256 }
|
||||
//`define BUILD_ICACHE_SIZE 256
|
||||
|
||||
// BUILD_ICACHE_LINE_SIZE = { 16 }
|
||||
//`define BUILD_ICACHE_LINE_SIZE 64
|
||||
|
||||
//// BUILD_BTB_SIZE = {256, 512}
|
||||
//`define BUILD_BTB_SIZE 512
|
||||
////`define BUILD_ICCM_SIZE 128
|
||||
//
|
||||
////----------------------------------------------------------------------
|
||||
//// For configurable BTB size
|
||||
//`define BTB_INDEX1_HI ((`BUILD_BTB_SIZE==256) ? 9 : 10)
|
||||
//`define BTB_INDEX1_LO 4
|
||||
//`define BTB_INDEX2_HI ((`BUILD_BTB_SIZE==256) ? 15 : 17)
|
||||
//`define BTB_INDEX2_LO ((`BUILD_BTB_SIZE==256) ? 10 : 11)
|
||||
//`define BTB_INDEX3_HI ((`BUILD_BTB_SIZE==256) ? 21 : 24)
|
||||
//`define BTB_INDEX3_LO ((`BUILD_BTB_SIZE==256) ? 16 : 18)
|
||||
//`define BTB_ADDR_HI ((`BUILD_BTB_SIZE==256) ? 9 : 10)
|
||||
//`define BTB_ADDR_LO 4
|
||||
//// ----------------------------------------------------------------------
|
||||
|
||||
|
||||
// BUILD_DTCM_SADDR
|
||||
//`define BUILD_DTCM_SADR 32'hf0000000
|
||||
// BUILD_DTCM_EADDR = {256, 512}
|
||||
//`define BUILD_DTCM_EADR 32'hf0020000
|
||||
|
||||
// BUILD_ITCM_SADDR
|
||||
//`define BUILD_ITCM_SADR 32'hee000000
|
||||
// BUILD_ITCM_EADDR = {256, 512}
|
||||
//`define BUILD_ITCM_EADR 32'hee020000
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//`define TOTAL_INT 256
|
||||
//`define INTPEND_BASE_ADDR 32'hcc000400
|
||||
//`define INTENABLE_BASE_ADDR 32'hcc000800
|
||||
//`define INTPRIORITY_BASE_ADDR 32'hcc000c00
|
||||
//`define CLAIMID_ADDR 32'hcc001000
|
||||
//`define PRITHRESH_ADDR 32'hcc001010
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
// Enable assertions
|
||||
//`define ASSERT_ON
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// 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.
|
||||
|
||||
localparam TOTAL_INT = `RV_PIC_TOTAL_INT_PLUS1;
|
||||
|
||||
localparam DCCM_BITS = `RV_DCCM_BITS;
|
||||
localparam DCCM_BANK_BITS = `RV_DCCM_BANK_BITS;
|
||||
localparam DCCM_NUM_BANKS = `RV_DCCM_NUM_BANKS;
|
||||
localparam DCCM_DATA_WIDTH = `RV_DCCM_DATA_WIDTH;
|
||||
localparam DCCM_FDATA_WIDTH = `RV_DCCM_FDATA_WIDTH;
|
||||
localparam DCCM_BYTE_WIDTH = `RV_DCCM_BYTE_WIDTH;
|
||||
localparam DCCM_ECC_WIDTH = `RV_DCCM_ECC_WIDTH;
|
||||
|
||||
localparam LSU_RDBUF_DEPTH = `RV_LSU_NUM_NBLOAD;
|
||||
localparam DMA_BUF_DEPTH = `RV_DMA_BUF_DEPTH;
|
||||
localparam LSU_STBUF_DEPTH = `RV_LSU_STBUF_DEPTH;
|
||||
localparam LSU_SB_BITS = `RV_LSU_SB_BITS;
|
||||
|
||||
localparam DEC_INSTBUF_DEPTH = `RV_DEC_INSTBUF_DEPTH;
|
||||
|
||||
localparam ICCM_SIZE = `RV_ICCM_SIZE;
|
||||
localparam ICCM_BITS = `RV_ICCM_BITS;
|
||||
localparam ICCM_NUM_BANKS = `RV_ICCM_NUM_BANKS;
|
||||
localparam ICCM_BANK_BITS = `RV_ICCM_BANK_BITS;
|
||||
localparam ICCM_INDEX_BITS = `RV_ICCM_INDEX_BITS;
|
||||
localparam ICCM_BANK_HI = 4 + (`RV_ICCM_BANK_BITS/4);
|
||||
|
||||
localparam ICACHE_TAG_HIGH = `RV_ICACHE_TAG_HIGH;
|
||||
localparam ICACHE_TAG_LOW = `RV_ICACHE_TAG_LOW;
|
||||
localparam ICACHE_IC_DEPTH = `RV_ICACHE_IC_DEPTH;
|
||||
localparam ICACHE_TAG_DEPTH = `RV_ICACHE_TAG_DEPTH;
|
||||
|
||||
localparam LSU_BUS_TAG = `RV_LSU_BUS_TAG;
|
||||
localparam DMA_BUS_TAG = `RV_DMA_BUS_TAG;
|
||||
localparam SB_BUS_TAG = `RV_SB_BUS_TAG;
|
||||
|
||||
localparam IFU_BUS_TAG = `RV_IFU_BUS_TAG;
|
||||
|
||||
|
|
@ -0,0 +1,335 @@
|
|||
// 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.
|
||||
package swerv_types;
|
||||
|
||||
// performance monitor stuff
|
||||
typedef struct packed {
|
||||
logic [2:0] trace_rv_i_valid_ip;
|
||||
logic [95:0] trace_rv_i_insn_ip;
|
||||
logic [95:0] trace_rv_i_address_ip;
|
||||
logic [2:0] trace_rv_i_exception_ip;
|
||||
logic [4:0] trace_rv_i_ecause_ip;
|
||||
logic [2:0] trace_rv_i_interrupt_ip;
|
||||
logic [31:0] trace_rv_i_tval_ip;
|
||||
} trace_pkt_t;
|
||||
|
||||
|
||||
typedef enum logic [3:0] {
|
||||
NULL = 4'b0000,
|
||||
MUL = 4'b0001,
|
||||
LOAD = 4'b0010,
|
||||
STORE = 4'b0011,
|
||||
ALU = 4'b0100,
|
||||
CSRREAD = 4'b0101,
|
||||
CSRWRITE = 4'b0110,
|
||||
CSRRW = 4'b0111,
|
||||
EBREAK = 4'b1000,
|
||||
ECALL = 4'b1001,
|
||||
FENCE = 4'b1010,
|
||||
FENCEI = 4'b1011,
|
||||
MRET = 4'b1100,
|
||||
CONDBR = 4'b1101,
|
||||
JAL = 4'b1110
|
||||
} inst_t;
|
||||
|
||||
typedef struct packed {
|
||||
`ifdef RV_ICACHE_ECC
|
||||
logic [39:0] ecc;
|
||||
`else
|
||||
logic [7:0] parity;
|
||||
`endif
|
||||
} icache_err_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic wb;
|
||||
logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] tag;
|
||||
logic [4:0] rd;
|
||||
} load_cam_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic pc0_call;
|
||||
logic pc0_ret;
|
||||
logic pc0_pc4;
|
||||
logic pc1_call;
|
||||
logic pc1_ret;
|
||||
logic pc1_pc4;
|
||||
} rets_pkt_t;
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic [11:0] toffset;
|
||||
logic [1:0] hist;
|
||||
logic br_error;
|
||||
logic br_start_error;
|
||||
logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] index;
|
||||
logic [1:0] bank;
|
||||
logic [31:1] prett; // predicted ret target
|
||||
logic [`RV_BHT_GHR_RANGE] fghr;
|
||||
`ifdef RV_BTB_48
|
||||
logic [1:0] way;
|
||||
`else
|
||||
logic way;
|
||||
`endif
|
||||
logic ret;
|
||||
logic [`RV_BTB_BTAG_SIZE-1:0] btag;
|
||||
} br_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic [1:0] hist;
|
||||
logic br_error;
|
||||
logic br_start_error;
|
||||
logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] index;
|
||||
logic [1:0] bank;
|
||||
logic [`RV_BHT_GHR_RANGE] fghr;
|
||||
`ifdef RV_BTB_48
|
||||
logic [1:0] way;
|
||||
`else
|
||||
logic way;
|
||||
`endif
|
||||
logic middle;
|
||||
} br_tlu_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic misp;
|
||||
logic ataken;
|
||||
logic boffset;
|
||||
logic pc4;
|
||||
logic [1:0] hist;
|
||||
logic [11:0] toffset;
|
||||
logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] index;
|
||||
logic [1:0] bank;
|
||||
logic valid;
|
||||
logic br_error;
|
||||
logic br_start_error;
|
||||
logic [31:1] prett;
|
||||
logic pcall;
|
||||
logic pret;
|
||||
logic pja;
|
||||
logic [`RV_BTB_BTAG_SIZE-1:0] btag;
|
||||
logic [`RV_BHT_GHR_RANGE] fghr;
|
||||
`ifdef RV_BTB_48
|
||||
logic [1:0] way;
|
||||
`else
|
||||
logic way;
|
||||
`endif
|
||||
} predict_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic legal;
|
||||
logic icaf;
|
||||
logic icaf_f1;
|
||||
logic perr;
|
||||
logic sbecc;
|
||||
logic fence_i;
|
||||
logic [3:0] i0trigger;
|
||||
logic [3:0] i1trigger;
|
||||
inst_t pmu_i0_itype; // pmu - instruction type
|
||||
inst_t pmu_i1_itype; // pmu - instruction type
|
||||
logic pmu_i0_br_unpred; // pmu
|
||||
logic pmu_i1_br_unpred; // pmu
|
||||
logic pmu_divide;
|
||||
logic pmu_lsu_misaligned;
|
||||
} trap_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [4:0] i0rd;
|
||||
logic i0mul;
|
||||
logic i0load;
|
||||
logic i0store;
|
||||
logic i0div;
|
||||
logic i0v;
|
||||
logic i0valid;
|
||||
logic i0secondary;
|
||||
logic [1:0] i0rs1bype2;
|
||||
logic [1:0] i0rs2bype2;
|
||||
logic [3:0] i0rs1bype3;
|
||||
logic [3:0] i0rs2bype3;
|
||||
logic [4:0] i1rd;
|
||||
logic i1mul;
|
||||
logic i1load;
|
||||
logic i1store;
|
||||
logic i1v;
|
||||
logic i1valid;
|
||||
logic csrwen;
|
||||
logic csrwonly;
|
||||
logic [11:0] csrwaddr;
|
||||
logic i1secondary;
|
||||
logic [1:0] i1rs1bype2;
|
||||
logic [1:0] i1rs2bype2;
|
||||
logic [6:0] i1rs1bype3;
|
||||
logic [6:0] i1rs2bype3;
|
||||
} dest_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic mul;
|
||||
logic load;
|
||||
logic sec;
|
||||
logic alu;
|
||||
} class_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic [4:0] rs1;
|
||||
logic [4:0] rs2;
|
||||
logic [4:0] rd;
|
||||
} reg_pkt_t;
|
||||
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic land;
|
||||
logic lor;
|
||||
logic lxor;
|
||||
logic sll;
|
||||
logic srl;
|
||||
logic sra;
|
||||
logic beq;
|
||||
logic bne;
|
||||
logic blt;
|
||||
logic bge;
|
||||
logic add;
|
||||
logic sub;
|
||||
logic slt;
|
||||
logic unsign;
|
||||
logic jal;
|
||||
logic predict_t;
|
||||
logic predict_nt;
|
||||
logic csr_write;
|
||||
logic csr_imm;
|
||||
} alu_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic by;
|
||||
logic half;
|
||||
logic word;
|
||||
logic dword; // for dma
|
||||
logic load;
|
||||
logic store;
|
||||
logic unsign;
|
||||
logic dma; // dma pkt
|
||||
logic store_data_bypass_c1;
|
||||
logic load_ldst_bypass_c1;
|
||||
logic store_data_bypass_c2;
|
||||
logic store_data_bypass_i0_e2_c2;
|
||||
logic [1:0] store_data_bypass_e4_c1;
|
||||
logic [1:0] store_data_bypass_e4_c2;
|
||||
logic [1:0] store_data_bypass_e4_c3;
|
||||
logic valid;
|
||||
} lsu_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic exc_valid;
|
||||
logic single_ecc_error;
|
||||
logic inst_type; //0: Load, 1: Store
|
||||
logic inst_pipe; //0: i0, 1: i1
|
||||
logic dma_valid;
|
||||
logic exc_type; //0: MisAligned, 1: Access Fault
|
||||
logic [31:0] addr;
|
||||
} lsu_error_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic alu;
|
||||
logic rs1;
|
||||
logic rs2;
|
||||
logic imm12;
|
||||
logic rd;
|
||||
logic shimm5;
|
||||
logic imm20;
|
||||
logic pc;
|
||||
logic load;
|
||||
logic store;
|
||||
logic lsu;
|
||||
logic add;
|
||||
logic sub;
|
||||
logic land;
|
||||
logic lor;
|
||||
logic lxor;
|
||||
logic sll;
|
||||
logic sra;
|
||||
logic srl;
|
||||
logic slt;
|
||||
logic unsign;
|
||||
logic condbr;
|
||||
logic beq;
|
||||
logic bne;
|
||||
logic bge;
|
||||
logic blt;
|
||||
logic jal;
|
||||
logic by;
|
||||
logic half;
|
||||
logic word;
|
||||
logic csr_read;
|
||||
logic csr_clr;
|
||||
logic csr_set;
|
||||
logic csr_write;
|
||||
logic csr_imm;
|
||||
logic presync;
|
||||
logic postsync;
|
||||
logic ebreak;
|
||||
logic ecall;
|
||||
logic mret;
|
||||
logic mul;
|
||||
logic rs1_sign;
|
||||
logic rs2_sign;
|
||||
logic low;
|
||||
logic div;
|
||||
logic rem;
|
||||
logic fence;
|
||||
logic fence_i;
|
||||
logic pm_alu;
|
||||
logic legal;
|
||||
} dec_pkt_t;
|
||||
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic rs1_sign;
|
||||
logic rs2_sign;
|
||||
logic low;
|
||||
logic load_mul_rs1_bypass_e1;
|
||||
logic load_mul_rs2_bypass_e1;
|
||||
} mul_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic unsign;
|
||||
logic rem;
|
||||
} div_pkt_t;
|
||||
|
||||
|
||||
typedef struct packed {
|
||||
logic select;
|
||||
logic match;
|
||||
logic store;
|
||||
logic load;
|
||||
logic execute;
|
||||
logic m;
|
||||
logic [31:0] tdata2;
|
||||
} trigger_pkt_t;
|
||||
|
||||
|
||||
typedef struct packed {
|
||||
`ifdef RV_ICACHE_ECC
|
||||
logic [41:0] icache_wrdata; // {dicad0[31:0], dicad1[1:0]}
|
||||
`else
|
||||
logic [33:0] icache_wrdata; // {dicad0[31:0], dicad1[1:0]}
|
||||
`endif
|
||||
logic [18:2] icache_dicawics;
|
||||
logic icache_rd_valid;
|
||||
logic icache_wr_valid;
|
||||
} cache_debug_pkt_t;
|
||||
|
||||
|
||||
endpackage // swerv_types
|
|
@ -0,0 +1,281 @@
|
|||
// 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: AHB to AXI4 Bridge
|
||||
// Comments:
|
||||
//
|
||||
//********************************************************************************
|
||||
module ahb_to_axi4 #(parameter TAG = 1) (
|
||||
|
||||
input clk,
|
||||
input rst_l,
|
||||
input scan_mode,
|
||||
input bus_clk_en,
|
||||
input clk_override,
|
||||
|
||||
// AXI signals
|
||||
// AXI Write Channels
|
||||
output logic axi_awvalid,
|
||||
input logic axi_awready,
|
||||
output logic [TAG-1:0] axi_awid,
|
||||
output logic [31:0] axi_awaddr,
|
||||
output logic [2:0] axi_awsize,
|
||||
output logic [2:0] axi_awprot,
|
||||
output logic [7:0] axi_awlen,
|
||||
output logic [1:0] axi_awburst,
|
||||
|
||||
output logic axi_wvalid,
|
||||
input logic axi_wready,
|
||||
output logic [63:0] axi_wdata,
|
||||
output logic [7:0] axi_wstrb,
|
||||
output logic axi_wlast,
|
||||
|
||||
input logic axi_bvalid,
|
||||
output logic axi_bready,
|
||||
input logic [1:0] axi_bresp,
|
||||
input logic [TAG-1:0] axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic axi_arvalid,
|
||||
input logic axi_arready,
|
||||
output logic [TAG-1:0] axi_arid,
|
||||
output logic [31:0] axi_araddr,
|
||||
output logic [2:0] axi_arsize,
|
||||
output logic [2:0] axi_arprot,
|
||||
output logic [7:0] axi_arlen,
|
||||
output logic [1:0] axi_arburst,
|
||||
|
||||
input logic axi_rvalid,
|
||||
output logic axi_rready,
|
||||
input logic [TAG-1:0] axi_rid,
|
||||
input logic [63:0] axi_rdata,
|
||||
input logic [1:0] axi_rresp,
|
||||
|
||||
// AHB-Lite signals
|
||||
input logic [31:0] ahb_haddr, // ahb bus address
|
||||
input logic [2:0] ahb_hburst, // tied to 0
|
||||
input logic ahb_hmastlock, // tied to 0
|
||||
input logic [3:0] ahb_hprot, // tied to 4'b0011
|
||||
input logic [2:0] ahb_hsize, // size of bus transaction (possible values 0,1,2,3)
|
||||
input logic [1:0] ahb_htrans, // Transaction type (possible values 0,2 only right now)
|
||||
input logic ahb_hwrite, // ahb bus write
|
||||
input logic [63:0] ahb_hwdata, // ahb bus write data
|
||||
input logic ahb_hsel, // this slave was selected
|
||||
input logic ahb_hreadyin, // previous hready was accepted or not
|
||||
|
||||
output logic [63:0] ahb_hrdata, // ahb bus read data
|
||||
output logic ahb_hreadyout, // slave ready to accept transaction
|
||||
output logic ahb_hresp // slave response (high indicates erro)
|
||||
|
||||
);
|
||||
|
||||
logic [7:0] master_wstrb;
|
||||
|
||||
typedef enum logic [1:0] { IDLE = 2'b00, // Nothing in the buffer. No commands yet recieved
|
||||
WR = 2'b01, // Write Command recieved
|
||||
RD = 2'b10, // Read Command recieved
|
||||
PEND = 2'b11 // Waiting on Read Data from core
|
||||
} state_t;
|
||||
state_t buf_state, buf_nxtstate;
|
||||
logic buf_state_en;
|
||||
|
||||
// Buffer signals (one entry buffer)
|
||||
logic buf_read_error_in, buf_read_error;
|
||||
logic [63:0] buf_rdata;
|
||||
|
||||
logic ahb_hready;
|
||||
logic ahb_hready_q;
|
||||
logic [1:0] ahb_htrans_in, ahb_htrans_q;
|
||||
logic [2:0] ahb_hsize_q;
|
||||
logic ahb_hwrite_q;
|
||||
logic [31:0] ahb_haddr_q;
|
||||
logic [63:0] ahb_hwdata_q;
|
||||
logic ahb_hresp_q;
|
||||
|
||||
//Miscellaneous signals
|
||||
logic ahb_addr_in_dccm, ahb_addr_in_iccm, ahb_addr_in_pic;
|
||||
logic ahb_addr_in_dccm_region_nc, ahb_addr_in_iccm_region_nc, ahb_addr_in_pic_region_nc;
|
||||
// signals needed for the read data coming back from the core and to block any further commands as AHB is a blocking bus
|
||||
logic buf_rdata_en;
|
||||
|
||||
logic ahb_bus_addr_clk_en, buf_rdata_clk_en;
|
||||
logic ahb_clk, ahb_addr_clk, buf_rdata_clk;
|
||||
// Command buffer is the holding station where we convert to AXI and send to core
|
||||
logic cmdbuf_wr_en, cmdbuf_rst;
|
||||
logic cmdbuf_full;
|
||||
logic cmdbuf_vld, cmdbuf_write;
|
||||
logic [1:0] cmdbuf_size;
|
||||
logic [7:0] cmdbuf_wstrb;
|
||||
logic [31:0] cmdbuf_addr;
|
||||
logic [63:0] cmdbuf_wdata;
|
||||
|
||||
logic bus_clk;
|
||||
|
||||
// FSM to control the bus states and when to block the hready and load the command buffer
|
||||
always_comb begin
|
||||
buf_nxtstate = IDLE;
|
||||
buf_state_en = 1'b0;
|
||||
buf_rdata_en = 1'b0; // signal to load the buffer when the core sends read data back
|
||||
buf_read_error_in = 1'b0; // signal indicating that an error came back with the read from the core
|
||||
cmdbuf_wr_en = 1'b0; // all clear from the gasket to load the buffer with the command for reads, command/dat for writes
|
||||
case (buf_state)
|
||||
IDLE: begin // No commands recieved
|
||||
buf_nxtstate = ahb_hwrite ? WR : RD;
|
||||
buf_state_en = ahb_hready & ahb_htrans[1] & ahb_hsel; // only transition on a valid hrtans
|
||||
end
|
||||
WR: begin // Write command recieved last cycle
|
||||
buf_nxtstate = (ahb_hresp | (ahb_htrans[1:0] == 2'b0) | ~ahb_hsel) ? IDLE : (ahb_hwrite ? WR : RD);
|
||||
buf_state_en = (~cmdbuf_full | ahb_hresp) ;
|
||||
cmdbuf_wr_en = ~cmdbuf_full & ~(ahb_hresp | ((ahb_htrans[1:0] == 2'b01) & ahb_hsel)); // Dont send command to the buffer in case of an error or when the master is not ready with the data now.
|
||||
end
|
||||
RD: begin // Read command recieved last cycle.
|
||||
buf_nxtstate = ahb_hresp ? IDLE :PEND; // If error go to idle, else wait for read data
|
||||
buf_state_en = (~cmdbuf_full | ahb_hresp); // only when command can go, or if its an error
|
||||
cmdbuf_wr_en = ~ahb_hresp & ~cmdbuf_full; // send command only when no error
|
||||
end
|
||||
PEND: begin // Read Command has been sent. Waiting on Data.
|
||||
buf_nxtstate = IDLE; // go back for next command and present data next cycle
|
||||
buf_state_en = axi_rvalid & ~cmdbuf_write; // read data is back
|
||||
buf_rdata_en = buf_state_en; // buffer the read data coming back from core
|
||||
buf_read_error_in = buf_state_en & |axi_rresp[1:0]; // buffer error flag if return has Error ( ECC )
|
||||
end
|
||||
endcase
|
||||
end // always_comb begin
|
||||
|
||||
rvdffs #($bits(state_t)) state_reg (.*, .din(buf_nxtstate), .dout({buf_state}), .en(buf_state_en), .clk(ahb_clk));
|
||||
|
||||
assign master_wstrb[7:0] = ({8{ahb_hsize_q[2:0] == 3'b0}} & (8'b1 << ahb_haddr_q[2:0])) |
|
||||
({8{ahb_hsize_q[2:0] == 3'b1}} & (8'b11 << ahb_haddr_q[2:0])) |
|
||||
({8{ahb_hsize_q[2:0] == 3'b10}} & (8'b1111 << ahb_haddr_q[2:0])) |
|
||||
({8{ahb_hsize_q[2:0] == 3'b11}} & 8'b1111_1111);
|
||||
|
||||
// AHB signals
|
||||
assign ahb_hreadyout = ahb_hresp ? (ahb_hresp_q & ~ahb_hready_q) :
|
||||
((~cmdbuf_full | (buf_state == IDLE)) & ~(buf_state == RD | buf_state == PEND) & ~buf_read_error);
|
||||
|
||||
assign ahb_hready = ahb_hreadyout & ahb_hreadyin;
|
||||
assign ahb_htrans_in[1:0] = {2{ahb_hsel}} & ahb_htrans[1:0];
|
||||
assign ahb_hrdata[63:0] = buf_rdata[63:0];
|
||||
assign ahb_hresp = ((ahb_htrans_q[1:0] != 2'b0) & (buf_state != IDLE) &
|
||||
((~(ahb_addr_in_dccm | ahb_addr_in_iccm)) | // request not for ICCM or DCCM
|
||||
((ahb_addr_in_iccm | (ahb_addr_in_dccm & ahb_hwrite_q)) & ~((ahb_hsize_q[1:0] == 2'b10) | (ahb_hsize_q[1:0] == 2'b11))) | // ICCM Rd/Wr OR DCCM Wr not the right size
|
||||
((ahb_hsize_q[2:0] == 3'h1) & ahb_haddr_q[0]) | // HW size but unaligned
|
||||
((ahb_hsize_q[2:0] == 3'h2) & (|ahb_haddr_q[1:0])) | // W size but unaligned
|
||||
((ahb_hsize_q[2:0] == 3'h3) & (|ahb_haddr_q[2:0])))) | // DW size but unaligned
|
||||
buf_read_error | // Read ECC error
|
||||
(ahb_hresp_q & ~ahb_hready_q); // This is for second cycle of hresp protocol
|
||||
|
||||
// Buffer signals - needed for the read data and ECC error response
|
||||
rvdff #(.WIDTH(64)) buf_rdata_ff (.din(axi_rdata[63:0]), .dout(buf_rdata[63:0]), .clk(buf_rdata_clk), .*);
|
||||
rvdff #(.WIDTH(1)) buf_read_error_ff(.din(buf_read_error_in), .dout(buf_read_error), .clk(ahb_clk), .*); // buf_read_error will be high only one cycle
|
||||
|
||||
// All the Master signals are captured before presenting it to the command buffer. We check for Hresp before sending it to the cmd buffer.
|
||||
rvdff #(.WIDTH(1)) hresp_ff (.din(ahb_hresp), .dout(ahb_hresp_q), .clk(ahb_clk), .*);
|
||||
rvdff #(.WIDTH(1)) hready_ff (.din(ahb_hready), .dout(ahb_hready_q), .clk(ahb_clk), .*);
|
||||
rvdff #(.WIDTH(2)) htrans_ff (.din(ahb_htrans_in[1:0]), .dout(ahb_htrans_q[1:0]), .clk(ahb_clk), .*);
|
||||
rvdff #(.WIDTH(3)) hsize_ff (.din(ahb_hsize[2:0]), .dout(ahb_hsize_q[2:0]), .clk(ahb_addr_clk), .*);
|
||||
rvdff #(.WIDTH(1)) hwrite_ff (.din(ahb_hwrite), .dout(ahb_hwrite_q), .clk(ahb_addr_clk), .*);
|
||||
rvdff #(.WIDTH(32)) haddr_ff (.din(ahb_haddr[31:0]), .dout(ahb_haddr_q[31:0]), .clk(ahb_addr_clk), .*);
|
||||
|
||||
// Clock header logic
|
||||
assign ahb_bus_addr_clk_en = bus_clk_en & (ahb_hready & ahb_htrans[1]);
|
||||
assign buf_rdata_clk_en = bus_clk_en & buf_rdata_en;
|
||||
|
||||
rvclkhdr ahb_cgc (.en(bus_clk_en), .l1clk(ahb_clk), .*);
|
||||
rvclkhdr ahb_addr_cgc (.en(ahb_bus_addr_clk_en), .l1clk(ahb_addr_clk), .*);
|
||||
rvclkhdr buf_rdata_cgc (.en(buf_rdata_clk_en), .l1clk(buf_rdata_clk), .*);
|
||||
|
||||
// Address check dccm
|
||||
rvrangecheck #(.CCM_SADR(`RV_DCCM_SADR),
|
||||
.CCM_SIZE(`RV_DCCM_SIZE)) addr_dccm_rangecheck (
|
||||
.addr(ahb_haddr_q[31:0]),
|
||||
.in_range(ahb_addr_in_dccm),
|
||||
.in_region(ahb_addr_in_dccm_region_nc)
|
||||
);
|
||||
|
||||
// Address check iccm
|
||||
`ifdef RV_ICCM_ENABLE
|
||||
rvrangecheck #(.CCM_SADR(`RV_ICCM_SADR),
|
||||
.CCM_SIZE(`RV_ICCM_SIZE)) addr_iccm_rangecheck (
|
||||
.addr(ahb_haddr_q[31:0]),
|
||||
.in_range(ahb_addr_in_iccm),
|
||||
.in_region(ahb_addr_in_iccm_region_nc)
|
||||
);
|
||||
`else
|
||||
assign ahb_addr_in_iccm = '0;
|
||||
assign ahb_addr_in_iccm_region_nc = '0;
|
||||
`endif
|
||||
|
||||
// PIC memory address check
|
||||
rvrangecheck #(.CCM_SADR(`RV_PIC_BASE_ADDR),
|
||||
.CCM_SIZE(`RV_PIC_SIZE)) addr_pic_rangecheck (
|
||||
.addr(ahb_haddr_q[31:0]),
|
||||
.in_range(ahb_addr_in_pic),
|
||||
.in_region(ahb_addr_in_pic_region_nc)
|
||||
);
|
||||
|
||||
// Command Buffer - Holding for the commands to be sent for the AXI. It will be converted to the AXI signals.
|
||||
assign cmdbuf_rst = (((axi_awvalid & axi_awready) | (axi_arvalid & axi_arready)) & ~cmdbuf_wr_en) | (ahb_hresp & ~cmdbuf_write);
|
||||
assign cmdbuf_full = (cmdbuf_vld & ~((axi_awvalid & axi_awready) | (axi_arvalid & axi_arready)));
|
||||
|
||||
rvdffsc #(.WIDTH(1)) cmdbuf_vldff (.din(1'b1), .dout(cmdbuf_vld), .en(cmdbuf_wr_en), .clear(cmdbuf_rst), .clk(bus_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) cmdbuf_writeff (.din(ahb_hwrite_q), .dout(cmdbuf_write), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
|
||||
rvdffs #(.WIDTH(2)) cmdbuf_sizeff (.din(ahb_hsize_q[1:0]), .dout(cmdbuf_size[1:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
|
||||
rvdffs #(.WIDTH(8)) cmdbuf_wstrbff (.din(master_wstrb[7:0]), .dout(cmdbuf_wstrb[7:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) cmdbuf_addrff (.din(ahb_haddr_q[31:0]), .dout(cmdbuf_addr[31:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
|
||||
rvdffe #(.WIDTH(64)) cmdbuf_wdataff (.din(ahb_hwdata[63:0]), .dout(cmdbuf_wdata[63:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
|
||||
|
||||
// AXI Write Command Channel
|
||||
assign axi_awvalid = cmdbuf_vld & cmdbuf_write;
|
||||
assign axi_awid[TAG-1:0] = '0;
|
||||
assign axi_awaddr[31:0] = cmdbuf_addr[31:0];
|
||||
assign axi_awsize[2:0] = {1'b0, cmdbuf_size[1:0]};
|
||||
assign axi_awprot[2:0] = 3'b0;
|
||||
assign axi_awlen[7:0] = '0;
|
||||
assign axi_awburst[1:0] = 2'b01;
|
||||
// AXI Write Data Channel - This is tied to the command channel as we only write the command buffer once we have the data.
|
||||
assign axi_wvalid = cmdbuf_vld & cmdbuf_write;
|
||||
assign axi_wdata[63:0] = cmdbuf_wdata[63:0];
|
||||
assign axi_wstrb[7:0] = cmdbuf_wstrb[7:0];
|
||||
assign axi_wlast = 1'b1;
|
||||
// AXI Write Response - Always ready. AHB does not require a write response.
|
||||
assign axi_bready = 1'b1;
|
||||
// AXI Read Channels
|
||||
assign axi_arvalid = cmdbuf_vld & ~cmdbuf_write;
|
||||
assign axi_arid[TAG-1:0] = '0;
|
||||
assign axi_araddr[31:0] = cmdbuf_addr[31:0];
|
||||
assign axi_arsize[2:0] = {1'b0, cmdbuf_size[1:0]};
|
||||
assign axi_arprot = 3'b0;
|
||||
assign axi_arlen[7:0] = '0;
|
||||
assign axi_arburst[1:0] = 2'b01;
|
||||
// AXI Read Response Channel - Always ready as AHB reads are blocking and the the buffer is available for the read coming back always.
|
||||
assign axi_rready = 1'b1;
|
||||
|
||||
// Clock header logic
|
||||
rvclkhdr bus_cgc (.en(bus_clk_en), .l1clk(bus_clk), .*);
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
property ahb_error_protocol;
|
||||
@(posedge ahb_clk) (ahb_hready & ahb_hresp) |-> (~$past(ahb_hready) & $past(ahb_hresp));
|
||||
endproperty
|
||||
assert_ahb_error_protocol: assert property (ahb_error_protocol) else
|
||||
$display("Bus Error with hReady isn't preceded with Bus Error without hready");
|
||||
|
||||
`endif
|
||||
|
||||
endmodule // ahb_to_axi4
|
|
@ -0,0 +1,472 @@
|
|||
// 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: AXI4 -> AHB Bridge
|
||||
// Comments:
|
||||
//
|
||||
//********************************************************************************
|
||||
module axi4_to_ahb #(parameter TAG = 1) (
|
||||
|
||||
input clk,
|
||||
input rst_l,
|
||||
input scan_mode,
|
||||
input bus_clk_en,
|
||||
input clk_override,
|
||||
|
||||
// AXI signals
|
||||
// AXI Write Channels
|
||||
input logic axi_awvalid,
|
||||
output logic axi_awready,
|
||||
input logic [TAG-1:0] axi_awid,
|
||||
input logic [31:0] axi_awaddr,
|
||||
input logic [2:0] axi_awsize,
|
||||
input logic [2:0] axi_awprot,
|
||||
|
||||
input logic axi_wvalid,
|
||||
output logic axi_wready,
|
||||
input logic [63:0] axi_wdata,
|
||||
input logic [7:0] axi_wstrb,
|
||||
input logic axi_wlast,
|
||||
|
||||
output logic axi_bvalid,
|
||||
input logic axi_bready,
|
||||
output logic [1:0] axi_bresp,
|
||||
output logic [TAG-1:0] axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
input logic axi_arvalid,
|
||||
output logic axi_arready,
|
||||
input logic [TAG-1:0] axi_arid,
|
||||
input logic [31:0] axi_araddr,
|
||||
input logic [2:0] axi_arsize,
|
||||
input logic [2:0] axi_arprot,
|
||||
|
||||
output logic axi_rvalid,
|
||||
input logic axi_rready,
|
||||
output logic [TAG-1:0] axi_rid,
|
||||
output logic [63:0] axi_rdata,
|
||||
output logic [1:0] axi_rresp,
|
||||
output logic axi_rlast,
|
||||
|
||||
// AHB-Lite signals
|
||||
output logic [31:0] ahb_haddr, // ahb bus address
|
||||
output logic [2:0] ahb_hburst, // tied to 0
|
||||
output logic ahb_hmastlock, // tied to 0
|
||||
output logic [3:0] ahb_hprot, // tied to 4'b0011
|
||||
output logic [2:0] ahb_hsize, // size of bus transaction (possible values 0,1,2,3)
|
||||
output logic [1:0] ahb_htrans, // Transaction type (possible values 0,2 only right now)
|
||||
output logic ahb_hwrite, // ahb bus write
|
||||
output logic [63:0] ahb_hwdata, // ahb bus write data
|
||||
|
||||
input logic [63:0] ahb_hrdata, // ahb bus read data
|
||||
input logic ahb_hready, // slave ready to accept transaction
|
||||
input logic ahb_hresp // slave response (high indicates erro)
|
||||
|
||||
);
|
||||
|
||||
localparam ID = 1;
|
||||
localparam PRTY = 1;
|
||||
typedef enum logic [2:0] {IDLE=3'b000, CMD_RD=3'b001, CMD_WR=3'b010, DATA_RD=3'b011, DATA_WR=3'b100, DONE=3'b101, STREAM_RD=3'b110, STREAM_ERR_RD=3'b111} state_t;
|
||||
state_t buf_state, buf_nxtstate;
|
||||
|
||||
logic slave_valid;
|
||||
logic slave_ready;
|
||||
logic [TAG-1:0] slave_tag;
|
||||
logic [63:0] slave_rdata;
|
||||
logic [3:0] slave_opc;
|
||||
|
||||
logic wrbuf_en, wrbuf_data_en;
|
||||
logic wrbuf_cmd_sent, wrbuf_rst;
|
||||
logic wrbuf_vld;
|
||||
logic wrbuf_data_vld;
|
||||
logic [TAG-1:0] wrbuf_tag;
|
||||
logic [2:0] wrbuf_size;
|
||||
logic [31:0] wrbuf_addr;
|
||||
logic [63:0] wrbuf_data;
|
||||
logic [7:0] wrbuf_byteen;
|
||||
|
||||
logic bus_write_clk_en;
|
||||
logic bus_clk, bus_write_clk;
|
||||
|
||||
logic master_valid;
|
||||
logic master_ready;
|
||||
logic [TAG-1:0] master_tag;
|
||||
logic [31:0] master_addr;
|
||||
logic [63:0] master_wdata;
|
||||
logic [2:0] master_size;
|
||||
logic [2:0] master_opc;
|
||||
|
||||
// Buffer signals (one entry buffer)
|
||||
logic [31:0] buf_addr;
|
||||
logic [1:0] buf_size;
|
||||
logic buf_write;
|
||||
logic [7:0] buf_byteen;
|
||||
logic buf_aligned;
|
||||
logic [63:0] buf_data;
|
||||
logic [TAG-1:0] buf_tag;
|
||||
|
||||
//Miscellaneous signals
|
||||
logic buf_rst;
|
||||
logic [TAG-1:0] buf_tag_in;
|
||||
logic [31:0] buf_addr_in;
|
||||
logic [7:0] buf_byteen_in;
|
||||
logic [63:0] buf_data_in;
|
||||
logic buf_write_in;
|
||||
logic buf_aligned_in;
|
||||
logic [2:0] buf_size_in;
|
||||
|
||||
logic buf_state_en;
|
||||
logic buf_wr_en;
|
||||
logic buf_data_wr_en;
|
||||
logic slvbuf_error_en;
|
||||
logic wr_cmd_vld;
|
||||
|
||||
logic cmd_done_rst, cmd_done, cmd_doneQ;
|
||||
logic trxn_done;
|
||||
logic [2:0] buf_cmd_byte_ptr, buf_cmd_byte_ptrQ, buf_cmd_nxtbyte_ptr;
|
||||
logic buf_cmd_byte_ptr_en;
|
||||
logic found;
|
||||
|
||||
logic slave_valid_pre;
|
||||
logic ahb_hready_q;
|
||||
logic ahb_hresp_q;
|
||||
logic [1:0] ahb_htrans_q;
|
||||
logic ahb_hwrite_q;
|
||||
logic [63:0] ahb_hrdata_q;
|
||||
|
||||
|
||||
logic slvbuf_write;
|
||||
logic slvbuf_error;
|
||||
logic [TAG-1:0] slvbuf_tag;
|
||||
|
||||
logic slvbuf_error_in;
|
||||
logic slvbuf_wr_en;
|
||||
logic bypass_en;
|
||||
logic rd_bypass_idle;
|
||||
|
||||
logic last_addr_en;
|
||||
logic [31:0] last_bus_addr;
|
||||
|
||||
// Clocks
|
||||
logic buf_clken, slvbuf_clken;
|
||||
logic ahbm_addr_clken;
|
||||
logic ahbm_data_clken;
|
||||
|
||||
logic buf_clk, slvbuf_clk;
|
||||
logic ahbm_clk;
|
||||
logic ahbm_addr_clk;
|
||||
logic ahbm_data_clk;
|
||||
|
||||
// Function to get the length from byte enable
|
||||
function automatic logic [1:0] get_write_size;
|
||||
input logic [7:0] byteen;
|
||||
|
||||
logic [1:0] size;
|
||||
|
||||
size[1:0] = (2'b11 & {2{(byteen[7:0] == 8'hff)}}) |
|
||||
(2'b10 & {2{((byteen[7:0] == 8'hf0) | (byteen[7:0] == 8'h0f))}}) |
|
||||
(2'b01 & {2{((byteen[7:0] == 8'hc0) | (byteen[7:0] == 8'h30) | (byteen[7:0] == 8'h0c) | (byteen[7:0] == 8'h03))}});
|
||||
|
||||
return size[1:0];
|
||||
endfunction // get_write_size
|
||||
|
||||
// Function to get the length from byte enable
|
||||
function automatic logic [2:0] get_write_addr;
|
||||
input logic [7:0] byteen;
|
||||
|
||||
logic [2:0] addr;
|
||||
|
||||
addr[2:0] = (3'h0 & {3{((byteen[7:0] == 8'hff) | (byteen[7:0] == 8'h0f) | (byteen[7:0] == 8'h03))}}) |
|
||||
(3'h2 & {3{(byteen[7:0] == 8'h0c)}}) |
|
||||
(3'h4 & {3{((byteen[7:0] == 8'hf0) | (byteen[7:0] == 8'h03))}}) |
|
||||
(3'h6 & {3{(byteen[7:0] == 8'hc0)}});
|
||||
|
||||
return addr[2:0];
|
||||
endfunction // get_write_size
|
||||
|
||||
// Function to get the next byte pointer
|
||||
function automatic logic [2:0] get_nxtbyte_ptr (logic [2:0] current_byte_ptr, logic [7:0] byteen, logic get_next);
|
||||
logic [2:0] start_ptr;
|
||||
logic found;
|
||||
found = '0;
|
||||
//get_nxtbyte_ptr[2:0] = current_byte_ptr[2:0];
|
||||
start_ptr[2:0] = get_next ? (current_byte_ptr[2:0] + 3'b1) : current_byte_ptr[2:0];
|
||||
for (int j=0; j<8; j++) begin
|
||||
if (~found) begin
|
||||
get_nxtbyte_ptr[2:0] = 3'(j);
|
||||
found |= (byteen[j] & (3'(j) >= start_ptr[2:0])) ;
|
||||
end
|
||||
end
|
||||
endfunction // get_nextbyte_ptr
|
||||
|
||||
|
||||
// Write buffer
|
||||
assign wrbuf_en = axi_awvalid & axi_awready & master_ready;
|
||||
assign wrbuf_data_en = axi_wvalid & axi_wready & master_ready;
|
||||
assign wrbuf_cmd_sent = master_valid & master_ready & (master_opc[2:1] == 2'b01);
|
||||
assign wrbuf_rst = wrbuf_cmd_sent & ~wrbuf_en;
|
||||
|
||||
assign axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent) & master_ready;
|
||||
assign axi_wready = ~(wrbuf_data_vld & ~wrbuf_cmd_sent) & master_ready;
|
||||
assign axi_arready = ~(wrbuf_vld & wrbuf_data_vld) & master_ready;
|
||||
assign axi_rlast = 1'b1;
|
||||
|
||||
assign wr_cmd_vld = (wrbuf_vld & wrbuf_data_vld);
|
||||
assign master_valid = wr_cmd_vld | axi_arvalid;
|
||||
assign master_tag[TAG-1:0] = wr_cmd_vld ? wrbuf_tag[TAG-1:0] : axi_arid[TAG-1:0];
|
||||
assign master_opc[2:0] = wr_cmd_vld ? 3'b011 : 3'b0;
|
||||
assign master_addr[31:0] = wr_cmd_vld ? wrbuf_addr[31:0] : axi_araddr[31:0];
|
||||
assign master_size[2:0] = wr_cmd_vld ? wrbuf_size[2:0] : axi_arsize[2:0];
|
||||
assign master_wdata[63:0] = wrbuf_data[63:0];
|
||||
|
||||
// AXI response channel signals
|
||||
assign axi_bvalid = slave_valid & slave_ready & slave_opc[3];
|
||||
assign axi_bresp[1:0] = slave_opc[0] ? 2'b10 : (slave_opc[1] ? 2'b11 : 2'b0);
|
||||
assign axi_bid[TAG-1:0] = slave_tag[TAG-1:0];
|
||||
|
||||
assign axi_rvalid = slave_valid & slave_ready & (slave_opc[3:2] == 2'b0);
|
||||
assign axi_rresp[1:0] = slave_opc[0] ? 2'b10 : (slave_opc[1] ? 2'b11 : 2'b0);
|
||||
assign axi_rid[TAG-1:0] = slave_tag[TAG-1:0];
|
||||
assign axi_rdata[63:0] = slave_rdata[63:0];
|
||||
assign slave_ready = axi_bready & axi_rready;
|
||||
|
||||
// Clock header logic
|
||||
assign bus_write_clk_en = bus_clk_en & ((axi_awvalid & axi_awready) | (axi_wvalid & axi_wready));
|
||||
|
||||
rvclkhdr bus_cgc (.en(bus_clk_en), .l1clk(bus_clk), .*);
|
||||
rvclkhdr bus_write_cgc (.en(bus_write_clk_en), .l1clk(bus_write_clk), .*);
|
||||
|
||||
|
||||
// FIFO state machine
|
||||
always_comb begin
|
||||
buf_nxtstate = IDLE;
|
||||
buf_state_en = 1'b0;
|
||||
buf_wr_en = 1'b0;
|
||||
buf_data_wr_en = 1'b0;
|
||||
slvbuf_error_in = 1'b0;
|
||||
slvbuf_error_en = 1'b0;
|
||||
buf_write_in = 1'b0;
|
||||
cmd_done = 1'b0;
|
||||
trxn_done = 1'b0;
|
||||
buf_cmd_byte_ptr_en = 1'b0;
|
||||
buf_cmd_byte_ptr[2:0] = '0;
|
||||
slave_valid_pre = 1'b0;
|
||||
master_ready = 1'b0;
|
||||
ahb_htrans[1:0] = 2'b0;
|
||||
slvbuf_wr_en = 1'b0;
|
||||
bypass_en = 1'b0;
|
||||
rd_bypass_idle = 1'b0;
|
||||
|
||||
case (buf_state)
|
||||
IDLE: begin
|
||||
master_ready = 1'b1;
|
||||
buf_write_in = (master_opc[2:1] == 2'b01);
|
||||
buf_nxtstate = buf_write_in ? CMD_WR : CMD_RD;
|
||||
buf_state_en = master_valid & master_ready;
|
||||
buf_wr_en = buf_state_en;
|
||||
buf_data_wr_en = buf_state_en & (buf_nxtstate == CMD_WR);
|
||||
buf_cmd_byte_ptr_en = buf_state_en;
|
||||
buf_cmd_byte_ptr[2:0] = buf_write_in ? get_nxtbyte_ptr(3'b0,buf_byteen_in[7:0],1'b0) : master_addr[2:0];
|
||||
bypass_en = buf_state_en;
|
||||
rd_bypass_idle = bypass_en & (buf_nxtstate == CMD_RD);
|
||||
ahb_htrans[1:0] = {2{bypass_en}} & 2'b10;
|
||||
end
|
||||
CMD_RD: begin
|
||||
buf_nxtstate = (master_valid & (master_opc[2:0] == 3'b000))? STREAM_RD : DATA_RD;
|
||||
buf_state_en = ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) & ~ahb_hwrite_q;
|
||||
cmd_done = buf_state_en & ~master_valid;
|
||||
slvbuf_wr_en = buf_state_en;
|
||||
master_ready = buf_state_en & (buf_nxtstate == STREAM_RD);
|
||||
buf_wr_en = master_ready;
|
||||
bypass_en = master_ready & master_valid;
|
||||
buf_cmd_byte_ptr[2:0] = bypass_en ? master_addr[2:0] : buf_addr[2:0];
|
||||
ahb_htrans[1:0] = 2'b10 & {2{~buf_state_en | bypass_en}};
|
||||
end
|
||||
STREAM_RD: begin
|
||||
master_ready = (ahb_hready_q & ~ahb_hresp_q) & ~(master_valid & master_opc[2:1] == 2'b01);
|
||||
buf_wr_en = (master_valid & master_ready & (master_opc[2:0] == 3'b000)); // update the fifo if we are streaming the read commands
|
||||
buf_nxtstate = ahb_hresp_q ? STREAM_ERR_RD : (buf_wr_en ? STREAM_RD : DATA_RD); // assuming that the master accpets the slave response right away.
|
||||
buf_state_en = (ahb_hready_q | ahb_hresp_q);
|
||||
buf_data_wr_en = buf_state_en;
|
||||
slvbuf_error_in = ahb_hresp_q;
|
||||
slvbuf_error_en = buf_state_en;
|
||||
slave_valid_pre = buf_state_en & ~ahb_hresp_q; // send a response right away if we are not going through an error response.
|
||||
cmd_done = buf_state_en & ~master_valid; // last one of the stream should not send a htrans
|
||||
bypass_en = master_ready & master_valid & (buf_nxtstate == STREAM_RD) & buf_state_en;
|
||||
buf_cmd_byte_ptr[2:0] = bypass_en ? master_addr[2:0] : buf_addr[2:0];
|
||||
ahb_htrans[1:0] = 2'b10 & {2{~((buf_nxtstate != STREAM_RD) & buf_state_en)}};
|
||||
slvbuf_wr_en = buf_wr_en; // shifting the contents from the buf to slv_buf for streaming cases
|
||||
end // case: STREAM_RD
|
||||
STREAM_ERR_RD: begin
|
||||
buf_nxtstate = DATA_RD;
|
||||
buf_state_en = ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) & ~ahb_hwrite_q;
|
||||
slave_valid_pre = buf_state_en;
|
||||
slvbuf_wr_en = buf_state_en; // Overwrite slvbuf with buffer
|
||||
buf_cmd_byte_ptr[2:0] = buf_addr[2:0];
|
||||
ahb_htrans[1:0] = 2'b10 & {2{~buf_state_en}};
|
||||
end
|
||||
DATA_RD: begin
|
||||
buf_nxtstate = DONE;
|
||||
buf_state_en = (ahb_hready_q | ahb_hresp_q);
|
||||
buf_data_wr_en = buf_state_en;
|
||||
slvbuf_error_in= ahb_hresp_q;
|
||||
slvbuf_error_en= buf_state_en;
|
||||
slvbuf_wr_en = buf_state_en;
|
||||
end
|
||||
CMD_WR: begin
|
||||
buf_nxtstate = DATA_WR;
|
||||
trxn_done = ahb_hready_q & ahb_hwrite_q & (ahb_htrans_q[1:0] != 2'b0);
|
||||
buf_state_en = trxn_done;
|
||||
buf_cmd_byte_ptr_en = buf_state_en;
|
||||
slvbuf_wr_en = buf_state_en;
|
||||
buf_cmd_byte_ptr = trxn_done ? get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0],buf_byteen[7:0],1'b1) : buf_cmd_byte_ptrQ;
|
||||
cmd_done = trxn_done & (buf_aligned | (buf_cmd_byte_ptrQ == 3'b111) |
|
||||
(buf_byteen[get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0],buf_byteen[7:0],1'b1)] == 1'b0));
|
||||
ahb_htrans[1:0] = {2{~(cmd_done | cmd_doneQ)}} & 2'b10;
|
||||
end
|
||||
DATA_WR: begin
|
||||
buf_state_en = (cmd_doneQ & ahb_hready_q) | ahb_hresp_q;
|
||||
master_ready = buf_state_en & ~ahb_hresp_q & slave_ready; // Ready to accept new command if current command done and no error
|
||||
buf_nxtstate = (ahb_hresp_q | ~slave_ready) ? DONE :
|
||||
((master_valid & master_ready) ? ((master_opc[2:1] == 2'b01) ? CMD_WR : CMD_RD) : IDLE);
|
||||
slvbuf_error_in = ahb_hresp_q;
|
||||
slvbuf_error_en = buf_state_en;
|
||||
|
||||
buf_write_in = (master_opc[2:1] == 2'b01);
|
||||
buf_wr_en = buf_state_en & ((buf_nxtstate == CMD_WR) | (buf_nxtstate == CMD_RD));
|
||||
buf_data_wr_en = buf_wr_en;
|
||||
|
||||
cmd_done = (ahb_hresp_q | (ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) &
|
||||
((buf_cmd_byte_ptrQ == 3'b111) | (buf_byteen[get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0],buf_byteen[7:0],1'b1)] == 1'b0))));
|
||||
bypass_en = buf_state_en & buf_write_in & (buf_nxtstate == CMD_WR); // Only bypass for writes for the time being
|
||||
ahb_htrans[1:0] = {2{(~(cmd_done | cmd_doneQ) | bypass_en)}} & 2'b10;
|
||||
slave_valid_pre = buf_state_en & (buf_nxtstate != DONE);
|
||||
|
||||
trxn_done = ahb_hready_q & ahb_hwrite_q & (ahb_htrans_q[1:0] != 2'b0);
|
||||
buf_cmd_byte_ptr_en = trxn_done | bypass_en;
|
||||
buf_cmd_byte_ptr = bypass_en ? get_nxtbyte_ptr(3'b0,buf_byteen_in[7:0],1'b0) :
|
||||
trxn_done ? get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0],buf_byteen[7:0],1'b1) : buf_cmd_byte_ptrQ;
|
||||
end
|
||||
DONE: begin
|
||||
buf_nxtstate = IDLE;
|
||||
buf_state_en = slave_ready;
|
||||
slvbuf_error_en = 1'b1;
|
||||
slave_valid_pre = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
assign buf_rst = 1'b0;
|
||||
assign cmd_done_rst = slave_valid_pre;
|
||||
assign buf_addr_in[2:0] = (buf_aligned_in & (master_opc[2:1] == 2'b01)) ? get_write_addr(wrbuf_byteen[7:0]) : master_addr[2:0];
|
||||
assign buf_addr_in[31:3] = master_addr[31:3];
|
||||
assign buf_tag_in[TAG-1:0] = master_tag[TAG-1:0];
|
||||
assign buf_byteen_in[7:0] = wrbuf_byteen[7:0];
|
||||
assign buf_data_in[63:0] = (buf_state == DATA_RD) ? ahb_hrdata_q[63:0] : master_wdata[63:0];
|
||||
assign buf_size_in[1:0] = (buf_aligned_in & (master_size[1:0] == 2'b11) & (master_opc[2:1] == 2'b01)) ? get_write_size(wrbuf_byteen[7:0]) : master_size[1:0];
|
||||
assign buf_aligned_in = (master_opc[2:0] == 3'b0) | // reads are always aligned since they are either DW or sideeffects
|
||||
(master_size[1:0] == 2'b0) | (master_size[1:0] == 2'b01) | (master_size[1:0] == 2'b10) | // Always aligned for Byte/HW/Word since they can be only for non-idempotent. IFU/SB are always aligned
|
||||
((master_size[1:0] == 2'b11) &
|
||||
((wrbuf_byteen[7:0] == 8'h3) | (wrbuf_byteen[7:0] == 8'hc) | (wrbuf_byteen[7:0] == 8'h30) | (wrbuf_byteen[7:0] == 8'hc0) |
|
||||
(wrbuf_byteen[7:0] == 8'hf) | (wrbuf_byteen[7:0] == 8'hf0) | (wrbuf_byteen[7:0] == 8'hff)));
|
||||
|
||||
// Generate the ahb signals
|
||||
assign ahb_haddr[31:0] = bypass_en ? {master_addr[31:3],buf_cmd_byte_ptr[2:0]} : {buf_addr[31:3],buf_cmd_byte_ptr[2:0]};
|
||||
// assign ahb_hsize[2:0] = ((buf_state == CMD_RD) | (buf_state == STREAM_RD) | (buf_state == STREAM_ERR_RD) | rd_bypass_idle) ? 3'b011 :
|
||||
// bypass_en ? {1'b0, ({2{buf_aligned_in}} & buf_size_in[1:0])} :
|
||||
// {1'b0, ({2{buf_aligned}} & buf_size[1:0])}; // Send the full size for aligned trxn
|
||||
assign ahb_hsize[2:0] = bypass_en ? {1'b0, ({2{buf_aligned_in}} & buf_size_in[1:0])} :
|
||||
{1'b0, ({2{buf_aligned}} & buf_size[1:0])}; // Send the full size for aligned trxn
|
||||
assign ahb_hburst[2:0] = 3'b0;
|
||||
assign ahb_hmastlock = 1'b0;
|
||||
assign ahb_hprot[3:0] = {3'b001,~axi_arprot[2]};
|
||||
assign ahb_hwrite = bypass_en ? (master_opc[2:1] == 2'b01) : buf_write;
|
||||
assign ahb_hwdata[63:0] = buf_data[63:0];
|
||||
|
||||
assign slave_valid = slave_valid_pre;
|
||||
assign slave_opc[3:2] = slvbuf_write ? 2'b11 : 2'b00;
|
||||
assign slave_opc[1:0] = {2{slvbuf_error}} & 2'b10;
|
||||
assign slave_rdata[63:0] = slvbuf_error ? {2{last_bus_addr[31:0]}} : ((buf_state == DONE) ? buf_data[63:0] : ahb_hrdata_q[63:0]);
|
||||
assign slave_tag[TAG-1:0] = slvbuf_tag[TAG-1:0];
|
||||
|
||||
assign last_addr_en = (ahb_htrans[1:0] != 2'b0) & ahb_hready & ahb_hwrite ;
|
||||
|
||||
|
||||
rvdffsc #(.WIDTH(1)) wrbuf_vldff (.din(1'b1), .dout(wrbuf_vld), .en(wrbuf_en), .clear(wrbuf_rst), .clk(bus_clk), .*);
|
||||
rvdffsc #(.WIDTH(1)) wrbuf_data_vldff(.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_rst), .clk(bus_clk), .*);
|
||||
rvdffs #(.WIDTH(TAG)) wrbuf_tagff (.din(axi_awid[TAG-1:0]), .dout(wrbuf_tag[TAG-1:0]), .en(wrbuf_en), .clk(bus_clk), .*);
|
||||
rvdffs #(.WIDTH(3)) wrbuf_sizeff (.din(axi_awsize[2:0]), .dout(wrbuf_size[2:0]), .en(wrbuf_en), .clk(bus_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) wrbuf_addrff (.din(axi_awaddr[31:0]), .dout(wrbuf_addr[31:0]), .en(wrbuf_en), .clk(bus_clk), .*);
|
||||
rvdffe #(.WIDTH(64)) wrbuf_dataff (.din(axi_wdata[63:0]), .dout(wrbuf_data[63:0]), .en(wrbuf_data_en), .clk(bus_clk), .*);
|
||||
rvdffs #(.WIDTH(8)) wrbuf_byteenff (.din(axi_wstrb[7:0]), .dout(wrbuf_byteen[7:0]), .en(wrbuf_data_en), .clk(bus_clk), .*);
|
||||
|
||||
rvdffs #(.WIDTH(32)) last_bus_addrff (.din(ahb_haddr[31:0]), .dout(last_bus_addr[31:0]), .en(last_addr_en), .clk(ahbm_clk), .*);
|
||||
|
||||
rvdffsc #(.WIDTH($bits(state_t))) buf_state_ff (.din(buf_nxtstate), .dout({buf_state}), .en(buf_state_en), .clear(buf_rst), .clk(ahbm_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_writeff (.din(buf_write_in), .dout(buf_write), .en(buf_wr_en), .clk(buf_clk), .*);
|
||||
rvdffs #(.WIDTH(TAG)) buf_tagff (.din(buf_tag_in[TAG-1:0]), .dout(buf_tag[TAG-1:0]), .en(buf_wr_en), .clk(buf_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) buf_addrff (.din(buf_addr_in[31:0]), .dout(buf_addr[31:0]), .en(buf_wr_en & bus_clk_en), .*);
|
||||
rvdffs #(.WIDTH(2)) buf_sizeff (.din(buf_size_in[1:0]), .dout(buf_size[1:0]), .en(buf_wr_en), .clk(buf_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_alignedff (.din(buf_aligned_in), .dout(buf_aligned), .en(buf_wr_en), .clk(buf_clk), .*);
|
||||
rvdffs #(.WIDTH(8)) buf_byteenff (.din(buf_byteen_in[7:0]), .dout(buf_byteen[7:0]), .en(buf_wr_en), .clk(buf_clk), .*);
|
||||
rvdffe #(.WIDTH(64)) buf_dataff (.din(buf_data_in[63:0]), .dout(buf_data[63:0]), .en(buf_data_wr_en & bus_clk_en), .*);
|
||||
|
||||
|
||||
rvdffs #(.WIDTH(1)) slvbuf_writeff (.din(buf_write), .dout(slvbuf_write), .en(slvbuf_wr_en), .clk(buf_clk), .*);
|
||||
rvdffs #(.WIDTH(TAG)) slvbuf_tagff (.din(buf_tag[TAG-1:0]), .dout(slvbuf_tag[TAG-1:0]), .en(slvbuf_wr_en), .clk(buf_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) slvbuf_errorff (.din(slvbuf_error_in), .dout(slvbuf_error), .en(slvbuf_error_en), .clk(ahbm_clk), .*);
|
||||
|
||||
rvdffsc #(.WIDTH(1)) buf_cmd_doneff (.din(1'b1), .en(cmd_done), .dout(cmd_doneQ), .clear(cmd_done_rst), .clk(ahbm_clk), .*);
|
||||
rvdffs #(.WIDTH(3)) buf_cmd_byte_ptrff (.din(buf_cmd_byte_ptr[2:0]), .dout(buf_cmd_byte_ptrQ[2:0]), .en(buf_cmd_byte_ptr_en), .clk(ahbm_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) hready_ff (.din(ahb_hready), .dout(ahb_hready_q), .clk(ahbm_clk), .*);
|
||||
rvdff #(.WIDTH(2)) htrans_ff (.din(ahb_htrans[1:0]), .dout(ahb_htrans_q[1:0]), .clk(ahbm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) hwrite_ff (.din(ahb_hwrite), .dout(ahb_hwrite_q), .clk(ahbm_addr_clk), .*);
|
||||
rvdff #(.WIDTH(1)) hresp_ff (.din(ahb_hresp), .dout(ahb_hresp_q), .clk(ahbm_clk), .*);
|
||||
rvdff #(.WIDTH(64)) hrdata_ff (.din(ahb_hrdata[63:0]), .dout(ahb_hrdata_q[63:0]), .clk(ahbm_data_clk), .*);
|
||||
|
||||
// Clock headers
|
||||
// clock enables for ahbm addr/data
|
||||
assign buf_clken = bus_clk_en & (buf_wr_en | slvbuf_wr_en | clk_override);
|
||||
assign ahbm_addr_clken = bus_clk_en & ((ahb_hready & ahb_htrans[1]) | clk_override);
|
||||
assign ahbm_data_clken = bus_clk_en & ((buf_state != IDLE) | clk_override);
|
||||
|
||||
rvclkhdr buf_cgc (.en(buf_clken), .l1clk(buf_clk), .*);
|
||||
rvclkhdr ahbm_cgc (.en(bus_clk_en), .l1clk(ahbm_clk), .*);
|
||||
rvclkhdr ahbm_addr_cgc (.en(ahbm_addr_clken), .l1clk(ahbm_addr_clk), .*);
|
||||
rvclkhdr ahbm_data_cgc (.en(ahbm_data_clken), .l1clk(ahbm_data_clk), .*);
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
property ahb_trxn_aligned;
|
||||
@(posedge ahbm_clk) ahb_htrans[1] |-> ((ahb_hsize[2:0] == 3'h0) |
|
||||
((ahb_hsize[2:0] == 3'h1) & (ahb_haddr[0] == 1'b0)) |
|
||||
((ahb_hsize[2:0] == 3'h2) & (ahb_haddr[1:0] == 2'b0)) |
|
||||
((ahb_hsize[2:0] == 3'h3) & (ahb_haddr[2:0] == 3'b0)));
|
||||
endproperty
|
||||
assert_ahb_trxn_aligned: assert property (ahb_trxn_aligned) else
|
||||
$display("Assertion ahb_trxn_aligned failed: ahb_htrans=2'h%h, ahb_hsize=3'h%h, ahb_haddr=32'h%h",ahb_htrans[1:0], ahb_hsize[2:0], ahb_haddr[31:0]);
|
||||
|
||||
property ahb_error_protocol;
|
||||
@(posedge ahbm_clk) (ahb_hready & ahb_hresp) |-> (~$past(ahb_hready) & $past(ahb_hresp));
|
||||
endproperty
|
||||
assert_ahb_error_protocol: assert property (ahb_error_protocol) else
|
||||
$display("Bus Error with hReady isn't preceded with Bus Error without hready");
|
||||
`endif
|
||||
|
||||
endmodule // axi4_to_ahb
|
|
@ -0,0 +1,452 @@
|
|||
// 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.
|
||||
|
||||
// all flops call the rvdff flop
|
||||
|
||||
|
||||
module rvdff #( parameter WIDTH=1 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
`ifdef CLOCKGATE
|
||||
always @(posedge tb_top.clk) begin
|
||||
#0 $strobe("CG: %0t %m din %x dout %x clk %b width %d",$time,din,dout,clk,WIDTH);
|
||||
end
|
||||
`endif
|
||||
|
||||
always_ff @(posedge clk or negedge rst_l) begin
|
||||
if (rst_l == 0)
|
||||
dout[WIDTH-1:0] <= 0;
|
||||
else
|
||||
dout[WIDTH-1:0] <= din[WIDTH-1:0];
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// rvdff with 2:1 input mux to flop din iff sel==1
|
||||
module rvdffs #( parameter WIDTH=1 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic en,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
rvdff #(WIDTH) dffs (.din((en) ? din[WIDTH-1:0] : dout[WIDTH-1:0]), .*);
|
||||
|
||||
endmodule
|
||||
|
||||
// rvdff with en and clear
|
||||
module rvdffsc #( parameter WIDTH=1 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic en,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] din_new;
|
||||
assign din_new = {WIDTH{~clear}} & (en ? din[WIDTH-1:0] : dout[WIDTH-1:0]);
|
||||
rvdff #(WIDTH) dffsc (.din(din_new[WIDTH-1:0]), .*);
|
||||
|
||||
endmodule
|
||||
|
||||
module `TEC_RV_ICG
|
||||
(
|
||||
input logic TE, E, CP,
|
||||
output Q
|
||||
);
|
||||
|
||||
logic en_ff;
|
||||
logic enable;
|
||||
|
||||
assign enable = E | TE;
|
||||
|
||||
`ifdef VERILATOR
|
||||
always @(negedge CP) begin
|
||||
en_ff <= enable;
|
||||
end
|
||||
`else
|
||||
always @(CP, enable) begin
|
||||
if(!CP)
|
||||
en_ff = enable;
|
||||
end
|
||||
`endif
|
||||
assign Q = CP & en_ff;
|
||||
|
||||
endmodule
|
||||
|
||||
module rvclkhdr
|
||||
(
|
||||
input logic en,
|
||||
input logic clk,
|
||||
input logic scan_mode,
|
||||
output logic l1clk
|
||||
);
|
||||
|
||||
logic TE;
|
||||
assign TE = scan_mode;
|
||||
|
||||
`TEC_RV_ICG rvclkhdr ( .*, .E(en), .CP(clk), .Q(l1clk));
|
||||
|
||||
endmodule
|
||||
|
||||
module rvdffe #( parameter WIDTH=1 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic en,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic scan_mode,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic l1clk;
|
||||
|
||||
`ifndef PHYSICAL
|
||||
if (WIDTH >= 8) begin: genblock
|
||||
`endif
|
||||
rvclkhdr clkhdr ( .* );
|
||||
rvdff #(WIDTH) dff (.*, .clk(l1clk));
|
||||
`ifndef PHYSICAL
|
||||
end
|
||||
else
|
||||
$error("%m: rvdffe width must be >= 8");
|
||||
`endif
|
||||
|
||||
endmodule // rvdffe
|
||||
|
||||
module rvsyncss #(parameter WIDTH = 251)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic [WIDTH-1:0] din,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] din_ff1;
|
||||
|
||||
rvdff #(WIDTH) sync_ff1 (.*, .din (din[WIDTH-1:0]), .dout(din_ff1[WIDTH-1:0]));
|
||||
rvdff #(WIDTH) sync_ff2 (.*, .din (din_ff1[WIDTH-1:0]), .dout(dout[WIDTH-1:0]));
|
||||
|
||||
endmodule // rvsyncss
|
||||
|
||||
module rvlsadder
|
||||
(
|
||||
input logic [31:0] rs1,
|
||||
input logic [11:0] offset,
|
||||
|
||||
output logic [31:0] dout
|
||||
);
|
||||
|
||||
logic cout;
|
||||
logic sign;
|
||||
|
||||
logic [31:12] rs1_inc;
|
||||
logic [31:12] rs1_dec;
|
||||
|
||||
assign {cout,dout[11:0]} = {1'b0,rs1[11:0]} + {1'b0,offset[11:0]};
|
||||
|
||||
assign rs1_inc[31:12] = rs1[31:12] + 1;
|
||||
|
||||
assign rs1_dec[31:12] = rs1[31:12] - 1;
|
||||
|
||||
assign sign = offset[11];
|
||||
|
||||
assign dout[31:12] = ({20{ sign ^~ cout}} & rs1[31:12]) |
|
||||
({20{ ~sign & cout}} & rs1_inc[31:12]) |
|
||||
({20{ sign & ~cout}} & rs1_dec[31:12]);
|
||||
|
||||
endmodule // rvlsadder
|
||||
|
||||
// assume we only maintain pc[31:1] in the pipe
|
||||
|
||||
module rvbradder
|
||||
(
|
||||
input [31:1] pc,
|
||||
input [12:1] offset,
|
||||
|
||||
output [31:1] dout
|
||||
);
|
||||
|
||||
logic cout;
|
||||
logic sign;
|
||||
|
||||
logic [31:13] pc_inc;
|
||||
logic [31:13] pc_dec;
|
||||
|
||||
assign {cout,dout[12:1]} = {1'b0,pc[12:1]} + {1'b0,offset[12:1]};
|
||||
|
||||
assign pc_inc[31:13] = pc[31:13] + 1;
|
||||
|
||||
assign pc_dec[31:13] = pc[31:13] - 1;
|
||||
|
||||
assign sign = offset[12];
|
||||
|
||||
|
||||
assign dout[31:13] = ({19{ sign ^~ cout}} & pc[31:13]) |
|
||||
({19{ ~sign & cout}} & pc_inc[31:13]) |
|
||||
({19{ sign & ~cout}} & pc_dec[31:13]);
|
||||
|
||||
|
||||
endmodule // rvbradder
|
||||
|
||||
|
||||
// 2s complement circuit
|
||||
module rvtwoscomp #( parameter WIDTH=32 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:1] dout_temp; // holding for all other bits except for the lsb. LSB is always din
|
||||
|
||||
genvar i;
|
||||
|
||||
for ( i = 1; i < WIDTH; i++ ) begin : flip_after_first_one
|
||||
assign dout_temp[i] = (|din[i-1:0]) ? ~din[i] : din[i];
|
||||
end : flip_after_first_one
|
||||
|
||||
assign dout[WIDTH-1:0] = { dout_temp[WIDTH-1:1], din[0] };
|
||||
|
||||
endmodule // 2'scomp
|
||||
|
||||
// find first
|
||||
module rvfindfirst1 #( parameter WIDTH=32, SHIFT=$clog2(WIDTH) )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
|
||||
output logic [SHIFT-1:0] dout
|
||||
);
|
||||
logic done;
|
||||
|
||||
always_comb begin
|
||||
dout[SHIFT-1:0] = {SHIFT{1'b0}};
|
||||
done = 1'b0;
|
||||
|
||||
for ( int i = WIDTH-1; i > 0; i-- ) begin : find_first_one
|
||||
done |= din[i];
|
||||
dout[SHIFT-1:0] += done ? 1'b0 : 1'b1;
|
||||
end : find_first_one
|
||||
end
|
||||
endmodule // rvfindfirst1
|
||||
|
||||
module rvfindfirst1hot #( parameter WIDTH=32 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
logic done;
|
||||
|
||||
always_comb begin
|
||||
dout[WIDTH-1:0] = {WIDTH{1'b0}};
|
||||
done = 1'b0;
|
||||
for ( int i = 0; i < WIDTH; i++ ) begin : find_first_one
|
||||
dout[i] = ~done & din[i];
|
||||
done |= din[i];
|
||||
end : find_first_one
|
||||
end
|
||||
endmodule // rvfindfirst1hot
|
||||
|
||||
// mask and match function matches bits after finding the first 0 position
|
||||
// find first starting from LSB. Skip that location and match the rest of the bits
|
||||
module rvmaskandmatch #( parameter WIDTH=32 )
|
||||
(
|
||||
input logic [WIDTH-1:0] mask, // this will have the mask in the lower bit positions
|
||||
input logic [WIDTH-1:0] data, // this is what needs to be matched on the upper bits with the mask's upper bits
|
||||
input logic masken, // when 1 : do mask. 0 : full match
|
||||
output logic match
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] matchvec;
|
||||
logic masken_or_fullmask;
|
||||
|
||||
assign masken_or_fullmask = masken & ~(&mask[WIDTH-1:0]);
|
||||
|
||||
assign matchvec[0] = masken_or_fullmask | (mask[0] == data[0]);
|
||||
genvar i;
|
||||
|
||||
for ( i = 1; i < WIDTH; i++ ) begin : match_after_first_zero
|
||||
assign matchvec[i] = (&mask[i-1:0] & masken_or_fullmask) ? 1'b1 : (mask[i] == data[i]);
|
||||
end : match_after_first_zero
|
||||
|
||||
assign match = &matchvec[WIDTH-1:0]; // all bits either matched or were masked off
|
||||
|
||||
endmodule // rvmaskandmatch
|
||||
|
||||
module rvbtb_tag_hash (
|
||||
input logic [31:1] pc,
|
||||
output logic [`RV_BTB_BTAG_SIZE-1:0] hash
|
||||
);
|
||||
`ifndef RV_BTB_BTAG_FOLD
|
||||
assign hash = {(pc[`RV_BTB_ADDR_HI+`RV_BTB_BTAG_SIZE+`RV_BTB_BTAG_SIZE+`RV_BTB_BTAG_SIZE:`RV_BTB_ADDR_HI+`RV_BTB_BTAG_SIZE+`RV_BTB_BTAG_SIZE+1] ^
|
||||
pc[`RV_BTB_ADDR_HI+`RV_BTB_BTAG_SIZE+`RV_BTB_BTAG_SIZE:`RV_BTB_ADDR_HI+`RV_BTB_BTAG_SIZE+1] ^
|
||||
pc[`RV_BTB_ADDR_HI+`RV_BTB_BTAG_SIZE:`RV_BTB_ADDR_HI+1])};
|
||||
`else
|
||||
assign hash = {(
|
||||
pc[`RV_BTB_ADDR_HI+`RV_BTB_BTAG_SIZE+`RV_BTB_BTAG_SIZE:`RV_BTB_ADDR_HI+`RV_BTB_BTAG_SIZE+1] ^
|
||||
pc[`RV_BTB_ADDR_HI+`RV_BTB_BTAG_SIZE:`RV_BTB_ADDR_HI+1])};
|
||||
`endif
|
||||
|
||||
// assign hash = {pc[`RV_BTB_ADDR_HI+1],(pc[`RV_BTB_ADDR_HI+13:`RV_BTB_ADDR_HI+10] ^
|
||||
// pc[`RV_BTB_ADDR_HI+9:`RV_BTB_ADDR_HI+6] ^
|
||||
// pc[`RV_BTB_ADDR_HI+5:`RV_BTB_ADDR_HI+2])};
|
||||
|
||||
endmodule
|
||||
|
||||
module rvbtb_addr_hash (
|
||||
input logic [31:1] pc,
|
||||
output logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] hash
|
||||
);
|
||||
|
||||
assign hash[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] = pc[`RV_BTB_INDEX1_HI:`RV_BTB_INDEX1_LO] ^
|
||||
|
||||
`ifndef RV_BTB_FOLD2_INDEX_HASH
|
||||
pc[`RV_BTB_INDEX2_HI:`RV_BTB_INDEX2_LO] ^
|
||||
`endif
|
||||
|
||||
pc[`RV_BTB_INDEX3_HI:`RV_BTB_INDEX3_LO];
|
||||
|
||||
endmodule
|
||||
|
||||
module rvbtb_ghr_hash (
|
||||
input logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] hashin,
|
||||
input logic [`RV_BHT_GHR_RANGE] ghr,
|
||||
output logic [`RV_BHT_ADDR_HI:`RV_BHT_ADDR_LO] hash
|
||||
);
|
||||
|
||||
// The hash function is too complex to write in verilog for all cases.
|
||||
// The config script generates the logic string based on the bp config.
|
||||
assign hash[`RV_BHT_ADDR_HI:`RV_BHT_ADDR_LO] = `RV_BHT_HASH_STRING;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
// Check if the S_ADDR <= addr < E_ADDR
|
||||
module rvrangecheck #(CCM_SADR = 32'h0,
|
||||
CCM_SIZE = 128) (
|
||||
input logic [31:0] addr, // Address to be checked for range
|
||||
output logic in_range, // S_ADDR <= start_addr < E_ADDR
|
||||
output logic in_region
|
||||
);
|
||||
|
||||
localparam REGION_BITS = 4;
|
||||
localparam MASK_BITS = 10 + $clog2(CCM_SIZE);
|
||||
|
||||
logic [31:0] start_addr;
|
||||
logic [3:0] region;
|
||||
|
||||
assign start_addr[31:0] = CCM_SADR;
|
||||
assign region[REGION_BITS-1:0] = start_addr[31:(32-REGION_BITS)];
|
||||
|
||||
assign in_region = (addr[31:(32-REGION_BITS)] == region[REGION_BITS-1:0]);
|
||||
if (CCM_SIZE == 48)
|
||||
assign in_range = (addr[31:MASK_BITS] == start_addr[31:MASK_BITS]) & ~(&addr[MASK_BITS-1 : MASK_BITS-2]);
|
||||
else
|
||||
assign in_range = (addr[31:MASK_BITS] == start_addr[31:MASK_BITS]);
|
||||
|
||||
endmodule // rvrangechecker
|
||||
|
||||
// 16 bit even parity generator
|
||||
module rveven_paritygen #(WIDTH = 16) (
|
||||
input logic [WIDTH-1:0] data_in, // Data
|
||||
output logic parity_out // generated even parity
|
||||
);
|
||||
|
||||
assign parity_out = ^(data_in[WIDTH-1:0]) ;
|
||||
|
||||
endmodule // rveven_paritygen
|
||||
|
||||
module rveven_paritycheck #(WIDTH = 16) (
|
||||
input logic [WIDTH-1:0] data_in, // Data
|
||||
input logic parity_in,
|
||||
output logic parity_err // Parity error
|
||||
);
|
||||
|
||||
assign parity_err = ^(data_in[WIDTH-1:0]) ^ parity_in ;
|
||||
|
||||
endmodule // rveven_paritycheck
|
||||
|
||||
module rvecc_encode (
|
||||
input [31:0] din,
|
||||
output [6:0] ecc_out
|
||||
);
|
||||
logic [5:0] ecc_out_temp;
|
||||
|
||||
assign ecc_out_temp[0] = din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30];
|
||||
assign ecc_out_temp[1] = din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31];
|
||||
assign ecc_out_temp[2] = din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31];
|
||||
assign ecc_out_temp[3] = din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
||||
assign ecc_out_temp[4] = din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
||||
assign ecc_out_temp[5] = din[26]^din[27]^din[28]^din[29]^din[30]^din[31];
|
||||
|
||||
assign ecc_out[6:0] = {(^din[31:0])^(^ecc_out_temp[5:0]),ecc_out_temp[5:0]};
|
||||
|
||||
endmodule // rvecc_encode
|
||||
|
||||
module rvecc_decode (
|
||||
input en,
|
||||
input [31:0] din,
|
||||
input [6:0] ecc_in,
|
||||
input sed_ded, // only do detection and no correction. Used for the I$
|
||||
output [31:0] dout,
|
||||
output [6:0] ecc_out,
|
||||
output single_ecc_error,
|
||||
output double_ecc_error
|
||||
|
||||
);
|
||||
|
||||
logic [6:0] ecc_check;
|
||||
logic [38:0] error_mask;
|
||||
logic [38:0] din_plus_parity, dout_plus_parity;
|
||||
|
||||
// Generate the ecc bits
|
||||
assign ecc_check[0] = ecc_in[0]^din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30];
|
||||
assign ecc_check[1] = ecc_in[1]^din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31];
|
||||
assign ecc_check[2] = ecc_in[2]^din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31];
|
||||
assign ecc_check[3] = ecc_in[3]^din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
||||
assign ecc_check[4] = ecc_in[4]^din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
||||
assign ecc_check[5] = ecc_in[5]^din[26]^din[27]^din[28]^din[29]^din[30]^din[31];
|
||||
|
||||
// This is the parity bit
|
||||
assign ecc_check[6] = ((^din[31:0])^(^ecc_in[6:0])) & ~sed_ded;
|
||||
|
||||
assign single_ecc_error = en & (ecc_check[6:0] != 0) & ecc_check[6]; // this will never be on for sed_ded
|
||||
assign double_ecc_error = en & (ecc_check[6:0] != 0) & ~ecc_check[6]; // all errors in the sed_ded case will be recorded as DE
|
||||
|
||||
// Generate the mask for error correctiong
|
||||
for (genvar i=1; i<40; i++) begin
|
||||
assign error_mask[i-1] = (ecc_check[5:0] == i);
|
||||
end
|
||||
|
||||
// Generate the corrected data
|
||||
assign din_plus_parity[38:0] = {ecc_in[6], din[31:26], ecc_in[5], din[25:11], ecc_in[4], din[10:4], ecc_in[3], din[3:1], ecc_in[2], din[0], ecc_in[1:0]};
|
||||
|
||||
assign dout_plus_parity[38:0] = single_ecc_error ? (error_mask[38:0] ^ din_plus_parity[38:0]) : din_plus_parity[38:0];
|
||||
assign dout[31:0] = {dout_plus_parity[37:32], dout_plus_parity[30:16], dout_plus_parity[14:8], dout_plus_parity[6:4], dout_plus_parity[2]};
|
||||
assign ecc_out[6:0] = {(dout_plus_parity[38] ^ (ecc_check[6:0] == 7'b1000000)), dout_plus_parity[31], dout_plus_parity[15], dout_plus_parity[7], dout_plus_parity[3], dout_plus_parity[1:0]};
|
||||
|
||||
endmodule // rvecc_decode
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,389 @@
|
|||
// 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$
|
||||
//
|
||||
//
|
||||
// Function: Top level file for load store unit
|
||||
// Comments:
|
||||
//
|
||||
//
|
||||
// DC1 -> DC2 -> DC3 -> DC4 (Commit)
|
||||
//
|
||||
//********************************************************************************
|
||||
|
||||
module lsu
|
||||
import swerv_types::*;
|
||||
(
|
||||
|
||||
input logic [31:0] i0_result_e4_eff, // I0 e4 result for e4 -> dc3 store forwarding
|
||||
input logic [31:0] i1_result_e4_eff, // I1 e4 result for e4 -> dc3 store forwarding
|
||||
input logic [31:0] i0_result_e2, // I0 e2 result for e2 -> dc2 store forwarding
|
||||
|
||||
input logic flush_final_e3, // I0/I1 flush in e3
|
||||
input logic i0_flush_final_e3, // I0 flush in e3
|
||||
input logic dec_tlu_flush_lower_wb, // I0/I1 writeback flush. This is used to flush the old packets only
|
||||
input logic dec_tlu_i0_kill_writeb_wb, // I0 is flushed, don't writeback any results to arch state
|
||||
input logic dec_tlu_i1_kill_writeb_wb, // I1 is flushed, don't writeback any results to arch state
|
||||
input logic dec_tlu_cancel_e4, // cancel the bus load in dc4 and reset the freeze
|
||||
|
||||
// chicken signals
|
||||
input logic dec_tlu_non_blocking_disable, // disable the non block
|
||||
input logic dec_tlu_wb_coalescing_disable, // disable the write buffer coalesce
|
||||
input logic dec_tlu_ld_miss_byp_wb_disable, // disable the miss bypass in the write buffer
|
||||
input logic dec_tlu_sideeffect_posted_disable, // disable posted writes to sideeffect addr to the bus
|
||||
input logic dec_tlu_core_ecc_disable, // disable the generation of the ecc
|
||||
|
||||
input logic [31:0] exu_lsu_rs1_d, // address rs operand
|
||||
input logic [31:0] exu_lsu_rs2_d, // store data
|
||||
input logic [11:0] dec_lsu_offset_d, // address offset operand
|
||||
|
||||
input lsu_pkt_t lsu_p, // lsu control packet
|
||||
input logic dec_i0_lsu_decode_d, // lsu is in i0
|
||||
input logic [31:0] dec_tlu_mrac_ff, // CSR for memory region control
|
||||
|
||||
output logic [31:0] lsu_result_dc3, // lsu load data
|
||||
output logic [31:0] lsu_result_corr_dc4, // This is the ECC corrected data going to RF
|
||||
output logic lsu_freeze_dc3, // lsu freeze due to load to external
|
||||
output logic lsu_load_stall_any, // This is for blocking loads in the decode
|
||||
output logic lsu_store_stall_any, // This is for blocking stores in the decode
|
||||
output logic lsu_idle_any, // lsu buffers are empty and no instruction in the pipeline
|
||||
output logic lsu_halt_idle_any, // This is used to enter halt mode. Exclude DMA
|
||||
|
||||
output lsu_error_pkt_t lsu_error_pkt_dc3, // lsu exception packet
|
||||
output logic lsu_freeze_external_ints_dc3, // freeze due to sideeffects loads need to suppress external interrupt
|
||||
output logic lsu_imprecise_error_load_any, // bus load imprecise error
|
||||
output logic lsu_imprecise_error_store_any, // bus store imprecise error
|
||||
output logic [31:0] lsu_imprecise_error_addr_any, // bus store imprecise error address
|
||||
|
||||
// Non-blocking loads
|
||||
input logic dec_nonblock_load_freeze_dc2, //
|
||||
output logic lsu_nonblock_load_valid_dc3, // there is an external load -> put in the cam
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_dc3, // the tag of the external non block load
|
||||
output logic lsu_nonblock_load_inv_dc5, // invalidate signal for the cam entry for non block loads
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_dc5, // tag of the enrty which needs to be invalidated
|
||||
output logic lsu_nonblock_load_data_valid, // the non block is valid - sending information back to the cam
|
||||
output logic lsu_nonblock_load_data_error, // non block load has an error
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // the tag of the non block load sending the data/error
|
||||
output logic [31:0] lsu_nonblock_load_data, // Data of the non block load
|
||||
|
||||
output logic lsu_pmu_misaligned_dc3, // PMU : misaligned
|
||||
output logic lsu_pmu_bus_trxn, // PMU : bus transaction
|
||||
output logic lsu_pmu_bus_misaligned, // PMU : misaligned access going to the bus
|
||||
output logic lsu_pmu_bus_error, // PMU : bus sending error back
|
||||
output logic lsu_pmu_bus_busy, // PMU : bus is not ready
|
||||
|
||||
// Trigger signals
|
||||
input trigger_pkt_t [3:0] trigger_pkt_any, // Trigger info from the decode
|
||||
output logic [3:0] lsu_trigger_match_dc3, // lsu trigger hit (one bit per trigger)
|
||||
|
||||
// DCCM ports
|
||||
output logic dccm_wren, // DCCM write enable
|
||||
output logic dccm_rden, // DCCM read enable
|
||||
output logic [`RV_DCCM_BITS-1:0] dccm_wr_addr, // DCCM write address (write can happen to one bank only)
|
||||
output logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_lo, // DCCM read address low bank
|
||||
output logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_hi, // DCCM read address hi bank (hi and low same if aligned read)
|
||||
output logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_wr_data, // DCCM write data (this is always aligned)
|
||||
|
||||
input logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // DCCM read data low bank
|
||||
input logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // DCCM read data hi bank
|
||||
|
||||
// PIC ports
|
||||
output logic picm_wren, // PIC memory write enable
|
||||
output logic picm_rden, // PIC memory read enable
|
||||
output logic picm_mken, // Need to read the mask for stores to determine which bits to write/forward
|
||||
output logic [31:0] picm_addr, // PIC memory address
|
||||
output logic [31:0] picm_wr_data, // PIC memory write data
|
||||
input logic [31:0] picm_rd_data, // PIC memory read/mask data
|
||||
|
||||
// AXI Write Channels
|
||||
output logic lsu_axi_awvalid,
|
||||
input logic lsu_axi_awready,
|
||||
output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_awid,
|
||||
output logic [31:0] lsu_axi_awaddr,
|
||||
output logic [3:0] lsu_axi_awregion,
|
||||
output logic [7:0] lsu_axi_awlen,
|
||||
output logic [2:0] lsu_axi_awsize,
|
||||
output logic [1:0] lsu_axi_awburst,
|
||||
output logic lsu_axi_awlock,
|
||||
output logic [3:0] lsu_axi_awcache,
|
||||
output logic [2:0] lsu_axi_awprot,
|
||||
output logic [3:0] lsu_axi_awqos,
|
||||
|
||||
output logic lsu_axi_wvalid,
|
||||
input logic lsu_axi_wready,
|
||||
output logic [63:0] lsu_axi_wdata,
|
||||
output logic [7:0] lsu_axi_wstrb,
|
||||
output logic lsu_axi_wlast,
|
||||
|
||||
input logic lsu_axi_bvalid,
|
||||
output logic lsu_axi_bready,
|
||||
input logic [1:0] lsu_axi_bresp,
|
||||
input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic lsu_axi_arvalid,
|
||||
input logic lsu_axi_arready,
|
||||
output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_arid,
|
||||
output logic [31:0] lsu_axi_araddr,
|
||||
output logic [3:0] lsu_axi_arregion,
|
||||
output logic [7:0] lsu_axi_arlen,
|
||||
output logic [2:0] lsu_axi_arsize,
|
||||
output logic [1:0] lsu_axi_arburst,
|
||||
output logic lsu_axi_arlock,
|
||||
output logic [3:0] lsu_axi_arcache,
|
||||
output logic [2:0] lsu_axi_arprot,
|
||||
output logic [3:0] lsu_axi_arqos,
|
||||
|
||||
input logic lsu_axi_rvalid,
|
||||
output logic lsu_axi_rready,
|
||||
input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_rid,
|
||||
input logic [63:0] lsu_axi_rdata,
|
||||
input logic [1:0] lsu_axi_rresp,
|
||||
input logic lsu_axi_rlast,
|
||||
|
||||
input logic lsu_bus_clk_en, // external drives a clock_en to control bus ratio
|
||||
|
||||
// DMA slave
|
||||
input logic dma_dccm_req, // DMA read/write to dccm
|
||||
input logic [31:0] dma_mem_addr, // DMA address
|
||||
input logic [2:0] dma_mem_sz, // DMA access size
|
||||
input logic dma_mem_write, // DMA access is a write
|
||||
input logic [63:0] dma_mem_wdata, // DMA write data
|
||||
|
||||
output logic dccm_dma_rvalid, // lsu data valid for DMA dccm read
|
||||
output logic dccm_dma_ecc_error, // DMA load had ecc error
|
||||
output logic [63:0] dccm_dma_rdata, // lsu data for DMA dccm read
|
||||
output logic dccm_ready, // lsu ready for DMA access
|
||||
|
||||
input logic clk_override, // Disable clock gating
|
||||
input logic scan_mode, // scan
|
||||
input logic clk,
|
||||
input logic free_clk,
|
||||
input logic rst_l
|
||||
|
||||
);
|
||||
|
||||
|
||||
`include "global.h"
|
||||
|
||||
logic lsu_dccm_rden_dc3;
|
||||
logic [63:0] store_data_dc2;
|
||||
logic [63:0] store_data_dc3;
|
||||
logic [31:0] store_data_dc4;
|
||||
logic [31:0] store_data_dc5;
|
||||
logic [31:0] store_ecc_datafn_hi_dc3;
|
||||
logic [31:0] store_ecc_datafn_lo_dc3;
|
||||
|
||||
logic single_ecc_error_hi_dc3, single_ecc_error_lo_dc3;
|
||||
logic lsu_single_ecc_error_dc3, lsu_single_ecc_error_dc4, lsu_single_ecc_error_dc5;
|
||||
logic lsu_double_ecc_error_dc3;
|
||||
|
||||
logic [31:0] dccm_data_hi_dc3;
|
||||
logic [31:0] dccm_data_lo_dc3;
|
||||
logic [6:0] dccm_data_ecc_hi_dc3;
|
||||
logic [6:0] dccm_data_ecc_lo_dc3;
|
||||
|
||||
logic [31:0] lsu_ld_data_dc3;
|
||||
logic [31:0] lsu_ld_data_corr_dc3;
|
||||
logic [31:0] picm_mask_data_dc3;
|
||||
|
||||
logic [31:0] lsu_addr_dc1, lsu_addr_dc2, lsu_addr_dc3, lsu_addr_dc4, lsu_addr_dc5;
|
||||
logic [31:0] end_addr_dc1, end_addr_dc2, end_addr_dc3, end_addr_dc4, end_addr_dc5;
|
||||
|
||||
lsu_pkt_t lsu_pkt_dc1, lsu_pkt_dc2, lsu_pkt_dc3, lsu_pkt_dc4, lsu_pkt_dc5;
|
||||
logic lsu_i0_valid_dc1, lsu_i0_valid_dc2, lsu_i0_valid_dc3, lsu_i0_valid_dc4, lsu_i0_valid_dc5;
|
||||
|
||||
// Store Buffer signals
|
||||
logic isldst_dc1, dccm_ldst_dc2, dccm_ldst_dc3;
|
||||
logic store_stbuf_reqvld_dc3;
|
||||
logic load_stbuf_reqvld_dc3;
|
||||
logic ldst_stbuf_reqvld_dc3;
|
||||
logic lsu_commit_dc5;
|
||||
logic lsu_exc_dc2;
|
||||
|
||||
logic addr_in_dccm_dc1, addr_in_dccm_dc2, addr_in_dccm_dc3;
|
||||
logic addr_in_pic_dc1, addr_in_pic_dc2, addr_in_pic_dc3;
|
||||
logic addr_external_dc2, addr_external_dc3, addr_external_dc4, addr_external_dc5;
|
||||
|
||||
logic stbuf_reqvld_any;
|
||||
logic stbuf_reqvld_flushed_any;
|
||||
logic stbuf_addr_in_pic_any;
|
||||
logic [DCCM_BYTE_WIDTH-1:0] stbuf_byteen_any;
|
||||
logic [LSU_SB_BITS-1:0] stbuf_addr_any;
|
||||
logic [DCCM_DATA_WIDTH-1:0] stbuf_data_any;
|
||||
logic [(DCCM_FDATA_WIDTH-DCCM_DATA_WIDTH-1):0] stbuf_ecc_any;
|
||||
|
||||
logic lsu_cmpen_dc2;
|
||||
logic [DCCM_DATA_WIDTH-1:0] stbuf_fwddata_hi_dc3;
|
||||
logic [DCCM_DATA_WIDTH-1:0] stbuf_fwddata_lo_dc3;
|
||||
logic [DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_dc3;
|
||||
logic [DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_dc3;
|
||||
|
||||
logic lsu_stbuf_commit_any;
|
||||
logic lsu_stbuf_empty_any;
|
||||
logic lsu_stbuf_nodma_empty_any; // Store Buffer is empty except dma writes
|
||||
logic lsu_stbuf_full_any;
|
||||
|
||||
// Bus signals
|
||||
logic lsu_busreq_dc5;
|
||||
logic lsu_bus_buffer_pend_any;
|
||||
logic lsu_bus_buffer_empty_any;
|
||||
logic lsu_bus_buffer_full_any;
|
||||
logic lsu_busreq_dc2;
|
||||
logic [31:0] bus_read_data_dc3;
|
||||
logic ld_bus_error_dc3;
|
||||
logic [31:0] ld_bus_error_addr_dc3;
|
||||
|
||||
logic flush_dc2_up, flush_dc3, flush_dc4, flush_dc5, flush_prior_dc5;
|
||||
logic is_sideeffects_dc2, is_sideeffects_dc3;
|
||||
logic ldst_nodma_dc1todc3;
|
||||
|
||||
|
||||
// Clocks
|
||||
logic lsu_c1_dc3_clk, lsu_c1_dc4_clk, lsu_c1_dc5_clk;
|
||||
logic lsu_c2_dc3_clk, lsu_c2_dc4_clk, lsu_c2_dc5_clk;
|
||||
logic lsu_freeze_c1_dc1_clk, lsu_freeze_c1_dc2_clk, lsu_freeze_c1_dc3_clk;
|
||||
logic lsu_store_c1_dc1_clk, lsu_store_c1_dc2_clk, lsu_store_c1_dc3_clk, lsu_store_c1_dc4_clk, lsu_store_c1_dc5_clk;
|
||||
|
||||
logic lsu_freeze_c2_dc1_clk, lsu_freeze_c2_dc2_clk, lsu_freeze_c2_dc3_clk, lsu_freeze_c2_dc4_clk;
|
||||
logic lsu_stbuf_c1_clk;
|
||||
logic lsu_bus_ibuf_c1_clk, lsu_bus_obuf_c1_clk, lsu_bus_buf_c1_clk;
|
||||
logic lsu_dccm_c1_dc3_clk, lsu_pic_c1_dc3_clk;
|
||||
logic lsu_busm_clk;
|
||||
logic lsu_free_c2_clk;
|
||||
|
||||
|
||||
lsu_lsc_ctl lsu_lsc_ctl(.*);
|
||||
|
||||
// block stores in decode - for either bus or stbuf reasons
|
||||
assign lsu_store_stall_any = lsu_stbuf_full_any | lsu_bus_buffer_full_any;
|
||||
assign lsu_load_stall_any = lsu_bus_buffer_full_any;
|
||||
|
||||
// Ready to accept dma trxns
|
||||
// There can't be any inpipe forwarding from non-dma packet to dma packet since they can be flushed so we can't have ld/st in dc3-dc5 when dma is in dc2
|
||||
assign ldst_nodma_dc1todc3 = (lsu_pkt_dc1.valid & ~lsu_pkt_dc1.dma) | (lsu_pkt_dc2.valid & ~lsu_pkt_dc2.dma) | (lsu_pkt_dc3.valid & ~lsu_pkt_dc3.dma);
|
||||
assign dccm_ready = ~(lsu_p.valid | lsu_stbuf_full_any | lsu_freeze_dc3 | ldst_nodma_dc1todc3);
|
||||
|
||||
// Generate per cycle flush signals
|
||||
assign flush_dc2_up = flush_final_e3 | i0_flush_final_e3 | dec_tlu_flush_lower_wb;
|
||||
assign flush_dc3 = (flush_final_e3 & i0_flush_final_e3) | dec_tlu_flush_lower_wb;
|
||||
assign flush_dc4 = dec_tlu_flush_lower_wb;
|
||||
assign flush_dc5 = (dec_tlu_i0_kill_writeb_wb | (dec_tlu_i1_kill_writeb_wb & ~lsu_i0_valid_dc5));
|
||||
assign flush_prior_dc5 = dec_tlu_i0_kill_writeb_wb & ~lsu_i0_valid_dc5; // Flush is due to i0 instruction and ld/st is in i1
|
||||
|
||||
// lsu idle
|
||||
assign lsu_idle_any = ~(lsu_pkt_dc1.valid | lsu_pkt_dc2.valid | lsu_pkt_dc3.valid | lsu_pkt_dc4.valid | lsu_pkt_dc5.valid) &
|
||||
lsu_bus_buffer_empty_any & lsu_stbuf_empty_any;
|
||||
|
||||
// lsu halt idle. This is used for entering the halt mode
|
||||
// Indicates non-idle if there is a instruction valid in dc1-dc5 or read/write buffers are non-empty since they can come with error
|
||||
// Need to make sure bus trxns are done and there are no non-dma writes in store buffer
|
||||
assign lsu_halt_idle_any = ~((lsu_pkt_dc1.valid & ~lsu_pkt_dc1.dma) |
|
||||
(lsu_pkt_dc2.valid & ~lsu_pkt_dc2.dma) |
|
||||
(lsu_pkt_dc3.valid & ~lsu_pkt_dc3.dma) |
|
||||
(lsu_pkt_dc4.valid & ~lsu_pkt_dc4.dma) |
|
||||
(lsu_pkt_dc5.valid & ~lsu_pkt_dc5.dma)) &
|
||||
lsu_bus_buffer_empty_any & lsu_stbuf_nodma_empty_any;
|
||||
|
||||
// Instantiate the store buffer
|
||||
//assign ldst_stbuf_reqvld_dc3 = store_stbuf_reqvld_dc3 | load_stbuf_reqvld_dc3;
|
||||
assign store_stbuf_reqvld_dc3 = lsu_pkt_dc3.valid & lsu_pkt_dc3.store & (addr_in_dccm_dc3 | addr_in_pic_dc3) & (~flush_dc3 | lsu_pkt_dc3.dma) & ~lsu_freeze_dc3;
|
||||
assign load_stbuf_reqvld_dc3 = lsu_pkt_dc3.valid & lsu_pkt_dc3.load & (addr_in_dccm_dc3 | addr_in_pic_dc3) & lsu_single_ecc_error_dc3 & (~flush_dc3 | lsu_pkt_dc3.dma) & ~lsu_freeze_dc3;
|
||||
|
||||
// These go to store buffer to detect full
|
||||
assign isldst_dc1 = lsu_pkt_dc1.valid & (lsu_pkt_dc1.load | lsu_pkt_dc1.store);
|
||||
assign dccm_ldst_dc2 = lsu_pkt_dc2.valid & (lsu_pkt_dc2.load | lsu_pkt_dc2.store) & (addr_in_dccm_dc2 | addr_in_pic_dc2);
|
||||
assign dccm_ldst_dc3 = lsu_pkt_dc3.valid & (lsu_pkt_dc3.load | lsu_pkt_dc3.store) & (addr_in_dccm_dc3 | addr_in_pic_dc3);
|
||||
|
||||
// Disable Forwarding for now
|
||||
assign lsu_cmpen_dc2 = lsu_pkt_dc2.valid & (lsu_pkt_dc2.load | lsu_pkt_dc2.store) & (addr_in_dccm_dc2 | addr_in_pic_dc2);
|
||||
|
||||
// Bus signals
|
||||
assign lsu_busreq_dc2 = lsu_pkt_dc2.valid & (lsu_pkt_dc2.load | lsu_pkt_dc2.store) & addr_external_dc2 & ~flush_dc2_up & ~lsu_exc_dc2;
|
||||
|
||||
// PMU signals
|
||||
assign lsu_pmu_misaligned_dc3 = lsu_pkt_dc3.valid & ((lsu_pkt_dc3.half & lsu_addr_dc3[0]) | (lsu_pkt_dc3.word & (|lsu_addr_dc3[1:0])));
|
||||
|
||||
|
||||
lsu_dccm_ctl dccm_ctl (
|
||||
.lsu_addr_dc1(lsu_addr_dc1[31:0]),
|
||||
.end_addr_dc1(end_addr_dc1[DCCM_BITS-1:0]),
|
||||
.lsu_addr_dc3(lsu_addr_dc3[DCCM_BITS-1:0]),
|
||||
.*
|
||||
);
|
||||
|
||||
lsu_stbuf stbuf(
|
||||
.lsu_addr_dc1(lsu_addr_dc1[LSU_SB_BITS-1:0]),
|
||||
.end_addr_dc1(end_addr_dc1[LSU_SB_BITS-1:0]),
|
||||
.lsu_addr_dc2(lsu_addr_dc2[LSU_SB_BITS-1:0]),
|
||||
.end_addr_dc2(end_addr_dc2[LSU_SB_BITS-1:0]),
|
||||
.lsu_addr_dc3(lsu_addr_dc3[LSU_SB_BITS-1:0]),
|
||||
.end_addr_dc3(end_addr_dc3[LSU_SB_BITS-1:0]),
|
||||
.*
|
||||
|
||||
);
|
||||
|
||||
lsu_ecc ecc (
|
||||
.lsu_addr_dc3(lsu_addr_dc3[DCCM_BITS-1:0]),
|
||||
.end_addr_dc3(end_addr_dc3[DCCM_BITS-1:0]),
|
||||
.*
|
||||
);
|
||||
|
||||
lsu_trigger trigger (
|
||||
.store_data_dc3(store_data_dc3[31:0]),
|
||||
.*
|
||||
);
|
||||
|
||||
// Clk domain
|
||||
lsu_clkdomain clkdomain (.*);
|
||||
|
||||
// Bus interface
|
||||
lsu_bus_intf bus_intf (.*);
|
||||
|
||||
//Flops
|
||||
//rvdffs #(1) lsu_i0_valid_dc1ff (.*, .din(dec_i0_lsu_decode_d), .dout(lsu_i0_valid_dc1), .en(~lsu_freeze_dc3));
|
||||
rvdff #(1) lsu_i0_valid_dc1ff (.*, .din(dec_i0_lsu_decode_d), .dout(lsu_i0_valid_dc1), .clk(lsu_freeze_c2_dc1_clk));
|
||||
rvdff #(1) lsu_i0_valid_dc2ff (.*, .din(lsu_i0_valid_dc1), .dout(lsu_i0_valid_dc2), .clk(lsu_freeze_c2_dc2_clk));
|
||||
rvdff #(1) lsu_i0_valid_dc3ff (.*, .din(lsu_i0_valid_dc2), .dout(lsu_i0_valid_dc3), .clk(lsu_freeze_c2_dc3_clk));
|
||||
rvdff #(1) lsu_i0_valid_dc4ff (.*, .din(lsu_i0_valid_dc3), .dout(lsu_i0_valid_dc4), .clk(lsu_freeze_c2_dc4_clk));
|
||||
rvdff #(1) lsu_i0_valid_dc5ff (.*, .din(lsu_i0_valid_dc4), .dout(lsu_i0_valid_dc5), .clk(lsu_c2_dc5_clk));
|
||||
rvdff #(1) lsu_single_ecc_err_dc4(.*, .din(lsu_single_ecc_error_dc3), .dout(lsu_single_ecc_error_dc4), .clk(lsu_c2_dc4_clk));
|
||||
rvdff #(1) lsu_single_ecc_err_dc5(.*, .din(lsu_single_ecc_error_dc4), .dout(lsu_single_ecc_error_dc5), .clk(lsu_c2_dc5_clk));
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
logic [8:0] store_data_bypass_sel;
|
||||
assign store_data_bypass_sel[8:0] = {lsu_p.store_data_bypass_c1,
|
||||
lsu_p.store_data_bypass_c2,
|
||||
lsu_p.store_data_bypass_i0_e2_c2,
|
||||
lsu_p.store_data_bypass_e4_c1[1:0],
|
||||
lsu_p.store_data_bypass_e4_c2[1:0],
|
||||
lsu_p.store_data_bypass_e4_c3[1:0]};
|
||||
assert_store_data_bypass_onehot: assert #0 ($onehot0(store_data_bypass_sel[8:0]));
|
||||
|
||||
assert_picm_rden_and_wren: assert #0 ($onehot0({(picm_rden | picm_mken),picm_wren}));
|
||||
assert_picm_rden_and_dccmen: assert #0 ($onehot0({(picm_rden | picm_mken),dccm_rden}));
|
||||
assert_picm_wren_and_dccmen: assert #0 ($onehot0({picm_wren, dccm_wren}));
|
||||
|
||||
//assert_no_exceptions: assert #0 (lsu_exc_pkt_dc3.exc_valid == 1'b0);
|
||||
property exception_no_lsu_flush;
|
||||
@(posedge clk) disable iff(~rst_l) lsu_error_pkt_dc3.exc_valid |-> ##[1:2] (flush_dc4 | flush_dc5);
|
||||
endproperty
|
||||
assert_exception_no_lsu_flush: assert property (exception_no_lsu_flush) else
|
||||
$display("No flush within 2 cycles of exception");
|
||||
`endif
|
||||
|
||||
endmodule // lsu
|
|
@ -0,0 +1,183 @@
|
|||
// 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 rst_l, // reset
|
||||
|
||||
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_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), .*);
|
||||
|
||||
endmodule // lsu_addrcheck
|
||||
|
|
@ -0,0 +1,923 @@
|
|||
// 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: lsu interface with interface queue
|
||||
// Comments:
|
||||
//
|
||||
//********************************************************************************
|
||||
|
||||
// Function to do 8 to 3 bit encoding
|
||||
function automatic logic [2:0] f_Enc8to3;
|
||||
input logic [7:0] Dec_value;
|
||||
|
||||
logic [2:0] Enc_value;
|
||||
Enc_value[0] = Dec_value[1] | Dec_value[3] | Dec_value[5] | Dec_value[7];
|
||||
Enc_value[1] = Dec_value[2] | Dec_value[3] | Dec_value[6] | Dec_value[7];
|
||||
Enc_value[2] = Dec_value[4] | Dec_value[5] | Dec_value[6] | Dec_value[7];
|
||||
|
||||
return Enc_value[2:0];
|
||||
endfunction // f_Enc8to3
|
||||
|
||||
|
||||
module lsu_bus_buffer
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic scan_mode,
|
||||
input logic dec_tlu_non_blocking_disable, // disable non block
|
||||
input logic dec_tlu_wb_coalescing_disable, // disable write buffer coalescing
|
||||
input logic dec_tlu_ld_miss_byp_wb_disable, // disable ld miss bypass of the write buffer
|
||||
input logic dec_tlu_sideeffect_posted_disable, // disable posted writes to sideeffect addr to the bus
|
||||
|
||||
// various clocks needed for the bus reads and writes
|
||||
input logic lsu_c1_dc3_clk,
|
||||
input logic lsu_c1_dc4_clk,
|
||||
input logic lsu_c1_dc5_clk,
|
||||
input logic lsu_c2_dc3_clk,
|
||||
input logic lsu_c2_dc4_clk,
|
||||
input logic lsu_c2_dc5_clk,
|
||||
input logic lsu_freeze_c1_dc2_clk,
|
||||
input logic lsu_freeze_c1_dc3_clk,
|
||||
input logic lsu_freeze_c2_dc2_clk,
|
||||
input logic lsu_freeze_c2_dc3_clk,
|
||||
input logic lsu_bus_ibuf_c1_clk,
|
||||
input logic lsu_bus_obuf_c1_clk,
|
||||
input logic lsu_bus_buf_c1_clk,
|
||||
input logic lsu_free_c2_clk,
|
||||
input logic lsu_busm_clk,
|
||||
|
||||
|
||||
input lsu_pkt_t lsu_pkt_dc1, // lsu packet flowing down the pipe
|
||||
input lsu_pkt_t lsu_pkt_dc2, // lsu packet flowing down the pipe
|
||||
input lsu_pkt_t lsu_pkt_dc3, // lsu packet flowing down the pipe
|
||||
input lsu_pkt_t lsu_pkt_dc4, // lsu packet flowing down the pipe
|
||||
input lsu_pkt_t lsu_pkt_dc5, // lsu packet flowing down the pipe
|
||||
|
||||
input logic [31:0] lsu_addr_dc2, // lsu address flowing down the pipe
|
||||
input logic [31:0] end_addr_dc2, // lsu address flowing down the pipe
|
||||
input logic [31:0] lsu_addr_dc5, // lsu address flowing down the pipe
|
||||
input logic [31:0] end_addr_dc5, // lsu address flowing down the pipe
|
||||
input logic [31:0] store_data_dc5, // store data flowing down the pipe
|
||||
|
||||
input logic no_word_merge_dc5, // dc5 store doesn't need to wait in ibuf since it will not coalesce
|
||||
input logic no_dword_merge_dc5, // dc5 store doesn't need to wait in ibuf since it will not coalesce
|
||||
input logic lsu_busreq_dc2, // bus request is in dc2
|
||||
output logic lsu_busreq_dc3, // bus request is in dc2
|
||||
output logic lsu_busreq_dc4, // bus request is in dc4
|
||||
output logic lsu_busreq_dc5, // bus request is in dc5
|
||||
input logic ld_full_hit_dc2, // load can get all its byte from a write buffer entry
|
||||
input logic flush_dc2_up, // flush
|
||||
input logic flush_dc3, // flush
|
||||
input logic flush_dc4, // flush
|
||||
input logic flush_dc5, // flush
|
||||
input logic lsu_freeze_dc3,
|
||||
input logic dec_tlu_cancel_e4, // cancel the bus load in dc4 and reset the freeze
|
||||
input logic lsu_commit_dc5, // lsu instruction in dc5 commits
|
||||
input logic is_sideeffects_dc2, // lsu attribute is side_effects
|
||||
input logic is_sideeffects_dc5, // lsu attribute is side_effects
|
||||
input logic ldst_dual_dc1, // load/store is unaligned at 32 bit boundary
|
||||
input logic ldst_dual_dc2, // load/store is unaligned at 32 bit boundary
|
||||
input logic ldst_dual_dc3, // load/store is unaligned at 32 bit boundary
|
||||
input logic ldst_dual_dc4, // load/store is unaligned at 32 bit boundary
|
||||
input logic ldst_dual_dc5, // load/store is unaligned at 32 bit boundary
|
||||
|
||||
input logic [7:0] ldst_byteen_ext_dc2,
|
||||
|
||||
output logic ld_freeze_dc3, // load goes to external and asserts freeze
|
||||
output logic lsu_bus_buffer_pend_any, // bus buffer has a pending bus entry
|
||||
output logic lsu_bus_buffer_full_any, // bus buffer is full
|
||||
output logic lsu_bus_buffer_empty_any, // bus buffer is empty
|
||||
|
||||
output logic ld_bus_error_dc3, // bus error in dc3
|
||||
output logic [31:0] ld_bus_error_addr_dc3, // address of the bus error
|
||||
output logic [31:0] ld_bus_data_dc3, // the Dc3 load data from bus
|
||||
|
||||
output logic [3:0] ld_byte_hit_buf_lo, ld_byte_hit_buf_hi, // Byte enables for forwarding data
|
||||
output logic [31:0] ld_fwddata_buf_lo, ld_fwddata_buf_hi, // load forwarding data
|
||||
|
||||
output logic lsu_imprecise_error_load_any, // imprecise load bus error
|
||||
output logic lsu_imprecise_error_store_any, // imprecise store bus error
|
||||
output logic [31:0] lsu_imprecise_error_addr_any, // address of the imprecise error
|
||||
|
||||
// Non-blocking loads
|
||||
input logic dec_nonblock_load_freeze_dc2,
|
||||
output logic lsu_nonblock_load_valid_dc3, // there is an external load -> put in the cam
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_dc3, // the tag of the external non block load
|
||||
output logic lsu_nonblock_load_inv_dc5, // invalidate signal for the cam entry for non block loads
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_dc5, // tag of the enrty which needs to be invalidated
|
||||
output logic lsu_nonblock_load_data_valid, // the non block is valid - sending information back to the cam
|
||||
output logic lsu_nonblock_load_data_error, // non block load has an error
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // the tag of the non block load sending the data/error
|
||||
output logic [31:0] lsu_nonblock_load_data, // Data of the non block load
|
||||
|
||||
// PMU events
|
||||
output logic lsu_pmu_bus_trxn,
|
||||
output logic lsu_pmu_bus_misaligned,
|
||||
output logic lsu_pmu_bus_error,
|
||||
output logic lsu_pmu_bus_busy,
|
||||
|
||||
// AXI Write Channels
|
||||
output logic lsu_axi_awvalid,
|
||||
input logic lsu_axi_awready,
|
||||
output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_awid,
|
||||
output logic [31:0] lsu_axi_awaddr,
|
||||
output logic [3:0] lsu_axi_awregion,
|
||||
output logic [7:0] lsu_axi_awlen,
|
||||
output logic [2:0] lsu_axi_awsize,
|
||||
output logic [1:0] lsu_axi_awburst,
|
||||
output logic lsu_axi_awlock,
|
||||
output logic [3:0] lsu_axi_awcache,
|
||||
output logic [2:0] lsu_axi_awprot,
|
||||
output logic [3:0] lsu_axi_awqos,
|
||||
|
||||
output logic lsu_axi_wvalid,
|
||||
input logic lsu_axi_wready,
|
||||
output logic [63:0] lsu_axi_wdata,
|
||||
output logic [7:0] lsu_axi_wstrb,
|
||||
output logic lsu_axi_wlast,
|
||||
|
||||
input logic lsu_axi_bvalid,
|
||||
output logic lsu_axi_bready,
|
||||
input logic [1:0] lsu_axi_bresp,
|
||||
input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic lsu_axi_arvalid,
|
||||
input logic lsu_axi_arready,
|
||||
output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_arid,
|
||||
output logic [31:0] lsu_axi_araddr,
|
||||
output logic [3:0] lsu_axi_arregion,
|
||||
output logic [7:0] lsu_axi_arlen,
|
||||
output logic [2:0] lsu_axi_arsize,
|
||||
output logic [1:0] lsu_axi_arburst,
|
||||
output logic lsu_axi_arlock,
|
||||
output logic [3:0] lsu_axi_arcache,
|
||||
output logic [2:0] lsu_axi_arprot,
|
||||
output logic [3:0] lsu_axi_arqos,
|
||||
|
||||
input logic lsu_axi_rvalid,
|
||||
output logic lsu_axi_rready,
|
||||
input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_rid,
|
||||
input logic [63:0] lsu_axi_rdata,
|
||||
input logic [1:0] lsu_axi_rresp,
|
||||
input logic lsu_axi_rlast,
|
||||
|
||||
input logic lsu_bus_clk_en,
|
||||
input logic lsu_bus_clk_en_q
|
||||
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
// For Ld: IDLE -> WAIT -> CMD -> RESP -> DONE -> IDLE
|
||||
// For St: IDLE -> WAIT -> CMD -> RESP(?) -> IDLE
|
||||
typedef enum logic [2:0] {IDLE=3'b000, WAIT=3'b001, CMD=3'b010, RESP=3'b011, DONE=3'b100} state_t;
|
||||
|
||||
localparam DEPTH = `RV_LSU_NUM_NBLOAD;
|
||||
localparam DEPTH_LOG2 = `RV_LSU_NUM_NBLOAD_WIDTH;
|
||||
localparam TIMER = 8; // This can be only power of 2
|
||||
localparam TIMER_LOG2 = (TIMER < 2) ? 1 : $clog2(TIMER);
|
||||
localparam TIMER_MAX = (TIMER == 0) ? TIMER_LOG2'(0) : TIMER_LOG2'(TIMER - 1); // Maximum value of timer
|
||||
|
||||
logic [3:0] ldst_byteen_hi_dc2, ldst_byteen_lo_dc2;
|
||||
logic [DEPTH-1:0] ld_addr_hitvec_lo, ld_addr_hitvec_hi;
|
||||
logic [3:0][DEPTH-1:0] ld_byte_hitvec_lo, ld_byte_hitvec_hi;
|
||||
logic [3:0][DEPTH-1:0] ld_byte_hitvecfn_lo, ld_byte_hitvecfn_hi;
|
||||
|
||||
logic ld_addr_ibuf_hit_lo, ld_addr_ibuf_hit_hi;
|
||||
logic [3:0] ld_byte_ibuf_hit_lo, ld_byte_ibuf_hit_hi;
|
||||
|
||||
logic [3:0] ldst_byteen_dc5;
|
||||
logic [7:0] ldst_byteen_ext_dc5;
|
||||
logic [3:0] ldst_byteen_hi_dc5, ldst_byteen_lo_dc5;
|
||||
logic [31:0] store_data_hi_dc5, store_data_lo_dc5;
|
||||
logic ldst_samedw_dc5;
|
||||
|
||||
logic lsu_nonblock_load_valid_dc4,lsu_nonblock_load_valid_dc5;
|
||||
logic [31:0] lsu_nonblock_load_data_hi, lsu_nonblock_load_data_lo, lsu_nonblock_data_unalgn;
|
||||
logic [1:0] lsu_nonblock_addr_offset;
|
||||
logic [1:0] lsu_nonblock_sz;
|
||||
logic lsu_nonblock_load_data_valid_hi, lsu_nonblock_load_data_valid_lo;
|
||||
logic lsu_nonblock_load_data_error_hi, lsu_nonblock_load_data_error_lo;
|
||||
logic lsu_nonblock_unsign, lsu_nonblock_dual;
|
||||
logic dec_nonblock_load_freeze_dc3;
|
||||
logic ld_precise_bus_error;
|
||||
logic [DEPTH_LOG2-1:0] lsu_imprecise_error_load_tag;
|
||||
logic [31:0] ld_block_bus_data;
|
||||
|
||||
logic [DEPTH-1:0] CmdPtr0Dec, CmdPtr1Dec;
|
||||
logic [DEPTH_LOG2-1:0] CmdPtr0, CmdPtr1;
|
||||
logic [DEPTH_LOG2-1:0] WrPtr0_dc3, WrPtr0_dc4, WrPtr0_dc5;
|
||||
logic [DEPTH_LOG2-1:0] WrPtr1_dc3, WrPtr1_dc4, WrPtr1_dc5;
|
||||
logic found_wrptr0, found_wrptr1, found_cmdptr0, found_cmdptr1;
|
||||
logic [3:0] buf_numvld_any, buf_numvld_wrcmd_any, buf_numvld_pend_any, buf_numvld_cmd_any;
|
||||
logic bus_sideeffect_pend;
|
||||
logic bus_coalescing_disable;
|
||||
|
||||
logic ld_freeze_en, ld_freeze_rst;
|
||||
logic FreezePtrEn;
|
||||
logic [DEPTH_LOG2-1:0] FreezePtr;
|
||||
|
||||
logic bus_addr_match_pending;
|
||||
logic bus_cmd_sent, bus_cmd_ready;
|
||||
logic bus_wcmd_sent, bus_wdata_sent;
|
||||
logic bus_rsp_read, bus_rsp_write;
|
||||
logic [LSU_BUS_TAG-1:0] bus_rsp_read_tag, bus_rsp_write_tag;
|
||||
logic bus_rsp_read_error, bus_rsp_write_error;
|
||||
logic [63:0] bus_rsp_rdata;
|
||||
|
||||
// Bus buffer signals
|
||||
state_t [DEPTH-1:0] buf_state;
|
||||
logic [DEPTH-1:0][2:0] buf_state_out;
|
||||
logic [DEPTH-1:0][1:0] buf_sz;
|
||||
logic [DEPTH-1:0][31:0] buf_addr;
|
||||
logic [DEPTH-1:0][3:0] buf_byteen;
|
||||
logic [DEPTH-1:0] buf_sideeffect;
|
||||
logic [DEPTH-1:0] buf_write;
|
||||
logic [DEPTH-1:0] buf_unsign;
|
||||
logic [DEPTH-1:0] buf_dual;
|
||||
logic [DEPTH-1:0] buf_samedw;
|
||||
logic [DEPTH-1:0] buf_nomerge;
|
||||
logic [DEPTH-1:0] buf_dualhi;
|
||||
logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_dualtag;
|
||||
logic [DEPTH-1:0] buf_nb;
|
||||
logic [DEPTH-1:0] buf_error;
|
||||
logic [DEPTH-1:0][31:0] buf_data;
|
||||
logic [DEPTH-1:0][DEPTH-1:0] buf_age, buf_age_younger, buf_age_temp;
|
||||
|
||||
state_t [DEPTH-1:0] buf_nxtstate;
|
||||
logic [DEPTH-1:0] buf_rst;
|
||||
logic [DEPTH-1:0] buf_state_en;
|
||||
logic [DEPTH-1:0] buf_cmd_state_bus_en;
|
||||
logic [DEPTH-1:0] buf_resp_state_bus_en;
|
||||
logic [DEPTH-1:0] buf_state_bus_en;
|
||||
logic [DEPTH-1:0] buf_dual_in;
|
||||
logic [DEPTH-1:0] buf_samedw_in;
|
||||
logic [DEPTH-1:0] buf_nomerge_in;
|
||||
logic [DEPTH-1:0] buf_nb_in;
|
||||
logic [DEPTH-1:0] buf_sideeffect_in;
|
||||
logic [DEPTH-1:0] buf_unsign_in;
|
||||
logic [DEPTH-1:0][1:0] buf_sz_in;
|
||||
logic [DEPTH-1:0] buf_write_in;
|
||||
logic [DEPTH-1:0] buf_wr_en;
|
||||
logic [DEPTH-1:0] buf_dualhi_in;
|
||||
logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_dualtag_in;
|
||||
logic [DEPTH-1:0][3:0] buf_byteen_in;
|
||||
logic [DEPTH-1:0][31:0] buf_addr_in;
|
||||
logic [DEPTH-1:0][31:0] buf_data_in;
|
||||
logic [DEPTH-1:0] buf_error_en;
|
||||
logic [DEPTH-1:0] buf_data_en;
|
||||
logic [DEPTH-1:0][DEPTH-1:0] buf_age_in;
|
||||
logic [DEPTH-1:0][DEPTH-1:0] buf_ageQ;
|
||||
|
||||
// Input buffer signals
|
||||
logic ibuf_valid;
|
||||
logic ibuf_dual;
|
||||
logic ibuf_samedw;
|
||||
logic ibuf_nomerge;
|
||||
logic [DEPTH_LOG2-1:0] ibuf_tag;
|
||||
logic [DEPTH_LOG2-1:0] ibuf_dualtag;
|
||||
logic ibuf_nb;
|
||||
logic ibuf_sideeffect;
|
||||
logic ibuf_unsign;
|
||||
logic ibuf_write;
|
||||
logic [1:0] ibuf_sz;
|
||||
logic [3:0] ibuf_byteen;
|
||||
logic [31:0] ibuf_addr;
|
||||
logic [31:0] ibuf_data;
|
||||
logic [TIMER_LOG2-1:0] ibuf_timer;
|
||||
|
||||
logic ibuf_byp;
|
||||
logic ibuf_wr_en;
|
||||
logic ibuf_rst;
|
||||
logic ibuf_force_drain;
|
||||
logic ibuf_drain_vld;
|
||||
logic [DEPTH-1:0] ibuf_drainvec_vld;
|
||||
logic [DEPTH_LOG2-1:0] ibuf_tag_in;
|
||||
logic [DEPTH_LOG2-1:0] ibuf_dualtag_in;
|
||||
logic [1:0] ibuf_sz_in;
|
||||
logic [31:0] ibuf_addr_in;
|
||||
logic [3:0] ibuf_byteen_in;
|
||||
logic [31:0] ibuf_data_in;
|
||||
logic [TIMER_LOG2-1:0] ibuf_timer_in;
|
||||
logic [3:0] ibuf_byteen_out;
|
||||
logic [31:0] ibuf_data_out;
|
||||
logic ibuf_merge_en, ibuf_merge_in;
|
||||
|
||||
// Output buffer signals
|
||||
logic obuf_valid;
|
||||
logic obuf_write;
|
||||
logic obuf_sideeffect;
|
||||
logic [31:0] obuf_addr;
|
||||
logic [63:0] obuf_data;
|
||||
logic [1:0] obuf_sz;
|
||||
logic [7:0] obuf_byteen;
|
||||
logic obuf_merge;
|
||||
logic obuf_cmd_done, obuf_data_done;
|
||||
logic [LSU_BUS_TAG-1:0] obuf_tag0;
|
||||
logic [LSU_BUS_TAG-1:0] obuf_tag1;
|
||||
|
||||
logic ibuf_buf_byp;
|
||||
logic obuf_force_wr_en;
|
||||
logic obuf_wr_wait;
|
||||
logic obuf_wr_en, obuf_wr_enQ;
|
||||
logic obuf_rst;
|
||||
logic obuf_write_in;
|
||||
logic obuf_sideeffect_in;
|
||||
logic [31:0] obuf_addr_in;
|
||||
logic [63:0] obuf_data_in;
|
||||
logic [1:0] obuf_sz_in;
|
||||
logic [7:0] obuf_byteen_in;
|
||||
logic obuf_merge_in;
|
||||
logic obuf_cmd_done_in, obuf_data_done_in;
|
||||
logic [LSU_BUS_TAG-1:0] obuf_tag0_in;
|
||||
logic [LSU_BUS_TAG-1:0] obuf_tag1_in;
|
||||
|
||||
logic obuf_merge_en;
|
||||
logic [TIMER_LOG2-1:0] obuf_wr_timer, obuf_wr_timer_in;
|
||||
logic [7:0] obuf_byteen0_in, obuf_byteen1_in;
|
||||
logic [63:0] obuf_data0_in, obuf_data1_in;
|
||||
|
||||
logic lsu_axi_awvalid_q, lsu_axi_awready_q;
|
||||
logic lsu_axi_wvalid_q, lsu_axi_wready_q;
|
||||
logic lsu_axi_arvalid_q, lsu_axi_arready_q;
|
||||
logic lsu_axi_bvalid_q, lsu_axi_bready_q;
|
||||
logic lsu_axi_rvalid_q, lsu_axi_rready_q;
|
||||
logic [LSU_BUS_TAG-1:0] lsu_axi_bid_q, lsu_axi_rid_q;
|
||||
logic [1:0] lsu_axi_bresp_q, lsu_axi_rresp_q;
|
||||
logic [63:0] lsu_axi_rdata_q;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Load forwarding logic start
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Buffer hit logic for bus load forwarding
|
||||
assign ldst_byteen_hi_dc2[3:0] = ldst_byteen_ext_dc2[7:4];
|
||||
assign ldst_byteen_lo_dc2[3:0] = ldst_byteen_ext_dc2[3:0];
|
||||
for (genvar i=0; i<DEPTH; i++) begin
|
||||
// We can't forward from RESP for ahb since multiple writes to the same address can be in RESP and we can't find out their age
|
||||
assign ld_addr_hitvec_lo[i] = (lsu_addr_dc2[31:2] == buf_addr[i][31:2]) & buf_write[i] & ((buf_state[i] == WAIT) | (buf_state[i] == CMD)) & lsu_busreq_dc2;
|
||||
assign ld_addr_hitvec_hi[i] = (end_addr_dc2[31:2] == buf_addr[i][31:2]) & buf_write[i] & ((buf_state[i] == WAIT) | (buf_state[i] == CMD)) & lsu_busreq_dc2;
|
||||
end
|
||||
|
||||
for (genvar j=0; j<4; j++) begin
|
||||
assign ld_byte_hit_buf_lo[j] = |(ld_byte_hitvecfn_lo[j]) | ld_byte_ibuf_hit_lo[j];
|
||||
assign ld_byte_hit_buf_hi[j] = |(ld_byte_hitvecfn_hi[j]) | ld_byte_ibuf_hit_hi[j];
|
||||
for (genvar i=0; i<DEPTH; i++) begin
|
||||
assign ld_byte_hitvec_lo[j][i] = ld_addr_hitvec_lo[i] & buf_byteen[i][j] & ldst_byteen_lo_dc2[j];
|
||||
assign ld_byte_hitvec_hi[j][i] = ld_addr_hitvec_hi[i] & buf_byteen[i][j] & ldst_byteen_hi_dc2[j];
|
||||
|
||||
assign ld_byte_hitvecfn_lo[j][i] = ld_byte_hitvec_lo[j][i] & ~(|(ld_byte_hitvec_lo[j] & buf_age_younger[i])) & ~ld_byte_ibuf_hit_lo[j]; // Kill the byte enable if younger entry exists or byte exists in ibuf
|
||||
assign ld_byte_hitvecfn_hi[j][i] = ld_byte_hitvec_hi[j][i] & ~(|(ld_byte_hitvec_hi[j] & buf_age_younger[i])) & ~ld_byte_ibuf_hit_hi[j]; // Kill the byte enable if younger entry exists or byte exists in ibuf
|
||||
end
|
||||
end
|
||||
|
||||
// Hit in the ibuf
|
||||
assign ld_addr_ibuf_hit_lo = (lsu_addr_dc2[31:2] == ibuf_addr[31:2]) & ibuf_write & ibuf_valid & lsu_busreq_dc2;
|
||||
assign ld_addr_ibuf_hit_hi = (end_addr_dc2[31:2] == ibuf_addr[31:2]) & ibuf_write & ibuf_valid & lsu_busreq_dc2;
|
||||
|
||||
for (genvar i=0; i<4; i++) begin
|
||||
assign ld_byte_ibuf_hit_lo[i] = ld_addr_ibuf_hit_lo & ibuf_byteen[i] & ldst_byteen_lo_dc2[i];
|
||||
assign ld_byte_ibuf_hit_hi[i] = ld_addr_ibuf_hit_hi & ibuf_byteen[i] & ldst_byteen_hi_dc2[i];
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
ld_fwddata_buf_lo[31:0] = {{8{ld_byte_ibuf_hit_lo[3]}},{8{ld_byte_ibuf_hit_lo[2]}},{8{ld_byte_ibuf_hit_lo[1]}},{8{ld_byte_ibuf_hit_lo[0]}}} & ibuf_data[31:0];
|
||||
ld_fwddata_buf_hi[31:0] = {{8{ld_byte_ibuf_hit_hi[3]}},{8{ld_byte_ibuf_hit_hi[2]}},{8{ld_byte_ibuf_hit_hi[1]}},{8{ld_byte_ibuf_hit_hi[0]}}} & ibuf_data[31:0];
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
ld_fwddata_buf_lo[7:0] |= {8{ld_byte_hitvecfn_lo[0][i]}} & buf_data[i][7:0];
|
||||
ld_fwddata_buf_lo[15:8] |= {8{ld_byte_hitvecfn_lo[1][i]}} & buf_data[i][15:8];
|
||||
ld_fwddata_buf_lo[23:16] |= {8{ld_byte_hitvecfn_lo[2][i]}} & buf_data[i][23:16];
|
||||
ld_fwddata_buf_lo[31:24] |= {8{ld_byte_hitvecfn_lo[3][i]}} & buf_data[i][31:24];
|
||||
|
||||
ld_fwddata_buf_hi[7:0] |= {8{ld_byte_hitvecfn_hi[0][i]}} & buf_data[i][7:0];
|
||||
ld_fwddata_buf_hi[15:8] |= {8{ld_byte_hitvecfn_hi[1][i]}} & buf_data[i][15:8];
|
||||
ld_fwddata_buf_hi[23:16] |= {8{ld_byte_hitvecfn_hi[2][i]}} & buf_data[i][23:16];
|
||||
ld_fwddata_buf_hi[31:24] |= {8{ld_byte_hitvecfn_hi[3][i]}} & buf_data[i][31:24];
|
||||
end
|
||||
end
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Load forwarding logic end
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
`ifdef RV_BUILD_AHB_LITE
|
||||
assign bus_coalescing_disable = 1'b1; // No coalescing for ahb
|
||||
`else
|
||||
assign bus_coalescing_disable = dec_tlu_wb_coalescing_disable;
|
||||
`endif
|
||||
|
||||
// Get the hi/lo byte enable
|
||||
assign ldst_byteen_dc5[3:0] = ({4{lsu_pkt_dc5.by}} & 4'b0001) |
|
||||
({4{lsu_pkt_dc5.half}} & 4'b0011) |
|
||||
({4{lsu_pkt_dc5.word}} & 4'b1111);
|
||||
|
||||
assign {ldst_byteen_hi_dc5[3:0], ldst_byteen_lo_dc5[3:0]} = {4'b0,ldst_byteen_dc5[3:0]} << lsu_addr_dc5[1:0];
|
||||
assign {store_data_hi_dc5[31:0], store_data_lo_dc5[31:0]} = {32'b0,store_data_dc5[31:0]} << {lsu_addr_dc5[1:0],3'b0};
|
||||
assign ldst_samedw_dc5 = (lsu_addr_dc5[3] == end_addr_dc5[3]);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Input buffer logic starts here
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
assign ibuf_byp = lsu_busreq_dc5 & ((lsu_pkt_dc5.load | no_word_merge_dc5) & ~ibuf_valid); // Bypass if ibuf is empty and it's a load or no merge possible
|
||||
assign ibuf_wr_en = lsu_busreq_dc5 & (lsu_commit_dc5 | lsu_freeze_dc3) & ~ibuf_byp;
|
||||
assign ibuf_rst = ibuf_drain_vld & ~ibuf_wr_en;
|
||||
assign ibuf_force_drain = lsu_busreq_dc2 & ~lsu_busreq_dc3 & ~lsu_busreq_dc4 & ~lsu_busreq_dc5 & ibuf_valid & (lsu_pkt_dc2.load | (ibuf_addr[31:2] != lsu_addr_dc2[31:2])); // Move the ibuf to buf if there is a non-colaescable ld/st in dc2 but nothing in dc3/dc4/dc5
|
||||
assign ibuf_drain_vld = ibuf_valid & (((ibuf_wr_en | (ibuf_timer == TIMER_MAX)) & ~(ibuf_merge_en & ibuf_merge_in)) | ibuf_byp | ibuf_force_drain | ibuf_sideeffect | ~ibuf_write | bus_coalescing_disable);
|
||||
assign ibuf_tag_in[DEPTH_LOG2-1:0] = (ibuf_merge_en & ibuf_merge_in) ? ibuf_tag[DEPTH_LOG2-1:0] : (ldst_dual_dc5 ? WrPtr1_dc5 : WrPtr0_dc5);
|
||||
assign ibuf_dualtag_in[DEPTH_LOG2-1:0] = WrPtr0_dc5;
|
||||
assign ibuf_sz_in[1:0] = {lsu_pkt_dc5.word, lsu_pkt_dc5.half}; // NOTE: Make sure lsu_pkt_dc3/dc4 are flopped in case of freeze (except the valid)
|
||||
assign ibuf_addr_in[31:0] = ldst_dual_dc5 ? end_addr_dc5[31:0] : lsu_addr_dc5[31:0];
|
||||
assign ibuf_byteen_in[3:0] = (ibuf_merge_en & ibuf_merge_in) ? (ibuf_byteen[3:0] | ldst_byteen_lo_dc5[3:0]) : (ldst_dual_dc5 ? ldst_byteen_hi_dc5[3:0] : ldst_byteen_lo_dc5[3:0]);
|
||||
for (genvar i=0; i<4; i++) begin
|
||||
assign ibuf_data_in[(8*i)+7:(8*i)] = (ibuf_merge_en & ibuf_merge_in) ? (ldst_byteen_lo_dc5[i] ? store_data_lo_dc5[(8*i)+7:(8*i)] : ibuf_data[(8*i)+7:(8*i)]) :
|
||||
(ldst_dual_dc5 ? store_data_hi_dc5[(8*i)+7:(8*i)] : store_data_lo_dc5[(8*i)+7:(8*i)]);
|
||||
end
|
||||
assign ibuf_timer_in = ibuf_wr_en ? '0 : (ibuf_timer < TIMER_MAX) ? (ibuf_timer + 1'b1) : ibuf_timer;
|
||||
|
||||
assign ibuf_merge_en = lsu_busreq_dc5 & lsu_commit_dc5 & lsu_pkt_dc5.store & ibuf_valid & ibuf_write & (lsu_addr_dc5[31:2] == ibuf_addr[31:2]) & ~is_sideeffects_dc5 & ~bus_coalescing_disable;
|
||||
assign ibuf_merge_in = ~ldst_dual_dc5; // If it's a unaligned store, merge needs to happen on the way out of ibuf
|
||||
|
||||
// ibuf signals going to bus buffer after merging
|
||||
for (genvar i=0; i<4; i++) begin
|
||||
assign ibuf_byteen_out[i] = (ibuf_merge_en & ~ibuf_merge_in) ? (ibuf_byteen[i] | ldst_byteen_lo_dc5[i]) : ibuf_byteen[i];
|
||||
assign ibuf_data_out[(8*i)+7:(8*i)] = (ibuf_merge_en & ~ibuf_merge_in) ? (ldst_byteen_lo_dc5[i] ? store_data_lo_dc5[(8*i)+7:(8*i)] : ibuf_data[(8*i)+7:(8*i)]) :
|
||||
ibuf_data[(8*i)+7:(8*i)];
|
||||
end
|
||||
|
||||
rvdffsc #(.WIDTH(1)) ibuf_valid_ff (.din(1'b1), .dout(ibuf_valid), .en(ibuf_wr_en), .clear(ibuf_rst), .clk(lsu_free_c2_clk), .*);
|
||||
rvdffs #(.WIDTH(DEPTH_LOG2)) ibuf_tagff (.din(ibuf_tag_in), .dout(ibuf_tag), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(DEPTH_LOG2)) ibuf_dualtagff (.din(ibuf_dualtag_in), .dout(ibuf_dualtag), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) ibuf_dualff (.din(ldst_dual_dc5), .dout(ibuf_dual), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) ibuf_samedwff (.din(ldst_samedw_dc5), .dout(ibuf_samedw), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) ibuf_nomergeff (.din(no_dword_merge_dc5), .dout(ibuf_nomerge), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) ibuf_nbff (.din(lsu_nonblock_load_valid_dc5), .dout(ibuf_nb), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) ibuf_sideeffectff (.din(is_sideeffects_dc5), .dout(ibuf_sideeffect), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) ibuf_unsignff (.din(lsu_pkt_dc5.unsign), .dout(ibuf_unsign), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) ibuf_writeff (.din(lsu_pkt_dc5.store), .dout(ibuf_write), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(2)) ibuf_szff (.din(ibuf_sz_in[1:0]), .dout(ibuf_sz), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) ibuf_addrff (.din(ibuf_addr_in[31:0]), .dout(ibuf_addr), .en(ibuf_wr_en), .*);
|
||||
rvdffs #(.WIDTH(4)) ibuf_byteenff (.din(ibuf_byteen_in[3:0]), .dout(ibuf_byteen), .en(ibuf_wr_en), .clk(lsu_bus_ibuf_c1_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) ibuf_dataff (.din(ibuf_data_in[31:0]), .dout(ibuf_data), .en(ibuf_wr_en), .*);
|
||||
rvdff #(.WIDTH(TIMER_LOG2)) ibuf_timerff (.din(ibuf_timer_in), .dout(ibuf_timer), .clk(lsu_free_c2_clk), .*);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Input buffer logic ends here
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Output buffer logic starts here
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
assign obuf_wr_wait = (buf_numvld_wrcmd_any[3:0] == 4'b1) & (buf_numvld_cmd_any[3:0] == 4'b1) & (obuf_wr_timer != TIMER_MAX) & ~bus_coalescing_disable & ~buf_nomerge[CmdPtr0] & ~obuf_force_wr_en;
|
||||
assign obuf_wr_timer_in = obuf_wr_en ? 3'b0: (((buf_numvld_cmd_any > 4'b0) & (obuf_wr_timer < TIMER_MAX)) ? (obuf_wr_timer + 1'b1) : obuf_wr_timer);
|
||||
assign obuf_force_wr_en = lsu_busreq_dc2 & ~lsu_busreq_dc3 & ~lsu_busreq_dc4 & ~lsu_busreq_dc5 & ~ibuf_valid & (buf_numvld_cmd_any[3:0] == 4'b1) & (lsu_addr_dc2[31:2] != buf_addr[CmdPtr0][31:2]); // Entry in dc2 can't merge with entry going to obuf and there is no entry in between
|
||||
assign ibuf_buf_byp = ibuf_byp & (buf_numvld_pend_any[3:0] == 4'b0) & ~ldst_dual_dc5 & lsu_pkt_dc5.store;
|
||||
|
||||
assign obuf_wr_en = (lsu_bus_clk_en & ((ibuf_buf_byp & lsu_commit_dc5) |
|
||||
((buf_state[CmdPtr0] == CMD) & found_cmdptr0 & ~buf_cmd_state_bus_en[CmdPtr0] &
|
||||
(~(buf_dual[CmdPtr0] & buf_samedw[CmdPtr0] & ~buf_write[CmdPtr0]) | found_cmdptr1 | buf_nomerge[CmdPtr0] | obuf_force_wr_en)))) &
|
||||
(bus_cmd_ready | ~obuf_valid) & ~obuf_wr_wait & ~bus_sideeffect_pend & ~bus_addr_match_pending;
|
||||
assign obuf_rst = bus_cmd_sent & ~obuf_wr_en;
|
||||
assign obuf_write_in = ibuf_buf_byp ? lsu_pkt_dc5.store : buf_write[CmdPtr0];
|
||||
assign obuf_sideeffect_in = ibuf_buf_byp ? is_sideeffects_dc5 : buf_sideeffect[CmdPtr0];
|
||||
assign obuf_addr_in[31:0] = ibuf_buf_byp ? lsu_addr_dc5[31:0] : buf_addr[CmdPtr0];
|
||||
assign obuf_sz_in[1:0] = ibuf_buf_byp ? {lsu_pkt_dc5.word, lsu_pkt_dc5.half} : buf_sz[CmdPtr0];
|
||||
assign obuf_merge_in = obuf_merge_en;
|
||||
assign obuf_tag0_in[LSU_BUS_TAG-1:0] = ibuf_buf_byp ? LSU_BUS_TAG'(WrPtr0_dc5) : LSU_BUS_TAG'(CmdPtr0);
|
||||
assign obuf_tag1_in[LSU_BUS_TAG-1:0] = LSU_BUS_TAG'(CmdPtr1);
|
||||
|
||||
assign obuf_cmd_done_in = ~(obuf_wr_en | obuf_rst) & (obuf_cmd_done | bus_wcmd_sent);
|
||||
assign obuf_data_done_in = ~(obuf_wr_en | obuf_rst) & (obuf_data_done | bus_wdata_sent);
|
||||
|
||||
assign obuf_byteen0_in[7:0] = ibuf_buf_byp ? (lsu_addr_dc5[2] ? {ldst_byteen_lo_dc5[3:0],4'b0} : {4'b0,ldst_byteen_lo_dc5[3:0]}) :
|
||||
(buf_addr[CmdPtr0][2] ? {buf_byteen[CmdPtr0],4'b0} : {4'b0,buf_byteen[CmdPtr0]});
|
||||
assign obuf_byteen1_in[7:0] = buf_addr[CmdPtr1][2] ? {buf_byteen[CmdPtr1],4'b0} : {4'b0,buf_byteen[CmdPtr1]};
|
||||
assign obuf_data0_in[63:0] = ibuf_buf_byp ? (lsu_addr_dc5[2] ? {store_data_lo_dc5[31:0],32'b0} : {32'b0,store_data_lo_dc5[31:0]}) :
|
||||
(buf_addr[CmdPtr0][2] ? {buf_data[CmdPtr0],32'b0} : {32'b0,buf_data[CmdPtr0]});
|
||||
assign obuf_data1_in[63:0] = buf_addr[CmdPtr1][2] ? {buf_data[CmdPtr1],32'b0} : {32'b0,buf_data[CmdPtr1]};
|
||||
for (genvar i=0 ;i<8; i++) begin
|
||||
assign obuf_byteen_in[i] = obuf_byteen0_in[i] | (obuf_merge_en & obuf_byteen1_in[i]);
|
||||
assign obuf_data_in[(8*i)+7:(8*i)] = (obuf_merge_en & obuf_byteen1_in[i]) ? obuf_data1_in[(8*i)+7:(8*i)] : obuf_data0_in[(8*i)+7:(8*i)];
|
||||
end
|
||||
|
||||
// No store obuf merging for AXI since all stores are sent non-posted. Can't track the second id right now
|
||||
assign obuf_merge_en = (CmdPtr0 != CmdPtr1) & found_cmdptr0 & found_cmdptr1 & (buf_state[CmdPtr0] == CMD) & (buf_state[CmdPtr1] == CMD) & ~buf_cmd_state_bus_en[CmdPtr0] & ~buf_sideeffect[CmdPtr0] &
|
||||
(~buf_write[CmdPtr0] & buf_dual[CmdPtr0] & ~buf_dualhi[CmdPtr0] & buf_samedw[CmdPtr0]); // CmdPtr0/CmdPtr1 are for same load which is within a DW
|
||||
|
||||
rvdff #(.WIDTH(1)) obuf_wren_ff (.din(obuf_wr_en), .dout(obuf_wr_enQ), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) obuf_cmd_done_ff (.din(obuf_cmd_done_in), .dout(obuf_cmd_done), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) obuf_data_done_ff (.din(obuf_data_done_in), .dout(obuf_data_done), .clk(lsu_busm_clk), .*);
|
||||
rvdffsc #(.WIDTH(1)) obuf_valid_ff (.din(1'b1), .dout(obuf_valid), .en(obuf_wr_en), .clear(obuf_rst), .clk(lsu_busm_clk), .*);
|
||||
rvdffs #(.WIDTH(LSU_BUS_TAG)) obuf_tag0ff (.din(obuf_tag0_in), .dout(obuf_tag0), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(LSU_BUS_TAG)) obuf_tag1ff (.din(obuf_tag1_in), .dout(obuf_tag1), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) obuf_mergeff (.din(obuf_merge_in), .dout(obuf_merge), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) obuf_writeff (.din(obuf_write_in), .dout(obuf_write), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) obuf_sideeffectff (.din(obuf_sideeffect_in), .dout(obuf_sideeffect), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(2)) obuf_szff (.din(obuf_sz_in[1:0]), .dout(obuf_sz), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) obuf_addrff (.din(obuf_addr_in[31:0]), .dout(obuf_addr), .en(obuf_wr_en), .*);
|
||||
rvdffs #(.WIDTH(8)) obuf_byteenff (.din(obuf_byteen_in[7:0]), .dout(obuf_byteen), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*);
|
||||
rvdffe #(.WIDTH(64)) obuf_dataff (.din(obuf_data_in[63:0]), .dout(obuf_data), .en(obuf_wr_en), .*);
|
||||
rvdff #(.WIDTH(TIMER_LOG2)) obuf_timerff (.din(obuf_wr_timer_in), .dout(obuf_wr_timer), .clk(lsu_busm_clk), .*);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Output buffer logic ends here
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Find the entry to allocate and entry to send
|
||||
always_comb begin
|
||||
WrPtr0_dc3[DEPTH_LOG2-1:0] = '0;
|
||||
WrPtr1_dc3[DEPTH_LOG2-1:0] = '0;
|
||||
found_wrptr0 = '0;
|
||||
found_wrptr1 = '0;
|
||||
|
||||
// Find first write pointer
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
if (~found_wrptr0) begin
|
||||
WrPtr0_dc3[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i);
|
||||
found_wrptr0 = (buf_state[i] == IDLE) & ~((ibuf_valid & (ibuf_tag == DEPTH_LOG2'(i))) |
|
||||
(lsu_busreq_dc4 & ((WrPtr0_dc4 == DEPTH_LOG2'(i)) | (ldst_dual_dc4 & (WrPtr1_dc4 == DEPTH_LOG2'(i))))) |
|
||||
(lsu_busreq_dc5 & ((WrPtr0_dc5 == DEPTH_LOG2'(i)) | (ldst_dual_dc5 & (WrPtr1_dc5 == DEPTH_LOG2'(i))))));
|
||||
//found_wrptr = (buf_state[i] == IDLE);
|
||||
end
|
||||
end
|
||||
|
||||
// Find second write pointer
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
if (~found_wrptr1) begin
|
||||
WrPtr1_dc3[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i);
|
||||
found_wrptr1 = (buf_state[i] == IDLE) & ~((ibuf_valid & (ibuf_tag == DEPTH_LOG2'(i))) |
|
||||
(lsu_busreq_dc3 & (WrPtr0_dc3 == DEPTH_LOG2'(i))) |
|
||||
(lsu_busreq_dc4 & ((WrPtr0_dc4 == DEPTH_LOG2'(i)) | (ldst_dual_dc4 & (WrPtr1_dc4 == DEPTH_LOG2'(i))))) |
|
||||
(lsu_busreq_dc5 & ((WrPtr0_dc5 == DEPTH_LOG2'(i)) | (ldst_dual_dc5 & (WrPtr1_dc5 == DEPTH_LOG2'(i))))));
|
||||
//found_wrptr = (buf_state[i] == IDLE);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Get the command ptr
|
||||
for (genvar i=0; i<DEPTH; i++) begin
|
||||
// These should be one-hot
|
||||
assign CmdPtr0Dec[i] = ~(|buf_age[i]) & (buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i];
|
||||
assign CmdPtr1Dec[i] = ~(|(buf_age[i] & ~CmdPtr0Dec)) & ~CmdPtr0Dec[i] & (buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i];
|
||||
end
|
||||
|
||||
assign found_cmdptr0 = |CmdPtr0Dec;
|
||||
assign found_cmdptr1 = |CmdPtr1Dec;
|
||||
assign CmdPtr0 = f_Enc8to3(8'(CmdPtr0Dec[DEPTH-1:0]));
|
||||
assign CmdPtr1 = f_Enc8to3(8'(CmdPtr1Dec[DEPTH-1:0]));
|
||||
|
||||
// Age vector
|
||||
for (genvar i=0; i<DEPTH; i++) begin: GenAgeVec
|
||||
for (genvar j=0; j<DEPTH; j++) begin
|
||||
assign buf_age_in[i][j] = (((buf_state[i] == IDLE) & buf_state_en[i]) &
|
||||
(((buf_state[j] == WAIT) | ((buf_state[j] == CMD) & ~buf_cmd_state_bus_en[j])) | // Set age bit for older entries
|
||||
(ibuf_drain_vld & lsu_busreq_dc5 & (ibuf_byp | ldst_dual_dc5) & (DEPTH_LOG2'(i) == WrPtr0_dc5) & (DEPTH_LOG2'(j) == ibuf_tag)) | // Set case for dual lo
|
||||
(ibuf_byp & lsu_busreq_dc5 & ldst_dual_dc5 & (DEPTH_LOG2'(i) == WrPtr1_dc5) & (DEPTH_LOG2'(j) == WrPtr0_dc5)))) | // ibuf bypass case
|
||||
buf_age[i][j];
|
||||
assign buf_age[i][j] = buf_ageQ[i][j] & ~((buf_state[j] == CMD) & buf_cmd_state_bus_en[j]); // Reset case
|
||||
|
||||
assign buf_age_younger[i][j] = (i == j) ? 1'b0: (~buf_age[i][j] & (buf_state[j] != IDLE)); // Younger entries
|
||||
assign buf_age_temp[i][j] = buf_age[i][j] & ~(CmdPtr0 == DEPTH_LOG2'(j)); // Used to determine CmdPtr1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Buffer logic
|
||||
//------------------------------------------------------------------------------
|
||||
for (genvar i=0; i<DEPTH; i++) begin
|
||||
|
||||
assign ibuf_drainvec_vld[i] = (ibuf_drain_vld & (i == ibuf_tag));
|
||||
assign buf_byteen_in[i] = ibuf_drainvec_vld[i] ? ibuf_byteen_out[3:0] : ((ibuf_byp & ldst_dual_dc5 & (i == WrPtr1_dc5)) ? ldst_byteen_hi_dc5[3:0] : ldst_byteen_lo_dc5[3:0]);
|
||||
assign buf_addr_in[i] = ibuf_drainvec_vld[i] ? ibuf_addr[31:0] : ((ibuf_byp & ldst_dual_dc5 & (i == WrPtr1_dc5)) ? end_addr_dc5[31:0] : lsu_addr_dc5[31:0]);
|
||||
assign buf_dual_in[i] = ibuf_drainvec_vld[i] ? ibuf_dual : ldst_dual_dc5;
|
||||
assign buf_samedw_in[i] = ibuf_drainvec_vld[i] ? ibuf_samedw : ldst_samedw_dc5;
|
||||
assign buf_nomerge_in[i] = ibuf_drainvec_vld[i] ? (ibuf_nomerge | ibuf_force_drain) : no_dword_merge_dc5;
|
||||
assign buf_dualhi_in[i] = ibuf_drainvec_vld[i] ? ibuf_dual : (ibuf_byp & ldst_dual_dc5 & (i == WrPtr1_dc5)); // If it's dual, ibuf will always have the high
|
||||
assign buf_dualtag_in[i] = ibuf_drainvec_vld[i] ? ibuf_dualtag : ((ibuf_byp & ldst_dual_dc5 & (i == WrPtr1_dc5)) ? WrPtr0_dc5 : WrPtr1_dc5);
|
||||
assign buf_nb_in[i] = ibuf_drainvec_vld[i] ? ibuf_nb : lsu_nonblock_load_valid_dc5;
|
||||
assign buf_sideeffect_in[i] = ibuf_drainvec_vld[i] ? ibuf_sideeffect : is_sideeffects_dc5;
|
||||
assign buf_unsign_in[i] = ibuf_drainvec_vld[i] ? ibuf_unsign : lsu_pkt_dc5.unsign;
|
||||
assign buf_sz_in[i] = ibuf_drainvec_vld[i] ? ibuf_sz : {lsu_pkt_dc5.word, lsu_pkt_dc5.half};
|
||||
assign buf_write_in[i] = ibuf_drainvec_vld[i] ? ibuf_write : lsu_pkt_dc5.store;
|
||||
|
||||
|
||||
// Buffer entry state machine
|
||||
always_comb begin
|
||||
buf_nxtstate[i] = IDLE;
|
||||
buf_state_en[i] = '0;
|
||||
buf_cmd_state_bus_en[i] = '0;
|
||||
buf_resp_state_bus_en[i] = '0;
|
||||
buf_state_bus_en[i] = '0;
|
||||
buf_wr_en[i] = '0;
|
||||
buf_data_in[i] = '0;
|
||||
buf_data_en[i] = '0;
|
||||
buf_error_en[i] = '0;
|
||||
buf_rst[i] = '0;
|
||||
|
||||
case (buf_state[i])
|
||||
IDLE: begin
|
||||
buf_nxtstate[i] = lsu_bus_clk_en ? CMD : WAIT;
|
||||
buf_state_en[i] = (lsu_busreq_dc5 & (lsu_commit_dc5 | lsu_freeze_dc3) & (((ibuf_byp | ldst_dual_dc5) & ~ibuf_merge_en & (i == WrPtr0_dc5)) | (ibuf_byp & ldst_dual_dc5 & (i == WrPtr1_dc5)))) |
|
||||
(ibuf_drain_vld & (i == ibuf_tag));
|
||||
buf_wr_en[i] = buf_state_en[i];
|
||||
buf_data_en[i] = buf_state_en[i];
|
||||
buf_data_in[i] = (ibuf_drain_vld & (i == ibuf_tag)) ? ibuf_data_out[31:0] : store_data_lo_dc5[31:0];
|
||||
end
|
||||
WAIT: begin
|
||||
buf_nxtstate[i] = CMD;
|
||||
buf_state_en[i] = lsu_bus_clk_en;
|
||||
end
|
||||
CMD: begin
|
||||
buf_nxtstate[i] = RESP;
|
||||
buf_cmd_state_bus_en[i] = ((obuf_tag0 == i) | (obuf_merge & (obuf_tag1 == i))) & obuf_valid & obuf_wr_enQ; // Just use the recently written obuf_valid
|
||||
buf_state_bus_en[i] = buf_cmd_state_bus_en[i];
|
||||
buf_state_en[i] = buf_state_bus_en[i] & lsu_bus_clk_en;
|
||||
end
|
||||
RESP: begin
|
||||
buf_nxtstate[i] = (buf_write[i] & ~bus_rsp_write_error) ? IDLE : DONE; // Need to go to done to handle errors
|
||||
buf_resp_state_bus_en[i] = (bus_rsp_write & (bus_rsp_write_tag == LSU_BUS_TAG'(i))) |
|
||||
(bus_rsp_read & ((bus_rsp_read_tag == LSU_BUS_TAG'(i)) | (buf_dual[i] & buf_dualhi[i] & ~buf_write[i] & buf_samedw[i] & (bus_rsp_read_tag == LSU_BUS_TAG'(buf_dualtag[i])))));
|
||||
buf_state_bus_en[i] = buf_resp_state_bus_en[i];
|
||||
buf_state_en[i] = buf_state_bus_en[i] & lsu_bus_clk_en;
|
||||
buf_data_en[i] = buf_state_bus_en[i] & ~buf_write[i] & bus_rsp_read & lsu_bus_clk_en;
|
||||
// Need to capture the error for stores as well for AXI
|
||||
buf_error_en[i] = buf_state_bus_en[i] & lsu_bus_clk_en & ((bus_rsp_read_error & (bus_rsp_read_tag == LSU_BUS_TAG'(i))) |
|
||||
(bus_rsp_write_error & (bus_rsp_write_tag == LSU_BUS_TAG'(i))));
|
||||
buf_data_in[i][31:0] = (buf_state_en[i] & ~buf_error_en[i]) ? (buf_addr[i][2] ? bus_rsp_rdata[63:32] : bus_rsp_rdata[31:0]) : bus_rsp_rdata[31:0];
|
||||
end
|
||||
DONE: begin
|
||||
buf_nxtstate[i] = IDLE;
|
||||
buf_rst[i] = lsu_bus_clk_en_q & (buf_write[i] | ~buf_dual[i] | (buf_state[buf_dualtag[i]] == DONE));
|
||||
buf_state_en[i] = buf_rst[i];
|
||||
end
|
||||
default : begin
|
||||
buf_nxtstate[i] = IDLE;
|
||||
buf_state_en[i] = '0;
|
||||
buf_cmd_state_bus_en[i] = '0;
|
||||
buf_resp_state_bus_en[i] = '0;
|
||||
buf_state_bus_en[i] = '0;
|
||||
buf_wr_en[i] = '0;
|
||||
buf_data_in[i] = '0;
|
||||
buf_data_en[i] = '0;
|
||||
buf_error_en[i] = '0;
|
||||
buf_rst[i] = '0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
assign buf_state[i] = state_t'(buf_state_out[i]);
|
||||
rvdffs #(.WIDTH($bits(state_t))) buf_state_ff (.din(buf_nxtstate[i]), .dout(buf_state_out[i]), .en(buf_state_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdff #(.WIDTH(DEPTH)) buf_ageff (.din(buf_age_in[i]), .dout(buf_ageQ[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(DEPTH_LOG2)) buf_dualtagff (.din(buf_dualtag_in[i]), .dout(buf_dualtag[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_dualff (.din(buf_dual_in[i]), .dout(buf_dual[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_samedwff (.din(buf_samedw_in[i]), .dout(buf_samedw[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_nomergeff (.din(buf_nomerge_in[i]), .dout(buf_nomerge[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_dualhiff (.din(buf_dualhi_in[i]), .dout(buf_dualhi[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_nbff (.din(buf_nb_in[i]), .dout(buf_nb[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_sideeffectff (.din(buf_sideeffect_in[i]), .dout(buf_sideeffect[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_unsignff (.din(buf_unsign_in[i]), .dout(buf_unsign[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) buf_writeff (.din(buf_write_in[i]), .dout(buf_write[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(2)) buf_szff (.din(buf_sz_in[i]), .dout(buf_sz[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) buf_addrff (.din(buf_addr_in[i][31:0]), .dout(buf_addr[i]), .en(buf_wr_en[i]), .*);
|
||||
rvdffs #(.WIDTH(4)) buf_byteenff (.din(buf_byteen_in[i][3:0]), .dout(buf_byteen[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
rvdffe #(.WIDTH(32)) buf_dataff (.din(buf_data_in[i][31:0]), .dout(buf_data[i]), .en(buf_data_en[i]), .*);
|
||||
rvdffsc #(.WIDTH(1)) buf_errorff (.din(1'b1), .dout(buf_error[i]), .en(buf_error_en[i]), .clear(buf_rst[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||
|
||||
end
|
||||
|
||||
// buffer full logic
|
||||
always_comb begin
|
||||
buf_numvld_any[3:0] = ({3'b0,(lsu_pkt_dc1.valid & ~lsu_pkt_dc1.dma)} << (lsu_pkt_dc1.valid & ldst_dual_dc1)) +
|
||||
({3'b0,lsu_busreq_dc2} << ldst_dual_dc2) +
|
||||
({3'b0,lsu_busreq_dc3} << ldst_dual_dc3) +
|
||||
({3'b0,lsu_busreq_dc4} << ldst_dual_dc4) +
|
||||
({3'b0,lsu_busreq_dc5} << ldst_dual_dc5) +
|
||||
{3'b0,ibuf_valid};
|
||||
buf_numvld_wrcmd_any[3:0] = 4'b0;
|
||||
buf_numvld_cmd_any[3:0] = 4'b0;
|
||||
buf_numvld_pend_any[3:0] = 4'b0;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
buf_numvld_any[3:0] += {3'b0, (buf_state[i] != IDLE)};
|
||||
buf_numvld_wrcmd_any[3:0] += {3'b0, (buf_write[i] & (buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i])};
|
||||
buf_numvld_cmd_any[3:0] += {3'b0, ((buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i])};
|
||||
buf_numvld_pend_any[3:0] += {3'b0, ((buf_state[i] == WAIT) | ((buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i]))};
|
||||
end
|
||||
end
|
||||
|
||||
assign lsu_bus_buffer_pend_any = (buf_numvld_pend_any != 0);
|
||||
assign lsu_bus_buffer_full_any = (buf_numvld_any[3:0] >= (DEPTH-1));
|
||||
assign lsu_bus_buffer_empty_any = ~(|buf_state[DEPTH-1:0]) & ~ibuf_valid & ~obuf_valid;
|
||||
|
||||
// Freeze logic
|
||||
assign FreezePtrEn = lsu_busreq_dc3 & lsu_pkt_dc3.load & ld_freeze_dc3;
|
||||
assign ld_freeze_en = (is_sideeffects_dc2 | dec_nonblock_load_freeze_dc2 | dec_tlu_non_blocking_disable) & lsu_busreq_dc2 & lsu_pkt_dc2.load & ~lsu_freeze_dc3 & ~flush_dc2_up & ~ld_full_hit_dc2;
|
||||
always_comb begin
|
||||
ld_freeze_rst = flush_dc3 | (dec_tlu_cancel_e4 & ld_freeze_dc3);
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
ld_freeze_rst |= (buf_rst[i] & (DEPTH_LOG2'(i) == FreezePtr) & ~FreezePtrEn & ld_freeze_dc3);
|
||||
end
|
||||
end
|
||||
|
||||
// Load signals for freeze
|
||||
assign ld_block_bus_data[31:0] = 32'(({({32{buf_dual[FreezePtr]}} & buf_data[buf_dualtag[FreezePtr]]), buf_data[FreezePtr][31:0]}) >> (8*buf_addr[FreezePtr][1:0]));
|
||||
assign ld_precise_bus_error = (buf_error[FreezePtr] | (buf_dual[FreezePtr] & buf_error[buf_dualtag[FreezePtr]])) & ~buf_write[FreezePtr] & buf_rst[FreezePtr] & lsu_freeze_dc3 & ld_freeze_rst & ~flush_dc3; // Don't give bus error for interrupts
|
||||
assign ld_bus_error_addr_dc3[31:0] = buf_addr[FreezePtr][31:0];
|
||||
|
||||
// Non blocking ports
|
||||
assign lsu_nonblock_load_valid_dc3 = lsu_busreq_dc3 & lsu_pkt_dc3.valid & lsu_pkt_dc3.load & ~flush_dc3 & ~dec_nonblock_load_freeze_dc3 & ~lsu_freeze_dc3 & ~dec_tlu_non_blocking_disable;
|
||||
assign lsu_nonblock_load_tag_dc3[DEPTH_LOG2-1:0] = WrPtr0_dc3[DEPTH_LOG2-1:0];
|
||||
assign lsu_nonblock_load_inv_dc5 = lsu_nonblock_load_valid_dc5 & ~lsu_commit_dc5;
|
||||
assign lsu_nonblock_load_inv_tag_dc5[DEPTH_LOG2-1:0] = WrPtr0_dc5[DEPTH_LOG2-1:0]; // dc5 tag needs to be accurate even if there is no invalidate
|
||||
|
||||
always_comb begin
|
||||
lsu_nonblock_load_data_valid_lo = '0;
|
||||
lsu_nonblock_load_data_valid_hi = '0;
|
||||
lsu_nonblock_load_data_error_lo = '0;
|
||||
lsu_nonblock_load_data_error_hi = '0;
|
||||
lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0] = '0;
|
||||
lsu_nonblock_load_data_lo[31:0] = '0;
|
||||
lsu_nonblock_load_data_hi[31:0] = '0;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
// Use buf_rst[i] instead of buf_state_en[i] for timing
|
||||
lsu_nonblock_load_data_valid_hi |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & ~dec_tlu_non_blocking_disable & buf_nb[i] & ~buf_error[i] & (buf_dual[i] & buf_dualhi[i]);
|
||||
lsu_nonblock_load_data_valid_lo |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & ~dec_tlu_non_blocking_disable & buf_nb[i] & ~buf_error[i] & (~buf_dual[i] | ~buf_dualhi[i]);
|
||||
lsu_nonblock_load_data_error_hi |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & ~dec_tlu_non_blocking_disable & buf_error[i] & buf_nb[i] & (buf_dual[i] & buf_dualhi[i]);
|
||||
lsu_nonblock_load_data_error_lo |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_rst[i] & ~dec_tlu_non_blocking_disable & buf_error[i] & buf_nb[i] & (~buf_dual[i] | ~buf_dualhi[i]);
|
||||
lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0] |= DEPTH_LOG2'(i) & {DEPTH_LOG2{((buf_state[i] == DONE) & buf_nb[i] & buf_rst[i] & (~buf_dual[i] | ~buf_dualhi[i]))}};
|
||||
lsu_nonblock_load_data_lo[31:0] |= buf_data[i][31:0] & {32{((buf_state[i] == DONE) & buf_nb[i] & buf_rst[i] & (~buf_dual[i] | ~buf_dualhi[i]))}};
|
||||
lsu_nonblock_load_data_hi[31:0] |= buf_data[i][31:0] & {32{((buf_state[i] == DONE) & buf_nb[i] & buf_rst[i] & (buf_dual[i] & buf_dualhi[i]))}};
|
||||
end
|
||||
end
|
||||
|
||||
assign lsu_nonblock_addr_offset[1:0] = buf_addr[lsu_nonblock_load_data_tag][1:0];
|
||||
assign lsu_nonblock_sz[1:0] = buf_sz[lsu_nonblock_load_data_tag][1:0];
|
||||
assign lsu_nonblock_unsign = buf_unsign[lsu_nonblock_load_data_tag];
|
||||
assign lsu_nonblock_dual = buf_dual[lsu_nonblock_load_data_tag];
|
||||
assign lsu_nonblock_data_unalgn[31:0] = 32'({lsu_nonblock_load_data_hi[31:0], lsu_nonblock_load_data_lo[31:0]} >> 8*lsu_nonblock_addr_offset[1:0]);
|
||||
|
||||
assign lsu_nonblock_load_data_valid = lsu_nonblock_load_data_valid_lo & (~lsu_nonblock_dual | lsu_nonblock_load_data_valid_hi);
|
||||
assign lsu_nonblock_load_data_error = lsu_nonblock_load_data_error_lo | (lsu_nonblock_dual & lsu_nonblock_load_data_error_hi);
|
||||
assign lsu_nonblock_load_data = ({32{ lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b00)}} & {24'b0,lsu_nonblock_data_unalgn[7:0]}) |
|
||||
({32{ lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b01)}} & {16'b0,lsu_nonblock_data_unalgn[15:0]}) |
|
||||
({32{~lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b00)}} & {{24{lsu_nonblock_data_unalgn[7]}}, lsu_nonblock_data_unalgn[7:0]}) |
|
||||
({32{~lsu_nonblock_unsign & (lsu_nonblock_sz[1:0] == 2'b01)}} & {{16{lsu_nonblock_data_unalgn[15]}},lsu_nonblock_data_unalgn[15:0]}) |
|
||||
({32{(lsu_nonblock_sz[1:0] == 2'b10)}} & lsu_nonblock_data_unalgn[31:0]);
|
||||
|
||||
// Determine if there is a pending return to sideeffect load/store
|
||||
always_comb begin
|
||||
bus_sideeffect_pend = obuf_valid & obuf_sideeffect & dec_tlu_sideeffect_posted_disable;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
bus_sideeffect_pend |= ((buf_state[i] == RESP) & buf_sideeffect[i] & dec_tlu_sideeffect_posted_disable);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Imprecise bus errors
|
||||
assign lsu_imprecise_error_load_any = lsu_nonblock_load_data_error; // This is to make sure we send only one imprecise error for loads
|
||||
|
||||
|
||||
// We have no ordering rules for AXI. Need to check outstanding trxns to same address for AXI
|
||||
always_comb begin
|
||||
bus_addr_match_pending = '0;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
bus_addr_match_pending |= (obuf_valid & (obuf_addr[31:3] == buf_addr[i][31:3]) & (buf_state[i] == RESP) & ~((obuf_tag0 == LSU_BUS_TAG'(i)) | (obuf_merge & (obuf_tag1 == LSU_BUS_TAG'(i)))));
|
||||
end
|
||||
end
|
||||
|
||||
// Store imprecise error logic
|
||||
logic [DEPTH_LOG2-1:0] lsu_imprecise_error_store_tag;
|
||||
always_comb begin
|
||||
lsu_imprecise_error_store_any = '0;
|
||||
lsu_imprecise_error_store_tag = '0;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
lsu_imprecise_error_store_any |= lsu_bus_clk_en_q & (buf_state[i] == DONE) & buf_error[i] & buf_write[i];
|
||||
lsu_imprecise_error_store_tag |= DEPTH_LOG2'(i) & {DEPTH_LOG2{((buf_state[i] == DONE) & buf_error[i] & buf_write[i])}};
|
||||
end
|
||||
end
|
||||
assign lsu_imprecise_error_addr_any[31:0] = lsu_imprecise_error_load_any ? buf_addr[lsu_nonblock_load_data_tag] : buf_addr[lsu_imprecise_error_store_tag];
|
||||
|
||||
// Generic bus signals
|
||||
assign bus_cmd_ready = obuf_write ? ((obuf_cmd_done | obuf_data_done) ? (obuf_cmd_done ? lsu_axi_wready : lsu_axi_awready) : (lsu_axi_awready & lsu_axi_wready)) : lsu_axi_arready;
|
||||
assign bus_wcmd_sent = lsu_axi_awvalid & lsu_axi_awready;
|
||||
assign bus_wdata_sent = lsu_axi_wvalid & lsu_axi_wready;
|
||||
assign bus_cmd_sent = ((obuf_cmd_done | bus_wcmd_sent) & (obuf_data_done | bus_wdata_sent)) | (lsu_axi_arvalid & lsu_axi_arready);
|
||||
|
||||
assign bus_rsp_read = lsu_axi_rvalid_q & lsu_axi_rready_q;
|
||||
assign bus_rsp_write = lsu_axi_bvalid_q & lsu_axi_bready_q;
|
||||
assign bus_rsp_read_tag[LSU_BUS_TAG-1:0] = lsu_axi_rid_q[LSU_BUS_TAG-1:0];
|
||||
assign bus_rsp_write_tag[LSU_BUS_TAG-1:0] = lsu_axi_bid_q[LSU_BUS_TAG-1:0];
|
||||
assign bus_rsp_write_error = bus_rsp_write & (lsu_axi_bresp_q[1:0] != 2'b0);
|
||||
assign bus_rsp_read_error = bus_rsp_read & (lsu_axi_rresp_q[1:0] != 2'b0);
|
||||
assign bus_rsp_rdata[63:0] = lsu_axi_rdata_q[63:0];
|
||||
|
||||
// AXI command signals
|
||||
assign lsu_axi_awvalid = obuf_valid & obuf_write & ~obuf_cmd_done & ~bus_addr_match_pending;
|
||||
assign lsu_axi_awid[LSU_BUS_TAG-1:0] = LSU_BUS_TAG'(obuf_tag0);
|
||||
assign lsu_axi_awaddr[31:0] = obuf_sideeffect ? obuf_addr[31:0] : {obuf_addr[31:3],3'b0};
|
||||
assign lsu_axi_awsize[2:0] = obuf_sideeffect ? {1'b0, obuf_sz[1:0]} : 3'b011;
|
||||
assign lsu_axi_awprot[2:0] = '0;
|
||||
assign lsu_axi_awcache[3:0] = obuf_sideeffect ? 4'b0 : 4'b1111;
|
||||
assign lsu_axi_awregion[3:0] = obuf_addr[31:28];
|
||||
assign lsu_axi_awlen[7:0] = '0;
|
||||
assign lsu_axi_awburst[1:0] = 2'b01;
|
||||
assign lsu_axi_awqos[3:0] = '0;
|
||||
assign lsu_axi_awlock = '0;
|
||||
|
||||
assign lsu_axi_wvalid = obuf_valid & obuf_write & ~obuf_data_done & ~bus_addr_match_pending;
|
||||
assign lsu_axi_wstrb[7:0] = obuf_byteen[7:0] & {8{obuf_write}};
|
||||
assign lsu_axi_wdata[63:0] = obuf_data[63:0];
|
||||
assign lsu_axi_wlast = '1;
|
||||
|
||||
assign lsu_axi_arvalid = obuf_valid & ~obuf_write & ~bus_addr_match_pending;
|
||||
assign lsu_axi_arid[LSU_BUS_TAG-1:0] = LSU_BUS_TAG'(obuf_tag0);
|
||||
assign lsu_axi_araddr[31:0] = obuf_sideeffect ? obuf_addr[31:0] : {obuf_addr[31:3],3'b0};
|
||||
assign lsu_axi_arsize[2:0] = obuf_sideeffect ? {1'b0, obuf_sz[1:0]} : 3'b011;
|
||||
assign lsu_axi_arprot[2:0] = '0;
|
||||
assign lsu_axi_arcache[3:0] = obuf_sideeffect ? 4'b0 : 4'b1111;
|
||||
assign lsu_axi_arregion[3:0] = obuf_addr[31:28];
|
||||
assign lsu_axi_arlen[7:0] = '0;
|
||||
assign lsu_axi_arburst[1:0] = 2'b01;
|
||||
assign lsu_axi_arqos[3:0] = '0;
|
||||
assign lsu_axi_arlock = '0;
|
||||
|
||||
assign lsu_axi_bready = 1;
|
||||
assign lsu_axi_rready = 1;
|
||||
|
||||
// PMU signals
|
||||
assign lsu_pmu_bus_trxn = (lsu_axi_awvalid_q & lsu_axi_awready_q) | (lsu_axi_wvalid_q & lsu_axi_wready_q) | (lsu_axi_arvalid_q & lsu_axi_arready_q);
|
||||
assign lsu_pmu_bus_misaligned = lsu_busreq_dc2 & ldst_dual_dc2;
|
||||
assign lsu_pmu_bus_error = ld_bus_error_dc3 | lsu_imprecise_error_load_any | lsu_imprecise_error_store_any;
|
||||
assign lsu_pmu_bus_busy = (lsu_axi_awvalid_q & ~lsu_axi_awready_q) | (lsu_axi_wvalid_q & ~lsu_axi_wready_q) | (lsu_axi_arvalid_q & ~lsu_axi_arready_q);
|
||||
|
||||
rvdff #(.WIDTH(1)) lsu_axi_awvalid_ff (.din(lsu_axi_awvalid), .dout(lsu_axi_awvalid_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_axi_awready_ff (.din(lsu_axi_awready), .dout(lsu_axi_awready_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_axi_wvalid_ff (.din(lsu_axi_wvalid), .dout(lsu_axi_wvalid_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_axi_wready_ff (.din(lsu_axi_wready), .dout(lsu_axi_wready_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_axi_arvalid_ff (.din(lsu_axi_arvalid), .dout(lsu_axi_arvalid_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_axi_arready_ff (.din(lsu_axi_arready), .dout(lsu_axi_arready_q), .clk(lsu_busm_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) lsu_axi_bvalid_ff (.din(lsu_axi_bvalid), .dout(lsu_axi_bvalid_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_axi_bready_ff (.din(lsu_axi_bready), .dout(lsu_axi_bready_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(2)) lsu_axi_bresp_ff (.din(lsu_axi_bresp[1:0]), .dout(lsu_axi_bresp_q[1:0]), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(LSU_BUS_TAG)) lsu_axi_bid_ff (.din(lsu_axi_bid[LSU_BUS_TAG-1:0]), .dout(lsu_axi_bid_q[LSU_BUS_TAG-1:0]), .clk(lsu_busm_clk), .*);
|
||||
rvdffe #(.WIDTH(64)) lsu_axi_rdata_ff (.din(lsu_axi_rdata[63:0]), .dout(lsu_axi_rdata_q[63:0]), .en(lsu_axi_rvalid & lsu_bus_clk_en), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) lsu_axi_rvalid_ff (.din(lsu_axi_rvalid), .dout(lsu_axi_rvalid_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_axi_rready_ff (.din(lsu_axi_rready), .dout(lsu_axi_rready_q), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(2)) lsu_axi_rresp_ff (.din(lsu_axi_rresp[1:0]), .dout(lsu_axi_rresp_q[1:0]), .clk(lsu_busm_clk), .*);
|
||||
rvdff #(.WIDTH(LSU_BUS_TAG)) lsu_axi_rid_ff (.din(lsu_axi_rid[LSU_BUS_TAG-1:0]), .dout(lsu_axi_rid_q[LSU_BUS_TAG-1:0]), .clk(lsu_busm_clk), .*);
|
||||
|
||||
// General flops
|
||||
rvdffsc #(.WIDTH(1)) ld_freezeff (.din(1'b1), .dout(ld_freeze_dc3), .en(ld_freeze_en), .clear(ld_freeze_rst), .clk(lsu_free_c2_clk), .*);
|
||||
rvdffs #(.WIDTH(DEPTH_LOG2)) lsu_FreezePtrff (.din(WrPtr0_dc3), .dout(FreezePtr), .en(FreezePtrEn), .clk(lsu_free_c2_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ld_bus_errorff (.din(ld_precise_bus_error), .dout(ld_bus_error_dc3), .clk(lsu_free_c2_clk), .*);
|
||||
rvdff #(.WIDTH(32)) ld_bus_dataff (.din(ld_block_bus_data[31:0]), .dout(ld_bus_data_dc3[31:0]), .clk(lsu_free_c2_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(DEPTH_LOG2)) lsu_WrPtr0_dc4ff (.din(WrPtr0_dc3), .dout(WrPtr0_dc4), .clk(lsu_c2_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(DEPTH_LOG2)) lsu_WrPtr0_dc5ff (.din(WrPtr0_dc4), .dout(WrPtr0_dc5), .clk(lsu_c2_dc5_clk), .*);
|
||||
rvdff #(.WIDTH(DEPTH_LOG2)) lsu_WrPtr1_dc4ff (.din(WrPtr1_dc3), .dout(WrPtr1_dc4), .clk(lsu_c2_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(DEPTH_LOG2)) lsu_WrPtr1_dc5ff (.din(WrPtr1_dc4), .dout(WrPtr1_dc5), .clk(lsu_c2_dc5_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) lsu_busreq_dc3ff (.din(lsu_busreq_dc2 & ~lsu_freeze_dc3 & ~ld_full_hit_dc2), .dout(lsu_busreq_dc3), .clk(lsu_c2_dc3_clk), .*); // Don't want dc2 to dc3 propagation during freeze. Maybe used freeze gated clock
|
||||
rvdff #(.WIDTH(1)) lsu_busreq_dc4ff (.din(lsu_busreq_dc3 & ~flush_dc4), .dout(lsu_busreq_dc4), .clk(lsu_c2_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_busreq_dc5ff (.din(lsu_busreq_dc4 & ~flush_dc5), .dout(lsu_busreq_dc5), .clk(lsu_c2_dc5_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) dec_nonblock_load_freeze_dc3ff (.din(dec_nonblock_load_freeze_dc2), .dout(dec_nonblock_load_freeze_dc3), .clk(lsu_freeze_c2_dc3_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_nonblock_load_valid_dc4ff (.din(lsu_nonblock_load_valid_dc3), .dout(lsu_nonblock_load_valid_dc4), .clk(lsu_c2_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(1)) lsu_nonblock_load_valid_dc5ff (.din(lsu_nonblock_load_valid_dc4), .dout(lsu_nonblock_load_valid_dc5), .clk(lsu_c2_dc5_clk), .*);
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
|
||||
for (genvar i=0; i<4; i++) begin: GenByte
|
||||
assert_ld_byte_hitvecfn_lo_onehot: assert #0 ($onehot0(ld_byte_hitvecfn_lo[i][DEPTH-1:0]));
|
||||
assert_ld_byte_hitvecfn_hi_onehot: assert #0 ($onehot0(ld_byte_hitvecfn_hi[i][DEPTH-1:0]));
|
||||
end
|
||||
|
||||
assert_CmdPtr0Dec_onehot: assert #0 ($onehot0(CmdPtr0Dec[DEPTH-1:0]));
|
||||
assert_CmdPtr1Dec_onehot: assert #0 ($onehot0(CmdPtr1Dec[DEPTH-1:0]));
|
||||
|
||||
`endif
|
||||
|
||||
endmodule // lsu_bus_buffer
|
|
@ -0,0 +1,419 @@
|
|||
// 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: lsu interface with interface queue
|
||||
// Comments:
|
||||
//
|
||||
//********************************************************************************
|
||||
module lsu_bus_intf
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic scan_mode,
|
||||
input logic dec_tlu_non_blocking_disable, // disable non block
|
||||
input logic dec_tlu_wb_coalescing_disable, // disable write buffer coalescing
|
||||
input logic dec_tlu_ld_miss_byp_wb_disable, // disable ld miss bypass of the write buffer
|
||||
input logic dec_tlu_sideeffect_posted_disable, // disable posted writes to sideeffect addr to the bus
|
||||
|
||||
// various clocks needed for the bus reads and writes
|
||||
input logic lsu_c1_dc3_clk,
|
||||
input logic lsu_c1_dc4_clk,
|
||||
input logic lsu_c1_dc5_clk,
|
||||
input logic lsu_c2_dc3_clk,
|
||||
input logic lsu_c2_dc4_clk,
|
||||
input logic lsu_c2_dc5_clk,
|
||||
input logic lsu_freeze_c1_dc2_clk,
|
||||
input logic lsu_freeze_c1_dc3_clk,
|
||||
input logic lsu_freeze_c2_dc2_clk,
|
||||
input logic lsu_freeze_c2_dc3_clk,
|
||||
input logic lsu_bus_ibuf_c1_clk,
|
||||
input logic lsu_bus_obuf_c1_clk,
|
||||
input logic lsu_bus_buf_c1_clk,
|
||||
input logic lsu_free_c2_clk,
|
||||
input logic free_clk,
|
||||
input logic lsu_busm_clk,
|
||||
|
||||
input logic lsu_busreq_dc2, // bus request is in dc2
|
||||
|
||||
input lsu_pkt_t lsu_pkt_dc1, // lsu packet flowing down the pipe
|
||||
input lsu_pkt_t lsu_pkt_dc2, // lsu packet flowing down the pipe
|
||||
input lsu_pkt_t lsu_pkt_dc3, // lsu packet flowing down the pipe
|
||||
input lsu_pkt_t lsu_pkt_dc4, // lsu packet flowing down the pipe
|
||||
input lsu_pkt_t lsu_pkt_dc5, // lsu packet flowing down the pipe
|
||||
|
||||
input logic [31:0] lsu_addr_dc1, // lsu address flowing down the pipe
|
||||
input logic [31:0] lsu_addr_dc2, // lsu address flowing down the pipe
|
||||
input logic [31:0] lsu_addr_dc3, // lsu address flowing down the pipe
|
||||
input logic [31:0] lsu_addr_dc4, // lsu address flowing down the pipe
|
||||
input logic [31:0] lsu_addr_dc5, // lsu address flowing down the pipe
|
||||
|
||||
input logic [31:0] end_addr_dc1, // lsu address flowing down the pipe
|
||||
input logic [31:0] end_addr_dc2, // lsu address flowing down the pipe
|
||||
input logic [31:0] end_addr_dc3, // lsu address flowing down the pipe
|
||||
input logic [31:0] end_addr_dc4, // lsu address flowing down the pipe
|
||||
input logic [31:0] end_addr_dc5, // lsu address flowing down the pipe
|
||||
|
||||
input logic addr_external_dc2, // lsu instruction going to external
|
||||
input logic addr_external_dc3, // lsu instruction going to external
|
||||
input logic addr_external_dc4, // lsu instruction going to external
|
||||
input logic addr_external_dc5, // lsu instruction going to external
|
||||
|
||||
input logic [63:0] store_data_dc2, // store data flowing down the pipe
|
||||
input logic [63:0] store_data_dc3, // store data flowing down the pipe
|
||||
input logic [31:0] store_data_dc4, // store data flowing down the pipe
|
||||
input logic [31:0] store_data_dc5, // store data flowing down the pipe
|
||||
|
||||
input logic lsu_commit_dc5, // lsu instruction in dc5 commits
|
||||
input logic is_sideeffects_dc2, // lsu attribute is side_effects
|
||||
input logic is_sideeffects_dc3, // lsu attribute is side_effects
|
||||
input logic flush_dc2_up, // flush
|
||||
input logic flush_dc3, // flush
|
||||
input logic flush_dc4, // flush
|
||||
input logic flush_dc5, // flush
|
||||
input logic dec_tlu_cancel_e4, // cancel the bus load in dc4 and reset the freeze
|
||||
|
||||
output logic lsu_freeze_dc3, // load goes to external and asserts freeze
|
||||
output logic lsu_busreq_dc5, // bus request is in dc5
|
||||
output logic lsu_bus_buffer_pend_any, // bus buffer has a pending bus entry
|
||||
output logic lsu_bus_buffer_full_any, // write buffer is full
|
||||
output logic lsu_bus_buffer_empty_any, // write buffer is empty
|
||||
output logic [31:0] bus_read_data_dc3, // the bus return data
|
||||
|
||||
output logic ld_bus_error_dc3, // bus error in dc3
|
||||
output logic [31:0] ld_bus_error_addr_dc3, // address of the bus error
|
||||
|
||||
output logic lsu_imprecise_error_load_any, // imprecise load bus error
|
||||
output logic lsu_imprecise_error_store_any, // imprecise store bus error
|
||||
output logic [31:0] lsu_imprecise_error_addr_any, // address of the imprecise error
|
||||
|
||||
// Non-blocking loads
|
||||
input logic dec_nonblock_load_freeze_dc2,
|
||||
output logic lsu_nonblock_load_valid_dc3, // there is an external load -> put in the cam
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_dc3, // the tag of the external non block load
|
||||
output logic lsu_nonblock_load_inv_dc5, // invalidate signal for the cam entry for non block loads
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_dc5, // tag of the enrty which needs to be invalidated
|
||||
output logic lsu_nonblock_load_data_valid, // the non block is valid - sending information back to the cam
|
||||
output logic lsu_nonblock_load_data_error, // non block load has an error
|
||||
output logic [`RV_LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // the tag of the non block load sending the data/error
|
||||
output logic [31:0] lsu_nonblock_load_data, // Data of the non block load
|
||||
|
||||
// PMU events
|
||||
output logic lsu_pmu_bus_trxn,
|
||||
output logic lsu_pmu_bus_misaligned,
|
||||
output logic lsu_pmu_bus_error,
|
||||
output logic lsu_pmu_bus_busy,
|
||||
|
||||
// AXI Write Channels
|
||||
output logic lsu_axi_awvalid,
|
||||
input logic lsu_axi_awready,
|
||||
output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_awid,
|
||||
output logic [31:0] lsu_axi_awaddr,
|
||||
output logic [3:0] lsu_axi_awregion,
|
||||
output logic [7:0] lsu_axi_awlen,
|
||||
output logic [2:0] lsu_axi_awsize,
|
||||
output logic [1:0] lsu_axi_awburst,
|
||||
output logic lsu_axi_awlock,
|
||||
output logic [3:0] lsu_axi_awcache,
|
||||
output logic [2:0] lsu_axi_awprot,
|
||||
output logic [3:0] lsu_axi_awqos,
|
||||
|
||||
output logic lsu_axi_wvalid,
|
||||
input logic lsu_axi_wready,
|
||||
output logic [63:0] lsu_axi_wdata,
|
||||
output logic [7:0] lsu_axi_wstrb,
|
||||
output logic lsu_axi_wlast,
|
||||
|
||||
input logic lsu_axi_bvalid,
|
||||
output logic lsu_axi_bready,
|
||||
input logic [1:0] lsu_axi_bresp,
|
||||
input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic lsu_axi_arvalid,
|
||||
input logic lsu_axi_arready,
|
||||
output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_arid,
|
||||
output logic [31:0] lsu_axi_araddr,
|
||||
output logic [3:0] lsu_axi_arregion,
|
||||
output logic [7:0] lsu_axi_arlen,
|
||||
output logic [2:0] lsu_axi_arsize,
|
||||
output logic [1:0] lsu_axi_arburst,
|
||||
output logic lsu_axi_arlock,
|
||||
output logic [3:0] lsu_axi_arcache,
|
||||
output logic [2:0] lsu_axi_arprot,
|
||||
output logic [3:0] lsu_axi_arqos,
|
||||
|
||||
input logic lsu_axi_rvalid,
|
||||
output logic lsu_axi_rready,
|
||||
input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_rid,
|
||||
input logic [63:0] lsu_axi_rdata,
|
||||
input logic [1:0] lsu_axi_rresp,
|
||||
input logic lsu_axi_rlast,
|
||||
|
||||
input logic lsu_bus_clk_en
|
||||
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
logic ld_freeze_dc3;
|
||||
|
||||
logic lsu_bus_clk_en_q;
|
||||
logic ldst_dual_dc1, ldst_dual_dc2, ldst_dual_dc3, ldst_dual_dc4, ldst_dual_dc5;
|
||||
logic lsu_busreq_dc3, lsu_busreq_dc4;
|
||||
|
||||
logic [3:0] ldst_byteen_dc2, ldst_byteen_dc3, ldst_byteen_dc4, ldst_byteen_dc5;
|
||||
logic [7:0] ldst_byteen_ext_dc2, ldst_byteen_ext_dc3, ldst_byteen_ext_dc4, ldst_byteen_ext_dc5;
|
||||
logic [3:0] ldst_byteen_hi_dc2, ldst_byteen_hi_dc3, ldst_byteen_hi_dc4, ldst_byteen_hi_dc5;
|
||||
logic [3:0] ldst_byteen_lo_dc2, ldst_byteen_lo_dc3, ldst_byteen_lo_dc4, ldst_byteen_lo_dc5;
|
||||
logic is_sideeffects_dc4, is_sideeffects_dc5;
|
||||
|
||||
|
||||
logic [63:0] store_data_ext_dc3, store_data_ext_dc4, store_data_ext_dc5;
|
||||
logic [31:0] store_data_hi_dc3, store_data_hi_dc4, store_data_hi_dc5;
|
||||
logic [31:0] store_data_lo_dc3, store_data_lo_dc4, store_data_lo_dc5;
|
||||
|
||||
logic addr_match_dw_lo_dc5_dc4, addr_match_dw_lo_dc5_dc3, addr_match_dw_lo_dc5_dc2;
|
||||
logic addr_match_word_lo_dc5_dc4, addr_match_word_lo_dc5_dc3, addr_match_word_lo_dc5_dc2;
|
||||
logic no_word_merge_dc5, no_dword_merge_dc5;
|
||||
|
||||
logic ld_addr_dc3hit_lo_lo, ld_addr_dc3hit_hi_lo, ld_addr_dc3hit_lo_hi, ld_addr_dc3hit_hi_hi;
|
||||
logic ld_addr_dc4hit_lo_lo, ld_addr_dc4hit_hi_lo, ld_addr_dc4hit_lo_hi, ld_addr_dc4hit_hi_hi;
|
||||
logic ld_addr_dc5hit_lo_lo, ld_addr_dc5hit_hi_lo, ld_addr_dc5hit_lo_hi, ld_addr_dc5hit_hi_hi;
|
||||
|
||||
logic [3:0] ld_byte_dc3hit_lo_lo, ld_byte_dc3hit_hi_lo, ld_byte_dc3hit_lo_hi, ld_byte_dc3hit_hi_hi;
|
||||
logic [3:0] ld_byte_dc4hit_lo_lo, ld_byte_dc4hit_hi_lo, ld_byte_dc4hit_lo_hi, ld_byte_dc4hit_hi_hi;
|
||||
logic [3:0] ld_byte_dc5hit_lo_lo, ld_byte_dc5hit_hi_lo, ld_byte_dc5hit_lo_hi, ld_byte_dc5hit_hi_hi;
|
||||
|
||||
logic [3:0] ld_byte_hit_lo, ld_byte_dc3hit_lo, ld_byte_dc4hit_lo, ld_byte_dc5hit_lo;
|
||||
logic [3:0] ld_byte_hit_hi, ld_byte_dc3hit_hi, ld_byte_dc4hit_hi, ld_byte_dc5hit_hi;
|
||||
|
||||
logic [31:0] ld_fwddata_dc3pipe_lo, ld_fwddata_dc4pipe_lo, ld_fwddata_dc5pipe_lo;
|
||||
logic [31:0] ld_fwddata_dc3pipe_hi, ld_fwddata_dc4pipe_hi, ld_fwddata_dc5pipe_hi;
|
||||
|
||||
logic [3:0] ld_byte_hit_buf_lo, ld_byte_hit_buf_hi;
|
||||
logic [31:0] ld_fwddata_buf_lo, ld_fwddata_buf_hi;
|
||||
|
||||
logic ld_hit_rdbuf_hi, ld_hit_rdbuf_lo;
|
||||
logic [31:0] ld_fwddata_rdbuf_hi, ld_fwddata_rdbuf_lo;
|
||||
|
||||
logic [63:0] ld_fwddata_lo, ld_fwddata_hi;
|
||||
logic [31:0] ld_fwddata_dc2, ld_fwddata_dc3;
|
||||
logic [31:0] ld_bus_data_dc3;
|
||||
|
||||
logic ld_full_hit_hi_dc2, ld_full_hit_lo_dc2;
|
||||
logic ld_hit_dc2, ld_full_hit_dc2, ld_full_hit_dc3;
|
||||
logic is_aligned_dc5;
|
||||
|
||||
logic [63:32] ld_fwddata_dc2_nc;
|
||||
|
||||
logic lsu_write_buffer_empty_any;
|
||||
assign lsu_write_buffer_empty_any = 1'b1;
|
||||
|
||||
assign ldst_byteen_dc2[3:0] = ({4{lsu_pkt_dc2.by}} & 4'b0001) |
|
||||
({4{lsu_pkt_dc2.half}} & 4'b0011) |
|
||||
({4{lsu_pkt_dc2.word}} & 4'b1111);
|
||||
assign ldst_dual_dc1 = (lsu_addr_dc1[2] != end_addr_dc1[2]);
|
||||
assign lsu_freeze_dc3 = ld_freeze_dc3 & ~(flush_dc4 | flush_dc5);
|
||||
|
||||
// Determine if the packet is word aligned
|
||||
assign is_aligned_dc5 = (lsu_pkt_dc5.word & (lsu_addr_dc5[1:0] == 2'b0)) |
|
||||
(lsu_pkt_dc5.half & (lsu_addr_dc5[0] == 1'b0));
|
||||
|
||||
// Read/Write Buffer
|
||||
lsu_bus_buffer bus_buffer (
|
||||
.*
|
||||
);
|
||||
|
||||
// Logic to determine if dc5 store can be coalesced or not with younger stores. Bypass ibuf if cannot colaesced
|
||||
assign addr_match_dw_lo_dc5_dc4 = (lsu_addr_dc5[31:3] == lsu_addr_dc4[31:3]);
|
||||
assign addr_match_dw_lo_dc5_dc3 = (lsu_addr_dc5[31:3] == lsu_addr_dc3[31:3]);
|
||||
assign addr_match_dw_lo_dc5_dc2 = (lsu_addr_dc5[31:3] == lsu_addr_dc2[31:3]);
|
||||
|
||||
assign addr_match_word_lo_dc5_dc4 = addr_match_dw_lo_dc5_dc4 & ~(lsu_addr_dc5[2]^lsu_addr_dc4[2]);
|
||||
assign addr_match_word_lo_dc5_dc3 = addr_match_dw_lo_dc5_dc3 & ~(lsu_addr_dc5[2]^lsu_addr_dc3[2]);
|
||||
assign addr_match_word_lo_dc5_dc2 = addr_match_dw_lo_dc5_dc2 & ~(lsu_addr_dc5[2]^lsu_addr_dc2[2]);
|
||||
|
||||
assign no_word_merge_dc5 = lsu_busreq_dc5 & ~ldst_dual_dc5 &
|
||||
((lsu_busreq_dc4 & (lsu_pkt_dc4.load | ~addr_match_word_lo_dc5_dc4)) |
|
||||
(lsu_busreq_dc3 & ~lsu_busreq_dc4 & (lsu_pkt_dc3.load | ~addr_match_word_lo_dc5_dc3)) |
|
||||
(lsu_busreq_dc2 & ~lsu_busreq_dc3 & ~lsu_busreq_dc4 & (lsu_pkt_dc2.load | ~addr_match_word_lo_dc5_dc2)));
|
||||
|
||||
assign no_dword_merge_dc5 = lsu_busreq_dc5 & ~ldst_dual_dc5 &
|
||||
((lsu_busreq_dc4 & (lsu_pkt_dc4.load | ~addr_match_dw_lo_dc5_dc4)) |
|
||||
(lsu_busreq_dc3 & ~lsu_busreq_dc4 & (lsu_pkt_dc3.load | ~addr_match_dw_lo_dc5_dc3)) |
|
||||
(lsu_busreq_dc2 & ~lsu_busreq_dc3 & ~lsu_busreq_dc4 & (lsu_pkt_dc2.load | ~addr_match_dw_lo_dc5_dc2)));
|
||||
|
||||
// Create Hi/Lo signals
|
||||
assign ldst_byteen_ext_dc2[7:0] = {4'b0,ldst_byteen_dc2[3:0]} << lsu_addr_dc2[1:0];
|
||||
assign ldst_byteen_ext_dc3[7:0] = {4'b0,ldst_byteen_dc3[3:0]} << lsu_addr_dc3[1:0];
|
||||
assign ldst_byteen_ext_dc4[7:0] = {4'b0,ldst_byteen_dc4[3:0]} << lsu_addr_dc4[1:0];
|
||||
assign ldst_byteen_ext_dc5[7:0] = {4'b0,ldst_byteen_dc5[3:0]} << lsu_addr_dc5[1:0];
|
||||
|
||||
assign store_data_ext_dc3[63:0] = {32'b0,store_data_dc3[31:0]} << {lsu_addr_dc3[1:0],3'b0};
|
||||
assign store_data_ext_dc4[63:0] = {32'b0,store_data_dc4[31:0]} << {lsu_addr_dc4[1:0],3'b0};
|
||||
assign store_data_ext_dc5[63:0] = {32'b0,store_data_dc5[31:0]} << {lsu_addr_dc5[1:0],3'b0};
|
||||
|
||||
assign ldst_byteen_hi_dc2[3:0] = ldst_byteen_ext_dc2[7:4];
|
||||
assign ldst_byteen_lo_dc2[3:0] = ldst_byteen_ext_dc2[3:0];
|
||||
assign ldst_byteen_hi_dc3[3:0] = ldst_byteen_ext_dc3[7:4];
|
||||
assign ldst_byteen_lo_dc3[3:0] = ldst_byteen_ext_dc3[3:0];
|
||||
assign ldst_byteen_hi_dc4[3:0] = ldst_byteen_ext_dc4[7:4];
|
||||
assign ldst_byteen_lo_dc4[3:0] = ldst_byteen_ext_dc4[3:0];
|
||||
assign ldst_byteen_hi_dc5[3:0] = ldst_byteen_ext_dc5[7:4];
|
||||
assign ldst_byteen_lo_dc5[3:0] = ldst_byteen_ext_dc5[3:0];
|
||||
|
||||
assign store_data_hi_dc3[31:0] = store_data_ext_dc3[63:32];
|
||||
assign store_data_lo_dc3[31:0] = store_data_ext_dc3[31:0];
|
||||
assign store_data_hi_dc4[31:0] = store_data_ext_dc4[63:32];
|
||||
assign store_data_lo_dc4[31:0] = store_data_ext_dc4[31:0];
|
||||
assign store_data_hi_dc5[31:0] = store_data_ext_dc5[63:32];
|
||||
assign store_data_lo_dc5[31:0] = store_data_ext_dc5[31:0];
|
||||
|
||||
assign ld_addr_dc3hit_lo_lo = (lsu_addr_dc2[31:2] == lsu_addr_dc3[31:2]) & lsu_pkt_dc3.valid & lsu_pkt_dc3.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc3hit_lo_hi = (end_addr_dc2[31:2] == lsu_addr_dc3[31:2]) & lsu_pkt_dc3.valid & lsu_pkt_dc3.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc3hit_hi_lo = (lsu_addr_dc2[31:2] == end_addr_dc3[31:2]) & lsu_pkt_dc3.valid & lsu_pkt_dc3.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc3hit_hi_hi = (end_addr_dc2[31:2] == end_addr_dc3[31:2]) & lsu_pkt_dc3.valid & lsu_pkt_dc3.store & lsu_busreq_dc2;
|
||||
|
||||
assign ld_addr_dc4hit_lo_lo = (lsu_addr_dc2[31:2] == lsu_addr_dc4[31:2]) & lsu_pkt_dc4.valid & lsu_pkt_dc4.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc4hit_lo_hi = (end_addr_dc2[31:2] == lsu_addr_dc4[31:2]) & lsu_pkt_dc4.valid & lsu_pkt_dc4.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc4hit_hi_lo = (lsu_addr_dc2[31:2] == end_addr_dc4[31:2]) & lsu_pkt_dc4.valid & lsu_pkt_dc4.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc4hit_hi_hi = (end_addr_dc2[31:2] == end_addr_dc4[31:2]) & lsu_pkt_dc4.valid & lsu_pkt_dc4.store & lsu_busreq_dc2;
|
||||
|
||||
assign ld_addr_dc5hit_lo_lo = (lsu_addr_dc2[31:2] == lsu_addr_dc5[31:2]) & lsu_pkt_dc5.valid & lsu_pkt_dc5.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc5hit_lo_hi = (end_addr_dc2[31:2] == lsu_addr_dc5[31:2]) & lsu_pkt_dc5.valid & lsu_pkt_dc5.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc5hit_hi_lo = (lsu_addr_dc2[31:2] == end_addr_dc5[31:2]) & lsu_pkt_dc5.valid & lsu_pkt_dc5.store & lsu_busreq_dc2;
|
||||
assign ld_addr_dc5hit_hi_hi = (end_addr_dc2[31:2] == end_addr_dc5[31:2]) & lsu_pkt_dc5.valid & lsu_pkt_dc5.store & lsu_busreq_dc2;
|
||||
|
||||
for (genvar i=0; i<4; i++) begin
|
||||
assign ld_byte_dc3hit_lo_lo[i] = ld_addr_dc3hit_lo_lo & ldst_byteen_lo_dc3[i] & ldst_byteen_lo_dc2[i];
|
||||
assign ld_byte_dc3hit_lo_hi[i] = ld_addr_dc3hit_lo_hi & ldst_byteen_lo_dc3[i] & ldst_byteen_hi_dc2[i];
|
||||
assign ld_byte_dc3hit_hi_lo[i] = ld_addr_dc3hit_hi_lo & ldst_byteen_hi_dc3[i] & ldst_byteen_lo_dc2[i];
|
||||
assign ld_byte_dc3hit_hi_hi[i] = ld_addr_dc3hit_hi_hi & ldst_byteen_hi_dc3[i] & ldst_byteen_hi_dc2[i];
|
||||
|
||||
assign ld_byte_dc4hit_lo_lo[i] = ld_addr_dc4hit_lo_lo & ldst_byteen_lo_dc4[i] & ldst_byteen_lo_dc2[i];
|
||||
assign ld_byte_dc4hit_lo_hi[i] = ld_addr_dc4hit_lo_hi & ldst_byteen_lo_dc4[i] & ldst_byteen_hi_dc2[i];
|
||||
assign ld_byte_dc4hit_hi_lo[i] = ld_addr_dc4hit_hi_lo & ldst_byteen_hi_dc4[i] & ldst_byteen_lo_dc2[i];
|
||||
assign ld_byte_dc4hit_hi_hi[i] = ld_addr_dc4hit_hi_hi & ldst_byteen_hi_dc4[i] & ldst_byteen_hi_dc2[i];
|
||||
|
||||
assign ld_byte_dc5hit_lo_lo[i] = ld_addr_dc5hit_lo_lo & ldst_byteen_lo_dc5[i] & ldst_byteen_lo_dc2[i];
|
||||
assign ld_byte_dc5hit_lo_hi[i] = ld_addr_dc5hit_lo_hi & ldst_byteen_lo_dc5[i] & ldst_byteen_hi_dc2[i];
|
||||
assign ld_byte_dc5hit_hi_lo[i] = ld_addr_dc5hit_hi_lo & ldst_byteen_hi_dc5[i] & ldst_byteen_lo_dc2[i];
|
||||
assign ld_byte_dc5hit_hi_hi[i] = ld_addr_dc5hit_hi_hi & ldst_byteen_hi_dc5[i] & ldst_byteen_hi_dc2[i];
|
||||
|
||||
assign ld_byte_hit_lo[i] = ld_byte_dc3hit_lo_lo[i] | ld_byte_dc3hit_hi_lo[i] |
|
||||
ld_byte_dc4hit_lo_lo[i] | ld_byte_dc4hit_hi_lo[i] |
|
||||
ld_byte_dc5hit_lo_lo[i] | ld_byte_dc5hit_hi_lo[i] |
|
||||
ld_byte_hit_buf_lo[i];
|
||||
//ld_hit_rdbuf_lo;
|
||||
assign ld_byte_hit_hi[i] = ld_byte_dc3hit_lo_hi[i] | ld_byte_dc3hit_hi_hi[i] |
|
||||
ld_byte_dc4hit_lo_hi[i] | ld_byte_dc4hit_hi_hi[i] |
|
||||
ld_byte_dc5hit_lo_hi[i] | ld_byte_dc5hit_hi_hi[i] |
|
||||
ld_byte_hit_buf_hi[i];
|
||||
//ld_hit_rdbuf_hi;
|
||||
|
||||
assign ld_byte_dc3hit_lo[i] = ld_byte_dc3hit_lo_lo[i] | ld_byte_dc3hit_hi_lo[i];
|
||||
assign ld_byte_dc4hit_lo[i] = ld_byte_dc4hit_lo_lo[i] | ld_byte_dc4hit_hi_lo[i];
|
||||
assign ld_byte_dc5hit_lo[i] = ld_byte_dc5hit_lo_lo[i] | ld_byte_dc5hit_hi_lo[i];
|
||||
|
||||
assign ld_byte_dc3hit_hi[i] = ld_byte_dc3hit_lo_hi[i] | ld_byte_dc3hit_hi_hi[i];
|
||||
assign ld_byte_dc4hit_hi[i] = ld_byte_dc4hit_lo_hi[i] | ld_byte_dc4hit_hi_hi[i];
|
||||
assign ld_byte_dc5hit_hi[i] = ld_byte_dc5hit_lo_hi[i] | ld_byte_dc5hit_hi_hi[i];
|
||||
|
||||
assign ld_fwddata_dc3pipe_lo[(8*i)+7:(8*i)] = ({8{ld_byte_dc3hit_lo_lo[i]}} & store_data_lo_dc3[(8*i)+7:(8*i)]) |
|
||||
({8{ld_byte_dc3hit_hi_lo[i]}} & store_data_hi_dc3[(8*i)+7:(8*i)]);
|
||||
assign ld_fwddata_dc4pipe_lo[(8*i)+7:(8*i)] = ({8{ld_byte_dc4hit_lo_lo[i]}} & store_data_lo_dc4[(8*i)+7:(8*i)]) |
|
||||
({8{ld_byte_dc4hit_hi_lo[i]}} & store_data_hi_dc4[(8*i)+7:(8*i)]);
|
||||
assign ld_fwddata_dc5pipe_lo[(8*i)+7:(8*i)] = ({8{ld_byte_dc5hit_lo_lo[i]}} & store_data_lo_dc5[(8*i)+7:(8*i)]) |
|
||||
({8{ld_byte_dc5hit_hi_lo[i]}} & store_data_hi_dc5[(8*i)+7:(8*i)]);
|
||||
|
||||
assign ld_fwddata_dc3pipe_hi[(8*i)+7:(8*i)] = ({8{ld_byte_dc3hit_lo_hi[i]}} & store_data_lo_dc3[(8*i)+7:(8*i)]) |
|
||||
({8{ld_byte_dc3hit_hi_hi[i]}} & store_data_hi_dc3[(8*i)+7:(8*i)]);
|
||||
assign ld_fwddata_dc4pipe_hi[(8*i)+7:(8*i)] = ({8{ld_byte_dc4hit_lo_hi[i]}} & store_data_lo_dc4[(8*i)+7:(8*i)]) |
|
||||
({8{ld_byte_dc4hit_hi_hi[i]}} & store_data_hi_dc4[(8*i)+7:(8*i)]);
|
||||
assign ld_fwddata_dc5pipe_hi[(8*i)+7:(8*i)] = ({8{ld_byte_dc5hit_lo_hi[i]}} & store_data_lo_dc5[(8*i)+7:(8*i)]) |
|
||||
({8{ld_byte_dc5hit_hi_hi[i]}} & store_data_hi_dc5[(8*i)+7:(8*i)]);
|
||||
|
||||
// Final muxing between dc3/dc4/dc5
|
||||
assign ld_fwddata_lo[(8*i)+7:(8*i)] = ld_byte_dc3hit_lo[i] ? ld_fwddata_dc3pipe_lo[(8*i)+7:(8*i)] :
|
||||
ld_byte_dc4hit_lo[i] ? ld_fwddata_dc4pipe_lo[(8*i)+7:(8*i)] :
|
||||
ld_byte_dc5hit_lo[i] ? ld_fwddata_dc5pipe_lo[(8*i)+7:(8*i)] :
|
||||
ld_fwddata_buf_lo[(8*i)+7:(8*i)];
|
||||
|
||||
assign ld_fwddata_hi[(8*i)+7:(8*i)] = ld_byte_dc3hit_hi[i] ? ld_fwddata_dc3pipe_hi[(8*i)+7:(8*i)] :
|
||||
ld_byte_dc4hit_hi[i] ? ld_fwddata_dc4pipe_hi[(8*i)+7:(8*i)] :
|
||||
ld_byte_dc5hit_hi[i] ? ld_fwddata_dc5pipe_hi[(8*i)+7:(8*i)] :
|
||||
ld_fwddata_buf_hi[(8*i)+7:(8*i)];
|
||||
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
ld_full_hit_lo_dc2 = 1'b1;
|
||||
ld_full_hit_hi_dc2 = 1'b1;
|
||||
for (int i=0; i<4; i++) begin
|
||||
ld_full_hit_lo_dc2 &= (ld_byte_hit_lo[i] | ~ldst_byteen_lo_dc2[i]);
|
||||
ld_full_hit_hi_dc2 &= (ld_byte_hit_hi[i] | ~ldst_byteen_hi_dc2[i]);
|
||||
end
|
||||
end
|
||||
|
||||
// This will be high if atleast one byte hit the stores in pipe/write buffer (dc3/dc4/dc5/wrbuf)
|
||||
assign ld_hit_dc2 = (|ld_byte_hit_lo[3:0]) | (|ld_byte_hit_hi[3:0]);
|
||||
|
||||
// This will be high if all the bytes of load hit the stores in pipe/write buffer (dc3/dc4/dc5/wrbuf)
|
||||
assign ld_full_hit_dc2 = ld_full_hit_lo_dc2 & ld_full_hit_hi_dc2 & lsu_busreq_dc2 & lsu_pkt_dc2.load & ~is_sideeffects_dc2;
|
||||
|
||||
assign {ld_fwddata_dc2_nc[63:32], ld_fwddata_dc2[31:0]} = {ld_fwddata_hi[31:0], ld_fwddata_lo[31:0]} >> (8*lsu_addr_dc2[1:0]);
|
||||
assign bus_read_data_dc3[31:0] = ld_full_hit_dc3 ? ld_fwddata_dc3[31:0] : ld_bus_data_dc3[31:0];
|
||||
|
||||
// Fifo flops
|
||||
rvdff #(.WIDTH(1)) lsu_full_hit_dc3ff (.din(ld_full_hit_dc2), .dout(ld_full_hit_dc3), .clk(lsu_freeze_c2_dc3_clk), .*);
|
||||
rvdff #(.WIDTH(32)) lsu_fwddata_dc3ff (.din(ld_fwddata_dc2[31:0]), .dout(ld_fwddata_dc3[31:0]), .clk(lsu_c1_dc3_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) clken_ff (.din(lsu_bus_clk_en), .dout(lsu_bus_clk_en_q), .clk(free_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) ldst_dual_dc2ff (.din(ldst_dual_dc1), .dout(ldst_dual_dc2), .clk(lsu_freeze_c1_dc2_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ldst_dual_dc3ff (.din(ldst_dual_dc2), .dout(ldst_dual_dc3), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ldst_dual_dc4ff (.din(ldst_dual_dc3), .dout(ldst_dual_dc4), .clk(lsu_c1_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ldst_dual_dc5ff (.din(ldst_dual_dc4), .dout(ldst_dual_dc5), .clk(lsu_c1_dc5_clk), .*);
|
||||
rvdff #(.WIDTH(1)) is_sideeffects_dc4ff (.din(is_sideeffects_dc3), .dout(is_sideeffects_dc4), .clk(lsu_c1_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(1)) is_sideeffects_dc5ff (.din(is_sideeffects_dc4), .dout(is_sideeffects_dc5), .clk(lsu_c1_dc5_clk), .*);
|
||||
|
||||
rvdff #(4) lsu_byten_dc3ff (.*, .din(ldst_byteen_dc2[3:0]), .dout(ldst_byteen_dc3[3:0]), .clk(lsu_freeze_c1_dc3_clk));
|
||||
rvdff #(4) lsu_byten_dc4ff (.*, .din(ldst_byteen_dc3[3:0]), .dout(ldst_byteen_dc4[3:0]), .clk(lsu_c1_dc4_clk));
|
||||
rvdff #(4) lsu_byten_dc5ff (.*, .din(ldst_byteen_dc4[3:0]), .dout(ldst_byteen_dc5[3:0]), .clk(lsu_c1_dc5_clk));
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
// Assertion to check ld imprecise error comes with right address
|
||||
// property lsu_ld_imprecise_error_check;
|
||||
// @(posedge clk) disable iff (~rst_l) lsu_imprecise_error_load_any |-> (lsu_imprecise_error_addr_any[31:0] == ld_imprecise_bus_error_addr[31:0]);
|
||||
// endproperty
|
||||
// assert_ld_imprecise_error_check: assert property (lsu_ld_imprecise_error_check) else
|
||||
// $display("Wrong imprecise error address when lsu_imprecise_error_load_any asserted");
|
||||
|
||||
// // Assertion to check st imprecise error comes with right address
|
||||
// property lsu_st_imprecise_error_check;
|
||||
// @(posedge clk) disable iff (~rst_l) lsu_imprecise_error_store_any |-> (lsu_imprecise_error_addr_any[31:0] == store_bus_error_addr[31:0]);
|
||||
// endproperty
|
||||
// assert_st_imprecise_error_check: assert property (lsu_st_imprecise_error_check) else
|
||||
// $display("Wrong imprecise error address when lsu_imprecise_error_store_any asserted");
|
||||
|
||||
`endif
|
||||
|
||||
endmodule // lsu_bus_intf
|
|
@ -0,0 +1,210 @@
|
|||
// 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: Clock Generation Block
|
||||
// Comments: All the clocks are generate here
|
||||
//
|
||||
// //********************************************************************************
|
||||
|
||||
|
||||
module lsu_clkdomain
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk, // clock
|
||||
input logic free_clk, // clock
|
||||
input logic rst_l, // reset
|
||||
|
||||
// Inputs
|
||||
input logic clk_override, // chciken bit to turn off clock gating
|
||||
input logic lsu_freeze_dc3, // freeze
|
||||
input logic addr_in_dccm_dc2, // address in dccm
|
||||
input logic addr_in_pic_dc2, // address is in pic
|
||||
input logic dma_dccm_req, // dma is active
|
||||
input logic dma_mem_write, // dma write is active
|
||||
input logic load_stbuf_reqvld_dc3, // instruction to stbuf
|
||||
input logic store_stbuf_reqvld_dc3, // instruction to stbuf
|
||||
input logic stbuf_reqvld_any, // stbuf is draining
|
||||
input logic stbuf_reqvld_flushed_any, // instruction going to stbuf is flushed
|
||||
input logic lsu_busreq_dc5, // busreq in dc5
|
||||
input logic lsu_bus_buffer_pend_any, // bus buffer has a pending bus entry
|
||||
input logic lsu_bus_buffer_empty_any, // external bus buffer is empty
|
||||
input logic lsu_stbuf_empty_any, // stbuf is empty
|
||||
//input logic lsu_load_stall_any, // Need to turn on clocks for this case
|
||||
|
||||
input logic lsu_bus_clk_en, // bus clock enable
|
||||
|
||||
input lsu_pkt_t lsu_p, // lsu packet in decode
|
||||
input lsu_pkt_t lsu_pkt_dc1, // lsu packet in dc1
|
||||
input lsu_pkt_t lsu_pkt_dc2, // lsu packet in dc2
|
||||
input lsu_pkt_t lsu_pkt_dc3, // lsu packet in dc3
|
||||
input lsu_pkt_t lsu_pkt_dc4, // lsu packet in dc4
|
||||
input lsu_pkt_t lsu_pkt_dc5, // lsu packet in dc5
|
||||
|
||||
// Outputs
|
||||
output logic lsu_c1_dc3_clk, // dc3 pipe single pulse clock
|
||||
output logic lsu_c1_dc4_clk, // dc4 pipe single pulse clock
|
||||
output logic lsu_c1_dc5_clk, // dc5 pipe single pulse clock
|
||||
|
||||
output logic lsu_c2_dc3_clk, // dc3 pipe double pulse clock
|
||||
output logic lsu_c2_dc4_clk, // dc4 pipe double pulse clock
|
||||
output logic lsu_c2_dc5_clk, // dc5 pipe double pulse clock
|
||||
|
||||
output logic lsu_store_c1_dc1_clk, // store in dc1
|
||||
output logic lsu_store_c1_dc2_clk, // store in dc2
|
||||
output logic lsu_store_c1_dc3_clk, // store in dc3
|
||||
output logic lsu_store_c1_dc4_clk, // store in dc4
|
||||
output logic lsu_store_c1_dc5_clk, // store in dc5
|
||||
|
||||
output logic lsu_freeze_c1_dc1_clk, // freeze
|
||||
output logic lsu_freeze_c1_dc2_clk, // freeze
|
||||
output logic lsu_freeze_c1_dc3_clk, // freeze
|
||||
|
||||
output logic lsu_freeze_c2_dc1_clk,
|
||||
output logic lsu_freeze_c2_dc2_clk,
|
||||
output logic lsu_freeze_c2_dc3_clk,
|
||||
output logic lsu_freeze_c2_dc4_clk,
|
||||
|
||||
output logic lsu_dccm_c1_dc3_clk, // dccm clock
|
||||
output logic lsu_pic_c1_dc3_clk, // pic clock
|
||||
|
||||
output logic lsu_stbuf_c1_clk,
|
||||
output logic lsu_bus_obuf_c1_clk, // ibuf clock
|
||||
output logic lsu_bus_ibuf_c1_clk, // ibuf clock
|
||||
output logic lsu_bus_buf_c1_clk, // ibuf clock
|
||||
output logic lsu_busm_clk, // bus clock
|
||||
|
||||
output logic lsu_free_c2_clk,
|
||||
|
||||
input logic scan_mode
|
||||
);
|
||||
|
||||
logic lsu_c1_dc1_clken, lsu_c1_dc2_clken, lsu_c1_dc3_clken, lsu_c1_dc4_clken, lsu_c1_dc5_clken;
|
||||
logic lsu_c2_dc3_clken, lsu_c2_dc4_clken, lsu_c2_dc5_clken;
|
||||
logic lsu_c1_dc1_clken_q, lsu_c1_dc2_clken_q, lsu_c1_dc3_clken_q, lsu_c1_dc4_clken_q, lsu_c1_dc5_clken_q;
|
||||
logic lsu_store_c1_dc1_clken, lsu_store_c1_dc2_clken, lsu_store_c1_dc3_clken, lsu_store_c1_dc4_clken, lsu_store_c1_dc5_clken;
|
||||
|
||||
logic lsu_freeze_c1_dc1_clken, lsu_freeze_c1_dc2_clken, lsu_freeze_c1_dc3_clken, lsu_freeze_c1_dc4_clken;
|
||||
logic lsu_freeze_c2_dc1_clken, lsu_freeze_c2_dc2_clken, lsu_freeze_c2_dc3_clken, lsu_freeze_c2_dc4_clken;
|
||||
logic lsu_freeze_c1_dc1_clken_q, lsu_freeze_c1_dc2_clken_q, lsu_freeze_c1_dc3_clken_q, lsu_freeze_c1_dc4_clken_q;
|
||||
|
||||
logic lsu_stbuf_c1_clken;
|
||||
logic lsu_bus_ibuf_c1_clken, lsu_bus_obuf_c1_clken, lsu_bus_buf_c1_clken;
|
||||
|
||||
logic lsu_dccm_c1_dc3_clken, lsu_pic_c1_dc3_clken;
|
||||
|
||||
logic lsu_free_c1_clken, lsu_free_c1_clken_q, lsu_free_c2_clken;
|
||||
logic lsu_bus_valid_clken;
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
// Clock Enable logic
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
// Also use the flopped clock enable. We want to turn on the clocks from dc1->dc5 even if there is a freeze
|
||||
assign lsu_c1_dc1_clken = lsu_p.valid | dma_dccm_req | clk_override;
|
||||
assign lsu_c1_dc2_clken = lsu_pkt_dc1.valid | lsu_c1_dc1_clken_q | clk_override;
|
||||
assign lsu_c1_dc3_clken = lsu_pkt_dc2.valid | lsu_c1_dc2_clken_q | clk_override;
|
||||
assign lsu_c1_dc4_clken = lsu_pkt_dc3.valid | lsu_c1_dc3_clken_q | clk_override;
|
||||
assign lsu_c1_dc5_clken = lsu_pkt_dc4.valid | lsu_c1_dc4_clken_q | clk_override;
|
||||
|
||||
assign lsu_c2_dc3_clken = lsu_c1_dc3_clken | lsu_c1_dc3_clken_q | clk_override;
|
||||
assign lsu_c2_dc4_clken = lsu_c1_dc4_clken | lsu_c1_dc4_clken_q | clk_override;
|
||||
assign lsu_c2_dc5_clken = lsu_c1_dc5_clken | lsu_c1_dc5_clken_q | clk_override;
|
||||
|
||||
assign lsu_store_c1_dc1_clken = ((lsu_c1_dc1_clken & (lsu_p.store | dma_mem_write)) | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_store_c1_dc2_clken = ((lsu_c1_dc2_clken & lsu_pkt_dc1.store) | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_store_c1_dc3_clken = ((lsu_c1_dc3_clken & lsu_pkt_dc2.store) | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_store_c1_dc4_clken = (lsu_c1_dc4_clken & lsu_pkt_dc3.store) | clk_override;
|
||||
assign lsu_store_c1_dc5_clken = (lsu_c1_dc5_clken & lsu_pkt_dc4.store) | clk_override;
|
||||
|
||||
assign lsu_freeze_c1_dc1_clken = (lsu_p.valid | dma_dccm_req | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_freeze_c1_dc2_clken = (lsu_pkt_dc1.valid | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_freeze_c1_dc3_clken = (lsu_pkt_dc2.valid | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_freeze_c1_dc4_clken = (lsu_pkt_dc3.valid | clk_override) & ~lsu_freeze_dc3;
|
||||
|
||||
assign lsu_freeze_c2_dc1_clken = (lsu_freeze_c1_dc1_clken | lsu_freeze_c1_dc1_clken_q | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_freeze_c2_dc2_clken = (lsu_freeze_c1_dc2_clken | lsu_freeze_c1_dc2_clken_q | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_freeze_c2_dc3_clken = (lsu_freeze_c1_dc3_clken | lsu_freeze_c1_dc3_clken_q | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_freeze_c2_dc4_clken = (lsu_freeze_c1_dc4_clken | lsu_freeze_c1_dc4_clken_q | clk_override) & ~lsu_freeze_dc3;
|
||||
|
||||
|
||||
assign lsu_stbuf_c1_clken = load_stbuf_reqvld_dc3 | store_stbuf_reqvld_dc3 | stbuf_reqvld_any | stbuf_reqvld_flushed_any | clk_override;
|
||||
assign lsu_bus_ibuf_c1_clken = lsu_busreq_dc5 | clk_override;
|
||||
assign lsu_bus_obuf_c1_clken = ((lsu_bus_buffer_pend_any | lsu_busreq_dc5) & lsu_bus_clk_en) | clk_override;
|
||||
assign lsu_bus_buf_c1_clken = ~lsu_bus_buffer_empty_any | lsu_busreq_dc5 | clk_override;
|
||||
|
||||
assign lsu_dccm_c1_dc3_clken = ((lsu_c1_dc3_clken & addr_in_dccm_dc2) | clk_override) & ~lsu_freeze_dc3;
|
||||
assign lsu_pic_c1_dc3_clken = ((lsu_c1_dc3_clken & addr_in_pic_dc2) | clk_override) & ~lsu_freeze_dc3;
|
||||
|
||||
assign lsu_free_c1_clken = (lsu_p.valid | lsu_pkt_dc1.valid | lsu_pkt_dc2.valid | lsu_pkt_dc3.valid | lsu_pkt_dc4.valid | lsu_pkt_dc5.valid) |
|
||||
~lsu_bus_buffer_empty_any | ~lsu_stbuf_empty_any | clk_override;
|
||||
assign lsu_free_c2_clken = lsu_free_c1_clken | lsu_free_c1_clken_q | clk_override;
|
||||
|
||||
// Flops
|
||||
rvdff #(1) lsu_free_c1_clkenff (.din(lsu_free_c1_clken), .dout(lsu_free_c1_clken_q), .clk(free_clk), .*);
|
||||
|
||||
rvdff #(1) lsu_c1_dc1_clkenff (.din(lsu_c1_dc1_clken), .dout(lsu_c1_dc1_clken_q), .clk(lsu_free_c2_clk), .*);
|
||||
rvdff #(1) lsu_c1_dc2_clkenff (.din(lsu_c1_dc2_clken), .dout(lsu_c1_dc2_clken_q), .clk(lsu_free_c2_clk), .*);
|
||||
rvdff #(1) lsu_c1_dc3_clkenff (.din(lsu_c1_dc3_clken), .dout(lsu_c1_dc3_clken_q), .clk(lsu_free_c2_clk), .*);
|
||||
rvdff #(1) lsu_c1_dc4_clkenff (.din(lsu_c1_dc4_clken), .dout(lsu_c1_dc4_clken_q), .clk(lsu_free_c2_clk), .*);
|
||||
rvdff #(1) lsu_c1_dc5_clkenff (.din(lsu_c1_dc5_clken), .dout(lsu_c1_dc5_clken_q), .clk(lsu_free_c2_clk), .*);
|
||||
|
||||
rvdff #(1) lsu_freeze_c1_dc1_clkenff (.din(lsu_freeze_c1_dc1_clken), .dout(lsu_freeze_c1_dc1_clken_q), .clk(lsu_freeze_c2_dc1_clk), .*);
|
||||
rvdff #(1) lsu_freeze_c1_dc2_clkenff (.din(lsu_freeze_c1_dc2_clken), .dout(lsu_freeze_c1_dc2_clken_q), .clk(lsu_freeze_c2_dc2_clk), .*);
|
||||
rvdff #(1) lsu_freeze_c1_dc3_clkenff (.din(lsu_freeze_c1_dc3_clken), .dout(lsu_freeze_c1_dc3_clken_q), .clk(lsu_freeze_c2_dc3_clk), .*);
|
||||
rvdff #(1) lsu_freeze_c1_dc4_clkenff (.din(lsu_freeze_c1_dc4_clken), .dout(lsu_freeze_c1_dc4_clken_q), .clk(lsu_freeze_c2_dc4_clk), .*);
|
||||
|
||||
// Clock Headers
|
||||
rvclkhdr lsu_c1dc3_cgc ( .en(lsu_c1_dc3_clken), .l1clk(lsu_c1_dc3_clk), .* );
|
||||
rvclkhdr lsu_c1dc4_cgc ( .en(lsu_c1_dc4_clken), .l1clk(lsu_c1_dc4_clk), .* );
|
||||
rvclkhdr lsu_c1dc5_cgc ( .en(lsu_c1_dc5_clken), .l1clk(lsu_c1_dc5_clk), .* );
|
||||
|
||||
rvclkhdr lsu_c2dc3_cgc ( .en(lsu_c2_dc3_clken), .l1clk(lsu_c2_dc3_clk), .* );
|
||||
rvclkhdr lsu_c2dc4_cgc ( .en(lsu_c2_dc4_clken), .l1clk(lsu_c2_dc4_clk), .* );
|
||||
rvclkhdr lsu_c2dc5_cgc ( .en(lsu_c2_dc5_clken), .l1clk(lsu_c2_dc5_clk), .* );
|
||||
|
||||
rvclkhdr lsu_store_c1dc1_cgc (.en(lsu_store_c1_dc1_clken), .l1clk(lsu_store_c1_dc1_clk), .*);
|
||||
rvclkhdr lsu_store_c1dc2_cgc (.en(lsu_store_c1_dc2_clken), .l1clk(lsu_store_c1_dc2_clk), .*);
|
||||
rvclkhdr lsu_store_c1dc3_cgc (.en(lsu_store_c1_dc3_clken), .l1clk(lsu_store_c1_dc3_clk), .*);
|
||||
rvclkhdr lsu_store_c1dc4_cgc (.en(lsu_store_c1_dc4_clken), .l1clk(lsu_store_c1_dc4_clk), .*);
|
||||
rvclkhdr lsu_store_c1dc5_cgc (.en(lsu_store_c1_dc5_clken), .l1clk(lsu_store_c1_dc5_clk), .*);
|
||||
|
||||
rvclkhdr lsu_freeze_c1dc1_cgc ( .en(lsu_freeze_c1_dc1_clken), .l1clk(lsu_freeze_c1_dc1_clk), .* );
|
||||
rvclkhdr lsu_freeze_c1dc2_cgc ( .en(lsu_freeze_c1_dc2_clken), .l1clk(lsu_freeze_c1_dc2_clk), .* );
|
||||
rvclkhdr lsu_freeze_c1dc3_cgc ( .en(lsu_freeze_c1_dc3_clken), .l1clk(lsu_freeze_c1_dc3_clk), .* );
|
||||
|
||||
rvclkhdr lsu_freeze_c2dc1_cgc ( .en(lsu_freeze_c2_dc1_clken), .l1clk(lsu_freeze_c2_dc1_clk), .* );
|
||||
rvclkhdr lsu_freeze_c2dc2_cgc ( .en(lsu_freeze_c2_dc2_clken), .l1clk(lsu_freeze_c2_dc2_clk), .* );
|
||||
rvclkhdr lsu_freeze_c2dc3_cgc ( .en(lsu_freeze_c2_dc3_clken), .l1clk(lsu_freeze_c2_dc3_clk), .* );
|
||||
rvclkhdr lsu_freeze_c2dc4_cgc ( .en(lsu_freeze_c2_dc4_clken), .l1clk(lsu_freeze_c2_dc4_clk), .* );
|
||||
|
||||
rvclkhdr lsu_stbuf_c1_cgc ( .en(lsu_stbuf_c1_clken), .l1clk(lsu_stbuf_c1_clk), .* );
|
||||
rvclkhdr lsu_bus_ibuf_c1_cgc ( .en(lsu_bus_ibuf_c1_clken), .l1clk(lsu_bus_ibuf_c1_clk), .* );
|
||||
rvclkhdr lsu_bus_obuf_c1_cgc ( .en(lsu_bus_obuf_c1_clken), .l1clk(lsu_bus_obuf_c1_clk), .* );
|
||||
rvclkhdr lsu_bus_buf_c1_cgc ( .en(lsu_bus_buf_c1_clken), .l1clk(lsu_bus_buf_c1_clk), .* );
|
||||
|
||||
rvclkhdr lsu_busm_cgc (.en(lsu_bus_clk_en), .l1clk(lsu_busm_clk), .*);
|
||||
|
||||
rvclkhdr lsu_dccm_c1dc3_cgc (.en(lsu_dccm_c1_dc3_clken), .l1clk(lsu_dccm_c1_dc3_clk), .*);
|
||||
rvclkhdr lsu_pic_c1dc3_cgc (.en(lsu_pic_c1_dc3_clken), .l1clk(lsu_pic_c1_dc3_clk), .*);
|
||||
|
||||
rvclkhdr lsu_free_cgc (.en(lsu_free_c2_clken), .l1clk(lsu_free_c2_clk), .*);
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
// 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: DCCM for LSU pipe
|
||||
// Comments: Single ported memory
|
||||
//
|
||||
//
|
||||
// DC1 -> DC2 -> DC3 -> DC4 (Commit)
|
||||
//
|
||||
// //********************************************************************************
|
||||
|
||||
module lsu_dccm_ctl
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic lsu_freeze_c2_dc2_clk, // clocks
|
||||
input logic lsu_freeze_c2_dc3_clk,
|
||||
input logic lsu_dccm_c1_dc3_clk,
|
||||
input logic lsu_pic_c1_dc3_clk,
|
||||
|
||||
input logic rst_l,
|
||||
input logic lsu_freeze_dc3, // freze
|
||||
|
||||
input lsu_pkt_t lsu_pkt_dc3, // lsu packets
|
||||
input lsu_pkt_t lsu_pkt_dc1,
|
||||
input logic addr_in_dccm_dc1, // address maps to dccm
|
||||
input logic addr_in_pic_dc1, // address maps to pic
|
||||
input logic addr_in_pic_dc3, // address maps to pic
|
||||
input logic [31:0] lsu_addr_dc1, // starting byte address for loads
|
||||
input logic [`RV_DCCM_BITS-1:0] end_addr_dc1, // last address used to calculate unaligned
|
||||
input logic [`RV_DCCM_BITS-1:0] lsu_addr_dc3, // starting byte address for loads
|
||||
|
||||
input logic stbuf_reqvld_any, // write enable
|
||||
input logic stbuf_addr_in_pic_any, // stbuf is going to pic
|
||||
input logic [`RV_LSU_SB_BITS-1:0] stbuf_addr_any, // stbuf address (aligned)
|
||||
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_data_any, // the read out from stbuf
|
||||
input logic [`RV_DCCM_ECC_WIDTH-1:0] stbuf_ecc_any, // the encoded data with ECC bits
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_fwddata_hi_dc3, // stbuf fowarding to load
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_fwddata_lo_dc3, // stbuf fowarding to load
|
||||
input logic [`RV_DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_dc3, // stbuf fowarding to load
|
||||
input logic [`RV_DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_dc3, // stbuf fowarding to load
|
||||
|
||||
input logic lsu_double_ecc_error_dc3, // lsu has a DED
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] store_ecc_datafn_hi_dc3, // store data
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] store_ecc_datafn_lo_dc3, // store data
|
||||
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] dccm_data_hi_dc3, // data from the dccm
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] dccm_data_lo_dc3, // data from the dccm
|
||||
output logic [`RV_DCCM_ECC_WIDTH-1:0] dccm_data_ecc_hi_dc3, // data from the dccm + ecc
|
||||
output logic [`RV_DCCM_ECC_WIDTH-1:0] dccm_data_ecc_lo_dc3,
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] lsu_ld_data_dc3, // right justified, ie load byte will have data at 7:0
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] lsu_ld_data_corr_dc3, // right justified, ie load byte will have data at 7:0
|
||||
output logic [31:0] picm_mask_data_dc3, // pic data to stbuf
|
||||
output logic lsu_stbuf_commit_any, // stbuf wins the dccm port or is to pic
|
||||
output logic lsu_dccm_rden_dc3, // dccm read
|
||||
|
||||
output logic dccm_dma_rvalid, // dccm serviving the dma load
|
||||
output logic dccm_dma_ecc_error, // DMA load had ecc error
|
||||
output logic [63:0] dccm_dma_rdata, // dccm data to dma request
|
||||
|
||||
// DCCM ports
|
||||
output logic dccm_wren, // dccm interface -- write
|
||||
output logic dccm_rden, // dccm interface -- write
|
||||
output logic [`RV_DCCM_BITS-1:0] dccm_wr_addr, // dccm interface -- wr addr
|
||||
output logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_lo, // dccm interface -- read address for lo bank
|
||||
output logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_hi, // dccm interface -- read address for hi bank
|
||||
output logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_wr_data, // dccm write data
|
||||
|
||||
input logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // dccm read data back from the dccm
|
||||
input logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // dccm read data back from the dccm
|
||||
|
||||
// PIC ports
|
||||
output logic picm_wren, // write to pic
|
||||
output logic picm_rden, // read to pick
|
||||
output logic picm_mken, // write to pic need a mask
|
||||
output logic [31:0] picm_addr, // address for pic access - shared between reads and write
|
||||
output logic [31:0] picm_wr_data, // write data
|
||||
input logic [31:0] picm_rd_data, // read data
|
||||
|
||||
input logic scan_mode // scan mode
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
`ifdef RV_DCCM_ENABLE
|
||||
localparam DCCM_ENABLE = 1'b1;
|
||||
`else
|
||||
localparam DCCM_ENABLE = 1'b0;
|
||||
`endif
|
||||
|
||||
localparam DCCM_WIDTH_BITS = $clog2(DCCM_BYTE_WIDTH);
|
||||
localparam PIC_BITS =`RV_PIC_BITS;
|
||||
|
||||
logic lsu_dccm_rden_dc1, lsu_dccm_rden_dc2;
|
||||
logic [DCCM_DATA_WIDTH-1:0] dccm_data_hi_dc2, dccm_data_lo_dc2;
|
||||
logic [DCCM_ECC_WIDTH-1:0] dccm_data_ecc_hi_dc2, dccm_data_ecc_lo_dc2;
|
||||
logic [63:0] dccm_dout_dc3, dccm_corr_dout_dc3;
|
||||
logic [63:0] stbuf_fwddata_dc3;
|
||||
logic [7:0] stbuf_fwdbyteen_dc3;
|
||||
logic [63:0] lsu_rdata_dc3, lsu_rdata_corr_dc3;
|
||||
logic [63:0] picm_rd_data_dc3;
|
||||
logic [31:0] picm_rd_data_lo_dc3;
|
||||
logic [63:32] lsu_ld_data_dc3_nc, lsu_ld_data_corr_dc3_nc;
|
||||
|
||||
assign dccm_dma_rvalid = lsu_pkt_dc3.valid & lsu_pkt_dc3.load & lsu_pkt_dc3.dma;
|
||||
assign dccm_dma_ecc_error = lsu_double_ecc_error_dc3;
|
||||
assign dccm_dma_rdata[63:0] = lsu_rdata_corr_dc3[63:0];
|
||||
|
||||
|
||||
assign {lsu_ld_data_dc3_nc[63:32], lsu_ld_data_dc3[31:0]} = lsu_rdata_dc3[63:0] >> 8*lsu_addr_dc3[1:0];
|
||||
assign {lsu_ld_data_corr_dc3_nc[63:32], lsu_ld_data_corr_dc3[31:0]} = lsu_rdata_corr_dc3[63:0] >> 8*lsu_addr_dc3[1:0];
|
||||
|
||||
assign dccm_dout_dc3[63:0] = {dccm_data_hi_dc3[DCCM_DATA_WIDTH-1:0], dccm_data_lo_dc3[DCCM_DATA_WIDTH-1:0]};
|
||||
assign dccm_corr_dout_dc3[63:0] = {store_ecc_datafn_hi_dc3[DCCM_DATA_WIDTH-1:0], store_ecc_datafn_lo_dc3[DCCM_DATA_WIDTH-1:0]};
|
||||
assign stbuf_fwddata_dc3[63:0] = {stbuf_fwddata_hi_dc3[DCCM_DATA_WIDTH-1:0], stbuf_fwddata_lo_dc3[DCCM_DATA_WIDTH-1:0]};
|
||||
assign stbuf_fwdbyteen_dc3[7:0] = {stbuf_fwdbyteen_hi_dc3[DCCM_BYTE_WIDTH-1:0], stbuf_fwdbyteen_lo_dc3[DCCM_BYTE_WIDTH-1:0]};
|
||||
|
||||
for (genvar i=0; i<8; i++) begin: GenLoop
|
||||
assign lsu_rdata_dc3[(8*i)+7:8*i] = stbuf_fwdbyteen_dc3[i] ? stbuf_fwddata_dc3[(8*i)+7:8*i] :
|
||||
(addr_in_pic_dc3 ? picm_rd_data_dc3[(8*i)+7:8*i] : dccm_dout_dc3[(8*i)+7:8*i]);
|
||||
assign lsu_rdata_corr_dc3[(8*i)+7:8*i] = stbuf_fwdbyteen_dc3[i] ? stbuf_fwddata_dc3[(8*i)+7:8*i] :
|
||||
(addr_in_pic_dc3 ? picm_rd_data_dc3[(8*i)+7:8*i] : dccm_corr_dout_dc3[(8*i)+7:8*i]);
|
||||
end
|
||||
|
||||
assign lsu_stbuf_commit_any = stbuf_reqvld_any & ~lsu_freeze_dc3 & (
|
||||
(~(lsu_dccm_rden_dc1 | picm_rden | picm_mken)) |
|
||||
((picm_rden | picm_mken) & ~stbuf_addr_in_pic_any) |
|
||||
(lsu_dccm_rden_dc1 & (stbuf_addr_in_pic_any | (~((stbuf_addr_any[DCCM_WIDTH_BITS+:DCCM_BANK_BITS] == lsu_addr_dc1[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]) |
|
||||
(stbuf_addr_any[DCCM_WIDTH_BITS+:DCCM_BANK_BITS] == end_addr_dc1[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]))))));
|
||||
|
||||
// No need to read for aligned word/dword stores since ECC will come by new data completely
|
||||
assign lsu_dccm_rden_dc1 = lsu_pkt_dc1.valid & (lsu_pkt_dc1.load | (lsu_pkt_dc1.store & (~(lsu_pkt_dc1.word | lsu_pkt_dc1.dword) | (lsu_addr_dc1[1:0] != 2'b0)))) & addr_in_dccm_dc1;
|
||||
|
||||
// DCCM inputs
|
||||
assign dccm_wren = lsu_stbuf_commit_any & ~stbuf_addr_in_pic_any;
|
||||
assign dccm_rden = lsu_dccm_rden_dc1 & addr_in_dccm_dc1;
|
||||
assign dccm_wr_addr[DCCM_BITS-1:0] = stbuf_addr_any[DCCM_BITS-1:0];
|
||||
assign dccm_rd_addr_lo[DCCM_BITS-1:0] = lsu_addr_dc1[DCCM_BITS-1:0];
|
||||
assign dccm_rd_addr_hi[DCCM_BITS-1:0] = end_addr_dc1[DCCM_BITS-1:0];
|
||||
assign dccm_wr_data[DCCM_FDATA_WIDTH-1:0] = {stbuf_ecc_any[DCCM_ECC_WIDTH-1:0],stbuf_data_any[DCCM_DATA_WIDTH-1:0]};
|
||||
|
||||
// DCCM outputs
|
||||
assign dccm_data_lo_dc2[DCCM_DATA_WIDTH-1:0] = dccm_rd_data_lo[DCCM_DATA_WIDTH-1:0];
|
||||
assign dccm_data_hi_dc2[DCCM_DATA_WIDTH-1:0] = dccm_rd_data_hi[DCCM_DATA_WIDTH-1:0];
|
||||
|
||||
assign dccm_data_ecc_lo_dc2[DCCM_ECC_WIDTH-1:0] = dccm_rd_data_lo[DCCM_FDATA_WIDTH-1:DCCM_DATA_WIDTH];
|
||||
assign dccm_data_ecc_hi_dc2[DCCM_ECC_WIDTH-1:0] = dccm_rd_data_hi[DCCM_FDATA_WIDTH-1:DCCM_DATA_WIDTH];
|
||||
|
||||
// PIC signals. PIC ignores the lower 2 bits of address since PIC memory registers are 32-bits
|
||||
assign picm_wren = lsu_stbuf_commit_any & stbuf_addr_in_pic_any;
|
||||
assign picm_rden = lsu_pkt_dc1.valid & lsu_pkt_dc1.load & addr_in_pic_dc1;
|
||||
assign picm_mken = lsu_pkt_dc1.valid & lsu_pkt_dc1.store & addr_in_pic_dc1; // Get the mask for stores
|
||||
assign picm_addr[31:0] = (picm_rden | picm_mken) ? (`RV_PIC_BASE_ADDR | {17'b0,lsu_addr_dc1[14:0]}) : (`RV_PIC_BASE_ADDR | {{32-PIC_BITS{1'b0}},stbuf_addr_any[`RV_PIC_BITS-1:0]});
|
||||
//assign picm_addr[31:0] = (picm_rden | picm_mken) ? {`RV_PIC_REGION,`RV_PIC_OFFSET,3'b0,lsu_addr_dc1[14:0]} : {`RV_PIC_REGION,`RV_PIC_OFFSET,{18-PIC_BITS{1'b0}},stbuf_addr_any[`RV_PIC_BITS-1:0]};
|
||||
assign picm_wr_data[31:0] = stbuf_data_any[31:0];
|
||||
|
||||
|
||||
// Flops
|
||||
assign picm_mask_data_dc3[31:0] = picm_rd_data_lo_dc3[31:0];
|
||||
assign picm_rd_data_dc3[63:0] = {picm_rd_data_lo_dc3[31:0], picm_rd_data_lo_dc3[31:0]} ;
|
||||
rvdff #(32) picm_data_ff (.*, .din(picm_rd_data[31:0]), .dout(picm_rd_data_lo_dc3[31:0]), .clk(lsu_pic_c1_dc3_clk));
|
||||
if (DCCM_ENABLE == 1) begin: Gen_dccm_enable
|
||||
rvdff #(1) dccm_rden_dc2ff (.*, .din(lsu_dccm_rden_dc1), .dout(lsu_dccm_rden_dc2), .clk(lsu_freeze_c2_dc2_clk));
|
||||
rvdff #(1) dccm_rden_dc3ff (.*, .din(lsu_dccm_rden_dc2), .dout(lsu_dccm_rden_dc3), .clk(lsu_freeze_c2_dc3_clk));
|
||||
|
||||
rvdff #(DCCM_DATA_WIDTH) dccm_data_hi_ff (.*, .din(dccm_data_hi_dc2[DCCM_DATA_WIDTH-1:0]), .dout(dccm_data_hi_dc3[DCCM_DATA_WIDTH-1:0]), .clk(lsu_dccm_c1_dc3_clk));
|
||||
rvdff #(DCCM_DATA_WIDTH) dccm_data_lo_ff (.*, .din(dccm_data_lo_dc2[DCCM_DATA_WIDTH-1:0]), .dout(dccm_data_lo_dc3[DCCM_DATA_WIDTH-1:0]), .clk(lsu_dccm_c1_dc3_clk));
|
||||
|
||||
rvdff #(DCCM_ECC_WIDTH) dccm_data_ecc_hi_ff (.*, .din(dccm_data_ecc_hi_dc2[DCCM_ECC_WIDTH-1:0]), .dout(dccm_data_ecc_hi_dc3[DCCM_ECC_WIDTH-1:0]), .clk(lsu_dccm_c1_dc3_clk));
|
||||
rvdff #(DCCM_ECC_WIDTH) dccm_data_ecc_lo_ff (.*, .din(dccm_data_ecc_lo_dc2[DCCM_ECC_WIDTH-1:0]), .dout(dccm_data_ecc_lo_dc3[DCCM_ECC_WIDTH-1:0]), .clk(lsu_dccm_c1_dc3_clk));
|
||||
end else begin: Gen_dccm_disable
|
||||
assign lsu_dccm_rden_dc2 = '0;
|
||||
assign lsu_dccm_rden_dc3 = '0;
|
||||
assign dccm_data_hi_dc3[DCCM_DATA_WIDTH-1:0] = '0;
|
||||
assign dccm_data_lo_dc3[DCCM_DATA_WIDTH-1:0] = '0;
|
||||
assign dccm_data_ecc_hi_dc3[DCCM_ECC_WIDTH-1:0] = '0;
|
||||
assign dccm_data_ecc_lo_dc3[DCCM_ECC_WIDTH-1:0] = '0;
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,127 @@
|
|||
// 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: DCCM for LSU pipe
|
||||
// Comments: Single ported memory
|
||||
//
|
||||
//
|
||||
// DC1 -> DC2 -> DC3 -> DC4 (Commit)
|
||||
//
|
||||
// //********************************************************************************
|
||||
|
||||
module lsu_dccm_mem
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk, // clock
|
||||
input logic rst_l,
|
||||
input logic lsu_freeze_dc3, // freeze
|
||||
input logic clk_override, // clock override
|
||||
|
||||
input logic dccm_wren, // write enable
|
||||
input logic dccm_rden, // read enable
|
||||
input logic [`RV_DCCM_BITS-1:0] dccm_wr_addr, // write address
|
||||
input logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_lo, // read address
|
||||
input logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_hi, // read address for the upper bank in case of a misaligned access
|
||||
input logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_wr_data, // write data
|
||||
|
||||
output logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // read data from the lo bank
|
||||
output logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // read data from the hi bank
|
||||
|
||||
input logic scan_mode
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
localparam DCCM_WIDTH_BITS = $clog2(DCCM_BYTE_WIDTH);
|
||||
localparam DCCM_INDEX_BITS = (DCCM_BITS - DCCM_BANK_BITS - DCCM_WIDTH_BITS);
|
||||
|
||||
logic [DCCM_NUM_BANKS-1:0] wren_bank;
|
||||
logic [DCCM_NUM_BANKS-1:0] rden_bank;
|
||||
logic [DCCM_NUM_BANKS-1:0] [DCCM_BITS-1:(DCCM_BANK_BITS+2)] addr_bank;
|
||||
logic [DCCM_BITS-1:(DCCM_BANK_BITS+DCCM_WIDTH_BITS)] rd_addr_even, rd_addr_odd;
|
||||
logic rd_unaligned;
|
||||
logic [DCCM_NUM_BANKS-1:0] [DCCM_FDATA_WIDTH-1:0] dccm_bank_dout;
|
||||
logic [DCCM_FDATA_WIDTH-1:0] wrdata;
|
||||
|
||||
logic [DCCM_NUM_BANKS-1:0] wren_bank_q;
|
||||
logic [DCCM_NUM_BANKS-1:0] rden_bank_q;
|
||||
logic [DCCM_NUM_BANKS-1:0][DCCM_BITS-1:(DCCM_BANK_BITS+2)] addr_bank_q;
|
||||
logic [DCCM_FDATA_WIDTH-1:0] dccm_wr_data_q;
|
||||
|
||||
logic [(DCCM_WIDTH_BITS+DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_lo_q;
|
||||
logic [(DCCM_WIDTH_BITS+DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_hi_q;
|
||||
|
||||
logic [DCCM_NUM_BANKS-1:0] dccm_clk;
|
||||
logic [DCCM_NUM_BANKS-1:0] dccm_clken;
|
||||
|
||||
assign rd_unaligned = (dccm_rd_addr_lo[DCCM_WIDTH_BITS+:DCCM_BANK_BITS] != dccm_rd_addr_hi[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]);
|
||||
|
||||
// Align the read data
|
||||
assign dccm_rd_data_lo[DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]][DCCM_FDATA_WIDTH-1:0];
|
||||
assign dccm_rd_data_hi[DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]][DCCM_FDATA_WIDTH-1:0];
|
||||
|
||||
// Generate even/odd address
|
||||
// assign rd_addr_even[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = dccm_rd_addr_lo[2] ? dccm_rd_addr_hi[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
|
||||
// dccm_rd_addr_lo[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS];
|
||||
|
||||
// assign rd_addr_odd[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = dccm_rd_addr_lo[2] ? dccm_rd_addr_lo[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
|
||||
// dccm_rd_addr_hi[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS];
|
||||
|
||||
// 8 Banks, 16KB each (2048 x 72)
|
||||
for (genvar i=0; i<DCCM_NUM_BANKS; i++) begin: mem_bank
|
||||
assign wren_bank[i] = dccm_wren & (dccm_wr_addr[2+:DCCM_BANK_BITS] == i);
|
||||
assign rden_bank[i] = dccm_rden & ((dccm_rd_addr_hi[2+:DCCM_BANK_BITS] == i) | (dccm_rd_addr_lo[2+:DCCM_BANK_BITS] == i));
|
||||
assign addr_bank[i][(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? dccm_wr_addr[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
|
||||
(((dccm_rd_addr_hi[2+:DCCM_BANK_BITS] == i) & rd_unaligned) ?
|
||||
dccm_rd_addr_hi[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
|
||||
dccm_rd_addr_lo[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS]);
|
||||
|
||||
// if (i%2 == 0) begin
|
||||
// assign addr_bank[i][(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? dccm_wr_addr[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
|
||||
// rd_addr_even[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS];
|
||||
// end else begin
|
||||
// assign addr_bank[i][(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? dccm_wr_addr[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
|
||||
// rd_addr_odd[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS];
|
||||
// end
|
||||
|
||||
// clock gating section
|
||||
assign dccm_clken[i] = (wren_bank[i] | rden_bank[i] | clk_override) & ~lsu_freeze_dc3;
|
||||
rvclkhdr lsu_dccm_cgc (.en(dccm_clken[i]), .l1clk(dccm_clk[i]), .*);
|
||||
// end clock gating section
|
||||
|
||||
`RV_DCCM_DATA_CELL dccm_bank (
|
||||
// Primary ports
|
||||
.CLK(dccm_clk[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(dccm_wr_data[DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0])
|
||||
|
||||
);
|
||||
|
||||
end : mem_bank
|
||||
|
||||
// Flops
|
||||
rvdffs #(DCCM_BANK_BITS) rd_addr_lo_ff (.*, .din(dccm_rd_addr_lo[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .dout(dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .en(~lsu_freeze_dc3));
|
||||
rvdffs #(DCCM_BANK_BITS) rd_addr_hi_ff (.*, .din(dccm_rd_addr_hi[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .dout(dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .en(~lsu_freeze_dc3));
|
||||
|
||||
endmodule // lsu_dccm_mem
|
||||
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
// 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: Top level file for load store unit
|
||||
// Comments:
|
||||
//
|
||||
//
|
||||
// DC1 -> DC2 -> DC3 -> DC4 (Commit)
|
||||
//
|
||||
//********************************************************************************
|
||||
module lsu_ecc
|
||||
import swerv_types::*;
|
||||
(
|
||||
|
||||
input logic lsu_c2_dc4_clk, // clocks
|
||||
input logic lsu_c1_dc4_clk,
|
||||
input logic lsu_c1_dc5_clk,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
|
||||
input lsu_pkt_t lsu_pkt_dc3, // packet in dc3
|
||||
input logic lsu_dccm_rden_dc3, // dccm rden
|
||||
input logic addr_in_dccm_dc3, // address in dccm
|
||||
input logic [`RV_DCCM_BITS-1:0] lsu_addr_dc3, // start address
|
||||
input logic [`RV_DCCM_BITS-1:0] end_addr_dc3, // end address
|
||||
input logic [63:0] store_data_dc3, // store data
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_data_any,
|
||||
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_fwddata_hi_dc3, // data forward from the store buffer
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_fwddata_lo_dc3, // data forward from the store buffer
|
||||
input logic [`RV_DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_dc3,// which bytes from the store buffer are on
|
||||
input logic [`RV_DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_dc3,// which bytes from the store buffer are on
|
||||
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] dccm_data_hi_dc3, // raw data from mem
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] dccm_data_lo_dc3, // raw data from mem
|
||||
input logic [`RV_DCCM_ECC_WIDTH-1:0] dccm_data_ecc_hi_dc3, // ecc read out from mem
|
||||
input logic [`RV_DCCM_ECC_WIDTH-1:0] dccm_data_ecc_lo_dc3, // ecc read out from mem
|
||||
|
||||
input logic dec_tlu_core_ecc_disable, // disables the ecc computation and error flagging
|
||||
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] store_ecc_datafn_hi_dc3, // final store data either from stbuf or SEC DCCM readout
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] store_ecc_datafn_lo_dc3,
|
||||
|
||||
output logic [`RV_DCCM_ECC_WIDTH-1:0] stbuf_ecc_any,
|
||||
output logic single_ecc_error_hi_dc3, // sec detected
|
||||
output logic single_ecc_error_lo_dc3, // sec detected on lower dccm bank
|
||||
output logic lsu_single_ecc_error_dc3, // or of the 2
|
||||
output logic lsu_double_ecc_error_dc3, // double error detected
|
||||
|
||||
input logic scan_mode
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
`ifdef RV_DCCM_ENABLE
|
||||
localparam DCCM_ENABLE = 1'b1;
|
||||
`else
|
||||
localparam DCCM_ENABLE = 1'b0;
|
||||
`endif
|
||||
|
||||
logic [DCCM_DATA_WIDTH-1:0] sec_data_hi_dc3;
|
||||
logic [DCCM_DATA_WIDTH-1:0] sec_data_lo_dc3;
|
||||
|
||||
|
||||
logic double_ecc_error_hi_dc3, double_ecc_error_lo_dc3;
|
||||
|
||||
logic ldst_dual_dc3;
|
||||
logic is_ldst_dc3;
|
||||
logic is_ldst_hi_dc3, is_ldst_lo_dc3;
|
||||
logic [7:0] ldst_byteen_dc3;
|
||||
logic [7:0] store_byteen_dc3;
|
||||
logic [7:0] store_byteen_ext_dc3;
|
||||
logic [DCCM_BYTE_WIDTH-1:0] store_byteen_hi_dc3, store_byteen_lo_dc3;
|
||||
|
||||
logic [163:0] store_data_ext_dc3;
|
||||
logic [DCCM_DATA_WIDTH-1:0] store_data_hi_dc3, store_data_lo_dc3;
|
||||
logic [6:0] ecc_out_hi_nc, ecc_out_lo_nc;
|
||||
|
||||
|
||||
assign ldst_dual_dc3 = (lsu_addr_dc3[2] != end_addr_dc3[2]);
|
||||
assign is_ldst_dc3 = lsu_pkt_dc3.valid & (lsu_pkt_dc3.load | lsu_pkt_dc3.store) & addr_in_dccm_dc3 & lsu_dccm_rden_dc3;
|
||||
assign is_ldst_lo_dc3 = is_ldst_dc3 & ~dec_tlu_core_ecc_disable;
|
||||
assign is_ldst_hi_dc3 = is_ldst_dc3 & ldst_dual_dc3 & ~dec_tlu_core_ecc_disable;
|
||||
|
||||
assign ldst_byteen_dc3[7:0] = ({8{lsu_pkt_dc3.by}} & 8'b0000_0001) |
|
||||
({8{lsu_pkt_dc3.half}} & 8'b0000_0011) |
|
||||
({8{lsu_pkt_dc3.word}} & 8'b0000_1111) |
|
||||
({8{lsu_pkt_dc3.dword}} & 8'b1111_1111);
|
||||
assign store_byteen_dc3[7:0] = ldst_byteen_dc3[7:0] & {8{lsu_pkt_dc3.store}};
|
||||
|
||||
assign store_byteen_ext_dc3[7:0] = store_byteen_dc3[7:0] << lsu_addr_dc3[1:0];
|
||||
assign store_byteen_hi_dc3[DCCM_BYTE_WIDTH-1:0] = store_byteen_ext_dc3[7:4];
|
||||
assign store_byteen_lo_dc3[DCCM_BYTE_WIDTH-1:0] = store_byteen_ext_dc3[3:0];
|
||||
|
||||
assign store_data_ext_dc3[63:0] = store_data_dc3[63:0] << {lsu_addr_dc3[1:0], 3'b000};
|
||||
assign store_data_hi_dc3[DCCM_DATA_WIDTH-1:0] = store_data_ext_dc3[63:32];
|
||||
assign store_data_lo_dc3[DCCM_DATA_WIDTH-1:0] = store_data_ext_dc3[31:0];
|
||||
|
||||
|
||||
// Merge store data and sec data
|
||||
// This is used for loads as well for ecc error case. store_byteen will be 0 for loads
|
||||
for (genvar i=0; i<DCCM_BYTE_WIDTH; i++) begin
|
||||
assign store_ecc_datafn_hi_dc3[(8*i)+7:(8*i)] = store_byteen_hi_dc3[i] ? store_data_hi_dc3[(8*i)+7:(8*i)] :
|
||||
(stbuf_fwdbyteen_hi_dc3[i] ? stbuf_fwddata_hi_dc3[(8*i)+7:(8*i)] : sec_data_hi_dc3[(8*i)+7:(8*i)]);
|
||||
assign store_ecc_datafn_lo_dc3[(8*i)+7:(8*i)] = store_byteen_lo_dc3[i] ? store_data_lo_dc3[(8*i)+7:(8*i)] :
|
||||
(stbuf_fwdbyteen_lo_dc3[i] ? stbuf_fwddata_lo_dc3[(8*i)+7:(8*i)] : sec_data_lo_dc3[(8*i)+7:(8*i)]);
|
||||
end
|
||||
|
||||
if (DCCM_ENABLE == 1) begin: Gen_dccm_enable
|
||||
//Detect/Repair for Hi/Lo
|
||||
rvecc_decode lsu_ecc_decode_hi (
|
||||
// Inputs
|
||||
.en(is_ldst_hi_dc3),
|
||||
.sed_ded (1'b0), // 1 : means only detection
|
||||
.din(dccm_data_hi_dc3[DCCM_DATA_WIDTH-1:0]),
|
||||
.ecc_in(dccm_data_ecc_hi_dc3[DCCM_ECC_WIDTH-1:0]),
|
||||
// Outputs
|
||||
.dout(sec_data_hi_dc3[DCCM_DATA_WIDTH-1:0]),
|
||||
.ecc_out (ecc_out_hi_nc[6:0]),
|
||||
.single_ecc_error(single_ecc_error_hi_dc3),
|
||||
.double_ecc_error(double_ecc_error_hi_dc3),
|
||||
.*
|
||||
);
|
||||
|
||||
rvecc_decode lsu_ecc_decode_lo (
|
||||
// Inputs
|
||||
.en(is_ldst_lo_dc3),
|
||||
.sed_ded (1'b0), // 1 : means only detection
|
||||
.din(dccm_data_lo_dc3[DCCM_DATA_WIDTH-1:0] ),
|
||||
.ecc_in(dccm_data_ecc_lo_dc3[DCCM_ECC_WIDTH-1:0]),
|
||||
// Outputs
|
||||
.dout(sec_data_lo_dc3[DCCM_DATA_WIDTH-1:0]),
|
||||
.ecc_out (ecc_out_lo_nc[6:0]),
|
||||
.single_ecc_error(single_ecc_error_lo_dc3),
|
||||
.double_ecc_error(double_ecc_error_lo_dc3),
|
||||
.*
|
||||
);
|
||||
|
||||
// Generate the ECC bits for store buffer drain
|
||||
rvecc_encode lsu_ecc_encode (
|
||||
//Inputs
|
||||
.din(stbuf_data_any[DCCM_DATA_WIDTH-1:0]),
|
||||
//Outputs
|
||||
.ecc_out(stbuf_ecc_any[DCCM_ECC_WIDTH-1:0]),
|
||||
.*
|
||||
);
|
||||
end else begin: Gen_dccm_disable // block: Gen_dccm_enable
|
||||
assign sec_data_hi_dc3[DCCM_DATA_WIDTH-1:0] = '0;
|
||||
assign sec_data_lo_dc3[DCCM_DATA_WIDTH-1:0] = '0;
|
||||
assign single_ecc_error_hi_dc3 = '0;
|
||||
assign double_ecc_error_hi_dc3 = '0;
|
||||
assign single_ecc_error_lo_dc3 = '0;
|
||||
assign double_ecc_error_lo_dc3 = '0;
|
||||
|
||||
assign stbuf_ecc_any[DCCM_ECC_WIDTH-1:0] = '0;
|
||||
end
|
||||
|
||||
assign lsu_single_ecc_error_dc3 = single_ecc_error_hi_dc3 | single_ecc_error_lo_dc3;
|
||||
assign lsu_double_ecc_error_dc3 = double_ecc_error_hi_dc3 | double_ecc_error_lo_dc3;
|
||||
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
|
||||
// ecc_check: assert property (@(posedge clk) ~(single_ecc_error_lo_dc3 | single_ecc_error_hi_dc3));
|
||||
|
||||
`endif
|
||||
|
||||
endmodule // lsu_ecc
|
|
@ -0,0 +1,329 @@
|
|||
// 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: LSU control
|
||||
// Comments:
|
||||
//
|
||||
//
|
||||
// DC1 -> DC2 -> DC3 -> DC4 (Commit)
|
||||
//
|
||||
//********************************************************************************
|
||||
module lsu_lsc_ctl
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic rst_l,
|
||||
// clocks per pipe
|
||||
input logic lsu_c1_dc4_clk,
|
||||
input logic lsu_c1_dc5_clk,
|
||||
input logic lsu_c2_dc4_clk,
|
||||
input logic lsu_c2_dc5_clk,
|
||||
// freez clocks per pipe
|
||||
input logic lsu_freeze_c1_dc1_clk,
|
||||
input logic lsu_freeze_c1_dc2_clk,
|
||||
input logic lsu_freeze_c1_dc3_clk,
|
||||
input logic lsu_freeze_c2_dc1_clk,
|
||||
input logic lsu_freeze_c2_dc2_clk,
|
||||
input logic lsu_freeze_c2_dc3_clk,
|
||||
|
||||
input logic lsu_store_c1_dc1_clk,
|
||||
input logic lsu_store_c1_dc2_clk,
|
||||
input logic lsu_store_c1_dc3_clk,
|
||||
input logic lsu_store_c1_dc4_clk,
|
||||
input logic lsu_store_c1_dc5_clk,
|
||||
|
||||
input logic [31:0] i0_result_e4_eff,
|
||||
input logic [31:0] i1_result_e4_eff,
|
||||
|
||||
input logic [31:0] i0_result_e2,
|
||||
|
||||
input logic ld_bus_error_dc3,
|
||||
input logic [31:0] ld_bus_error_addr_dc3,
|
||||
input logic lsu_single_ecc_error_dc3,
|
||||
input logic lsu_double_ecc_error_dc3,
|
||||
input logic lsu_freeze_dc3,
|
||||
|
||||
input logic lsu_i0_valid_dc3,
|
||||
input logic flush_dc2_up,
|
||||
input logic flush_dc3,
|
||||
input logic flush_dc4,
|
||||
input logic flush_dc5,
|
||||
|
||||
input logic [31:0] exu_lsu_rs1_d, // address
|
||||
input logic [31:0] exu_lsu_rs2_d, // store data
|
||||
|
||||
input lsu_pkt_t lsu_p, // lsu control packet
|
||||
input logic [11:0] dec_lsu_offset_d,
|
||||
|
||||
input logic [31:0] picm_mask_data_dc3,
|
||||
input logic [31:0] lsu_ld_data_dc3,
|
||||
input logic [31:0] lsu_ld_data_corr_dc3,
|
||||
input logic [31:0] bus_read_data_dc3,
|
||||
output logic [31:0] lsu_result_dc3,
|
||||
output logic [31:0] lsu_result_corr_dc4, // This is the ECC corrected data going to RF
|
||||
// lsu address down the pipe
|
||||
output logic [31:0] lsu_addr_dc1,
|
||||
output logic [31:0] lsu_addr_dc2,
|
||||
output logic [31:0] lsu_addr_dc3,
|
||||
output logic [31:0] lsu_addr_dc4,
|
||||
output logic [31:0] lsu_addr_dc5,
|
||||
// lsu address down the pipe - needed to check unaligned
|
||||
output logic [31:0] end_addr_dc1,
|
||||
output logic [31:0] end_addr_dc2,
|
||||
output logic [31:0] end_addr_dc3,
|
||||
output logic [31:0] end_addr_dc4,
|
||||
output logic [31:0] end_addr_dc5,
|
||||
// store data down the pipe
|
||||
output logic [63:0] store_data_dc2,
|
||||
output logic [63:0] store_data_dc3,
|
||||
output logic [31:0] store_data_dc4,
|
||||
output logic [31:0] store_data_dc5,
|
||||
|
||||
input logic [31:0] dec_tlu_mrac_ff,
|
||||
output logic lsu_exc_dc2,
|
||||
output lsu_error_pkt_t lsu_error_pkt_dc3,
|
||||
output logic lsu_freeze_external_ints_dc3,
|
||||
output logic is_sideeffects_dc2,
|
||||
output logic is_sideeffects_dc3,
|
||||
output logic lsu_commit_dc5,
|
||||
// address in dccm/pic/external per pipe stage
|
||||
output logic addr_in_dccm_dc1,
|
||||
output logic addr_in_dccm_dc2,
|
||||
output logic addr_in_dccm_dc3,
|
||||
output logic addr_in_pic_dc1,
|
||||
output logic addr_in_pic_dc2,
|
||||
output logic addr_in_pic_dc3,
|
||||
output logic addr_external_dc2,
|
||||
output logic addr_external_dc3,
|
||||
output logic addr_external_dc4,
|
||||
output logic addr_external_dc5,
|
||||
|
||||
// DMA slave
|
||||
input logic dma_dccm_req,
|
||||
input logic [31:0] dma_mem_addr,
|
||||
input logic [2:0] dma_mem_sz,
|
||||
input logic dma_mem_write,
|
||||
input logic [63:0] dma_mem_wdata,
|
||||
|
||||
// Store buffer related signals
|
||||
output lsu_pkt_t lsu_pkt_dc1,
|
||||
output lsu_pkt_t lsu_pkt_dc2,
|
||||
output lsu_pkt_t lsu_pkt_dc3,
|
||||
output lsu_pkt_t lsu_pkt_dc4,
|
||||
output lsu_pkt_t lsu_pkt_dc5,
|
||||
|
||||
input logic scan_mode
|
||||
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
logic [31:0] full_addr_dc1;
|
||||
logic [31:0] full_end_addr_dc1;
|
||||
logic [31:0] lsu_rs1_d;
|
||||
logic [11:0] lsu_offset_d;
|
||||
logic [31:0] rs1_dc1;
|
||||
logic [11:0] offset_dc1;
|
||||
logic [12:0] end_addr_offset_dc1;
|
||||
logic [31:0] lsu_ld_datafn_dc3;
|
||||
logic [31:0] lsu_ld_datafn_corr_dc3;
|
||||
logic [31:0] lsu_result_corr_dc3;
|
||||
logic [2:0] addr_offset_dc1;
|
||||
|
||||
logic [63:0] dma_mem_wdata_shifted;
|
||||
logic addr_external_dc1;
|
||||
logic access_fault_dc1, misaligned_fault_dc1;
|
||||
logic access_fault_dc2, misaligned_fault_dc2;
|
||||
logic access_fault_dc3, misaligned_fault_dc3;
|
||||
|
||||
logic [63:0] store_data_d;
|
||||
logic [63:0] store_data_dc1;
|
||||
logic [63:0] store_data_pre_dc2;
|
||||
logic [63:0] store_data_pre_dc3;
|
||||
logic [63:0] store_data_dc2_in;
|
||||
|
||||
logic [31:0] rs1_dc1_raw;
|
||||
|
||||
lsu_pkt_t dma_pkt_d;
|
||||
lsu_pkt_t lsu_pkt_dc1_in, lsu_pkt_dc2_in, lsu_pkt_dc3_in, lsu_pkt_dc4_in, lsu_pkt_dc5_in;
|
||||
|
||||
// Premux the rs1/offset for dma
|
||||
assign lsu_rs1_d[31:0] = dma_dccm_req ? dma_mem_addr[31:0] : exu_lsu_rs1_d[31:0];
|
||||
assign lsu_offset_d[11:0] = dec_lsu_offset_d[11:0] & ~{12{dma_dccm_req}};
|
||||
|
||||
rvdff #(32) rs1ff (.*, .din(lsu_rs1_d[31:0]), .dout(rs1_dc1_raw[31:0]), .clk(lsu_freeze_c1_dc1_clk));
|
||||
rvdff #(12) offsetff (.*, .din(lsu_offset_d[11:0]), .dout(offset_dc1[11:0]), .clk(lsu_freeze_c1_dc1_clk));
|
||||
|
||||
assign rs1_dc1[31:0] = (lsu_pkt_dc1.load_ldst_bypass_c1) ? lsu_result_dc3[31:0] : rs1_dc1_raw[31:0];
|
||||
|
||||
|
||||
// generate the ls address
|
||||
// need to refine this is memory is only 128KB
|
||||
rvlsadder lsadder (.rs1(rs1_dc1[31:0]),
|
||||
.offset(offset_dc1[11:0]),
|
||||
.dout(full_addr_dc1[31:0])
|
||||
);
|
||||
|
||||
// Module to generate the memory map of the address
|
||||
lsu_addrcheck addrcheck (
|
||||
.start_addr_dc1(full_addr_dc1[31:0]),
|
||||
.end_addr_dc1(full_end_addr_dc1[31:0]),
|
||||
.*
|
||||
);
|
||||
|
||||
// Calculate start/end address for load/store
|
||||
assign addr_offset_dc1[2:0] = ({3{lsu_pkt_dc1.half}} & 3'b01) | ({3{lsu_pkt_dc1.word}} & 3'b11) | ({3{lsu_pkt_dc1.dword}} & 3'b111);
|
||||
assign end_addr_offset_dc1[12:0] = {offset_dc1[11],offset_dc1[11:0]} + {9'b0,addr_offset_dc1[2:0]};
|
||||
assign full_end_addr_dc1[31:0] = rs1_dc1[31:0] + {{19{end_addr_offset_dc1[12]}},end_addr_offset_dc1[12:0]};
|
||||
assign end_addr_dc1[31:0] = full_end_addr_dc1[31:0];
|
||||
assign lsu_exc_dc2 = access_fault_dc2 | misaligned_fault_dc2;
|
||||
assign lsu_freeze_external_ints_dc3 = lsu_freeze_dc3 & is_sideeffects_dc3;
|
||||
|
||||
// Generate exception packet
|
||||
assign lsu_error_pkt_dc3.exc_valid = (access_fault_dc3 | misaligned_fault_dc3 | ld_bus_error_dc3 | lsu_double_ecc_error_dc3) & lsu_pkt_dc3.valid & ~lsu_pkt_dc3.dma & ~flush_dc3;
|
||||
assign lsu_error_pkt_dc3.single_ecc_error = lsu_single_ecc_error_dc3;
|
||||
assign lsu_error_pkt_dc3.inst_type = lsu_pkt_dc3.store;
|
||||
assign lsu_error_pkt_dc3.dma_valid = lsu_pkt_dc3.dma;
|
||||
assign lsu_error_pkt_dc3.inst_pipe = ~lsu_i0_valid_dc3;
|
||||
assign lsu_error_pkt_dc3.exc_type = ~misaligned_fault_dc3;
|
||||
// assign lsu_error_pkt_dc3.addr[31:0] = (access_fault_dc3 | misaligned_fault_dc3) ? lsu_addr_dc3[31:0] : ld_bus_error_addr_dc3[31:0];
|
||||
assign lsu_error_pkt_dc3.addr[31:0] = lsu_addr_dc3[31:0];
|
||||
|
||||
|
||||
//Create DMA packet
|
||||
assign dma_pkt_d.valid = dma_dccm_req;
|
||||
assign dma_pkt_d.dma = 1'b1;
|
||||
assign dma_pkt_d.unsign = '0;
|
||||
assign dma_pkt_d.store = dma_mem_write;
|
||||
assign dma_pkt_d.load = ~dma_mem_write;
|
||||
assign dma_pkt_d.by = (dma_mem_sz[2:0] == 3'b0);
|
||||
assign dma_pkt_d.half = (dma_mem_sz[2:0] == 3'b1);
|
||||
assign dma_pkt_d.word = (dma_mem_sz[2:0] == 3'b10);
|
||||
assign dma_pkt_d.dword = (dma_mem_sz[2:0] == 3'b11);
|
||||
assign dma_pkt_d.load_ldst_bypass_c1 = '0;
|
||||
assign dma_pkt_d.store_data_bypass_c1 = '0;
|
||||
assign dma_pkt_d.store_data_bypass_c2 = '0;
|
||||
assign dma_pkt_d.store_data_bypass_i0_e2_c2 = '0;
|
||||
assign dma_pkt_d.store_data_bypass_e4_c1 = '0;
|
||||
assign dma_pkt_d.store_data_bypass_e4_c2 = '0;
|
||||
assign dma_pkt_d.store_data_bypass_e4_c3 = '0;
|
||||
|
||||
always_comb begin
|
||||
lsu_pkt_dc1_in = dma_dccm_req ? dma_pkt_d : lsu_p;
|
||||
lsu_pkt_dc2_in = lsu_pkt_dc1;
|
||||
lsu_pkt_dc3_in = lsu_pkt_dc2;
|
||||
lsu_pkt_dc4_in = lsu_pkt_dc3;
|
||||
lsu_pkt_dc5_in = lsu_pkt_dc4;
|
||||
|
||||
lsu_pkt_dc1_in.valid = (lsu_p.valid & ~flush_dc2_up) | dma_dccm_req;
|
||||
lsu_pkt_dc2_in.valid = lsu_pkt_dc1.valid & ~(flush_dc2_up & ~lsu_pkt_dc1.dma);
|
||||
lsu_pkt_dc3_in.valid = lsu_pkt_dc2.valid & ~(flush_dc2_up & ~lsu_pkt_dc2.dma);
|
||||
lsu_pkt_dc4_in.valid = lsu_pkt_dc3.valid & ~(flush_dc3 & ~lsu_pkt_dc3.dma) & ~lsu_freeze_dc3;
|
||||
lsu_pkt_dc5_in.valid = lsu_pkt_dc4.valid & ~(flush_dc4 & ~lsu_pkt_dc4.dma);
|
||||
end
|
||||
|
||||
// C2 clock for valid and C1 for other bits of packet
|
||||
rvdff #(1) lsu_pkt_vlddc1ff (.*, .din(lsu_pkt_dc1_in.valid), .dout(lsu_pkt_dc1.valid), .clk(lsu_freeze_c2_dc1_clk));
|
||||
rvdff #(1) lsu_pkt_vlddc2ff (.*, .din(lsu_pkt_dc2_in.valid), .dout(lsu_pkt_dc2.valid), .clk(lsu_freeze_c2_dc2_clk));
|
||||
rvdff #(1) lsu_pkt_vlddc3ff (.*, .din(lsu_pkt_dc3_in.valid), .dout(lsu_pkt_dc3.valid), .clk(lsu_freeze_c2_dc3_clk));
|
||||
rvdff #(1) lsu_pkt_vlddc4ff (.*, .din(lsu_pkt_dc4_in.valid), .dout(lsu_pkt_dc4.valid), .clk(lsu_c2_dc4_clk));
|
||||
rvdff #(1) lsu_pkt_vlddc5ff (.*, .din(lsu_pkt_dc5_in.valid), .dout(lsu_pkt_dc5.valid), .clk(lsu_c2_dc5_clk));
|
||||
|
||||
rvdff #($bits(lsu_pkt_t)-1) lsu_pkt_dc1ff (.*, .din(lsu_pkt_dc1_in[$bits(lsu_pkt_t)-1:1]), .dout(lsu_pkt_dc1[$bits(lsu_pkt_t)-1:1]), .clk(lsu_freeze_c1_dc1_clk));
|
||||
rvdff #($bits(lsu_pkt_t)-1) lsu_pkt_dc2ff (.*, .din(lsu_pkt_dc2_in[$bits(lsu_pkt_t)-1:1]), .dout(lsu_pkt_dc2[$bits(lsu_pkt_t)-1:1]), .clk(lsu_freeze_c1_dc2_clk));
|
||||
rvdff #($bits(lsu_pkt_t)-1) lsu_pkt_dc3ff (.*, .din(lsu_pkt_dc3_in[$bits(lsu_pkt_t)-1:1]), .dout(lsu_pkt_dc3[$bits(lsu_pkt_t)-1:1]), .clk(lsu_freeze_c1_dc3_clk));
|
||||
rvdff #($bits(lsu_pkt_t)-1) lsu_pkt_dc4ff (.*, .din(lsu_pkt_dc4_in[$bits(lsu_pkt_t)-1:1]), .dout(lsu_pkt_dc4[$bits(lsu_pkt_t)-1:1]), .clk(lsu_c1_dc4_clk));
|
||||
rvdff #($bits(lsu_pkt_t)-1) lsu_pkt_dc5ff (.*, .din(lsu_pkt_dc5_in[$bits(lsu_pkt_t)-1:1]), .dout(lsu_pkt_dc5[$bits(lsu_pkt_t)-1:1]), .clk(lsu_c1_dc5_clk));
|
||||
|
||||
assign lsu_ld_datafn_dc3[31:0] = addr_external_dc3 ? bus_read_data_dc3[31:0] : lsu_ld_data_dc3[31:0];
|
||||
assign lsu_ld_datafn_corr_dc3[31:0] = addr_external_dc3 ? bus_read_data_dc3[31:0] : lsu_ld_data_corr_dc3[31:0];
|
||||
|
||||
// this result must look at prior stores and merge them in
|
||||
assign lsu_result_dc3[31:0] = ({32{ lsu_pkt_dc3.unsign & lsu_pkt_dc3.by }} & {24'b0,lsu_ld_datafn_dc3[7:0]}) |
|
||||
({32{ lsu_pkt_dc3.unsign & lsu_pkt_dc3.half}} & {16'b0,lsu_ld_datafn_dc3[15:0]}) |
|
||||
({32{~lsu_pkt_dc3.unsign & lsu_pkt_dc3.by }} & {{24{ lsu_ld_datafn_dc3[7]}}, lsu_ld_datafn_dc3[7:0]}) |
|
||||
({32{~lsu_pkt_dc3.unsign & lsu_pkt_dc3.half}} & {{16{ lsu_ld_datafn_dc3[15]}},lsu_ld_datafn_dc3[15:0]}) |
|
||||
({32{lsu_pkt_dc3.word}} & lsu_ld_datafn_dc3[31:0]);
|
||||
|
||||
assign lsu_result_corr_dc3[31:0] = ({32{ lsu_pkt_dc3.unsign & lsu_pkt_dc3.by }} & {24'b0,lsu_ld_datafn_corr_dc3[7:0]}) |
|
||||
({32{ lsu_pkt_dc3.unsign & lsu_pkt_dc3.half}} & {16'b0,lsu_ld_datafn_corr_dc3[15:0]}) |
|
||||
({32{~lsu_pkt_dc3.unsign & lsu_pkt_dc3.by }} & {{24{ lsu_ld_datafn_corr_dc3[7]}}, lsu_ld_datafn_corr_dc3[7:0]}) |
|
||||
({32{~lsu_pkt_dc3.unsign & lsu_pkt_dc3.half}} & {{16{ lsu_ld_datafn_corr_dc3[15]}},lsu_ld_datafn_corr_dc3[15:0]}) |
|
||||
({32{lsu_pkt_dc3.word}} & lsu_ld_datafn_corr_dc3[31:0]);
|
||||
|
||||
|
||||
// absence load/store all 0's
|
||||
assign lsu_addr_dc1[31:0] = full_addr_dc1[31:0];
|
||||
|
||||
// Interrupt as a flush source allows the WB to occur
|
||||
assign lsu_commit_dc5 = lsu_pkt_dc5.valid & (lsu_pkt_dc5.store | lsu_pkt_dc5.load) & ~flush_dc5 & ~lsu_pkt_dc5.dma;
|
||||
|
||||
assign dma_mem_wdata_shifted[63:0] = dma_mem_wdata[63:0] >> {dma_mem_addr[2:0], 3'b000}; // Shift the dma data to lower bits to make it consistent to lsu stores
|
||||
assign store_data_d[63:0] = dma_dccm_req ? dma_mem_wdata_shifted[63:0] : {32'b0,exu_lsu_rs2_d[31:0]};
|
||||
|
||||
assign store_data_dc2_in[63:32] = store_data_dc1[63:32];
|
||||
assign store_data_dc2_in[31:0] = (lsu_pkt_dc1.store_data_bypass_c1) ? lsu_result_dc3[31:0] :
|
||||
(lsu_pkt_dc1.store_data_bypass_e4_c1[1]) ? i1_result_e4_eff[31:0] :
|
||||
(lsu_pkt_dc1.store_data_bypass_e4_c1[0]) ? i0_result_e4_eff[31:0] : store_data_dc1[31:0];
|
||||
|
||||
assign store_data_dc2[63:32] = store_data_pre_dc2[63:32];
|
||||
assign store_data_dc2[31:0] = (lsu_pkt_dc2.store_data_bypass_i0_e2_c2) ? i0_result_e2[31:0] :
|
||||
(lsu_pkt_dc2.store_data_bypass_c2) ? lsu_result_dc3[31:0] :
|
||||
(lsu_pkt_dc2.store_data_bypass_e4_c2[1]) ? i1_result_e4_eff[31:0] :
|
||||
(lsu_pkt_dc2.store_data_bypass_e4_c2[0]) ? i0_result_e4_eff[31:0] : store_data_pre_dc2[31:0];
|
||||
|
||||
assign store_data_dc3[63:32] = store_data_pre_dc3[63:32];
|
||||
assign store_data_dc3[31:0] = (picm_mask_data_dc3[31:0] | {32{~addr_in_pic_dc3}}) &
|
||||
((lsu_pkt_dc3.store_data_bypass_e4_c3[1]) ? i1_result_e4_eff[31:0] :
|
||||
(lsu_pkt_dc3.store_data_bypass_e4_c3[0]) ? i0_result_e4_eff[31:0] : store_data_pre_dc3[31:0]);
|
||||
|
||||
rvdff #(32) lsu_result_corr_dc4ff (.*, .din(lsu_result_corr_dc3[31:0]), .dout(lsu_result_corr_dc4[31:0]), .clk(lsu_c1_dc4_clk));
|
||||
|
||||
rvdff #(64) sddc1ff (.*, .din(store_data_d[63:0]), .dout(store_data_dc1[63:0]), .clk(lsu_store_c1_dc1_clk));
|
||||
rvdff #(64) sddc2ff (.*, .din(store_data_dc2_in[63:0]), .dout(store_data_pre_dc2[63:0]), .clk(lsu_store_c1_dc2_clk));
|
||||
rvdffs #(64) sddc3ff (.*, .din(store_data_dc2[63:0]), .dout(store_data_pre_dc3[63:0]), .en(~lsu_freeze_dc3), .clk(lsu_store_c1_dc3_clk));
|
||||
rvdff #(32) sddc4ff (.*, .din(store_data_dc3[31:0]), .dout(store_data_dc4[31:0]), .clk(lsu_store_c1_dc4_clk));
|
||||
rvdff #(32) sddc5ff (.*, .din(store_data_dc4[31:0]), .dout(store_data_dc5[31:0]), .clk(lsu_store_c1_dc5_clk));
|
||||
|
||||
rvdff #(32) sadc2ff (.*, .din(lsu_addr_dc1[31:0]), .dout(lsu_addr_dc2[31:0]), .clk(lsu_freeze_c1_dc2_clk));
|
||||
rvdff #(32) sadc3ff (.*, .din(lsu_addr_dc2[31:0]), .dout(lsu_addr_dc3[31:0]), .clk(lsu_freeze_c1_dc3_clk));
|
||||
rvdff #(32) sadc4ff (.*, .din(lsu_addr_dc3[31:0]), .dout(lsu_addr_dc4[31:0]), .clk(lsu_c1_dc4_clk));
|
||||
rvdff #(32) sadc5ff (.*, .din(lsu_addr_dc4[31:0]), .dout(lsu_addr_dc5[31:0]), .clk(lsu_c1_dc5_clk));
|
||||
|
||||
rvdff #(32) end_addr_dc2ff (.*, .din(end_addr_dc1[31:0]), .dout(end_addr_dc2[31:0]), .clk(lsu_freeze_c1_dc2_clk));
|
||||
rvdff #(32) end_addr_dc3ff (.*, .din(end_addr_dc2[31:0]), .dout(end_addr_dc3[31:0]), .clk(lsu_freeze_c1_dc3_clk));
|
||||
rvdff #(32) end_addr_dc4ff (.*, .din(end_addr_dc3[31:0]), .dout(end_addr_dc4[31:0]), .clk(lsu_c1_dc4_clk));
|
||||
rvdff #(32) end_addr_dc5ff (.*, .din(end_addr_dc4[31:0]), .dout(end_addr_dc5[31:0]), .clk(lsu_c1_dc5_clk));
|
||||
|
||||
rvdff #(1) addr_in_dccm_dc2ff(.din(addr_in_dccm_dc1), .dout(addr_in_dccm_dc2), .clk(lsu_freeze_c1_dc2_clk), .*);
|
||||
rvdff #(1) addr_in_dccm_dc3ff(.din(addr_in_dccm_dc2), .dout(addr_in_dccm_dc3), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
rvdff #(1) addr_in_pic_dc2ff(.din(addr_in_pic_dc1), .dout(addr_in_pic_dc2), .clk(lsu_freeze_c1_dc2_clk), .*);
|
||||
rvdff #(1) addr_in_pic_dc3ff(.din(addr_in_pic_dc2), .dout(addr_in_pic_dc3), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
|
||||
rvdff #(1) addr_external_dc2ff(.din(addr_external_dc1), .dout(addr_external_dc2), .clk(lsu_freeze_c1_dc2_clk), .*);
|
||||
rvdff #(1) addr_external_dc3ff(.din(addr_external_dc2), .dout(addr_external_dc3), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
rvdff #(1) addr_external_dc4ff(.din(addr_external_dc3), .dout(addr_external_dc4), .clk(lsu_c1_dc4_clk), .*);
|
||||
rvdff #(1) addr_external_dc5ff(.din(addr_external_dc4), .dout(addr_external_dc5), .clk(lsu_c1_dc5_clk), .*);
|
||||
|
||||
rvdff #(1) access_fault_dc2ff(.din(access_fault_dc1), .dout(access_fault_dc2), .clk(lsu_freeze_c1_dc2_clk), .*);
|
||||
rvdff #(1) access_fault_dc3ff(.din(access_fault_dc2), .dout(access_fault_dc3), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
rvdff #(1) misaligned_fault_dc2ff(.din(misaligned_fault_dc1), .dout(misaligned_fault_dc2), .clk(lsu_freeze_c1_dc2_clk), .*);
|
||||
rvdff #(1) misaligned_fault_dc3ff(.din(misaligned_fault_dc2), .dout(misaligned_fault_dc3), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,399 @@
|
|||
// 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: Store Buffer
|
||||
// Comments: Dual writes and single drain
|
||||
//
|
||||
//
|
||||
// DC1 -> DC2 -> DC3 -> DC4 (Commit)
|
||||
//
|
||||
// //********************************************************************************
|
||||
|
||||
|
||||
module lsu_stbuf
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk, // core clock
|
||||
input logic rst_l, // reset
|
||||
|
||||
input logic lsu_freeze_c2_dc2_clk, // freeze clock
|
||||
input logic lsu_freeze_c2_dc3_clk, // freeze clock
|
||||
input logic lsu_freeze_c1_dc2_clk, // freeze clock
|
||||
input logic lsu_freeze_c1_dc3_clk, // freeze clock
|
||||
input logic lsu_c1_dc4_clk, // lsu pipe clock
|
||||
input logic lsu_c1_dc5_clk, // lsu pipe clock
|
||||
input logic lsu_c2_dc4_clk, // lsu pipe clock
|
||||
input logic lsu_c2_dc5_clk, // lsu pipe clock
|
||||
input logic lsu_stbuf_c1_clk, // stbuf clock
|
||||
input logic lsu_free_c2_clk, // free clk
|
||||
|
||||
// Store Buffer input
|
||||
input logic load_stbuf_reqvld_dc3, // core instruction goes to stbuf
|
||||
input logic store_stbuf_reqvld_dc3, // core instruction goes to stbuf
|
||||
//input logic ldst_stbuf_reqvld_dc3,
|
||||
input logic addr_in_pic_dc2, // address is in pic
|
||||
input logic addr_in_pic_dc3, // address is in pic
|
||||
input logic addr_in_dccm_dc2, // address is in pic
|
||||
input logic addr_in_dccm_dc3, // address is in pic
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] store_ecc_datafn_hi_dc3, // data to write
|
||||
input logic [`RV_DCCM_DATA_WIDTH-1:0] store_ecc_datafn_lo_dc3, // data to write
|
||||
|
||||
input logic isldst_dc1, // instruction in dc1 is lsu
|
||||
input logic dccm_ldst_dc2, // instruction in dc2 is lsu
|
||||
input logic dccm_ldst_dc3, // instruction in dc3 is lsu
|
||||
|
||||
input logic single_ecc_error_hi_dc3, // single ecc error in hi bank
|
||||
input logic single_ecc_error_lo_dc3, // single ecc error in lo bank
|
||||
input logic lsu_single_ecc_error_dc5, // single_ecc_error in either bank staged to the dc5 - needed for the load repairs
|
||||
input logic lsu_commit_dc5, // lsu commits
|
||||
input logic lsu_freeze_dc3, // lsu freeze
|
||||
input logic flush_prior_dc5, // Flush is due to i0 and ld/st is in i1
|
||||
|
||||
// Store Buffer output
|
||||
output logic stbuf_reqvld_any, // stbuf is draining
|
||||
output logic stbuf_reqvld_flushed_any, // Top entry is flushed
|
||||
output logic stbuf_addr_in_pic_any, // address maps to pic
|
||||
output logic [`RV_DCCM_BYTE_WIDTH-1:0] stbuf_byteen_any, // which bytes are active
|
||||
output logic [`RV_LSU_SB_BITS-1:0] stbuf_addr_any, // address
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_data_any, // stbuf data
|
||||
|
||||
input logic lsu_stbuf_commit_any, // pop the stbuf as it commite
|
||||
output logic lsu_stbuf_full_any, // stbuf is full
|
||||
output logic lsu_stbuf_empty_any, // stbuf is empty
|
||||
output logic lsu_stbuf_nodma_empty_any, // stbuf is empty except dma
|
||||
|
||||
input logic [`RV_LSU_SB_BITS-1:0] lsu_addr_dc1, // lsu address
|
||||
input logic [`RV_LSU_SB_BITS-1:0] lsu_addr_dc2,
|
||||
input logic [`RV_LSU_SB_BITS-1:0] lsu_addr_dc3,
|
||||
|
||||
input logic [`RV_LSU_SB_BITS-1:0] end_addr_dc1, // lsu end addrress - needed to check unaligned
|
||||
input logic [`RV_LSU_SB_BITS-1:0] end_addr_dc2,
|
||||
input logic [`RV_LSU_SB_BITS-1:0] end_addr_dc3,
|
||||
|
||||
// Forwarding signals
|
||||
input logic lsu_cmpen_dc2, // needed for forwarding stbuf - load
|
||||
input lsu_pkt_t lsu_pkt_dc2,
|
||||
input lsu_pkt_t lsu_pkt_dc3,
|
||||
input lsu_pkt_t lsu_pkt_dc5,
|
||||
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_fwddata_hi_dc3, // stbuf data
|
||||
output logic [`RV_DCCM_DATA_WIDTH-1:0] stbuf_fwddata_lo_dc3,
|
||||
output logic [`RV_DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_dc3,
|
||||
output logic [`RV_DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_dc3,
|
||||
|
||||
input logic scan_mode
|
||||
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
localparam DEPTH = LSU_STBUF_DEPTH;
|
||||
localparam DATA_WIDTH = DCCM_DATA_WIDTH;
|
||||
localparam BYTE_WIDTH = DCCM_BYTE_WIDTH;
|
||||
localparam DEPTH_LOG2 = $clog2(DEPTH);
|
||||
|
||||
logic [DEPTH-1:0] stbuf_data_vld;
|
||||
logic [DEPTH-1:0] stbuf_drain_vld;
|
||||
logic [DEPTH-1:0] stbuf_flush_vld;
|
||||
logic [DEPTH-1:0] stbuf_addr_in_pic;
|
||||
logic [DEPTH-1:0] stbuf_dma;
|
||||
logic [DEPTH-1:0][LSU_SB_BITS-1:0] stbuf_addr;
|
||||
logic [DEPTH-1:0][BYTE_WIDTH-1:0] stbuf_byteen;
|
||||
logic [DEPTH-1:0][DATA_WIDTH-1:0] stbuf_data;
|
||||
|
||||
logic [DEPTH-1:0] sel_lo;
|
||||
logic [DEPTH-1:0] stbuf_wr_en;
|
||||
logic [DEPTH-1:0] stbuf_data_en;
|
||||
logic [DEPTH-1:0] stbuf_drain_or_flush_en;
|
||||
logic [DEPTH-1:0] stbuf_flush_en;
|
||||
logic [DEPTH-1:0] stbuf_drain_en;
|
||||
logic [DEPTH-1:0] stbuf_reset;
|
||||
logic [DEPTH-1:0][LSU_SB_BITS-1:0] stbuf_addrin;
|
||||
logic [DEPTH-1:0][DATA_WIDTH-1:0] stbuf_datain;
|
||||
logic [DEPTH-1:0][BYTE_WIDTH-1:0] stbuf_byteenin;
|
||||
|
||||
logic [7:0] ldst_byteen_dc3;
|
||||
logic [7:0] store_byteen_ext_dc3;
|
||||
logic [BYTE_WIDTH-1:0] store_byteen_hi_dc3;
|
||||
logic [BYTE_WIDTH-1:0] store_byteen_lo_dc3;
|
||||
|
||||
logic ldst_stbuf_reqvld_dc3;
|
||||
logic dual_ecc_error_dc3;
|
||||
logic dual_stbuf_write_dc3;
|
||||
|
||||
logic WrPtrEn, RdPtrEn;
|
||||
logic [DEPTH_LOG2-1:0] WrPtr, RdPtr;
|
||||
logic [DEPTH_LOG2-1:0] NxtWrPtr, NxtRdPtr;
|
||||
logic [DEPTH_LOG2-1:0] WrPtrPlus1, WrPtrPlus1_dc5, WrPtrPlus2, RdPtrPlus1;
|
||||
logic [DEPTH_LOG2-1:0] WrPtr_dc3, WrPtr_dc4, WrPtr_dc5;
|
||||
logic ldst_dual_dc1, ldst_dual_dc2, ldst_dual_dc3, ldst_dual_dc4, ldst_dual_dc5;
|
||||
logic ldst_stbuf_reqvld_dc4, ldst_stbuf_reqvld_dc5;
|
||||
logic dual_stbuf_write_dc4, dual_stbuf_write_dc5;
|
||||
|
||||
logic [3:0] stbuf_numvld_any, stbuf_specvld_any;
|
||||
logic [1:0] stbuf_specvld_dc1, stbuf_specvld_dc2, stbuf_specvld_dc3;
|
||||
logic stbuf_oneavl_any, stbuf_twoavl_any;
|
||||
|
||||
logic cmpen_hi_dc2, cmpen_lo_dc2, jit_in_same_region;
|
||||
|
||||
logic [LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] cmpaddr_hi_dc2, cmpaddr_lo_dc2;
|
||||
|
||||
logic stbuf_ldmatch_hi_hi, stbuf_ldmatch_hi_lo;
|
||||
logic stbuf_ldmatch_lo_hi, stbuf_ldmatch_lo_lo;
|
||||
logic [BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_hi, stbuf_fwdbyteen_hi_lo;
|
||||
logic [BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_hi, stbuf_fwdbyteen_lo_lo;
|
||||
logic [DATA_WIDTH-1:0] stbuf_fwddata_hi_hi, stbuf_fwddata_hi_lo;
|
||||
logic [DATA_WIDTH-1:0] stbuf_fwddata_lo_hi, stbuf_fwddata_lo_lo;
|
||||
|
||||
logic [DEPTH-1:0] stbuf_ldmatch_hi, stbuf_ldmatch_lo;
|
||||
logic [DEPTH-1:0][BYTE_WIDTH-1:0] stbuf_fwdbyteenvec_hi, stbuf_fwdbyteenvec_lo;
|
||||
logic [DEPTH-1:0][DATA_WIDTH-1:0] stbuf_fwddatavec_hi, stbuf_fwddatavec_lo;
|
||||
logic [DATA_WIDTH-1:0] stbuf_fwddata_hi_dc2, stbuf_fwddata_lo_dc2;
|
||||
logic [DATA_WIDTH-1:0] stbuf_fwddata_hi_fn_dc2, stbuf_fwddata_lo_fn_dc2;
|
||||
logic [BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_dc2, stbuf_fwdbyteen_lo_dc2;
|
||||
logic [BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_fn_dc2, stbuf_fwdbyteen_lo_fn_dc2;
|
||||
logic stbuf_load_repair_dc5;
|
||||
//----------------------------------------
|
||||
// Logic starts here
|
||||
//----------------------------------------
|
||||
// Create high/low byte enables
|
||||
assign ldst_byteen_dc3[7:0] = ({8{lsu_pkt_dc3.by}} & 8'b0000_0001) |
|
||||
({8{lsu_pkt_dc3.half}} & 8'b0000_0011) |
|
||||
({8{lsu_pkt_dc3.word}} & 8'b0000_1111) |
|
||||
({8{lsu_pkt_dc3.dword}} & 8'b1111_1111);
|
||||
assign store_byteen_ext_dc3[7:0] = ldst_byteen_dc3[7:0] << lsu_addr_dc3[1:0];
|
||||
assign store_byteen_hi_dc3[BYTE_WIDTH-1:0] = store_byteen_ext_dc3[7:4];
|
||||
assign store_byteen_lo_dc3[BYTE_WIDTH-1:0] = store_byteen_ext_dc3[3:0];
|
||||
|
||||
assign RdPtrPlus1[DEPTH_LOG2-1:0] = RdPtr[DEPTH_LOG2-1:0] + 1'b1;
|
||||
assign WrPtrPlus1[DEPTH_LOG2-1:0] = WrPtr[DEPTH_LOG2-1:0] + 1'b1;
|
||||
assign WrPtrPlus2[DEPTH_LOG2-1:0] = WrPtr[DEPTH_LOG2-1:0] + 2'b10;
|
||||
assign WrPtrPlus1_dc5[DEPTH_LOG2-1:0] = WrPtr_dc5[DEPTH_LOG2-1:0] + 1'b1;
|
||||
|
||||
// ecc error on both hi/lo
|
||||
assign ldst_dual_dc1 = (lsu_addr_dc1[2] != end_addr_dc1[2]);
|
||||
assign dual_ecc_error_dc3 = (single_ecc_error_hi_dc3 & single_ecc_error_lo_dc3);
|
||||
assign dual_stbuf_write_dc3 = ldst_dual_dc3 & (store_stbuf_reqvld_dc3 | dual_ecc_error_dc3);
|
||||
assign ldst_stbuf_reqvld_dc3 = store_stbuf_reqvld_dc3 |
|
||||
(load_stbuf_reqvld_dc3 & (dual_ecc_error_dc3 ? stbuf_twoavl_any : stbuf_oneavl_any)); // Don't correct ecc if not enough entries. Load will be flushed and come back again
|
||||
assign stbuf_load_repair_dc5 = lsu_single_ecc_error_dc5 & (lsu_pkt_dc5.valid & lsu_pkt_dc5.load & ~flush_prior_dc5);
|
||||
|
||||
// Store Buffer instantiation
|
||||
for (genvar i=0; i<DEPTH; i++) begin: GenStBuf
|
||||
assign stbuf_wr_en[i] = ldst_stbuf_reqvld_dc3 & ((i == WrPtr[DEPTH_LOG2-1:0]) |
|
||||
(i == WrPtrPlus1[DEPTH_LOG2-1:0] & dual_stbuf_write_dc3));
|
||||
assign stbuf_data_en[i] = stbuf_wr_en[i];
|
||||
assign stbuf_drain_or_flush_en[i] = ldst_stbuf_reqvld_dc5 & ~lsu_pkt_dc5.dma & ((i == WrPtr_dc5[DEPTH_LOG2-1:0]) |
|
||||
(i == WrPtrPlus1_dc5[DEPTH_LOG2-1:0] & dual_stbuf_write_dc5));
|
||||
assign stbuf_drain_en[i] = (stbuf_drain_or_flush_en[i] & (lsu_commit_dc5 | stbuf_load_repair_dc5)) | (stbuf_wr_en[i] & lsu_pkt_dc3.dma);
|
||||
assign stbuf_flush_en[i] = stbuf_drain_or_flush_en[i] & ~(lsu_commit_dc5 | stbuf_load_repair_dc5);
|
||||
assign stbuf_reset[i] = (lsu_stbuf_commit_any | stbuf_reqvld_flushed_any) & (i == RdPtr[DEPTH_LOG2-1:0]);
|
||||
|
||||
// Mux select for start/end address
|
||||
assign sel_lo[i] = (~ldst_dual_dc3 | (store_stbuf_reqvld_dc3 | single_ecc_error_lo_dc3)) & (i == WrPtr[DEPTH_LOG2-1:0]);
|
||||
assign stbuf_addrin[i][LSU_SB_BITS-1:0] = sel_lo[i] ? lsu_addr_dc3[LSU_SB_BITS-1:0] : end_addr_dc3[LSU_SB_BITS-1:0];
|
||||
assign stbuf_byteenin[i][BYTE_WIDTH-1:0] = sel_lo[i] ? store_byteen_lo_dc3[BYTE_WIDTH-1:0] : store_byteen_hi_dc3[BYTE_WIDTH-1:0];
|
||||
assign stbuf_datain[i][DATA_WIDTH-1:0] = sel_lo[i] ? store_ecc_datafn_lo_dc3[DATA_WIDTH-1:0] : store_ecc_datafn_hi_dc3[DATA_WIDTH-1:0];
|
||||
|
||||
rvdffsc #(.WIDTH(1)) stbuf_data_vldff (.din(1'b1), .dout(stbuf_data_vld[i]), .en(stbuf_wr_en[i]), .clear(stbuf_reset[i]), .clk(lsu_stbuf_c1_clk), .*);
|
||||
rvdffsc #(.WIDTH(1)) stbuf_drain_vldff (.din(1'b1), .dout(stbuf_drain_vld[i]), .en(stbuf_drain_en[i]), .clear(stbuf_reset[i]), .clk(lsu_free_c2_clk), .*);
|
||||
rvdffsc #(.WIDTH(1)) stbuf_flush_vldff (.din(1'b1), .dout(stbuf_flush_vld[i]), .en(stbuf_flush_en[i]), .clear(stbuf_reset[i]), .clk(lsu_free_c2_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) stbuf_dma_picff (.din(lsu_pkt_dc3.dma), .dout(stbuf_dma[i]), .en(stbuf_wr_en[i]), .clk(lsu_stbuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(1)) stbuf_addr_in_picff (.din(addr_in_pic_dc3), .dout(stbuf_addr_in_pic[i]), .en(stbuf_wr_en[i]), .clk(lsu_stbuf_c1_clk), .*);
|
||||
rvdffe #(.WIDTH(LSU_SB_BITS)) stbuf_addrff (.din(stbuf_addrin[i][LSU_SB_BITS-1:0]), .dout(stbuf_addr[i][LSU_SB_BITS-1:0]), .en(stbuf_wr_en[i]), .*);
|
||||
rvdffs #(.WIDTH(BYTE_WIDTH)) stbuf_byteenff (.din(stbuf_byteenin[i][BYTE_WIDTH-1:0]), .dout(stbuf_byteen[i][BYTE_WIDTH-1:0]), .en(stbuf_wr_en[i]), .clk(lsu_stbuf_c1_clk), .*);
|
||||
rvdffe #(.WIDTH(DATA_WIDTH)) stbuf_dataff (.din(stbuf_datain[i][DATA_WIDTH-1:0]), .dout(stbuf_data[i][DATA_WIDTH-1:0]), .en(stbuf_data_en[i]), .*);
|
||||
|
||||
end
|
||||
|
||||
// WrPtr flops to dc5
|
||||
assign WrPtr_dc3[DEPTH_LOG2-1:0] = WrPtr[DEPTH_LOG2-1:0];
|
||||
rvdff #(.WIDTH(DEPTH_LOG2)) WrPtr_dc4ff (.din(WrPtr_dc3[DEPTH_LOG2-1:0]), .dout(WrPtr_dc4[DEPTH_LOG2-1:0]), .clk(lsu_c1_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(DEPTH_LOG2)) WrPtr_dc5ff (.din(WrPtr_dc4[DEPTH_LOG2-1:0]), .dout(WrPtr_dc5[DEPTH_LOG2-1:0]), .clk(lsu_c1_dc5_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) ldst_dual_dc2ff (.din(ldst_dual_dc1), .dout(ldst_dual_dc2), .clk(lsu_freeze_c1_dc2_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ldst_dual_dc3ff (.din(ldst_dual_dc2), .dout(ldst_dual_dc3), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ldst_dual_dc4ff (.din(ldst_dual_dc3), .dout(ldst_dual_dc4), .clk(lsu_c1_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ldst_dual_dc5ff (.din(ldst_dual_dc4), .dout(ldst_dual_dc5), .clk(lsu_c1_dc5_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(1)) dual_stbuf_write_dc4ff (.din(dual_stbuf_write_dc3), .dout(dual_stbuf_write_dc4), .clk(lsu_c1_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(1)) dual_stbuf_write_dc5ff (.din(dual_stbuf_write_dc4), .dout(dual_stbuf_write_dc5), .clk(lsu_c1_dc5_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ldst_reqvld_dc4ff (.din(ldst_stbuf_reqvld_dc3), .dout(ldst_stbuf_reqvld_dc4), .clk(lsu_c2_dc4_clk), .*);
|
||||
rvdff #(.WIDTH(1)) ldst_reqvld_dc5ff (.din(ldst_stbuf_reqvld_dc4), .dout(ldst_stbuf_reqvld_dc5), .clk(lsu_c2_dc5_clk), .*);
|
||||
|
||||
// Store Buffer drain logic
|
||||
assign stbuf_reqvld_flushed_any = stbuf_flush_vld[RdPtr];
|
||||
assign stbuf_reqvld_any = stbuf_drain_vld[RdPtr];
|
||||
assign stbuf_addr_in_pic_any = stbuf_addr_in_pic[RdPtr];
|
||||
assign stbuf_addr_any[LSU_SB_BITS-1:0] = stbuf_addr[RdPtr][LSU_SB_BITS-1:0];
|
||||
assign stbuf_byteen_any[BYTE_WIDTH-1:0] = stbuf_byteen[RdPtr][BYTE_WIDTH-1:0]; // Not needed as we always write all the bytes
|
||||
assign stbuf_data_any[DATA_WIDTH-1:0] = stbuf_data[RdPtr][DATA_WIDTH-1:0];
|
||||
|
||||
// Update the RdPtr/WrPtr logic
|
||||
// Need to revert the WrPtr for flush cases. Also revert the pipe WrPtrs
|
||||
|
||||
assign WrPtrEn = ldst_stbuf_reqvld_dc3;
|
||||
assign NxtWrPtr[DEPTH_LOG2-1:0] = (ldst_stbuf_reqvld_dc3 & dual_stbuf_write_dc3) ? WrPtrPlus2[DEPTH_LOG2-1:0] : WrPtrPlus1[DEPTH_LOG2-1:0];
|
||||
assign RdPtrEn = lsu_stbuf_commit_any | stbuf_reqvld_flushed_any;
|
||||
assign NxtRdPtr[DEPTH_LOG2-1:0] = RdPtrPlus1[DEPTH_LOG2-1:0];
|
||||
|
||||
|
||||
always_comb begin
|
||||
//stbuf_numvld_any[3:0] = {3'b0,isldst_dc3} << ldst_dual_dc3; // Use isldst_dc3 for timing reason
|
||||
stbuf_numvld_any[3:0] = '0;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
stbuf_numvld_any[3:0] += {3'b0, stbuf_data_vld[i]};
|
||||
end
|
||||
end
|
||||
|
||||
assign stbuf_specvld_dc1[1:0] = {1'b0,isldst_dc1} << (isldst_dc1 & ldst_dual_dc1); // Gate dual with isldst to avoid X propagation
|
||||
assign stbuf_specvld_dc2[1:0] = {1'b0,dccm_ldst_dc2} << (dccm_ldst_dc2 & ldst_dual_dc2);
|
||||
assign stbuf_specvld_dc3[1:0] = {1'b0,dccm_ldst_dc3} << (dccm_ldst_dc3 & ldst_dual_dc3);
|
||||
assign stbuf_specvld_any[3:0] = stbuf_numvld_any[3:0] + {2'b0, stbuf_specvld_dc1[1:0]} + {2'b0, stbuf_specvld_dc2[1:0]} + {2'b0, stbuf_specvld_dc3[1:0]};
|
||||
|
||||
assign lsu_stbuf_full_any = (stbuf_specvld_any[3:0] > (DEPTH - 2));
|
||||
assign lsu_stbuf_empty_any = (stbuf_numvld_any[3:0] == 4'b0);
|
||||
assign lsu_stbuf_nodma_empty_any = ~(|(stbuf_data_vld[DEPTH-1:0] & ~stbuf_dma[DEPTH-1:0]));
|
||||
|
||||
assign stbuf_oneavl_any = (stbuf_numvld_any[3:0] < DEPTH);
|
||||
assign stbuf_twoavl_any = (stbuf_numvld_any[3:0] < (DEPTH - 1));
|
||||
|
||||
// Load forwarding logic
|
||||
assign cmpen_hi_dc2 = lsu_cmpen_dc2 & ldst_dual_dc2;
|
||||
assign cmpaddr_hi_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] = end_addr_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)];
|
||||
|
||||
assign cmpen_lo_dc2 = lsu_cmpen_dc2;
|
||||
assign cmpaddr_lo_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] = lsu_addr_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)];
|
||||
assign jit_in_same_region = (addr_in_pic_dc2 & addr_in_pic_dc3) | (addr_in_dccm_dc2 & addr_in_dccm_dc3);
|
||||
|
||||
// JIT forwarding
|
||||
assign stbuf_ldmatch_hi_hi = (end_addr_dc3[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == cmpaddr_hi_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) & ~(cmpen_hi_dc2 & lsu_pkt_dc2.dma & ~lsu_pkt_dc3.dma) & jit_in_same_region;
|
||||
assign stbuf_ldmatch_hi_lo = (lsu_addr_dc3[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == cmpaddr_hi_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) & ~(cmpen_hi_dc2 & lsu_pkt_dc2.dma & ~lsu_pkt_dc3.dma) & jit_in_same_region;
|
||||
assign stbuf_ldmatch_lo_hi = (end_addr_dc3[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == cmpaddr_lo_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) & ~(cmpen_lo_dc2 & lsu_pkt_dc2.dma & ~lsu_pkt_dc3.dma) & jit_in_same_region;
|
||||
assign stbuf_ldmatch_lo_lo = (lsu_addr_dc3[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == cmpaddr_lo_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) & ~(cmpen_lo_dc2 & lsu_pkt_dc2.dma & ~lsu_pkt_dc3.dma) & jit_in_same_region;
|
||||
|
||||
for (genvar i=0; i<BYTE_WIDTH; i++) begin
|
||||
assign stbuf_fwdbyteen_hi_hi[i] = stbuf_ldmatch_hi_hi & store_byteen_hi_dc3[i] & ldst_stbuf_reqvld_dc3 & dual_stbuf_write_dc3;
|
||||
assign stbuf_fwdbyteen_hi_lo[i] = stbuf_ldmatch_hi_lo & store_byteen_lo_dc3[i] & ldst_stbuf_reqvld_dc3;
|
||||
assign stbuf_fwdbyteen_lo_hi[i] = stbuf_ldmatch_lo_hi & store_byteen_hi_dc3[i] & ldst_stbuf_reqvld_dc3 & dual_stbuf_write_dc3;
|
||||
assign stbuf_fwdbyteen_lo_lo[i] = stbuf_ldmatch_lo_lo & store_byteen_lo_dc3[i] & ldst_stbuf_reqvld_dc3;
|
||||
|
||||
assign stbuf_fwddata_hi_hi[(8*i)+7:(8*i)] = {8{stbuf_fwdbyteen_hi_hi[i]}} & store_ecc_datafn_hi_dc3[(8*i)+7:(8*i)];
|
||||
assign stbuf_fwddata_hi_lo[(8*i)+7:(8*i)] = {8{stbuf_fwdbyteen_hi_lo[i]}} & store_ecc_datafn_lo_dc3[(8*i)+7:(8*i)];
|
||||
assign stbuf_fwddata_lo_hi[(8*i)+7:(8*i)] = {8{stbuf_fwdbyteen_lo_hi[i]}} & store_ecc_datafn_hi_dc3[(8*i)+7:(8*i)];
|
||||
assign stbuf_fwddata_lo_lo[(8*i)+7:(8*i)] = {8{stbuf_fwdbyteen_lo_lo[i]}} & store_ecc_datafn_lo_dc3[(8*i)+7:(8*i)];
|
||||
end
|
||||
|
||||
|
||||
always_comb begin: GenLdFwd
|
||||
stbuf_fwdbyteen_hi_dc2[BYTE_WIDTH-1:0] = '0;
|
||||
stbuf_fwdbyteen_lo_dc2[BYTE_WIDTH-1:0] = '0;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
stbuf_ldmatch_hi[i] = (stbuf_addr[i][LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == cmpaddr_hi_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) &
|
||||
(stbuf_drain_vld[i] | ~lsu_pkt_dc2.dma) & ~stbuf_flush_vld[i] & ((stbuf_addr_in_pic[i] & addr_in_pic_dc2) | (~stbuf_addr_in_pic[i] & addr_in_dccm_dc2));
|
||||
stbuf_ldmatch_lo[i] = (stbuf_addr[i][LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == cmpaddr_lo_dc2[LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) &
|
||||
(stbuf_drain_vld[i] | ~lsu_pkt_dc2.dma) & ~stbuf_flush_vld[i] & ((stbuf_addr_in_pic[i] & addr_in_pic_dc2) | (~stbuf_addr_in_pic[i] & addr_in_dccm_dc2));
|
||||
|
||||
for (int j=0; j<BYTE_WIDTH; j++) begin
|
||||
stbuf_fwdbyteenvec_hi[i][j] = stbuf_ldmatch_hi[i] & stbuf_byteen[i][j] & stbuf_data_vld[i];
|
||||
stbuf_fwdbyteen_hi_dc2[j] |= stbuf_fwdbyteenvec_hi[i][j];
|
||||
|
||||
stbuf_fwdbyteenvec_lo[i][j] = stbuf_ldmatch_lo[i] & stbuf_byteen[i][j] & stbuf_data_vld[i];
|
||||
stbuf_fwdbyteen_lo_dc2[j] |= stbuf_fwdbyteenvec_lo[i][j];
|
||||
end
|
||||
end
|
||||
end // block: GenLdFwd
|
||||
|
||||
for (genvar i=0; i<DEPTH; i++) begin
|
||||
for (genvar j=0; j<BYTE_WIDTH; j++) begin
|
||||
assign stbuf_fwddatavec_hi[i][(8*j)+7:(8*j)] = {8{stbuf_fwdbyteenvec_hi[i][j]}} & stbuf_data[i][(8*j)+7:(8*j)];
|
||||
assign stbuf_fwddatavec_lo[i][(8*j)+7:(8*j)] = {8{stbuf_fwdbyteenvec_lo[i][j]}} & stbuf_data[i][(8*j)+7:(8*j)];
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
stbuf_fwddata_hi_dc2[DATA_WIDTH-1:0] = '0;
|
||||
stbuf_fwddata_lo_dc2[DATA_WIDTH-1:0] = '0;
|
||||
for (int i=0; i<DEPTH; i++) begin
|
||||
// Byte0
|
||||
if (stbuf_fwdbyteenvec_hi[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][0]) begin
|
||||
stbuf_fwddata_hi_dc2[7:0] = stbuf_fwddatavec_hi[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][7:0];
|
||||
end
|
||||
if (stbuf_fwdbyteenvec_lo[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][0]) begin
|
||||
stbuf_fwddata_lo_dc2[7:0] = stbuf_fwddatavec_lo[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][7:0];
|
||||
end
|
||||
|
||||
// Byte1
|
||||
if (stbuf_fwdbyteenvec_hi[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][1]) begin
|
||||
stbuf_fwddata_hi_dc2[15:8] = stbuf_fwddatavec_hi[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][15:8];
|
||||
end
|
||||
if (stbuf_fwdbyteenvec_lo[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][1]) begin
|
||||
stbuf_fwddata_lo_dc2[15:8] = stbuf_fwddatavec_lo[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][15:8];
|
||||
end
|
||||
|
||||
// Byte2
|
||||
if (stbuf_fwdbyteenvec_hi[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][2]) begin
|
||||
stbuf_fwddata_hi_dc2[23:16] = stbuf_fwddatavec_hi[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][23:16];
|
||||
end
|
||||
if (stbuf_fwdbyteenvec_lo[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][2]) begin
|
||||
stbuf_fwddata_lo_dc2[23:16] = stbuf_fwddatavec_lo[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][23:16];
|
||||
end
|
||||
|
||||
// Byte3
|
||||
if (stbuf_fwdbyteenvec_hi[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][3]) begin
|
||||
stbuf_fwddata_hi_dc2[31:24] = stbuf_fwddatavec_hi[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][31:24];
|
||||
end
|
||||
if (stbuf_fwdbyteenvec_lo[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][3]) begin
|
||||
stbuf_fwddata_lo_dc2[31:24] = stbuf_fwddatavec_lo[DEPTH_LOG2'(WrPtr[DEPTH_LOG2-1:0] + DEPTH_LOG2'(i))][31:24];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for (genvar i=0; i<BYTE_WIDTH; i++) begin
|
||||
assign stbuf_fwdbyteen_hi_fn_dc2[i] = stbuf_fwdbyteen_hi_hi[i] | stbuf_fwdbyteen_hi_lo[i] | stbuf_fwdbyteen_hi_dc2[i];
|
||||
assign stbuf_fwdbyteen_lo_fn_dc2[i] = stbuf_fwdbyteen_lo_hi[i] | stbuf_fwdbyteen_lo_lo[i] | stbuf_fwdbyteen_lo_dc2[i];
|
||||
|
||||
assign stbuf_fwddata_hi_fn_dc2[(8*i)+7:(8*i)] = (stbuf_fwdbyteen_hi_hi[i] | stbuf_fwdbyteen_hi_lo[i]) ?
|
||||
(stbuf_fwddata_hi_hi[(8*i)+7:(8*i)] | stbuf_fwddata_hi_lo[(8*i)+7:(8*i)]) :
|
||||
stbuf_fwddata_hi_dc2[(8*i)+7:(8*i)];
|
||||
assign stbuf_fwddata_lo_fn_dc2[(8*i)+7:(8*i)] = (stbuf_fwdbyteen_lo_hi[i] | stbuf_fwdbyteen_lo_lo[i]) ?
|
||||
(stbuf_fwddata_lo_hi[(8*i)+7:(8*i)] | stbuf_fwddata_lo_lo[(8*i)+7:(8*i)]) :
|
||||
stbuf_fwddata_lo_dc2[(8*i)+7:(8*i)];
|
||||
end
|
||||
|
||||
// Flops
|
||||
rvdffs #(.WIDTH(DEPTH_LOG2)) WrPtrff (.din(NxtWrPtr[DEPTH_LOG2-1:0]), .dout(WrPtr[DEPTH_LOG2-1:0]), .en(WrPtrEn), .clk(lsu_stbuf_c1_clk), .*);
|
||||
rvdffs #(.WIDTH(DEPTH_LOG2)) RdPtrff (.din(NxtRdPtr[DEPTH_LOG2-1:0]), .dout(RdPtr[DEPTH_LOG2-1:0]), .en(RdPtrEn), .clk(lsu_stbuf_c1_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(BYTE_WIDTH)) stbuf_fwdbyteen_hi_dc3ff (.din(stbuf_fwdbyteen_hi_fn_dc2[BYTE_WIDTH-1:0]), .dout(stbuf_fwdbyteen_hi_dc3[BYTE_WIDTH-1:0]), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
rvdff #(.WIDTH(BYTE_WIDTH)) stbuf_fwdbyteen_lo_dc3ff (.din(stbuf_fwdbyteen_lo_fn_dc2[BYTE_WIDTH-1:0]), .dout(stbuf_fwdbyteen_lo_dc3[BYTE_WIDTH-1:0]), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
|
||||
rvdff #(.WIDTH(DATA_WIDTH)) stbuf_fwddata_hi_dc3ff (.din(stbuf_fwddata_hi_fn_dc2[DATA_WIDTH-1:0]), .dout(stbuf_fwddata_hi_dc3[DATA_WIDTH-1:0]), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
rvdff #(.WIDTH(DATA_WIDTH)) stbuf_fwddata_lo_dc3ff (.din(stbuf_fwddata_lo_fn_dc2[DATA_WIDTH-1:0]), .dout(stbuf_fwddata_lo_dc3[DATA_WIDTH-1:0]), .clk(lsu_freeze_c1_dc3_clk), .*);
|
||||
|
||||
`ifdef ASSERT_ON
|
||||
|
||||
assert_drainorflushvld_notvld: assert #0 (~(|((stbuf_drain_vld[DEPTH-1:0] | stbuf_flush_vld[DEPTH-1:0]) & ~stbuf_data_vld[DEPTH-1:0])));
|
||||
assert_drainAndflushvld: assert #0 (~(|(stbuf_drain_vld[DEPTH-1:0] & stbuf_flush_vld[DEPTH-1:0])));
|
||||
assert_stbufempty: assert #0 (~lsu_stbuf_empty_any | lsu_stbuf_nodma_empty_any);
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// 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: LSU Trigger logic
|
||||
// Comments:
|
||||
//
|
||||
//********************************************************************************
|
||||
module lsu_trigger
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk, // clock
|
||||
input logic lsu_free_c2_clk, // clock
|
||||
input logic rst_l, // reset
|
||||
|
||||
input trigger_pkt_t [3:0] trigger_pkt_any, // trigger packet from dec
|
||||
input lsu_pkt_t lsu_pkt_dc3, // lsu packet
|
||||
input logic [31:0] lsu_addr_dc3, // address
|
||||
input logic [31:0] lsu_result_dc3, // load data
|
||||
input logic [31:0] store_data_dc3, // store data
|
||||
|
||||
output logic [3:0] lsu_trigger_match_dc3 // match result
|
||||
);
|
||||
|
||||
logic [3:0][31:0] lsu_match_data;
|
||||
logic [3:0] lsu_trigger_data_match;
|
||||
logic [31:0] store_data_trigger_dc3;
|
||||
|
||||
assign store_data_trigger_dc3[31:0] = { ({16{lsu_pkt_dc3.word}} & store_data_dc3[31:16]) , ({8{(lsu_pkt_dc3.half | lsu_pkt_dc3.word)}} & store_data_dc3[15:8]), store_data_dc3[7:0]};
|
||||
|
||||
|
||||
for (genvar i=0; i<4; i++) begin
|
||||
assign lsu_match_data[i][31:0] = ({32{~trigger_pkt_any[i].select}} & lsu_addr_dc3[31:0]) |
|
||||
({32{trigger_pkt_any[i].select & trigger_pkt_any[i].store}} & store_data_trigger_dc3[31:0]);
|
||||
|
||||
|
||||
rvmaskandmatch trigger_match (.mask(trigger_pkt_any[i].tdata2[31:0]), .data(lsu_match_data[i][31:0]), .masken(trigger_pkt_any[i].match), .match(lsu_trigger_data_match[i]));
|
||||
|
||||
assign lsu_trigger_match_dc3[i] = lsu_pkt_dc3.valid & ~lsu_pkt_dc3.dma &
|
||||
((trigger_pkt_any[i].store & lsu_pkt_dc3.store) | (trigger_pkt_any[i].load & lsu_pkt_dc3.load & ~trigger_pkt_any[i].select)) &
|
||||
lsu_trigger_data_match[i];
|
||||
end
|
||||
|
||||
|
||||
endmodule // lsu_trigger
|
|
@ -0,0 +1,132 @@
|
|||
//********************************************************************************
|
||||
// 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.
|
||||
//********************************************************************************
|
||||
|
||||
module mem
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic lsu_freeze_dc3,
|
||||
input logic dccm_clk_override,
|
||||
input logic icm_clk_override,
|
||||
input logic dec_tlu_core_ecc_disable,
|
||||
|
||||
//DCCM ports
|
||||
input logic dccm_wren,
|
||||
input logic dccm_rden,
|
||||
input logic [`RV_DCCM_BITS-1:0] dccm_wr_addr,
|
||||
input logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_lo,
|
||||
input logic [`RV_DCCM_BITS-1:0] dccm_rd_addr_hi,
|
||||
input logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_wr_data,
|
||||
|
||||
|
||||
output logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo,
|
||||
output logic [`RV_DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi,
|
||||
|
||||
|
||||
`ifdef RV_ICCM_ENABLE
|
||||
//ICCM ports
|
||||
input logic [`RV_ICCM_BITS-1:2] iccm_rw_addr,
|
||||
input logic iccm_wren,
|
||||
input logic iccm_rden,
|
||||
input logic [2:0] iccm_wr_size,
|
||||
input logic [77:0] iccm_wr_data,
|
||||
|
||||
output logic [155:0] iccm_rd_data,
|
||||
`endif
|
||||
// Icache and Itag Ports
|
||||
`ifdef RV_ICACHE_ENABLE //temp
|
||||
input logic [31:3] ic_rw_addr,
|
||||
input logic [3:0] ic_tag_valid,
|
||||
input logic [3:0] ic_wr_en,
|
||||
input logic ic_rd_en,
|
||||
input logic [127:0] ic_premux_data, // Premux data to be muxed with each way of the Icache.
|
||||
input logic ic_sel_premux_data, // Premux data sel
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
input logic [83:0] ic_wr_data, // Data to fill to the Icache. With ECC
|
||||
input logic [41:0] ic_debug_wr_data, // Debug wr cache.
|
||||
`else
|
||||
input logic [67:0] ic_wr_data, // Data to fill to the Icache. With Parity
|
||||
input logic [33:0] ic_debug_wr_data, // Debug wr cache.
|
||||
`endif
|
||||
|
||||
|
||||
|
||||
input logic [15:2] ic_debug_addr, // Read/Write addresss to the Icache.
|
||||
input logic ic_debug_rd_en, // Icache debug rd
|
||||
input logic ic_debug_wr_en, // Icache debug wr
|
||||
input logic ic_debug_tag_array, // Debug tag array
|
||||
input logic [3:0] ic_debug_way, // Debug way. Rd or Wr.
|
||||
|
||||
`endif
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
output logic [167:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
|
||||
output logic [24:0] ictag_debug_rd_data,// Debug icache tag.
|
||||
`else
|
||||
output logic [135:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With Parity
|
||||
output logic [20:0] ictag_debug_rd_data,// Debug icache tag.
|
||||
`endif
|
||||
|
||||
output logic [3:0] ic_rd_hit,
|
||||
output logic ic_tag_perr, // Icache Tag parity error
|
||||
|
||||
|
||||
input logic scan_mode
|
||||
|
||||
);
|
||||
`include "global.h"
|
||||
|
||||
`ifdef RV_DCCM_ENABLE
|
||||
localparam DCCM_ENABLE = 1'b1;
|
||||
`else
|
||||
localparam DCCM_ENABLE = 1'b0;
|
||||
`endif
|
||||
|
||||
// DCCM Instantiation
|
||||
if (DCCM_ENABLE == 1) begin: Gen_dccm_enable
|
||||
lsu_dccm_mem dccm (
|
||||
.clk_override(dccm_clk_override),
|
||||
.*
|
||||
);
|
||||
end else begin: Gen_dccm_disable
|
||||
assign dccm_rd_data_lo = '0;
|
||||
assign dccm_rd_data_hi = '0;
|
||||
end
|
||||
|
||||
`ifdef RV_ICACHE_ENABLE
|
||||
ifu_ic_mem icm (
|
||||
.clk_override(icm_clk_override),
|
||||
.*
|
||||
);
|
||||
`else
|
||||
assign ic_rd_hit[3:0] = '0;
|
||||
assign ic_tag_perr = '0 ;
|
||||
assign ic_rd_data = '0 ;
|
||||
assign ictag_debug_rd_data = '0 ;
|
||||
`endif
|
||||
|
||||
`ifdef RV_ICCM_ENABLE
|
||||
ifu_iccm_mem iccm (.*,
|
||||
.clk_override(icm_clk_override),
|
||||
.iccm_rw_addr(iccm_rw_addr[`RV_ICCM_BITS-1:2]),
|
||||
.iccm_rd_data(iccm_rd_data[155:0])
|
||||
);
|
||||
`endif
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,521 @@
|
|||
//********************************************************************************
|
||||
// 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.
|
||||
//********************************************************************************
|
||||
|
||||
//********************************************************************************
|
||||
// Function: Programmable Interrupt Controller
|
||||
// Comments:
|
||||
//********************************************************************************
|
||||
|
||||
module pic_ctrl
|
||||
(
|
||||
|
||||
input logic clk, // Core clock
|
||||
input logic free_clk, // free clock
|
||||
input logic active_clk, // active clock
|
||||
input logic rst_l, // Reset for all flops
|
||||
input logic clk_override, // Clock over-ride for gating
|
||||
input logic [`RV_PIC_TOTAL_INT_PLUS1-1:0] extintsrc_req, // Interrupt requests
|
||||
input logic [31:0] picm_addr, // Address of the register
|
||||
input logic [31:0] picm_wr_data, // Data to be written to the register
|
||||
input logic picm_wren, // Write enable to the register
|
||||
input logic picm_rden, // Read enable for the register
|
||||
input logic picm_mken, // Read the Mask for the register
|
||||
input logic [3:0] meicurpl, // Current Priority Level
|
||||
input logic [3:0] meipt, // Current Priority Threshold
|
||||
|
||||
output logic mexintpend, // External Inerrupt request to the core
|
||||
output logic [7:0] claimid, // Claim Id of the requested interrupt
|
||||
output logic [3:0] pl, // Priority level of the requested interrupt
|
||||
output logic [31:0] picm_rd_data, // Read data of the register
|
||||
output logic mhwakeup, // Wake-up interrupt request
|
||||
input logic scan_mode // scan mode
|
||||
|
||||
);
|
||||
`include "global.h"
|
||||
|
||||
localparam NUM_LEVELS = $clog2(TOTAL_INT);
|
||||
localparam INTPRIORITY_BASE_ADDR = `RV_PIC_BASE_ADDR ;
|
||||
localparam INTPEND_BASE_ADDR = `RV_PIC_BASE_ADDR + 32'h00001000 ;
|
||||
localparam INTENABLE_BASE_ADDR = `RV_PIC_BASE_ADDR + 32'h00002000 ;
|
||||
localparam EXT_INTR_PIC_CONFIG = `RV_PIC_BASE_ADDR + 32'h00003000 ;
|
||||
localparam EXT_INTR_GW_CONFIG = `RV_PIC_BASE_ADDR + 32'h00004000 ;
|
||||
localparam EXT_INTR_GW_CLEAR = `RV_PIC_BASE_ADDR + 32'h00005000 ;
|
||||
|
||||
|
||||
localparam INTPEND_SIZE = (TOTAL_INT < 32) ? 32 :
|
||||
(TOTAL_INT < 64) ? 64 :
|
||||
(TOTAL_INT < 128) ? 128 :
|
||||
(TOTAL_INT < 256) ? 256 :
|
||||
(TOTAL_INT < 512) ? 512 : 1024 ;
|
||||
|
||||
localparam INT_GRPS = INTPEND_SIZE / 32 ;
|
||||
localparam INTPRIORITY_BITS = 4 ;
|
||||
localparam ID_BITS = 8 ;
|
||||
localparam int GW_CONFIG[TOTAL_INT-1:0] = '{default:0} ;
|
||||
|
||||
logic addr_intpend_base_match;
|
||||
logic addr_intenable_base_match;
|
||||
logic addr_intpriority_base_match;
|
||||
logic addr_config_pic_match ;
|
||||
logic addr_config_gw_base_match ;
|
||||
logic addr_clear_gw_base_match ;
|
||||
logic mexintpend_in;
|
||||
logic mhwakeup_in ;
|
||||
logic intpend_reg_read ;
|
||||
|
||||
logic [31:0] picm_rd_data_in, intpend_rd_out;
|
||||
logic intenable_rd_out ;
|
||||
logic [INTPRIORITY_BITS-1:0] intpriority_rd_out;
|
||||
logic [1:0] gw_config_rd_out;
|
||||
|
||||
logic [TOTAL_INT-1:0] [INTPRIORITY_BITS-1:0] intpriority_reg;
|
||||
logic [TOTAL_INT-1:0] [INTPRIORITY_BITS-1:0] intpriority_reg_inv;
|
||||
logic [TOTAL_INT-1:0] intpriority_reg_we;
|
||||
logic [TOTAL_INT-1:0] intpriority_reg_re;
|
||||
logic [TOTAL_INT-1:0] [1:0] gw_config_reg;
|
||||
|
||||
logic [TOTAL_INT-1:0] intenable_reg;
|
||||
logic [TOTAL_INT-1:0] intenable_reg_we;
|
||||
logic [TOTAL_INT-1:0] intenable_reg_re;
|
||||
logic [TOTAL_INT-1:0] gw_config_reg_we;
|
||||
logic [TOTAL_INT-1:0] gw_config_reg_re;
|
||||
logic [TOTAL_INT-1:0] gw_clear_reg_we;
|
||||
|
||||
logic [INTPEND_SIZE-1:0] intpend_reg_extended;
|
||||
|
||||
logic [TOTAL_INT-1:0] [INTPRIORITY_BITS-1:0] intpend_w_prior_en;
|
||||
logic [TOTAL_INT-1:0] [ID_BITS-1:0] intpend_id;
|
||||
logic [INTPRIORITY_BITS-1:0] maxint;
|
||||
logic [INTPRIORITY_BITS-1:0] selected_int_priority;
|
||||
logic [INT_GRPS-1:0] [31:0] intpend_rd_part_out ;
|
||||
|
||||
logic config_reg;
|
||||
logic intpriord;
|
||||
logic config_reg_we ;
|
||||
logic config_reg_re ;
|
||||
logic config_reg_in ;
|
||||
logic prithresh_reg_write , prithresh_reg_read;
|
||||
logic intpriority_reg_read ;
|
||||
logic intenable_reg_read ;
|
||||
logic gw_config_reg_read ;
|
||||
logic picm_wren_ff , picm_rden_ff ;
|
||||
logic [31:0] picm_addr_ff;
|
||||
logic [31:0] picm_wr_data_ff;
|
||||
logic [3:0] mask;
|
||||
logic picm_mken_ff;
|
||||
logic [ID_BITS-1:0] claimid_in ;
|
||||
logic [INTPRIORITY_BITS-1:0] pl_in ;
|
||||
logic [INTPRIORITY_BITS-1:0] pl_in_q ;
|
||||
|
||||
logic [TOTAL_INT-1:0] extintsrc_req_sync;
|
||||
logic [TOTAL_INT-1:0] extintsrc_req_gw;
|
||||
|
||||
// clkens
|
||||
logic pic_addr_c1_clken;
|
||||
logic pic_data_c1_clken;
|
||||
logic pic_pri_c1_clken;
|
||||
logic pic_int_c1_clken;
|
||||
logic gw_config_c1_clken;
|
||||
|
||||
// clocks
|
||||
logic pic_addr_c1_clk;
|
||||
logic pic_data_c1_clk;
|
||||
logic pic_pri_c1_clk;
|
||||
logic pic_int_c1_clk;
|
||||
logic gw_config_c1_clk;
|
||||
|
||||
// ---- Clock gating section ------
|
||||
// c1 clock enables
|
||||
assign pic_addr_c1_clken = picm_mken | picm_rden | picm_wren | clk_override;
|
||||
assign pic_data_c1_clken = picm_wren | clk_override;
|
||||
assign pic_pri_c1_clken = (addr_intpriority_base_match & (picm_wren_ff | picm_rden_ff)) | clk_override;
|
||||
assign pic_int_c1_clken = (addr_intenable_base_match & (picm_wren_ff | picm_rden_ff)) | clk_override;
|
||||
assign gw_config_c1_clken = (addr_config_gw_base_match & (picm_wren_ff | picm_rden_ff)) | clk_override;
|
||||
|
||||
// C1 - 1 clock pulse for data
|
||||
rvclkhdr pic_addr_c1_cgc ( .en(pic_addr_c1_clken), .l1clk(pic_addr_c1_clk), .* );
|
||||
rvclkhdr pic_data_c1_cgc ( .en(pic_data_c1_clken), .l1clk(pic_data_c1_clk), .* );
|
||||
rvclkhdr pic_pri_c1_cgc ( .en(pic_pri_c1_clken), .l1clk(pic_pri_c1_clk), .* );
|
||||
rvclkhdr pic_int_c1_cgc ( .en(pic_int_c1_clken), .l1clk(pic_int_c1_clk), .* );
|
||||
rvclkhdr gw_config_c1_cgc ( .en(gw_config_c1_clken), .l1clk(gw_config_c1_clk), .* );
|
||||
|
||||
// ------ end clock gating section ------------------------
|
||||
|
||||
assign addr_intpend_base_match = (picm_addr_ff[31:6] == INTPEND_BASE_ADDR[31:6]) ;
|
||||
assign addr_intenable_base_match = (picm_addr_ff[31:NUM_LEVELS+2] == INTENABLE_BASE_ADDR[31:NUM_LEVELS+2]) ;
|
||||
assign addr_intpriority_base_match = (picm_addr_ff[31:NUM_LEVELS+2] == INTPRIORITY_BASE_ADDR[31:NUM_LEVELS+2]) ;
|
||||
assign addr_config_pic_match = (picm_addr_ff[31:0] == EXT_INTR_PIC_CONFIG[31:0]) ;
|
||||
assign addr_config_gw_base_match = (picm_addr_ff[31:NUM_LEVELS+2] == EXT_INTR_GW_CONFIG[31:NUM_LEVELS+2]) ;
|
||||
assign addr_clear_gw_base_match = (picm_addr_ff[31:NUM_LEVELS+2] == EXT_INTR_GW_CLEAR[31:NUM_LEVELS+2]) ;
|
||||
|
||||
|
||||
|
||||
rvdff #(32) picm_add_flop (.*, .din (picm_addr), .dout(picm_addr_ff), .clk(pic_addr_c1_clk));
|
||||
rvdff #(1) picm_wre_flop (.*, .din (picm_wren), .dout(picm_wren_ff), .clk(active_clk));
|
||||
rvdff #(1) picm_rde_flop (.*, .din (picm_rden), .dout(picm_rden_ff), .clk(active_clk));
|
||||
rvdff #(1) picm_mke_flop (.*, .din (picm_mken), .dout(picm_mken_ff), .clk(active_clk));
|
||||
rvdff #(32) picm_dat_flop (.*, .din (picm_wr_data[31:0]), .dout(picm_wr_data_ff[31:0]), .clk(pic_data_c1_clk));
|
||||
|
||||
rvsyncss #(TOTAL_INT-1) sync_inst
|
||||
(
|
||||
.clk (free_clk),
|
||||
.dout(extintsrc_req_sync[TOTAL_INT-1:1]),
|
||||
.din (extintsrc_req[TOTAL_INT-1:1]),
|
||||
.*) ;
|
||||
|
||||
assign extintsrc_req_sync[0] = extintsrc_req[0];
|
||||
|
||||
genvar i ;
|
||||
for (i=0; i<TOTAL_INT ; i++) begin : SETREG
|
||||
|
||||
if (i > 0 ) begin : NON_ZERO_INT
|
||||
assign intpriority_reg_we[i] = addr_intpriority_base_match & (picm_addr_ff[NUM_LEVELS+1:2] == i) & picm_wren_ff;
|
||||
assign intpriority_reg_re[i] = addr_intpriority_base_match & (picm_addr_ff[NUM_LEVELS+1:2] == i) & picm_rden_ff;
|
||||
|
||||
assign intenable_reg_we[i] = addr_intenable_base_match & (picm_addr_ff[NUM_LEVELS+1:2] == i) & picm_wren_ff;
|
||||
assign intenable_reg_re[i] = addr_intenable_base_match & (picm_addr_ff[NUM_LEVELS+1:2] == i) & picm_rden_ff;
|
||||
|
||||
assign gw_config_reg_we[i] = addr_config_gw_base_match & (picm_addr_ff[NUM_LEVELS+1:2] == i) & picm_wren_ff;
|
||||
assign gw_config_reg_re[i] = addr_config_gw_base_match & (picm_addr_ff[NUM_LEVELS+1:2] == i) & picm_rden_ff;
|
||||
|
||||
assign gw_clear_reg_we[i] = addr_clear_gw_base_match & (picm_addr_ff[NUM_LEVELS+1:2] == i) & picm_wren_ff ;
|
||||
|
||||
rvdffs #(INTPRIORITY_BITS) intpriority_ff (.*, .en( intpriority_reg_we[i]), .din (picm_wr_data_ff[INTPRIORITY_BITS-1:0]), .dout(intpriority_reg[i]), .clk(pic_pri_c1_clk));
|
||||
rvdffs #(1) intenable_ff (.*, .en( intenable_reg_we[i]), .din (picm_wr_data_ff[0]), .dout(intenable_reg[i]), .clk(pic_int_c1_clk));
|
||||
|
||||
|
||||
// if (GW_CONFIG[i]) begin
|
||||
|
||||
rvdffs #(2) gw_config_ff (.*, .en( gw_config_reg_we[i]), .din (picm_wr_data_ff[1:0]), .dout(gw_config_reg[i]), .clk(gw_config_c1_clk));
|
||||
configurable_gw config_gw_inst(.*, .clk(free_clk),
|
||||
.extintsrc_req_sync(extintsrc_req_sync[i]) ,
|
||||
.meigwctrl_polarity(gw_config_reg[i][0]) ,
|
||||
.meigwctrl_type(gw_config_reg[i][1]) ,
|
||||
.meigwclr(gw_clear_reg_we[i]) ,
|
||||
.extintsrc_req_config(extintsrc_req_gw[i])
|
||||
);
|
||||
// end else begin
|
||||
// assign extintsrc_req_gw[i] = extintsrc_req_sync[i] ;
|
||||
// assign gw_config_reg[i] = '0 ;
|
||||
// end
|
||||
|
||||
|
||||
end else begin : INT_ZERO
|
||||
assign intpriority_reg_we[i] = 1'b0 ;
|
||||
assign intpriority_reg_re[i] = 1'b0 ;
|
||||
assign intenable_reg_we[i] = 1'b0 ;
|
||||
assign intenable_reg_re[i] = 1'b0 ;
|
||||
|
||||
assign gw_config_reg_we[i] = 1'b0 ;
|
||||
assign gw_config_reg_re[i] = 1'b0 ;
|
||||
assign gw_clear_reg_we[i] = 1'b0 ;
|
||||
|
||||
assign gw_config_reg[i] = '0 ;
|
||||
|
||||
assign intpriority_reg[i] = {INTPRIORITY_BITS{1'b0}} ;
|
||||
assign intenable_reg[i] = 1'b0 ;
|
||||
assign extintsrc_req_gw[i] = 1'b0 ;
|
||||
end
|
||||
|
||||
|
||||
assign intpriority_reg_inv[i] = intpriord ? ~intpriority_reg[i] : intpriority_reg[i] ;
|
||||
|
||||
assign intpend_w_prior_en[i] = {INTPRIORITY_BITS{(extintsrc_req_gw[i] & intenable_reg[i])}} & intpriority_reg_inv[i] ;
|
||||
assign intpend_id[i] = i ;
|
||||
end
|
||||
|
||||
|
||||
assign pl_in[INTPRIORITY_BITS-1:0] = selected_int_priority[INTPRIORITY_BITS-1:0] ;
|
||||
|
||||
`ifdef RV_PIC_2CYCLE
|
||||
logic [NUM_LEVELS/2:0] [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en;
|
||||
logic [NUM_LEVELS/2:0] [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id;
|
||||
logic [NUM_LEVELS:NUM_LEVELS/2] [(TOTAL_INT/2**(NUM_LEVELS/2))+1:0] [INTPRIORITY_BITS-1:0] levelx_intpend_w_prior_en;
|
||||
logic [NUM_LEVELS:NUM_LEVELS/2] [(TOTAL_INT/2**(NUM_LEVELS/2))+1:0] [ID_BITS-1:0] levelx_intpend_id;
|
||||
|
||||
assign level_intpend_w_prior_en[0][TOTAL_INT+2:0] = {4'b0,4'b0,4'b0,intpend_w_prior_en[TOTAL_INT-1:0]} ;
|
||||
assign level_intpend_id[0][TOTAL_INT+2:0] = {8'b0,8'b0,8'b0,intpend_id[TOTAL_INT-1:0]} ;
|
||||
|
||||
logic [(TOTAL_INT/2**(NUM_LEVELS/2)):0] [INTPRIORITY_BITS-1:0] l2_intpend_w_prior_en_ff;
|
||||
logic [(TOTAL_INT/2**(NUM_LEVELS/2)):0] [ID_BITS-1:0] l2_intpend_id_ff;
|
||||
|
||||
assign levelx_intpend_w_prior_en[NUM_LEVELS/2][(TOTAL_INT/2**(NUM_LEVELS/2))+1:0] = {{1*INTPRIORITY_BITS{1'b0}},l2_intpend_w_prior_en_ff[(TOTAL_INT/2**(NUM_LEVELS/2)):0]} ;
|
||||
assign levelx_intpend_id[NUM_LEVELS/2][(TOTAL_INT/2**(NUM_LEVELS/2))+1:0] = {{1*ID_BITS{1'b1}},l2_intpend_id_ff[(TOTAL_INT/2**(NUM_LEVELS/2)):0]} ;
|
||||
|
||||
`else
|
||||
logic [NUM_LEVELS:0] [TOTAL_INT+1:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en;
|
||||
logic [NUM_LEVELS:0] [TOTAL_INT+1:0] [ID_BITS-1:0] level_intpend_id;
|
||||
|
||||
assign level_intpend_w_prior_en[0][TOTAL_INT+1:0] = {{2*INTPRIORITY_BITS{1'b0}},intpend_w_prior_en[TOTAL_INT-1:0]} ;
|
||||
assign level_intpend_id[0][TOTAL_INT+1:0] = {{2*ID_BITS{1'b1}},intpend_id[TOTAL_INT-1:0]} ;
|
||||
|
||||
`endif
|
||||
|
||||
genvar l, m , j, k;
|
||||
|
||||
// `ifdef VERILATOR
|
||||
`include "pic_ctrl_verilator_unroll.sv"
|
||||
// `else
|
||||
// `ifdef RV_PIC_2CYCLE
|
||||
// /// Do the prioritization of the interrupts here ////////////
|
||||
// for (l=0; l<NUM_LEVELS/2 ; l++) begin : TOP_LEVEL
|
||||
// for (m=0; m<=(TOTAL_INT)/(2**(l+1)) ; m++) begin : COMPARE
|
||||
// if ( m == (TOTAL_INT)/(2**(l+1))) begin
|
||||
// assign level_intpend_w_prior_en[l+1][m+1] = '0 ;
|
||||
// assign level_intpend_id[l+1][m+1] = '0 ;
|
||||
// end
|
||||
// cmp_and_mux #(.ID_BITS(ID_BITS),
|
||||
// .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l1 (
|
||||
// .a_id(level_intpend_id[l][2*m]),
|
||||
// .a_priority(level_intpend_w_prior_en[l][2*m]),
|
||||
// .b_id(level_intpend_id[l][2*m+1]),
|
||||
// .b_priority(level_intpend_w_prior_en[l][2*m+1]),
|
||||
// .out_id(level_intpend_id[l+1][m]),
|
||||
// .out_priority(level_intpend_w_prior_en[l+1][m])) ;
|
||||
//
|
||||
// end
|
||||
// end
|
||||
//
|
||||
// for (i=0; i<=TOTAL_INT/2**(NUM_LEVELS/2) ; i++) begin : MIDDLE_FLOPS
|
||||
// rvdff #(INTPRIORITY_BITS) level2_intpend_prior_reg (.*, .din (level_intpend_w_prior_en[NUM_LEVELS/2][i]), .dout(l2_intpend_w_prior_en_ff[i]), .clk(free_clk));
|
||||
// rvdff #(ID_BITS) level2_intpend_id_reg (.*, .din (level_intpend_id[NUM_LEVELS/2][i]), .dout(l2_intpend_id_ff[i]), .clk(free_clk));
|
||||
// end
|
||||
//
|
||||
// for (j=NUM_LEVELS/2; j<NUM_LEVELS ; j++) begin : BOT_LEVELS
|
||||
// for (k=0; k<=(TOTAL_INT)/(2**(j+1)) ; k++) begin : COMPARE
|
||||
// if ( k == (TOTAL_INT)/(2**(j+1))) begin
|
||||
// assign levelx_intpend_w_prior_en[j+1][k+1] = '0 ;
|
||||
// assign levelx_intpend_id[j+1][k+1] = '0 ;
|
||||
// end
|
||||
// cmp_and_mux #(.ID_BITS(ID_BITS),
|
||||
// .INTPRIORITY_BITS(INTPRIORITY_BITS))
|
||||
// cmp_l1 (
|
||||
// .a_id(levelx_intpend_id[j][2*k]),
|
||||
// .a_priority(levelx_intpend_w_prior_en[j][2*k]),
|
||||
// .b_id(levelx_intpend_id[j][2*k+1]),
|
||||
// .b_priority(levelx_intpend_w_prior_en[j][2*k+1]),
|
||||
// .out_id(levelx_intpend_id[j+1][k]),
|
||||
// .out_priority(levelx_intpend_w_prior_en[j+1][k])) ;
|
||||
// end
|
||||
// end
|
||||
// assign claimid_in[ID_BITS-1:0] = levelx_intpend_id[NUM_LEVELS][0] ; // This is the last level output
|
||||
// assign selected_int_priority[INTPRIORITY_BITS-1:0] = levelx_intpend_w_prior_en[NUM_LEVELS][0] ;
|
||||
//
|
||||
// `else
|
||||
//
|
||||
// /// Do the prioritization of the interrupts here ////////////
|
||||
// // genvar l, m , j, k; already declared outside ifdef
|
||||
// for (l=0; l<NUM_LEVELS ; l++) begin : LEVEL
|
||||
// for (m=0; m<=(TOTAL_INT)/(2**(l+1)) ; m++) begin : COMPARE
|
||||
// if ( m == (TOTAL_INT)/(2**(l+1))) begin
|
||||
// assign level_intpend_w_prior_en[l+1][m+1] = '0 ;
|
||||
// assign level_intpend_id[l+1][m+1] = '0 ;
|
||||
// end
|
||||
// cmp_and_mux #(.ID_BITS(ID_BITS),
|
||||
// .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l1 (
|
||||
// .a_id(level_intpend_id[l][2*m]),
|
||||
// .a_priority(level_intpend_w_prior_en[l][2*m]),
|
||||
// .b_id(level_intpend_id[l][2*m+1]),
|
||||
// .b_priority(level_intpend_w_prior_en[l][2*m+1]),
|
||||
// .out_id(level_intpend_id[l+1][m]),
|
||||
// .out_priority(level_intpend_w_prior_en[l+1][m])) ;
|
||||
//
|
||||
// end
|
||||
// end
|
||||
// assign claimid_in[ID_BITS-1:0] = level_intpend_id[NUM_LEVELS][0] ; // This is the last level output
|
||||
// assign selected_int_priority[INTPRIORITY_BITS-1:0] = level_intpend_w_prior_en[NUM_LEVELS][0] ;
|
||||
//
|
||||
// `endif
|
||||
// `endif
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Config Reg`
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
assign config_reg_we = addr_config_pic_match & picm_wren_ff;
|
||||
assign config_reg_re = addr_config_pic_match & picm_rden_ff;
|
||||
|
||||
assign config_reg_in = picm_wr_data_ff[0] ; //
|
||||
rvdffs #(1) config_reg_ff (.*, .clk(free_clk), .en(config_reg_we), .din (config_reg_in), .dout(config_reg));
|
||||
|
||||
assign intpriord = config_reg ;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Thresh-hold Reg`
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//assign prithresh_reg_write = addr_prithresh_match & picm_wren_ff;
|
||||
//assign prithresh_reg_read = addr_prithresh_match & picm_rden_ff;
|
||||
//
|
||||
//assign prithresh_reg_in[INTPRIORITY_BITS-1:0] = picm_wr_data_ff[INTPRIORITY_BITS-1:0] ; // Thresh-hold priority.
|
||||
//rvdffs #(INTPRIORITY_BITS) prithresh_reg_ff (.*, .en(prithresh_reg_write), .din (prithresh_reg_in[INTPRIORITY_BITS-1:0]), .dout(prithresh_reg[INTPRIORITY_BITS-1:0]));
|
||||
//
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Send the interrupt to the core if it is above the thresh-hold
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
/// ClaimId Reg and Corresponding PL
|
||||
///////////////////////////////////////////////////////////
|
||||
// logic atleast_one_int_enabled_in,atleast_one_int_enabled ;
|
||||
// logic mexintpend_unq ;
|
||||
// logic mhwakeup_unq ;
|
||||
//
|
||||
assign pl_in_q[INTPRIORITY_BITS-1:0] = intpriord ? ~pl_in : pl_in ;
|
||||
rvdff #(ID_BITS) claimid_ff (.*, .din (claimid_in[ID_BITS-1:00]), .dout(claimid[ID_BITS-1:00]), .clk(free_clk));
|
||||
rvdff #(INTPRIORITY_BITS) pl_ff (.*, .din (pl_in_q[INTPRIORITY_BITS-1:0]), .dout(pl[INTPRIORITY_BITS-1:0]), .clk(free_clk));
|
||||
|
||||
logic [INTPRIORITY_BITS-1:0] meipt_inv , meicurpl_inv ;
|
||||
assign meipt_inv[INTPRIORITY_BITS-1:0] = intpriord ? ~meipt[INTPRIORITY_BITS-1:0] : meipt[INTPRIORITY_BITS-1:0] ;
|
||||
assign meicurpl_inv[INTPRIORITY_BITS-1:0] = intpriord ? ~meicurpl[INTPRIORITY_BITS-1:0] : meicurpl[INTPRIORITY_BITS-1:0] ;
|
||||
assign mexintpend_in = (( selected_int_priority[INTPRIORITY_BITS-1:0] > meipt_inv[INTPRIORITY_BITS-1:0]) &
|
||||
( selected_int_priority[INTPRIORITY_BITS-1:0] > meicurpl_inv[INTPRIORITY_BITS-1:0]) );
|
||||
rvdff #(1) mexintpend_ff (.*, .clk(free_clk), .din (mexintpend_in), .dout(mexintpend));
|
||||
|
||||
assign maxint[INTPRIORITY_BITS-1:0] = intpriord ? 0 : 15 ;
|
||||
assign mhwakeup_in = ( pl_in_q[INTPRIORITY_BITS-1:0] == maxint) ;
|
||||
rvdff #(1) wake_up_ff (.*, .clk(free_clk), .din (mhwakeup_in), .dout(mhwakeup));
|
||||
|
||||
|
||||
// assign atleast_one_int_enabled_in = |intenable_reg[TOTAL_INT-1:0] ;
|
||||
// rvdff #(1) one_int_en_ff (.*, .din (atleast_one_int_enabled_in), .dout(atleast_one_int_enabled));
|
||||
//
|
||||
// assign mexintpend = mexintpend_unq & atleast_one_int_enabled ;
|
||||
// assign mhwakeup = mhwakeup_unq & atleast_one_int_enabled ;
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Reads of register.
|
||||
// 1- intpending
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
assign intpend_reg_read = addr_intpend_base_match & picm_rden_ff ;
|
||||
assign intpriority_reg_read = addr_intpriority_base_match & picm_rden_ff;
|
||||
assign intenable_reg_read = addr_intenable_base_match & picm_rden_ff;
|
||||
assign gw_config_reg_read = addr_config_gw_base_match & picm_rden_ff;
|
||||
|
||||
assign intpend_reg_extended[INTPEND_SIZE-1:0] = {{INTPEND_SIZE-TOTAL_INT{1'b0}},extintsrc_req_gw[TOTAL_INT-1:0]} ;
|
||||
|
||||
for (i=0; i<(INT_GRPS); i++) begin
|
||||
assign intpend_rd_part_out[i] = (({32{intpend_reg_read & picm_addr_ff[5:2] == i}}) & intpend_reg_extended[((32*i)+31):(32*i)]) ;
|
||||
end
|
||||
|
||||
always_comb begin : INTPEND_RD
|
||||
intpend_rd_out = '0 ;
|
||||
for (int i=0; i<INT_GRPS; i++) begin
|
||||
intpend_rd_out |= intpend_rd_part_out[i] ;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin : INTEN_RD
|
||||
intenable_rd_out = '0 ;
|
||||
intpriority_rd_out = '0 ;
|
||||
gw_config_rd_out = '0 ;
|
||||
for (int i=0; i<TOTAL_INT; i++) begin
|
||||
if (intenable_reg_re[i]) begin
|
||||
intenable_rd_out = intenable_reg[i] ;
|
||||
end
|
||||
if (intpriority_reg_re[i]) begin
|
||||
intpriority_rd_out = intpriority_reg[i] ;
|
||||
end
|
||||
if (gw_config_reg_re[i]) begin
|
||||
gw_config_rd_out = gw_config_reg[i] ;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
assign picm_rd_data_in[31:0] = ({32{intpend_reg_read }} & intpend_rd_out ) |
|
||||
({32{intpriority_reg_read }} & {{32-INTPRIORITY_BITS{1'b0}}, intpriority_rd_out } ) |
|
||||
({32{intenable_reg_read }} & {31'b0 , intenable_rd_out } ) |
|
||||
({32{gw_config_reg_read }} & {30'b0 , gw_config_rd_out } ) |
|
||||
({32{config_reg_re }} & {31'b0 , config_reg } ) |
|
||||
({32{picm_mken_ff & mask[3]}} & {30'b0 , 2'b11 } ) |
|
||||
({32{picm_mken_ff & mask[2]}} & {31'b0 , 1'b1 } ) |
|
||||
({32{picm_mken_ff & mask[1]}} & {28'b0 , 4'b1111 } ) |
|
||||
({32{picm_mken_ff & mask[0]}} & 32'b0 ) ;
|
||||
|
||||
|
||||
assign picm_rd_data[31:0] = picm_rd_data_in[31:0] ;
|
||||
|
||||
logic [14:0] address;
|
||||
|
||||
assign address[14:0] = picm_addr_ff[14:0];
|
||||
|
||||
`include "pic_map_auto.h"
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module cmp_and_mux #(parameter ID_BITS=8,
|
||||
INTPRIORITY_BITS = 4)
|
||||
(
|
||||
input logic [ID_BITS-1:0] a_id,
|
||||
input logic [INTPRIORITY_BITS-1:0] a_priority,
|
||||
|
||||
input logic [ID_BITS-1:0] b_id,
|
||||
input logic [INTPRIORITY_BITS-1:0] b_priority,
|
||||
|
||||
output logic [ID_BITS-1:0] out_id,
|
||||
output logic [INTPRIORITY_BITS-1:0] out_priority
|
||||
|
||||
);
|
||||
|
||||
logic a_is_lt_b ;
|
||||
|
||||
assign a_is_lt_b = ( a_priority[INTPRIORITY_BITS-1:0] < b_priority[INTPRIORITY_BITS-1:0] ) ;
|
||||
// assign a_is_eq_b = ( a_priority[INTPRIORITY_BITS-1:0] == b_priority[INTPRIORITY_BITS-1:0]) ;
|
||||
|
||||
assign out_id[ID_BITS-1:0] = a_is_lt_b ? b_id[ID_BITS-1:0] :
|
||||
a_id[ID_BITS-1:0] ;
|
||||
assign out_priority[INTPRIORITY_BITS-1:0] = a_is_lt_b ? b_priority[INTPRIORITY_BITS-1:0] :
|
||||
a_priority[INTPRIORITY_BITS-1:0] ;
|
||||
endmodule // cmp_and_mux
|
||||
|
||||
|
||||
module configurable_gw (
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
|
||||
input logic extintsrc_req_sync ,
|
||||
input logic meigwctrl_polarity ,
|
||||
input logic meigwctrl_type ,
|
||||
input logic meigwclr ,
|
||||
|
||||
output logic extintsrc_req_config
|
||||
);
|
||||
|
||||
|
||||
logic gw_int_pending_in , gw_int_pending ;
|
||||
|
||||
assign gw_int_pending_in = (extintsrc_req_sync ^ meigwctrl_polarity) | (gw_int_pending & ~meigwclr) ;
|
||||
rvdff #(1) int_pend_ff (.*, .clk(clk), .din (gw_int_pending_in), .dout(gw_int_pending));
|
||||
|
||||
assign extintsrc_req_config = meigwctrl_type ? ((extintsrc_req_sync ^ meigwctrl_polarity) | gw_int_pending) : (extintsrc_req_sync ^ meigwctrl_polarity) ;
|
||||
|
||||
endmodule // configurable_gw
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,409 @@
|
|||
// 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$
|
||||
//
|
||||
// Function: Top wrapper file with swerv/mem instantiated inside
|
||||
// Comments:
|
||||
//
|
||||
//********************************************************************************
|
||||
`include "build.h"
|
||||
//`include "def.sv"
|
||||
module swerv_wrapper
|
||||
import swerv_types::*;
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic [31:1] rst_vec,
|
||||
input logic nmi_int,
|
||||
input logic [31:1] nmi_vec,
|
||||
input logic [31:1] jtag_id,
|
||||
|
||||
|
||||
output logic [63:0] trace_rv_i_insn_ip,
|
||||
output logic [63:0] trace_rv_i_address_ip,
|
||||
output logic [2:0] trace_rv_i_valid_ip,
|
||||
output logic [2:0] trace_rv_i_exception_ip,
|
||||
output logic [4:0] trace_rv_i_ecause_ip,
|
||||
output logic [2:0] trace_rv_i_interrupt_ip,
|
||||
output logic [31:0] trace_rv_i_tval_ip,
|
||||
|
||||
// Bus signals
|
||||
|
||||
`ifdef RV_BUILD_AXI4
|
||||
//-------------------------- LSU AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
output logic lsu_axi_awvalid,
|
||||
input logic lsu_axi_awready,
|
||||
output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_awid,
|
||||
output logic [31:0] lsu_axi_awaddr,
|
||||
output logic [3:0] lsu_axi_awregion,
|
||||
output logic [7:0] lsu_axi_awlen,
|
||||
output logic [2:0] lsu_axi_awsize,
|
||||
output logic [1:0] lsu_axi_awburst,
|
||||
output logic lsu_axi_awlock,
|
||||
output logic [3:0] lsu_axi_awcache,
|
||||
output logic [2:0] lsu_axi_awprot,
|
||||
output logic [3:0] lsu_axi_awqos,
|
||||
|
||||
output logic lsu_axi_wvalid,
|
||||
input logic lsu_axi_wready,
|
||||
output logic [63:0] lsu_axi_wdata,
|
||||
output logic [7:0] lsu_axi_wstrb,
|
||||
output logic lsu_axi_wlast,
|
||||
|
||||
input logic lsu_axi_bvalid,
|
||||
output logic lsu_axi_bready,
|
||||
input logic [1:0] lsu_axi_bresp,
|
||||
input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic lsu_axi_arvalid,
|
||||
input logic lsu_axi_arready,
|
||||
output logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_arid,
|
||||
output logic [31:0] lsu_axi_araddr,
|
||||
output logic [3:0] lsu_axi_arregion,
|
||||
output logic [7:0] lsu_axi_arlen,
|
||||
output logic [2:0] lsu_axi_arsize,
|
||||
output logic [1:0] lsu_axi_arburst,
|
||||
output logic lsu_axi_arlock,
|
||||
output logic [3:0] lsu_axi_arcache,
|
||||
output logic [2:0] lsu_axi_arprot,
|
||||
output logic [3:0] lsu_axi_arqos,
|
||||
|
||||
input logic lsu_axi_rvalid,
|
||||
output logic lsu_axi_rready,
|
||||
input logic [`RV_LSU_BUS_TAG-1:0] lsu_axi_rid,
|
||||
input logic [63:0] lsu_axi_rdata,
|
||||
input logic [1:0] lsu_axi_rresp,
|
||||
input logic lsu_axi_rlast,
|
||||
|
||||
//-------------------------- IFU AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
output logic ifu_axi_awvalid,
|
||||
input logic ifu_axi_awready,
|
||||
output logic [`RV_IFU_BUS_TAG-1:0] ifu_axi_awid,
|
||||
output logic [31:0] ifu_axi_awaddr,
|
||||
output logic [3:0] ifu_axi_awregion,
|
||||
output logic [7:0] ifu_axi_awlen,
|
||||
output logic [2:0] ifu_axi_awsize,
|
||||
output logic [1:0] ifu_axi_awburst,
|
||||
output logic ifu_axi_awlock,
|
||||
output logic [3:0] ifu_axi_awcache,
|
||||
output logic [2:0] ifu_axi_awprot,
|
||||
output logic [3:0] ifu_axi_awqos,
|
||||
|
||||
output logic ifu_axi_wvalid,
|
||||
input logic ifu_axi_wready,
|
||||
output logic [63:0] ifu_axi_wdata,
|
||||
output logic [7:0] ifu_axi_wstrb,
|
||||
output logic ifu_axi_wlast,
|
||||
|
||||
input logic ifu_axi_bvalid,
|
||||
output logic ifu_axi_bready,
|
||||
input logic [1:0] ifu_axi_bresp,
|
||||
input logic [`RV_IFU_BUS_TAG-1:0] ifu_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic ifu_axi_arvalid,
|
||||
input logic ifu_axi_arready,
|
||||
output logic [`RV_IFU_BUS_TAG-1:0] ifu_axi_arid,
|
||||
output logic [31:0] ifu_axi_araddr,
|
||||
output logic [3:0] ifu_axi_arregion,
|
||||
output logic [7:0] ifu_axi_arlen,
|
||||
output logic [2:0] ifu_axi_arsize,
|
||||
output logic [1:0] ifu_axi_arburst,
|
||||
output logic ifu_axi_arlock,
|
||||
output logic [3:0] ifu_axi_arcache,
|
||||
output logic [2:0] ifu_axi_arprot,
|
||||
output logic [3:0] ifu_axi_arqos,
|
||||
|
||||
input logic ifu_axi_rvalid,
|
||||
output logic ifu_axi_rready,
|
||||
input logic [`RV_IFU_BUS_TAG-1:0] ifu_axi_rid,
|
||||
input logic [63:0] ifu_axi_rdata,
|
||||
input logic [1:0] ifu_axi_rresp,
|
||||
input logic ifu_axi_rlast,
|
||||
|
||||
//-------------------------- SB AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
output logic sb_axi_awvalid,
|
||||
input logic sb_axi_awready,
|
||||
output logic [`RV_SB_BUS_TAG-1:0] sb_axi_awid,
|
||||
output logic [31:0] sb_axi_awaddr,
|
||||
output logic [3:0] sb_axi_awregion,
|
||||
output logic [7:0] sb_axi_awlen,
|
||||
output logic [2:0] sb_axi_awsize,
|
||||
output logic [1:0] sb_axi_awburst,
|
||||
output logic sb_axi_awlock,
|
||||
output logic [3:0] sb_axi_awcache,
|
||||
output logic [2:0] sb_axi_awprot,
|
||||
output logic [3:0] sb_axi_awqos,
|
||||
|
||||
output logic sb_axi_wvalid,
|
||||
input logic sb_axi_wready,
|
||||
output logic [63:0] sb_axi_wdata,
|
||||
output logic [7:0] sb_axi_wstrb,
|
||||
output logic sb_axi_wlast,
|
||||
|
||||
input logic sb_axi_bvalid,
|
||||
output logic sb_axi_bready,
|
||||
input logic [1:0] sb_axi_bresp,
|
||||
input logic [`RV_SB_BUS_TAG-1:0] sb_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
output logic sb_axi_arvalid,
|
||||
input logic sb_axi_arready,
|
||||
output logic [`RV_SB_BUS_TAG-1:0] sb_axi_arid,
|
||||
output logic [31:0] sb_axi_araddr,
|
||||
output logic [3:0] sb_axi_arregion,
|
||||
output logic [7:0] sb_axi_arlen,
|
||||
output logic [2:0] sb_axi_arsize,
|
||||
output logic [1:0] sb_axi_arburst,
|
||||
output logic sb_axi_arlock,
|
||||
output logic [3:0] sb_axi_arcache,
|
||||
output logic [2:0] sb_axi_arprot,
|
||||
output logic [3:0] sb_axi_arqos,
|
||||
|
||||
input logic sb_axi_rvalid,
|
||||
output logic sb_axi_rready,
|
||||
input logic [`RV_SB_BUS_TAG-1:0] sb_axi_rid,
|
||||
input logic [63:0] sb_axi_rdata,
|
||||
input logic [1:0] sb_axi_rresp,
|
||||
input logic sb_axi_rlast,
|
||||
|
||||
//-------------------------- DMA AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
input logic dma_axi_awvalid,
|
||||
output logic dma_axi_awready,
|
||||
input logic [`RV_DMA_BUS_TAG-1:0] dma_axi_awid,
|
||||
input logic [31:0] dma_axi_awaddr,
|
||||
input logic [2:0] dma_axi_awsize,
|
||||
input logic [2:0] dma_axi_awprot,
|
||||
input logic [7:0] dma_axi_awlen,
|
||||
input logic [1:0] dma_axi_awburst,
|
||||
|
||||
|
||||
input logic dma_axi_wvalid,
|
||||
output logic dma_axi_wready,
|
||||
input logic [63:0] dma_axi_wdata,
|
||||
input logic [7:0] dma_axi_wstrb,
|
||||
input logic dma_axi_wlast,
|
||||
|
||||
output logic dma_axi_bvalid,
|
||||
input logic dma_axi_bready,
|
||||
output logic [1:0] dma_axi_bresp,
|
||||
output logic [`RV_DMA_BUS_TAG-1:0] dma_axi_bid,
|
||||
|
||||
// AXI Read Channels
|
||||
input logic dma_axi_arvalid,
|
||||
output logic dma_axi_arready,
|
||||
input logic [`RV_DMA_BUS_TAG-1:0] dma_axi_arid,
|
||||
input logic [31:0] dma_axi_araddr,
|
||||
input logic [2:0] dma_axi_arsize,
|
||||
input logic [2:0] dma_axi_arprot,
|
||||
input logic [7:0] dma_axi_arlen,
|
||||
input logic [1:0] dma_axi_arburst,
|
||||
|
||||
output logic dma_axi_rvalid,
|
||||
input logic dma_axi_rready,
|
||||
output logic [`RV_DMA_BUS_TAG-1:0] dma_axi_rid,
|
||||
output logic [63:0] dma_axi_rdata,
|
||||
output logic [1:0] dma_axi_rresp,
|
||||
output logic dma_axi_rlast,
|
||||
|
||||
`endif
|
||||
|
||||
`ifdef RV_BUILD_AHB_LITE
|
||||
//// AHB LITE BUS
|
||||
output logic [31:0] haddr,
|
||||
output logic [2:0] hburst,
|
||||
output logic hmastlock,
|
||||
output logic [3:0] hprot,
|
||||
output logic [2:0] hsize,
|
||||
output logic [1:0] htrans,
|
||||
output logic hwrite,
|
||||
|
||||
input logic [63:0] hrdata,
|
||||
input logic hready,
|
||||
input logic hresp,
|
||||
|
||||
// LSU AHB Master
|
||||
output logic [31:0] lsu_haddr,
|
||||
output logic [2:0] lsu_hburst,
|
||||
output logic lsu_hmastlock,
|
||||
output logic [3:0] lsu_hprot,
|
||||
output logic [2:0] lsu_hsize,
|
||||
output logic [1:0] lsu_htrans,
|
||||
output logic lsu_hwrite,
|
||||
output logic [63:0] lsu_hwdata,
|
||||
|
||||
input logic [63:0] lsu_hrdata,
|
||||
input logic lsu_hready,
|
||||
input logic lsu_hresp,
|
||||
// Debug Syster Bus AHB
|
||||
output logic [31:0] sb_haddr,
|
||||
output logic [2:0] sb_hburst,
|
||||
output logic sb_hmastlock,
|
||||
output logic [3:0] sb_hprot,
|
||||
output logic [2:0] sb_hsize,
|
||||
output logic [1:0] sb_htrans,
|
||||
output logic sb_hwrite,
|
||||
output logic [63:0] sb_hwdata,
|
||||
|
||||
input logic [63:0] sb_hrdata,
|
||||
input logic sb_hready,
|
||||
input logic sb_hresp,
|
||||
|
||||
// DMA Slave
|
||||
input logic [31:0] dma_haddr,
|
||||
input logic [2:0] dma_hburst,
|
||||
input logic dma_hmastlock,
|
||||
input logic [3:0] dma_hprot,
|
||||
input logic [2:0] dma_hsize,
|
||||
input logic [1:0] dma_htrans,
|
||||
input logic dma_hwrite,
|
||||
input logic [63:0] dma_hwdata,
|
||||
input logic dma_hsel,
|
||||
input logic dma_hreadyin,
|
||||
|
||||
output logic [63:0] dma_hrdata,
|
||||
output logic dma_hreadyout,
|
||||
output logic dma_hresp,
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
// clk ratio signals
|
||||
input logic lsu_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface
|
||||
input logic ifu_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface
|
||||
input logic dbg_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface
|
||||
input logic dma_bus_clk_en, // Clock ratio b/w cpu core clk & AHB slave interface
|
||||
|
||||
|
||||
// input logic ext_int,
|
||||
input logic timer_int,
|
||||
input logic [`RV_PIC_TOTAL_INT:1] extintsrc_req,
|
||||
|
||||
output logic [1:0] dec_tlu_perfcnt0, // toggles when perf counter 0 has an event inc
|
||||
output logic [1:0] dec_tlu_perfcnt1,
|
||||
output logic [1:0] dec_tlu_perfcnt2,
|
||||
output logic [1:0] dec_tlu_perfcnt3,
|
||||
|
||||
// ports added by the soc team
|
||||
input logic jtag_tck, // JTAG clk
|
||||
input logic jtag_tms, // JTAG TMS
|
||||
input logic jtag_tdi, // JTAG tdi
|
||||
input logic jtag_trst_n, // JTAG Reset
|
||||
output logic jtag_tdo, // JTAG TDO
|
||||
// external MPC halt/run interface
|
||||
input logic mpc_debug_halt_req, // Async halt request
|
||||
input logic mpc_debug_run_req, // Async run request
|
||||
input logic mpc_reset_run_req, // Run/halt after reset
|
||||
output logic mpc_debug_halt_ack, // Halt ack
|
||||
output logic mpc_debug_run_ack, // Run ack
|
||||
output logic debug_brkpt_status, // debug breakpoint
|
||||
|
||||
input logic i_cpu_halt_req, // Async halt req to CPU
|
||||
output logic o_cpu_halt_ack, // core response to halt
|
||||
output logic o_cpu_halt_status, // 1'b1 indicates core is halted
|
||||
output logic o_debug_mode_status, // Core to the PMU that core is in debug mode. When core is in debug mode, the PMU should refrain from sendng a halt or run request
|
||||
input logic i_cpu_run_req, // Async restart req to CPU
|
||||
output logic o_cpu_run_ack, // Core response to run req
|
||||
input logic scan_mode, // To enable scan mode
|
||||
input logic mbist_mode // to enable mbist
|
||||
);
|
||||
|
||||
`include "global.h"
|
||||
|
||||
// DCCM ports
|
||||
logic dccm_wren;
|
||||
logic dccm_rden;
|
||||
logic [DCCM_BITS-1:0] dccm_wr_addr;
|
||||
logic [DCCM_BITS-1:0] dccm_rd_addr_lo;
|
||||
logic [DCCM_BITS-1:0] dccm_rd_addr_hi;
|
||||
logic [DCCM_FDATA_WIDTH-1:0] dccm_wr_data;
|
||||
|
||||
logic [DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo;
|
||||
logic [DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi;
|
||||
|
||||
logic lsu_freeze_dc3;
|
||||
|
||||
// PIC ports
|
||||
|
||||
// Icache & Itag ports
|
||||
logic [31:3] ic_rw_addr;
|
||||
logic [3:0] ic_wr_en ; // Which way to write
|
||||
logic ic_rd_en ;
|
||||
|
||||
|
||||
logic [3:0] ic_tag_valid; // Valid from the I$ tag valid outside (in flops).
|
||||
|
||||
logic [3:0] ic_rd_hit; // ic_rd_hit[3:0]
|
||||
logic ic_tag_perr; // Ic tag parity error
|
||||
|
||||
logic [15:2] ic_debug_addr; // Read/Write addresss to the Icache.
|
||||
logic ic_debug_rd_en; // Icache debug rd
|
||||
logic ic_debug_wr_en; // Icache debug wr
|
||||
logic ic_debug_tag_array; // Debug tag array
|
||||
logic [3:0] ic_debug_way; // Debug way. Rd or Wr.
|
||||
|
||||
`ifdef RV_ICACHE_ECC
|
||||
logic [24:0] ictag_debug_rd_data;// Debug icache tag.
|
||||
logic [83:0] ic_wr_data; // ic_wr_data[135:0]
|
||||
logic [167:0] ic_rd_data; // ic_rd_data[135:0]
|
||||
logic [41:0] ic_debug_wr_data; // Debug wr cache.
|
||||
`else
|
||||
logic [20:0] ictag_debug_rd_data;// Debug icache tag.
|
||||
logic [67:0] ic_wr_data; // ic_wr_data[135:0]
|
||||
logic [135:0] ic_rd_data; // ic_rd_data[135:0]
|
||||
logic [33:0] ic_debug_wr_data; // Debug wr cache.
|
||||
`endif
|
||||
|
||||
logic [127:0] ic_premux_data;
|
||||
logic ic_sel_premux_data;
|
||||
|
||||
`ifdef RV_ICCM_ENABLE
|
||||
// ICCM ports
|
||||
logic [`RV_ICCM_BITS-1:2] iccm_rw_addr;
|
||||
logic iccm_wren;
|
||||
logic iccm_rden;
|
||||
logic [2:0] iccm_wr_size;
|
||||
logic [77:0] iccm_wr_data;
|
||||
logic [155:0] iccm_rd_data;
|
||||
`endif
|
||||
|
||||
logic core_rst_l; // Core reset including rst_l and dbg_rst_l
|
||||
logic jtag_tdoEn;
|
||||
|
||||
logic dccm_clk_override;
|
||||
logic icm_clk_override;
|
||||
logic dec_tlu_core_ecc_disable;
|
||||
|
||||
// Instantiate the swerv core
|
||||
swerv swerv (
|
||||
.*
|
||||
);
|
||||
|
||||
// Instantiate the mem
|
||||
mem mem (
|
||||
.rst_l(core_rst_l),
|
||||
.*
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
// 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.
|
||||
//
|
||||
|
||||
module ahb_sif (
|
||||
input logic [63:0] HWDATA,
|
||||
input logic HCLK,
|
||||
input logic HSEL,
|
||||
input logic [3:0] HPROT,
|
||||
input logic HWRITE,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic [2:0] HSIZE,
|
||||
input logic HREADY,
|
||||
input logic HRESETn,
|
||||
input logic [31:0] HADDR,
|
||||
input logic [2:0] HBURST,
|
||||
|
||||
output logic HREADYOUT,
|
||||
output logic HRESP,
|
||||
output logic [63:0] HRDATA
|
||||
|
||||
);
|
||||
|
||||
localparam MEM_SIZE_DW = 8192;
|
||||
localparam MAILBOX_ADDR = 32'hD0580000;
|
||||
|
||||
logic Last_HSEL;
|
||||
logic NextLast_HSEL;
|
||||
logic Last_HWRITE;
|
||||
logic [1:0] Last_HTRANS;
|
||||
logic [1:0] NextLast_HTRANS;
|
||||
logic [31:0] Last_HADDR;
|
||||
logic [63:0] Next_HRDATA;
|
||||
logic [63:0] WriteReadData;
|
||||
logic [63:0] WriteMask;
|
||||
|
||||
bit [7:0] mem [0:MEM_SIZE_DW-1];
|
||||
|
||||
|
||||
// Wires
|
||||
wire [63:0] Next_WriteMask = HSIZE == 3'b000 ? (64'hff << {HADDR[2:0], 3'b000}) : (HSIZE == 3'b001 ? (64'hffff << {HADDR[2], 4'h0}) : (HSIZE == 3'b010 ? (64'hffff_ffff << {HADDR[3],5'h0}) : 64'hffff_ffff_ffff_ffff));
|
||||
|
||||
wire [63:0] MaskedWriteData = HWDATA & WriteMask;
|
||||
wire [63:0] MaskedWriteReadData = WriteReadData & ~WriteMask;
|
||||
wire [63:0] WriteData = (MaskedWriteData | MaskedWriteReadData );
|
||||
wire Write = &{Last_HSEL, Last_HWRITE, Last_HTRANS[1]};
|
||||
wire Read = &{ HSEL, ~HWRITE, HTRANS[1]};
|
||||
|
||||
wire mailbox_write = &{Write, Last_HADDR==MAILBOX_ADDR, HRESETn==1};
|
||||
wire Next_HWRITE = |{HTRANS} ? HWRITE : Last_HWRITE;
|
||||
wire [63:0] mem_dout = {mem[{Last_HADDR[12:3],3'b0}+7],mem[{Last_HADDR[12:3],3'b0}+6],mem[{Last_HADDR[12:3],3'b0}+5],mem[{Last_HADDR[12:3],3'b0}+4],mem[{Last_HADDR[12:3],3'b0}+3],mem[{Last_HADDR[12:3],3'b0}+2],mem[{Last_HADDR[12:3],3'b0}+1],mem[{Last_HADDR[12:3],3'b0}]};
|
||||
|
||||
|
||||
always @ (posedge HCLK or negedge HRESETn) begin
|
||||
if (Write && Last_HADDR == 32'h0) begin
|
||||
mem[{Last_HADDR[12:3],3'b0}+7] <= #1 { WriteData[63:56] };
|
||||
mem[{Last_HADDR[12:3],3'b0}+6] <= #1 { WriteData[55:48] };
|
||||
mem[{Last_HADDR[12:3],3'b0}+5] <= #1 { WriteData[47:40] };
|
||||
mem[{Last_HADDR[12:3],3'b0}+4] <= #1 { WriteData[39:32] };
|
||||
mem[{Last_HADDR[12:3],3'b0}+3] <= #1 { WriteData[31:24] };
|
||||
mem[{Last_HADDR[12:3],3'b0}+2] <= #1 { WriteData[23:16] };
|
||||
mem[{Last_HADDR[12:3],3'b0}+1] <= #1 { WriteData[15:08] };
|
||||
mem[{Last_HADDR[12:3],3'b0}+0] <= #1 { WriteData[07:00] };
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge HCLK or negedge HRESETn) begin
|
||||
if(~HRESETn) begin
|
||||
HREADYOUT <= #1 1'b0 ;
|
||||
HRESP <= #1 1'b0;
|
||||
end else begin
|
||||
HREADYOUT <= #1 |HTRANS;
|
||||
HRESP <= #1 1'b0;
|
||||
WriteMask <= #1 Next_WriteMask;
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef VERILATOR
|
||||
always @(posedge HCLK or negedge HRESETn) begin
|
||||
`else
|
||||
always @(negedge HCLK or negedge HRESETn) begin
|
||||
`endif
|
||||
if(~HRESETn) begin
|
||||
Last_HADDR <= #1 32'b0;
|
||||
end else begin
|
||||
Last_HADDR <= #1 |{HTRANS} ? {HADDR[31:2], 2'b00} : Last_HADDR;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge HCLK or negedge HRESETn) begin
|
||||
if(~HRESETn) begin
|
||||
Last_HWRITE <= #1 1'b0;
|
||||
end else begin
|
||||
Last_HWRITE <= #1 Next_HWRITE;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge HCLK or negedge HRESETn) begin
|
||||
if(~HRESETn) begin
|
||||
Last_HTRANS <= #1 2'b0;
|
||||
end else begin
|
||||
Last_HTRANS <= #1 HTRANS;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge HCLK or negedge HRESETn) begin
|
||||
if(~HRESETn) begin
|
||||
Last_HSEL <= #1 1'b0;
|
||||
end else begin
|
||||
Last_HSEL <= #1 HSEL;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
`ifndef VERILATOR
|
||||
|
||||
always @(posedge HCLK or negedge HRESETn) begin
|
||||
if(~HRESETn) begin
|
||||
HRDATA <= #1 Next_HRDATA ;
|
||||
end else begin
|
||||
HRDATA <= #1 Next_HRDATA ;
|
||||
end
|
||||
end
|
||||
|
||||
always @* begin
|
||||
Next_HRDATA = mem_dout;
|
||||
end
|
||||
|
||||
`else
|
||||
|
||||
always @(posedge HCLK) begin
|
||||
Next_HRDATA <= mem_dout;
|
||||
end
|
||||
|
||||
assign HRDATA = mem_dout;
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
always @* begin
|
||||
if(Last_HSEL) begin
|
||||
WriteReadData[07:00] = mem[{Last_HADDR[12:3],3'b0}];
|
||||
WriteReadData[15:08] = mem[{Last_HADDR[12:3],3'b0}+1];
|
||||
WriteReadData[23:16] = mem[{Last_HADDR[12:3],3'b0}+2];
|
||||
WriteReadData[31:24] = mem[{Last_HADDR[12:3],3'b0}+3];
|
||||
WriteReadData[39:32] = mem[{Last_HADDR[12:3],3'b0}+4];
|
||||
WriteReadData[47:40] = mem[{Last_HADDR[12:3],3'b0}+5];
|
||||
WriteReadData[55:48] = mem[{Last_HADDR[12:3],3'b0}+6];
|
||||
WriteReadData[63:56] = mem[{Last_HADDR[12:3],3'b0}+7];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
csrrw x2, 0xb02, x3
|
||||
|
||||
|
||||
lui x5, 974848
|
||||
ori x5, x5, 0
|
||||
csrrw x2, 0x305, x5
|
||||
|
||||
|
||||
lui x6, 382293
|
||||
ori x6, x6, 1365
|
||||
csrrw x1, 0x7c0, x6
|
||||
|
||||
|
||||
|
||||
|
||||
lui x5, 0
|
||||
ori x5, x5, 0
|
||||
csrrw x2, 0x7f8, x5
|
||||
|
||||
|
||||
|
||||
|
||||
lui x5, 0
|
||||
ori x5, x5, 0
|
||||
csrrw x2, 0x7f9, x5
|
||||
|
||||
|
||||
addi x0, x0, 0
|
||||
lui x11, 853376
|
||||
ori x9, x0, 'H'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, 'E'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, 'L'
|
||||
sw x9, 0 (x11)
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, 'O'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, ' '
|
||||
sw x9, 0 (x11)
|
||||
addi x9, x0, 'W'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, 'O'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, 'R'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, 'L'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, 'D'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, '!'
|
||||
sw x9, 0 (x11)
|
||||
ori x9, x0, 255
|
||||
sw x9, 0 (x11)
|
||||
addi x1,x0,0
|
||||
|
||||
finish:
|
||||
addi x1,x1,1
|
||||
jal x0, finish;
|
||||
addi x0,x0,0
|
||||
addi x0,x0,0
|
||||
addi x0,x0,0
|
||||
addi x0,x0,0
|
|
@ -0,0 +1,71 @@
|
|||
// 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.
|
||||
//
|
||||
|
||||
// Assembly code for Hello World
|
||||
// Not using only ALU ops for creating the string
|
||||
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#define STDOUT 0xd0580000
|
||||
|
||||
|
||||
// Code to execute
|
||||
.section .text
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
// Clear minstret
|
||||
csrw minstret, zero
|
||||
csrw minstreth, zero
|
||||
|
||||
// Set up MTVEC - not expecting to use it though
|
||||
li x1, RV_ICCM_SADR
|
||||
csrw mtvec, x1
|
||||
|
||||
|
||||
// Enable Caches in MRAC
|
||||
li x1, 0x55555555
|
||||
csrw 0x7c0, x1
|
||||
|
||||
// Load string from hw_data
|
||||
// and write to stdout address
|
||||
|
||||
li x3, STDOUT
|
||||
la x4, hw_data
|
||||
|
||||
loop:
|
||||
lb x5, 0(x4)
|
||||
sb x5, 0(x3)
|
||||
addi x4, x4, 1
|
||||
bnez x5, loop
|
||||
|
||||
// Write 0xff to STDOUT for TB to termiate test.
|
||||
_finish:
|
||||
li x3, STDOUT
|
||||
addi x5, x0, 0xff
|
||||
sb x5, 0(x3)
|
||||
beq x0, x0, _finish
|
||||
.rept 100
|
||||
nop
|
||||
.endr
|
||||
|
||||
.data
|
||||
hw_data:
|
||||
.ascii "------------------------------------\n"
|
||||
.ascii "Hello World from SweRV EH1.1 @WDC !!\n"
|
||||
.ascii "------------------------------------"
|
||||
.byte 0
|
|
@ -0,0 +1,42 @@
|
|||
$RV_ROOT/design/swerv_wrapper.sv
|
||||
$RV_ROOT/design/mem.sv
|
||||
$RV_ROOT/design/pic_ctrl.sv
|
||||
$RV_ROOT/design/swerv.sv
|
||||
$RV_ROOT/design/dma_ctrl.sv
|
||||
$RV_ROOT/design/ifu/ifu_aln_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_compress_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ifc_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_bp_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ic_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu_mem_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_iccm_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu.sv
|
||||
$RV_ROOT/design/dec/dec_decode_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_gpr_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_ib_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_tlu_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_trigger.sv
|
||||
$RV_ROOT/design/dec/dec.sv
|
||||
$RV_ROOT/design/exu/exu_alu_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_mul_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_div_ctl.sv
|
||||
$RV_ROOT/design/exu/exu.sv
|
||||
$RV_ROOT/design/lsu/lsu.sv
|
||||
$RV_ROOT/design/lsu/lsu_clkdomain.sv
|
||||
$RV_ROOT/design/lsu/lsu_addrcheck.sv
|
||||
$RV_ROOT/design/lsu/lsu_lsc_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_stbuf.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_buffer.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_intf.sv
|
||||
$RV_ROOT/design/lsu/lsu_ecc.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_mem.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_trigger.sv
|
||||
$RV_ROOT/design/dbg/dbg.sv
|
||||
$RV_ROOT/design/dmi/dmi_wrapper.v
|
||||
$RV_ROOT/design/dmi/dmi_jtag_to_core_sync.v
|
||||
$RV_ROOT/design/dmi/rvjtag_tap.sv
|
||||
$RV_ROOT/design/lib/beh_lib.sv
|
||||
$RV_ROOT/design/lib/mem_lib.sv
|
||||
$RV_ROOT/design/lib/ahb_to_axi4.sv
|
||||
$RV_ROOT/design/lib/axi4_to_ahb.sv
|
|
@ -0,0 +1,42 @@
|
|||
$RV_ROOT/design/swerv_wrapper.sv
|
||||
$RV_ROOT/design/mem.sv
|
||||
$RV_ROOT/design/pic_ctrl.sv
|
||||
$RV_ROOT/design/swerv.sv
|
||||
$RV_ROOT/design/dma_ctrl.sv
|
||||
$RV_ROOT/design/ifu/ifu_aln_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_compress_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ifc_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_bp_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ic_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu_mem_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_iccm_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu.sv
|
||||
$RV_ROOT/design/dec/dec_decode_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_gpr_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_ib_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_tlu_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_trigger.sv
|
||||
$RV_ROOT/design/dec/dec.sv
|
||||
$RV_ROOT/design/exu/exu_alu_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_mul_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_div_ctl.sv
|
||||
$RV_ROOT/design/exu/exu.sv
|
||||
$RV_ROOT/design/lsu/lsu.sv
|
||||
$RV_ROOT/design/lsu/lsu_clkdomain.sv
|
||||
$RV_ROOT/design/lsu/lsu_addrcheck.sv
|
||||
$RV_ROOT/design/lsu/lsu_lsc_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_stbuf.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_buffer.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_intf.sv
|
||||
$RV_ROOT/design/lsu/lsu_ecc.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_mem.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_trigger.sv
|
||||
$RV_ROOT/design/dbg/dbg.sv
|
||||
$RV_ROOT/design/dmi/dmi_wrapper.v
|
||||
$RV_ROOT/design/dmi/dmi_jtag_to_core_sync.v
|
||||
$RV_ROOT/design/dmi/rvjtag_tap.sv
|
||||
$RV_ROOT/design/lib/beh_lib.sv
|
||||
$RV_ROOT/design/lib/mem_lib.sv
|
||||
$RV_ROOT/design/lib/ahb_to_axi4.sv
|
||||
$RV_ROOT/design/lib/axi4_to_ahb.sv
|
|
@ -0,0 +1,42 @@
|
|||
$RV_ROOT/design/swerv_wrapper.sv
|
||||
$RV_ROOT/design/mem.sv
|
||||
$RV_ROOT/design/pic_ctrl.sv
|
||||
$RV_ROOT/design/swerv.sv
|
||||
$RV_ROOT/design/dma_ctrl.sv
|
||||
$RV_ROOT/design/ifu/ifu_aln_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_compress_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ifc_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_bp_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ic_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu_mem_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_iccm_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu.sv
|
||||
$RV_ROOT/design/dec/dec_decode_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_gpr_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_ib_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_tlu_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_trigger.sv
|
||||
$RV_ROOT/design/dec/dec.sv
|
||||
$RV_ROOT/design/exu/exu_alu_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_mul_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_div_ctl.sv
|
||||
$RV_ROOT/design/exu/exu.sv
|
||||
$RV_ROOT/design/lsu/lsu.sv
|
||||
$RV_ROOT/design/lsu/lsu_clkdomain.sv
|
||||
$RV_ROOT/design/lsu/lsu_addrcheck.sv
|
||||
$RV_ROOT/design/lsu/lsu_lsc_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_stbuf.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_buffer.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_intf.sv
|
||||
$RV_ROOT/design/lsu/lsu_ecc.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_mem.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_trigger.sv
|
||||
$RV_ROOT/design/dbg/dbg.sv
|
||||
$RV_ROOT/design/dmi/dmi_wrapper.v
|
||||
$RV_ROOT/design/dmi/dmi_jtag_to_core_sync.v
|
||||
$RV_ROOT/design/dmi/rvjtag_tap.sv
|
||||
$RV_ROOT/design/lib/beh_lib.sv
|
||||
$RV_ROOT/design/lib/mem_lib.sv
|
||||
$RV_ROOT/design/lib/ahb_to_axi4.sv
|
||||
$RV_ROOT/design/lib/axi4_to_ahb.sv
|
|
@ -0,0 +1,42 @@
|
|||
$RV_ROOT/design/swerv_wrapper.sv
|
||||
$RV_ROOT/design/mem.sv
|
||||
$RV_ROOT/design/pic_ctrl.sv
|
||||
$RV_ROOT/design/swerv.sv
|
||||
$RV_ROOT/design/dma_ctrl.sv
|
||||
$RV_ROOT/design/ifu/ifu_aln_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_compress_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ifc_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_bp_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_ic_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu_mem_ctl.sv
|
||||
$RV_ROOT/design/ifu/ifu_iccm_mem.sv
|
||||
$RV_ROOT/design/ifu/ifu.sv
|
||||
$RV_ROOT/design/dec/dec_decode_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_gpr_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_ib_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_tlu_ctl.sv
|
||||
$RV_ROOT/design/dec/dec_trigger.sv
|
||||
$RV_ROOT/design/dec/dec.sv
|
||||
$RV_ROOT/design/exu/exu_alu_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_mul_ctl.sv
|
||||
$RV_ROOT/design/exu/exu_div_ctl.sv
|
||||
$RV_ROOT/design/exu/exu.sv
|
||||
$RV_ROOT/design/lsu/lsu.sv
|
||||
$RV_ROOT/design/lsu/lsu_clkdomain.sv
|
||||
$RV_ROOT/design/lsu/lsu_addrcheck.sv
|
||||
$RV_ROOT/design/lsu/lsu_lsc_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_stbuf.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_buffer.sv
|
||||
$RV_ROOT/design/lsu/lsu_bus_intf.sv
|
||||
$RV_ROOT/design/lsu/lsu_ecc.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_mem.sv
|
||||
$RV_ROOT/design/lsu/lsu_dccm_ctl.sv
|
||||
$RV_ROOT/design/lsu/lsu_trigger.sv
|
||||
$RV_ROOT/design/dbg/dbg.sv
|
||||
$RV_ROOT/design/dmi/dmi_wrapper.v
|
||||
$RV_ROOT/design/dmi/dmi_jtag_to_core_sync.v
|
||||
$RV_ROOT/design/dmi/rvjtag_tap.sv
|
||||
$RV_ROOT/design/lib/beh_lib.sv
|
||||
$RV_ROOT/design/lib/mem_lib.sv
|
||||
$RV_ROOT/design/lib/ahb_to_axi4.sv
|
||||
$RV_ROOT/design/lib/axi4_to_ahb.sv
|
|
@ -0,0 +1,7 @@
|
|||
@00001000
|
||||
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
|
||||
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 0A 48
|
||||
65 6C 6C 6F 20 57 6F 72 6C 64 20 66 72 6F 6D 20
|
||||
53 77 65 52 56 20 40 57 44 43 20 21 21 0A 2D 2D
|
||||
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
|
||||
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 00
|
|
@ -0,0 +1,6 @@
|
|||
@00000000
|
||||
73 10 20 B0 73 10 20 B8 B7 00 00 EE 73 90 50 30
|
||||
B7 50 55 55 93 80 50 55 73 90 00 7C B7 01 58 D0
|
||||
17 12 00 00 13 02 02 FE 83 02 02 00 23 80 51 00
|
||||
05 02 E3 9B 02 FE B7 01 58 D0 93 02 F0 0F 23 80
|
||||
51 00 E3 0A 00 FE
|
|
@ -0,0 +1,4 @@
|
|||
database -open waves -into waves.shm -default
|
||||
probe -create tb_top -depth all -database waves
|
||||
run
|
||||
exit
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x1000;
|
||||
.data . : { *(.*data) *(.rodata*) }
|
||||
. = 0x0;
|
||||
.text . : { *(.text) }
|
||||
_end = .;
|
||||
}
|
|
@ -0,0 +1,415 @@
|
|||
// 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.
|
||||
//
|
||||
`ifndef VERILATOR
|
||||
module tb_top;
|
||||
`else
|
||||
module tb_top ( input logic core_clk, input logic reset_l, output finished);
|
||||
`endif
|
||||
|
||||
`ifndef VERILATOR
|
||||
logic reset_l;
|
||||
logic core_clk;
|
||||
`endif
|
||||
logic nmi_int;
|
||||
|
||||
logic [31:0] reset_vector;
|
||||
logic [31:0] nmi_vector;
|
||||
logic [31:1] jtag_id;
|
||||
|
||||
logic [31:0] ic_haddr ;
|
||||
logic [2:0] ic_hburst ;
|
||||
logic ic_hmastlock ;
|
||||
logic [3:0] ic_hprot ;
|
||||
logic [2:0] ic_hsize ;
|
||||
logic [1:0] ic_htrans ;
|
||||
logic ic_hwrite ;
|
||||
logic [63:0] ic_hrdata ;
|
||||
logic ic_hready ;
|
||||
logic ic_hresp ;
|
||||
|
||||
logic [31:0] lsu_haddr ;
|
||||
logic [2:0] lsu_hburst ;
|
||||
logic lsu_hmastlock ;
|
||||
logic [3:0] lsu_hprot ;
|
||||
logic [2:0] lsu_hsize ;
|
||||
logic [1:0] lsu_htrans ;
|
||||
logic lsu_hwrite ;
|
||||
logic [63:0] lsu_hrdata ;
|
||||
logic [63:0] lsu_hwdata ;
|
||||
logic lsu_hready ;
|
||||
logic lsu_hresp ;
|
||||
|
||||
logic [31:0] sb_haddr ;
|
||||
logic [2:0] sb_hburst ;
|
||||
logic sb_hmastlock ;
|
||||
logic [3:0] sb_hprot ;
|
||||
logic [2:0] sb_hsize ;
|
||||
logic [1:0] sb_htrans ;
|
||||
logic sb_hwrite ;
|
||||
|
||||
logic [63:0] sb_hrdata ;
|
||||
logic [63:0] sb_hwdata ;
|
||||
logic sb_hready ;
|
||||
logic sb_hresp ;
|
||||
|
||||
logic [63:0] trace_rv_i_insn_ip;
|
||||
logic [63:0] trace_rv_i_address_ip;
|
||||
logic [2:0] trace_rv_i_valid_ip;
|
||||
logic [2:0] trace_rv_i_exception_ip;
|
||||
logic [4:0] trace_rv_i_ecause_ip;
|
||||
logic [2:0] trace_rv_i_interrupt_ip;
|
||||
logic [31:0] trace_rv_i_tval_ip;
|
||||
|
||||
logic o_debug_mode_status;
|
||||
logic [1:0] dec_tlu_perfcnt0;
|
||||
logic [1:0] dec_tlu_perfcnt1;
|
||||
logic [1:0] dec_tlu_perfcnt2;
|
||||
logic [1:0] dec_tlu_perfcnt3;
|
||||
|
||||
|
||||
logic jtag_tdo;
|
||||
logic o_cpu_halt_ack;
|
||||
logic o_cpu_halt_status;
|
||||
logic o_cpu_run_ack;
|
||||
|
||||
logic mailbox_write;
|
||||
logic [63:0] dma_hrdata ;
|
||||
logic [63:0] dma_hwdata ;
|
||||
logic dma_hready ;
|
||||
logic dma_hresp ;
|
||||
|
||||
logic mpc_debug_halt_req;
|
||||
logic mpc_debug_run_req;
|
||||
logic mpc_reset_run_req;
|
||||
logic mpc_debug_halt_ack;
|
||||
logic mpc_debug_run_ack;
|
||||
logic debug_brkpt_status;
|
||||
|
||||
logic [31:0] cycleCnt ;
|
||||
logic mailbox_data_val;
|
||||
logic finished;
|
||||
|
||||
wire dma_hready_out;
|
||||
|
||||
|
||||
//assign mailbox_write = &{i_ahb_lsu.Write, i_ahb_lsu.Last_HADDR==32'hD0580000, i_ahb_lsu.HRESETn==1};
|
||||
assign mailbox_write = i_ahb_lsu.mailbox_write;
|
||||
//assign mailbox_write = i_ahb_lsu.mailbox_write & !core_clk;
|
||||
assign mailbox_data_val = (i_ahb_lsu.WriteData[7:0] > 8'h5) & (i_ahb_lsu.WriteData[7:0] < 8'h7f);
|
||||
|
||||
assign finished = finished | &{i_ahb_lsu.mailbox_write, (i_ahb_lsu.WriteData[7:0] == 8'hff)};
|
||||
|
||||
assign jtag_id[31:28] = 4'b1;
|
||||
assign jtag_id[27:12] = '0;
|
||||
assign jtag_id[11:1] = 11'h45;
|
||||
|
||||
`ifndef VERILATOR
|
||||
`define FORCE force
|
||||
`else
|
||||
`define FORCE
|
||||
`endif
|
||||
|
||||
|
||||
integer fd;
|
||||
initial begin
|
||||
fd = $fopen("console.log","w");
|
||||
end
|
||||
|
||||
integer tp;
|
||||
|
||||
always @(posedge core_clk or negedge reset_l) begin
|
||||
if( reset_l == 0)
|
||||
cycleCnt <= 0;
|
||||
else
|
||||
cycleCnt <= cycleCnt+1;
|
||||
end
|
||||
|
||||
always @(posedge core_clk) begin
|
||||
//if(cycleCnt == 32'h800)
|
||||
if(cycleCnt == 32'h800) begin
|
||||
$display ("Hit max cycle count.. stopping");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
`ifdef VERILATOR
|
||||
always @(negedge mailbox_write)
|
||||
`else
|
||||
always @(posedge mailbox_write)
|
||||
`endif
|
||||
if( mailbox_data_val ) begin
|
||||
$fwrite(fd,"%c", i_ahb_lsu.WriteData[7:0]);
|
||||
$write("%c", i_ahb_lsu.WriteData[7:0]);
|
||||
end
|
||||
|
||||
always @(posedge finished) begin
|
||||
$display("\n\nFinished : minstret = %0d, mcycle = %0d", rvtop.swerv.dec.tlu.minstretl[31:0],rvtop.swerv.dec.tlu.mcyclel[31:0]);
|
||||
`ifndef VERILATOR
|
||||
$finish;
|
||||
`endif
|
||||
end
|
||||
|
||||
always @(posedge core_clk)
|
||||
if (rvtop.trace_rv_i_valid_ip !== 0) begin
|
||||
$fwrite(tp,"%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", rvtop.trace_rv_i_valid_ip, rvtop.trace_rv_i_address_ip[63:32], rvtop.trace_rv_i_address_ip[31:0], rvtop.trace_rv_i_insn_ip[63:32], rvtop.trace_rv_i_insn_ip[31:0],rvtop.trace_rv_i_exception_ip,rvtop.trace_rv_i_ecause_ip,rvtop.trace_rv_i_tval_ip,rvtop.trace_rv_i_interrupt_ip);
|
||||
end
|
||||
|
||||
initial begin
|
||||
|
||||
`ifndef VERILATOR
|
||||
core_clk = 0;
|
||||
reset_l = 0;
|
||||
`endif
|
||||
|
||||
reset_vector = 32'h80000000;
|
||||
nmi_vector = 32'hee000000;
|
||||
nmi_int = 0;
|
||||
|
||||
`ifndef VERILATOR
|
||||
@(posedge core_clk);
|
||||
reset_l = 0;
|
||||
`endif
|
||||
|
||||
$readmemh("data.hex", i_ahb_lsu.mem);
|
||||
$readmemh("program.hex", i_ahb_ic.mem);
|
||||
tp = $fopen("trace_port.csv","w");
|
||||
|
||||
`ifndef VERILATOR
|
||||
repeat (5) @(posedge core_clk);
|
||||
reset_l = 1;
|
||||
#100000 $display("");$finish;
|
||||
`endif
|
||||
end
|
||||
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
forever begin
|
||||
core_clk = #5 ~core_clk;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
//=========================================================================-
|
||||
// RTL instance
|
||||
//=========================================================================-
|
||||
swerv_wrapper rvtop (
|
||||
.rst_l ( reset_l ),
|
||||
.clk ( core_clk ),
|
||||
.rst_vec ( 31'h40000000 ),
|
||||
.nmi_int ( nmi_int ),
|
||||
.nmi_vec ( 31'h77000000 ),
|
||||
.jtag_id (jtag_id[31:1]),
|
||||
|
||||
.haddr ( ic_haddr ),
|
||||
.hburst ( ic_hburst ),
|
||||
.hmastlock ( ic_hmastlock ),
|
||||
.hprot ( ic_hprot ),
|
||||
.hsize ( ic_hsize ),
|
||||
.htrans ( ic_htrans ),
|
||||
.hwrite ( ic_hwrite ),
|
||||
|
||||
.hrdata ( ic_hrdata[63:0]),
|
||||
.hready ( ic_hready ),
|
||||
.hresp ( ic_hresp ),
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Debug AHB Master
|
||||
//---------------------------------------------------------------
|
||||
.sb_haddr ( sb_haddr ),
|
||||
.sb_hburst ( sb_hburst ),
|
||||
.sb_hmastlock ( sb_hmastlock ),
|
||||
.sb_hprot ( sb_hprot ),
|
||||
.sb_hsize ( sb_hsize ),
|
||||
.sb_htrans ( sb_htrans ),
|
||||
.sb_hwrite ( sb_hwrite ),
|
||||
.sb_hwdata ( sb_hwdata ),
|
||||
|
||||
.sb_hrdata ( sb_hrdata ),
|
||||
.sb_hready ( sb_hready ),
|
||||
.sb_hresp ( sb_hresp ),
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// LSU AHB Master
|
||||
//---------------------------------------------------------------
|
||||
.lsu_haddr ( lsu_haddr ),
|
||||
.lsu_hburst ( lsu_hburst ),
|
||||
.lsu_hmastlock ( lsu_hmastlock ),
|
||||
.lsu_hprot ( lsu_hprot ),
|
||||
.lsu_hsize ( lsu_hsize ),
|
||||
.lsu_htrans ( lsu_htrans ),
|
||||
.lsu_hwrite ( lsu_hwrite ),
|
||||
.lsu_hwdata ( lsu_hwdata ),
|
||||
|
||||
.lsu_hrdata ( lsu_hrdata[63:0]),
|
||||
.lsu_hready ( lsu_hready ),
|
||||
.lsu_hresp ( lsu_hresp ),
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// DMA Slave
|
||||
//---------------------------------------------------------------
|
||||
.dma_haddr ( '0 ),
|
||||
.dma_hburst ( '0 ),
|
||||
.dma_hmastlock ( '0 ),
|
||||
.dma_hprot ( '0 ),
|
||||
.dma_hsize ( '0 ),
|
||||
.dma_htrans ( '0 ),
|
||||
.dma_hwrite ( '0 ),
|
||||
.dma_hwdata ( '0 ),
|
||||
|
||||
.dma_hrdata ( dma_hrdata ),
|
||||
.dma_hresp ( dma_hresp ),
|
||||
.dma_hsel ( 1'b1 ),
|
||||
.dma_hreadyin ( dma_hready_out ),
|
||||
.dma_hreadyout ( dma_hready_out ),
|
||||
|
||||
.timer_int ( 1'b0 ),
|
||||
`ifdef TB_RESTRUCT
|
||||
.extintsrc_req ( '0 ),
|
||||
`else
|
||||
.extintsrc_req ( '0 ),
|
||||
`endif
|
||||
|
||||
`ifdef RV_BUILD_AHB_LITE
|
||||
.lsu_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB master interface
|
||||
.ifu_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB master interface
|
||||
.dbg_bus_clk_en ( 1'b0 ),// Clock ratio b/w cpu core clk & AHB Debug master interface
|
||||
.dma_bus_clk_en ( 1'b0 ),// Clock ratio b/w cpu core clk & AHB slave interface
|
||||
`endif
|
||||
|
||||
.trace_rv_i_insn_ip(trace_rv_i_insn_ip),
|
||||
.trace_rv_i_address_ip(trace_rv_i_address_ip),
|
||||
.trace_rv_i_valid_ip(trace_rv_i_valid_ip),
|
||||
.trace_rv_i_exception_ip(trace_rv_i_exception_ip),
|
||||
.trace_rv_i_ecause_ip(trace_rv_i_ecause_ip),
|
||||
.trace_rv_i_interrupt_ip(trace_rv_i_interrupt_ip),
|
||||
.trace_rv_i_tval_ip(trace_rv_i_tval_ip),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.jtag_tck ( 1'b0 ), // JTAG clk
|
||||
.jtag_tms ( 1'b0 ), // JTAG TMS
|
||||
.jtag_tdi ( 1'b0 ), // JTAG tdi
|
||||
.jtag_trst_n ( 1'b0 ), // JTAG Reset
|
||||
.jtag_tdo ( jtag_tdo ), // JTAG TDO
|
||||
|
||||
.mpc_debug_halt_ack ( mpc_debug_halt_ack),
|
||||
.mpc_debug_halt_req ( 1'b0),
|
||||
.mpc_debug_run_ack ( mpc_debug_run_ack),
|
||||
.mpc_debug_run_req ( 1'b1),
|
||||
.mpc_reset_run_req ( 1'b1), // Start running after reset
|
||||
.debug_brkpt_status (debug_brkpt_status),
|
||||
|
||||
.i_cpu_halt_req ( 1'b0 ), // Async halt req to CPU
|
||||
.o_cpu_halt_ack ( o_cpu_halt_ack ), // core response to halt
|
||||
.o_cpu_halt_status ( o_cpu_halt_status ), // 1'b1 indicates core is halted
|
||||
.i_cpu_run_req ( 1'b0 ), // Async restart req to CPU
|
||||
.o_debug_mode_status (o_debug_mode_status),
|
||||
.o_cpu_run_ack ( o_cpu_run_ack ), // Core response to run req
|
||||
|
||||
.dec_tlu_perfcnt0(dec_tlu_perfcnt0),
|
||||
.dec_tlu_perfcnt1(dec_tlu_perfcnt1),
|
||||
.dec_tlu_perfcnt2(dec_tlu_perfcnt2),
|
||||
.dec_tlu_perfcnt3(dec_tlu_perfcnt3),
|
||||
|
||||
.scan_mode ( 1'b0 ), // To enable scan mode
|
||||
.mbist_mode ( 1'b0 ) // to enable mbist
|
||||
|
||||
);
|
||||
|
||||
initial begin
|
||||
`FORCE rvtop.dccm_rd_data_hi = '0;
|
||||
`FORCE rvtop.dccm_rd_data_lo = '0;
|
||||
end
|
||||
|
||||
|
||||
//=========================================================================-
|
||||
// AHB I$ instance
|
||||
//=========================================================================-
|
||||
|
||||
ahb_sif i_ahb_ic (
|
||||
|
||||
// Inputs
|
||||
.HWDATA(64'h0),
|
||||
.HCLK(core_clk),
|
||||
.HSEL(1'b1),
|
||||
.HPROT(ic_hprot),
|
||||
.HWRITE(ic_hwrite),
|
||||
.HTRANS(ic_htrans),
|
||||
.HSIZE(ic_hsize),
|
||||
.HREADY(ic_hready),
|
||||
.HRESETn(reset_l),
|
||||
.HADDR(ic_haddr),
|
||||
.HBURST(ic_hburst),
|
||||
|
||||
// Outputs
|
||||
.HREADYOUT(ic_hready),
|
||||
.HRESP(ic_hresp),
|
||||
.HRDATA(ic_hrdata[63:0])
|
||||
|
||||
);
|
||||
|
||||
|
||||
ahb_sif i_ahb_lsu (
|
||||
|
||||
// Inputs
|
||||
.HWDATA(lsu_hwdata),
|
||||
.HCLK(core_clk),
|
||||
.HSEL(1'b1),
|
||||
.HPROT(lsu_hprot),
|
||||
.HWRITE(lsu_hwrite),
|
||||
.HTRANS(lsu_htrans),
|
||||
.HSIZE(lsu_hsize),
|
||||
.HREADY(lsu_hready),
|
||||
.HRESETn(reset_l),
|
||||
.HADDR(lsu_haddr),
|
||||
.HBURST(lsu_hburst),
|
||||
|
||||
// Outputs
|
||||
.HREADYOUT(lsu_hready),
|
||||
.HRESP(lsu_hresp),
|
||||
.HRDATA(lsu_hrdata[63:0])
|
||||
|
||||
);
|
||||
|
||||
ahb_sif i_ahb_sb (
|
||||
|
||||
// Inputs
|
||||
.HWDATA(sb_hwdata),
|
||||
.HCLK(core_clk),
|
||||
.HSEL(1'b1),
|
||||
.HPROT(sb_hprot),
|
||||
.HWRITE(sb_hwrite),
|
||||
.HTRANS(sb_htrans),
|
||||
.HSIZE(sb_hsize),
|
||||
.HREADY(1'b0),
|
||||
.HRESETn(reset_l),
|
||||
.HADDR(sb_haddr),
|
||||
.HBURST(sb_hburst),
|
||||
|
||||
// Outputs
|
||||
.HREADYOUT(sb_hready),
|
||||
.HRESP(sb_hresp),
|
||||
.HRDATA(sb_hrdata[63:0])
|
||||
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,83 @@
|
|||
// 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.
|
||||
//
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include "Vtb_top.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
|
||||
|
||||
// /*
|
||||
vluint64_t main_time = 0;
|
||||
|
||||
double sc_time_stamp () {
|
||||
return main_time;
|
||||
}
|
||||
// */
|
||||
|
||||
//int main(int argc, char* argv[]) {
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
std::cout << "\nStart of sim\n" << std::endl;
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
Vtb_top* tb = new Vtb_top;
|
||||
uint32_t clkCnt = 0;
|
||||
|
||||
// init trace dump
|
||||
Verilated::traceEverOn(true);
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
tb->trace (tfp, 24);
|
||||
tfp->open ("sim.vcd");
|
||||
|
||||
|
||||
// Simulate
|
||||
for(auto i=0; i<200000; ++i){
|
||||
clkCnt++;
|
||||
if(i<10) {
|
||||
tb->reset_l = 0;
|
||||
} else {
|
||||
tb->reset_l = 1;
|
||||
}
|
||||
|
||||
for (auto clk=0; clk<2; clk++) {
|
||||
tfp->dump (2*i+clk);
|
||||
tb->core_clk = !tb->core_clk;
|
||||
tb->eval();
|
||||
}
|
||||
|
||||
if (tb->finished) {
|
||||
tfp->close();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(auto i=0; i<100; ++i){
|
||||
clkCnt++;
|
||||
for (auto clk=0; clk<2; clk++) {
|
||||
tfp->dump (2*i+clk);
|
||||
tb->core_clk = !tb->core_clk;
|
||||
tb->eval();
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\nEnd of sim" << std::endl;
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,129 @@
|
|||
# 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.
|
||||
#
|
||||
|
||||
# Check for RV_ROOT
|
||||
ifeq (,$(wildcard ${RV_ROOT}/configs/swerv.config))
|
||||
$(error env var RV_ROOT does not point to a valid dir! Exiting!)
|
||||
endif
|
||||
|
||||
# Allow snapshot override
|
||||
ifeq ($(strip $(snapshot)),)
|
||||
snapshot = default
|
||||
endif
|
||||
|
||||
# Allow tool override
|
||||
SWERV_CONFIG = ${RV_ROOT}/configs/swerv.config
|
||||
IRUN = irun
|
||||
VCS = vcs
|
||||
VERILATOR = verilator
|
||||
GCC_PREFIX = riscv64-unknown-elf
|
||||
|
||||
# Define test name
|
||||
ifeq ($(strip $(ASM_TEST)),)
|
||||
ASM_TEST = hello_world2
|
||||
endif
|
||||
|
||||
# Define test name
|
||||
ifeq ($(strip $(ASM_TEST_DIR)),)
|
||||
ASM_TEST_DIR = ${RV_ROOT}/testbench/asm
|
||||
endif
|
||||
|
||||
defines = ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh ${RV_ROOT}/design/include/build.h ${RV_ROOT}/design/include/global.h ${RV_ROOT}/design/include/swerv_types.sv
|
||||
includes = -I${RV_ROOT}/design/include -I${RV_ROOT}/design/lib -I${RV_ROOT}/design/dmi -I${RV_ROOT}/configs/snapshots/$(snapshot)
|
||||
|
||||
# CFLAGS for verilator generated Makefiles. Without -std=c++11 it complains for `auto` variables
|
||||
CFLAGS += "-std=c++11"
|
||||
# Optimization for better performance; alternative is nothing for slower runtime (faster compiles)
|
||||
# -O2 for faster runtime (slower compiles), or -O for balance.
|
||||
VERILATOR_MAKE_FLAGS = OPT_FAST=""
|
||||
|
||||
# Targets
|
||||
all: clean verilator
|
||||
|
||||
clean:
|
||||
rm -rf obj_dir *.hex build ${RV_ROOT}/configs/snapshots/$(snapshot)
|
||||
|
||||
verilator: ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh
|
||||
echo '`undef ASSERT_ON' >> ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh
|
||||
$(VERILATOR) '-UASSERT_ON' --cc -CFLAGS ${CFLAGS} $(defines) $(includes) ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh \
|
||||
-f ${RV_ROOT}/testbench/flist.verilator --top-module swerv_wrapper
|
||||
$(MAKE) -C obj_dir/ -f Vswerv_wrapper.mk $(VERILATOR_MAKE_FLAGS)
|
||||
|
||||
vcs: ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh
|
||||
$(VCS) -full64 -assert svaext -sverilog +define+RV_OPENSOURCE +error+500 +incdir+${RV_ROOT}/design/lib +incdir+${RV_ROOT}/design/include \
|
||||
${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh \
|
||||
+incdir+${RV_ROOT}/design/dmi +incdir+${RV_ROOT}/configs/snapshots/$(snapshot) +libext+.v ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh \
|
||||
$(defines)-f ${RV_ROOT}/testbench/flist.vcs -l vcs.log
|
||||
|
||||
irun: ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh
|
||||
$(IRUN) -64bit -elaborate -ida -access +rw -q -sv -sysv -nowarn CUVIHR -nclibdirpath ${PWD} -nclibdirname swerv.build \
|
||||
-incdir ${RV_ROOT}/design/lib -incdir ${RV_ROOT}/design/include -incdir ${RV_ROOT}/design/dmi -vlog_ext +.vh+.h\
|
||||
$(defines) -incdir ${RV_ROOT}/configs/snapshots/$(snapshot) -f ${RV_ROOT}/testbench/flist.vcs -elaborate -snapshot default
|
||||
|
||||
${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh:
|
||||
$(SWERV_CONFIG) -snapshot=$(snapshot)
|
||||
|
||||
verilator-run: program.hex
|
||||
snapshot=ahb_lite
|
||||
$(SWERV_CONFIG) -snapshot=$(snapshot) -ahb_lite
|
||||
echo '`undef ASSERT_ON' >> ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh
|
||||
$(VERILATOR) '-UASSERT_ON' --cc -CFLAGS ${CFLAGS} $(defines) $(includes) ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh \
|
||||
${RV_ROOT}/testbench/tb_top.sv -I${RV_ROOT}/testbench \
|
||||
-f ${RV_ROOT}/testbench/flist.verilator --top-module tb_top -exe test_tb_top.cpp --trace --autoflush
|
||||
cp ${RV_ROOT}/testbench/test_tb_top.cpp obj_dir/
|
||||
$(MAKE) -C obj_dir/ -f Vtb_top.mk $(VERILATOR_MAKE_FLAGS)
|
||||
./obj_dir/Vtb_top
|
||||
|
||||
irun-run: program.hex
|
||||
snapshot=ahb_lite
|
||||
$(SWERV_CONFIG) -snapshot=$(snapshot) -ahb_lite
|
||||
$(IRUN) -64bit -ida -access +rw -q -sv -sysv -nowarn CUVIHR -nclibdirpath ${PWD} -nclibdirname swerv.build \
|
||||
-incdir ${RV_ROOT}/design/lib -incdir ${RV_ROOT}/design/include -incdir ${RV_ROOT}/design/dmi -vlog_ext +.vh+.h\
|
||||
$(defines) -top tb_top ${RV_ROOT}/testbench/tb_top.sv -I${RV_ROOT}/testbench ${RV_ROOT}/testbench/ahb_sif.sv\
|
||||
-incdir ${RV_ROOT}/configs/snapshots/$(snapshot) -f ${RV_ROOT}/testbench/flist.vcs -snapshot default
|
||||
|
||||
vcs-run: program.hex
|
||||
snapshot=ahb_lite
|
||||
$(SWERV_CONFIG) -snapshot=$(snapshot) -ahb_lite
|
||||
cp ${RV_ROOT}/testbench/hex/*.hex .
|
||||
$(VCS) -full64 -assert svaext -sverilog +define+RV_OPENSOURCE +error+500 +incdir+${RV_ROOT}/design/lib +incdir+${RV_ROOT}/design/include \
|
||||
${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh \
|
||||
+incdir+${RV_ROOT}/design/dmi +incdir+${RV_ROOT}/configs/snapshots/$(snapshot) +libext+.v \
|
||||
$(defines) -f ${RV_ROOT}/testbench/flist.vcs ${RV_ROOT}/testbench/tb_top.sv -I${RV_ROOT}/testbench ${RV_ROOT}/testbench/ahb_sif.sv -l vcs.log
|
||||
./simv
|
||||
|
||||
program.hex: $(ASM_TEST_DIR)/$(ASM_TEST).s ${RV_ROOT}/configs/snapshots/$(snapshot)/common_defines.vh
|
||||
@echo Building $(ASM_TEST)
|
||||
ifeq ($(shell which $(GCC_PREFIX)-as),)
|
||||
@echo " !!! No $(GCC_PREFIX)-as in path, using canned hex files !!"
|
||||
cp ${RV_ROOT}/testbench/hex/*.hex .
|
||||
else
|
||||
cp $(ASM_TEST_DIR)/$(ASM_TEST).s .
|
||||
$(GCC_PREFIX)-cpp -I${RV_ROOT}/configs/snapshots/$(snapshot) $(ASM_TEST).s > $(ASM_TEST).cpp.s
|
||||
$(GCC_PREFIX)-as -march=rv32imc $(ASM_TEST).cpp.s -o $(ASM_TEST).o
|
||||
$(GCC_PREFIX)-ld -m elf32lriscv --discard-none -T${RV_ROOT}/testbench/link.ld -o $(ASM_TEST).exe $(ASM_TEST).o
|
||||
$(GCC_PREFIX)-objcopy -O verilog --only-section ".data*" --only-section ".rodata*" $(ASM_TEST).exe data.hex
|
||||
$(GCC_PREFIX)-objcopy -O verilog --only-section ".text*" --set-start=0x0 $(ASM_TEST).exe program.hex
|
||||
$(GCC_PREFIX)-objdump -dS $(ASM_TEST).exe > $(ASM_TEST).dis
|
||||
$(GCC_PREFIX)-nm -f posix -C $(ASM_TEST).exe > $(ASM_TEST).tbl
|
||||
@echo Completed building $(ASM_TEST)
|
||||
endif
|
||||
|
||||
help:
|
||||
@echo Make sure the environment variable RV_ROOT is set.
|
||||
@echo Possible targets: verilator vcs irun help clean all verilator-run irun-run vcs-run program.hex
|
||||
|
||||
.PHONY: help clean verilator vcs irun verilator-run irun-run vcs-run
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use Getopt::Long;
|
||||
|
||||
$helpusage = "placeholder";
|
||||
|
||||
GetOptions ('in=s' => \$in,
|
||||
'prefix=s' => \$prefix) || die("$helpusage");
|
||||
|
||||
|
||||
|
||||
@in=`cat $in`;
|
||||
|
||||
|
||||
foreach $line (@in) {
|
||||
|
||||
if ($line=~/\#/) { next; }
|
||||
|
||||
if ($line=~/([^=]+)=/) {
|
||||
$sig=$1;
|
||||
$sig=~s/\s+//g;
|
||||
printf("logic $sig;\n");
|
||||
}
|
||||
}
|
||||
|
||||
foreach $line (@in) {
|
||||
|
||||
if ($line=~/\#/) { next; }
|
||||
|
||||
if ($line=~/([^=]+)=\s*;/) {
|
||||
printf("assign ${prefix}$1 = 1'b0;\n");
|
||||
next;
|
||||
}
|
||||
|
||||
if ($line=~/([^=]+)=\s*\(\s*\);/) {
|
||||
printf("assign ${prefix}$1 = 1'b0;\n");
|
||||
next;
|
||||
}
|
||||
|
||||
if ($line =~ /=/) { printf("assign ${prefix}$line"); }
|
||||
else { printf("$line"); }
|
||||
}
|
||||
|
||||
|
||||
exit;
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use Getopt::Long;
|
||||
|
||||
$helpusage = "placeholder";
|
||||
|
||||
GetOptions ('legal' => \$legal,
|
||||
'in=s' => \$in,
|
||||
'out=s' => \$out,
|
||||
'view=s' => \$view ) || die("$helpusage");
|
||||
|
||||
|
||||
if (!defined($in)) { die("must define -in=input"); }
|
||||
if (!defined($out)) { $out="${in}.out"; }
|
||||
|
||||
if ($in eq "decode") { $view="rv32i"; }
|
||||
elsif ($in eq "cdecode") { $view="rv32c"; }
|
||||
elsif ($in eq "csrdecode") { $view="csr"; }
|
||||
|
||||
if (defined($in)) { printf("in=$in\n"); }
|
||||
if (defined($out)) { printf("out=$out\n"); }
|
||||
if (defined($view)) { printf("view=$view\n"); }
|
||||
|
||||
@in=`cat $in`;
|
||||
|
||||
$gather=0;
|
||||
|
||||
$TIMEOUT=50;
|
||||
|
||||
foreach $line (@in) {
|
||||
|
||||
#printf("$pstate: $line");
|
||||
|
||||
if ($line=~/^\s*\#/) { #printf("skip $line");
|
||||
next; }
|
||||
|
||||
if ($gather==1) {
|
||||
if ($line=~/(\S+)/) {
|
||||
if ($line=~/}/) { $gather=0; $position=0; next; }
|
||||
$label=$1;
|
||||
$label=~s/,//g;
|
||||
if ($pstate==2) {
|
||||
if (defined($INPUT{$CVIEW}{$label})) { die("input $label already defined"); }
|
||||
$INPUT{$CVIEW}{$label}=$position++;
|
||||
$INPUTLEN{$CVIEW}++;
|
||||
$INPUTSTR{$CVIEW}.=" $label";
|
||||
}
|
||||
elsif ($pstate==3) {
|
||||
if (defined($OUTPUT{$CVIEW}{$label})) { die("output $label already defined"); }
|
||||
$OUTPUT{$CVIEW}{$label}=$position++;
|
||||
$OUTPUTLEN{$CVIEW}++;
|
||||
$OUTPUTSTR{$CVIEW}.=" $label";
|
||||
}
|
||||
else { die("unknown pstate $pstate in gather"); }
|
||||
}
|
||||
}
|
||||
|
||||
if ($line=~/^.definition/) {
|
||||
$pstate=1; next;
|
||||
}
|
||||
if ($pstate==1) { # definition
|
||||
if ($line!~/^.output/) {
|
||||
if ($line=~/(\S+)\s*=\s*(\S+)/) {
|
||||
$key=$1; $value=$2;
|
||||
$value=~s/\./-/g;
|
||||
$value=~s/\[//g;
|
||||
$value=~s/\]//g;
|
||||
$DEFINITION{$key}=$value;
|
||||
}
|
||||
}
|
||||
else { $pstate=2; next; }
|
||||
}
|
||||
|
||||
if ($line=~/^.input/) {
|
||||
$pstate=2; next;
|
||||
}
|
||||
|
||||
if ($pstate==2) { # input
|
||||
if ($line=~/(\S+)\s*=\s*\{/) {
|
||||
$CVIEW=$1; $gather=1; next;
|
||||
}
|
||||
}
|
||||
|
||||
if ($line=~/^.output/) {
|
||||
$pstate=3; next;
|
||||
}
|
||||
|
||||
if ($pstate==3) { # output
|
||||
if ($line=~/(\S+)\s*=\s*\{/) {
|
||||
$CVIEW=$1; $gather=1; next;
|
||||
}
|
||||
}
|
||||
|
||||
if ($line=~/^.decode/) {
|
||||
$pstate=4; next;
|
||||
}
|
||||
|
||||
if ($pstate==4) { # decode
|
||||
if ($line=~/([^\[]+)\[([^\]]+)\]\s+=\s+\{([^\}]+)\}/) {
|
||||
$dview=$1; $inst=$2; $body=$3;
|
||||
$dview=~s/\s+//g;
|
||||
$inst=~s/\s+//g;
|
||||
#printf("$dview $inst $body\n");
|
||||
if ($inst=~/([^\{]+)\{([^-]+)-([^\}]+)\}/) {
|
||||
$base=$1; $lo=$2; $hi=$3;
|
||||
$hi++;
|
||||
for ($i=0; $i<$TIMEOUT && $lo ne $hi; $i++) {
|
||||
#printf("decode $dview $base$lo\n");
|
||||
|
||||
$expand=$base.$lo;
|
||||
if (!defined($DEFINITION{$expand})) { die("could not find instruction definition for inst $expand"); }
|
||||
|
||||
$DECODE{$dview}{$expand}=$body;
|
||||
$lo++;
|
||||
}
|
||||
if ($i == $TIMEOUT) { die("timeout in decode expansion"); }
|
||||
|
||||
}
|
||||
else {
|
||||
if (!defined($DEFINITION{$inst})) { die("could not find instruction definition for inst $inst"); }
|
||||
$DECODE{$dview}{$inst}=$body;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#printf("view $view len %d\n",$OUTPUTLEN{$view});
|
||||
|
||||
#printf("$OUTPUTSTR{$view}\n");
|
||||
|
||||
|
||||
# need to switch this somehow based on 16/32
|
||||
printf(".i %d\n",$INPUTLEN{$view});
|
||||
|
||||
if (defined($legal)) {
|
||||
printf(".o 1\n");
|
||||
}
|
||||
else {
|
||||
printf(".o %d\n",$OUTPUTLEN{$view});
|
||||
}
|
||||
|
||||
printf(".ilb %s\n",$INPUTSTR{$view});
|
||||
|
||||
if (defined($legal)) {
|
||||
printf(".ob legal\n");
|
||||
}
|
||||
else {
|
||||
printf(".ob %s\n",$OUTPUTSTR{$view});
|
||||
}
|
||||
|
||||
if (defined($legal)) {
|
||||
printf(".type fd\n");
|
||||
}
|
||||
else {
|
||||
printf(".type fr\n");
|
||||
}
|
||||
|
||||
$DEFAULT_TEMPLATE='0'x$OUTPUTLEN{$view};
|
||||
|
||||
foreach $inst (sort keys %{ $DECODE{$view} }) {
|
||||
|
||||
$body=$DECODE{$view}{$inst};
|
||||
@sigs=split(' ',$body);
|
||||
|
||||
$template=$DEFAULT_TEMPLATE;
|
||||
foreach $sig (@sigs) {
|
||||
if (!defined($OUTPUT{$view}{$sig})) { die("could not find output definition for sig $sig in view $view"); }
|
||||
$position=$OUTPUT{$view}{$sig};
|
||||
substr($template,$position,1,1);
|
||||
}
|
||||
|
||||
# if (!defined($DEFINITION{$inst})) { die("could not find instruction defintion for inst $inst"); }
|
||||
|
||||
printf("# $inst\n");
|
||||
if (defined($legal)) {
|
||||
printf("$DEFINITION{$inst} 1\n");
|
||||
}
|
||||
else {
|
||||
printf("$DEFINITION{$inst} $template\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
exit;
|
||||
|
||||
foreach $inst (sort keys %DEFINITION) {
|
||||
$value=$DEFINITION{$inst};
|
||||
printf("%-10s = $value\n",$inst);
|
||||
}
|
||||
|
||||
|
||||
foreach $sig (sort keys %{ $OUTPUT{$view} }) {
|
||||
$position=$OUTPUT{$view}{$sig};
|
||||
printf("$sig $position\n");
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use Getopt::Long;
|
||||
|
||||
use integer;
|
||||
|
||||
$helpusage = "placeholder";
|
||||
|
||||
GetOptions ('total_int=s' => \$total_int)|| die("$helpusage");
|
||||
|
||||
$LEN=15;
|
||||
|
||||
#printf("logic [2:0] mask;\n");
|
||||
|
||||
printf("// mask[3:0] = { 4'b1000 - 30b mask,4'b0100 - 31b mask, 4'b0010 - 28b mask, 4'b0001 - 32b mask }\n");
|
||||
printf("always_comb begin\n");
|
||||
printf(" case \(address[14:0]\)\n");
|
||||
printf(" 15'b011000000000000 : mask[3:0] = 4'b0100;\n");
|
||||
for ($i=1; $i<=$total_int; $i++) {
|
||||
$j=hex("4000");
|
||||
printf(" 15'b%s : mask[3:0] = 4'b1000;\n",d2b($j+$i*4));
|
||||
}
|
||||
for ($i=1; $i<=$total_int; $i++) {
|
||||
$j=hex("2000");
|
||||
printf(" 15'b%s : mask[3:0] = 4'b0100;\n",d2b($j+$i*4));
|
||||
}
|
||||
for ($i=1; $i<=$total_int; $i++) {
|
||||
$j=hex("0");
|
||||
printf(" 15'b%s : mask[3:0] = 4'b0010;\n",d2b($j+$i*4));
|
||||
}
|
||||
printf(" %-17s : mask[3:0] = 4'b0001;\n","default");
|
||||
printf(" endcase\n");
|
||||
printf("end\n");
|
||||
|
||||
|
||||
sub b2d {
|
||||
my ($v) = @_;
|
||||
|
||||
$v = oct("0b" . $v);
|
||||
|
||||
return($v);
|
||||
}
|
||||
|
||||
sub d2b {
|
||||
my ($v) = @_;
|
||||
|
||||
my $repeat;
|
||||
|
||||
$v = sprintf "%b",$v;
|
||||
if (length($v)<$LEN) {
|
||||
$repeat=$LEN-length($v);
|
||||
$v="0"x$repeat.$v;
|
||||
}
|
||||
elsif (length($v)>$LEN) {
|
||||
$v=substr($v,length($v)-$LEN,$LEN);
|
||||
}
|
||||
|
||||
return($v);
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use Getopt::Long;
|
||||
|
||||
use integer;
|
||||
|
||||
$helpusage = "placeholder";
|
||||
|
||||
GetOptions ('len=s' => \$len,
|
||||
'num=s' => \$num,
|
||||
'den=s' => \$den,
|
||||
'skip' => \$skip) || die("$helpusage");
|
||||
|
||||
if (!defined($len)) { $len=8; }
|
||||
$LEN=$len;
|
||||
|
||||
$n=d2b($num); # numerator - quotient
|
||||
$m=d2b($den); # denominator - divisor
|
||||
|
||||
|
||||
printf(".i 8\n");
|
||||
printf(".o 4\n");
|
||||
printf(".ilb q_ff[3] q_ff[2] q_ff[1] q_ff[0] m_ff[3] m_ff[2] m_ff[1] m_ff[0]\n");
|
||||
printf(".ob smallnum[3] smallnum[2] smallnum[1] smallnum[0]\n");
|
||||
printf(".type fr\n");
|
||||
for ($q=0; $q<16; $q++) {
|
||||
for ($m=0; $m<16; $m++) {
|
||||
if ($m==0) { next; }
|
||||
$result=int($q/$m);
|
||||
printf("%s %s %s\n",d2bl($q,4),d2bl($m,4),d2bl($result,4));
|
||||
}
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
#$LEN=length($n);
|
||||
|
||||
$a="0"x$LEN;
|
||||
$q=$n;
|
||||
|
||||
#printf("n=%s, m=%s\n",$n,$m);
|
||||
#printf("a=%s, q=%s\n",$a,$q);
|
||||
|
||||
for ($i=1; $i<=$LEN; $i++) {
|
||||
|
||||
#printf("iteration $n:\n");
|
||||
|
||||
printf("$i: a=%s q=%s\n",$a,$q);
|
||||
|
||||
|
||||
$signa = substr($a,0,1);
|
||||
|
||||
|
||||
$a = substr($a.$q,1,$LEN); # new a with q shifted in
|
||||
|
||||
if ($signa==0) { $a=b2d($a)-b2d($m); }
|
||||
else { $a=b2d($a)+b2d($m); }
|
||||
|
||||
$a=d2b($a);
|
||||
|
||||
|
||||
$signa = substr($a,0,1);
|
||||
if ($signa==0) { $q=substr($q,1,$LEN-1)."1"; }
|
||||
else { $q=substr($q,1,$LEN-1)."0"; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
#printf("a=$a\n");
|
||||
$signa = substr($a,0,1);
|
||||
if ($signa==1 && !defined($skip)) {
|
||||
printf("correction:\n");
|
||||
$a=b2d($a)+b2d($m);
|
||||
$a=d2b($a);
|
||||
}
|
||||
#printf("a=$a\n");
|
||||
printf("%d / %d = %d R %d ",b2d($n),b2d($m),b2d($q),b2d($a));
|
||||
if ($a eq $n) { printf("-> remainder equal numerator\n"); }
|
||||
else { printf("\n"); }
|
||||
|
||||
sub b2d {
|
||||
my ($v) = @_;
|
||||
|
||||
$v = oct("0b" . $v);
|
||||
|
||||
return($v);
|
||||
}
|
||||
|
||||
sub d2b {
|
||||
my ($v) = @_;
|
||||
|
||||
my $repeat;
|
||||
|
||||
$v = sprintf "%b",$v;
|
||||
if (length($v)<$LEN) {
|
||||
$repeat=$LEN-length($v);
|
||||
$v="0"x$repeat.$v;
|
||||
}
|
||||
elsif (length($v)>$LEN) {
|
||||
$v=substr($v,length($v)-$LEN,$LEN);
|
||||
}
|
||||
|
||||
return($v);
|
||||
}
|
||||
|
||||
sub d2bl {
|
||||
my ($v,$LEN) = @_;
|
||||
|
||||
my $repeat;
|
||||
|
||||
$v = sprintf "%b",$v;
|
||||
if (length($v)<$LEN) {
|
||||
$repeat=$LEN-length($v);
|
||||
$v="0"x$repeat.$v;
|
||||
}
|
||||
elsif (length($v)>$LEN) {
|
||||
$v=substr($v,length($v)-$LEN,$LEN);
|
||||
}
|
||||
|
||||
return($v);
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
#!/usr/bin/perl
|
||||
#use strict;
|
||||
#use warnings;
|
||||
|
||||
my $RV_ROOT = $ENV{RV_ROOT};
|
||||
|
||||
my $TOTAL_INT=$ARGV[0];
|
||||
print "// argv=".$ARGV[0]."\n";
|
||||
my $NUM_LEVELS;
|
||||
if($TOTAL_INT==2){$NUM_LEVELS=1;}
|
||||
elsif ($TOTAL_INT==4){$NUM_LEVELS=2;}
|
||||
elsif ($TOTAL_INT==8){$NUM_LEVELS=3;}
|
||||
elsif ($TOTAL_INT==16){$NUM_LEVELS=4;}
|
||||
elsif ($TOTAL_INT==32){$NUM_LEVELS=5;}
|
||||
elsif ($TOTAL_INT==64){$NUM_LEVELS=6;}
|
||||
elsif ($TOTAL_INT==128){$NUM_LEVELS=7;}
|
||||
elsif ($TOTAL_INT==256){$NUM_LEVELS=8;}
|
||||
elsif ($TOTAL_INT==512){$NUM_LEVELS=9;}
|
||||
elsif ($TOTAL_INT==1024){$NUM_LEVELS=10;}
|
||||
else {$NUM_LEVELS=int(log($TOTAL_INT)/log(2))+1;}
|
||||
print ("// TOTAL_INT=".$TOTAL_INT." NUM_LEVELS=".$NUM_LEVELS."\n");
|
||||
$next_level = 1;
|
||||
print ("`ifdef RV_PIC_2CYCLE\n");
|
||||
if($TOTAL_INT > 2){
|
||||
print ("// LEVEL0\n");
|
||||
print ("logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_".$next_level.";\n");
|
||||
print ("logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_".$next_level.";\n");
|
||||
print (" for (m=0; m<=(TOTAL_INT)/(2**(".$next_level.")) ; m++) begin : COMPARE0\n");
|
||||
print (" if ( m == (TOTAL_INT)/(2**(".$next_level."))) begin \n");
|
||||
print (" assign level_intpend_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" end\n");
|
||||
print (" cmp_and_mux #(\n");
|
||||
print (" .ID_BITS(ID_BITS),\n");
|
||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||
print (" .a_id(level_intpend_id[0][2*m]),\n");
|
||||
print (" .a_priority(level_intpend_w_prior_en[0][2*m]),\n");
|
||||
print (" .b_id(level_intpend_id[0][2*m+1]),\n");
|
||||
print (" .b_priority(level_intpend_w_prior_en[0][2*m+1]),\n");
|
||||
print (" .out_id(level_intpend_id_".$next_level."[m]),\n");
|
||||
print (" .out_priority(level_intpend_w_prior_en_".$next_level."[m])) ;\n");
|
||||
print (" \n");
|
||||
print (" end\n\n");
|
||||
for (my $l=1; $l<int($NUM_LEVELS/2) ; $l++) {
|
||||
$next_level = $l+1;
|
||||
print ("// LEVEL".$l."\n");
|
||||
print ("logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_".$next_level.";\n");
|
||||
print ("logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_".$next_level.";\n");
|
||||
print (" for (m=0; m<=(TOTAL_INT)/(2**(".$next_level.")) ; m++) begin : COMPARE$l\n");
|
||||
print (" if ( m == (TOTAL_INT)/(2**(".$next_level."))) begin \n");
|
||||
print (" assign level_intpend_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" end\n");
|
||||
print (" cmp_and_mux #(\n");
|
||||
print (" .ID_BITS(ID_BITS),\n");
|
||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||
print (" .a_id(level_intpend_id_".$l."[2*m]),\n");
|
||||
print (" .a_priority(level_intpend_w_prior_en_".$l."[2*m]),\n");
|
||||
print (" .b_id(level_intpend_id_".$l."[2*m+1]),\n");
|
||||
print (" .b_priority(level_intpend_w_prior_en_".$l."[2*m+1]),\n");
|
||||
print (" .out_id(level_intpend_id_".$next_level."[m]),\n");
|
||||
print (" .out_priority(level_intpend_w_prior_en_".$next_level."[m])) ;\n");
|
||||
print (" \n");
|
||||
print (" end\n\n");
|
||||
}
|
||||
### ADD FLOP STAGE
|
||||
print ("for (i=0; i<=TOTAL_INT/2**(NUM_LEVELS/2) ; i++) begin : MIDDLE_FLOPS\n");
|
||||
print (" rvdff #(INTPRIORITY_BITS) level2_intpend_prior_reg (.*, .din (level_intpend_w_prior_en_".$next_level."[i]), .dout(l2_intpend_w_prior_en_ff[i]), .clk(active_clk));\n");
|
||||
print (" rvdff #(ID_BITS) level2_intpend_id_reg (.*, .din (level_intpend_id_".$next_level."[i]), .dout(l2_intpend_id_ff[i]), .clk(active_clk));\n");
|
||||
print ("end\n");
|
||||
}else{
|
||||
print ("for (i=0; i<=TOTAL_INT/2**(NUM_LEVELS/2) ; i++) begin : MIDDLE_FLOPS\n");
|
||||
print (" rvdff #(INTPRIORITY_BITS) level2_intpend_prior_reg (.*, .din (level_intpend_w_prior_en[0][i]), .dout(l2_intpend_w_prior_en_ff[i]), .clk(active_clk));\n");
|
||||
print (" rvdff #(ID_BITS) level2_intpend_id_reg (.*, .din (level_intpend_id[0][i]), .dout(l2_intpend_id_ff[i]), .clk(active_clk));\n");
|
||||
print ("end\n");
|
||||
}
|
||||
### END FLOP STAGE
|
||||
$next_level = int($NUM_LEVELS/2) + 1;
|
||||
my $tmp = int($NUM_LEVELS/2);
|
||||
print ("// LEVEL".$tmp."\n");
|
||||
print ("logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] levelx_intpend_w_prior_en_".$next_level.";\n");
|
||||
print ("logic [TOTAL_INT+2:0] [ID_BITS-1:0] levelx_intpend_id_".$next_level.";\n");
|
||||
print (" for (m=0; m<=(TOTAL_INT)/(2**(".$next_level.")) ; m++) begin : COMPARE$tmp\n");
|
||||
print (" if ( m == (TOTAL_INT)/(2**(".$next_level."))) begin \n");
|
||||
print (" assign levelx_intpend_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" assign levelx_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" end\n");
|
||||
print (" cmp_and_mux #(\n");
|
||||
print (" .ID_BITS(ID_BITS),\n");
|
||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||
print (" .a_id(levelx_intpend_id[$tmp][2*m]),\n");
|
||||
print (" .a_priority(levelx_intpend_w_prior_en[$tmp][2*m]),\n");
|
||||
print (" .b_id(levelx_intpend_id[$tmp][2*m+1]),\n");
|
||||
print (" .b_priority(levelx_intpend_w_prior_en[$tmp][2*m+1]),\n");
|
||||
print (" .out_id(levelx_intpend_id_".$next_level."[m]),\n");
|
||||
print (" .out_priority(levelx_intpend_w_prior_en_".$next_level."[m])) ;\n");
|
||||
print (" \n");
|
||||
print (" end\n\n");
|
||||
for (my $l=int($NUM_LEVELS/2)+1; $l<$NUM_LEVELS ; $l++) {
|
||||
$next_level = $l+1;
|
||||
print ("// LEVEL".$l."\n");
|
||||
print ("logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] levelx_intpend_w_prior_en_".$next_level.";\n");
|
||||
print ("logic [TOTAL_INT+2:0] [ID_BITS-1:0] levelx_intpend_id_".$next_level.";\n");
|
||||
print (" for (m=0; m<=(TOTAL_INT)/(2**(".$next_level.")) ; m++) begin : COMPARE$l\n");
|
||||
print (" if ( m == (TOTAL_INT)/(2**(".$next_level."))) begin \n");
|
||||
print (" assign levelx_intpend_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" assign levelx_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" end\n");
|
||||
print (" cmp_and_mux #(\n");
|
||||
print (" .ID_BITS(ID_BITS),\n");
|
||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||
print (" .a_id(levelx_intpend_id_".$l."[2*m]),\n");
|
||||
print (" .a_priority(levelx_intpend_w_prior_en_".$l."[2*m]),\n");
|
||||
print (" .b_id(levelx_intpend_id_".$l."[2*m+1]),\n");
|
||||
print (" .b_priority(levelx_intpend_w_prior_en_".$l."[2*m+1]),\n");
|
||||
print (" .out_id(levelx_intpend_id_".$next_level."[m]),\n");
|
||||
print (" .out_priority(levelx_intpend_w_prior_en_".$next_level."[m])) ;\n");
|
||||
print (" \n");
|
||||
print (" end\n\n");
|
||||
}
|
||||
print ("assign claimid_in[ID_BITS-1:0] = levelx_intpend_id_".$next_level."[0] ; // This is the last level output\n");
|
||||
print ("assign selected_int_priority[INTPRIORITY_BITS-1:0] = levelx_intpend_w_prior_en_".$next_level."[0] ;\n");
|
||||
print ("`else\n");
|
||||
$next_level = 1;
|
||||
print ("// LEVEL0\n");
|
||||
print ("logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_".$next_level.";\n");
|
||||
print ("logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_".$next_level.";\n");
|
||||
print (" for (m=0; m<=(TOTAL_INT)/(2**(".$next_level.")) ; m++) begin : COMPARE0\n");
|
||||
print (" if ( m == (TOTAL_INT)/(2**(".$next_level."))) begin \n");
|
||||
print (" assign level_intpend_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" end\n");
|
||||
print (" cmp_and_mux #(\n");
|
||||
print (" .ID_BITS(ID_BITS),\n");
|
||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||
print (" .a_id(level_intpend_id[0][2*m]),\n");
|
||||
print (" .a_priority(level_intpend_w_prior_en[0][2*m]),\n");
|
||||
print (" .b_id(level_intpend_id[0][2*m+1]),\n");
|
||||
print (" .b_priority(level_intpend_w_prior_en[0][2*m+1]),\n");
|
||||
print (" .out_id(level_intpend_id_".$next_level."[m]),\n");
|
||||
print (" .out_priority(level_intpend_w_prior_en_".$next_level."[m])) ;\n");
|
||||
print (" \n");
|
||||
print (" end\n\n");
|
||||
for (my $l=1; $l<$NUM_LEVELS ; $l++) {
|
||||
$next_level = $l+1;
|
||||
print ("// LEVEL".$l."\n");
|
||||
print ("logic [TOTAL_INT+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en_".$next_level.";\n");
|
||||
print ("logic [TOTAL_INT+2:0] [ID_BITS-1:0] level_intpend_id_".$next_level.";\n");
|
||||
print (" for (m=0; m<=(TOTAL_INT)/(2**(".$next_level.")) ; m++) begin : COMPARE$l\n");
|
||||
print (" if ( m == (TOTAL_INT)/(2**(".$next_level."))) begin \n");
|
||||
print (" assign level_intpend_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||
print (" end\n");
|
||||
print (" cmp_and_mux #(\n");
|
||||
print (" .ID_BITS(ID_BITS),\n");
|
||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||
print (" .a_id(level_intpend_id_".$l."[2*m]),\n");
|
||||
print (" .a_priority(level_intpend_w_prior_en_".$l."[2*m]),\n");
|
||||
print (" .b_id(level_intpend_id_".$l."[2*m+1]),\n");
|
||||
print (" .b_priority(level_intpend_w_prior_en_".$l."[2*m+1]),\n");
|
||||
print (" .out_id(level_intpend_id_".$next_level."[m]),\n");
|
||||
print (" .out_priority(level_intpend_w_prior_en_".$next_level."[m])) ;\n");
|
||||
print (" \n");
|
||||
print (" end\n\n");
|
||||
}
|
||||
print ("assign claimid_in[ID_BITS-1:0] = level_intpend_id_".$next_level."[0] ; // This is the last level output\n");
|
||||
print ("assign selected_int_priority[INTPRIORITY_BITS-1:0] = level_intpend_w_prior_en_".$next_level."[0] ;\n");
|
||||
print ("`endif\n");
|
||||
|
Loading…
Reference in New Issue