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