Branch 1.3
This commit is contained in:
		
							parent
							
								
									7570549cf7
								
							
						
					
					
						commit
						2d26189faf
					
				
							
								
								
									
										62
									
								
								README.md
								
								
								
								
							
							
						
						
									
										62
									
								
								README.md
								
								
								
								
							|  | @ -1,4 +1,4 @@ | |||
| # EL2 SweRV RISC-V Core<sup>TM</sup> 1.2 from Western Digital | ||||
| # EL2 SweRV RISC-V Core<sup>TM</sup> 1.3 from Western Digital | ||||
| 
 | ||||
| This repository contains the SweRV EL2 Core<sup>TM</sup>  design RTL | ||||
| 
 | ||||
|  | @ -24,13 +24,14 @@ Files under the [tools](tools/) directory may be available under a different lic | |||
|     ├── tools                   # Scripts/Makefiles | ||||
|     └── testbench               # (Very) simple testbench | ||||
|         ├── asm                 #   Example assembly files | ||||
|         └── hex                 #   Canned demo hex files | ||||
|         ├── hex                 #   Canned demo hex files | ||||
|         └── tests               #   Example tests | ||||
|   | ||||
| ## Dependencies | ||||
| 
 | ||||
| - Verilator **(4.020 or later)** must be installed on the system if running with verilator | ||||
| - Verilator **(4.102 or later)** must be installed on the system if running with verilator | ||||
| - If adding/removing instructions, espresso must be installed (used by *tools/coredecode*) | ||||
| - RISCV tool chain (based on gcc version 7.3 or higher) must be | ||||
| - RISCV tool chain (based on gcc version 8.3 or higher) must be | ||||
| installed so that it can be used to prepare RISCV binaries to run. | ||||
| 
 | ||||
| ## Quickstart guide | ||||
|  | @ -57,7 +58,15 @@ This will update the **default** snapshot in $RV_ROOT/configs/snapshots/default/ | |||
| Add `-snapshot=dccm64`, for example, if you wish to name your build snapshot *dccm64* and refer to it during the build.   | ||||
| 
 | ||||
| There are 4 predefined target configurations: `default`, `default_ahb`, `typical_pd` and `high_perf` that can be selected via  | ||||
| the `-target=name` option to swerv.config. | ||||
| the `-target=name` option to swerv.config. **Note:** that the `typical_pd` target is what we base our published PPA numbers. It does not include an ICCM. | ||||
| 
 | ||||
| **Building an FPGA speed optimized model:** | ||||
| Use ``-fpga_optimize=1`` option to ``swerv.config`` to build a model that removes clock gating logic from flop model so that the FPGA builds can run at higher speeds. **This is now the default option for | ||||
| targets other than ``typical_pd``.** | ||||
| 
 | ||||
| **Building a Power optimized model (ASIC flows):** | ||||
| Use ``-fpga_optimize=0`` option to ``swerv.config`` to build a model that **enables** clock gating logic into the flop model so that the ASIC flows get a better power footprint. **This is now the default option for | ||||
| target``typical_pd``.** | ||||
| 
 | ||||
| This script derives the following consistent set of include files :   | ||||
| 
 | ||||
|  | @ -70,6 +79,7 @@ This script derives the following consistent set of include files : | |||
|     ├── perl_configs.pl                         # Perl %configs hash for scripting | ||||
|     ├── pic_map_auto.h                          # PIC memory map based on configure size | ||||
|     └── whisper.json                            # JSON file for swerv-iss | ||||
|     └── link.ld                                 # default linker control file | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -107,7 +117,7 @@ execute a short sequence of instructions that writes out "HELLO WORLD" | |||
| to the bus. | ||||
| 
 | ||||
|      | ||||
| The simulation produces output on the screen like:   | ||||
| The simulation produces output on the screen like: u  | ||||
| ``` | ||||
| 
 | ||||
| VerilatorTB: Start of sim | ||||
|  | @ -130,8 +140,6 @@ The simulation generates following files: | |||
|   gtkwave or similar waveform viewers. | ||||
|    | ||||
| You can re-execute simulation using:   | ||||
|      ` ./obj_dir/Vtb_top `   | ||||
| or   | ||||
|     `make -f $RV_ROOT/tools/Makefile verilator` | ||||
| 
 | ||||
| 
 | ||||
|  | @ -143,20 +151,20 @@ The simulation run/build command has following generic form: | |||
| where: | ||||
| ```  | ||||
| <simulator> -  can be 'verilator' (by default) 'irun' - Cadence xrun, 'vcs' - Synopsys VCS, 'vlog' Mentor Questa | ||||
|                if not provided, 'make' cleans work directory, builds verilator executable and runs a test. | ||||
|                'riviera'- Aldec Riviera-PRO. if not provided, 'make' cleans work directory, builds verilator executable and runs a test. | ||||
| debug=1     -  allows VCD generation for verilator and VCS and SHM waves for irun option. | ||||
| <target>    -  predefined CPU configurations 'default' ( by default), 'default_ahb', 'typical_pd', 'high_perf'  | ||||
| TEST        -  allows to run a C (<test>.c) or assembly (<test>.s) test, hello_world is run by default  | ||||
| TEST_DIR    -  alternative to test source directory testbench/asm | ||||
| TEST_DIR    -  alternative to test source directory testbench/asm or testbench/tests | ||||
| <snapshot>  -  run and build executable model of custom CPU configuration, remember to provide 'snapshot' argument  | ||||
|                for runs on custom configurations. | ||||
| 
 | ||||
| CONF_PARAMS -  allows to provide -set options to swerv.conf script to alter predefined EL2 targets parameters | ||||
| ``` | ||||
| Example: | ||||
|       | ||||
|     make -f $RV_ROOT/tools/Makefile verilator TEST=cmark | ||||
| 
 | ||||
| will simulate  testbench/asm/cmark.c program with verilator  | ||||
| will build and simulate  testbench/asm/cmark.c program with verilator  | ||||
| 
 | ||||
| 
 | ||||
| If you want to compile a test only, you can run: | ||||
|  | @ -164,35 +172,43 @@ If you want to compile a test only, you can run: | |||
|     make -f $RV_ROOT/tools/Makefile program.hex TEST=<test> [TEST_DIR=/path/to/dir] | ||||
| 
 | ||||
| 
 | ||||
| The Makefile uses  `$RV_ROOT/testbench/link.ld` file by default to build test executable. | ||||
| The Makefile uses  `snapshot/<target>/link.ld` file, generated by swerv.conf script by default to build test executable. | ||||
| User can provide test specific linker file in form `<test_name>.ld` to build the test executable, | ||||
|  in the same directory with the test source. | ||||
| in the same directory with the test source. | ||||
| 
 | ||||
| User also can create a test specific makefile in form `<test_name>.makefile`, containing building instructions | ||||
| how to create `program.hex` and `data.hex` files used by simulation. The private makefile should be in the same directory | ||||
| as the test source.   | ||||
| *(`program.hex` file is loaded to instruction bus memory slave and `data.hex` file is loaded to LSU bus memory slave and | ||||
| optionally to DCCM at the beginning of simulation)*. | ||||
| how to create `program.hex` file used by simulation. The private makefile should be in the same directory | ||||
| as the test source. See examples in `testbench/asm` directory. | ||||
| 
 | ||||
| Another way to alter test building process is to use `<test_name>.mki` file in test source directory. It may help to select multiple sources | ||||
| to compile and/or alter compilation swiches. See examples in `testbench/tests/` directory | ||||
|   | ||||
| *(`program.hex` file is loaded to instruction and LSU bus memory slaves and | ||||
| optionally to DCCM/ICCM at the beginning of simulation)*. | ||||
| 
 | ||||
| User can build `program.hex` file by any other means and then run simulation with following command: | ||||
| 
 | ||||
|     make -f $RV_ROOT/tools/Makefile <simulator> | ||||
| 
 | ||||
| Note: You may need to delete `program.hex` file from work directory, when run a new test. | ||||
| 
 | ||||
| The  `$RV_ROOT/testbench/asm` directory contains following tests ready to simulate: | ||||
| ``` | ||||
| hello_world      - default tes to run, prints Hello World message to screen and console.log | ||||
| hello_world       - default test program to run, prints Hello World message to screen and console.log | ||||
| hello_world_dccm  - the same as above, but takes the string from preloaded DCCM. | ||||
| hello_world_iccm  - the same as hello_world, but loads the test code to ICCM via LSU to DMA bridge and then executes | ||||
|                   it from there. Runs on EL2 with AXI4 buses only.  | ||||
|                     it from there. Runs on EL2 with AXI4 buses only.  | ||||
| cmark             - coremark benchmark running with code and data in external memories | ||||
| cmark_dccm        - the same as above, running data and stack from DCCM (faster) | ||||
| cmark_iccm        - the same as above with preloaded code to ICCM.  | ||||
| cmark_iccm        - the same as above with preloaded code to ICCM (slower, optimized for size to fit into default ICCM).  | ||||
| 
 | ||||
| dhry              - Run dhrystone. (Scale by 1757 to get DMIPS/MHZ) | ||||
| ``` | ||||
| 
 | ||||
| The `$RV_ROOT/testbench/hex` directory contains precompiled hex files of the tests, ready for simulation in case RISCV SW tools are not installed. | ||||
| 
 | ||||
| **Note**: The testbench has a simple synthesizable bridge that allows you to load the ICCM via load/store instructions. This is only supported for AXI4 builds. | ||||
| 
 | ||||
| **Building an FPGA speed optimized model:**   | ||||
| Use ``-set=fpga_optimize=1`` option to ``swerv.config`` to build a model that is removes clock gating logic from flop model so that the FPGA builds can run a higher speeds. | ||||
| 
 | ||||
| 
 | ||||
| ---- | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -108,14 +108,14 @@ import el2_pkg::*; | |||
| 
 | ||||
|    // general inputs
 | ||||
|    input logic                         clk, | ||||
|    input logic                         rst_l, | ||||
|    input logic                         rst_l,        // This includes both top rst and debug rst
 | ||||
|    input logic                         dbg_rst_l, | ||||
|    input logic                         clk_override, | ||||
|    input logic                         scan_mode | ||||
| ); | ||||
| 
 | ||||
| 
 | ||||
|    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] {IDLE=4'h0, HALTING=4'h1, HALTED=4'h2, CORE_CMD_START=4'h3, CORE_CMD_WAIT=4'h4, SB_CMD_START=4'h5, SB_CMD_SEND=4'h6, SB_CMD_RESP=4'h7, CMD_DONE=4'h8, RESUMING=4'h9} state_t; | ||||
|    typedef enum logic [3:0] {SBIDLE=4'h0, WAIT_RD=4'h1, WAIT_WR=4'h2, CMD_RD=4'h3, CMD_WR=4'h4, CMD_WR_ADDR=4'h5, CMD_WR_DATA=4'h6, RSP_RD=4'h7, RSP_WR=4'h8, DONE=4'h9} sb_state_t; | ||||
| 
 | ||||
|    state_t       dbg_state; | ||||
|  | @ -132,32 +132,43 @@ import el2_pkg::*; | |||
| 
 | ||||
|    // data 0
 | ||||
|    logic [31:0]  data0_din; | ||||
|    logic         data0_reg_wren, data0_reg_wren0, data0_reg_wren1; | ||||
|    logic         data0_reg_wren, data0_reg_wren0, data0_reg_wren1, data0_reg_wren2; | ||||
|    // data 1
 | ||||
|    logic [31:0]  data1_din; | ||||
|    logic         data1_reg_wren, data1_reg_wren0; | ||||
|    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; | ||||
|    logic         abstractcs_error_sel0, abstractcs_error_sel1, abstractcs_error_sel2, abstractcs_error_sel3, abstractcs_error_sel4, abstractcs_error_sel5, abstractcs_error_sel6; | ||||
|    logic         dbg_sb_bus_error; | ||||
|    // abstractauto
 | ||||
|    logic         abstractauto_reg_wren; | ||||
|    logic [1:0]   abstractauto_reg; | ||||
| 
 | ||||
|    // dmstatus
 | ||||
|    logic         dmstatus_resumeack_wren; | ||||
|    logic         dmstatus_resumeack_din; | ||||
|    logic         dmstatus_havereset_wren; | ||||
|    logic         dmstatus_havereset_rst; | ||||
|    logic         dmstatus_haveresetn_wren; | ||||
|    logic         dmstatus_resumeack; | ||||
|    logic         dmstatus_unavail; | ||||
|    logic         dmstatus_running; | ||||
|    logic         dmstatus_halted; | ||||
|    logic         dmstatus_havereset; | ||||
|    logic         dmstatus_havereset, dmstatus_haveresetn; | ||||
| 
 | ||||
|    // dmcontrol
 | ||||
|    logic         resumereq; | ||||
|    logic         dmcontrol_wren, dmcontrol_wren_Q; | ||||
|    // command
 | ||||
|    logic         command_wren; | ||||
|    logic         execute_command_ns, execute_command; | ||||
|    logic         command_wren, command_regno_wren; | ||||
|    logic         command_transfer_din; | ||||
|    logic         command_postexec_din; | ||||
|    logic [31:0]  command_din; | ||||
|    logic [3:0]   dbg_cmd_addr_incr; | ||||
|    logic [31:0]  dbg_cmd_curr_addr; | ||||
|    logic [31:0]  dbg_cmd_next_addr; | ||||
| 
 | ||||
|    // needed to send the read data back for dmi reads
 | ||||
|    logic  [31:0] dmi_reg_rdata_din; | ||||
| 
 | ||||
|  | @ -176,6 +187,7 @@ import el2_pkg::*; | |||
|    logic [2:0]        sbcs_sberror_din; | ||||
|    logic              sbcs_unaligned; | ||||
|    logic              sbcs_illegal_size; | ||||
|    logic [19:15]      sbcs_reg_int; | ||||
| 
 | ||||
|    // data
 | ||||
|    logic              sbdata0_reg_wren0; | ||||
|  | @ -197,6 +209,24 @@ import el2_pkg::*; | |||
|    logic              sbreadondata_access; | ||||
|    logic              sbdata0wr_access; | ||||
| 
 | ||||
|    logic              sb_abmem_cmd_done_in, sb_abmem_data_done_in; | ||||
|    logic              sb_abmem_cmd_done_en, sb_abmem_data_done_en; | ||||
|    logic              sb_abmem_cmd_done, sb_abmem_data_done; | ||||
|    logic [31:0]       abmem_addr; | ||||
|    logic              abmem_addr_in_dccm_region, abmem_addr_in_iccm_region, abmem_addr_in_pic_region; | ||||
|    logic              abmem_addr_core_local; | ||||
|    logic              abmem_addr_external; | ||||
| 
 | ||||
|    logic              sb_cmd_pending, sb_abmem_cmd_pending; | ||||
|    logic              sb_abmem_cmd_write; | ||||
|    logic [2:0]        sb_abmem_cmd_size; | ||||
|    logic [31:0]       sb_abmem_cmd_addr; | ||||
|    logic [31:0]       sb_abmem_cmd_wdata; | ||||
| 
 | ||||
|    logic [2:0]        sb_cmd_size; | ||||
|    logic [31:0]       sb_cmd_addr; | ||||
|    logic [63:0]       sb_cmd_wdata; | ||||
| 
 | ||||
|    logic              sb_bus_cmd_read, sb_bus_cmd_write_addr, sb_bus_cmd_write_data; | ||||
|    logic              sb_bus_rsp_read, sb_bus_rsp_write; | ||||
|    logic              sb_bus_rsp_error; | ||||
|  | @ -208,6 +238,14 @@ import el2_pkg::*; | |||
|    logic [31:0]       sbdata0_reg; | ||||
|    logic [31:0]       sbdata1_reg; | ||||
| 
 | ||||
|    logic              sb_abmem_cmd_arvalid, sb_abmem_cmd_awvalid, sb_abmem_cmd_wvalid; | ||||
|    logic              sb_abmem_read_pend; | ||||
|    logic              sb_cmd_awvalid, sb_cmd_wvalid, sb_cmd_arvalid; | ||||
|    logic              sb_read_pend; | ||||
|    logic [31:0]       sb_axi_addr; | ||||
|    logic [63:0]       sb_axi_wrdata; | ||||
|    logic [2:0]        sb_axi_size; | ||||
| 
 | ||||
|    logic              dbg_dm_rst_l; | ||||
| 
 | ||||
|    //clken
 | ||||
|  | @ -219,10 +257,10 @@ import el2_pkg::*; | |||
| 
 | ||||
|    // 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; | ||||
|    assign dbg_free_clken  = dmi_reg_en | execute_command | (dbg_state != IDLE) | dbg_state_en | dec_tlu_dbg_halted | dec_tlu_mpc_halted_only | dec_tlu_debug_mode | dbg_halt_req | clk_override; | ||||
| 
 | ||||
|    // used for the system bus
 | ||||
|    assign sb_free_clken = dmi_reg_en | sb_state_en | (sb_state != SBIDLE) | clk_override; | ||||
|    assign sb_free_clken = dmi_reg_en | execute_command | sb_state_en | (sb_state != SBIDLE) | clk_override; | ||||
| 
 | ||||
|    rvoclkhdr dbg_free_cgc    (.en(dbg_free_clken), .l1clk(dbg_free_clk), .*); | ||||
|    rvoclkhdr sb_free_cgc     (.en(sb_free_clken), .l1clk(sb_free_clk), .*); | ||||
|  | @ -231,23 +269,25 @@ import el2_pkg::*; | |||
| 
 | ||||
|    // Reset logic
 | ||||
|    assign dbg_dm_rst_l = dbg_rst_l & (dmcontrol_reg[0] | scan_mode); | ||||
|    assign dbg_core_rst_l = ~dmcontrol_reg[1]; | ||||
|    assign dbg_core_rst_l = ~dmcontrol_reg[1] | scan_mode; | ||||
| 
 | ||||
|    // 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[19:15] = {sbcs_reg_int[19], ~sbcs_reg_int[18], sbcs_reg_int[17:15]}; | ||||
|    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_wren = (dmi_reg_addr ==  7'h38) & dmi_reg_en & dmi_reg_wr_en & (sb_state == SBIDLE); | ||||
|    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))); | ||||
|                                          (sbcs_reg[21] & dmi_reg_en & ((dmi_reg_wr_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 #(5) sbcs_misc_reg         (.din({dmi_reg_wdata[19],~dmi_reg_wdata[18],dmi_reg_wdata[17:15]}), | ||||
|                                       .dout(sbcs_reg_int[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]) | | ||||
|  | @ -294,8 +334,9 @@ import el2_pkg::*; | |||
|    // 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[29]  = '0; | ||||
|    assign dmcontrol_reg[29]   = '0; | ||||
|    assign dmcontrol_reg[27:2] = '0; | ||||
|    assign resumereq           = dmcontrol_reg[30] & ~dmcontrol_reg[31] & dmcontrol_wren_Q; | ||||
|    rvdffs #(4) dmcontrolff (.din({dmi_reg_wdata[31:30],dmi_reg_wdata[28],dmi_reg_wdata[1]}), .dout({dmcontrol_reg[31:30], dmcontrol_reg[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(dbg_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)); | ||||
|  | @ -303,6 +344,7 @@ import el2_pkg::*; | |||
|    // 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[31:0] ==  32'h11) & dmi_reg_en;
 | ||||
|    assign dmstatus_reg[31:20] = '0; | ||||
|    assign dmstatus_reg[19:18] = {2{dmstatus_havereset}}; | ||||
|    assign dmstatus_reg[15:14] = '0; | ||||
|  | @ -314,18 +356,18 @@ import el2_pkg::*; | |||
|    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_wren = ((dbg_state == RESUMING) & dec_tlu_resume_ack) | (dmstatus_resumeack & resumereq & dmstatus_halted); | ||||
|    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; | ||||
|    assign dmstatus_haveresetn_wren  = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[28] & dmi_reg_en & dmi_reg_wr_en & dmcontrol_reg[0];   // clear the havereset
 | ||||
|    assign dmstatus_havereset        = ~dmstatus_haveresetn; | ||||
| 
 | ||||
|    assign dmstatus_unavail = dmcontrol_reg[1] | ~rst_l; | ||||
|    assign dmstatus_running = ~(dmstatus_unavail | dmstatus_halted); | ||||
| 
 | ||||
|    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)); | ||||
|    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)); | ||||
|    rvdffs  #(1) dmstatus_haveresetn_reg (.din(1'b1), .dout(dmstatus_haveresetn), .en(dmstatus_haveresetn_wren), .rst_l(rst_l), .clk(dbg_free_clk)); | ||||
| 
 | ||||
|    // haltsum0 register
 | ||||
|    assign haltsum0_reg[31:1] = '0; | ||||
|  | @ -337,54 +379,76 @@ import el2_pkg::*; | |||
|    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) & ~dmstatus_reg[9];  //(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'b010) | ((dmi_reg_wdata[31:24] == 8'h2) && (|data1_reg[1:0])));  // Only word size is allowed
 | ||||
| 
 | ||||
|    assign        abstractcs_error_sel5 = (dmi_reg_addr ==  7'h16) & dmi_reg_en & dmi_reg_wr_en; | ||||
|    assign        abstractcs_error_sel0 = abstractcs_reg[12] & ~(|abstractcs_reg[10:8]) & dmi_reg_en & ((dmi_reg_wr_en & ((dmi_reg_addr == 7'h16) | (dmi_reg_addr == 7'h17)) | (dmi_reg_addr == 7'h18)) | | ||||
|                                                                                                        (dmi_reg_addr == 7'h4) | (dmi_reg_addr == 7'h5)); | ||||
|    assign        abstractcs_error_sel1 = execute_command & ~(|abstractcs_reg[10:8]) & | ||||
|                                          ((~((command_reg[31:24] == 8'b0) | (command_reg[31:24] == 8'h2)))                      |   // Illegal command
 | ||||
|                                           (((command_reg[22:20] == 3'b011) | (command_reg[22])) & (command_reg[31:24] == 8'h2)) |   // Illegal abstract memory size (can't be DW or higher)
 | ||||
|                                           ((command_reg[22:20] != 3'b010) & ((command_reg[31:24] == 8'h0) & command_reg[17]))   |   // Illegal abstract reg size
 | ||||
|                                           ((command_reg[31:24] == 8'h0) & command_reg[18]));                                          //postexec for abstract register access
 | ||||
|    assign        abstractcs_error_sel2 = ((core_dbg_cmd_done & core_dbg_cmd_fail) |                   // exception from core
 | ||||
|                                           (execute_command & (command_reg[31:24] == 8'h0) &           // unimplemented regs
 | ||||
|                                                 (((command_reg[15:12] == 4'h1) & (command_reg[11:5] != 0)) | (command_reg[15:13] != 0)))) & ~(|abstractcs_reg[10:8]); | ||||
|    assign        abstractcs_error_sel3 = execute_command & (dbg_state != HALTED) & ~(|abstractcs_reg[10:8]); | ||||
|    assign        abstractcs_error_sel4 = dbg_sb_bus_error & dbg_bus_clk_en & ~(|abstractcs_reg[10:8]);// sb bus error for abstract memory command
 | ||||
|    assign        abstractcs_error_sel5 = execute_command & (command_reg[31:24] == 8'h2) & ~(|abstractcs_reg[10:8]) & | ||||
|                                          (((command_reg[22:20] == 3'b001) & data1_reg[0]) | ((command_reg[22:20] == 3'b010) & (|data1_reg[1:0])));  //Unaligned address for abstract memory
 | ||||
|    assign        abstractcs_error_sel6 = (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
 | ||||
|    assign        abstractcs_error_din[2:0]  = abstractcs_error_sel0 ? 3'b001 :                  // writing command or abstractcs while a command was executing. Or accessing data0
 | ||||
|                                                  abstractcs_error_sel1 ? 3'b010 :               // writing a illegal command type to cmd field of command
 | ||||
|                                                     abstractcs_error_sel2 ? 3'b011 :            // exception while running command
 | ||||
|                                                        abstractcs_error_sel3 ? 3'b100 :         // writing a comnand when not in the halted state
 | ||||
|                                                           abstractcs_error_sel4 ? 3'b101 :      // Bus error
 | ||||
|                                                              abstractcs_error_sel5 ? 3'b111 :   // unaligned or illegal size abstract memory command
 | ||||
|                                                                 abstractcs_error_sel6 ? (~dmi_reg_wdata[10:8] & abstractcs_reg[10:8]) :   //W1C
 | ||||
|                                                                                         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)); | ||||
| 
 | ||||
|     // abstract auto reg
 | ||||
|    assign abstractauto_reg_wren  = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h18) & ~abstractcs_reg[12]; | ||||
|    rvdffs #(2) dbg_abstractauto_reg (.*, .din(dmi_reg_wdata[1:0]), .dout(abstractauto_reg[1:0]), .en(abstractauto_reg_wren), .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
 | ||||
|    // Size - 2, Bits Not implemented: 23 (aamvirtual), 19-autoincrement, 18-postexec, 17-transfer
 | ||||
|    assign     command_wren = (dmi_reg_addr ==  7'h17) & dmi_reg_en & dmi_reg_wr_en & (dbg_state == HALTED); | ||||
|    assign     command_din[31:0] = {dmi_reg_wdata[31:24],1'b0,dmi_reg_wdata[22:20],3'b0,dmi_reg_wdata[16:0]}; | ||||
|    rvdffe #(32) dmcommand_reg (.*, .din(command_din[31:0]), .dout(command_reg[31:0]), .en(command_wren), .rst_l(dbg_dm_rst_l)); | ||||
|    assign execute_command_ns = command_wren | | ||||
|                                (dmi_reg_en & ~abstractcs_reg[12] & (((dmi_reg_addr == 7'h4) & abstractauto_reg[0]) | ((dmi_reg_addr == 7'h5) & abstractauto_reg[1]))); | ||||
|    assign command_wren = (dmi_reg_addr ==  7'h17) & dmi_reg_en & dmi_reg_wr_en; | ||||
|    assign command_regno_wren = command_wren | ((command_reg[31:24] == 8'h0) & command_reg[19] & (dbg_state == CMD_DONE) & ~(|abstractcs_reg[10:8]));  // aarpostincrement
 | ||||
|    assign command_postexec_din = (dmi_reg_wdata[31:24] == 8'h0) & dmi_reg_wdata[18]; | ||||
|    assign command_transfer_din = (dmi_reg_wdata[31:24] == 8'h0) & dmi_reg_wdata[17]; | ||||
|    assign command_din[31:16] = {dmi_reg_wdata[31:24],1'b0,dmi_reg_wdata[22:19],command_postexec_din,command_transfer_din, dmi_reg_wdata[16]}; | ||||
|    assign command_din[15:0] =  command_wren ? dmi_reg_wdata[15:0] : dbg_cmd_next_addr[15:0]; | ||||
|    rvdff  #(1)  execute_commandff   (.*, .din(execute_command_ns), .dout(execute_command), .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l)); | ||||
|    rvdffe #(16) dmcommand_reg       (.*, .din(command_din[31:16]), .dout(command_reg[31:16]), .en(command_wren), .rst_l(dbg_dm_rst_l)); | ||||
|    rvdffe #(16) dmcommand_regno_reg (.*, .din(command_din[15:0]),  .dout(command_reg[15:0]),  .en(command_regno_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; | ||||
|   // data0 reg
 | ||||
|    assign data0_reg_wren0   = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h4) & (dbg_state == HALTED) & ~abstractcs_reg[12]); | ||||
|    assign data0_reg_wren1   = core_dbg_cmd_done & (dbg_state == CORE_CMD_WAIT) & ~command_reg[16]; | ||||
|    assign data0_reg_wren    = data0_reg_wren0 | data0_reg_wren1 | data0_reg_wren2; | ||||
| 
 | ||||
|    assign data0_din[31:0]   = ({32{data0_reg_wren0}} & dmi_reg_wdata[31:0]) | | ||||
|                               ({32{data0_reg_wren1}} & core_dbg_rddata[31:0]); | ||||
|    assign data0_din[31:0]   = ({32{data0_reg_wren0}} & dmi_reg_wdata[31:0])   | | ||||
|                               ({32{data0_reg_wren1}} & core_dbg_rddata[31:0]) | | ||||
|                               ({32{data0_reg_wren2}} & sb_bus_rdata[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_wren    = data1_reg_wren0; | ||||
|    assign data1_reg_wren0   = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h5) & (dbg_state == HALTED) & ~abstractcs_reg[12]); | ||||
|    assign data1_reg_wren1   = (dbg_state == CMD_DONE) & (command_reg[31:24] == 8'h2) & command_reg[19] & ~(|abstractcs_reg[10:8]);   // aampostincrement
 | ||||
|    assign data1_reg_wren    = data1_reg_wren0 | data1_reg_wren1; | ||||
| 
 | ||||
|    assign data1_din[31:0]   = ({32{data1_reg_wren0}} & dmi_reg_wdata[31:0]); | ||||
|    assign data1_din[31:0]   = ({32{data1_reg_wren0}} & dmi_reg_wdata[31:0]) | | ||||
|                               ({32{data1_reg_wren1}} & dbg_cmd_next_addr[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)); | ||||
| 
 | ||||
|    rvdffs #(1) sb_abmem_cmd_doneff  (.din(sb_abmem_cmd_done_in),  .dout(sb_abmem_cmd_done),  .en(sb_abmem_cmd_done_en),  .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l), .*); | ||||
|    rvdffs #(1) sb_abmem_data_doneff (.din(sb_abmem_data_done_in), .dout(sb_abmem_data_done), .en(sb_abmem_data_done_en), .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l), .*); | ||||
| 
 | ||||
|    // FSM to control the debug mode entry, command send/recieve, and Resume flow.
 | ||||
|    always_comb begin | ||||
|  | @ -392,45 +456,74 @@ import el2_pkg::*; | |||
|       dbg_state_en            = 1'b0; | ||||
|       abstractcs_busy_wren    = 1'b0; | ||||
|       abstractcs_busy_din     = 1'b0; | ||||
|       dbg_halt_req            = dmcontrol_wren_Q & dmcontrol_reg[31] & ~dmcontrol_reg[1];      // single pulse output to the core. Need to drive every time this register is written since core might be halted due to MPC
 | ||||
|       dbg_halt_req            = dmcontrol_wren_Q & dmcontrol_reg[31];      // single pulse output to the core. Need to drive every time this register is written since core might be halted due to MPC
 | ||||
|       dbg_resume_req          = 1'b0;                                      // single pulse output to the core
 | ||||
|       dbg_sb_bus_error        = 1'b0; | ||||
|       data0_reg_wren2         = 1'b0; | ||||
|       sb_abmem_cmd_done_in    = 1'b0; | ||||
|       sb_abmem_data_done_in   = 1'b0; | ||||
|       sb_abmem_cmd_done_en    = 1'b0; | ||||
|       sb_abmem_data_done_en   = 1'b0; | ||||
| 
 | ||||
|        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 H
 | ||||
|                      dbg_halt_req         = dmcontrol_reg[31] & ~dmcontrol_reg[1];                           // only when jtag has written the halt_req bit in the control. Removed debug mode qualification during MPC changes
 | ||||
|                      dbg_state_en         = dmcontrol_reg[31] | dmstatus_reg[9] | dec_tlu_mpc_halted_only;      // when the jtag writes the halt bit in the DM register, OR when the status indicates H
 | ||||
|                      dbg_halt_req         = dmcontrol_reg[31];               // only when jtag has written the halt_req bit in the control. Removed debug mode qualification during MPC changes
 | ||||
|             end | ||||
|             HALTING : begin | ||||
|                      dbg_nxtstate         = dmcontrol_reg[1] ? IDLE : HALTED;                                 // Goto HALTED once the core sends an ACK
 | ||||
|                      dbg_state_en         = dmstatus_reg[9] | dmcontrol_reg[1];                               // core indicates halted
 | ||||
|                      dbg_nxtstate         = HALTED;                                 // Goto HALTED once the core sends an ACK
 | ||||
|                      dbg_state_en         = dmstatus_reg[9] | dec_tlu_mpc_halted_only;     // 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) : | ||||
|                      dbg_nxtstate         = dmstatus_reg[9] ? (resumereq ? RESUMING : (((command_reg[31:24] == 8'h2) & abmem_addr_external) ? SB_CMD_START : CORE_CMD_START)) : | ||||
|                                                                                     (dmcontrol_reg[31] ? HALTING : IDLE);       // This is MPC halted case
 | ||||
|                      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);         // need to be exclusive ???
 | ||||
|                      abstractcs_busy_wren = dbg_state_en & (dbg_nxtstate == CMD_START);                      // write busy when a new command was written by jtag
 | ||||
|                      dbg_state_en         = (dmstatus_reg[9] & resumereq) | execute_command | ~(dmstatus_reg[9] | dec_tlu_mpc_halted_only); | ||||
|                      abstractcs_busy_wren = dbg_state_en & ((dbg_nxtstate == CORE_CMD_START) | (dbg_nxtstate == SB_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         = dmcontrol_reg[1] ? IDLE : (|abstractcs_reg[10:8]) ? CMD_DONE : CMD_WAIT;    // new command sent to the core
 | ||||
|                      dbg_state_en         = dbg_cmd_valid | (|abstractcs_reg[10:8]) | dmcontrol_reg[1]; | ||||
|             CORE_CMD_START: begin | ||||
|                      // Don't execute the command if cmderror or transfer=0 for abstract register access
 | ||||
|                      dbg_nxtstate         = ((|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17])) ? CMD_DONE : CORE_CMD_WAIT;     // new command sent to the core
 | ||||
|                      dbg_state_en         = dbg_cmd_valid | (|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17]); | ||||
|             end | ||||
|             CMD_WAIT: begin | ||||
|                      dbg_nxtstate         = dmcontrol_reg[1] ? IDLE : CMD_DONE; | ||||
|                      dbg_state_en         = core_dbg_cmd_done | dmcontrol_reg[1];                   // go to done state for one cycle after completing current command
 | ||||
|             CORE_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 | ||||
|             SB_CMD_START: begin | ||||
|                      dbg_nxtstate         = (|abstractcs_reg[10:8]) ? CMD_DONE : SB_CMD_SEND; | ||||
|                      dbg_state_en         = (dbg_bus_clk_en & ~sb_cmd_pending) | (|abstractcs_reg[10:8]); | ||||
|             end | ||||
|             SB_CMD_SEND: begin | ||||
|                      sb_abmem_cmd_done_in = 1'b1; | ||||
|                      sb_abmem_data_done_in= 1'b1; | ||||
|                      sb_abmem_cmd_done_en = (sb_bus_cmd_read | sb_bus_cmd_write_addr) & dbg_bus_clk_en; | ||||
|                      sb_abmem_data_done_en= (sb_bus_cmd_read | sb_bus_cmd_write_data) & dbg_bus_clk_en; | ||||
|                      dbg_nxtstate         = SB_CMD_RESP; | ||||
|                      dbg_state_en         = (sb_abmem_cmd_done | sb_abmem_cmd_done_en) & (sb_abmem_data_done | sb_abmem_data_done_en) & dbg_bus_clk_en; | ||||
|             end | ||||
|             SB_CMD_RESP: begin | ||||
|                      dbg_nxtstate         = CMD_DONE; | ||||
|                      dbg_state_en         = (sb_bus_rsp_read | sb_bus_rsp_write) & dbg_bus_clk_en; | ||||
|                      dbg_sb_bus_error     = (sb_bus_rsp_read | sb_bus_rsp_write) & sb_bus_rsp_error & dbg_bus_clk_en; | ||||
|                      data0_reg_wren2      = dbg_state_en & ~sb_abmem_cmd_write & ~dbg_sb_bus_error; | ||||
|             end | ||||
|             CMD_DONE: begin | ||||
|                      dbg_nxtstate         = dmcontrol_reg[1] ? IDLE : HALTED; | ||||
|                      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; | ||||
|                      sb_abmem_cmd_done_in = 1'b0; | ||||
|                      sb_abmem_data_done_in= 1'b0; | ||||
|                      sb_abmem_cmd_done_en = 1'b1; | ||||
|                      sb_abmem_data_done_en= 1'b1; | ||||
|             end | ||||
|             RESUMING : begin | ||||
|                      dbg_nxtstate            = IDLE; | ||||
|                      dbg_state_en            = dmstatus_reg[17] | dmcontrol_reg[1];             // resume ack has been updated in the dmstatus register
 | ||||
|                      dbg_state_en            = dmstatus_reg[17];             // resume ack has been updated in the dmstatus register
 | ||||
|            end | ||||
|            default : begin | ||||
|                      dbg_nxtstate            = IDLE; | ||||
|  | @ -439,16 +532,23 @@ import el2_pkg::*; | |||
|                      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
 | ||||
|                      dbg_sb_bus_error        = 1'b0; | ||||
|                      data0_reg_wren2         = 1'b0; | ||||
|                      sb_abmem_cmd_done_in    = 1'b0; | ||||
|                      sb_abmem_data_done_in   = 1'b0; | ||||
|                      sb_abmem_cmd_done_en    = 1'b0; | ||||
|                      sb_abmem_data_done_en   = 1'b0; | ||||
|           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'h10}} & {2'b0,dmcontrol_reg[29],1'b0,dmcontrol_reg[27:0]})  |  // Read0 to Write only bits
 | ||||
|                                     ({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'h18}} & {30'h0,abstractauto_reg[1: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]) | | ||||
|  | @ -457,19 +557,34 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
|    rvdffs #($bits(state_t)) dbg_state_reg    (.din(dbg_nxtstate), .dout({dbg_state}), .en(dbg_state_en), .rst_l(dbg_dm_rst_l & 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
 | ||||
|    rvdffs #(32)             dmi_rddata_reg   (.din(dmi_reg_rdata_din[31:0]), .dout(dmi_reg_rdata[31:0]), .en(dmi_reg_en), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); | ||||
|    rvdffe #(32)             dmi_rddata_reg   (.din(dmi_reg_rdata_din[31:0]), .dout(dmi_reg_rdata[31:0]), .en(dmi_reg_en), .rst_l(dbg_dm_rst_l), .clk(clk), .*); | ||||
| 
 | ||||
|    assign abmem_addr[31:0]      = data1_reg[31:0]; | ||||
|    assign abmem_addr_core_local = (abmem_addr_in_dccm_region | abmem_addr_in_iccm_region | abmem_addr_in_pic_region); | ||||
|    assign abmem_addr_external   = ~abmem_addr_core_local; | ||||
| 
 | ||||
|    assign abmem_addr_in_dccm_region = (abmem_addr[31:28] == pt.DCCM_REGION) & pt.DCCM_ENABLE; | ||||
|    assign abmem_addr_in_iccm_region = (abmem_addr[31:28] == pt.ICCM_REGION) & pt.ICCM_ENABLE; | ||||
|    assign abmem_addr_in_pic_region  = (abmem_addr[31:28] == pt.PIC_REGION); | ||||
| 
 | ||||
|    // 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]; | ||||
|    assign dbg_cmd_addr[31:0]    = (command_reg[31:24] == 8'h2) ? data1_reg[31:0]  : {20'b0, command_reg[11:0]}; | ||||
|    assign dbg_cmd_wrdata[31:0]  = data0_reg[31:0]; | ||||
|    assign dbg_cmd_valid         = (dbg_state == CORE_CMD_START) & ~((|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17]) | ((command_reg[31:24] == 8'h2) & abmem_addr_external)) & 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]; | ||||
| 
 | ||||
|    assign dbg_cmd_addr_incr[3:0]  = (command_reg[31:24] == 8'h2) ? (4'h1 << sb_abmem_cmd_size[1:0]) : 4'h1; | ||||
|    assign dbg_cmd_curr_addr[31:0] = (command_reg[31:24] == 8'h2) ? data1_reg[31:0]  : {16'b0, command_reg[15:0]}; | ||||
|    assign dbg_cmd_next_addr[31:0] = dbg_cmd_curr_addr[31:0] + {28'h0,dbg_cmd_addr_incr[3:0]}; | ||||
| 
 | ||||
|    // 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); | ||||
|    assign dbg_dma_bubble = ((dbg_state == CORE_CMD_START) & ~(|abstractcs_reg[10:8])) | (dbg_state == CORE_CMD_WAIT); | ||||
| 
 | ||||
|    assign sb_cmd_pending       = (sb_state == CMD_RD) | (sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR) | (sb_state == CMD_WR_DATA) | (sb_state == RSP_RD) | (sb_state == RSP_WR); | ||||
|    assign sb_abmem_cmd_pending = (dbg_state == SB_CMD_START) | (dbg_state == SB_CMD_SEND) | (dbg_state== SB_CMD_RESP); | ||||
| 
 | ||||
| 
 | ||||
|   // system bus FSM
 | ||||
|   always_comb begin | ||||
|  | @ -483,7 +598,7 @@ import el2_pkg::*; | |||
|       case (sb_state) | ||||
|             SBIDLE: begin | ||||
|                      sb_nxtstate            = sbdata0wr_access ? WAIT_WR : WAIT_RD; | ||||
|                      sb_state_en            = sbdata0wr_access | sbreadondata_access | sbreadonaddr_access; | ||||
|                      sb_state_en            = (sbdata0wr_access | sbreadondata_access | sbreadonaddr_access) & ~(|sbcs_reg[14:12]) & ~sbcs_reg[22]; | ||||
|                      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
 | ||||
|  | @ -491,13 +606,13 @@ import el2_pkg::*; | |||
|             end | ||||
|             WAIT_RD: begin | ||||
|                      sb_nxtstate           = (sbcs_unaligned | sbcs_illegal_size) ? DONE : CMD_RD; | ||||
|                      sb_state_en           = dbg_bus_clk_en | sbcs_unaligned | sbcs_illegal_size; | ||||
|                      sb_state_en           = (dbg_bus_clk_en & ~sb_abmem_cmd_pending) | 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 | ||||
|             WAIT_WR: begin | ||||
|                      sb_nxtstate           = (sbcs_unaligned | sbcs_illegal_size) ? DONE : CMD_WR; | ||||
|                      sb_state_en           = dbg_bus_clk_en | sbcs_unaligned | sbcs_illegal_size; | ||||
|                      sb_state_en           = (dbg_bus_clk_en & ~sb_abmem_cmd_pending) | 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 | ||||
|  | @ -534,8 +649,7 @@ import el2_pkg::*; | |||
|                      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
 | ||||
| 
 | ||||
|                      sbaddress0_reg_wren1   = sbcs_reg[16] & (sbcs_reg[14:12] == 3'b0);    // auto increment was set and no error. Update to new address after completing the current command
 | ||||
|             end | ||||
|             default : begin | ||||
|                      sb_nxtstate            = SBIDLE; | ||||
|  | @ -551,6 +665,29 @@ import el2_pkg::*; | |||
| 
 | ||||
|    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)); | ||||
| 
 | ||||
|    assign sb_abmem_cmd_write      = command_reg[16]; | ||||
|    assign sb_abmem_cmd_size[2:0]  = {1'b0, command_reg[21:20]}; | ||||
|    assign sb_abmem_cmd_addr[31:0] = abmem_addr[31:0]; | ||||
|    assign sb_abmem_cmd_wdata[31:0] = data0_reg[31:0]; | ||||
| 
 | ||||
|    assign sb_cmd_size[2:0]   = sbcs_reg[19:17]; | ||||
|    assign sb_cmd_wdata[63:0] = {sbdata1_reg[31:0], sbdata0_reg[31:0]}; | ||||
|    assign sb_cmd_addr[31:0]  = sbaddress0_reg[31:0]; | ||||
| 
 | ||||
|    assign sb_abmem_cmd_awvalid    = (dbg_state == SB_CMD_SEND) & sb_abmem_cmd_write & ~sb_abmem_cmd_done; | ||||
|    assign sb_abmem_cmd_wvalid     = (dbg_state == SB_CMD_SEND) & sb_abmem_cmd_write & ~sb_abmem_data_done; | ||||
|    assign sb_abmem_cmd_arvalid    = (dbg_state == SB_CMD_SEND) & ~sb_abmem_cmd_write & ~sb_abmem_cmd_done & ~sb_abmem_data_done; | ||||
|    assign sb_abmem_read_pend      = (dbg_state == SB_CMD_RESP) & ~sb_abmem_cmd_write; | ||||
| 
 | ||||
|    assign sb_cmd_awvalid     = ((sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR)); | ||||
|    assign sb_cmd_wvalid      = ((sb_state == CMD_WR) | (sb_state == CMD_WR_DATA)); | ||||
|    assign sb_cmd_arvalid     = (sb_state == CMD_RD); | ||||
|    assign sb_read_pend       = (sb_state == RSP_RD); | ||||
| 
 | ||||
|    assign sb_axi_size[2:0]    = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid | sb_abmem_cmd_arvalid | sb_abmem_read_pend) ? sb_abmem_cmd_size[2:0] : sb_cmd_size[2:0]; | ||||
|    assign sb_axi_addr[31:0]   = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid | sb_abmem_cmd_arvalid | sb_abmem_read_pend) ? sb_abmem_cmd_addr[31:0] : sb_cmd_addr[31:0]; | ||||
|    assign sb_axi_wrdata[63:0] = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid) ? {2{sb_abmem_cmd_wdata[31:0]}} : sb_cmd_wdata[63:0]; | ||||
| 
 | ||||
|    // Generic bus response signals
 | ||||
|    assign sb_bus_cmd_read       = sb_axi_arvalid & sb_axi_arready; | ||||
|    assign sb_bus_cmd_write_addr = sb_axi_awvalid & sb_axi_awready; | ||||
|  | @ -561,36 +698,36 @@ import el2_pkg::*; | |||
|    assign sb_bus_rsp_error = (sb_bus_rsp_read & (|(sb_axi_rresp[1:0]))) | (sb_bus_rsp_write & (|(sb_axi_bresp[1:0]))); | ||||
| 
 | ||||
|    // AXI Request signals
 | ||||
|    assign sb_axi_awvalid              = (sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR); | ||||
|    assign sb_axi_awaddr[31:0]         = sbaddress0_reg[31:0]; | ||||
|    assign sb_axi_awvalid              = sb_abmem_cmd_awvalid | sb_cmd_awvalid; | ||||
|    assign sb_axi_awaddr[31:0]         = sb_axi_addr[31:0]; | ||||
|    assign sb_axi_awid[pt.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_awsize[2:0]          = sb_axi_size[2:0]; | ||||
|    assign sb_axi_awprot[2:0]          = 3'b001; | ||||
|    assign sb_axi_awcache[3:0]         = 4'b1111; | ||||
|    assign sb_axi_awregion[3:0]        = sbaddress0_reg[31:28]; | ||||
|    assign sb_axi_awregion[3:0]        = sb_axi_addr[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); | ||||
|    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_wvalid       = sb_abmem_cmd_wvalid | sb_cmd_wvalid; | ||||
|    assign sb_axi_wdata[63:0]  = ({64{(sb_axi_size[2:0] == 3'h0)}} & {8{sb_axi_wrdata[7:0]}}) | | ||||
|                                 ({64{(sb_axi_size[2:0] == 3'h1)}} & {4{sb_axi_wrdata[15:0]}}) | | ||||
|                                 ({64{(sb_axi_size[2:0] == 3'h2)}} & {2{sb_axi_wrdata[31:0]}}) | | ||||
|                                 ({64{(sb_axi_size[2:0] == 3'h3)}} & {sb_axi_wrdata[63:0]}); | ||||
|    assign sb_axi_wstrb[7:0]   = ({8{(sb_axi_size[2:0] == 3'h0)}} & (8'h1 << sb_axi_addr[2:0])) | | ||||
|                                 ({8{(sb_axi_size[2:0] == 3'h1)}} & (8'h3 << {sb_axi_addr[2:1],1'b0})) | | ||||
|                                 ({8{(sb_axi_size[2:0] == 3'h2)}} & (8'hf << {sb_axi_addr[2],2'b0})) | | ||||
|                                 ({8{(sb_axi_size[2:0] == 3'h3)}} & 8'hff); | ||||
|    assign sb_axi_wlast        = '1; | ||||
| 
 | ||||
|    assign sb_axi_arvalid              = (sb_state == CMD_RD); | ||||
|    assign sb_axi_araddr[31:0]         = sbaddress0_reg[31:0]; | ||||
|    assign sb_axi_arvalid              = sb_abmem_cmd_arvalid | sb_cmd_arvalid; | ||||
|    assign sb_axi_araddr[31:0]         = sb_axi_addr[31:0]; | ||||
|    assign sb_axi_arid[pt.SB_BUS_TAG-1:0] = '0; | ||||
|    assign sb_axi_arsize[2:0]          = sbcs_reg[19:17]; | ||||
|    assign sb_axi_arprot[2:0]          = '0; | ||||
|    assign sb_axi_arsize[2:0]          = sb_axi_size[2:0]; | ||||
|    assign sb_axi_arprot[2:0]          = 3'b001; | ||||
|    assign sb_axi_arcache[3:0]         = 4'b0; | ||||
|    assign sb_axi_arregion[3:0]        = sbaddress0_reg[31:28]; | ||||
|    assign sb_axi_arregion[3:0]        = sb_axi_addr[31:28]; | ||||
|    assign sb_axi_arlen[7:0]           = '0; | ||||
|    assign sb_axi_arburst[1:0]         = 2'b01; | ||||
|    assign sb_axi_arqos[3:0]           = '0; | ||||
|  | @ -600,14 +737,17 @@ import el2_pkg::*; | |||
|    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[63:0] >> 8*sbaddress0_reg[2:0]) & 64'hff))       | | ||||
|                                ({64{sbcs_reg[19:17] == 3'h1}} & ((sb_axi_rdata[63:0] >> 16*sbaddress0_reg[2:1]) & 64'hffff))    | | ||||
|                                ({64{sbcs_reg[19:17] == 3'h2}} & ((sb_axi_rdata[63:0] >> 32*sbaddress0_reg[2]) & 64'hffff_ffff)) | | ||||
|                                ({64{sbcs_reg[19:17] == 3'h3}} & sb_axi_rdata[63:0]); | ||||
|    assign sb_bus_rdata[63:0] = ({64{sb_axi_size == 3'h0}} & ((sb_axi_rdata[63:0] >>  8*sb_axi_addr[2:0]) & 64'hff))       | | ||||
|                                ({64{sb_axi_size == 3'h1}} & ((sb_axi_rdata[63:0] >> 16*sb_axi_addr[2:1]) & 64'hffff))    | | ||||
|                                ({64{sb_axi_size == 3'h2}} & ((sb_axi_rdata[63:0] >> 32*sb_axi_addr[2]) & 64'hffff_ffff)) | | ||||
|                                ({64{sb_axi_size == 3'h3}} & sb_axi_rdata[63:0]); | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_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)); | ||||
| 
 | ||||
|    assert_b2b_haltreq: assert property (@(posedge clk) disable iff (~(rst_l)) (##1 dbg_halt_req |=> ~dbg_halt_req));  // One cycle delay to fix weird issue around reset
 | ||||
|    assert_halt_resume_onehot: assert #0 ($onehot0({dbg_halt_req, dbg_resume_req})); | ||||
| `endif | ||||
| endmodule | ||||
|  |  | |||
|  | @ -209,6 +209,7 @@ csr[ csr_mpmc      ] = {  csr_mpmc      } | |||
| csr[ csr_mcpc      ] = {  csr_mcpc presync postsync } | ||||
| csr[ csr_meicidpl  ] = {  csr_meicidpl  } | ||||
| csr[ csr_mcgc      ] = {  csr_mcgc      } | ||||
| csr[ csr_mcountinhibit] = {  csr_mcountinhibit presync postsync } | ||||
| csr[ csr_mfdc      ] = {  csr_mfdc presync postsync } | ||||
| csr[ csr_dcsr      ] = {  csr_dcsr      } | ||||
| csr[ csr_dpc       ] = {  csr_dpc       } | ||||
|  |  | |||
|  | @ -1,6 +1,146 @@ | |||
| 
 | ||||
| .definition | ||||
| 
 | ||||
| clz       =  [011000000000.....001.....0010011] | ||||
| ctz       =  [011000000001.....001.....0010011] | ||||
| pcnt      =  [011000000010.....001.....0010011] | ||||
| sext_b    =  [011000000100.....001.....0010011] | ||||
| sext_h    =  [011000000101.....001.....0010011] | ||||
| slo       =  [0010000..........001.....0110011] | ||||
| sro       =  [0010000..........101.....0110011] | ||||
| sloi      =  [0010000..........001.....0010011] | ||||
| sroi      =  [0010000..........101.....0010011] | ||||
| 
 | ||||
| min       =  [0000101..........100.....0110011] | ||||
| max       =  [0000101..........101.....0110011] | ||||
| minu      =  [0000101..........110.....0110011] | ||||
| maxu      =  [0000101..........111.....0110011] | ||||
| 
 | ||||
| andn      =  [0100000..........111.....0110011] | ||||
| orn       =  [0100000..........110.....0110011] | ||||
| xnor      =  [0100000..........100.....0110011] | ||||
| pack      =  [0000100..........100.....0110011] | ||||
| packu     =  [0100100..........100.....0110011] | ||||
| packh     =  [0000100..........111.....0110011] | ||||
| rol       =  [0110000..........001.....0110011] | ||||
| ror       =  [0110000..........101.....0110011] | ||||
| rori      =  [0110000..........101.....0010011] | ||||
| 
 | ||||
| sh1add    =  [0010000..........010.....0110011] | ||||
| sh2add    =  [0010000..........100.....0110011] | ||||
| sh3add    =  [0010000..........110.....0110011] | ||||
| 
 | ||||
| sbset     =  [0010100..........001.....0110011] | ||||
| sbclr     =  [0100100..........001.....0110011] | ||||
| sbinv     =  [0110100..........001.....0110011] | ||||
| sbext     =  [0100100..........101.....0110011] | ||||
| 
 | ||||
| sbseti    =  [0010100..........001.....0010011] | ||||
| sbclri    =  [0100100..........001.....0010011] | ||||
| sbinvi    =  [0110100..........001.....0010011] | ||||
| sbexti    =  [0100100..........101.....0010011] | ||||
| 
 | ||||
| grev      =  [0110100..........101.....0110011] | ||||
| #grevi    =  [01101............101.....0010011] | ||||
| grevi0   =   [011010000000.....101.....0010011] | ||||
| grevi1   =   [011010000001.....101.....0010011] | ||||
| grevi2   =   [011010000010.....101.....0010011] | ||||
| grevi3   =   [011010000011.....101.....0010011] | ||||
| grevi4   =   [011010000100.....101.....0010011] | ||||
| grevi5   =   [011010000101.....101.....0010011] | ||||
| grevi6   =   [011010000110.....101.....0010011] | ||||
| grevi7   =   [011010000111.....101.....0010011] | ||||
| grevi8   =   [011010001000.....101.....0010011] | ||||
| grevi9   =   [011010001001.....101.....0010011] | ||||
| grevi10   =  [011010001010.....101.....0010011] | ||||
| grevi11   =  [011010001011.....101.....0010011] | ||||
| grevi12   =  [011010001100.....101.....0010011] | ||||
| grevi13   =  [011010001101.....101.....0010011] | ||||
| grevi14   =  [011010001110.....101.....0010011] | ||||
| grevi15   =  [011010001111.....101.....0010011] | ||||
| grevi16   =  [011010010000.....101.....0010011] | ||||
| grevi17   =  [011010010001.....101.....0010011] | ||||
| grevi18   =  [011010010010.....101.....0010011] | ||||
| grevi19   =  [011010010011.....101.....0010011] | ||||
| grevi20   =  [011010010100.....101.....0010011] | ||||
| grevi21   =  [011010010101.....101.....0010011] | ||||
| grevi22   =  [011010010110.....101.....0010011] | ||||
| grevi23   =  [011010010111.....101.....0010011] | ||||
| #grevi24  =  [011010011000.....101.....0010011]    # REV8 | ||||
| rev8      =  [011010011000.....101.....0010011] | ||||
| grevi25   =  [011010011001.....101.....0010011] | ||||
| grevi26   =  [011010011010.....101.....0010011] | ||||
| grevi27   =  [011010011011.....101.....0010011] | ||||
| grevi28   =  [011010011100.....101.....0010011] | ||||
| grevi29   =  [011010011101.....101.....0010011] | ||||
| grevi30   =  [011010011110.....101.....0010011] | ||||
| #grevi31  =  [011010011111.....101.....0010011]    # REV | ||||
| rev       =  [011010011111.....101.....0010011] | ||||
| 
 | ||||
| gorc      =  [0010100..........101.....0110011] | ||||
| #gorci    =  [00101............101.....0010011] | ||||
| gorci0    =  [001010000000.....101.....0010011] | ||||
| gorci1    =  [001010000001.....101.....0010011] | ||||
| gorci2    =  [001010000010.....101.....0010011] | ||||
| gorci3    =  [001010000011.....101.....0010011] | ||||
| gorci4    =  [001010000100.....101.....0010011] | ||||
| gorci5    =  [001010000101.....101.....0010011] | ||||
| gorci6    =  [001010000110.....101.....0010011] | ||||
| #gorci7   =  [001010000111.....101.....0010011]    # ORC_B | ||||
| orc_b     =  [001010000111.....101.....0010011] | ||||
| gorci8    =  [001010001000.....101.....0010011] | ||||
| gorci9    =  [001010001001.....101.....0010011] | ||||
| gorci10   =  [001010001010.....101.....0010011] | ||||
| gorci11   =  [001010001011.....101.....0010011] | ||||
| gorci12   =  [001010001100.....101.....0010011] | ||||
| gorci13   =  [001010001101.....101.....0010011] | ||||
| gorci14   =  [001010001110.....101.....0010011] | ||||
| gorci15   =  [001010001111.....101.....0010011] | ||||
| #gorci16  =  [001010010000.....101.....0010011]    # ORC16 | ||||
| orc16     =  [001010010000.....101.....0010011] | ||||
| gorci17   =  [001010010001.....101.....0010011] | ||||
| gorci18   =  [001010010010.....101.....0010011] | ||||
| gorci19   =  [001010010011.....101.....0010011] | ||||
| gorci20   =  [001010010100.....101.....0010011] | ||||
| gorci21   =  [001010010101.....101.....0010011] | ||||
| gorci22   =  [001010010110.....101.....0010011] | ||||
| gorci23   =  [001010010111.....101.....0010011] | ||||
| gorci24   =  [001010011000.....101.....0010011] | ||||
| gorci25   =  [001010011001.....101.....0010011] | ||||
| gorci26   =  [001010011010.....101.....0010011] | ||||
| gorci27   =  [001010011011.....101.....0010011] | ||||
| gorci28   =  [001010011100.....101.....0010011] | ||||
| gorci29   =  [001010011101.....101.....0010011] | ||||
| gorci30   =  [001010011110.....101.....0010011] | ||||
| gorci31   =  [001010011111.....101.....0010011] | ||||
| 
 | ||||
| 
 | ||||
| shfl      =  [0000100..........001.....0110011] | ||||
| shfli     =  [00001000.........001.....0010011] | ||||
| 
 | ||||
| unshfl    =  [0000100..........101.....0110011] | ||||
| unshfli   =  [00001000.........101.....0010011] | ||||
| 
 | ||||
| bdep      =  [0100100..........110.....0110011] | ||||
| bext      =  [0000100..........110.....0110011] | ||||
| 
 | ||||
| clmul     =  [0000101..........001.....0110011] | ||||
| clmulr    =  [0000101..........010.....0110011] | ||||
| clmulh    =  [0000101..........011.....0110011] | ||||
| 
 | ||||
| crc32_b   =  [011000010000.....001.....0010011] | ||||
| crc32_h   =  [011000010001.....001.....0010011] | ||||
| crc32_w   =  [011000010010.....001.....0010011] | ||||
| crc32c_b  =  [011000011000.....001.....0010011] | ||||
| crc32c_h  =  [011000011001.....001.....0010011] | ||||
| crc32c_w  =  [011000011010.....001.....0010011] | ||||
| 
 | ||||
| bfp       =  [0100100..........111.....0110011] | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| add       =  [0000000..........000.....0110011] | ||||
| addi      =  [.................000.....0010011] | ||||
| 
 | ||||
|  | @ -206,20 +346,138 @@ rv32i = { | |||
|       rem | ||||
|       fence | ||||
|       fence_i | ||||
|       clz | ||||
|       ctz | ||||
|       pcnt | ||||
|       sext_b | ||||
|       sext_h | ||||
|       slo | ||||
|       sro | ||||
|       min | ||||
|       max | ||||
|       pack | ||||
|       packu | ||||
|       packh | ||||
|       rol | ||||
|       ror | ||||
|       zbb | ||||
|       sbset | ||||
|       sbclr | ||||
|       sbinv | ||||
|       sbext | ||||
|       zbs | ||||
|       bext | ||||
|       bdep | ||||
|       zbe | ||||
|       clmul | ||||
|       clmulh | ||||
|       clmulr | ||||
|       zbc | ||||
|       grev | ||||
|       gorc | ||||
|       shfl | ||||
|       unshfl | ||||
|       zbp | ||||
|       crc32_b | ||||
|       crc32_h | ||||
|       crc32_w | ||||
|       crc32c_b | ||||
|       crc32c_h | ||||
|       crc32c_w | ||||
|       zbr | ||||
|       bfp | ||||
|       zbf | ||||
|       sh1add | ||||
|       sh2add | ||||
|       sh3add | ||||
|       zba | ||||
|       pm_alu | ||||
| } | ||||
| 
 | ||||
| .decode | ||||
| 
 | ||||
| rv32i[clz]       =  { alu zbb     rs1     rd                       clz   } | ||||
| rv32i[ctz]       =  { alu zbb     rs1     rd                       ctz   } | ||||
| rv32i[pcnt]      =  { alu zbb     rs1     rd                       pcnt  } | ||||
| rv32i[sext_b]    =  { alu zbb     rs1     rd                       sext_b} | ||||
| rv32i[sext_h]    =  { alu zbb     rs1     rd                       sext_h} | ||||
| rv32i[slo]       =  { alu     zbp rs1 rs2 rd                       slo   } | ||||
| rv32i[sro]       =  { alu     zbp rs1 rs2 rd                       sro   } | ||||
| rv32i[sloi]      =  { alu     zbp rs1     rd         shimm5        slo   } | ||||
| rv32i[sroi]      =  { alu     zbp rs1     rd         shimm5        sro   } | ||||
| rv32i[min]       =  { alu zbb     rs1 rs2 rd                sub    min   } | ||||
| rv32i[max]       =  { alu zbb     rs1 rs2 rd                sub    max   } | ||||
| rv32i[minu]      =  { alu zbb     rs1 rs2 rd  unsign        sub    min   } | ||||
| rv32i[maxu]      =  { alu zbb     rs1 rs2 rd  unsign        sub    max   } | ||||
| rv32i[andn]      =  { alu zbb zbp rs1 rs2 rd                       land  } | ||||
| rv32i[orn]       =  { alu zbb zbp rs1 rs2 rd                       lor   } | ||||
| rv32i[xnor]      =  { alu zbb zbp rs1 rs2 rd                       lxor  } | ||||
| rv32i[pack]      =  { alu zbb zbp rs1 rs2 rd                       pack  } | ||||
| rv32i[packu]     =  { alu zbb zbp rs1 rs2 rd                       packu } | ||||
| rv32i[packh]     =  { alu zbb zbp rs1 rs2 rd                       packh } | ||||
| rv32i[rol]       =  { alu zbb zbp rs1 rs2 rd                       rol   } | ||||
| rv32i[ror]       =  { alu zbb zbp rs1 rs2 rd                       ror   } | ||||
| rv32i[rori]      =  { alu zbb zbp rs1     rd         shimm5        ror   } | ||||
| rv32i[sbset]     =  { alu zbs     rs1 rs2 rd                       sbset } | ||||
| rv32i[sbclr]     =  { alu zbs     rs1 rs2 rd                       sbclr } | ||||
| rv32i[sbinv]     =  { alu zbs     rs1 rs2 rd                       sbinv } | ||||
| rv32i[sbext]     =  { alu zbs     rs1 rs2 rd                       sbext } | ||||
| rv32i[sbseti]    =  { alu zbs     rs1     rd         shimm5        sbset } | ||||
| rv32i[sbclri]    =  { alu zbs     rs1     rd         shimm5        sbclr } | ||||
| rv32i[sbinvi]    =  { alu zbs     rs1     rd         shimm5        sbinv } | ||||
| rv32i[sbexti]    =  { alu zbs     rs1     rd         shimm5        sbext } | ||||
| rv32i[sh1add]    =  { alu zba     rs1 rs2 rd                       sh1add} | ||||
| rv32i[sh2add]    =  { alu zba     rs1 rs2 rd                       sh2add} | ||||
| rv32i[sh3add]    =  { alu zba     rs1 rs2 rd                       sh3add} | ||||
| 
 | ||||
| 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[bext]      =  { mul zbe     rs1 rs2 rd                       bext  } | ||||
| rv32i[bdep]      =  { mul zbe     rs1 rs2 rd                       bdep  } | ||||
| rv32i[clmul]     =  { mul zbc     rs1 rs2 rd                       clmul } | ||||
| rv32i[clmulh]    =  { mul zbc     rs1 rs2 rd                       clmulh} | ||||
| rv32i[clmulr]    =  { mul zbc     rs1 rs2 rd                       clmulr} | ||||
| 
 | ||||
| rv32i[div]       =  { div rs1 rs2 rd            } | ||||
| rv32i[divu]      =  { div rs1 rs2 rd unsign     } | ||||
| rv32i[rem]       =  { div rs1 rs2 rd         rem} | ||||
| rv32i[remu]      =  { div rs1 rs2 rd unsign  rem} | ||||
| rv32i[crc32_b]   =  { mul zbr     rs1     rd                       crc32_b} | ||||
| rv32i[crc32_h]   =  { mul zbr     rs1     rd                       crc32_h} | ||||
| rv32i[crc32_w]   =  { mul zbr     rs1     rd                       crc32_w} | ||||
| rv32i[crc32c_b]  =  { mul zbr     rs1     rd                       crc32c_b} | ||||
| rv32i[crc32c_h]  =  { mul zbr     rs1     rd                       crc32c_h} | ||||
| rv32i[crc32c_w]  =  { mul zbr     rs1     rd                       crc32c_w} | ||||
| 
 | ||||
| rv32i[bfp]       =  { mul zbf     rs1 rs2 rd                       bfp   } | ||||
| 
 | ||||
| rv32i[grev]          =  { mul     zbp rs1 rs2 rd                       grev  } | ||||
| 
 | ||||
| rv32i[grevi{0-23}]   =  { mul     zbp rs1     rd         shimm5        grev  } | ||||
| rv32i[grevi{25-30}]  =  { mul     zbp rs1     rd         shimm5        grev  } | ||||
| 
 | ||||
| rv32i[rev8]          =  { alu zbb zbp rs1     rd         shimm5        grev  } # grevi24 | ||||
| rv32i[rev]           =  { alu zbb zbp rs1     rd         shimm5        grev  } # grevi31 | ||||
| 
 | ||||
| rv32i[gorc]          =  { mul     zbp rs1 rs2 rd                       gorc  } | ||||
| 
 | ||||
| rv32i[gorci{0-6}]    =  { mul     zbp rs1     rd         shimm5        gorc  } | ||||
| rv32i[gorci{8-15}]   =  { mul     zbp rs1     rd         shimm5        gorc  } | ||||
| rv32i[gorci{17-31}]  =  { mul     zbp rs1     rd         shimm5        gorc  } | ||||
| 
 | ||||
| rv32i[orc_b]         =  { alu zbb zbp rs1     rd         shimm5        gorc  }  # gorci7 | ||||
| rv32i[orc16]         =  { alu zbb zbp rs1     rd         shimm5        gorc  }  # gorci16 | ||||
| 
 | ||||
| 
 | ||||
| rv32i[shfl]      =  { mul     zbp rs1 rs2 rd                       shfl  } | ||||
| rv32i[shfli]     =  { mul     zbp rs1     rd         shimm5        shfl  } | ||||
| 
 | ||||
| rv32i[unshfl]    =  { mul     zbp rs1 rs2 rd                       unshfl} | ||||
| rv32i[unshfli]   =  { mul     zbp rs1     rd         shimm5        unshfl} | ||||
| 
 | ||||
| 
 | ||||
| rv32i[div]       =  { div rs1 rs2 rd           } | ||||
| rv32i[divu]      =  { div rs1 rs2 rd unsign    } | ||||
| rv32i[rem]       =  { div rs1 rs2 rd        rem} | ||||
| rv32i[remu]      =  { div rs1 rs2 rd unsign rem} | ||||
| 
 | ||||
| rv32i[add]       =  { alu rs1 rs2   rd add pm_alu } | ||||
| rv32i[addi]      =  { alu rs1 imm12 rd add pm_alu } | ||||
|  | @ -321,3 +579,4 @@ rv32i[csrwi]       =         { alu rd     csr_write csr_imm   } | |||
| 
 | ||||
| 
 | ||||
| .end | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -33,18 +33,20 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
|   ( | ||||
|    input logic clk, | ||||
|    input logic free_clk, | ||||
|    input logic active_clk, | ||||
|    input logic clk,                          // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic active_clk,                   // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic free_clk,                     // Clock always.                  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic free_l2clk,                   // Clock always.                  Through one clock header.  For flops with    second header built in.
 | ||||
| 
 | ||||
|    input logic lsu_fastint_stall_any,   // needed by lsu for 2nd pass of dma with ecc correction, stall next cycle
 | ||||
|    input logic lsu_fastint_stall_any,        // needed by lsu for 2nd pass of dma with ecc correction, stall next cycle
 | ||||
| 
 | ||||
| // fast interrupt
 | ||||
|    output logic dec_extint_stall, | ||||
|    output logic dec_extint_stall,            // Stall on external interrupt
 | ||||
| 
 | ||||
|    output logic dec_i0_decode_d, | ||||
|    output logic dec_i0_decode_d,             // Valid instruction at D-stage and not blocked
 | ||||
|    output logic dec_pause_state_cg,          // to top for active state clock gating
 | ||||
| 
 | ||||
|    output logic dec_tlu_core_empty, | ||||
| 
 | ||||
|    input logic rst_l,                        // reset, active low
 | ||||
|    input logic [31:1] rst_vec,               // reset vector, from core pins
 | ||||
| 
 | ||||
|  | @ -59,44 +61,44 @@ import el2_pkg::*; | |||
|    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
 | ||||
| 
 | ||||
|    input logic [31:4] core_id, // CORE ID
 | ||||
|    //
 | ||||
|    // 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 [31:4] core_id,               // CORE ID
 | ||||
| 
 | ||||
|     input logic       exu_pmu_i0_br_misp,     // slot 0 branch misp
 | ||||
|    // 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       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                                 lsu_nonblock_load_valid_m,      // valid nonblock load at m
 | ||||
|    input logic                                lsu_nonblock_load_valid_m,      // valid nonblock load at m
 | ||||
|    input logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0]  lsu_nonblock_load_tag_m,        // -> corresponding tag
 | ||||
|    input logic                                 lsu_nonblock_load_inv_r,        // invalidate request for nonblock load r
 | ||||
|    input logic                                lsu_nonblock_load_inv_r,        // invalidate request for nonblock load r
 | ||||
|    input logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0]  lsu_nonblock_load_inv_tag_r,    // -> 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 [pt.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_nonblock_load_data_valid,   // valid nonblock load data back
 | ||||
|    input logic                                lsu_nonblock_load_data_error,   // nonblock load bus error
 | ||||
|    input logic [pt.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_m, // D side load or store misaligned
 | ||||
|    input logic       lsu_pmu_load_external_m, // D side bus load
 | ||||
|    input logic       lsu_pmu_store_external_m, // D side bus store
 | ||||
|    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_m,       // D side load or store misaligned
 | ||||
|    input logic       lsu_pmu_load_external_m,    // D side bus load
 | ||||
|    input logic       lsu_pmu_store_external_m,   // D side bus store
 | ||||
|    input logic       dma_pmu_dccm_read,          // DMA DCCM read
 | ||||
|    input logic       dma_pmu_dccm_write,         // DMA DCCM write
 | ||||
|    input logic       dma_pmu_any_read,           // DMA read
 | ||||
|    input logic       dma_pmu_any_write,          // DMA write
 | ||||
| 
 | ||||
|    input logic [31:1] lsu_fir_addr, // Fast int address
 | ||||
|    input logic [1:0] lsu_fir_error, // Fast int lookup error
 | ||||
|    input logic [31:1] lsu_fir_addr,          // Fast int address
 | ||||
|    input logic [1:0] lsu_fir_error,          // Fast int lookup error
 | ||||
| 
 | ||||
|    input logic       ifu_pmu_instr_aligned,  // aligned instructions
 | ||||
|    input logic       ifu_pmu_fetch_stall,    // fetch unit stalled
 | ||||
|  | @ -110,28 +112,29 @@ import el2_pkg::*; | |||
|    input logic       ifu_iccm_rd_ecc_single_err, // ICCM single bit error
 | ||||
| 
 | ||||
|    input logic [3:0]  lsu_trigger_match_m, | ||||
|    input logic        dbg_cmd_valid,   // debugger abstract command valid
 | ||||
|    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        dbg_cmd_valid,         // debugger abstract command valid
 | ||||
|    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 [1:0]  ifu_i0_icaf_type, | ||||
|    input logic        ifu_i0_icaf,           // icache access fault
 | ||||
|    input logic [1:0]  ifu_i0_icaf_type,      // icache access fault type
 | ||||
| 
 | ||||
|    input logic   ifu_i0_icaf_f1,       // i0 has access fault on second fetch group
 | ||||
|    input logic   ifu_i0_dbecc,         // icache/iccm double-bit error
 | ||||
|    input logic   ifu_i0_icaf_second,         // i0 has access fault on second 2B of 4B inst
 | ||||
|    input logic   ifu_i0_dbecc,               // icache/iccm double-bit error
 | ||||
| 
 | ||||
|    input logic lsu_idle_any,      // lsu idle for halting
 | ||||
|    input logic lsu_idle_any,                 // lsu idle for halting
 | ||||
| 
 | ||||
|    input el2_br_pkt_t i0_brp,              // branch packet
 | ||||
|    input el2_br_pkt_t i0_brp,                                  // branch packet
 | ||||
|    input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index, // BP index
 | ||||
|    input logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr, // BP FGHR
 | ||||
|    input logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag, // BP tag
 | ||||
|    input logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr,            // BP FGHR
 | ||||
|    input logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag,           // BP tag
 | ||||
|    input logic [$clog2(pt.BTB_SIZE)-1:0] ifu_i0_fa_index,          // Fully associt btb index
 | ||||
| 
 | ||||
|    input    el2_lsu_error_pkt_t lsu_error_pkt_r, // LSU exception/error packet
 | ||||
|    input logic         lsu_single_ecc_error_incr, // LSU inc SB error counter
 | ||||
|    input el2_lsu_error_pkt_t lsu_error_pkt_r,         // LSU exception/error packet
 | ||||
|    input logic         lsu_single_ecc_error_incr,      // LSU inc SB error counter
 | ||||
| 
 | ||||
|    input logic         lsu_imprecise_error_load_any,   // LSU imprecise load bus error
 | ||||
|    input logic         lsu_imprecise_error_store_any,  // LSU imprecise store bus error
 | ||||
|  | @ -178,7 +181,7 @@ import el2_pkg::*; | |||
| 
 | ||||
|    input logic [70:0] ifu_ic_debug_rd_data,           // diagnostic icache read data
 | ||||
|    input logic ifu_ic_debug_rd_data_valid,            // diagnostic icache read data valid
 | ||||
|    output el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt,      // packet of DICAWICS, DICAD0/1, DICAGO info for icache diagnostics
 | ||||
|    output el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt, // packet of DICAWICS, DICAD0/1, DICAGO info for icache diagnostics
 | ||||
| 
 | ||||
| 
 | ||||
| // Debug start
 | ||||
|  | @ -189,11 +192,11 @@ import el2_pkg::*; | |||
|    output logic dec_tlu_dbg_halted,          // Core is halted and ready for debug command
 | ||||
|    output logic dec_tlu_debug_mode,          // Core is in debug mode
 | ||||
|    output logic dec_tlu_resume_ack,          // Resume acknowledge
 | ||||
|    output logic dec_tlu_flush_noredir_r,    // 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_flush_leak_one_r,   // single step
 | ||||
|    output logic dec_tlu_flush_err_r,        // iside perr/ecc rfpc
 | ||||
|    output logic [31:2] dec_tlu_meihap, // Fast ext int base
 | ||||
|    output logic dec_tlu_flush_noredir_r,     // 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_flush_leak_one_r,    // single step
 | ||||
|    output logic dec_tlu_flush_err_r,         // iside perr/ecc rfpc
 | ||||
|    output logic [31:2] dec_tlu_meihap,       // Fast ext int base
 | ||||
| 
 | ||||
|    output logic dec_debug_wdata_rs1_d,       // insert debug write data into rs1 at decode
 | ||||
| 
 | ||||
|  | @ -204,15 +207,17 @@ import el2_pkg::*; | |||
| 
 | ||||
|    output el2_trigger_pkt_t  [3:0] trigger_pkt_any, // info needed by debug trigger blocks
 | ||||
| 
 | ||||
|    output logic dec_tlu_force_halt, // halt has been forced
 | ||||
|    output logic dec_tlu_force_halt,          // halt has been forced
 | ||||
| // Debug end
 | ||||
|    // branch info from pipe0 for errors or counter updates
 | ||||
|    input logic [1:0]  exu_i0_br_hist_r,                              // history
 | ||||
|    input logic        exu_i0_br_error_r,                             // error
 | ||||
|    input logic        exu_i0_br_start_error_r,                       // start error
 | ||||
|    input logic        exu_i0_br_valid_r,                             // valid
 | ||||
|    input logic        exu_i0_br_mp_r,                                // mispredict
 | ||||
|    input logic        exu_i0_br_middle_r,                            // middle of bank
 | ||||
|    input logic [1:0]  exu_i0_br_hist_r,             // history
 | ||||
|    input logic        exu_i0_br_error_r,            // error
 | ||||
|    input logic        exu_i0_br_start_error_r,      // start error
 | ||||
|    input logic        exu_i0_br_valid_r,            // valid
 | ||||
|    input logic        exu_i0_br_mp_r,               // mispredict
 | ||||
|    input logic        exu_i0_br_middle_r,           // middle of bank
 | ||||
| 
 | ||||
|    // branch info from pipe1 for errors or counter updates
 | ||||
| 
 | ||||
|    input logic             exu_i0_br_way_r,         // way hit or repl
 | ||||
| 
 | ||||
|  | @ -224,61 +229,65 @@ import el2_pkg::*; | |||
|    output logic [31:0] dec_i0_immed_d,              // immediate data
 | ||||
|    output logic [12:1] dec_i0_br_immed_d,           // br immediate data
 | ||||
| 
 | ||||
|    output        el2_alu_pkt_t i0_ap,                   // alu packet
 | ||||
|    output        el2_alu_pkt_t i0_ap,              // alu packet
 | ||||
| 
 | ||||
|    output logic          dec_i0_alu_decode_d,       // schedule on D-stage alu
 | ||||
|    output logic          dec_i0_branch_d,           // Branch in D-stage
 | ||||
| 
 | ||||
|    output logic          dec_i0_select_pc_d,        // select pc onto rs1 for jal's
 | ||||
| 
 | ||||
|    output logic [31:1]  dec_i0_pc_d,                // pc's at decode
 | ||||
|    output logic [1:0]   dec_i0_rs1_bypass_en_d,     // rs1 bypass enable
 | ||||
|    output logic [1:0]   dec_i0_rs2_bypass_en_d,     // rs2 bypass enable
 | ||||
|    output logic [3:0]   dec_i0_rs1_bypass_en_d,     // rs1 bypass enable
 | ||||
|    output logic [3:0]   dec_i0_rs2_bypass_en_d,     // rs2 bypass enable
 | ||||
| 
 | ||||
|    output logic [31:0]  dec_i0_rs1_bypass_data_d,   // rs1 bypass data
 | ||||
|    output logic [31:0]  dec_i0_rs2_bypass_data_d,   // rs2 bypass data
 | ||||
|    output logic [31:0]  dec_i0_result_r,            // Result R-stage
 | ||||
| 
 | ||||
|    output el2_lsu_pkt_t    lsu_p,                      // lsu packet
 | ||||
|    output el2_mul_pkt_t    mul_p,                      // mul packet
 | ||||
|    output el2_div_pkt_t    div_p,                      // div packet
 | ||||
|    output logic             dec_div_cancel,             // cancel divide operation
 | ||||
|    output el2_lsu_pkt_t    lsu_p,                  // lsu packet
 | ||||
|    output logic             dec_qual_lsu_d,         // LSU instruction at D.  Use to quiet LSU operands
 | ||||
|    output el2_mul_pkt_t    mul_p,                  // mul packet
 | ||||
|    output el2_div_pkt_t    div_p,                  // div packet
 | ||||
|    output logic             dec_div_cancel,         // cancel divide operation
 | ||||
| 
 | ||||
|    output logic [11:0] dec_lsu_offset_d,           // 12b offset for load/store addresses
 | ||||
|    output logic [11:0] dec_lsu_offset_d,            // 12b offset for load/store addresses
 | ||||
| 
 | ||||
|    output logic        dec_csr_ren_d,              // csr read enable
 | ||||
|    output logic        dec_csr_ren_d,               // CSR read enable
 | ||||
|    output logic [31:0] dec_csr_rddata_d,            // CSR read data
 | ||||
| 
 | ||||
|    output logic        dec_tlu_flush_lower_r,       // tlu flush due to late mp, exception, rfpc, or int
 | ||||
|    output logic        dec_tlu_flush_lower_wb, | ||||
|    output logic [31:1] dec_tlu_flush_path_r,        // tlu flush target
 | ||||
|    output logic        dec_tlu_i0_kill_writeb_r,    // I0 is flushed, don't writeback any results to arch state
 | ||||
|    output logic        dec_tlu_fence_i_r,           // flush is a fence_i rfnpc, flush icache
 | ||||
| 
 | ||||
|    output logic        dec_tlu_flush_lower_r,     // tlu flush due to late mp, exception, rfpc, or int
 | ||||
|    output logic [31:1] dec_tlu_flush_path_r,      // tlu flush target
 | ||||
|    output logic        dec_tlu_i0_kill_writeb_r,  // I0 is flushed, don't writeback any results to arch state
 | ||||
|    output logic        dec_tlu_fence_i_r,         // flush is a fence_i rfnpc, flush icache
 | ||||
|    output logic [31:1] pred_correct_npc_x,          // npc if prediction is correct at e2 stage
 | ||||
| 
 | ||||
|    output logic [31:1] pred_correct_npc_x,         // npc if prediction is correct at e2 stage
 | ||||
|    output el2_br_tlu_pkt_t dec_tlu_br0_r_pkt,      // slot 0 branch predictor update packet
 | ||||
| 
 | ||||
|    output el2_br_tlu_pkt_t dec_tlu_br0_r_pkt,         // slot 0 branch predictor update packet
 | ||||
| 
 | ||||
|    output logic dec_tlu_perfcnt0,                  // toggles when slot0 perf counter 0 has an event inc
 | ||||
|    output logic dec_tlu_perfcnt1,                  // toggles when slot0 perf counter 1 has an event inc
 | ||||
|    output logic dec_tlu_perfcnt2,                  // toggles when slot0 perf counter 2 has an event inc
 | ||||
|    output logic dec_tlu_perfcnt3,                  // toggles when slot0 perf counter 3 has an event inc
 | ||||
|    output logic dec_tlu_perfcnt0,                   // toggles when slot0 perf counter 0 has an event inc
 | ||||
|    output logic dec_tlu_perfcnt1,                   // toggles when slot0 perf counter 1 has an event inc
 | ||||
|    output logic dec_tlu_perfcnt2,                   // toggles when slot0 perf counter 2 has an event inc
 | ||||
|    output logic dec_tlu_perfcnt3,                   // toggles when slot0 perf counter 3 has an event inc
 | ||||
| 
 | ||||
|    output el2_predict_pkt_t dec_i0_predict_p_d,                        // prediction packet to alus
 | ||||
|    output logic [pt.BHT_GHR_SIZE-1:0] i0_predict_fghr_d,                // DEC predict fghr
 | ||||
|    output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] i0_predict_index_d,     // DEC predict index
 | ||||
|    output logic [pt.BTB_BTAG_SIZE-1:0] i0_predict_btag_d,               // DEC predict branch tag
 | ||||
| 
 | ||||
|    output logic [$clog2(pt.BTB_SIZE)-1:0] dec_fa_error_index, // Fully associt btb error index
 | ||||
| 
 | ||||
|    output logic dec_lsu_valid_raw_d, | ||||
| 
 | ||||
|    output logic [31:0] dec_tlu_mrac_ff,            // CSR for memory region control
 | ||||
|    output logic [31:0] dec_tlu_mrac_ff,              // CSR for memory region control
 | ||||
| 
 | ||||
|    output logic [1:0] dec_data_en,                   // clock-gate control logic
 | ||||
|    output logic [1:0] dec_ctl_en, | ||||
| 
 | ||||
|    input logic [15:0] ifu_i0_cinst,                  // 16b compressed instruction
 | ||||
| 
 | ||||
|    output el2_trace_pkt_t  rv_trace_pkt,             // trace packet
 | ||||
|    output el2_trace_pkt_t  trace_rv_trace_pkt,      // trace packet
 | ||||
| 
 | ||||
|    // feature disable from mfdc
 | ||||
|    output logic  dec_tlu_external_ldfwd_disable, // disable external load forwarding
 | ||||
|    output logic  dec_tlu_external_ldfwd_disable,     // disable external load forwarding
 | ||||
|    output logic  dec_tlu_sideeffect_posted_disable,  // disable posted stores to side-effect address
 | ||||
|    output logic  dec_tlu_core_ecc_disable,           // disable core ECC
 | ||||
|    output logic  dec_tlu_bpred_disable,              // disable branch prediction
 | ||||
|  | @ -291,16 +300,17 @@ import el2_pkg::*; | |||
|    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_picio_clk_override,         // override PICIO 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
 | ||||
| 
 | ||||
|    output logic  dec_tlu_i0_commit_cmt,              // committed i0 instruction
 | ||||
|    input  logic        scan_mode | ||||
|    input  logic  scan_mode                           // Flop scan mode control
 | ||||
| 
 | ||||
|    ); | ||||
| 
 | ||||
| 
 | ||||
|    logic  dec_tlu_dec_clk_override; // to and from dec blocks
 | ||||
|    logic  dec_tlu_dec_clk_override;      // to and from dec blocks
 | ||||
|    logic  clk_override; | ||||
| 
 | ||||
|    logic               dec_ib0_valid_d; | ||||
|  | @ -310,26 +320,26 @@ import el2_pkg::*; | |||
|    logic               dec_pmu_presync_stall; | ||||
|    logic               dec_pmu_postsync_stall; | ||||
| 
 | ||||
|    logic dec_tlu_wr_pause_r;           // CSR write to pause reg is at R.
 | ||||
|    logic dec_tlu_wr_pause_r;             // CSR write to pause reg is at R.
 | ||||
| 
 | ||||
|    logic [4:0]  dec_i0_rs1_d; | ||||
|    logic [4:0]  dec_i0_rs2_d; | ||||
| 
 | ||||
|    logic [31:0] dec_i0_instr_d; | ||||
| 
 | ||||
|    logic  dec_tlu_trace_disable; | ||||
|    logic  dec_tlu_pipelining_disable; | ||||
| 
 | ||||
| 
 | ||||
|    logic [4:0]  dec_i0_waddr_r; | ||||
|    logic        dec_i0_wen_r; | ||||
|    logic [31:0] dec_i0_wdata_r; | ||||
|    logic        dec_csr_wen_r;      // csr write enable at wb
 | ||||
|    logic [11:0] dec_csr_wraddr_r;      // write address for csryes
 | ||||
|    logic [31:0] dec_csr_wrdata_r;    // csr write data at wb
 | ||||
|    logic        dec_csr_wen_r;           // csr write enable at wb
 | ||||
|    logic [11:0] dec_csr_wraddr_r;        // write address for csryes
 | ||||
|    logic [31:0] dec_csr_wrdata_r;        // csr write data at wb
 | ||||
| 
 | ||||
|    logic [11:0] dec_csr_rdaddr_d;      // read address for csr
 | ||||
|    logic [31:0] dec_csr_rddata_d;    // csr read data at wb
 | ||||
|    logic        dec_csr_legal_d;            // csr indicates legal operation
 | ||||
|    logic [11:0] dec_csr_rdaddr_d;        // read address for csr
 | ||||
|    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
 | ||||
|  | @ -347,7 +357,7 @@ import el2_pkg::*; | |||
|    logic                      dec_i0_icaf_d; | ||||
| 
 | ||||
|    logic                      dec_i0_dbecc_d; | ||||
|    logic                      dec_i0_icaf_f1_d; | ||||
|    logic                      dec_i0_icaf_second_d; | ||||
|    logic [3:0]                dec_i0_trigger_match_d; | ||||
|    logic                      dec_debug_fence_d; | ||||
|    logic                      dec_nonblock_load_wen; | ||||
|  | @ -357,30 +367,29 @@ import el2_pkg::*; | |||
|    logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] dec_i0_bp_index; | ||||
|    logic [pt.BHT_GHR_SIZE-1:0] dec_i0_bp_fghr; | ||||
|    logic [pt.BTB_BTAG_SIZE-1:0] dec_i0_bp_btag; | ||||
|    logic [$clog2(pt.BTB_SIZE)-1:0] dec_i0_bp_fa_index;          // Fully associt btb index
 | ||||
| 
 | ||||
|    logic [31:1]               dec_tlu_i0_pc_r; | ||||
|    logic                      dec_tlu_i0_kill_writeb_wb; | ||||
|    logic                      dec_tlu_flush_lower_wb; | ||||
|    logic                      dec_tlu_i0_valid_r; | ||||
| 
 | ||||
|    logic                      dec_pause_state; | ||||
| 
 | ||||
|    logic [1:0]                dec_i0_icaf_type_d; // i0 instruction access fault type
 | ||||
|    logic [1:0]                dec_i0_icaf_type_d;   // i0 instruction access fault type
 | ||||
| 
 | ||||
|    logic                      dec_tlu_flush_extint; // Fast ext int started
 | ||||
| 
 | ||||
|    logic [31:0]               dec_i0_inst_wb1; | ||||
|    logic [31:1]               dec_i0_pc_wb1; | ||||
|    logic [31:0]               dec_i0_inst_wb; | ||||
|    logic [31:1]               dec_i0_pc_wb; | ||||
|    logic                      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; | ||||
| 
 | ||||
|    logic [4:0]                div_waddr_wb; | ||||
|    logic                      dec_div_active; | ||||
| 
 | ||||
|    logic                      dec_div_active;              // non-block divide is active
 | ||||
| 
 | ||||
| 
 | ||||
|    logic                      dec_debug_valid_d; | ||||
| 
 | ||||
|    assign clk_override = dec_tlu_dec_clk_override; | ||||
| 
 | ||||
|  | @ -419,14 +428,17 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
| // trace
 | ||||
|    assign rv_trace_pkt.rv_i_insn_ip    =   dec_i0_inst_wb1[31:0]; | ||||
|    assign rv_trace_pkt.rv_i_address_ip = { dec_i0_pc_wb1[31:1], 1'b0}; | ||||
|    assign rv_trace_pkt.rv_i_valid_ip =     {dec_tlu_int_valid_wb1,   // always int
 | ||||
|                                                     dec_tlu_i0_valid_wb1 | dec_tlu_i0_exc_valid_wb1}; | ||||
|    assign rv_trace_pkt.rv_i_exception_ip = {dec_tlu_int_valid_wb1, dec_tlu_i0_exc_valid_wb1}; | ||||
|    assign rv_trace_pkt.rv_i_ecause_ip =     dec_tlu_exc_cause_wb1[4:0];  // replicate across ports
 | ||||
|    assign rv_trace_pkt.rv_i_interrupt_ip = {dec_tlu_int_valid_wb1,1'b0}; | ||||
|    assign rv_trace_pkt.rv_i_tval_ip =    dec_tlu_mtval_wb1[31:0];        // replicate across ports
 | ||||
|    assign trace_rv_trace_pkt.trace_rv_i_insn_ip      =   dec_i0_inst_wb[31:0]; | ||||
|    assign trace_rv_trace_pkt.trace_rv_i_address_ip   = { dec_i0_pc_wb[31:1], 1'b0}; | ||||
| 
 | ||||
|    assign trace_rv_trace_pkt.trace_rv_i_valid_ip     = dec_tlu_int_valid_wb1 | 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_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; | ||||
|    assign trace_rv_trace_pkt.trace_rv_i_tval_ip      = dec_tlu_mtval_wb1[31:0];        // replicate across ports
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| // end trace
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -18,7 +18,7 @@ import el2_pkg::*; | |||
| #( | ||||
|    `include "el2_param.vh" | ||||
|  )  ( | ||||
|     input logic [4:0]  raddr0,      // logical read addresses
 | ||||
|     input logic [4:0]  raddr0,       // logical read addresses
 | ||||
|     input logic [4:0]  raddr1, | ||||
| 
 | ||||
|     input logic        wen0,         // write enable
 | ||||
|  | @ -42,18 +42,18 @@ import el2_pkg::*; | |||
|     input  logic        scan_mode | ||||
| ); | ||||
| 
 | ||||
|    logic [31:1] [31:0] gpr_out;     // 31 x 32 bit GPRs
 | ||||
|    logic [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; | ||||
| 
 | ||||
|    // GPR Write Enables for power savings
 | ||||
|    // GPR Write Enables
 | ||||
|    assign gpr_wr_en[31:1] = (w0v[31:1] | w1v[31:1] | w2v[31:1]); | ||||
|    for ( genvar j=1; j<32; j++ )  begin : gpr | ||||
|       rvdffe #(32) gprff (.*, .en(gpr_wr_en[j]), .din(gpr_in[j][31:0]), .dout(gpr_out[j][31:0])); | ||||
|    end : gpr | ||||
| 
 | ||||
| // the read out
 | ||||
|    // the read out
 | ||||
|    always_comb begin | ||||
|       rd0[31:0] = 32'b0; | ||||
|       rd1[31:0] = 32'b0; | ||||
|  | @ -79,7 +79,7 @@ import el2_pkg::*; | |||
|      end | ||||
|    end // always_comb begin
 | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_ASSERT_ON | ||||
| 
 | ||||
|    logic  write_collision_unused; | ||||
|    assign write_collision_unused = ( (w0v[31:1] == w1v[31:1]) & wen0 & wen1 ) | | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -19,47 +19,52 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
|   ( | ||||
|    input logic                 dbg_cmd_valid,  // valid dbg cmd
 | ||||
|    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 [31:0]          dbg_cmd_addr,   // expand to 31:0
 | ||||
|    input logic                 dbg_cmd_write,                      // dbg cmd is write
 | ||||
|    input logic [1:0]           dbg_cmd_type,                       // dbg type
 | ||||
|    input logic [31:0]          dbg_cmd_addr,                       // expand to 31:0
 | ||||
| 
 | ||||
|    input el2_br_pkt_t i0_brp,                      // i0 branch packet from aligner
 | ||||
|    input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index, // BP index
 | ||||
|    input logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr, // BP FGHR
 | ||||
|    input logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag, // BP tag
 | ||||
|    input logic       ifu_i0_pc4,                   // i0 is 4B inst else 2B
 | ||||
|    input logic       ifu_i0_valid,                 // i0 valid from ifu
 | ||||
|    input logic       ifu_i0_icaf,                  // i0 instruction access fault
 | ||||
|    input logic [1:0] ifu_i0_icaf_type,         // i0 instruction access fault type
 | ||||
|    input el2_br_pkt_t i0_brp,                                     // i0 branch packet from aligner
 | ||||
|    input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index,    // BP index
 | ||||
|    input logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr,               // BP FGHR
 | ||||
|    input logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag,              // BP tag
 | ||||
|    input logic [$clog2(pt.BTB_SIZE)-1:0] ifu_i0_fa_index,          // Fully associt btb index
 | ||||
| 
 | ||||
|    input logic   ifu_i0_icaf_f1,               // i0 has access fault on second fetch group
 | ||||
|    input logic   ifu_i0_dbecc,                 // i0 double-bit error
 | ||||
|    input logic [31:0]  ifu_i0_instr,           // i0 instruction from the aligner
 | ||||
|    input logic [31:1]  ifu_i0_pc,              // i0 pc from the aligner
 | ||||
|    input logic       ifu_i0_pc4,                                   // i0 is 4B inst else 2B
 | ||||
|    input logic       ifu_i0_valid,                                 // i0 valid from ifu
 | ||||
|    input logic       ifu_i0_icaf,                                  // i0 instruction access fault
 | ||||
|    input logic [1:0] ifu_i0_icaf_type,                             // i0 instruction access fault type
 | ||||
| 
 | ||||
|    input logic   ifu_i0_icaf_second,                               // i0 has access fault on second 2B of 4B inst
 | ||||
|    input logic   ifu_i0_dbecc,                                     // i0 double-bit error
 | ||||
|    input logic [31:0]  ifu_i0_instr,                               // i0 instruction from the aligner
 | ||||
|    input logic [31:1]  ifu_i0_pc,                                  // i0 pc from the aligner
 | ||||
| 
 | ||||
| 
 | ||||
|    output logic dec_ib0_valid_d,               // ib0 valid
 | ||||
|    output logic dec_ib0_valid_d,                                   // ib0 valid
 | ||||
|    output logic dec_debug_valid_d,                                 // Debug read or write at D-stage
 | ||||
| 
 | ||||
| 
 | ||||
|    output logic [31:0] dec_i0_instr_d,         // i0 inst at decode
 | ||||
|    output logic [31:0] dec_i0_instr_d,                             // i0 inst at decode
 | ||||
| 
 | ||||
|    output logic [31:1] dec_i0_pc_d,            // i0 pc at decode
 | ||||
|    output logic [31:1] dec_i0_pc_d,                                // i0 pc at decode
 | ||||
| 
 | ||||
|    output logic dec_i0_pc4_d,                  // i0 is 4B inst else 2B
 | ||||
|    output logic dec_i0_pc4_d,                                      // i0 is 4B inst else 2B
 | ||||
| 
 | ||||
|    output el2_br_pkt_t dec_i0_brp,            // i0 branch packet at decode
 | ||||
|    output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] dec_i0_bp_index,            // i0 branch index
 | ||||
|    output logic [pt.BHT_GHR_SIZE-1:0] dec_i0_bp_fghr, // BP FGHR
 | ||||
|    output logic [pt.BTB_BTAG_SIZE-1:0] dec_i0_bp_btag, // BP tag
 | ||||
|    output logic dec_i0_icaf_d,                 // i0 instruction access fault at decode
 | ||||
|    output logic dec_i0_icaf_f1_d,              // i0 instruction access fault at decode for f1 fetch group
 | ||||
|    output logic [1:0] dec_i0_icaf_type_d,      // i0 instruction access fault type
 | ||||
|    output logic dec_i0_dbecc_d,                // i0 double-bit error at decode
 | ||||
|    output logic dec_debug_wdata_rs1_d,         // put debug write data onto rs1 source: machine is halted
 | ||||
|    output el2_br_pkt_t dec_i0_brp,                                // i0 branch packet at decode
 | ||||
|    output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] dec_i0_bp_index,   // i0 branch index
 | ||||
|    output logic [pt.BHT_GHR_SIZE-1:0] dec_i0_bp_fghr,              // BP FGHR
 | ||||
|    output logic [pt.BTB_BTAG_SIZE-1:0] dec_i0_bp_btag,             // BP tag
 | ||||
|    output logic [$clog2(pt.BTB_SIZE)-1:0] dec_i0_bp_fa_index,          // Fully associt btb index
 | ||||
| 
 | ||||
|    output logic dec_debug_fence_d             // debug fence inst
 | ||||
|    output logic dec_i0_icaf_d,                                     // i0 instruction access fault at decode
 | ||||
|    output logic dec_i0_icaf_second_d,                              // i0 instruction access fault on second 2B of 4B inst
 | ||||
|    output logic [1:0] dec_i0_icaf_type_d,                          // i0 instruction access fault type
 | ||||
|    output logic dec_i0_dbecc_d,                                    // i0 double-bit error at decode
 | ||||
|    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
 | ||||
| 
 | ||||
|    ); | ||||
| 
 | ||||
|  | @ -78,12 +83,12 @@ import el2_pkg::*; | |||
| 
 | ||||
|    logic [34:0]  ifu_i0_pcdata, pc0; | ||||
| 
 | ||||
|    assign ifu_i0_pcdata[34:0] = { ifu_i0_icaf_f1, ifu_i0_dbecc, ifu_i0_icaf, | ||||
|    assign ifu_i0_pcdata[34:0] = { ifu_i0_icaf_second, ifu_i0_dbecc, ifu_i0_icaf, | ||||
|                                   ifu_i0_pc[31:1], ifu_i0_pc4 }; | ||||
| 
 | ||||
|    assign pc0[34:0] = ifu_i0_pcdata[34:0]; | ||||
| 
 | ||||
|    assign dec_i0_icaf_f1_d = pc0[34];   // icaf's can only decode as i0
 | ||||
|    assign dec_i0_icaf_second_d = pc0[34];   // icaf's can only decode as i0
 | ||||
| 
 | ||||
|    assign dec_i0_dbecc_d = pc0[33]; | ||||
| 
 | ||||
|  | @ -146,11 +151,14 @@ import el2_pkg::*; | |||
| 
 | ||||
|    assign dec_ib0_valid_d = ifu_i0_valid | debug_valid; | ||||
| 
 | ||||
|    assign dec_debug_valid_d = debug_valid; | ||||
| 
 | ||||
|    assign dec_i0_instr_d[31:0] = ib0[31:0]; | ||||
| 
 | ||||
|    assign dec_i0_brp = i0_brp; | ||||
|    assign dec_i0_bp_index = ifu_i0_bp_index; | ||||
|    assign dec_i0_bp_fghr = ifu_i0_bp_fghr; | ||||
|    assign dec_i0_bp_btag = ifu_i0_bp_btag; | ||||
|    assign dec_i0_bp_fa_index = ifu_i0_fa_index; | ||||
| 
 | ||||
| endmodule | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -29,9 +29,9 @@ import el2_pkg::*; | |||
|  )( | ||||
| 
 | ||||
|    input el2_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_i0_pc_d,                          // i0 pc
 | ||||
| 
 | ||||
|    output logic [3:0] dec_i0_trigger_match_d | ||||
|    output logic [3:0] dec_i0_trigger_match_d                 // Trigger match
 | ||||
| ); | ||||
| 
 | ||||
|    logic [3:0][31:0]  dec_i0_match_data; | ||||
|  |  | |||
|  | @ -173,6 +173,7 @@ always_comb begin | |||
|                     endcase | ||||
|                 end | ||||
|     capture_dr: begin | ||||
|                     nsr[0] = 1'b0; | ||||
|                     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}; | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -64,6 +64,7 @@ module el2_dma_ctrl #( | |||
|    input logic [2:0]   iccm_dma_rtag,      // Tag of the DMA req
 | ||||
|    input logic [63:0]  iccm_dma_rdata,     // iccm data for DMA read
 | ||||
| 
 | ||||
|    output logic        dma_active,         // DMA is busy
 | ||||
|    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
 | ||||
|  | @ -154,6 +155,10 @@ module el2_dma_ctrl #( | |||
|    logic [DEPTH_PTR-1:0]    RdPtr, NxtRdPtr; | ||||
|    logic                    WrPtrEn, RdPtrEn, RspPtrEn; | ||||
| 
 | ||||
|    logic [1:0]              dma_dbg_sz; | ||||
|    logic [1:0]              dma_dbg_addr; | ||||
|    logic [31:0]             dma_dbg_mem_rddata; | ||||
|    logic [31:0]             dma_dbg_mem_wrdata; | ||||
|    logic                    dma_dbg_cmd_error; | ||||
|    logic                    dma_dbg_cmd_done_q; | ||||
| 
 | ||||
|  | @ -193,6 +198,7 @@ module el2_dma_ctrl #( | |||
| 
 | ||||
|    logic                    fifo_full_spec_bus; | ||||
|    logic                    dbg_dma_bubble_bus; | ||||
|    logic                    stall_dma_in; | ||||
|    logic                    dma_fifo_ready; | ||||
| 
 | ||||
|    logic                       wrbuf_en, wrbuf_data_en; | ||||
|  | @ -225,14 +231,14 @@ module el2_dma_ctrl #( | |||
| 
 | ||||
|    // FIFO inputs
 | ||||
|    assign fifo_addr_in[31:0]    = dbg_cmd_valid ? dbg_cmd_addr[31:0] : bus_cmd_addr[31:0]; | ||||
|    assign fifo_byteen_in[7:0]   = dbg_cmd_valid ? (8'h0f << 4*dbg_cmd_addr[2]) : bus_cmd_byteen[7:0]; | ||||
|    assign fifo_byteen_in[7:0]   = {8{~dbg_cmd_valid}} & bus_cmd_byteen[7:0];    // Byte enable is used only for bus requests
 | ||||
|    assign fifo_sz_in[2:0]       = dbg_cmd_valid ? {1'b0,dbg_cmd_size[1:0]} : bus_cmd_sz[2:0]; | ||||
|    assign fifo_write_in         = dbg_cmd_valid ? dbg_cmd_write : bus_cmd_write; | ||||
|    assign fifo_posted_write_in  = ~dbg_cmd_valid & bus_cmd_posted_write; | ||||
|    assign fifo_dbg_in           = dbg_cmd_valid; | ||||
| 
 | ||||
|    for (genvar i=0 ;i<32'(DEPTH); i++) begin: GenFifo | ||||
|       assign fifo_cmd_en[i]   = ((bus_cmd_sent & dma_bus_clk_en) | (dbg_cmd_valid & dbg_cmd_type[1])) & (DEPTH_PTR'(i) == WrPtr[DEPTH_PTR-1:0]); | ||||
|    for (genvar i=0 ;i<DEPTH; i++) begin: GenFifo | ||||
|       assign fifo_cmd_en[i]   = ((bus_cmd_sent & dma_bus_clk_en) | (dbg_cmd_valid & dbg_cmd_type[1])) & (i == WrPtr[DEPTH_PTR-1:0]); | ||||
|       assign fifo_data_en[i] = (((bus_cmd_sent & fifo_write_in & dma_bus_clk_en) | (dbg_cmd_valid & dbg_cmd_type[1] & dbg_cmd_write))  & (i == WrPtr[DEPTH_PTR-1:0])) | | ||||
|                                ((dma_address_error | dma_alignment_error) & (i == RdPtr[DEPTH_PTR-1:0])) | | ||||
|                                (dccm_dma_rvalid & (i == DEPTH_PTR'(dccm_dma_rtag[2:0]))) | | ||||
|  | @ -251,7 +257,7 @@ module el2_dma_ctrl #( | |||
|                                                                                                                 {(dma_address_error | dma_alignment_error | dma_dbg_cmd_error), dma_alignment_error}; | ||||
|       assign fifo_data_in[i]   = (fifo_error_en[i] & (|fifo_error_in[i])) ? {32'b0,fifo_addr[i]} : | ||||
|                                                         ((dccm_dma_rvalid & (i == DEPTH_PTR'(dccm_dma_rtag[2:0])))  ? dccm_dma_rdata[63:0] : (iccm_dma_rvalid & (i == DEPTH_PTR'(iccm_dma_rtag[2:0]))) ? iccm_dma_rdata[63:0] : | ||||
|                                                                                                                                                        (dbg_cmd_valid ? {2{dbg_cmd_wrdata[31:0]}} : bus_cmd_wdata[63:0])); | ||||
|                                                                                                                                                        (dbg_cmd_valid ? {2{dma_dbg_mem_wrdata[31:0]}} : bus_cmd_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), .*); | ||||
|  | @ -299,7 +305,7 @@ module el2_dma_ctrl #( | |||
| 
 | ||||
|    // Error logic
 | ||||
|    assign dma_address_error = fifo_valid[RdPtr] & ~fifo_done[RdPtr] & ~fifo_dbg[RdPtr] & (~(dma_mem_addr_in_dccm | dma_mem_addr_in_iccm));    // request not for ICCM or DCCM
 | ||||
|    assign dma_alignment_error = fifo_valid[RdPtr] & ~fifo_done[RdPtr] & ~dma_address_error & | ||||
|    assign dma_alignment_error = fifo_valid[RdPtr] & ~fifo_done[RdPtr] & ~fifo_dbg[RdPtr] & ~dma_address_error & | ||||
|                                 (((dma_mem_sz_int[2:0] == 3'h1) & dma_mem_addr_int[0])                                                       |    // HW size but unaligned
 | ||||
|                                  ((dma_mem_sz_int[2:0] == 3'h2) & (|dma_mem_addr_int[1:0]))                                                  |    // W size but unaligned
 | ||||
|                                  ((dma_mem_sz_int[2:0] == 3'h3) & (|dma_mem_addr_int[2:0]))                                                  |    // DW size but unaligned
 | ||||
|  | @ -310,20 +316,31 @@ module el2_dma_ctrl #( | |||
| 
 | ||||
| 
 | ||||
|    //Dbg outputs
 | ||||
|    assign dma_dbg_ready    = fifo_empty & dbg_dma_bubble_bus; | ||||
|    assign dma_dbg_ready    = fifo_empty & dbg_dma_bubble; | ||||
|    assign dma_dbg_cmd_done = (fifo_valid[RspPtr] & fifo_dbg[RspPtr] & fifo_done[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_sz[1:0]          = fifo_sz[RspPtr][1:0]; | ||||
|    assign dma_dbg_addr[1:0]        = fifo_addr[RspPtr][1:0]; | ||||
|    assign dma_dbg_mem_rddata[31:0] = fifo_addr[RspPtr][2] ? fifo_data[RspPtr][63:32] : fifo_data[RspPtr][31:0]; | ||||
|    assign dma_dbg_rddata[31:0]     = ({32{(dma_dbg_sz[1:0] == 2'h0)}} & ((dma_dbg_mem_rddata[31:0] >> 8*dma_dbg_addr[1:0]) & 32'hff)) | | ||||
|                                      ({32{(dma_dbg_sz[1:0] == 2'h1)}} & ((dma_dbg_mem_rddata[31:0] >> 16*dma_dbg_addr[1]) & 32'hffff)) | | ||||
|                                      ({32{(dma_dbg_sz[1:0] == 2'h2)}} & dma_dbg_mem_rddata[31:0]); | ||||
| 
 | ||||
|    assign dma_dbg_cmd_error = fifo_valid[RdPtr] & ~fifo_done[RdPtr] & fifo_dbg[RdPtr] & | ||||
|                                  ((~(dma_mem_addr_in_dccm | dma_mem_addr_in_iccm | dma_mem_addr_in_pic)) | (dma_mem_sz_int[1:0] != 2'b10));  // Only word accesses allowed
 | ||||
|                                  ((~(dma_mem_addr_in_dccm | dma_mem_addr_in_iccm | dma_mem_addr_in_pic)) |             // Address outside of ICCM/DCCM/PIC
 | ||||
|                                   ((dma_mem_addr_in_iccm | dma_mem_addr_in_pic) & (dma_mem_sz_int[1:0] != 2'b10)));    // Only word accesses allowed for ICCM/PIC
 | ||||
| 
 | ||||
|    assign dma_dbg_mem_wrdata[31:0] = ({32{dbg_cmd_size[1:0] == 2'h0}} & {4{dbg_cmd_wrdata[7:0]}}) | | ||||
|                                      ({32{dbg_cmd_size[1:0] == 2'h1}} & {2{dbg_cmd_wrdata[15:0]}}) | | ||||
|                                      ({32{dbg_cmd_size[1:0] == 2'h2}} & dbg_cmd_wrdata[31:0]); | ||||
| 
 | ||||
|    // Block the decode if fifo full
 | ||||
|    assign dma_dccm_stall_any = dma_mem_req & (dma_mem_addr_in_dccm | dma_mem_addr_in_pic) & (dma_nack_count >= dma_nack_count_csr); | ||||
|    assign dma_iccm_stall_any = dma_mem_req & dma_mem_addr_in_iccm & (dma_nack_count >= dma_nack_count_csr); | ||||
| 
 | ||||
|    // Used to indicate ready to debug
 | ||||
|    assign fifo_empty     = ~(|(fifo_valid[DEPTH-1:0])); | ||||
|    assign fifo_empty     = ~((|(fifo_valid[DEPTH-1:0])) | bus_cmd_sent); | ||||
| 
 | ||||
|    // Nack counter, stall the lsu pipe if 7 nacks
 | ||||
|    assign dma_nack_count_csr[2:0] = dec_tlu_dma_qos_prty[2:0]; | ||||
|  | @ -339,8 +356,8 @@ module el2_dma_ctrl #( | |||
|    assign dma_mem_tag[2:0]    = 3'(RdPtr); | ||||
|    assign dma_mem_addr_int[31:0] = fifo_addr[RdPtr]; | ||||
|    assign dma_mem_sz_int[2:0] = fifo_sz[RdPtr]; | ||||
|    assign dma_mem_addr[31:0]  = (dma_mem_write & (dma_mem_byteen[7:0] == 8'hf0)) ? {dma_mem_addr_int[31:3],1'b1,dma_mem_addr_int[1:0]} : dma_mem_addr_int[31:0]; | ||||
|    assign dma_mem_sz[2:0]     = (dma_mem_write & ((dma_mem_byteen[7:0] == 8'h0f) | (dma_mem_byteen[7:0] == 8'hf0))) ? 3'h2 : dma_mem_sz_int[2:0]; | ||||
|    assign dma_mem_addr[31:0]  = (dma_mem_write & ~fifo_dbg[RdPtr] & (dma_mem_byteen[7:0] == 8'hf0)) ? {dma_mem_addr_int[31:3],1'b1,dma_mem_addr_int[1:0]} : dma_mem_addr_int[31:0]; | ||||
|    assign dma_mem_sz[2:0]     = (dma_mem_write & ~fifo_dbg[RdPtr] & ((dma_mem_byteen[7:0] == 8'h0f) | (dma_mem_byteen[7:0] == 8'hf0))) ? 3'h2 : dma_mem_sz_int[2:0]; | ||||
|    assign dma_mem_byteen[7:0] = fifo_byteen[RdPtr]; | ||||
|    assign dma_mem_write       = fifo_write[RdPtr]; | ||||
|    assign dma_mem_wdata[63:0] = fifo_data[RdPtr]; | ||||
|  | @ -352,23 +369,27 @@ module el2_dma_ctrl #( | |||
|    assign dma_pmu_any_write   = (dma_dccm_req | dma_iccm_req) & dma_mem_write; | ||||
| 
 | ||||
|    // Address check  dccm
 | ||||
|    rvrangecheck #(.CCM_SADR(pt.DCCM_SADR), | ||||
|                   .CCM_SIZE(pt.DCCM_SIZE)) addr_dccm_rangecheck ( | ||||
|       .addr(dma_mem_addr_int[31:0]), | ||||
|       .in_range(dma_mem_addr_in_dccm), | ||||
|       .in_region(dma_mem_addr_in_dccm_region_nc) | ||||
|    ); | ||||
|    if (pt.DCCM_ENABLE) begin: Gen_dccm_enable | ||||
|       rvrangecheck #(.CCM_SADR(pt.DCCM_SADR), | ||||
|                      .CCM_SIZE(pt.DCCM_SIZE)) addr_dccm_rangecheck ( | ||||
|          .addr(dma_mem_addr_int[31:0]), | ||||
|          .in_range(dma_mem_addr_in_dccm), | ||||
|          .in_region(dma_mem_addr_in_dccm_region_nc) | ||||
|       ); | ||||
|    end else begin: Gen_dccm_disable | ||||
|       assign dma_mem_addr_in_dccm = '0; | ||||
|       assign dma_mem_addr_in_dccm_region_nc = '0; | ||||
|    end // else: !if(pt.ICCM_ENABLE)
 | ||||
| 
 | ||||
|    // Address check  iccm
 | ||||
|    if (pt.ICCM_ENABLE) begin | ||||
|    if (pt.ICCM_ENABLE) begin: Gen_iccm_enable | ||||
|       rvrangecheck #(.CCM_SADR(pt.ICCM_SADR), | ||||
|                      .CCM_SIZE(pt.ICCM_SIZE)) addr_iccm_rangecheck ( | ||||
|          .addr(dma_mem_addr_int[31:0]), | ||||
|          .in_range(dma_mem_addr_in_iccm), | ||||
|          .in_region(dma_mem_addr_in_iccm_region_nc) | ||||
|       ); | ||||
|    end | ||||
|    else  begin | ||||
|    end else begin: Gen_iccm_disable | ||||
|       assign dma_mem_addr_in_iccm = '0; | ||||
|       assign dma_mem_addr_in_iccm_region_nc = '0; | ||||
|    end // else: !if(pt.ICCM_ENABLE)
 | ||||
|  | @ -382,11 +403,10 @@ module el2_dma_ctrl #( | |||
|       .in_region(dma_mem_addr_in_pic_region_nc) | ||||
|     ); | ||||
| 
 | ||||
| 
 | ||||
|    // Inputs
 | ||||
|    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) dma_dbg_cmd_doneff   (.din(dma_dbg_cmd_done), .dout(dma_dbg_cmd_done_q), .clk(free_clk), .*); | ||||
|    rvdff_fpga #(1) fifo_full_bus_ff     (.din(fifo_full_spec),   .dout(fifo_full_spec_bus), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdff_fpga #(1) dbg_dma_bubble_ff    (.din(dbg_dma_bubble),   .dout(dbg_dma_bubble_bus), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(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 = (bus_cmd_valid & dma_bus_clk_en) | dbg_cmd_valid | clk_override; | ||||
|  | @ -394,7 +414,12 @@ module el2_dma_ctrl #( | |||
| 
 | ||||
|    rvoclkhdr dma_buffer_c1cgc ( .en(dma_buffer_c1_clken), .l1clk(dma_buffer_c1_clk), .* ); | ||||
|    rvoclkhdr dma_free_cgc (.en(dma_free_clken), .l1clk(dma_free_clk), .*); | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    assign dma_bus_clk = 1'b0; | ||||
| `else | ||||
|    rvclkhdr  dma_bus_cgc (.en(dma_bus_clk_en), .l1clk(dma_bus_clk), .*); | ||||
| `endif | ||||
| 
 | ||||
|    // Write channel buffer
 | ||||
|    assign wrbuf_en       = dma_axi_awvalid & dma_axi_awready; | ||||
|  | @ -403,23 +428,23 @@ module el2_dma_ctrl #( | |||
|    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(pt.DMA_BUS_TAG)) wrbuf_tagff(.din(dma_axi_awid[pt.DMA_BUS_TAG-1:0]), .dout(wrbuf_tag[pt.DMA_BUS_TAG-1:0]), .en(wrbuf_en), .clk(dma_bus_clk), .*); | ||||
|    rvdffs   #(.WIDTH(3)) wrbuf_szff(.din(dma_axi_awsize[2:0]), .dout(wrbuf_sz[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), .*); | ||||
|    rvdffsc_fpga  #(.WIDTH(1))              wrbuf_vldff       (.din(1'b1), .dout(wrbuf_vld),      .en(wrbuf_en),      .clear(wrbuf_rst),      .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffsc_fpga  #(.WIDTH(1))              wrbuf_data_vldff  (.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_data_rst), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga   #(.WIDTH(pt.DMA_BUS_TAG)) wrbuf_tagff       (.din(dma_axi_awid[pt.DMA_BUS_TAG-1:0]), .dout(wrbuf_tag[pt.DMA_BUS_TAG-1:0]), .en(wrbuf_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga   #(.WIDTH(3))              wrbuf_szff        (.din(dma_axi_awsize[2:0]),  .dout(wrbuf_sz[2:0]),     .en(wrbuf_en),                  .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(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_fpga   #(.WIDTH(8))              wrbuf_byteenff    (.din(dma_axi_wstrb[7:0]),   .dout(wrbuf_byteen[7:0]), .en(wrbuf_data_en),             .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); | ||||
| 
 | ||||
|    // Read channel buffer
 | ||||
|    assign rdbuf_en    = dma_axi_arvalid & dma_axi_arready; | ||||
|    assign rdbuf_cmd_sent = bus_cmd_sent & ~bus_cmd_write; | ||||
|    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(pt.DMA_BUS_TAG)) rdbuf_tagff(.din(dma_axi_arid[pt.DMA_BUS_TAG-1:0]), .dout(rdbuf_tag[pt.DMA_BUS_TAG-1:0]), .en(rdbuf_en), .clk(dma_bus_clk), .*); | ||||
|    rvdffs   #(.WIDTH(3)) rdbuf_szff(.din(dma_axi_arsize[2:0]), .dout(rdbuf_sz[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), .*); | ||||
|    rvdffsc_fpga  #(.WIDTH(1))              rdbuf_vldff  (.din(1'b1), .dout(rdbuf_vld), .en(rdbuf_en), .clear(rdbuf_rst), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga   #(.WIDTH(pt.DMA_BUS_TAG)) rdbuf_tagff  (.din(dma_axi_arid[pt.DMA_BUS_TAG-1:0]), .dout(rdbuf_tag[pt.DMA_BUS_TAG-1:0]), .en(rdbuf_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga   #(.WIDTH(3))              rdbuf_szff   (.din(dma_axi_arsize[2:0]),  .dout(rdbuf_sz[2:0]),    .en(rdbuf_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(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); | ||||
|  | @ -442,7 +467,7 @@ module el2_dma_ctrl #( | |||
|    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 = bus_cmd_sent; | ||||
|    rvdffs #(.WIDTH(1)) mstr_prtyff(.din(axi_mstr_prty_in), .dout(axi_mstr_priority), .en(axi_mstr_prty_en), .clk(dma_bus_clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(1)) mstr_prtyff(.din(axi_mstr_prty_in), .dout(axi_mstr_priority), .en(axi_mstr_prty_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); | ||||
| 
 | ||||
|    assign axi_rsp_valid                   = fifo_valid[RspPtr] & ~fifo_dbg[RspPtr] & fifo_done_bus[RspPtr]; | ||||
|    assign axi_rsp_rdata[63:0]             = fifo_data[RspPtr]; | ||||
|  | @ -465,7 +490,10 @@ module el2_dma_ctrl #( | |||
|    assign bus_rsp_valid      = (dma_axi_bvalid | dma_axi_rvalid); | ||||
|    assign bus_rsp_sent       = (dma_axi_bvalid & dma_axi_bready) | (dma_axi_rvalid & dma_axi_rready); | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
|    assign dma_active  = wrbuf_vld | rdbuf_vld | (|fifo_valid[DEPTH-1:0]); | ||||
| 
 | ||||
| 
 | ||||
| `ifdef RV_ASSERT_ON | ||||
| 
 | ||||
|    for (genvar i=0; i<DEPTH; i++) begin | ||||
|       assert_fifo_done_and_novalid: assert #0 (~fifo_done[i] | fifo_valid[i]); | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -42,10 +42,12 @@ import el2_pkg::*; | |||
|    output logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_rd_data_hi, | ||||
| 
 | ||||
| //`ifdef pt.DCCM_ENABLE
 | ||||
|    input el2_dccm_ext_in_pkt_t  [pt.DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt, | ||||
| 
 | ||||
| //`endif
 | ||||
| 
 | ||||
|    //ICCM ports
 | ||||
|    input el2_ccm_ext_in_pkt_t   [pt.ICCM_NUM_BANKS-1:0]  iccm_ext_in_pkt, | ||||
| 
 | ||||
|    input logic [pt.ICCM_BITS-1:1]  iccm_rw_addr, | ||||
|    input logic                                        iccm_buf_correct_ecc,                    // ICCM is doing a single bit error correct cycle
 | ||||
|  | @ -66,6 +68,8 @@ import el2_pkg::*; | |||
|    input  logic         ic_rd_en, | ||||
|    input  logic [63:0] ic_premux_data,      // Premux data to be muxed with each way of the Icache.
 | ||||
|    input  logic         ic_sel_premux_data, // Premux data sel
 | ||||
|    input el2_ic_data_ext_in_pkt_t   [pt.ICACHE_NUM_WAYS-1:0][pt.ICACHE_BANKS_WAY-1:0]         ic_data_ext_in_pkt, | ||||
|    input el2_ic_tag_ext_in_pkt_t    [pt.ICACHE_NUM_WAYS-1:0]           ic_tag_ext_in_pkt, | ||||
| 
 | ||||
|    input  logic [pt.ICACHE_BANKS_WAY-1:0][70:0]               ic_wr_data,         // Data to fill to the Icache. With ECC
 | ||||
|    input  logic [70:0]               ic_debug_wr_data,   // Debug wr cache.
 | ||||
|  | @ -90,6 +94,9 @@ import el2_pkg::*; | |||
| 
 | ||||
| ); | ||||
| 
 | ||||
|    logic active_clk; | ||||
|    rvoclkhdr active_cg   ( .en(1'b1),         .l1clk(active_clk), .* ); | ||||
| 
 | ||||
|    // DCCM Instantiation
 | ||||
|    if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable | ||||
|       el2_lsu_dccm_mem #(.pt(pt)) dccm ( | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -27,9 +27,9 @@ module el2_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                   io_clk_override,      // PIC IO  Clock over-ride for gating
 | ||||
|                      input  logic [pt.PIC_TOTAL_INT_PLUS1-1:0]   extintsrc_req,  // Interrupt requests
 | ||||
|                      input  logic [31:0]            picm_rdaddr,          // Address of the register
 | ||||
|                      input  logic [31:0]            picm_wraddr,          // Address of the register
 | ||||
|  | @ -69,6 +69,12 @@ localparam INTPRIORITY_BITS      =  4 ; | |||
| localparam ID_BITS               =  8 ; | ||||
| localparam int GW_CONFIG[pt.PIC_TOTAL_INT_PLUS1-1:0] = '{default:0} ; | ||||
| 
 | ||||
| localparam INT_ENABLE_GRPS       =   (pt.PIC_TOTAL_INT_PLUS1 - 1)  / 4 ; | ||||
| 
 | ||||
| logic [pt.PIC_TOTAL_INT_PLUS1-1:0]           intenable_clk_enable ; | ||||
| logic [INT_ENABLE_GRPS:0]                    intenable_clk_enable_grp ; | ||||
| logic [INT_ENABLE_GRPS:0]                    gw_clk ; | ||||
| 
 | ||||
| logic  addr_intpend_base_match; | ||||
| 
 | ||||
| logic  raddr_config_pic_match ; | ||||
|  | @ -112,12 +118,6 @@ 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 [NUM_LEVELS:NUM_LEVELS/2] [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] [INTPRIORITY_BITS-1:0] levelx_intpend_w_prior_en; | ||||
| logic [NUM_LEVELS:NUM_LEVELS/2] [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] [ID_BITS-1:0]          levelx_intpend_id; | ||||
| logic [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0] [INTPRIORITY_BITS-1:0] l2_intpend_w_prior_en_ff; | ||||
| logic [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0] [ID_BITS-1:0]          l2_intpend_id_ff; | ||||
| 
 | ||||
| logic                                        config_reg; | ||||
| logic                                        intpriord; | ||||
| logic                                        config_reg_we ; | ||||
|  | @ -191,19 +191,24 @@ assign waddr_config_gw_base_match   = (picm_waddr_ff[31:NUM_LEVELS+2] == EXT_INT | |||
| 
 | ||||
| rvdff #(32) picm_radd_flop  (.*, .din (picm_rdaddr),        .dout(picm_raddr_ff),         .clk(pic_raddr_c1_clk)); | ||||
| rvdff #(32) picm_wadd_flop  (.*, .din (picm_wraddr),        .dout(picm_waddr_ff),         .clk(pic_data_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  #(1) picm_wre_flop   (.*, .din (picm_wren),          .dout(picm_wren_ff),          .clk(free_clk)); | ||||
| rvdff  #(1) picm_rde_flop   (.*, .din (picm_rden),          .dout(picm_rden_ff),          .clk(free_clk)); | ||||
| rvdff  #(1) picm_mke_flop   (.*, .din (picm_mken),          .dout(picm_mken_ff),          .clk(free_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  #(pt.PIC_TOTAL_INT_PLUS1-1) sync_inst | ||||
| ( | ||||
|  .clk (free_clk), | ||||
|  .dout(extintsrc_req_sync[pt.PIC_TOTAL_INT_PLUS1-1:1]), | ||||
|  .din (extintsrc_req[pt.PIC_TOTAL_INT_PLUS1-1:1]), | ||||
|  .*) ; | ||||
| 
 | ||||
| assign extintsrc_req_sync[0] = extintsrc_req[0]; | ||||
| genvar p ; | ||||
| for (p=0; p<=INT_ENABLE_GRPS ; p++) begin  : IO_CLK_GRP | ||||
|    if (p==INT_ENABLE_GRPS) begin : LAST_GRP | ||||
|        assign intenable_clk_enable_grp[p] = |intenable_clk_enable[pt.PIC_TOTAL_INT_PLUS1-1 : p*4] | io_clk_override; | ||||
|        rvoclkhdr intenable_c1_cgc   ( .en(intenable_clk_enable_grp[p]),  .l1clk(gw_clk[p]), .* ); | ||||
|    end else begin :  CLK_GRPS | ||||
|        assign intenable_clk_enable_grp[p] = |intenable_clk_enable[p*4+3 : p*4] | io_clk_override; | ||||
|        rvoclkhdr intenable_c1_cgc   ( .en(intenable_clk_enable_grp[p]),  .l1clk(gw_clk[p]), .* ); | ||||
|    end | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| genvar i ; | ||||
| for (i=0; i<pt.PIC_TOTAL_INT_PLUS1 ; i++) begin  : SETREG | ||||
|  | @ -223,15 +228,33 @@ for (i=0; i<pt.PIC_TOTAL_INT_PLUS1 ; i++) begin  : SETREG | |||
|      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)); | ||||
| 
 | ||||
|      assign intenable_clk_enable[i]  =  gw_config_reg[i][1] | intenable_reg_we[i] | intenable_reg[i] | gw_clear_reg_we[i] ; | ||||
| 
 | ||||
|      rvsyncss_fpga  #(1) sync_inst | ||||
|      ( | ||||
|       .gw_clk      (gw_clk[i/4]), | ||||
|       .rawclk      (clk), | ||||
|       .clken       (intenable_clk_enable_grp[i/4]), | ||||
|       .dout        (extintsrc_req_sync[i]), | ||||
|       .din         (extintsrc_req[i]), | ||||
|       .*) ; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //     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)); | ||||
|         el2_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]) | ||||
|                             ); | ||||
| 
 | ||||
|         el2_configurable_gw config_gw_inst(.*, | ||||
|                                             .gw_clk(gw_clk[i/4]), | ||||
|                                             .rawclk(clk), | ||||
|                                             .clken (intenable_clk_enable_grp[i/4]), | ||||
|                                             .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 : INT_ZERO | ||||
|      assign intpriority_reg_we[i] =  1'b0 ; | ||||
|  | @ -248,6 +271,8 @@ for (i=0; i<pt.PIC_TOTAL_INT_PLUS1 ; i++) begin  : SETREG | |||
|      assign intpriority_reg[i] = {INTPRIORITY_BITS{1'b0}} ; | ||||
|      assign intenable_reg[i]   = 1'b0 ; | ||||
|      assign extintsrc_req_gw[i] = 1'b0 ; | ||||
|      assign extintsrc_req_sync[i]    = 1'b0 ; | ||||
|      assign intenable_clk_enable[i] = 1'b0; | ||||
|  end | ||||
| 
 | ||||
| 
 | ||||
|  | @ -266,10 +291,14 @@ end | |||
| if (pt.PIC_2CYCLE == 1) begin : genblock | ||||
|         logic [NUM_LEVELS/2:0] [pt.PIC_TOTAL_INT_PLUS1+2:0] [INTPRIORITY_BITS-1:0] level_intpend_w_prior_en; | ||||
|         logic [NUM_LEVELS/2:0] [pt.PIC_TOTAL_INT_PLUS1+2:0] [ID_BITS-1:0]          level_intpend_id; | ||||
|         logic [NUM_LEVELS:NUM_LEVELS/2] [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] [INTPRIORITY_BITS-1:0] levelx_intpend_w_prior_en; | ||||
|         logic [NUM_LEVELS:NUM_LEVELS/2] [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] [ID_BITS-1:0]          levelx_intpend_id; | ||||
| 
 | ||||
|         assign level_intpend_w_prior_en[0][pt.PIC_TOTAL_INT_PLUS1+2:0] = {4'b0,4'b0,4'b0,intpend_w_prior_en[pt.PIC_TOTAL_INT_PLUS1-1:0]} ; | ||||
|         assign level_intpend_id[0][pt.PIC_TOTAL_INT_PLUS1+2:0]         = {8'b0,8'b0,8'b0,intpend_id[pt.PIC_TOTAL_INT_PLUS1-1:0]} ; | ||||
| 
 | ||||
|         logic [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0] [INTPRIORITY_BITS-1:0] l2_intpend_w_prior_en_ff; | ||||
|         logic [(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0] [ID_BITS-1:0]          l2_intpend_id_ff; | ||||
| 
 | ||||
|         assign levelx_intpend_w_prior_en[NUM_LEVELS/2][(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0] = {{1*INTPRIORITY_BITS{1'b0}},l2_intpend_w_prior_en_ff[(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0]} ; | ||||
|         assign levelx_intpend_id[NUM_LEVELS/2][(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2))+1:0]         = {{1*ID_BITS{1'b1}},l2_intpend_id_ff[(pt.PIC_TOTAL_INT_PLUS1/2**(NUM_LEVELS/2)):0]} ; | ||||
|  | @ -326,6 +355,7 @@ else begin : genblock | |||
|         assign level_intpend_id[0][pt.PIC_TOTAL_INT_PLUS1+1:0] = {{2*ID_BITS{1'b1}},intpend_id[pt.PIC_TOTAL_INT_PLUS1-1:0]} ; | ||||
| 
 | ||||
| ///  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<=(pt.PIC_TOTAL_INT_PLUS1)/(2**(l+1)) ; m++) begin : COMPARE | ||||
|        if ( m == (pt.PIC_TOTAL_INT_PLUS1)/(2**(l+1))) begin | ||||
|  | @ -362,9 +392,14 @@ rvdffs #(1) config_reg_ff  (.*, .clk(free_clk), .en(config_reg_we), .din (config | |||
| assign intpriord  = config_reg ; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //////////////////////////////////////////////////////////////////////////
 | ||||
| // Send the interrupt to the core if it is above the thresh-hold
 | ||||
| //////////////////////////////////////////////////////////////////////////
 | ||||
| ///////////////////////////////////////////////////////////
 | ||||
| /// ClaimId  Reg and Corresponding PL
 | ||||
| ///////////////////////////////////////////////////////////
 | ||||
| //
 | ||||
| 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)); | ||||
|  | @ -382,6 +417,8 @@ rvdff #(1) wake_up_ff  (.*, .clk(free_clk), .din (mhwakeup_in), .dout(mhwakeup)) | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //////////////////////////////////////////////////////////////////////////
 | ||||
| //  Reads of register.
 | ||||
| //  1- intpending
 | ||||
|  | @ -471,9 +508,10 @@ endmodule // cmp_and_mux | |||
| 
 | ||||
| 
 | ||||
| module el2_configurable_gw ( | ||||
|                              input logic clk, | ||||
|                              input logic gw_clk, | ||||
|                              input logic rawclk, | ||||
|                              input logic clken, | ||||
|                              input logic rst_l, | ||||
| 
 | ||||
|                              input logic extintsrc_req_sync , | ||||
|                              input logic meigwctrl_polarity , | ||||
|                              input logic meigwctrl_type , | ||||
|  | @ -486,7 +524,8 @@ module el2_configurable_gw ( | |||
|   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)); | ||||
|   rvdff_fpga #(1) int_pend_ff        (.*, .clk(gw_clk), .rawclk(rawclk), .clken(clken), .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) ; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -34,14 +34,18 @@ import el2_pkg::*; | |||
|    input logic [31:1]           nmi_vec, | ||||
|    output logic                 core_rst_l,   // This is "rst_l | dbg_rst_l"
 | ||||
| 
 | ||||
|    output logic                 active_l2clk, | ||||
|    output logic                 free_l2clk, | ||||
| 
 | ||||
|    output logic [31:0] trace_rv_i_insn_ip, | ||||
|    output logic [31:0] trace_rv_i_address_ip, | ||||
|    output logic [1:0]  trace_rv_i_valid_ip, | ||||
|    output logic [1:0]  trace_rv_i_exception_ip, | ||||
|    output logic   trace_rv_i_valid_ip, | ||||
|    output logic   trace_rv_i_exception_ip, | ||||
|    output logic [4:0]  trace_rv_i_ecause_ip, | ||||
|    output logic [1:0]  trace_rv_i_interrupt_ip, | ||||
|    output logic   trace_rv_i_interrupt_ip, | ||||
|    output logic [31:0] trace_rv_i_tval_ip, | ||||
| 
 | ||||
| 
 | ||||
|    output logic                 dccm_clk_override, | ||||
|    output logic                 icm_clk_override, | ||||
|    output logic                 dec_tlu_core_ecc_disable, | ||||
|  | @ -304,6 +308,7 @@ import el2_pkg::*; | |||
|    output logic [1:0]                   dma_axi_rresp, | ||||
|    output logic                         dma_axi_rlast, | ||||
| 
 | ||||
| 
 | ||||
|  //// AHB LITE BUS
 | ||||
|    output logic [31:0]           haddr, | ||||
|    output logic [2:0]            hburst, | ||||
|  | @ -366,16 +371,11 @@ import el2_pkg::*; | |||
|    input   logic                 dbg_bus_clk_en, | ||||
|    input   logic                 dma_bus_clk_en, | ||||
| 
 | ||||
| 
 | ||||
|    // Debug ports
 | ||||
|    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
 | ||||
|    // outputs from the dbg back to jtag
 | ||||
|    output logic [31:0]           dmi_reg_rdata, | ||||
|    input logic                   dmi_hard_reset, | ||||
| 
 | ||||
|    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 logic [31:0]          dmi_reg_rdata, | ||||
| 
 | ||||
|    input logic [pt.PIC_TOTAL_INT:1]           extintsrc_req, | ||||
|    input logic                   timer_int, | ||||
|  | @ -386,8 +386,6 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| `define ADDRWIDTH 32 | ||||
| 
 | ||||
|    logic [63:0]                  hwdata_nc; | ||||
|    //----------------------------------------------------------------------
 | ||||
|    //
 | ||||
|  | @ -517,6 +515,7 @@ import el2_pkg::*; | |||
|    logic [1:0]                   dma_axi_arburst_int; | ||||
|    logic                         dma_axi_rready_int; | ||||
| 
 | ||||
| 
 | ||||
| // Icache debug
 | ||||
|    logic [70:0] ifu_ic_debug_rd_data; // diagnostic icache read data
 | ||||
|    logic ifu_ic_debug_rd_data_valid; // diagnostic icache read data valid
 | ||||
|  | @ -528,8 +527,7 @@ import el2_pkg::*; | |||
|    logic  [31:0] gpr_i0_rs1_d; | ||||
|    logic  [31:0] gpr_i0_rs2_d; | ||||
| 
 | ||||
|    logic [31:0] dec_i0_rs1_bypass_data_d; | ||||
|    logic [31:0] dec_i0_rs2_bypass_data_d; | ||||
|    logic [31:0] dec_i0_result_r; | ||||
|    logic [31:0] exu_i0_result_x; | ||||
|    logic [31:1] exu_i0_pc_x; | ||||
|    logic [31:1] exu_npc_r; | ||||
|  | @ -546,10 +544,11 @@ import el2_pkg::*; | |||
|    logic         dec_i0_select_pc_d; | ||||
| 
 | ||||
|    logic [31:1] dec_i0_pc_d; | ||||
|    logic [1:0]  dec_i0_rs1_bypass_en_d; | ||||
|    logic [1:0]  dec_i0_rs2_bypass_en_d; | ||||
|    logic [3:0]  dec_i0_rs1_bypass_en_d; | ||||
|    logic [3:0]  dec_i0_rs2_bypass_en_d; | ||||
| 
 | ||||
|    logic         dec_i0_alu_decode_d; | ||||
|    logic         dec_i0_branch_d; | ||||
| 
 | ||||
|    logic         ifu_miss_state_idle; | ||||
|    logic         dec_tlu_flush_noredir_r; | ||||
|  | @ -568,6 +567,7 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
|    el2_lsu_pkt_t    lsu_p; | ||||
|    logic             dec_qual_lsu_d; | ||||
| 
 | ||||
|    logic        dec_lsu_valid_raw_d; | ||||
|    logic [11:0] dec_lsu_offset_d; | ||||
|  | @ -582,6 +582,7 @@ import el2_pkg::*; | |||
|    logic         lsu_load_stall_any;       // This is for blocking loads
 | ||||
|    logic         lsu_store_stall_any;      // This is for blocking stores
 | ||||
|    logic         lsu_idle_any;             // doesn't include DMA
 | ||||
|    logic         lsu_active;               // lsu is active. used for clock
 | ||||
| 
 | ||||
| 
 | ||||
|    logic [31:1]  lsu_fir_addr;        // fast interrupt address
 | ||||
|  | @ -597,11 +598,13 @@ import el2_pkg::*; | |||
|    logic [31:0]                          lsu_nonblock_load_data; | ||||
| 
 | ||||
|    logic        dec_csr_ren_d; | ||||
|    logic [31:0] dec_csr_rddata_d; | ||||
| 
 | ||||
|    logic [31:0] exu_csr_rs1_x; | ||||
| 
 | ||||
|    logic        dec_tlu_i0_commit_cmt; | ||||
|    logic        dec_tlu_flush_lower_r; | ||||
|    logic        dec_tlu_flush_lower_wb; | ||||
|    logic        dec_tlu_i0_kill_writeb_r;     // I0 is flushed, don't writeback any results to arch state
 | ||||
|    logic        dec_tlu_fence_i_r;            // flush is a fence_i rfnpc, flush icache
 | ||||
| 
 | ||||
|  | @ -674,7 +677,7 @@ import el2_pkg::*; | |||
|    logic [1:0]  ifu_i0_icaf_type; | ||||
| 
 | ||||
| 
 | ||||
|    logic        ifu_i0_icaf_f1; | ||||
|    logic        ifu_i0_icaf_second; | ||||
|    logic        ifu_i0_dbecc; | ||||
|    logic        iccm_dma_sb_error; | ||||
| 
 | ||||
|  | @ -683,6 +686,9 @@ import el2_pkg::*; | |||
|    logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr; | ||||
|    logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag; | ||||
| 
 | ||||
|    logic [$clog2(pt.BTB_SIZE)-1:0] ifu_i0_fa_index; | ||||
|    logic [$clog2(pt.BTB_SIZE)-1:0] dec_fa_error_index; // Fully associative btb error index
 | ||||
| 
 | ||||
| 
 | ||||
|    el2_predict_pkt_t dec_i0_predict_p_d; | ||||
| 
 | ||||
|  | @ -690,7 +696,7 @@ import el2_pkg::*; | |||
|    logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] i0_predict_index_d;     // DEC predict index
 | ||||
|    logic [pt.BTB_BTAG_SIZE-1:0] i0_predict_btag_d;               // DEC predict branch tag
 | ||||
| 
 | ||||
|       // PIC ports
 | ||||
|    // PIC ports
 | ||||
|    logic                  picm_wren; | ||||
|    logic                  picm_rden; | ||||
|    logic                  picm_mken; | ||||
|  | @ -699,7 +705,6 @@ import el2_pkg::*; | |||
|    logic [31:0]           picm_wr_data; | ||||
|    logic [31:0]           picm_rd_data; | ||||
| 
 | ||||
| 
 | ||||
|    // feature disable from mfdc
 | ||||
|    logic  dec_tlu_external_ldfwd_disable; // disable external load forwarding
 | ||||
|    logic  dec_tlu_bpred_disable; | ||||
|  | @ -716,6 +721,8 @@ import el2_pkg::*; | |||
|    logic  dec_tlu_dccm_clk_override; | ||||
|    logic  dec_tlu_icm_clk_override; | ||||
| 
 | ||||
|    logic  dec_tlu_picio_clk_override; | ||||
| 
 | ||||
|    assign        dccm_clk_override = dec_tlu_dccm_clk_override;   // dccm memory
 | ||||
|    assign        icm_clk_override = dec_tlu_icm_clk_override;    // icache/iccm memory
 | ||||
| 
 | ||||
|  | @ -723,7 +730,7 @@ import el2_pkg::*; | |||
| 
 | ||||
|    logic [31:0]            dbg_cmd_addr;              // the address of the debug command to used by the core
 | ||||
|    logic [31:0]            dbg_cmd_wrdata;            // If the debug command is a write command, this has the data to be written to the CSR/GPR
 | ||||
|    logic                   dbg_cmd_valid;             // command is being driven by the dbg module. One pulse. Only dirven when core_halted has been seen
 | ||||
|    logic                   dbg_cmd_valid;             // commad is being driven by the dbg module. One pulse. Only dirven when core_halted has been seen
 | ||||
|    logic                   dbg_cmd_write;             // 1: write command; 0: read_command
 | ||||
|    logic [1:0]             dbg_cmd_type;              // 0:gpr 1:csr 2: memory
 | ||||
|    logic [1:0]             dbg_cmd_size;              // size of the abstract mem access debug command
 | ||||
|  | @ -746,11 +753,11 @@ import el2_pkg::*; | |||
|    logic                   dec_dbg_cmd_done;          // This will be treated like a valid signal
 | ||||
|    logic                   dec_dbg_cmd_fail;          // Abstract command failed
 | ||||
|    logic                   dec_tlu_mpc_halted_only;   // Only halted due to MPC
 | ||||
|    logic                   dec_tlu_dbg_halted;            // The core has finished the queiscing sequence. Sticks this signal high
 | ||||
|    logic                   dec_tlu_dbg_halted;        // The core has finished the queiscing sequence. Sticks this signal high
 | ||||
|    logic                   dec_tlu_resume_ack; | ||||
|    logic                   dec_tlu_debug_mode;        // Core is in debug mode
 | ||||
|    logic                   dec_debug_wdata_rs1_d; | ||||
|    logic                   dec_tlu_force_halt;  // halt has been forced
 | ||||
|    logic                   dec_tlu_force_halt;        // halt has been forced
 | ||||
| 
 | ||||
|    logic [1:0]             dec_data_en; | ||||
|    logic [1:0]             dec_ctl_en; | ||||
|  | @ -776,7 +783,8 @@ import el2_pkg::*; | |||
|    logic                   ifu_pmu_bus_trxn; | ||||
| 
 | ||||
|    logic                   active_state; | ||||
|    logic                   free_clk, active_clk; | ||||
|    logic                   free_clk; | ||||
|    logic                   active_clk; | ||||
|    logic                   dec_pause_state_cg; | ||||
| 
 | ||||
|    logic                   lsu_nonblock_load_data_error; | ||||
|  | @ -787,24 +795,37 @@ import el2_pkg::*; | |||
|    logic [31:2]            dec_tlu_meihap; | ||||
|    logic                   dec_extint_stall; | ||||
| 
 | ||||
|    el2_trace_pkt_t  rv_trace_pkt; | ||||
|    el2_trace_pkt_t  trace_rv_trace_pkt; | ||||
| 
 | ||||
| 
 | ||||
|    logic                   lsu_fastint_stall_any; | ||||
| 
 | ||||
| 
 | ||||
|    logic [7:0]  pic_claimid; | ||||
|    logic [3:0]  pic_pl, dec_tlu_meicurpl, dec_tlu_meipt; | ||||
|    logic        mexintpend; | ||||
|    logic        mhwakeup; | ||||
| 
 | ||||
|    logic        dma_active; | ||||
| 
 | ||||
|    //assign lsu_fastint_stall_any = 1'b0;
 | ||||
| 
 | ||||
|    assign active_state = (~dec_pause_state_cg | dec_tlu_flush_lower_r)  | dec_tlu_misc_clk_override; | ||||
|    logic        pause_state; | ||||
|    logic        halt_state; | ||||
| 
 | ||||
|    rvoclkhdr free_cg   ( .en(1'b1),         .l1clk(free_clk), .* ); | ||||
|    rvoclkhdr active_cg ( .en(active_state), .l1clk(active_clk), .* ); | ||||
|    logic        dec_tlu_core_empty; | ||||
| 
 | ||||
|    assign pause_state = dec_pause_state_cg & ~(dma_active | lsu_active) & dec_tlu_core_empty; | ||||
| 
 | ||||
|    assign halt_state = o_cpu_halt_status & ~(dma_active | lsu_active); | ||||
| 
 | ||||
| 
 | ||||
|    assign active_state = (~(halt_state | pause_state) | dec_tlu_flush_lower_r | dec_tlu_flush_lower_wb)  | dec_tlu_misc_clk_override; | ||||
| 
 | ||||
|    rvoclkhdr free_cg2   ( .clk(clk), .en(1'b1),         .l1clk(free_l2clk), .* ); | ||||
|    rvoclkhdr active_cg2 ( .clk(clk), .en(active_state), .l1clk(active_l2clk), .* ); | ||||
| 
 | ||||
| // all other clock headers are 1st level
 | ||||
|    rvoclkhdr free_cg1   ( .clk(free_l2clk),     .en(1'b1), .l1clk(free_clk), .* ); | ||||
|    rvoclkhdr active_cg1 ( .clk(active_l2clk),   .en(1'b1), .l1clk(active_clk), .* ); | ||||
| 
 | ||||
| 
 | ||||
|    assign core_dbg_cmd_done = dma_dbg_cmd_done | dec_dbg_cmd_done; | ||||
|  | @ -812,6 +833,8 @@ import el2_pkg::*; | |||
|    assign core_dbg_rddata[31:0] = dma_dbg_cmd_done ? dma_dbg_rddata[31:0] : dec_dbg_rddata[31:0]; | ||||
| 
 | ||||
|    el2_dbg #(.pt(pt)) dbg ( | ||||
|       .rst_l(core_rst_l), | ||||
|       .clk(free_l2clk), | ||||
|       .clk_override(dec_tlu_misc_clk_override), | ||||
| 
 | ||||
|       // AXI signals
 | ||||
|  | @ -824,111 +847,124 @@ import el2_pkg::*; | |||
|       .sb_axi_rvalid(sb_axi_rvalid_int), | ||||
|       .sb_axi_rdata(sb_axi_rdata_int[63:0]), | ||||
|       .sb_axi_rresp(sb_axi_rresp_int[1:0]), | ||||
| 
 | ||||
|       .* | ||||
|    ); | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_ASSERT_ON | ||||
|       assert_fetch_indbghalt: assert #0 (~(ifu.ifc_fetch_req_f & dec.tlu.dbg_tlu_halted_f & ~dec.tlu.dcsr_single_step_running)) else $display("ERROR: Fetching in dBG halt!"); | ||||
| `endif | ||||
| 
 | ||||
|    assign core_rst_l = rst_l & (dbg_core_rst_l | scan_mode); | ||||
|    // -----------------   DEBUG END -----------------------------
 | ||||
| 
 | ||||
|    assign core_rst_l = rst_l & (dbg_core_rst_l | scan_mode); | ||||
|    // fetch
 | ||||
|    el2_ifu #(.pt(pt)) ifu ( | ||||
|       .rst_l(core_rst_l), | ||||
|       .dec_tlu_flush_err_wb       (dec_tlu_flush_err_r      ), | ||||
|       .dec_tlu_flush_noredir_wb   (dec_tlu_flush_noredir_r  ), | ||||
|       .dec_tlu_fence_i_wb         (dec_tlu_fence_i_r        ), | ||||
|       .dec_tlu_flush_leak_one_wb  (dec_tlu_flush_leak_one_r ), | ||||
|       .dec_tlu_flush_lower_wb     (dec_tlu_flush_lower_r    ), | ||||
|                             .clk(active_l2clk), | ||||
|                             .rst_l(core_rst_l), | ||||
|                             .dec_tlu_flush_err_wb       (dec_tlu_flush_err_r      ), | ||||
|                             .dec_tlu_flush_noredir_wb   (dec_tlu_flush_noredir_r  ), | ||||
|                             .dec_tlu_fence_i_wb         (dec_tlu_fence_i_r        ), | ||||
|                             .dec_tlu_flush_leak_one_wb  (dec_tlu_flush_leak_one_r ), | ||||
|                             .dec_tlu_flush_lower_wb     (dec_tlu_flush_lower_r    ), | ||||
| 
 | ||||
|       // AXI signals
 | ||||
|       .ifu_axi_arready(ifu_axi_arready_int), | ||||
|       .ifu_axi_rvalid(ifu_axi_rvalid_int), | ||||
|       .ifu_axi_rid(ifu_axi_rid_int[pt.IFU_BUS_TAG-1:0]), | ||||
|       .ifu_axi_rdata(ifu_axi_rdata_int[63:0]), | ||||
|       .ifu_axi_rresp(ifu_axi_rresp_int[1:0]), | ||||
|                             // AXI signals
 | ||||
|                             .ifu_axi_arready(ifu_axi_arready_int), | ||||
|                             .ifu_axi_rvalid(ifu_axi_rvalid_int), | ||||
|                             .ifu_axi_rid(ifu_axi_rid_int[pt.IFU_BUS_TAG-1:0]), | ||||
|                             .ifu_axi_rdata(ifu_axi_rdata_int[63:0]), | ||||
|                             .ifu_axi_rresp(ifu_axi_rresp_int[1:0]), | ||||
| 
 | ||||
|        .* | ||||
|    ); | ||||
|                             .* | ||||
|                             ); | ||||
| 
 | ||||
| 
 | ||||
|    el2_dec #(.pt(pt)) dec ( | ||||
|             .dbg_cmd_wrdata(dbg_cmd_wrdata[1:0]), | ||||
|             .rst_l(core_rst_l), | ||||
|             .* | ||||
|             ); | ||||
|                             .clk(active_l2clk), | ||||
|                             .dbg_cmd_wrdata(dbg_cmd_wrdata[1:0]), | ||||
|                             .rst_l(core_rst_l), | ||||
|                             .* | ||||
|                             ); | ||||
| 
 | ||||
|    el2_exu #(.pt(pt)) exu ( | ||||
|       .rst_l(core_rst_l), | ||||
|       .* | ||||
|    ); | ||||
|                             .clk(active_l2clk), | ||||
|                             .rst_l(core_rst_l), | ||||
|                             .* | ||||
|                             ); | ||||
| 
 | ||||
|    el2_lsu #(.pt(pt)) lsu ( | ||||
|       .rst_l(core_rst_l), | ||||
|       .clk_override(dec_tlu_lsu_clk_override), | ||||
|       .dec_tlu_i0_kill_writeb_r(dec_tlu_i0_kill_writeb_r), | ||||
|                             .clk(active_l2clk), | ||||
|                             .rst_l(core_rst_l), | ||||
|                             .clk_override(dec_tlu_lsu_clk_override), | ||||
|                             .dec_tlu_i0_kill_writeb_r(dec_tlu_i0_kill_writeb_r), | ||||
| 
 | ||||
|       // AXI signals
 | ||||
|       .lsu_axi_awready(lsu_axi_awready_int), | ||||
|       .lsu_axi_wready(lsu_axi_wready_int), | ||||
|       .lsu_axi_bvalid(lsu_axi_bvalid_int), | ||||
|       .lsu_axi_bid(lsu_axi_bid_int[pt.LSU_BUS_TAG-1:0]), | ||||
|       .lsu_axi_bresp(lsu_axi_bresp_int[1:0]), | ||||
|                             // AXI signals
 | ||||
|                             .lsu_axi_awready(lsu_axi_awready_int), | ||||
|                             .lsu_axi_wready(lsu_axi_wready_int), | ||||
|                             .lsu_axi_bvalid(lsu_axi_bvalid_int), | ||||
|                             .lsu_axi_bid(lsu_axi_bid_int[pt.LSU_BUS_TAG-1:0]), | ||||
|                             .lsu_axi_bresp(lsu_axi_bresp_int[1:0]), | ||||
| 
 | ||||
|       .lsu_axi_arready(lsu_axi_arready_int), | ||||
|       .lsu_axi_rvalid(lsu_axi_rvalid_int), | ||||
|       .lsu_axi_rid(lsu_axi_rid_int[pt.LSU_BUS_TAG-1:0]), | ||||
|       .lsu_axi_rdata(lsu_axi_rdata_int[63:0]), | ||||
|       .lsu_axi_rresp(lsu_axi_rresp_int[1:0]), | ||||
|       .lsu_axi_rlast(lsu_axi_rlast_int), | ||||
|                             .lsu_axi_arready(lsu_axi_arready_int), | ||||
|                             .lsu_axi_rvalid(lsu_axi_rvalid_int), | ||||
|                             .lsu_axi_rid(lsu_axi_rid_int[pt.LSU_BUS_TAG-1:0]), | ||||
|                             .lsu_axi_rdata(lsu_axi_rdata_int[63:0]), | ||||
|                             .lsu_axi_rresp(lsu_axi_rresp_int[1:0]), | ||||
|                             .lsu_axi_rlast(lsu_axi_rlast_int), | ||||
| 
 | ||||
|       .* | ||||
|                             .* | ||||
| 
 | ||||
|                             ); | ||||
| 
 | ||||
|    ); | ||||
| 
 | ||||
|    el2_pic_ctrl  #(.pt(pt)) pic_ctrl_inst ( | ||||
|                   .clk_override(dec_tlu_pic_clk_override), | ||||
|                   .picm_mken (picm_mken), | ||||
|                   .extintsrc_req({extintsrc_req[pt.PIC_TOTAL_INT:1],1'b0}), | ||||
|                   .pl(pic_pl[3:0]), | ||||
|                   .claimid(pic_claimid[7:0]), | ||||
|                   .meicurpl(dec_tlu_meicurpl[3:0]), | ||||
|                   .meipt(dec_tlu_meipt[3:0]), | ||||
|                   .rst_l(core_rst_l), | ||||
|                      .*); | ||||
|                                             .clk(free_l2clk), | ||||
|                                             .clk_override(dec_tlu_pic_clk_override), | ||||
|                                             .io_clk_override(dec_tlu_picio_clk_override), | ||||
|                                             .picm_mken (picm_mken), | ||||
|                                             .extintsrc_req({extintsrc_req[pt.PIC_TOTAL_INT:1],1'b0}), | ||||
|                                             .pl(pic_pl[3:0]), | ||||
|                                             .claimid(pic_claimid[7:0]), | ||||
|                                             .meicurpl(dec_tlu_meicurpl[3:0]), | ||||
|                                             .meipt(dec_tlu_meipt[3:0]), | ||||
|                                             .rst_l(core_rst_l), | ||||
|                                             .*); | ||||
| 
 | ||||
|    el2_dma_ctrl #(.pt(pt)) dma_ctrl ( | ||||
|       .rst_l(core_rst_l), | ||||
|       .clk_override(dec_tlu_misc_clk_override), | ||||
|                                       .clk(free_l2clk), | ||||
|                                       .rst_l(core_rst_l), | ||||
|                                       .clk_override(dec_tlu_misc_clk_override), | ||||
| 
 | ||||
|       // AXI signals
 | ||||
|       .dma_axi_awvalid(dma_axi_awvalid_int), | ||||
|       .dma_axi_awid(dma_axi_awid_int[pt.DMA_BUS_TAG-1:0]), | ||||
|       .dma_axi_awaddr(dma_axi_awaddr_int[31:0]), | ||||
|       .dma_axi_awsize(dma_axi_awsize_int[2:0]), | ||||
|       .dma_axi_wvalid(dma_axi_wvalid_int), | ||||
|       .dma_axi_wdata(dma_axi_wdata_int[63:0]), | ||||
|       .dma_axi_wstrb(dma_axi_wstrb_int[7:0]), | ||||
|       .dma_axi_bready(dma_axi_bready_int), | ||||
|                                       // AXI signals
 | ||||
|                                       .dma_axi_awvalid(dma_axi_awvalid_int), | ||||
|                                       .dma_axi_awid(dma_axi_awid_int[pt.DMA_BUS_TAG-1:0]), | ||||
|                                       .dma_axi_awaddr(dma_axi_awaddr_int[31:0]), | ||||
|                                       .dma_axi_awsize(dma_axi_awsize_int[2:0]), | ||||
|                                       .dma_axi_wvalid(dma_axi_wvalid_int), | ||||
|                                       .dma_axi_wdata(dma_axi_wdata_int[63:0]), | ||||
|                                       .dma_axi_wstrb(dma_axi_wstrb_int[7:0]), | ||||
|                                       .dma_axi_bready(dma_axi_bready_int), | ||||
| 
 | ||||
|       .dma_axi_arvalid(dma_axi_arvalid_int), | ||||
|       .dma_axi_arid(dma_axi_arid_int[pt.DMA_BUS_TAG-1:0]), | ||||
|       .dma_axi_araddr(dma_axi_araddr_int[31:0]), | ||||
|       .dma_axi_arsize(dma_axi_arsize_int[2:0]), | ||||
|       .dma_axi_rready(dma_axi_rready_int), | ||||
|                                       .dma_axi_arvalid(dma_axi_arvalid_int), | ||||
|                                       .dma_axi_arid(dma_axi_arid_int[pt.DMA_BUS_TAG-1:0]), | ||||
|                                       .dma_axi_araddr(dma_axi_araddr_int[31:0]), | ||||
|                                       .dma_axi_arsize(dma_axi_arsize_int[2:0]), | ||||
|                                       .dma_axi_rready(dma_axi_rready_int), | ||||
| 
 | ||||
|       .* | ||||
|    ); | ||||
|                                       .* | ||||
|                                       ); | ||||
| 
 | ||||
|    if (pt.BUILD_AHB_LITE == 1) begin: Gen_AXI_To_AHB | ||||
| 
 | ||||
|       // AXI4 -> AHB Gasket for LSU
 | ||||
|       axi4_to_ahb #(.pt(pt), | ||||
|                     .TAG(pt.LSU_BUS_TAG)) lsu_axi4_to_ahb ( | ||||
| 
 | ||||
|          .clk(free_l2clk), | ||||
|          .free_clk(free_clk), | ||||
|          .rst_l(core_rst_l), | ||||
|          .clk_override(dec_tlu_bus_clk_override), | ||||
|          .bus_clk_en(lsu_bus_clk_en), | ||||
|          .dec_tlu_force_halt(dec_tlu_force_halt), | ||||
| 
 | ||||
|          // AXI Write Channels
 | ||||
|          .axi_awvalid(lsu_axi_awvalid), | ||||
|  | @ -983,9 +1019,12 @@ import el2_pkg::*; | |||
| 
 | ||||
|       axi4_to_ahb #(.pt(pt), | ||||
|                     .TAG(pt.IFU_BUS_TAG)) ifu_axi4_to_ahb ( | ||||
|          .clk(clk), | ||||
|          .clk(free_l2clk), | ||||
|          .free_clk(free_clk), | ||||
|          .rst_l(core_rst_l), | ||||
|          .clk_override(dec_tlu_bus_clk_override), | ||||
|          .bus_clk_en(ifu_bus_clk_en), | ||||
|          .dec_tlu_force_halt(dec_tlu_force_halt), | ||||
| 
 | ||||
|           // AHB-Lite signals
 | ||||
|          .ahb_haddr(haddr[31:0]), | ||||
|  | @ -1040,8 +1079,12 @@ import el2_pkg::*; | |||
|       // AXI4 -> AHB Gasket for System Bus
 | ||||
|       axi4_to_ahb #(.pt(pt), | ||||
|                     .TAG(pt.SB_BUS_TAG)) sb_axi4_to_ahb ( | ||||
|          .clk(free_l2clk), | ||||
|          .free_clk(free_clk), | ||||
|          .rst_l(dbg_rst_l), | ||||
|          .clk_override(dec_tlu_bus_clk_override), | ||||
|          .bus_clk_en(dbg_bus_clk_en), | ||||
|          .dec_tlu_force_halt(1'b0), | ||||
| 
 | ||||
|          // AXI Write Channels
 | ||||
|          .axi_awvalid(sb_axi_awvalid), | ||||
|  | @ -1096,6 +1139,8 @@ import el2_pkg::*; | |||
|       //AHB -> AXI4 Gasket for DMA
 | ||||
|       ahb_to_axi4 #(.pt(pt), | ||||
|                     .TAG(pt.DMA_BUS_TAG)) dma_ahb_to_axi4 ( | ||||
|          .clk(free_l2clk), | ||||
|          .rst_l(core_rst_l), | ||||
|          .clk_override(dec_tlu_bus_clk_override), | ||||
|          .bus_clk_en(dma_bus_clk_en), | ||||
| 
 | ||||
|  | @ -1219,7 +1264,7 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
| if  (pt.BUILD_AHB_LITE == 1) begin | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_ASSERT_ON | ||||
|    property ahb_trxn_aligned; | ||||
|      @(posedge clk) disable iff(~rst_l) (lsu_htrans[1:0] != 2'b0)  |-> ((lsu_hsize[2:0] == 3'h0)                              | | ||||
|                                                                         ((lsu_hsize[2:0] == 3'h1) & (lsu_haddr[0] == 1'b0))   | | ||||
|  | @ -1244,15 +1289,19 @@ if  (pt.BUILD_AHB_LITE == 1) begin | |||
|       // unpack packet
 | ||||
|       // also need retires_p==3
 | ||||
| 
 | ||||
|       assign trace_rv_i_insn_ip[31:0]     = rv_trace_pkt.rv_i_insn_ip[31:0]; | ||||
|       assign trace_rv_i_address_ip[31:0]  = rv_trace_pkt.rv_i_address_ip[31:0]; | ||||
|       assign trace_rv_i_valid_ip[1:0]     = rv_trace_pkt.rv_i_valid_ip[1:0]; | ||||
|       assign trace_rv_i_exception_ip[1:0] = rv_trace_pkt.rv_i_exception_ip[1:0]; | ||||
|       assign trace_rv_i_ecause_ip[4:0]    = rv_trace_pkt.rv_i_ecause_ip[4:0]; | ||||
|       assign trace_rv_i_interrupt_ip[1:0] = rv_trace_pkt.rv_i_interrupt_ip[1:0]; | ||||
|       assign trace_rv_i_tval_ip[31:0]     = rv_trace_pkt.rv_i_tval_ip[31:0]; | ||||
|       assign trace_rv_i_insn_ip[31:0]     = trace_rv_trace_pkt.trace_rv_i_insn_ip[31:0]; | ||||
| 
 | ||||
|       assign trace_rv_i_address_ip[31:0]  = trace_rv_trace_pkt.trace_rv_i_address_ip[31:0]; | ||||
| 
 | ||||
|       assign trace_rv_i_valid_ip     = trace_rv_trace_pkt.trace_rv_i_valid_ip; | ||||
| 
 | ||||
|       assign trace_rv_i_exception_ip = trace_rv_trace_pkt.trace_rv_i_exception_ip; | ||||
| 
 | ||||
|       assign trace_rv_i_ecause_ip[4:0]    = trace_rv_trace_pkt.trace_rv_i_ecause_ip[4:0]; | ||||
| 
 | ||||
|       assign trace_rv_i_interrupt_ip = trace_rv_trace_pkt.trace_rv_i_interrupt_ip; | ||||
| 
 | ||||
|       assign trace_rv_i_tval_ip[31:0]     = trace_rv_trace_pkt.trace_rv_i_tval_ip[31:0]; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -26,22 +26,22 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
| ) | ||||
| ( | ||||
|    input logic                       clk, | ||||
|    input logic                       rst_l, | ||||
|    input logic                       dbg_rst_l, | ||||
|    input logic [31:1]                rst_vec, | ||||
|    input logic                       nmi_int, | ||||
|    input logic [31:1]                nmi_vec, | ||||
|    input logic [31:1]                jtag_id, | ||||
|    input logic                             clk, | ||||
|    input logic                             rst_l, | ||||
|    input logic                             dbg_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 [31:0] trace_rv_i_insn_ip, | ||||
|    output logic [31:0] trace_rv_i_address_ip, | ||||
|    output logic [1:0]  trace_rv_i_valid_ip, | ||||
|    output logic [1:0]  trace_rv_i_exception_ip, | ||||
|    output logic [4:0]  trace_rv_i_ecause_ip, | ||||
|    output logic [1:0]  trace_rv_i_interrupt_ip, | ||||
|    output logic [31:0] trace_rv_i_tval_ip, | ||||
|    output logic [31:0]                     trace_rv_i_insn_ip, | ||||
|    output logic [31:0]                     trace_rv_i_address_ip, | ||||
|    output logic                            trace_rv_i_valid_ip, | ||||
|    output logic                            trace_rv_i_exception_ip, | ||||
|    output logic [4:0]                      trace_rv_i_ecause_ip, | ||||
|    output logic                            trace_rv_i_interrupt_ip, | ||||
|    output logic [31:0]                     trace_rv_i_tval_ip, | ||||
| 
 | ||||
|    // Bus signals
 | ||||
| `ifdef RV_BUILD_AXI4 | ||||
|  | @ -49,7 +49,7 @@ import el2_pkg::*; | |||
|    // AXI Write Channels
 | ||||
|    output logic                            lsu_axi_awvalid, | ||||
|    input  logic                            lsu_axi_awready, | ||||
|    output logic [pt.LSU_BUS_TAG-1:0]      lsu_axi_awid, | ||||
|    output logic [pt.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, | ||||
|  | @ -69,12 +69,12 @@ import el2_pkg::*; | |||
|    input  logic                            lsu_axi_bvalid, | ||||
|    output logic                            lsu_axi_bready, | ||||
|    input  logic [1:0]                      lsu_axi_bresp, | ||||
|    input  logic [pt.LSU_BUS_TAG-1:0]      lsu_axi_bid, | ||||
|    input  logic [pt.LSU_BUS_TAG-1:0]       lsu_axi_bid, | ||||
| 
 | ||||
|    // AXI Read Channels
 | ||||
|    output logic                            lsu_axi_arvalid, | ||||
|    input  logic                            lsu_axi_arready, | ||||
|    output logic [pt.LSU_BUS_TAG-1:0]      lsu_axi_arid, | ||||
|    output logic [pt.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, | ||||
|  | @ -87,7 +87,7 @@ import el2_pkg::*; | |||
| 
 | ||||
|    input  logic                            lsu_axi_rvalid, | ||||
|    output logic                            lsu_axi_rready, | ||||
|    input  logic [pt.LSU_BUS_TAG-1:0]      lsu_axi_rid, | ||||
|    input  logic [pt.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, | ||||
|  | @ -96,7 +96,7 @@ import el2_pkg::*; | |||
|    // AXI Write Channels
 | ||||
|    output logic                            ifu_axi_awvalid, | ||||
|    input  logic                            ifu_axi_awready, | ||||
|    output logic [pt.IFU_BUS_TAG-1:0]      ifu_axi_awid, | ||||
|    output logic [pt.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, | ||||
|  | @ -116,12 +116,12 @@ import el2_pkg::*; | |||
|    input  logic                            ifu_axi_bvalid, | ||||
|    output logic                            ifu_axi_bready, | ||||
|    input  logic [1:0]                      ifu_axi_bresp, | ||||
|    input  logic [pt.IFU_BUS_TAG-1:0]      ifu_axi_bid, | ||||
|    input  logic [pt.IFU_BUS_TAG-1:0]       ifu_axi_bid, | ||||
| 
 | ||||
|    // AXI Read Channels
 | ||||
|    output logic                            ifu_axi_arvalid, | ||||
|    input  logic                            ifu_axi_arready, | ||||
|    output logic [pt.IFU_BUS_TAG-1:0]      ifu_axi_arid, | ||||
|    output logic [pt.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, | ||||
|  | @ -134,7 +134,7 @@ import el2_pkg::*; | |||
| 
 | ||||
|    input  logic                            ifu_axi_rvalid, | ||||
|    output logic                            ifu_axi_rready, | ||||
|    input  logic [pt.IFU_BUS_TAG-1:0]      ifu_axi_rid, | ||||
|    input  logic [pt.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, | ||||
|  | @ -143,7 +143,7 @@ import el2_pkg::*; | |||
|    // AXI Write Channels
 | ||||
|    output logic                            sb_axi_awvalid, | ||||
|    input  logic                            sb_axi_awready, | ||||
|    output logic [pt.SB_BUS_TAG-1:0]       sb_axi_awid, | ||||
|    output logic [pt.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, | ||||
|  | @ -163,12 +163,12 @@ import el2_pkg::*; | |||
|    input  logic                            sb_axi_bvalid, | ||||
|    output logic                            sb_axi_bready, | ||||
|    input  logic [1:0]                      sb_axi_bresp, | ||||
|    input  logic [pt.SB_BUS_TAG-1:0]       sb_axi_bid, | ||||
|    input  logic [pt.SB_BUS_TAG-1:0]        sb_axi_bid, | ||||
| 
 | ||||
|    // AXI Read Channels
 | ||||
|    output logic                            sb_axi_arvalid, | ||||
|    input  logic                            sb_axi_arready, | ||||
|    output logic [pt.SB_BUS_TAG-1:0]       sb_axi_arid, | ||||
|    output logic [pt.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, | ||||
|  | @ -181,160 +181,168 @@ import el2_pkg::*; | |||
| 
 | ||||
|    input  logic                            sb_axi_rvalid, | ||||
|    output logic                            sb_axi_rready, | ||||
|    input  logic [pt.SB_BUS_TAG-1:0]       sb_axi_rid, | ||||
|    input  logic [pt.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 [pt.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_awvalid, | ||||
|    output logic                            dma_axi_awready, | ||||
|    input  logic [pt.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, | ||||
|    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 [pt.DMA_BUS_TAG-1:0]   dma_axi_bid, | ||||
|    output logic                            dma_axi_bvalid, | ||||
|    input  logic                            dma_axi_bready, | ||||
|    output logic [1:0]                      dma_axi_bresp, | ||||
|    output logic [pt.DMA_BUS_TAG-1:0]       dma_axi_bid, | ||||
| 
 | ||||
|    // AXI Read Channels
 | ||||
|    input  logic                         dma_axi_arvalid, | ||||
|    output logic                         dma_axi_arready, | ||||
|    input  logic [pt.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, | ||||
|    input  logic                            dma_axi_arvalid, | ||||
|    output logic                            dma_axi_arready, | ||||
|    input  logic [pt.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 [pt.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_axi_rvalid, | ||||
|    input  logic                            dma_axi_rready, | ||||
|    output logic [pt.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, | ||||
|    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, | ||||
|    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, | ||||
|    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, | ||||
|    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, | ||||
|    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, | ||||
|    input  logic [63:0]                     sb_hrdata, | ||||
|    input  logic                            sb_hready, | ||||
|    input  logic                            sb_hresp, | ||||
| 
 | ||||
|    // DMA Slave
 | ||||
|    input logic                       dma_hsel, | ||||
|    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_hreadyin, | ||||
|    input logic                             dma_hsel, | ||||
|    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_hreadyin, | ||||
| 
 | ||||
|    output logic [63:0]               dma_hrdata, | ||||
|    output logic                      dma_hreadyout, | ||||
|    output logic                      dma_hresp, | ||||
|    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                             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
 | ||||
| 
 | ||||
|  // all of these test inputs are brought to top-level; must be tied off based on usage by physical design (ie. icache or not, iccm or not, dccm or not)
 | ||||
| 
 | ||||
| //   input logic                   ext_int,
 | ||||
|    input logic                       timer_int, | ||||
|    input logic                       soft_int, | ||||
|    input logic [pt.PIC_TOTAL_INT:1] extintsrc_req, | ||||
|    input                                   el2_dccm_ext_in_pkt_t  [pt.DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt, | ||||
|    input                                   el2_ccm_ext_in_pkt_t  [pt.ICCM_NUM_BANKS-1:0] iccm_ext_in_pkt, | ||||
|    input                                   el2_ic_data_ext_in_pkt_t  [pt.ICACHE_NUM_WAYS-1:0][pt.ICACHE_BANKS_WAY-1:0] ic_data_ext_in_pkt, | ||||
|    input                                   el2_ic_tag_ext_in_pkt_t  [pt.ICACHE_NUM_WAYS-1:0] ic_tag_ext_in_pkt, | ||||
| 
 | ||||
|    output logic dec_tlu_perfcnt0, // toggles when slot0 perf counter 0 has an event inc
 | ||||
|    output logic dec_tlu_perfcnt1, | ||||
|    output logic dec_tlu_perfcnt2, | ||||
|    output logic dec_tlu_perfcnt3, | ||||
|    input logic                             timer_int, | ||||
|    input logic                             soft_int, | ||||
|    input logic [pt.PIC_TOTAL_INT:1]        extintsrc_req, | ||||
| 
 | ||||
|    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
 | ||||
|    output logic                            dec_tlu_perfcnt0, // toggles when slot0 perf counter 0 has an event inc
 | ||||
|    output logic                            dec_tlu_perfcnt1, | ||||
|    output logic                            dec_tlu_perfcnt2, | ||||
|    output logic                            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
 | ||||
| 
 | ||||
|    input logic [31:4] core_id, | ||||
| 
 | ||||
|    // 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                             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
 | ||||
|    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
 | ||||
| ); | ||||
| 
 | ||||
|    logic                             active_l2clk; | ||||
|    logic                             free_l2clk; | ||||
| 
 | ||||
|    // DCCM ports
 | ||||
|    logic         dccm_wren; | ||||
|    logic         dccm_rden; | ||||
|    logic [pt.DCCM_BITS-1:0]  dccm_wr_addr_lo; | ||||
|    logic [pt.DCCM_BITS-1:0]  dccm_wr_addr_hi; | ||||
|    logic [pt.DCCM_BITS-1:0]  dccm_rd_addr_lo; | ||||
|    logic [pt.DCCM_BITS-1:0]  dccm_rd_addr_hi; | ||||
|    logic [pt.DCCM_BITS-1:0]         dccm_wr_addr_lo; | ||||
|    logic [pt.DCCM_BITS-1:0]         dccm_wr_addr_hi; | ||||
|    logic [pt.DCCM_BITS-1:0]         dccm_rd_addr_lo; | ||||
|    logic [pt.DCCM_BITS-1:0]         dccm_rd_addr_hi; | ||||
|    logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_wr_data_lo; | ||||
|    logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_wr_data_hi; | ||||
| 
 | ||||
|  | @ -352,22 +360,22 @@ import el2_pkg::*; | |||
|    logic [pt.ICACHE_NUM_WAYS-1:0]   ic_tag_valid;   // Valid from the I$ tag valid outside (in flops).
 | ||||
| 
 | ||||
|    logic [pt.ICACHE_NUM_WAYS-1:0]   ic_rd_hit;      // ic_rd_hit[3:0]
 | ||||
|    logic         ic_tag_perr;    // Ic tag parity error
 | ||||
|    logic         ic_tag_perr;                       // Ic tag parity error
 | ||||
| 
 | ||||
|    logic [pt.ICACHE_INDEX_HI:3]  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 [pt.ICACHE_NUM_WAYS-1:0]   ic_debug_way;       // Debug way. Rd or Wr.
 | ||||
|    logic [pt.ICACHE_INDEX_HI:3]  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 [pt.ICACHE_NUM_WAYS-1:0]   ic_debug_way;   // Debug way. Rd or Wr.
 | ||||
| 
 | ||||
|    logic [25:0]  ictag_debug_rd_data;// Debug icache tag.
 | ||||
|    logic [25:0]  ictag_debug_rd_data;               // Debug icache tag.
 | ||||
|    logic [pt.ICACHE_BANKS_WAY-1:0][70:0]  ic_wr_data; | ||||
|    logic [63:0]  ic_rd_data; | ||||
|    logic [70:0]  ic_debug_rd_data;  // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
 | ||||
|    logic [70:0]  ic_debug_wr_data;   // Debug wr cache.
 | ||||
|    logic [70:0]  ic_debug_rd_data;                  // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
 | ||||
|    logic [70:0]  ic_debug_wr_data;                  // Debug wr cache.
 | ||||
| 
 | ||||
|    logic [pt.ICACHE_BANKS_WAY-1:0] ic_eccerr;    // ecc error per bank
 | ||||
|    logic [pt.ICACHE_BANKS_WAY-1:0] ic_parerr;    // parity error per bank
 | ||||
|    logic [pt.ICACHE_BANKS_WAY-1:0] ic_eccerr;       // ecc error per bank
 | ||||
|    logic [pt.ICACHE_BANKS_WAY-1:0] ic_parerr;       // parity error per bank
 | ||||
| 
 | ||||
|    logic [63:0]  ic_premux_data; | ||||
|    logic         ic_sel_premux_data; | ||||
|  | @ -384,14 +392,8 @@ import el2_pkg::*; | |||
|    logic [63:0]    iccm_rd_data; | ||||
|    logic [77:0]    iccm_rd_data_ecc; | ||||
| 
 | ||||
|    logic        core_rst_l;     // Core reset including rst_l and dbg_rst_l
 | ||||
|    logic        core_rst_l;                         // Core reset including rst_l and dbg_rst_l
 | ||||
|    logic        jtag_tdoEn; | ||||
|    logic        dmi_reg_en; | ||||
|    logic [6:0]  dmi_reg_addr; | ||||
|    logic        dmi_reg_wr_en; | ||||
|    logic [31:0] dmi_reg_wdata; | ||||
|    logic [31:0] dmi_reg_rdata; | ||||
|    logic        dmi_hard_reset; | ||||
| 
 | ||||
|    logic        dccm_clk_override; | ||||
|    logic        icm_clk_override; | ||||
|  | @ -402,7 +404,7 @@ import el2_pkg::*; | |||
| `ifdef RV_BUILD_AXI4 | ||||
| 
 | ||||
|  //// AHB LITE BUS
 | ||||
|    logic [31:0]                      haddr; | ||||
|    logic [31:0]              haddr; | ||||
|    logic [2:0]               hburst; | ||||
|    logic                     hmastlock; | ||||
|    logic [3:0]               hprot; | ||||
|  | @ -410,54 +412,55 @@ import el2_pkg::*; | |||
|    logic [1:0]               htrans; | ||||
|    logic                     hwrite; | ||||
| 
 | ||||
|    logic [63:0]                      hrdata; | ||||
|    logic                             hready; | ||||
|    logic                             hresp; | ||||
|    logic [63:0]              hrdata; | ||||
|    logic                     hready; | ||||
|    logic                     hresp; | ||||
| 
 | ||||
|    // LSU AHB Master
 | ||||
|    logic [31:0]                      lsu_haddr; | ||||
|    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_hwdata; | ||||
|    logic [63:0]              lsu_hwdata; | ||||
| 
 | ||||
|    logic [63:0]                      lsu_hrdata; | ||||
|    logic                             lsu_hready; | ||||
|    logic                             lsu_hresp; | ||||
|    logic [63:0]              lsu_hrdata; | ||||
|    logic                     lsu_hready; | ||||
|    logic                     lsu_hresp; | ||||
|    // Debug Syster Bus AHB
 | ||||
|    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_hwdata; | ||||
|    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_hwdata; | ||||
| 
 | ||||
|     logic [63:0]               sb_hrdata; | ||||
|     logic                      sb_hready; | ||||
|     logic                      sb_hresp; | ||||
|     logic [63:0]             sb_hrdata; | ||||
|     logic                    sb_hready; | ||||
|     logic                    sb_hresp; | ||||
| 
 | ||||
|    // DMA Slave
 | ||||
|    logic                       dma_hsel; | ||||
|    logic [31:0]                      dma_haddr; | ||||
|    logic                     dma_hsel; | ||||
|    logic [31:0]              dma_haddr; | ||||
|    logic [2:0]               dma_hburst; | ||||
|    logic                             dma_hmastlock; | ||||
|    logic                     dma_hmastlock; | ||||
|    logic [3:0]               dma_hprot; | ||||
|    logic [2:0]               dma_hsize; | ||||
|    logic [1:0]               dma_htrans; | ||||
|    logic                             dma_hwrite; | ||||
|    logic [63:0]                      dma_hwdata; | ||||
|    logic                             dma_hreadyin; | ||||
|    logic                     dma_hwrite; | ||||
|    logic [63:0]              dma_hwdata; | ||||
|    logic                     dma_hreadyin; | ||||
| 
 | ||||
|    logic [63:0]                      dma_hrdata; | ||||
|    logic [63:0]              dma_hrdata; | ||||
|    logic                     dma_hreadyout; | ||||
|    logic                     dma_hresp; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // AHB
 | ||||
|    assign  hrdata[63:0]                           = '0; | ||||
|    assign  hready                                 = '0; | ||||
|  | @ -485,10 +488,11 @@ import el2_pkg::*; | |||
| 
 | ||||
| `endif //  `ifdef RV_BUILD_AXI4
 | ||||
| 
 | ||||
| 
 | ||||
| `ifdef RV_BUILD_AHB_LITE | ||||
|    wire                            lsu_axi_awvalid; | ||||
|     wire                            lsu_axi_awready; | ||||
|    wire [pt.LSU_BUS_TAG-1:0]      lsu_axi_awid; | ||||
|    wire                            lsu_axi_awready; | ||||
|    wire [pt.LSU_BUS_TAG-1:0]       lsu_axi_awid; | ||||
|    wire [31:0]                     lsu_axi_awaddr; | ||||
|    wire [3:0]                      lsu_axi_awregion; | ||||
|    wire [7:0]                      lsu_axi_awlen; | ||||
|  | @ -500,20 +504,20 @@ import el2_pkg::*; | |||
|    wire [3:0]                      lsu_axi_awqos; | ||||
| 
 | ||||
|    wire                            lsu_axi_wvalid; | ||||
|     wire                            lsu_axi_wready; | ||||
|    wire                            lsu_axi_wready; | ||||
|    wire [63:0]                     lsu_axi_wdata; | ||||
|    wire [7:0]                      lsu_axi_wstrb; | ||||
|    wire                            lsu_axi_wlast; | ||||
| 
 | ||||
|     wire                            lsu_axi_bvalid; | ||||
|    wire                            lsu_axi_bvalid; | ||||
|    wire                            lsu_axi_bready; | ||||
|     wire [1:0]                      lsu_axi_bresp; | ||||
|     wire [pt.LSU_BUS_TAG-1:0]      lsu_axi_bid; | ||||
|    wire [1:0]                      lsu_axi_bresp; | ||||
|    wire [pt.LSU_BUS_TAG-1:0]       lsu_axi_bid; | ||||
| 
 | ||||
|    // AXI Read Channels
 | ||||
|    wire                            lsu_axi_arvalid; | ||||
|     wire                            lsu_axi_arready; | ||||
|    wire [pt.LSU_BUS_TAG-1:0]      lsu_axi_arid; | ||||
|    wire                            lsu_axi_arready; | ||||
|    wire [pt.LSU_BUS_TAG-1:0]       lsu_axi_arid; | ||||
|    wire [31:0]                     lsu_axi_araddr; | ||||
|    wire [3:0]                      lsu_axi_arregion; | ||||
|    wire [7:0]                      lsu_axi_arlen; | ||||
|  | @ -524,18 +528,18 @@ import el2_pkg::*; | |||
|    wire [2:0]                      lsu_axi_arprot; | ||||
|    wire [3:0]                      lsu_axi_arqos; | ||||
| 
 | ||||
|     wire                            lsu_axi_rvalid; | ||||
|    wire                            lsu_axi_rvalid; | ||||
|    wire                            lsu_axi_rready; | ||||
|     wire [pt.LSU_BUS_TAG-1:0]      lsu_axi_rid; | ||||
|     wire [63:0]                     lsu_axi_rdata; | ||||
|     wire [1:0]                      lsu_axi_rresp; | ||||
|     wire                            lsu_axi_rlast; | ||||
|    wire [pt.LSU_BUS_TAG-1:0]       lsu_axi_rid; | ||||
|    wire [63:0]                     lsu_axi_rdata; | ||||
|    wire [1:0]                      lsu_axi_rresp; | ||||
|    wire                            lsu_axi_rlast; | ||||
| 
 | ||||
|    //-------------------------- IFU AXI signals--------------------------
 | ||||
|    // AXI Write Channels
 | ||||
|    wire                            ifu_axi_awvalid; | ||||
|     wire                            ifu_axi_awready; | ||||
|    wire [pt.IFU_BUS_TAG-1:0]      ifu_axi_awid; | ||||
|    wire                            ifu_axi_awready; | ||||
|    wire [pt.IFU_BUS_TAG-1:0]       ifu_axi_awid; | ||||
|    wire [31:0]                     ifu_axi_awaddr; | ||||
|    wire [3:0]                      ifu_axi_awregion; | ||||
|    wire [7:0]                      ifu_axi_awlen; | ||||
|  | @ -547,20 +551,20 @@ import el2_pkg::*; | |||
|    wire [3:0]                      ifu_axi_awqos; | ||||
| 
 | ||||
|    wire                            ifu_axi_wvalid; | ||||
|     wire                            ifu_axi_wready; | ||||
|    wire                            ifu_axi_wready; | ||||
|    wire [63:0]                     ifu_axi_wdata; | ||||
|    wire [7:0]                      ifu_axi_wstrb; | ||||
|    wire                            ifu_axi_wlast; | ||||
| 
 | ||||
|     wire                            ifu_axi_bvalid; | ||||
|    wire                            ifu_axi_bvalid; | ||||
|    wire                            ifu_axi_bready; | ||||
|     wire [1:0]                      ifu_axi_bresp; | ||||
|     wire [pt.IFU_BUS_TAG-1:0]      ifu_axi_bid; | ||||
|    wire [1:0]                      ifu_axi_bresp; | ||||
|    wire [pt.IFU_BUS_TAG-1:0]      ifu_axi_bid; | ||||
| 
 | ||||
|    // AXI Read Channels
 | ||||
|    wire                            ifu_axi_arvalid; | ||||
|     wire                            ifu_axi_arready; | ||||
|    wire [pt.IFU_BUS_TAG-1:0]      ifu_axi_arid; | ||||
|    wire                            ifu_axi_arready; | ||||
|    wire [pt.IFU_BUS_TAG-1:0]       ifu_axi_arid; | ||||
|    wire [31:0]                     ifu_axi_araddr; | ||||
|    wire [3:0]                      ifu_axi_arregion; | ||||
|    wire [7:0]                      ifu_axi_arlen; | ||||
|  | @ -571,18 +575,18 @@ import el2_pkg::*; | |||
|    wire [2:0]                      ifu_axi_arprot; | ||||
|    wire [3:0]                      ifu_axi_arqos; | ||||
| 
 | ||||
|     wire                            ifu_axi_rvalid; | ||||
|    wire                            ifu_axi_rvalid; | ||||
|    wire                            ifu_axi_rready; | ||||
|     wire [pt.IFU_BUS_TAG-1:0]      ifu_axi_rid; | ||||
|     wire [63:0]                     ifu_axi_rdata; | ||||
|     wire [1:0]                      ifu_axi_rresp; | ||||
|     wire                            ifu_axi_rlast; | ||||
|    wire [pt.IFU_BUS_TAG-1:0]       ifu_axi_rid; | ||||
|    wire [63:0]                     ifu_axi_rdata; | ||||
|    wire [1:0]                      ifu_axi_rresp; | ||||
|    wire                            ifu_axi_rlast; | ||||
| 
 | ||||
|    //-------------------------- SB AXI signals--------------------------
 | ||||
|    // AXI Write Channels
 | ||||
|    wire                            sb_axi_awvalid; | ||||
|     wire                            sb_axi_awready; | ||||
|    wire [pt.SB_BUS_TAG-1:0]       sb_axi_awid; | ||||
|    wire                            sb_axi_awready; | ||||
|    wire [pt.SB_BUS_TAG-1:0]        sb_axi_awid; | ||||
|    wire [31:0]                     sb_axi_awaddr; | ||||
|    wire [3:0]                      sb_axi_awregion; | ||||
|    wire [7:0]                      sb_axi_awlen; | ||||
|  | @ -594,20 +598,20 @@ import el2_pkg::*; | |||
|    wire [3:0]                      sb_axi_awqos; | ||||
| 
 | ||||
|    wire                            sb_axi_wvalid; | ||||
|     wire                            sb_axi_wready; | ||||
|    wire                            sb_axi_wready; | ||||
|    wire [63:0]                     sb_axi_wdata; | ||||
|    wire [7:0]                      sb_axi_wstrb; | ||||
|    wire                            sb_axi_wlast; | ||||
| 
 | ||||
|     wire                            sb_axi_bvalid; | ||||
|    wire                            sb_axi_bvalid; | ||||
|    wire                            sb_axi_bready; | ||||
|     wire [1:0]                      sb_axi_bresp; | ||||
|     wire [pt.SB_BUS_TAG-1:0]       sb_axi_bid; | ||||
|    wire [1:0]                      sb_axi_bresp; | ||||
|    wire [pt.SB_BUS_TAG-1:0]        sb_axi_bid; | ||||
| 
 | ||||
|    // AXI Read Channels
 | ||||
|    wire                            sb_axi_arvalid; | ||||
|     wire                            sb_axi_arready; | ||||
|    wire [pt.SB_BUS_TAG-1:0]       sb_axi_arid; | ||||
|    wire                            sb_axi_arready; | ||||
|    wire [pt.SB_BUS_TAG-1:0]        sb_axi_arid; | ||||
|    wire [31:0]                     sb_axi_araddr; | ||||
|    wire [3:0]                      sb_axi_arregion; | ||||
|    wire [7:0]                      sb_axi_arlen; | ||||
|  | @ -618,49 +622,49 @@ import el2_pkg::*; | |||
|    wire [2:0]                      sb_axi_arprot; | ||||
|    wire [3:0]                      sb_axi_arqos; | ||||
| 
 | ||||
|     wire                            sb_axi_rvalid; | ||||
|    wire                            sb_axi_rvalid; | ||||
|    wire                            sb_axi_rready; | ||||
|     wire [pt.SB_BUS_TAG-1:0]       sb_axi_rid; | ||||
|     wire [63:0]                     sb_axi_rdata; | ||||
|     wire [1:0]                      sb_axi_rresp; | ||||
|     wire                            sb_axi_rlast; | ||||
|    wire [pt.SB_BUS_TAG-1:0]        sb_axi_rid; | ||||
|    wire [63:0]                     sb_axi_rdata; | ||||
|    wire [1:0]                      sb_axi_rresp; | ||||
|    wire                            sb_axi_rlast; | ||||
| 
 | ||||
|    //-------------------------- DMA AXI signals--------------------------
 | ||||
|    // AXI Write Channels
 | ||||
|     wire                         dma_axi_awvalid; | ||||
|    wire                         dma_axi_awvalid; | ||||
|    wire                         dma_axi_awready; | ||||
|     wire [pt.DMA_BUS_TAG-1:0]   dma_axi_awid; | ||||
|     wire [31:0]                  dma_axi_awaddr; | ||||
|     wire [2:0]                   dma_axi_awsize; | ||||
|     wire [2:0]                   dma_axi_awprot; | ||||
|     wire [7:0]                   dma_axi_awlen; | ||||
|     wire [1:0]                   dma_axi_awburst; | ||||
|    wire [pt.DMA_BUS_TAG-1:0]    dma_axi_awid; | ||||
|    wire [31:0]                  dma_axi_awaddr; | ||||
|    wire [2:0]                   dma_axi_awsize; | ||||
|    wire [2:0]                   dma_axi_awprot; | ||||
|    wire [7:0]                   dma_axi_awlen; | ||||
|    wire [1:0]                   dma_axi_awburst; | ||||
| 
 | ||||
| 
 | ||||
|     wire                         dma_axi_wvalid; | ||||
|    wire                         dma_axi_wvalid; | ||||
|    wire                         dma_axi_wready; | ||||
|     wire [63:0]                  dma_axi_wdata; | ||||
|     wire [7:0]                   dma_axi_wstrb; | ||||
|     wire                         dma_axi_wlast; | ||||
|    wire [63:0]                  dma_axi_wdata; | ||||
|    wire [7:0]                   dma_axi_wstrb; | ||||
|    wire                         dma_axi_wlast; | ||||
| 
 | ||||
|    wire                         dma_axi_bvalid; | ||||
|     wire                         dma_axi_bready; | ||||
|    wire                         dma_axi_bready; | ||||
|    wire [1:0]                   dma_axi_bresp; | ||||
|    wire [pt.DMA_BUS_TAG-1:0]   dma_axi_bid; | ||||
|    wire [pt.DMA_BUS_TAG-1:0]    dma_axi_bid; | ||||
| 
 | ||||
|    // AXI Read Channels
 | ||||
|     wire                         dma_axi_arvalid; | ||||
|    wire                         dma_axi_arvalid; | ||||
|    wire                         dma_axi_arready; | ||||
|     wire [pt.DMA_BUS_TAG-1:0]   dma_axi_arid; | ||||
|     wire [31:0]                  dma_axi_araddr; | ||||
|     wire [2:0]                   dma_axi_arsize; | ||||
|     wire [2:0]                   dma_axi_arprot; | ||||
|     wire [7:0]                   dma_axi_arlen; | ||||
|     wire [1:0]                   dma_axi_arburst; | ||||
|    wire [pt.DMA_BUS_TAG-1:0]    dma_axi_arid; | ||||
|    wire [31:0]                  dma_axi_araddr; | ||||
|    wire [2:0]                   dma_axi_arsize; | ||||
|    wire [2:0]                   dma_axi_arprot; | ||||
|    wire [7:0]                   dma_axi_arlen; | ||||
|    wire [1:0]                   dma_axi_arburst; | ||||
| 
 | ||||
|    wire                         dma_axi_rvalid; | ||||
|     wire                         dma_axi_rready; | ||||
|    wire [pt.DMA_BUS_TAG-1:0]   dma_axi_rid; | ||||
|    wire                         dma_axi_rready; | ||||
|    wire [pt.DMA_BUS_TAG-1:0]    dma_axi_rid; | ||||
|    wire [63:0]                  dma_axi_rdata; | ||||
|    wire [1:0]                   dma_axi_rresp; | ||||
|    wire                         dma_axi_rlast; | ||||
|  | @ -674,40 +678,53 @@ import el2_pkg::*; | |||
| 
 | ||||
| `endif //  `ifdef RV_BUILD_AHB_LITE
 | ||||
| 
 | ||||
|    logic                   dmi_reg_en; | ||||
|    logic [6:0]             dmi_reg_addr; | ||||
|    logic                   dmi_reg_wr_en; | ||||
|    logic [31:0]            dmi_reg_wdata; | ||||
|    logic [31:0]            dmi_reg_rdata; | ||||
| 
 | ||||
|    // Instantiate the el2_swerv core
 | ||||
|    el2_swerv #(.pt(pt)) swerv ( | ||||
|           .* | ||||
|           ); | ||||
|                                 .clk(clk), | ||||
|                                 .* | ||||
|                                 ); | ||||
| 
 | ||||
|    // Instantiate the mem
 | ||||
|    el2_mem  #(.pt(pt)) mem( | ||||
|         .rst_l(core_rst_l), | ||||
|         .* | ||||
|         ); | ||||
|    el2_mem  #(.pt(pt)) mem ( | ||||
|                              .clk(active_l2clk), | ||||
|                              .rst_l(core_rst_l), | ||||
|                              .* | ||||
|                              ); | ||||
| 
 | ||||
|   // Instantiate the JTAG/DMI
 | ||||
| 
 | ||||
|    //  JTAG/DMI instance
 | ||||
|    dmi_wrapper  dmi_wrapper ( | ||||
|            // JTAG signals
 | ||||
|            .trst_n(jtag_trst_n),           // JTAG reset
 | ||||
|            .tck   (jtag_tck),              // JTAG clock
 | ||||
|            .tms   (jtag_tms),              // Test mode select
 | ||||
|            .tdi   (jtag_tdi),              // Test Data Input
 | ||||
|            .tdo   (jtag_tdo),              // Test Data Output
 | ||||
|            .tdoEnable (),                  // Test Data Output enable
 | ||||
| 
 | ||||
|            // Processor Signals
 | ||||
|            .core_rst_n  (dbg_rst_l),      // Primary reset active low
 | ||||
|            .core_clk    (clk),            // Core clock
 | ||||
|            .jtag_id     (jtag_id),        // 32 bit JTAG ID
 | ||||
|            .rd_data     (dmi_reg_rdata),  // 32 bit Read data from  Processor
 | ||||
|            .reg_wr_data (dmi_reg_wdata),  // 32 bit Write data to Processor
 | ||||
|            .reg_wr_addr (dmi_reg_addr),   // 32 bit Write address to Processor
 | ||||
|            .reg_en      (dmi_reg_en),     // 1 bit  Write interface bit to Processor
 | ||||
|            .reg_wr_en   (dmi_reg_wr_en),   // 1 bit  Write enable to Processor
 | ||||
|            .dmi_hard_reset   (dmi_hard_reset)   //a hard reset of the DTM, causing the DTM to forget about any outstanding DMI transactions
 | ||||
| ); | ||||
| 
 | ||||
|     // JTAG signals
 | ||||
|     .trst_n      (jtag_trst_n),     // JTAG reset
 | ||||
|     .tck         (jtag_tck),        // JTAG clock
 | ||||
|     .tms         (jtag_tms),        // Test mode select
 | ||||
|     .tdi         (jtag_tdi),        // Test Data Input
 | ||||
|     .tdo         (jtag_tdo),        // Test Data Output
 | ||||
|     .tdoEnable   (), | ||||
|     // Processor Signals
 | ||||
|     .core_rst_n  (dbg_rst_l),       // Debug reset, active low
 | ||||
|     .core_clk    (clk),             // Core clock
 | ||||
|     .jtag_id     (jtag_id),         // JTAG ID
 | ||||
|     .rd_data     (dmi_reg_rdata),   // Read data from  Processor
 | ||||
|     .reg_wr_data (dmi_reg_wdata),   // Write data to Processor
 | ||||
|     .reg_wr_addr (dmi_reg_addr),    // Write address to Processor
 | ||||
|     .reg_en      (dmi_reg_en),      // Write interface bit to Processor
 | ||||
|     .reg_wr_en   (dmi_reg_wr_en),   // Write enable to Processor
 | ||||
|     .dmi_hard_reset   () | ||||
|    ); | ||||
| 
 | ||||
| `ifdef RV_ASSERT_ON | ||||
| // to avoid internal assertions failure at time 0
 | ||||
| initial begin | ||||
|     $assertoff(0, swerv); | ||||
|     @ (negedge clk) $asserton(0, swerv); | ||||
| end | ||||
| `endif | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -36,21 +36,25 @@ import el2_pkg::*; | |||
|    input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] i0_predict_index_d,     // DEC predict index
 | ||||
|    input logic [pt.BTB_BTAG_SIZE-1:0] i0_predict_btag_d,               // DEC predict branch tag
 | ||||
| 
 | ||||
|    input logic  [31:0]  lsu_result_m,                                  // Load result M-stage
 | ||||
|    input logic  [31:0]  lsu_nonblock_load_data,                        // nonblock load data
 | ||||
|    input logic          dec_i0_rs1_en_d,                               // Qualify GPR RS1 data
 | ||||
|    input logic          dec_i0_rs2_en_d,                               // Qualify GPR RS2 data
 | ||||
|    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]  dec_i0_rs1_bypass_data_d,                      // DEC bypass data
 | ||||
|    input logic  [31:0]  dec_i0_rs2_bypass_data_d,                      // DEC bypass data
 | ||||
|    input logic  [31:0]  dec_i0_result_r,                               // DEC result in R-stage
 | ||||
|    input logic  [12:1]  dec_i0_br_immed_d,                             // Branch immediate
 | ||||
|    input logic          dec_i0_alu_decode_d,                           // Valid to X-stage ALU
 | ||||
|    input logic          dec_i0_branch_d,                               // Branch in D-stage
 | ||||
|    input logic          dec_i0_select_pc_d,                            // PC select to RS1
 | ||||
|    input logic  [31:1]  dec_i0_pc_d,                                   // Instruction PC
 | ||||
|    input logic  [1:0]   dec_i0_rs1_bypass_en_d,                        // DEC bypass select  1 - X-stage, 0 - dec bypass data
 | ||||
|    input logic  [1:0]   dec_i0_rs2_bypass_en_d,                        // DEC bypass select  1 - X-stage, 0 - dec bypass data
 | ||||
|    input logic          dec_csr_ren_d,                                 // Clear I0 RS1 primary
 | ||||
|    input logic  [3:0]   dec_i0_rs1_bypass_en_d,                        // DEC bypass select  1 - X-stage, 0 - dec bypass data
 | ||||
|    input logic  [3:0]   dec_i0_rs2_bypass_en_d,                        // DEC bypass select  1 - X-stage, 0 - dec bypass data
 | ||||
|    input logic          dec_csr_ren_d,                                 // CSR read select
 | ||||
|    input logic  [31:0]  dec_csr_rddata_d,                              // CSR read data
 | ||||
| 
 | ||||
|    input logic          dec_qual_lsu_d,                                // LSU instruction at D.  Use to quiet LSU operands
 | ||||
|    input el2_mul_pkt_t mul_p,                                         // DEC {valid, operand signs, low, operand bypass}
 | ||||
|    input el2_div_pkt_t div_p,                                         // DEC {valid, unsigned, rem}
 | ||||
|    input logic          dec_div_cancel,                                // Cancel the divide operation
 | ||||
|  | @ -105,18 +109,16 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    logic                       data_gate_en; | ||||
|    logic [31:0]                i0_rs1_bypass_data_d; | ||||
|    logic [31:0]                i0_rs2_bypass_data_d; | ||||
|    logic                       i0_rs1_bypass_en_d; | ||||
|    logic                       i0_rs2_bypass_en_d; | ||||
|    logic [31:0]                i0_rs1_d,  i0_rs2_d; | ||||
|    logic [31:0]                muldiv_rs1_d, muldiv_rs2_d; | ||||
|    logic [31:0]                muldiv_rs1_d; | ||||
|    logic [31:1]                pred_correct_npc_r; | ||||
|    logic                       i0_pred_correct_upper_r; | ||||
|    logic [31:0]                csr_rs1_in_d; | ||||
|    logic [31:1]                i0_flush_path_upper_r; | ||||
|    logic                       x_data_en, r_data_en; | ||||
|    logic                       x_data_en, x_data_en_q1, x_data_en_q2, r_data_en, r_data_en_q2; | ||||
|    logic                       x_ctl_en,  r_ctl_en; | ||||
| 
 | ||||
|    logic [pt.BHT_GHR_SIZE-1:0] ghr_d_ns, ghr_d; | ||||
|  | @ -130,7 +132,6 @@ import el2_pkg::*; | |||
|    el2_predict_pkt_t          final_predict_mp; | ||||
|    el2_predict_pkt_t          i0_predict_newp_d; | ||||
| 
 | ||||
|    logic                       flush_lower_ff; | ||||
|    logic                       flush_in_d; | ||||
|    logic [31:0]                alu_result_x; | ||||
| 
 | ||||
|  | @ -148,6 +149,7 @@ import el2_pkg::*; | |||
|    logic [31:1]                i0_flush_path_x; | ||||
|    el2_predict_pkt_t          i0_predict_p_x; | ||||
|    logic                       i0_pred_correct_upper_x; | ||||
|    logic                       i0_branch_x; | ||||
| 
 | ||||
|    localparam PREDPIPESIZE = pt.BTB_ADDR_HI-pt.BTB_ADDR_LO+1+pt.BHT_GHR_SIZE+pt.BTB_BTAG_SIZE; | ||||
|    logic [PREDPIPESIZE-1:0]    predpipe_d, predpipe_x, predpipe_r, final_predpipe_mp; | ||||
|  | @ -155,84 +157,73 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    rvdffe #(31)                         i_flush_path_x_ff    (.*, .en ( x_data_en     ),  .din( i0_flush_path_d[31:1]         ),  .dout( i0_flush_path_x[31:1]      ) ); | ||||
|    rvdffe #(32)                         i_csr_rs1_x_ff       (.*, .en ( x_data_en     ),  .din( csr_rs1_in_d[31:0]            ),  .dout( exu_csr_rs1_x[31:0]        ) ); | ||||
|    rvdffe #($bits(el2_predict_pkt_t))  i_predictpacket_x_ff (.*, .en ( x_data_en     ),  .din( i0_predict_p_d                ),  .dout( i0_predict_p_x             ) ); | ||||
|    rvdffe #(PREDPIPESIZE)               i_predpipe_x_ff      (.*, .en ( x_data_en     ),  .din( predpipe_d                    ),  .dout( predpipe_x                 ) ); | ||||
|    rvdffe #(PREDPIPESIZE)               i_predpipe_r_ff      (.*, .en ( r_data_en     ),  .din( predpipe_x                    ),  .dout( predpipe_r                 ) ); | ||||
|    rvdffpcie #(31)                       i_flush_path_x_ff    (.*, .clk(clk),        .en ( x_data_en     ),  .din ( i0_flush_path_d[31:1]         ),  .dout( i0_flush_path_x[31:1]      ) ); | ||||
|    rvdffe #(32)                          i_csr_rs1_x_ff       (.*, .clk(clk),        .en ( x_data_en_q1  ),  .din ( i0_rs1_d[31:0]                ),  .dout( exu_csr_rs1_x[31:0]        ) ); | ||||
|    rvdffppe #($bits(el2_predict_pkt_t)) i_predictpacket_x_ff (.*, .clk(clk),        .en ( x_data_en     ),  .din ( i0_predict_p_d                ),  .dout( i0_predict_p_x             ) ); | ||||
|    rvdffe #(PREDPIPESIZE)                i_predpipe_x_ff      (.*, .clk(clk),        .en ( x_data_en_q2  ),  .din ( predpipe_d                    ),  .dout( predpipe_x                 ) ); | ||||
|    rvdffe #(PREDPIPESIZE)                i_predpipe_r_ff      (.*, .clk(clk),        .en ( r_data_en_q2  ),  .din ( predpipe_x                    ),  .dout( predpipe_r                 ) ); | ||||
| 
 | ||||
|    rvdffe #(4+pt.BHT_GHR_SIZE)          i_x_ff               (.*, .en ( x_ctl_en      ),  .din ({i0_valid_d,i0_taken_d,i0_flush_upper_d,i0_pred_correct_upper_d,ghr_x_ns[pt.BHT_GHR_SIZE-1:0]} ), | ||||
|                                                                                           .dout({i0_valid_x,i0_taken_x,i0_flush_upper_x,i0_pred_correct_upper_x,ghr_x[pt.BHT_GHR_SIZE-1:0]}    ) ); | ||||
|    rvdffe #(4+pt.BHT_GHR_SIZE)          i_x_ff               (.*, .clk(clk),        .en ( x_ctl_en      ),  .din ({i0_valid_d,i0_taken_d,i0_flush_upper_d,i0_pred_correct_upper_d,ghr_x_ns[pt.BHT_GHR_SIZE-1:0]} ), | ||||
|                                                                                                             .dout({i0_valid_x,i0_taken_x,i0_flush_upper_x,i0_pred_correct_upper_x,ghr_x[pt.BHT_GHR_SIZE-1:0]}    ) ); | ||||
| 
 | ||||
|    rvdffe #($bits(el2_predict_pkt_t)+7) i_r_ff0             (.*, .en ( r_ctl_en      ),  .din ({i0_predict_p_x             ,pred_correct_npc_x[6:1],i0_pred_correct_upper_x}), | ||||
|                                                                                           .dout({i0_pp_r                    ,pred_correct_npc_r[6:1],i0_pred_correct_upper_r}) ); | ||||
|    rvdffppe #($bits(el2_predict_pkt_t)+1) i_r_ff0         (.*, .clk(clk),        .en ( r_ctl_en      ),  .din ({i0_pred_correct_upper_x, i0_predict_p_x}), | ||||
|                                                                                                           .dout({i0_pred_correct_upper_r, i0_pp_r       }) ); | ||||
| 
 | ||||
|    rvdffe #(56)                         i_r_ff1              (.*, .en ( r_data_en     ),  .din ({i0_flush_path_x[31:1]      ,pred_correct_npc_x[31:7]}), | ||||
|                                                                                           .dout({i0_flush_path_upper_r[31:1],pred_correct_npc_r[31:7]}) ); | ||||
|    rvdffpcie #(31)                      i_flush_r_ff         (.*, .clk(clk),        .en ( r_data_en     ),  .din ( i0_flush_path_x[31:1]         ),  .dout( i0_flush_path_upper_r[31:1]) ); | ||||
|    rvdffpcie #(31)                      i_npc_r_ff           (.*, .clk(clk),        .en ( r_data_en     ),  .din ( pred_correct_npc_x[31:1]      ),  .dout( pred_correct_npc_r[31:1]   ) ); | ||||
| 
 | ||||
|    if (pt.BHT_SIZE==32 || pt.BHT_SIZE==64) | ||||
|      begin | ||||
|        rvdffs #(pt.BHT_GHR_SIZE+2)      i_data_gate_ff       (.*, .en( data_gate_en   ),  .din ({ghr_d_ns[pt.BHT_GHR_SIZE-1:0],mul_p.valid,dec_tlu_flush_lower_r}), | ||||
|                                                                                           .dout({ghr_d[pt.BHT_GHR_SIZE-1:0]   ,mul_valid_x,flush_lower_ff}       ) ); | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        rvdffe #(pt.BHT_GHR_SIZE+2)      i_data_gate_ff       (.*, .en( data_gate_en   ),  .din ({ghr_d_ns[pt.BHT_GHR_SIZE-1:0],mul_p.valid,dec_tlu_flush_lower_r}), | ||||
|                                                                                           .dout({ghr_d[pt.BHT_GHR_SIZE-1:0]   ,mul_valid_x,flush_lower_ff}       ) ); | ||||
|      end | ||||
|    rvdffie #(pt.BHT_GHR_SIZE+2,1)       i_misc_ff            (.*, .clk(clk),                                .din ({ghr_d_ns[pt.BHT_GHR_SIZE-1:0], mul_p.valid, dec_i0_branch_d}), | ||||
|                                                                                                             .dout({ghr_d[pt.BHT_GHR_SIZE-1:0]   , mul_valid_x, i0_branch_x}) ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign data_gate_en             =  ( ghr_d_ns[pt.BHT_GHR_SIZE-1:0] != ghr_d[pt.BHT_GHR_SIZE-1:0]) | | ||||
|                                       ( mul_p.valid                   != mul_valid_x               ) | | ||||
|                                       ( dec_tlu_flush_lower_r         != flush_lower_ff            ); | ||||
| 
 | ||||
|    assign predpipe_d[PREDPIPESIZE-1:0] | ||||
|                                    = {i0_predict_fghr_d, i0_predict_index_d, i0_predict_btag_d}; | ||||
| 
 | ||||
| 
 | ||||
|    assign i0_rs1_bypass_en_d       = dec_i0_rs1_bypass_en_d[0] | dec_i0_rs1_bypass_en_d[1]; | ||||
|    assign i0_rs2_bypass_en_d       = dec_i0_rs2_bypass_en_d[0] | dec_i0_rs2_bypass_en_d[1]; | ||||
|    assign i0_rs1_bypass_en_d       = dec_i0_rs1_bypass_en_d[0] | dec_i0_rs1_bypass_en_d[1] | dec_i0_rs1_bypass_en_d[2] | dec_i0_rs1_bypass_en_d[3]; | ||||
|    assign i0_rs2_bypass_en_d       = dec_i0_rs2_bypass_en_d[0] | dec_i0_rs2_bypass_en_d[1] | dec_i0_rs2_bypass_en_d[2] | dec_i0_rs2_bypass_en_d[3]; | ||||
| 
 | ||||
|    assign i0_rs1_bypass_data_d[31:0]=({32{dec_i0_rs1_bypass_en_d[0]}} & dec_i0_rs1_bypass_data_d[31:0]) | | ||||
|                                      ({32{dec_i0_rs1_bypass_en_d[1]}} & exu_i0_result_x[31:0]         ); | ||||
|    assign i0_rs1_bypass_data_d[31:0]=({32{dec_i0_rs1_bypass_en_d[0]}} & dec_i0_result_r[31:0]       ) | | ||||
|                                      ({32{dec_i0_rs1_bypass_en_d[1]}} & lsu_result_m[31:0]          ) | | ||||
|                                      ({32{dec_i0_rs1_bypass_en_d[2]}} & exu_i0_result_x[31:0]       ) | | ||||
|                                      ({32{dec_i0_rs1_bypass_en_d[3]}} & lsu_nonblock_load_data[31:0]); | ||||
| 
 | ||||
|    assign i0_rs2_bypass_data_d[31:0]=({32{dec_i0_rs2_bypass_en_d[0]}} & dec_i0_rs2_bypass_data_d[31:0]) | | ||||
|                                      ({32{dec_i0_rs2_bypass_en_d[1]}} & exu_i0_result_x[31:0]         ); | ||||
|    assign i0_rs2_bypass_data_d[31:0]=({32{dec_i0_rs2_bypass_en_d[0]}} & dec_i0_result_r[31:0]       ) | | ||||
|                                      ({32{dec_i0_rs2_bypass_en_d[1]}} & lsu_result_m[31:0]          ) | | ||||
|                                      ({32{dec_i0_rs2_bypass_en_d[2]}} & exu_i0_result_x[31:0]       ) | | ||||
|                                      ({32{dec_i0_rs2_bypass_en_d[3]}} & lsu_nonblock_load_data[31:0]); | ||||
| 
 | ||||
| 
 | ||||
|    assign i0_rs1_d[31:0]           = ({32{ i0_rs1_bypass_en_d                                           }}           & i0_rs1_bypass_data_d[31:0]) | | ||||
|                                      ({32{~i0_rs1_bypass_en_d &  dec_i0_select_pc_d                     }}           & {dec_i0_pc_d[31:1],1'b0}  ) |    // for jal's
 | ||||
|                                      ({32{~i0_rs1_bypass_en_d &  dec_debug_wdata_rs1_d                  }}           & dbg_cmd_wrdata[31:0]      ) | | ||||
|                                      ({32{~i0_rs1_bypass_en_d & ~dec_debug_wdata_rs1_d & dec_i0_rs1_en_d}}           & gpr_i0_rs1_d[31:0]        ); | ||||
|    assign i0_rs1_d[31:0]           = ({32{ i0_rs1_bypass_en_d                                           }}             & i0_rs1_bypass_data_d[31:0]) | | ||||
|                                      ({32{~i0_rs1_bypass_en_d &  dec_i0_select_pc_d                     }}             & {dec_i0_pc_d[31:1],1'b0}  ) |    // for jal's
 | ||||
|                                      ({32{~i0_rs1_bypass_en_d &  dec_debug_wdata_rs1_d                  }}             & dbg_cmd_wrdata[31:0]      ) | | ||||
|                                      ({32{~i0_rs1_bypass_en_d & ~dec_debug_wdata_rs1_d & dec_i0_rs1_en_d}}             & gpr_i0_rs1_d[31:0]        ); | ||||
| 
 | ||||
|    assign i0_rs2_d[31:0]           = ({32{~i0_rs2_bypass_en_d & dec_i0_rs2_en_d}}                                    & gpr_i0_rs2_d[31:0]        ) | | ||||
|                                      ({32{~i0_rs2_bypass_en_d                  }}                                    & dec_i0_immed_d[31:0]      ) | | ||||
|                                      ({32{ i0_rs2_bypass_en_d                  }}                                    & i0_rs2_bypass_data_d[31:0]); | ||||
|    assign i0_rs2_d[31:0]           = ({32{~i0_rs2_bypass_en_d & dec_i0_rs2_en_d}}                                      & gpr_i0_rs2_d[31:0]        ) | | ||||
|                                      ({32{~i0_rs2_bypass_en_d                  }}                                      & dec_i0_immed_d[31:0]      ) | | ||||
|                                      ({32{ i0_rs2_bypass_en_d                  }}                                      & i0_rs2_bypass_data_d[31:0]); | ||||
| 
 | ||||
| 
 | ||||
|    assign exu_lsu_rs1_d[31:0]      = ({32{~i0_rs1_bypass_en_d & ~dec_extint_stall & dec_i0_rs1_en_d}} & gpr_i0_rs1_d[31:0]        ) | | ||||
|                                      ({32{ i0_rs1_bypass_en_d & ~dec_extint_stall                  }} & i0_rs1_bypass_data_d[31:0]) | | ||||
|                                      ({32{                       dec_extint_stall                  }} & {dec_tlu_meihap[31:2],2'b0}); | ||||
|    assign exu_lsu_rs1_d[31:0]      = ({32{~i0_rs1_bypass_en_d & ~dec_extint_stall & dec_i0_rs1_en_d & dec_qual_lsu_d}} & gpr_i0_rs1_d[31:0]        ) | | ||||
|                                      ({32{ i0_rs1_bypass_en_d & ~dec_extint_stall                   & dec_qual_lsu_d}} & i0_rs1_bypass_data_d[31:0]) | | ||||
|                                      ({32{                       dec_extint_stall                   & dec_qual_lsu_d}} & {dec_tlu_meihap[31:2],2'b0}); | ||||
| 
 | ||||
|    assign exu_lsu_rs2_d[31:0]      = ({32{~i0_rs2_bypass_en_d & ~dec_extint_stall & dec_i0_rs2_en_d}} & gpr_i0_rs2_d[31:0]        ) | | ||||
|                                      ({32{ i0_rs2_bypass_en_d & ~dec_extint_stall                  }} & i0_rs2_bypass_data_d[31:0]); | ||||
|    assign exu_lsu_rs2_d[31:0]      = ({32{~i0_rs2_bypass_en_d & ~dec_extint_stall & dec_i0_rs2_en_d & dec_qual_lsu_d}} & gpr_i0_rs2_d[31:0]        ) | | ||||
|                                      ({32{ i0_rs2_bypass_en_d & ~dec_extint_stall                   & dec_qual_lsu_d}} & i0_rs2_bypass_data_d[31:0]); | ||||
| 
 | ||||
| 
 | ||||
|    assign muldiv_rs1_d[31:0]       = ({32{~i0_rs1_bypass_en_d & dec_i0_rs1_en_d}}                     & gpr_i0_rs1_d[31:0]        ) | | ||||
|                                      ({32{ i0_rs1_bypass_en_d                  }}                     & i0_rs1_bypass_data_d[31:0]); | ||||
|    assign muldiv_rs1_d[31:0]       = ({32{~i0_rs1_bypass_en_d & dec_i0_rs1_en_d}}                                      & gpr_i0_rs1_d[31:0]        ) | | ||||
|                                      ({32{ i0_rs1_bypass_en_d                  }}                                      & i0_rs1_bypass_data_d[31:0]); | ||||
| 
 | ||||
|    assign muldiv_rs2_d[31:0]       = ({32{~i0_rs2_bypass_en_d & dec_i0_rs2_en_d}}                     & gpr_i0_rs2_d[31:0]        ) | | ||||
|                                      ({32{~i0_rs2_bypass_en_d                  }}                     & dec_i0_immed_d[31:0]      ) | | ||||
|                                      ({32{ i0_rs2_bypass_en_d                  }}                     & i0_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_x[31:0]; | ||||
| 
 | ||||
|    assign x_data_en                =  dec_data_en[1]; | ||||
|    assign x_data_en_q1             =  dec_data_en[1] & dec_csr_ren_d; | ||||
|    assign x_data_en_q2             =  dec_data_en[1] & dec_i0_branch_d; | ||||
|    assign r_data_en                =  dec_data_en[0]; | ||||
|    assign r_data_en_q2             =  dec_data_en[0] & i0_branch_x; | ||||
|    assign x_ctl_en                 =  dec_ctl_en[1]; | ||||
|    assign r_ctl_en                 =  dec_ctl_en[0]; | ||||
| 
 | ||||
|  | @ -240,7 +231,7 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
|    el2_exu_alu_ctl #(.pt(pt)) i_alu  (.*, | ||||
|                           .enable            ( x_ctl_en                    ),   // I
 | ||||
|                           .enable            ( x_data_en                   ),   // I
 | ||||
|                           .pp_in             ( i0_predict_newp_d           ),   // I
 | ||||
|                           .valid_in          ( dec_i0_alu_decode_d         ),   // I
 | ||||
|                           .flush_upper_x     ( i0_flush_upper_x            ),   // I
 | ||||
|  | @ -251,6 +242,7 @@ import el2_pkg::*; | |||
|                           .brimm_in          ( dec_i0_br_immed_d[12:1]     ),   // I
 | ||||
|                           .ap                ( i0_ap                       ),   // I
 | ||||
|                           .csr_ren_in        ( dec_csr_ren_d               ),   // I
 | ||||
|                           .csr_rddata_in     ( dec_csr_rddata_d[31:0]      ),   // I
 | ||||
|                           .result_ff         ( alu_result_x[31:0]          ),   // O
 | ||||
|                           .flush_upper_out   ( i0_flush_upper_d            ),   // O
 | ||||
|                           .flush_final_out   ( exu_flush_final             ),   // O
 | ||||
|  | @ -262,10 +254,10 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
|    el2_exu_mul_ctl #(.pt(pt)) i_mul   (.*, | ||||
|                           .mul_p             ( mul_p                       ),   // I
 | ||||
|                           .rs1_in            ( muldiv_rs1_d[31:0]          ),   // I
 | ||||
|                           .rs2_in            ( muldiv_rs2_d[31:0]          ),   // I
 | ||||
|                           .result_x          ( mul_result_x[31:0]          ));  // O
 | ||||
|                           .mul_p             ( mul_p              & {$bits(el2_mul_pkt_t){mul_p.valid}} ),   // I
 | ||||
|                           .rs1_in            ( muldiv_rs1_d[31:0] & {32{mul_p.valid}}                    ),   // I
 | ||||
|                           .rs2_in            ( i0_rs2_d[31:0]     & {32{mul_p.valid}}                    ),   // I
 | ||||
|                           .result_x          ( mul_result_x[31:0]                                        ));  // O
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -273,7 +265,7 @@ import el2_pkg::*; | |||
|                           .cancel            ( dec_div_cancel              ),   // I
 | ||||
|                           .dp                ( div_p                       ),   // I
 | ||||
|                           .dividend          ( muldiv_rs1_d[31:0]          ),   // I
 | ||||
|                           .divisor           ( muldiv_rs2_d[31:0]          ),   // I
 | ||||
|                           .divisor           ( i0_rs2_d[31:0]              ),   // I
 | ||||
|                           .finish_dly        ( exu_div_wren                ),   // O
 | ||||
|                           .out               ( exu_div_result[31:0]        ));  // O
 | ||||
| 
 | ||||
|  | @ -298,7 +290,7 @@ import el2_pkg::*; | |||
|    assign i0_valid_d               =  i0_predict_p_d.valid  & dec_i0_alu_decode_d & ~dec_tlu_flush_lower_r; | ||||
|    assign i0_taken_d               = (i0_predict_p_d.ataken & dec_i0_alu_decode_d); | ||||
| 
 | ||||
| 
 | ||||
| if(pt.BTB_ENABLE==1) begin | ||||
|    // maintain GHR at D
 | ||||
|    assign ghr_d_ns[pt.BHT_GHR_SIZE-1:0] | ||||
|                                    = ({pt.BHT_GHR_SIZE{~dec_tlu_flush_lower_r &  i0_valid_d}} & {ghr_d[pt.BHT_GHR_SIZE-2:0], i0_taken_d}) | | ||||
|  | @ -314,7 +306,7 @@ import el2_pkg::*; | |||
|    assign exu_i0_br_valid_r                                 =  i0_pp_r.valid; | ||||
|    assign exu_i0_br_mp_r                                    =  i0_pp_r.misp; | ||||
|    assign exu_i0_br_way_r                                   =  i0_pp_r.way; | ||||
|    assign exu_i0_br_hist_r[1:0]                             =  i0_pp_r.hist[1:0]; | ||||
|    assign exu_i0_br_hist_r[1:0]                             =  {2{i0_pp_r.valid}} & i0_pp_r.hist[1:0]; | ||||
|    assign exu_i0_br_error_r                                 =  i0_pp_r.br_error; | ||||
|    assign exu_i0_br_middle_r                                =  i0_pp_r.pc4 ^ i0_pp_r.boffset; | ||||
|    assign exu_i0_br_start_error_r                           =  i0_pp_r.br_start_error; | ||||
|  | @ -330,6 +322,7 @@ import el2_pkg::*; | |||
|    assign after_flush_eghr[pt.BHT_GHR_SIZE-1:0]             = (i0_flush_upper_x & ~dec_tlu_flush_lower_r)  ?  ghr_d[pt.BHT_GHR_SIZE-1:0]  :  ghr_x[pt.BHT_GHR_SIZE-1:0]; | ||||
| 
 | ||||
| 
 | ||||
|    assign exu_mp_pkt.valid                                  =  final_predict_mp.valid; | ||||
|    assign exu_mp_pkt.way                                    =  final_predict_mp.way; | ||||
|    assign exu_mp_pkt.misp                                   =  final_predict_mp.misp; | ||||
|    assign exu_mp_pkt.pcall                                  =  final_predict_mp.pcall; | ||||
|  | @ -347,11 +340,30 @@ import el2_pkg::*; | |||
|            exu_mp_btag[pt.BTB_BTAG_SIZE-1:0]}               =  final_predpipe_mp[PREDPIPESIZE-pt.BHT_GHR_SIZE-1:0]; | ||||
| 
 | ||||
|    assign exu_mp_eghr[pt.BHT_GHR_SIZE-1:0]                  =  final_predpipe_mp[PREDPIPESIZE-1:pt.BTB_ADDR_HI-pt.BTB_ADDR_LO+pt.BTB_BTAG_SIZE+1]; // mp ghr for bht write
 | ||||
| end // if (pt.BTB_ENABLE==1)
 | ||||
| else begin | ||||
|    assign ghr_d_ns = '0; | ||||
|    assign ghr_x_ns = '0; | ||||
|    assign exu_mp_pkt = '0; | ||||
|    assign exu_mp_eghr = '0; | ||||
|    assign exu_mp_fghr = '0; | ||||
|    assign exu_mp_index = '0; | ||||
|    assign exu_mp_btag = '0; | ||||
|    assign exu_i0_br_hist_r = '0; | ||||
|    assign exu_i0_br_error_r = '0; | ||||
|    assign exu_i0_br_start_error_r = '0; | ||||
|    assign exu_i0_br_index_r = '0; | ||||
|    assign exu_i0_br_valid_r = '0; | ||||
|    assign exu_i0_br_mp_r = '0; | ||||
|    assign exu_i0_br_middle_r = '0; | ||||
|    assign exu_i0_br_fghr_r = '0; | ||||
|    assign exu_i0_br_way_r = '0; | ||||
| end // else: !if(pt.BTB_ENABLE==1)
 | ||||
| 
 | ||||
|    assign exu_flush_path_final[31:1] = (dec_tlu_flush_lower_r)    ?  dec_tlu_flush_path_r[31:1]  :  i0_flush_path_d[31:1]; | ||||
|    assign exu_flush_path_final[31:1] = ( {31{ dec_tlu_flush_lower_r                   }} & dec_tlu_flush_path_r[31:1] ) | | ||||
|                                        ( {31{~dec_tlu_flush_lower_r & i0_flush_upper_d}} & i0_flush_path_d[31:1]      ); | ||||
| 
 | ||||
|    assign exu_npc_r[31:1]            = (i0_pred_correct_upper_r)  ?  pred_correct_npc_r[31:1]    : | ||||
|                                                                      i0_flush_path_upper_r[31:1]; | ||||
|    assign exu_npc_r[31:1]            = (i0_pred_correct_upper_r)  ?  pred_correct_npc_r[31:1]    :  i0_flush_path_upper_r[31:1]; | ||||
| 
 | ||||
| 
 | ||||
| endmodule // el2_exu
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -29,7 +29,8 @@ import el2_pkg::*; | |||
|    input  logic                  enable,             // Clock enable
 | ||||
|    input  logic                  valid_in,           // Valid
 | ||||
|    input  el2_alu_pkt_t         ap,                 // predecodes
 | ||||
|    input  logic                  csr_ren_in,         // extra decode
 | ||||
|    input  logic                  csr_ren_in,         // CSR select
 | ||||
|    input  logic        [31:0]    csr_rddata_in,      // CSR data
 | ||||
|    input  logic signed [31:0]    a_in,               // A operand
 | ||||
|    input  logic        [31:0]    b_in,               // B operand
 | ||||
|    input  logic        [31:1]    pc_in,              // for pc=pc+2,4 calculations
 | ||||
|  | @ -47,13 +48,10 @@ import el2_pkg::*; | |||
|   ); | ||||
| 
 | ||||
| 
 | ||||
|    logic               [31:0]    zba_a_in; | ||||
|    logic               [31:0]    aout; | ||||
|    logic                         cout,ov,neg; | ||||
|    logic               [31:0]    lout; | ||||
|    logic               [5:0]     shift_amount; | ||||
|    logic               [31:0]    shift_mask; | ||||
|    logic               [62:0]    shift_extend; | ||||
|    logic               [62:0]    shift_long; | ||||
|    logic               [31:0]    sout; | ||||
|    logic                         sel_shift; | ||||
|    logic                         sel_adder; | ||||
|  | @ -72,10 +70,148 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // *** Start - BitManip ***
 | ||||
| 
 | ||||
|    // Zbb
 | ||||
|    logic                  ap_clz; | ||||
|    logic                  ap_ctz; | ||||
|    logic                  ap_pcnt; | ||||
|    logic                  ap_sext_b; | ||||
|    logic                  ap_sext_h; | ||||
|    logic                  ap_min; | ||||
|    logic                  ap_max; | ||||
|    logic                  ap_pack; | ||||
|    logic                  ap_packu; | ||||
|    logic                  ap_packh; | ||||
|    logic                  ap_rol; | ||||
|    logic                  ap_ror; | ||||
|    logic                  ap_rev; | ||||
|    logic                  ap_rev8; | ||||
|    logic                  ap_orc_b; | ||||
|    logic                  ap_orc16; | ||||
|    logic                  ap_zbb; | ||||
| 
 | ||||
|    // Zbs
 | ||||
|    logic                  ap_sbset; | ||||
|    logic                  ap_sbclr; | ||||
|    logic                  ap_sbinv; | ||||
|    logic                  ap_sbext; | ||||
| 
 | ||||
|    // Zbr
 | ||||
|    logic                  ap_slo; | ||||
|    logic                  ap_sro; | ||||
| 
 | ||||
|    // Zba
 | ||||
|    logic                  ap_sh1add; | ||||
|    logic                  ap_sh2add; | ||||
|    logic                  ap_sh3add; | ||||
|    logic                  ap_zba; | ||||
| 
 | ||||
| 
 | ||||
|    rvdffe #(31) i_pc_ff       (.*, .en(enable),   .din(pc_in[31:1]),    .dout(pc_ff[31:1]));   // any PC is run through here - doesn't have to be alu
 | ||||
|    rvdffe #(32) i_result_ff   (.*, .en(enable),   .din(result[31:0]),   .dout(result_ff[31:0])); | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBB == 1) | ||||
|      begin | ||||
|        assign ap_clz          =  ap.clz; | ||||
|        assign ap_ctz          =  ap.ctz; | ||||
|        assign ap_pcnt         =  ap.pcnt; | ||||
|        assign ap_sext_b       =  ap.sext_b; | ||||
|        assign ap_sext_h       =  ap.sext_h; | ||||
|        assign ap_min          =  ap.min; | ||||
|        assign ap_max          =  ap.max; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_clz          =  1'b0; | ||||
|        assign ap_ctz          =  1'b0; | ||||
|        assign ap_pcnt         =  1'b0; | ||||
|        assign ap_sext_b       =  1'b0; | ||||
|        assign ap_sext_h       =  1'b0; | ||||
|        assign ap_min          =  1'b0; | ||||
|        assign ap_max          =  1'b0; | ||||
|      end | ||||
| 
 | ||||
| 
 | ||||
|    if ( (pt.BITMANIP_ZBB == 1) | (pt.BITMANIP_ZBP == 1) ) | ||||
|      begin | ||||
|        assign ap_pack         =  ap.pack; | ||||
|        assign ap_packu        =  ap.packu; | ||||
|        assign ap_packh        =  ap.packh; | ||||
|        assign ap_rol          =  ap.rol; | ||||
|        assign ap_ror          =  ap.ror; | ||||
|        assign ap_rev          =  ap.grev & (b_in[4:0] == 5'b11111); | ||||
|        assign ap_rev8         =  ap.grev & (b_in[4:0] == 5'b11000); | ||||
|        assign ap_orc_b        =  ap.gorc & (b_in[4:0] == 5'b00111); | ||||
|        assign ap_orc16        =  ap.gorc & (b_in[4:0] == 5'b10000); | ||||
|        assign ap_zbb          =  ap.zbb; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_pack         =  1'b0; | ||||
|        assign ap_packu        =  1'b0; | ||||
|        assign ap_packh        =  1'b0; | ||||
|        assign ap_rol          =  1'b0; | ||||
|        assign ap_ror          =  1'b0; | ||||
|        assign ap_rev          =  1'b0; | ||||
|        assign ap_rev8         =  1'b0; | ||||
|        assign ap_orc_b        =  1'b0; | ||||
|        assign ap_orc16        =  1'b0; | ||||
|        assign ap_zbb          =  1'b0; | ||||
|      end | ||||
| 
 | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBS == 1) | ||||
|      begin | ||||
|        assign ap_sbset        =  ap.sbset; | ||||
|        assign ap_sbclr        =  ap.sbclr; | ||||
|        assign ap_sbinv        =  ap.sbinv; | ||||
|        assign ap_sbext        =  ap.sbext; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_sbset        =  1'b0; | ||||
|        assign ap_sbclr        =  1'b0; | ||||
|        assign ap_sbinv        =  1'b0; | ||||
|        assign ap_sbext        =  1'b0; | ||||
|      end | ||||
| 
 | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBP == 1) | ||||
|      begin | ||||
|        assign ap_slo          =  ap.slo; | ||||
|        assign ap_sro          =  ap.sro; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_slo          =  1'b0; | ||||
|        assign ap_sro          =  1'b0; | ||||
|      end | ||||
| 
 | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBA == 1) | ||||
|      begin | ||||
|        assign ap_sh1add       =  ap.sh1add; | ||||
|        assign ap_sh2add       =  ap.sh2add; | ||||
|        assign ap_sh3add       =  ap.sh3add; | ||||
|        assign ap_zba          =  ap.zba; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_sh1add       =  1'b0; | ||||
|        assign ap_sh2add       =  1'b0; | ||||
|        assign ap_sh3add       =  1'b0; | ||||
|        assign ap_zba          =  1'b0; | ||||
|      end | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // *** End   - BitManip ***
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    rvdffpcie #(31) i_pc_ff      (.*, .clk(clk), .en(enable),              .din(pc_in[31:1]),    .dout(pc_ff[31:1]));   // any PC is run through here - doesn't have to be alu
 | ||||
|    rvdffe    #(32) i_result_ff  (.*, .clk(clk), .en(enable & valid_in),   .din(result[31:0]),   .dout(result_ff[31:0])); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -106,11 +242,17 @@ import el2_pkg::*; | |||
|    // jalr   =>  rs1=rs1,                 rs2=sext(offset20:1]);   rd=pc+[2,4]
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign zba_a_in[31:0]      = ( {32{ ap_sh1add}} & {a_in[30:0],1'b0} ) | | ||||
|                                 ( {32{ ap_sh2add}} & {a_in[29:0],2'b0} ) | | ||||
|                                 ( {32{ ap_sh3add}} & {a_in[28:0],3'b0} ) | | ||||
|                                 ( {32{~ap_zba   }} &  a_in[31:0]       ); | ||||
| 
 | ||||
|    logic        [31:0]    bm; | ||||
| 
 | ||||
|    assign bm[31:0]            = ( ap.sub )  ?  ~b_in[31:0]  :  b_in[31:0]; | ||||
| 
 | ||||
|    assign {cout, aout[31:0]}  = {1'b0, a_in[31:0]} + {1'b0, bm[31:0]} + {32'b0, ap.sub}; | ||||
|    assign {cout, aout[31:0]}  = {1'b0, zba_a_in[31:0]} + {1'b0, bm[31:0]} + {32'b0, ap.sub}; | ||||
| 
 | ||||
|    assign ov                  = (~a_in[31] & ~bm[31] &  aout[31]) | | ||||
|                                 ( a_in[31] &  bm[31] & ~aout[31] ); | ||||
|  | @ -118,7 +260,6 @@ import el2_pkg::*; | |||
|    assign lt                  = (~ap.unsign & (neg ^ ov)) | | ||||
|                                 ( ap.unsign & ~cout); | ||||
| 
 | ||||
| 
 | ||||
|    assign eq                  = (a_in[31:0] == b_in[31:0]); | ||||
|    assign ne                  = ~eq; | ||||
|    assign neg                 =  aout[31]; | ||||
|  | @ -126,39 +267,227 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign lout[31:0]          =  ( {32{csr_ren_in}} &                b_in[31:0]  ) | | ||||
|                                  ( {32{ap.land   }} &  a_in[31:0] &  b_in[31:0]  ) | | ||||
|                                  ( {32{ap.lor    }} & (a_in[31:0] |  b_in[31:0]) ) | | ||||
|                                  ( {32{ap.lxor   }} & (a_in[31:0] ^  b_in[31:0]) ); | ||||
|    assign lout[31:0]          =  ( {32{csr_ren_in       }} &  csr_rddata_in[31:0]       ) | | ||||
|                                  ( {32{ap.land & ~ap_zbb}} &  a_in[31:0] &  b_in[31:0]  ) | | ||||
|                                  ( {32{ap.lor  & ~ap_zbb}} & (a_in[31:0] |  b_in[31:0]) ) | | ||||
|                                  ( {32{ap.lxor & ~ap_zbb}} & (a_in[31:0] ^  b_in[31:0]) ) | | ||||
|                                  ( {32{ap.land &  ap_zbb}} &  a_in[31:0] & ~b_in[31:0]  ) | | ||||
|                                  ( {32{ap.lor  &  ap_zbb}} & (a_in[31:0] | ~b_in[31:0]) ) | | ||||
|                                  ( {32{ap.lxor &  ap_zbb}} & (a_in[31:0] ^ ~b_in[31:0]) ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  SLO,SRO      * * * * * * * * * * * * * * * * * *
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  ROL,ROR      * * * * * * * * * * * * * * * * * *
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  ZBEXT        * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic        [5:0]     shift_amount; | ||||
|    logic        [31:0]    shift_mask; | ||||
|    logic        [62:0]    shift_extend; | ||||
|    logic        [62:0]    shift_long; | ||||
| 
 | ||||
| 
 | ||||
|    assign shift_amount[5:0]            = ( { 6{ap.sll}}   & (6'd32 - {1'b0,b_in[4:0]}) ) |   // [5] unused
 | ||||
|                                          ( { 6{ap.srl}}   &          {1'b0,b_in[4:0]}  ) | | ||||
|                                          ( { 6{ap.sra}}   &          {1'b0,b_in[4:0]}  ); | ||||
|                                          ( { 6{ap.sra}}   &          {1'b0,b_in[4:0]}  ) | | ||||
|                                          ( { 6{ap_rol}}   & (6'd32 - {1'b0,b_in[4:0]}) ) | | ||||
|                                          ( { 6{ap_ror}}   &          {1'b0,b_in[4:0]}  ) | | ||||
|                                          ( { 6{ap_slo}}   & (6'd32 - {1'b0,b_in[4:0]}) ) | | ||||
|                                          ( { 6{ap_sro}}   &          {1'b0,b_in[4:0]}  ) | | ||||
|                                          ( { 6{ap_sbext}} &          {1'b0,b_in[4:0]}  ); | ||||
| 
 | ||||
| 
 | ||||
|    assign shift_mask[31:0]             = ( 32'hffffffff << ({5{ap.sll}} & b_in[4:0]) ); | ||||
|    assign shift_mask[31:0]             = ( 32'hffffffff << ({5{ap.sll | ap_slo}} & b_in[4:0]) ); | ||||
| 
 | ||||
| 
 | ||||
|    assign shift_extend[31:0]           =  a_in[31:0]; | ||||
| 
 | ||||
|    assign shift_extend[62:32]          = ( {31{ap.sra}} & {31{a_in[31]}} ) | | ||||
|                                          ( {31{ap.sll}} &     a_in[30:0] ); | ||||
|                                          ( {31{ap.sll}} &     a_in[30:0] ) | | ||||
|                                          ( {31{ap_rol}} &     a_in[30:0] ) | | ||||
|                                          ( {31{ap_ror}} &     a_in[30:0] ) | | ||||
|                                          ( {31{ap_slo}} &     a_in[30:0] ) | | ||||
|                                          ( {31{ap_sro}} & {31{  1'b1  }} ); | ||||
| 
 | ||||
| 
 | ||||
|    assign shift_long[62:0]    = ( shift_extend[62:0] >> shift_amount[4:0] );   // 62-32 unused
 | ||||
| 
 | ||||
|    assign sout[31:0]          = ( shift_long[31:0] & shift_mask[31:0] ); | ||||
|    assign sout[31:0]          = ( shift_long[31:0] & shift_mask[31:0] ) | ( {32{ap_slo}} & ~shift_mask[31:0] ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  CLZ,CTZ      * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic                  bitmanip_clz_ctz_sel; | ||||
|    logic        [31:0]    bitmanip_a_reverse_ff; | ||||
|    logic        [31:0]    bitmanip_lzd_in; | ||||
|    logic        [5:0]     bitmanip_dw_lzd_enc; | ||||
|    logic        [5:0]     bitmanip_clz_ctz_result; | ||||
| 
 | ||||
|    assign bitmanip_clz_ctz_sel         =  ap_clz | ap_ctz; | ||||
| 
 | ||||
|    assign bitmanip_a_reverse_ff[31:0]  = {a_in[0],  a_in[1],  a_in[2],  a_in[3],  a_in[4],  a_in[5],  a_in[6],  a_in[7], | ||||
|                                           a_in[8],  a_in[9],  a_in[10], a_in[11], a_in[12], a_in[13], a_in[14], a_in[15], | ||||
|                                           a_in[16], a_in[17], a_in[18], a_in[19], a_in[20], a_in[21], a_in[22], a_in[23], | ||||
|                                           a_in[24], a_in[25], a_in[26], a_in[27], a_in[28], a_in[29], a_in[30], a_in[31]}; | ||||
| 
 | ||||
|    assign bitmanip_lzd_in[31:0]        = ( {32{ap_clz}} & a_in[31:0]                 ) | | ||||
|                                          ( {32{ap_ctz}} & bitmanip_a_reverse_ff[31:0]); | ||||
| 
 | ||||
|    logic        [31:0]    bitmanip_lzd_os; | ||||
|    integer                i; | ||||
|    logic                  found; | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
|         bitmanip_lzd_os[31:0]   =  bitmanip_lzd_in[31:0]; | ||||
|         bitmanip_dw_lzd_enc[5:0]=  6'b0; | ||||
|         found = 1'b0; | ||||
| 
 | ||||
|         for (int i=0; i<32 && found==0; i++) begin | ||||
|            if (bitmanip_lzd_os[31] == 1'b0) begin | ||||
|               bitmanip_dw_lzd_enc[5:0]=  bitmanip_dw_lzd_enc[5:0] + 6'b00_0001; | ||||
|               bitmanip_lzd_os[31:0]   =  bitmanip_lzd_os[31:0] << 1; | ||||
|            end | ||||
|            else | ||||
|               found=1'b1; | ||||
|         end | ||||
|      end | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign bitmanip_clz_ctz_result[5:0] = {6{bitmanip_clz_ctz_sel}} & {bitmanip_dw_lzd_enc[5],( {5{~bitmanip_dw_lzd_enc[5]}} & bitmanip_dw_lzd_enc[4:0] )}; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  PCNT         * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic        [5:0]     bitmanip_pcnt; | ||||
|    logic        [5:0]     bitmanip_pcnt_result; | ||||
| 
 | ||||
| 
 | ||||
|    integer                bitmanip_pcnt_i; | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
|        bitmanip_pcnt[5:0]               =  6'b0; | ||||
| 
 | ||||
|        for (bitmanip_pcnt_i=0; bitmanip_pcnt_i<32; bitmanip_pcnt_i++) | ||||
|          begin | ||||
|             bitmanip_pcnt[5:0]          =  bitmanip_pcnt[5:0] + {5'b0,a_in[bitmanip_pcnt_i]}; | ||||
|          end      // FOR    bitmanip_pcnt_i
 | ||||
|      end          // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
|    assign bitmanip_pcnt_result[5:0]    =  {6{ap_pcnt}} & bitmanip_pcnt[5:0]; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  SEXT_B,SEXT_H  * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic       [31:0]     bitmanip_sext_result; | ||||
| 
 | ||||
|    assign bitmanip_sext_result[31:0]   = ( {32{ap_sext_b}} & { {24{a_in[7]}} ,a_in[7:0]  } ) | | ||||
|                                          ( {32{ap_sext_h}} & { {16{a_in[15]}},a_in[15:0] } ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  MIN,MAX,MINU,MAXU  * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic                  bitmanip_minmax_sel; | ||||
|    logic        [31:0]    bitmanip_minmax_result; | ||||
| 
 | ||||
|    assign bitmanip_minmax_sel          =  ap_min | ap_max; | ||||
| 
 | ||||
| 
 | ||||
|    logic                  bitmanip_minmax_sel_a; | ||||
| 
 | ||||
|    assign bitmanip_minmax_sel_a        =  ge  ^ ap_min; | ||||
| 
 | ||||
|    assign bitmanip_minmax_result[31:0] = ({32{bitmanip_minmax_sel &  bitmanip_minmax_sel_a}}  &  a_in[31:0]) | | ||||
|                                          ({32{bitmanip_minmax_sel & ~bitmanip_minmax_sel_a}}  &  b_in[31:0]); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  PACK, PACKU, PACKH * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic        [31:0]    bitmanip_pack_result; | ||||
|    logic        [31:0]    bitmanip_packu_result; | ||||
|    logic        [31:0]    bitmanip_packh_result; | ||||
| 
 | ||||
|    assign bitmanip_pack_result[31:0]   = {32{ap_pack}}  & {b_in[15:0], a_in[15:0]}; | ||||
|    assign bitmanip_packu_result[31:0]  = {32{ap_packu}} & {b_in[31:16],a_in[31:16]}; | ||||
|    assign bitmanip_packh_result[31:0]  = {32{ap_packh}} & {16'b0,b_in[7:0],a_in[7:0]}; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  REV, REV8, ORC_B * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic        [31:0]    bitmanip_rev_result; | ||||
|    logic        [31:0]    bitmanip_rev8_result; | ||||
|    logic        [31:0]    bitmanip_orc_b_result; | ||||
|    logic        [31:0]    bitmanip_orc16_result; | ||||
| 
 | ||||
|    assign bitmanip_rev_result[31:0]    = {32{ap_rev}}   & | ||||
|                                          {a_in[00],a_in[01],a_in[02],a_in[03],a_in[04],a_in[05],a_in[06],a_in[07], | ||||
|                                           a_in[08],a_in[09],a_in[10],a_in[11],a_in[12],a_in[13],a_in[14],a_in[15], | ||||
|                                           a_in[16],a_in[17],a_in[18],a_in[19],a_in[20],a_in[21],a_in[22],a_in[23], | ||||
|                                           a_in[24],a_in[25],a_in[26],a_in[27],a_in[28],a_in[29],a_in[30],a_in[31]}; | ||||
| 
 | ||||
|    assign bitmanip_rev8_result[31:0]   = {32{ap_rev8}}  & {a_in[7:0],a_in[15:8],a_in[23:16],a_in[31:24]}; | ||||
| 
 | ||||
| 
 | ||||
| // uint32_t gorc32(uint32_t rs1, uint32_t rs2)
 | ||||
| // {
 | ||||
| //      uint32_t x = rs1;
 | ||||
| //      int shamt = rs2 & 31;                                                        ORC.B  ORC16
 | ||||
| //      if (shamt &  1) x |= ((x & 0x55555555) <<  1) | ((x & 0xAAAAAAAA) >>  1);      1      0
 | ||||
| //      if (shamt &  2) x |= ((x & 0x33333333) <<  2) | ((x & 0xCCCCCCCC) >>  2);      1      0
 | ||||
| //      if (shamt &  4) x |= ((x & 0x0F0F0F0F) <<  4) | ((x & 0xF0F0F0F0) >>  4);      1      0
 | ||||
| //      if (shamt &  8) x |= ((x & 0x00FF00FF) <<  8) | ((x & 0xFF00FF00) >>  8);      0      0
 | ||||
| //      if (shamt & 16) x |= ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16);      0      1
 | ||||
| //      return x;
 | ||||
| // }
 | ||||
| 
 | ||||
| 
 | ||||
| // BEFORE              31  ,   30  ,   29  ,   28  ,    27  ,   26,     25,     24
 | ||||
| // shamt[0]  b =    a31|a30,a31|a30,a29|a28,a29|a28, a27|a26,a27|a26,a25|a24,a25|a24
 | ||||
| // shamt[1]  c =    b31|b29,b30|b28,b31|b29,b30|b28, b27|b25,b26|b24,b27|b25,b26|b24
 | ||||
| // shamt[2]  d =    c31|c27,c30|c26,c29|c25,c28|c24, c31|c27,c30|c26,c29|c25,c28|c24
 | ||||
| //
 | ||||
| // Expand d31 =        c31         |         c27;
 | ||||
| //            =   b31   |   b29    |    b27   |   b25;
 | ||||
| //            = a31|a30 | a29|a28  |  a27|a26 | a25|a24
 | ||||
| 
 | ||||
|    assign bitmanip_orc_b_result[31:0]  = {32{ap_orc_b}} & { {8{| a_in[31:24]}}, {8{| a_in[23:16]}}, {8{| a_in[15:8]}}, {8{| a_in[7:0]}} }; | ||||
| 
 | ||||
|    assign bitmanip_orc16_result[31:0]  = {32{ap_orc16}} & {     {a_in[31:16] | a_in[15:0]},             {a_in[31:16] | a_in[15:0]}      }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  ZBSET, ZBCLR, ZBINV  * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic        [31:0]    bitmanip_sb_1hot; | ||||
|    logic        [31:0]    bitmanip_sb_data; | ||||
| 
 | ||||
|    assign bitmanip_sb_1hot[31:0]       = ( 32'h00000001 << b_in[4:0] ); | ||||
| 
 | ||||
|    assign bitmanip_sb_data[31:0]       = ( {32{ap_sbset}} & ( a_in[31:0] |  bitmanip_sb_1hot[31:0]) ) | | ||||
|                                          ( {32{ap_sbclr}} & ( a_in[31:0] & ~bitmanip_sb_1hot[31:0]) ) | | ||||
|                                          ( {32{ap_sbinv}} & ( a_in[31:0] ^  bitmanip_sb_1hot[31:0]) ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign sel_shift           =  ap.sll  | ap.srl | ap.sra; | ||||
|    assign sel_adder           = (ap.add  | ap.sub) & ~ap.slt; | ||||
| 
 | ||||
|    assign sel_shift           =  ap.sll  | ap.srl | ap.sra | ap_slo | ap_sro | ap_rol | ap_ror; | ||||
|    assign sel_adder           = (ap.add  | ap.sub | ap_zba) & ~ap.slt & ~ap_min & ~ap_max; | ||||
|    assign sel_pc              =  ap.jal  | pp_in.pcall | pp_in.pja | pp_in.pret; | ||||
|    assign csr_write_data[31:0]= (ap.csr_imm)  ?  b_in[31:0]  :  a_in[31:0]; | ||||
| 
 | ||||
|  | @ -171,7 +500,20 @@ import el2_pkg::*; | |||
|                                 ({32{sel_adder}}    &  aout[31:0]           ) | | ||||
|                                 ({32{sel_pc}}       & {pcout[31:1],1'b0}    ) | | ||||
|                                 ({32{ap.csr_write}} &  csr_write_data[31:0] ) | | ||||
|                                                       {31'b0, slt_one}       ; | ||||
|                                                       {31'b0, slt_one}        | | ||||
|                                 ({32{ap_sbext}}     & {31'b0, sout[0]}      ) | | ||||
|                                                       {26'b0, bitmanip_clz_ctz_result[5:0]} | | ||||
|                                                       {26'b0, bitmanip_pcnt_result[5:0]}    | | ||||
|                                                        bitmanip_sext_result[31:0]    | | ||||
|                                                        bitmanip_minmax_result[31:0]  | | ||||
|                                                        bitmanip_pack_result[31:0]    | | ||||
|                                                        bitmanip_packu_result[31:0]   | | ||||
|                                                        bitmanip_packh_result[31:0]   | | ||||
|                                                        bitmanip_rev_result[31:0]     | | ||||
|                                                        bitmanip_rev8_result[31:0]    | | ||||
|                                                        bitmanip_orc_b_result[31:0]   | | ||||
|                                                        bitmanip_orc16_result[31:0]   | | ||||
|                                                        bitmanip_sb_data[31:0]; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -35,6 +35,7 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
|    logic                mul_x_enable; | ||||
|    logic                bit_x_enable; | ||||
|    logic signed [32:0]  rs1_ext_in; | ||||
|    logic signed [32:0]  rs2_ext_in; | ||||
|    logic        [65:0]  prod_x; | ||||
|  | @ -42,8 +43,116 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // *** Start - BitManip ***
 | ||||
| 
 | ||||
|    logic                bitmanip_sel_d; | ||||
|    logic                bitmanip_sel_x; | ||||
|    logic        [31:0]  bitmanip_d; | ||||
|    logic        [31:0]  bitmanip_x; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // ZBE
 | ||||
|    logic                ap_bext; | ||||
|    logic                ap_bdep; | ||||
| 
 | ||||
|    // ZBC
 | ||||
|    logic                ap_clmul; | ||||
|    logic                ap_clmulh; | ||||
|    logic                ap_clmulr; | ||||
| 
 | ||||
|    // ZBP
 | ||||
|    logic                ap_grev; | ||||
|    logic                ap_gorc; | ||||
|    logic                ap_shfl; | ||||
|    logic                ap_unshfl; | ||||
| 
 | ||||
|    // ZBR
 | ||||
|    logic                ap_crc32_b; | ||||
|    logic                ap_crc32_h; | ||||
|    logic                ap_crc32_w; | ||||
|    logic                ap_crc32c_b; | ||||
|    logic                ap_crc32c_h; | ||||
|    logic                ap_crc32c_w; | ||||
| 
 | ||||
|    // ZBF
 | ||||
|    logic                ap_bfp; | ||||
| 
 | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBE == 1) | ||||
|      begin | ||||
|        assign ap_bext         =  mul_p.bext; | ||||
|        assign ap_bdep         =  mul_p.bdep; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_bext         =  1'b0; | ||||
|        assign ap_bdep         =  1'b0; | ||||
|      end | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBC == 1) | ||||
|      begin | ||||
|        assign ap_clmul        =  mul_p.clmul; | ||||
|        assign ap_clmulh       =  mul_p.clmulh; | ||||
|        assign ap_clmulr       =  mul_p.clmulr; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_clmul        =  1'b0; | ||||
|        assign ap_clmulh       =  1'b0; | ||||
|        assign ap_clmulr       =  1'b0; | ||||
|      end | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBP == 1) | ||||
|      begin | ||||
|        assign ap_grev         =  mul_p.grev; | ||||
|        assign ap_gorc         =  mul_p.gorc; | ||||
|        assign ap_shfl         =  mul_p.shfl; | ||||
|        assign ap_unshfl       =  mul_p.unshfl; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_grev         =  1'b0; | ||||
|        assign ap_gorc         =  1'b0; | ||||
|        assign ap_shfl         =  1'b0; | ||||
|        assign ap_unshfl       =  1'b0; | ||||
|      end | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBR == 1) | ||||
|      begin | ||||
|        assign ap_crc32_b      =  mul_p.crc32_b; | ||||
|        assign ap_crc32_h      =  mul_p.crc32_h; | ||||
|        assign ap_crc32_w      =  mul_p.crc32_w; | ||||
|        assign ap_crc32c_b     =  mul_p.crc32c_b; | ||||
|        assign ap_crc32c_h     =  mul_p.crc32c_h; | ||||
|        assign ap_crc32c_w     =  mul_p.crc32c_w; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_crc32_b      =  1'b0; | ||||
|        assign ap_crc32_h      =  1'b0; | ||||
|        assign ap_crc32_w      =  1'b0; | ||||
|        assign ap_crc32c_b     =  1'b0; | ||||
|        assign ap_crc32c_h     =  1'b0; | ||||
|        assign ap_crc32c_w     =  1'b0; | ||||
|      end | ||||
| 
 | ||||
|    if (pt.BITMANIP_ZBF == 1) | ||||
|      begin | ||||
|        assign ap_bfp          =  mul_p.bfp; | ||||
|      end | ||||
|    else | ||||
|      begin | ||||
|        assign ap_bfp          =  1'b0; | ||||
|      end | ||||
| 
 | ||||
| 
 | ||||
|    // *** End   - BitManip ***
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign mul_x_enable           =  mul_p.valid; | ||||
|    assign bit_x_enable           =  mul_p.valid; | ||||
| 
 | ||||
|    assign rs1_ext_in[32]         =  mul_p.rs1_sign & rs1_in[31]; | ||||
|    assign rs2_ext_in[32]         =  mul_p.rs2_sign & rs2_in[31]; | ||||
|  | @ -59,17 +168,460 @@ import el2_pkg::*; | |||
|    logic signed [32:0]  rs1_x; | ||||
|    logic signed [32:0]  rs2_x; | ||||
| 
 | ||||
|    rvdffe #(34) i_a_x_ff         (.*, .din({mul_p.low,rs1_ext_in[32:0]}),        .dout({low_x,rs1_x[32:0]}),                 .en(mul_x_enable)); | ||||
|    rvdffe #(33) i_b_x_ff         (.*, .din(           rs2_ext_in[32:0] ),        .dout(       rs2_x[32:0] ),                 .en(mul_x_enable)); | ||||
|    rvdffe #(34) i_a_x_ff         (.*, .clk(clk),  .din({mul_p.low,rs1_ext_in[32:0]}),        .dout({low_x,rs1_x[32:0]}),                 .en(mul_x_enable)); | ||||
|    rvdffe #(33) i_b_x_ff         (.*, .clk(clk),  .din(           rs2_ext_in[32:0] ),        .dout(       rs2_x[32:0] ),                 .en(mul_x_enable)); | ||||
| 
 | ||||
| 
 | ||||
|    assign prod_x[65:0]           =  rs1_x  *  rs2_x; | ||||
| 
 | ||||
| 
 | ||||
|    assign result_x[31:0]         =  ( {32{~low_x}} & prod_x[63:32]    ) | | ||||
|                                     ( {32{ low_x}} & prod_x[31:0]     ); | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  BEXT, BDEP   * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
| 
 | ||||
|    // *** BEXT == "gather"  ***
 | ||||
| 
 | ||||
|    logic        [31:0]    bext_d; | ||||
|    logic                  bext_test_bit_d; | ||||
|    integer                bext_i, bext_j; | ||||
| 
 | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
| 
 | ||||
|        bext_j                    =      0; | ||||
|        bext_test_bit_d           =   1'b0; | ||||
|        bext_d[31:0]              =  32'b0; | ||||
| 
 | ||||
|        for (bext_i=0; bext_i<32; bext_i++) | ||||
|          begin | ||||
|              bext_test_bit_d     =  rs2_in[bext_i]; | ||||
|              if (bext_test_bit_d) | ||||
|                begin | ||||
|                   bext_d[bext_j] =  rs1_in[bext_i]; | ||||
|                   bext_j         =  bext_j + 1; | ||||
|                end  // IF  bext_test_bit
 | ||||
|          end        // FOR bext_i
 | ||||
|      end            // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // *** BDEP == "scatter" ***
 | ||||
| 
 | ||||
|    logic        [31:0]    bdep_d; | ||||
|    logic                  bdep_test_bit_d; | ||||
|    integer                bdep_i, bdep_j; | ||||
| 
 | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
| 
 | ||||
|        bdep_j                    =      0; | ||||
|        bdep_test_bit_d           =   1'b0; | ||||
|        bdep_d[31:0]              =  32'b0; | ||||
| 
 | ||||
|        for (bdep_i=0; bdep_i<32; bdep_i++) | ||||
|          begin | ||||
|              bdep_test_bit_d     =  rs2_in[bdep_i]; | ||||
|              if (bdep_test_bit_d) | ||||
|                begin | ||||
|                   bdep_d[bdep_i] =  rs1_in[bdep_j]; | ||||
|                   bdep_j         =  bdep_j + 1; | ||||
|                end  // IF  bdep_test_bit
 | ||||
|          end        // FOR bdep_i
 | ||||
|      end            // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  CLMUL, CLMULH, CLMULR  * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic        [62:0]    clmul_raw_d; | ||||
| 
 | ||||
| 
 | ||||
|    assign clmul_raw_d[62:0]      = ( {63{rs2_in[00]}} & {31'b0,rs1_in[31:0]      } ) ^ | ||||
|                                    ( {63{rs2_in[01]}} & {30'b0,rs1_in[31:0], 1'b0} ) ^ | ||||
|                                    ( {63{rs2_in[02]}} & {29'b0,rs1_in[31:0], 2'b0} ) ^ | ||||
|                                    ( {63{rs2_in[03]}} & {28'b0,rs1_in[31:0], 3'b0} ) ^ | ||||
|                                    ( {63{rs2_in[04]}} & {27'b0,rs1_in[31:0], 4'b0} ) ^ | ||||
|                                    ( {63{rs2_in[05]}} & {26'b0,rs1_in[31:0], 5'b0} ) ^ | ||||
|                                    ( {63{rs2_in[06]}} & {25'b0,rs1_in[31:0], 6'b0} ) ^ | ||||
|                                    ( {63{rs2_in[07]}} & {24'b0,rs1_in[31:0], 7'b0} ) ^ | ||||
|                                    ( {63{rs2_in[08]}} & {23'b0,rs1_in[31:0], 8'b0} ) ^ | ||||
|                                    ( {63{rs2_in[09]}} & {22'b0,rs1_in[31:0], 9'b0} ) ^ | ||||
|                                    ( {63{rs2_in[10]}} & {21'b0,rs1_in[31:0],10'b0} ) ^ | ||||
|                                    ( {63{rs2_in[11]}} & {20'b0,rs1_in[31:0],11'b0} ) ^ | ||||
|                                    ( {63{rs2_in[12]}} & {19'b0,rs1_in[31:0],12'b0} ) ^ | ||||
|                                    ( {63{rs2_in[13]}} & {18'b0,rs1_in[31:0],13'b0} ) ^ | ||||
|                                    ( {63{rs2_in[14]}} & {17'b0,rs1_in[31:0],14'b0} ) ^ | ||||
|                                    ( {63{rs2_in[15]}} & {16'b0,rs1_in[31:0],15'b0} ) ^ | ||||
|                                    ( {63{rs2_in[16]}} & {15'b0,rs1_in[31:0],16'b0} ) ^ | ||||
|                                    ( {63{rs2_in[17]}} & {14'b0,rs1_in[31:0],17'b0} ) ^ | ||||
|                                    ( {63{rs2_in[18]}} & {13'b0,rs1_in[31:0],18'b0} ) ^ | ||||
|                                    ( {63{rs2_in[19]}} & {12'b0,rs1_in[31:0],19'b0} ) ^ | ||||
|                                    ( {63{rs2_in[20]}} & {11'b0,rs1_in[31:0],20'b0} ) ^ | ||||
|                                    ( {63{rs2_in[21]}} & {10'b0,rs1_in[31:0],21'b0} ) ^ | ||||
|                                    ( {63{rs2_in[22]}} & { 9'b0,rs1_in[31:0],22'b0} ) ^ | ||||
|                                    ( {63{rs2_in[23]}} & { 8'b0,rs1_in[31:0],23'b0} ) ^ | ||||
|                                    ( {63{rs2_in[24]}} & { 7'b0,rs1_in[31:0],24'b0} ) ^ | ||||
|                                    ( {63{rs2_in[25]}} & { 6'b0,rs1_in[31:0],25'b0} ) ^ | ||||
|                                    ( {63{rs2_in[26]}} & { 5'b0,rs1_in[31:0],26'b0} ) ^ | ||||
|                                    ( {63{rs2_in[27]}} & { 4'b0,rs1_in[31:0],27'b0} ) ^ | ||||
|                                    ( {63{rs2_in[28]}} & { 3'b0,rs1_in[31:0],28'b0} ) ^ | ||||
|                                    ( {63{rs2_in[29]}} & { 2'b0,rs1_in[31:0],29'b0} ) ^ | ||||
|                                    ( {63{rs2_in[30]}} & { 1'b0,rs1_in[31:0],30'b0} ) ^ | ||||
|                                    ( {63{rs2_in[31]}} & {      rs1_in[31:0],31'b0} ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  GREV         * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    // uint32_t grev32(uint32_t rs1, uint32_t rs2)
 | ||||
|    // {
 | ||||
|    //     uint32_t x = rs1;
 | ||||
|    //     int shamt = rs2 & 31;
 | ||||
|    //
 | ||||
|    //     if (shamt &  1)  x = ( (x & 0x55555555) <<  1) | ( (x & 0xAAAAAAAA) >>  1);
 | ||||
|    //     if (shamt &  2)  x = ( (x & 0x33333333) <<  2) | ( (x & 0xCCCCCCCC) >>  2);
 | ||||
|    //     if (shamt &  4)  x = ( (x & 0x0F0F0F0F) <<  4) | ( (x & 0xF0F0F0F0) >>  4);
 | ||||
|    //     if (shamt &  8)  x = ( (x & 0x00FF00FF) <<  8) | ( (x & 0xFF00FF00) >>  8);
 | ||||
|    //     if (shamt & 16)  x = ( (x & 0x0000FFFF) << 16) | ( (x & 0xFFFF0000) >> 16);
 | ||||
|    //
 | ||||
|    //     return x;
 | ||||
|    //  }
 | ||||
| 
 | ||||
| 
 | ||||
|    logic        [31:0]    grev1_d; | ||||
|    logic        [31:0]    grev2_d; | ||||
|    logic        [31:0]    grev4_d; | ||||
|    logic        [31:0]    grev8_d; | ||||
|    logic        [31:0]    grev_d; | ||||
| 
 | ||||
| 
 | ||||
|    assign grev1_d[31:0]       = (rs2_in[0])  ?  {rs1_in[30],rs1_in[31],rs1_in[28],rs1_in[29],rs1_in[26],rs1_in[27],rs1_in[24],rs1_in[25], | ||||
|                                                  rs1_in[22],rs1_in[23],rs1_in[20],rs1_in[21],rs1_in[18],rs1_in[19],rs1_in[16],rs1_in[17], | ||||
|                                                  rs1_in[14],rs1_in[15],rs1_in[12],rs1_in[13],rs1_in[10],rs1_in[11],rs1_in[08],rs1_in[09], | ||||
|                                                  rs1_in[06],rs1_in[07],rs1_in[04],rs1_in[05],rs1_in[02],rs1_in[03],rs1_in[00],rs1_in[01]}  :  rs1_in[31:0]; | ||||
| 
 | ||||
|    assign grev2_d[31:0]       = (rs2_in[1])  ?  {grev1_d[29:28],grev1_d[31:30],grev1_d[25:24],grev1_d[27:26], | ||||
|                                                  grev1_d[21:20],grev1_d[23:22],grev1_d[17:16],grev1_d[19:18], | ||||
|                                                  grev1_d[13:12],grev1_d[15:14],grev1_d[09:08],grev1_d[11:10], | ||||
|                                                  grev1_d[05:04],grev1_d[07:06],grev1_d[01:00],grev1_d[03:02]}  :  grev1_d[31:0]; | ||||
| 
 | ||||
|    assign grev4_d[31:0]       = (rs2_in[2])  ?  {grev2_d[27:24],grev2_d[31:28],grev2_d[19:16],grev2_d[23:20], | ||||
|                                                  grev2_d[11:08],grev2_d[15:12],grev2_d[03:00],grev2_d[07:04]}  :  grev2_d[31:0]; | ||||
| 
 | ||||
|    assign grev8_d[31:0]       = (rs2_in[3])  ?  {grev4_d[23:16],grev4_d[31:24],grev4_d[07:00],grev4_d[15:08]}  :  grev4_d[31:0]; | ||||
| 
 | ||||
|    assign grev_d[31:0]        = (rs2_in[4])  ?  {grev8_d[15:00],grev8_d[31:16]}  :  grev8_d[31:0]; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  GORC         * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    // uint32_t gorc32(uint32_t rs1, uint32_t rs2)
 | ||||
|    // {
 | ||||
|    //     uint32_t x = rs1;
 | ||||
|    //     int shamt = rs2 & 31;
 | ||||
|    //
 | ||||
|    //     if (shamt &  1)  x |= ( (x & 0x55555555) <<  1) | ( (x & 0xAAAAAAAA) >>  1);
 | ||||
|    //     if (shamt &  2)  x |= ( (x & 0x33333333) <<  2) | ( (x & 0xCCCCCCCC) >>  2);
 | ||||
|    //     if (shamt &  4)  x |= ( (x & 0x0F0F0F0F) <<  4) | ( (x & 0xF0F0F0F0) >>  4);
 | ||||
|    //     if (shamt &  8)  x |= ( (x & 0x00FF00FF) <<  8) | ( (x & 0xFF00FF00) >>  8);
 | ||||
|    //     if (shamt & 16)  x |= ( (x & 0x0000FFFF) << 16) | ( (x & 0xFFFF0000) >> 16);
 | ||||
|    //
 | ||||
|    //     return x;
 | ||||
|    //  }
 | ||||
| 
 | ||||
| 
 | ||||
|    logic        [31:0]    gorc1_d; | ||||
|    logic        [31:0]    gorc2_d; | ||||
|    logic        [31:0]    gorc4_d; | ||||
|    logic        [31:0]    gorc8_d; | ||||
|    logic        [31:0]    gorc_d; | ||||
| 
 | ||||
| 
 | ||||
|    assign gorc1_d[31:0]       = ( {32{rs2_in[0]}} & {rs1_in[30],rs1_in[31],rs1_in[28],rs1_in[29],rs1_in[26],rs1_in[27],rs1_in[24],rs1_in[25], | ||||
|                                                      rs1_in[22],rs1_in[23],rs1_in[20],rs1_in[21],rs1_in[18],rs1_in[19],rs1_in[16],rs1_in[17], | ||||
|                                                      rs1_in[14],rs1_in[15],rs1_in[12],rs1_in[13],rs1_in[10],rs1_in[11],rs1_in[08],rs1_in[09], | ||||
|                                                      rs1_in[06],rs1_in[07],rs1_in[04],rs1_in[05],rs1_in[02],rs1_in[03],rs1_in[00],rs1_in[01]} ) | rs1_in[31:0]; | ||||
| 
 | ||||
|    assign gorc2_d[31:0]       = ( {32{rs2_in[1]}} & {gorc1_d[29:28],gorc1_d[31:30],gorc1_d[25:24],gorc1_d[27:26], | ||||
|                                                      gorc1_d[21:20],gorc1_d[23:22],gorc1_d[17:16],gorc1_d[19:18], | ||||
|                                                      gorc1_d[13:12],gorc1_d[15:14],gorc1_d[09:08],gorc1_d[11:10], | ||||
|                                                      gorc1_d[05:04],gorc1_d[07:06],gorc1_d[01:00],gorc1_d[03:02]} ) | gorc1_d[31:0]; | ||||
| 
 | ||||
|    assign gorc4_d[31:0]       = ( {32{rs2_in[2]}} & {gorc2_d[27:24],gorc2_d[31:28],gorc2_d[19:16],gorc2_d[23:20], | ||||
|                                                      gorc2_d[11:08],gorc2_d[15:12],gorc2_d[03:00],gorc2_d[07:04]} ) | gorc2_d[31:0]; | ||||
| 
 | ||||
|    assign gorc8_d[31:0]       = ( {32{rs2_in[3]}} & {gorc4_d[23:16],gorc4_d[31:24],gorc4_d[07:00],gorc4_d[15:08]} ) | gorc4_d[31:0]; | ||||
| 
 | ||||
|    assign gorc_d[31:0]        = ( {32{rs2_in[4]}} & {gorc8_d[15:00],gorc8_d[31:16]} ) | gorc8_d[31:0]; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  SHFL, UNSHLF * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    // uint32_t shuffle32_stage (uint32_t src, uint32_t maskL, uint32_t maskR, int N)
 | ||||
|    // {
 | ||||
|    //     uint32_t x  = src & ~(maskL | maskR);
 | ||||
|    //     x          |= ((src << N) & maskL) | ((src >> N) & maskR);
 | ||||
|    //     return x;
 | ||||
|    // }
 | ||||
|    //
 | ||||
|    //
 | ||||
|    //
 | ||||
|    // uint32_t shfl32(uint32_t rs1, uint32_t rs2)
 | ||||
|    // {
 | ||||
|    //     uint32_t x = rs1;
 | ||||
|    //     int shamt = rs2 & 15
 | ||||
|    //
 | ||||
|    //     if (shamt & 8)  x = shuffle32_stage(x, 0x00ff0000, 0x0000ff00, 8);
 | ||||
|    //     if (shamt & 4)  x = shuffle32_stage(x, 0x0f000f00, 0x00f000f0, 4);
 | ||||
|    //     if (shamt & 2)  x = shuffle32_stage(x, 0x30303030, 0xc0c0c0c0, 2);
 | ||||
|    //     if (shamt & 1)  x = shuffle32_stage(x, 0x44444444, 0x22222222, 1);
 | ||||
|    //
 | ||||
|    //     return x;
 | ||||
|    // }
 | ||||
| 
 | ||||
| 
 | ||||
|    logic        [31:0]    shfl8_d; | ||||
|    logic        [31:0]    shfl4_d; | ||||
|    logic        [31:0]    shfl2_d; | ||||
|    logic        [31:0]    shfl_d; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign shfl8_d[31:0]       = (rs2_in[3])  ?  {rs1_in[31:24],rs1_in[15:08],rs1_in[23:16],rs1_in[07:00]}      :  rs1_in[31:0]; | ||||
| 
 | ||||
|    assign shfl4_d[31:0]       = (rs2_in[2])  ?  {shfl8_d[31:28],shfl8_d[23:20],shfl8_d[27:24],shfl8_d[19:16], | ||||
|                                                  shfl8_d[15:12],shfl8_d[07:04],shfl8_d[11:08],shfl8_d[03:00]}  :  shfl8_d[31:0]; | ||||
| 
 | ||||
|    assign shfl2_d[31:0]       = (rs2_in[1])  ?  {shfl4_d[31:30],shfl4_d[27:26],shfl4_d[29:28],shfl4_d[25:24], | ||||
|                                                  shfl4_d[23:22],shfl4_d[19:18],shfl4_d[21:20],shfl4_d[17:16], | ||||
|                                                  shfl4_d[15:14],shfl4_d[11:10],shfl4_d[13:12],shfl4_d[09:08], | ||||
|                                                  shfl4_d[07:06],shfl4_d[03:02],shfl4_d[05:04],shfl4_d[01:00]}  :  shfl4_d[31:0]; | ||||
| 
 | ||||
|    assign shfl_d[31:0]        = (rs2_in[0])  ?  {shfl2_d[31],shfl2_d[29],shfl2_d[30],shfl2_d[28],shfl2_d[27],shfl2_d[25],shfl2_d[26],shfl2_d[24], | ||||
|                                                  shfl2_d[23],shfl2_d[21],shfl2_d[22],shfl2_d[20],shfl2_d[19],shfl2_d[17],shfl2_d[18],shfl2_d[16], | ||||
|                                                  shfl2_d[15],shfl2_d[13],shfl2_d[14],shfl2_d[12],shfl2_d[11],shfl2_d[09],shfl2_d[10],shfl2_d[08], | ||||
|                                                  shfl2_d[07],shfl2_d[05],shfl2_d[06],shfl2_d[04],shfl2_d[03],shfl2_d[01],shfl2_d[02],shfl2_d[00]}  :  shfl2_d[31:0]; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // uint32_t unshfl32(uint32_t rs1, uint32_t rs2)
 | ||||
|    // {
 | ||||
|    //     uint32_t x = rs1;
 | ||||
|    //     int shamt = rs2 & 15
 | ||||
|    //
 | ||||
|    //     if (shamt & 1)  x = shuffle32_stage(x, 0x44444444, 0x22222222, 1);
 | ||||
|    //     if (shamt & 2)  x = shuffle32_stage(x, 0x30303030, 0xc0c0c0c0, 2);
 | ||||
|    //     if (shamt & 4)  x = shuffle32_stage(x, 0x0f000f00, 0x00f000f0, 4);
 | ||||
|    //     if (shamt & 8)  x = shuffle32_stage(x, 0x00ff0000, 0x0000ff00, 8);
 | ||||
|    //
 | ||||
|    //     return x;
 | ||||
|    // }
 | ||||
| 
 | ||||
| 
 | ||||
|    logic        [31:0]    unshfl1_d; | ||||
|    logic        [31:0]    unshfl2_d; | ||||
|    logic        [31:0]    unshfl4_d; | ||||
|    logic        [31:0]    unshfl_d; | ||||
| 
 | ||||
| 
 | ||||
|    assign unshfl1_d[31:0]     = (rs2_in[0])  ?  {rs1_in[31],rs1_in[29],rs1_in[30],rs1_in[28],rs1_in[27],rs1_in[25],rs1_in[26],rs1_in[24], | ||||
|                                                  rs1_in[23],rs1_in[21],rs1_in[22],rs1_in[20],rs1_in[19],rs1_in[17],rs1_in[18],rs1_in[16], | ||||
|                                                  rs1_in[15],rs1_in[13],rs1_in[14],rs1_in[12],rs1_in[11],rs1_in[09],rs1_in[10],rs1_in[08], | ||||
|                                                  rs1_in[07],rs1_in[05],rs1_in[06],rs1_in[04],rs1_in[03],rs1_in[01],rs1_in[02],rs1_in[00]}  :  rs1_in[31:0]; | ||||
| 
 | ||||
|    assign unshfl2_d[31:0]     = (rs2_in[1])  ?  {unshfl1_d[31:30],unshfl1_d[27:26],unshfl1_d[29:28],unshfl1_d[25:24], | ||||
|                                                  unshfl1_d[23:22],unshfl1_d[19:18],unshfl1_d[21:20],unshfl1_d[17:16], | ||||
|                                                  unshfl1_d[15:14],unshfl1_d[11:10],unshfl1_d[13:12],unshfl1_d[09:08], | ||||
|                                                  unshfl1_d[07:06],unshfl1_d[03:02],unshfl1_d[05:04],unshfl1_d[01:00]}  :  unshfl1_d[31:0]; | ||||
| 
 | ||||
|    assign unshfl4_d[31:0]     = (rs2_in[2])  ?  {unshfl2_d[31:28],unshfl2_d[23:20],unshfl2_d[27:24],unshfl2_d[19:16], | ||||
|                                                  unshfl2_d[15:12],unshfl2_d[07:04],unshfl2_d[11:08],unshfl2_d[03:00]}  :  unshfl2_d[31:0]; | ||||
| 
 | ||||
|    assign unshfl_d[31:0]      = (rs2_in[3])  ?  {unshfl4_d[31:24],unshfl4_d[15:08],unshfl4_d[23:16],unshfl4_d[07:00]}  :  unshfl4_d[31:0]; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  CRC32, CRC32c  * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    // ***  computed from   https: //crccalc.com  ***
 | ||||
|    //
 | ||||
|    // "a" is 8'h61 = 8'b0110_0001    (8'h61 ^ 8'hff = 8'h9e)
 | ||||
|    //
 | ||||
|    // Input must first be XORed with 32'hffff_ffff
 | ||||
|    //
 | ||||
|    //
 | ||||
|    // CRC32
 | ||||
|    //
 | ||||
|    // Input    Output        Input      Output
 | ||||
|    // -----   --------      --------   --------
 | ||||
|    // "a"     e8b7be43      ffffff9e   174841bc
 | ||||
|    // "aa"    078a19d7      ffff9e9e   f875e628
 | ||||
|    // "aaaa"  ad98e545      9e9e9e9e   5267a1ba
 | ||||
|    //
 | ||||
|    //
 | ||||
|    //
 | ||||
|    // CRC32c
 | ||||
|    //
 | ||||
|    // Input    Output        Input      Output
 | ||||
|    // -----   --------      --------   --------
 | ||||
|    // "a"     c1d04330      ffffff9e   3e2fbccf
 | ||||
|    // "aa"    f1f2dac2      ffff9e9e   0e0d253d
 | ||||
|    // "aaaa"  6a52eeb0      9e9e9e9e   95ad114f
 | ||||
| 
 | ||||
| 
 | ||||
|    logic                  crc32_all; | ||||
|    logic        [31:0]    crc32_poly_rev; | ||||
|    logic        [31:0]    crc32c_poly_rev; | ||||
|    integer                crc32_bi, crc32_hi, crc32_wi, crc32c_bi, crc32c_hi, crc32c_wi; | ||||
|    logic        [31:0]    crc32_bd, crc32_hd, crc32_wd, crc32c_bd, crc32c_hd, crc32c_wd; | ||||
| 
 | ||||
| 
 | ||||
|    assign crc32_all              =  ap_crc32_b  | ap_crc32_h  | ap_crc32_w | ap_crc32c_b | ap_crc32c_h | ap_crc32c_w; | ||||
| 
 | ||||
|    assign crc32_poly_rev[31:0]   =  32'hEDB88320;    // bit reverse of 32'h04C11DB7
 | ||||
|    assign crc32c_poly_rev[31:0]  =  32'h82F63B78;    // bit reverse of 32'h1EDC6F41
 | ||||
| 
 | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
|        crc32_bd[31:0]            =  rs1_in[31:0]; | ||||
| 
 | ||||
|        for (crc32_bi=0; crc32_bi<8; crc32_bi++) | ||||
|          begin | ||||
|             crc32_bd[31:0] = (crc32_bd[31:0] >> 1) ^ (crc32_poly_rev[31:0] & {32{crc32_bd[0]}}); | ||||
|          end      // FOR    crc32_bi
 | ||||
|      end          // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
|        crc32_hd[31:0]            =  rs1_in[31:0]; | ||||
| 
 | ||||
|        for (crc32_hi=0; crc32_hi<16; crc32_hi++) | ||||
|          begin | ||||
|             crc32_hd[31:0] = (crc32_hd[31:0] >> 1) ^ (crc32_poly_rev[31:0] & {32{crc32_hd[0]}}); | ||||
|          end      // FOR    crc32_hi
 | ||||
|      end          // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
|        crc32_wd[31:0]            =  rs1_in[31:0]; | ||||
| 
 | ||||
|        for (crc32_wi=0; crc32_wi<32; crc32_wi++) | ||||
|          begin | ||||
|             crc32_wd[31:0] = (crc32_wd[31:0] >> 1) ^ (crc32_poly_rev[31:0] & {32{crc32_wd[0]}}); | ||||
|          end      // FOR    crc32_wi
 | ||||
|      end          // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
|        crc32c_bd[31:0]           =  rs1_in[31:0]; | ||||
| 
 | ||||
|        for (crc32c_bi=0; crc32c_bi<8; crc32c_bi++) | ||||
|          begin | ||||
|             crc32c_bd[31:0] = (crc32c_bd[31:0] >> 1) ^ (crc32c_poly_rev[31:0] & {32{crc32c_bd[0]}}); | ||||
|          end      // FOR    crc32c_bi
 | ||||
|      end          // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
|        crc32c_hd[31:0]           =  rs1_in[31:0]; | ||||
| 
 | ||||
|        for (crc32c_hi=0; crc32c_hi<16; crc32c_hi++) | ||||
|          begin | ||||
|             crc32c_hd[31:0] = (crc32c_hd[31:0] >> 1) ^ (crc32c_poly_rev[31:0] & {32{crc32c_hd[0]}}); | ||||
|          end      // FOR    crc32c_hi
 | ||||
|      end          // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
|    always_comb | ||||
|      begin | ||||
|        crc32c_wd[31:0]           =  rs1_in[31:0]; | ||||
| 
 | ||||
|        for (crc32c_wi=0; crc32c_wi<32; crc32c_wi++) | ||||
|          begin | ||||
|             crc32c_wd[31:0] = (crc32c_wd[31:0] >> 1) ^ (crc32c_poly_rev[31:0] & {32{crc32c_wd[0]}}); | ||||
|          end      // FOR    crc32c_wi
 | ||||
|      end          // ALWAYS_COMB
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  BFP          * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
|    logic        [4:0]     bfp_len; | ||||
|    logic        [4:0]     bfp_off; | ||||
|    logic        [31:0]    bfp_len_mask_; | ||||
|    logic        [15:0]    bfp_preshift_data; | ||||
|    logic        [63:0]    bfp_shift_data; | ||||
|    logic        [63:0]    bfp_shift_mask; | ||||
|    logic        [31:0]    bfp_result_d; | ||||
| 
 | ||||
| 
 | ||||
|    assign bfp_len[3:0]           =  rs2_in[27:24]; | ||||
|    assign bfp_len[4]             = (bfp_len[3:0] == 4'b0);   // If LEN field is zero, then LEN=16
 | ||||
|    assign bfp_off[4:0]           =  rs2_in[20:16]; | ||||
| 
 | ||||
|    assign bfp_len_mask_[31:0]    =  32'hffff_ffff  <<  bfp_len[4:0]; | ||||
|    assign bfp_preshift_data[15:0]=  rs2_in[15:0] & ~bfp_len_mask_[15:0]; | ||||
| 
 | ||||
|    assign bfp_shift_data[63:0]   = {16'b0,bfp_preshift_data[15:0], 16'b0,bfp_preshift_data[15:0]}  <<  bfp_off[4:0]; | ||||
|    assign bfp_shift_mask[63:0]   = {bfp_len_mask_[31:0],           bfp_len_mask_[31:0]}            <<  bfp_off[4:0]; | ||||
| 
 | ||||
|    assign bfp_result_d[31:0]     = bfp_shift_data[63:32] | (rs1_in[31:0] & bfp_shift_mask[63:32]); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // * * * * * * * * * * * * * * * * * *  BitManip  :  Common logic * * * * * * * * * * * * * * * * * *
 | ||||
| 
 | ||||
| 
 | ||||
|    assign bitmanip_sel_d         =  ap_bext | ap_bdep | ap_clmul | ap_clmulh | ap_clmulr | ap_grev | ap_gorc | ap_shfl | ap_unshfl | crc32_all | ap_bfp; | ||||
| 
 | ||||
|    assign bitmanip_d[31:0]       = ( {32{ap_bext}}     &       bext_d[31:0]        ) | | ||||
|                                    ( {32{ap_bdep}}     &       bdep_d[31:0]        ) | | ||||
|                                    ( {32{ap_clmul}}    &       clmul_raw_d[31:0]   ) | | ||||
|                                    ( {32{ap_clmulh}}   & {1'b0,clmul_raw_d[62:32]} ) | | ||||
|                                    ( {32{ap_clmulr}}   &       clmul_raw_d[62:31]  ) | | ||||
|                                    ( {32{ap_grev}}     &       grev_d[31:0]        ) | | ||||
|                                    ( {32{ap_gorc}}     &       gorc_d[31:0]        ) | | ||||
|                                    ( {32{ap_shfl}}     &       shfl_d[31:0]        ) | | ||||
|                                    ( {32{ap_unshfl}}   &       unshfl_d[31:0]      ) | | ||||
|                                    ( {32{ap_crc32_b}}  &       crc32_bd[31:0]      ) | | ||||
|                                    ( {32{ap_crc32_h}}  &       crc32_hd[31:0]      ) | | ||||
|                                    ( {32{ap_crc32_w}}  &       crc32_wd[31:0]      ) | | ||||
|                                    ( {32{ap_crc32c_b}} &       crc32c_bd[31:0]     ) | | ||||
|                                    ( {32{ap_crc32c_h}} &       crc32c_hd[31:0]     ) | | ||||
|                                    ( {32{ap_crc32c_w}} &       crc32c_wd[31:0]     ) | | ||||
|                                    ( {32{ap_bfp}}      &       bfp_result_d[31:0]  ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    rvdffe #(33) i_bitmanip_ff    (.*, .clk(clk),  .din({bitmanip_sel_d,bitmanip_d[31:0]}),   .dout({bitmanip_sel_x,bitmanip_x[31:0]}),   .en(bit_x_enable)); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign result_x[31:0]         =  ( {32{~bitmanip_sel_x & ~low_x}} & prod_x[63:32]    ) | | ||||
|                                     ( {32{~bitmanip_sel_x &  low_x}} & prod_x[31:0]     ) | | ||||
|                                                                        bitmanip_x[31:0]; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| endmodule  // el2_exu_mul_ctl
 | ||||
|  |  | |||
|  | @ -0,0 +1,63 @@ | |||
| #-*-dotf-*- | ||||
| 
 | ||||
| $RV_ROOT/design/include/el2_def.sv | ||||
| 
 | ||||
| +incdir+$RV_ROOT/design/lib | ||||
| +incdir+$RV_ROOT/design/include | ||||
| +incdir+$RV_ROOT/design/dmi | ||||
| 
 | ||||
| //|+incdir+$SYNOPSYS_SYN_ROOT/dw/sim_ver | ||||
| //|-y $SYNOPSYS_SYN_ROOT/dw/sim_ver | ||||
| //| | ||||
| //|$SYNOPSYS_SYN_ROOT/dw/sim_ver/DW01_addsub.v | ||||
| //|$SYNOPSYS_SYN_ROOT/dw/sim_ver/DW_lzd.v | ||||
| //|$SYNOPSYS_SYN_ROOT/dw/sim_ver/DW_minmax.v | ||||
| //|$SYNOPSYS_SYN_ROOT/dw/sim_ver/DW02_mult.v | ||||
| 
 | ||||
| +incdir+/wdc/apps/mentor/questa/formal/2019.2/share/MODIFIED/dw | ||||
| +incdir+/wdc/apps/mentor/questa/formal/2019.2/share/MODIFIED/dw/dw_datapath | ||||
|         /wdc/apps/mentor/questa/formal/2019.2/share/MODIFIED/dw/dw.remodel.v | ||||
| 
 | ||||
| $RV_ROOT/design/el2_swerv_wrapper.sv | ||||
| $RV_ROOT/design/el2_mem.sv | ||||
| $RV_ROOT/design/el2_pic_ctrl.sv | ||||
| $RV_ROOT/design/el2_swerv.sv | ||||
| $RV_ROOT/design/el2_dma_ctrl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_aln_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_compress_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_ifc_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_bp_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_ic_mem.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_mem_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_iccm_mem.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu.sv | ||||
| $RV_ROOT/design/dec/el2_dec_decode_ctl.sv | ||||
| $RV_ROOT/design/dec/el2_dec_gpr_ctl.sv | ||||
| $RV_ROOT/design/dec/el2_dec_ib_ctl.sv | ||||
| $RV_ROOT/design/dec/el2_dec_tlu_ctl.sv | ||||
| $RV_ROOT/design/dec/el2_dec_trigger.sv | ||||
| $RV_ROOT/design/dec/el2_dec.sv | ||||
| $RV_ROOT/design/exu/el2_exu_alu_ctl.sv | ||||
| $RV_ROOT/design/exu/el2_exu_mul_ctl.sv | ||||
| $RV_ROOT/design/exu/el2_exu_div_ctl.sv | ||||
| $RV_ROOT/design/exu/el2_exu.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_clkdomain.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_addrcheck.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_lsc_ctl.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_stbuf.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_bus_buffer.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_bus_intf.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_ecc.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_dccm_mem.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_dccm_ctl.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_trigger.sv | ||||
| $RV_ROOT/design/dbg/el2_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.v | ||||
| $RV_ROOT/design/lib/el2_lib.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,61 @@ | |||
| #-*-dotf-*- | ||||
| 
 | ||||
| # $RV_ROOT/workspace/work/snapshots/default/common_defines.vh | ||||
| # $RV_ROOT/configs/snapshots/default/common_defines.vh | ||||
| $RV_ROOT/workspace/work/snapshots/default/common_defines.vh | ||||
| 
 | ||||
| 
 | ||||
| $RV_ROOT/design/include/el2_def.sv | ||||
| 
 | ||||
| # +incdir+$RV_ROOT/workspace/work/snapshots/default | ||||
| # +incdir+$RV_ROOT/configs/snapshots/default | ||||
| +incdir+$RV_ROOT/workspace/work/snapshots/default | ||||
| 
 | ||||
| +incdir+$RV_ROOT/design/lib | ||||
| +incdir+$RV_ROOT/design/include | ||||
| +incdir+$RV_ROOT/design/dmi | ||||
| +incdir+$SYNOPSYS_SYN_ROOT/dw/sim_ver | ||||
| -y $SYNOPSYS_SYN_ROOT/dw/sim_ver | ||||
| $RV_ROOT/design/el2_swerv_wrapper.sv | ||||
| $RV_ROOT/design/el2_mem.sv | ||||
| $RV_ROOT/design/el2_pic_ctrl.sv | ||||
| $RV_ROOT/design/el2_swerv.sv | ||||
| $RV_ROOT/design/el2_dma_ctrl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_aln_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_compress_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_ifc_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_bp_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_ic_mem.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_mem_ctl.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu_iccm_mem.sv | ||||
| $RV_ROOT/design/ifu/el2_ifu.sv | ||||
| $RV_ROOT/design/dec/el2_dec_decode_ctl.sv | ||||
| $RV_ROOT/design/dec/el2_dec_gpr_ctl.sv | ||||
| $RV_ROOT/design/dec/el2_dec_ib_ctl.sv | ||||
| $RV_ROOT/design/dec/el2_dec_tlu_ctl.sv | ||||
| $RV_ROOT/design/dec/el2_dec_trigger.sv | ||||
| $RV_ROOT/design/dec/el2_dec.sv | ||||
| $RV_ROOT/design/exu/el2_exu_alu_ctl.sv | ||||
| $RV_ROOT/design/exu/el2_exu_mul_ctl.sv | ||||
| $RV_ROOT/design/exu/el2_exu_div_ctl.sv | ||||
| $RV_ROOT/design/exu/el2_exu.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_clkdomain.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_addrcheck.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_lsc_ctl.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_stbuf.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_bus_buffer.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_bus_intf.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_ecc.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_dccm_mem.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_dccm_ctl.sv | ||||
| $RV_ROOT/design/lsu/el2_lsu_trigger.sv | ||||
| $RV_ROOT/design/dbg/el2_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.v | ||||
| $RV_ROOT/design/lib/el2_lib.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 | ||||
|  | @ -1,6 +1,6 @@ | |||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -25,12 +25,12 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
|   ( | ||||
|    input logic free_clk, | ||||
|    input logic active_clk, | ||||
|    input logic clk, | ||||
|    input logic rst_l, | ||||
|    input logic free_l2clk,                   // Clock always.                  Through one clock header.  For flops with    second header built in.
 | ||||
|    input logic active_clk,                   // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic clk,                          // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic rst_l,                        // reset, active low
 | ||||
| 
 | ||||
|    input logic dec_i0_decode_d, | ||||
|    input logic dec_i0_decode_d,              // Valid instruction at D and not blocked
 | ||||
| 
 | ||||
|    input logic exu_flush_final, // flush, includes upper and lower
 | ||||
|    input logic dec_tlu_i0_commit_cmt , // committed i0
 | ||||
|  | @ -87,7 +87,6 @@ import el2_pkg::*; | |||
|    input  logic [63:0]                     ifu_axi_rdata, | ||||
|    input  logic [1:0]                      ifu_axi_rresp, | ||||
| 
 | ||||
| 
 | ||||
|    input  logic                      ifu_bus_clk_en, | ||||
| 
 | ||||
|    input  logic                      dma_iccm_req, | ||||
|  | @ -160,24 +159,24 @@ import el2_pkg::*; | |||
|    output logic       ifu_pmu_bus_trxn, // iside bus transactions
 | ||||
| 
 | ||||
| 
 | ||||
|    output logic       ifu_i0_icaf,         // Instructio 0 access fault. From Aligner to Decode
 | ||||
|    output logic       ifu_i0_icaf,         // Instruction 0 access fault. From Aligner to Decode
 | ||||
|    output logic [1:0] ifu_i0_icaf_type, // Instruction 0 access fault type
 | ||||
| 
 | ||||
|    output logic  ifu_i0_valid,        // Instructio 0 valid. From Aligner to Decode
 | ||||
|    output logic  ifu_i0_icaf_f1,      // Instruction 0 has access fault on second fetch group
 | ||||
|    output logic  ifu_i0_valid,        // Instruction 0 valid. From Aligner to Decode
 | ||||
|    output logic  ifu_i0_icaf_second,  // Instruction 0 has access fault on second 2B of 4B inst
 | ||||
|    output logic  ifu_i0_dbecc,        // Instruction 0 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,   // Instructio 0 . From Aligner to Decode
 | ||||
|    output logic[31:1] ifu_i0_pc,      // Instructio 0 pc. From Aligner to Decode
 | ||||
|    output logic ifu_i0_pc4,           // Instructio 0 is 4 byte. From Aligner to Decode
 | ||||
|    output logic[31:0] ifu_i0_instr,   // Instruction 0 . From Aligner to Decode
 | ||||
|    output logic[31:1] ifu_i0_pc,      // Instruction 0 pc. From Aligner to Decode
 | ||||
|    output logic ifu_i0_pc4,           // Instruction 0 is 4 byte. From Aligner to Decode
 | ||||
| 
 | ||||
|    output logic ifu_miss_state_idle,   // There is no outstanding miss. Cache miss state is idle.
 | ||||
| 
 | ||||
| 
 | ||||
|    output el2_br_pkt_t i0_brp,           // Instructio 0 branch packet. From Aligner to Decode
 | ||||
|    output el2_br_pkt_t i0_brp,           // Instruction 0 branch packet. From Aligner to Decode
 | ||||
|    output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index, // BP index
 | ||||
|    output logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr, // BP FGHR
 | ||||
|    output logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag, // BP tag
 | ||||
|    output logic [$clog2(pt.BTB_SIZE)-1:0]         ifu_i0_fa_index,          // Fully associt btb index
 | ||||
| 
 | ||||
|    input el2_predict_pkt_t  exu_mp_pkt, // mispredict packet
 | ||||
|    input logic [pt.BHT_GHR_SIZE-1:0] exu_mp_eghr, // execute ghr
 | ||||
|  | @ -188,16 +187,18 @@ import el2_pkg::*; | |||
|    input el2_br_tlu_pkt_t dec_tlu_br0_r_pkt, // slot0 update/error pkt
 | ||||
|    input logic [pt.BHT_GHR_SIZE-1:0] exu_i0_br_fghr_r, // fghr to bp
 | ||||
|    input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] exu_i0_br_index_r, // bp index
 | ||||
|    input logic [$clog2(pt.BTB_SIZE)-1:0] dec_fa_error_index, // Fully associt btb error index
 | ||||
| 
 | ||||
|    input dec_tlu_flush_lower_wb, | ||||
| 
 | ||||
|    output logic [15:0] ifu_i0_cinst, | ||||
| 
 | ||||
| 
 | ||||
| /// Icache debug
 | ||||
|    input  el2_cache_debug_pkt_t        dec_tlu_ic_diag_pkt , | ||||
|    output logic                    ifu_ic_debug_rd_data_valid, | ||||
|     output logic                                iccm_buf_correct_ecc, | ||||
|     output logic                                iccm_correction_state, | ||||
|    output logic                                iccm_buf_correct_ecc, | ||||
|    output logic                                iccm_correction_state, | ||||
| 
 | ||||
|    input logic scan_mode | ||||
|    ); | ||||
|  | @ -220,22 +221,16 @@ import el2_pkg::*; | |||
|    logic        ic_write_stall; | ||||
|    logic        ic_dma_active; | ||||
|    logic        ifc_dma_access_ok; | ||||
|    logic        ic_access_fault_f; | ||||
|    logic [1:0]  ic_access_fault_f; | ||||
|    logic [1:0]  ic_access_fault_type_f; | ||||
|    logic        ifu_ic_mb_empty; | ||||
| 
 | ||||
| 
 | ||||
|    logic ic_hit_f; | ||||
| 
 | ||||
|    // fetch control
 | ||||
|    el2_ifu_ifc_ctl #(.pt(pt)) ifc (.* | ||||
|                     ); | ||||
| 
 | ||||
|    logic [1:0]  ifu_bp_way_f; // way indication; right justified
 | ||||
|    logic  ifu_bp_hit_taken_f; // kill next fetch; taken target found
 | ||||
|    logic [1:0] ifu_bp_way_f; // way indication; right justified
 | ||||
|    logic       ifu_bp_hit_taken_f; // kill next fetch; taken target found
 | ||||
|    logic [31:1] ifu_bp_btb_target_f; //  predicted target PC
 | ||||
|    logic        ifu_bp_inst_mask_f; // tell ic which valids to kill because of a taken branch; right justified
 | ||||
| 
 | ||||
|    logic [1:0]  ifu_bp_hist1_f; // history counters for all 4 potential branches; right justified
 | ||||
|    logic [1:0]  ifu_bp_hist0_f; // history counters for all 4 potential branches; right justified
 | ||||
|    logic [11:0] ifu_bp_poffset_f; // predicted target
 | ||||
|  | @ -243,9 +238,28 @@ import el2_pkg::*; | |||
|    logic [1:0]  ifu_bp_pc4_f; // pc4 indication; right justified
 | ||||
|    logic [1:0]  ifu_bp_valid_f; // branch valid, right justified
 | ||||
|    logic [pt.BHT_GHR_SIZE-1:0] ifu_bp_fghr_f; | ||||
|    logic [1:0] [$clog2(pt.BTB_SIZE)-1:0] ifu_bp_fa_index_f; | ||||
| 
 | ||||
| 
 | ||||
|    // fetch control
 | ||||
|    el2_ifu_ifc_ctl #(.pt(pt)) ifc (.* | ||||
|                     ); | ||||
| 
 | ||||
|    // branch predictor
 | ||||
|    el2_ifu_bp_ctl #(.pt(pt)) bp (.*); | ||||
|    if (pt.BTB_ENABLE==1) begin  : bpred | ||||
|       el2_ifu_bp_ctl #(.pt(pt)) bp (.*); | ||||
|    end | ||||
|    else begin : bpred | ||||
|       assign ifu_bp_hit_taken_f = '0; | ||||
|       // verif wires
 | ||||
|       logic btb_wr_en_way0, btb_wr_en_way1,dec_tlu_error_wb; | ||||
|       logic [16+pt.BTB_BTAG_SIZE:0] btb_wr_data; | ||||
|       assign btb_wr_en_way0 = '0; | ||||
|       assign btb_wr_en_way1 = '0; | ||||
|       assign btb_wr_data = '0; | ||||
|       assign dec_tlu_error_wb ='0; | ||||
|       assign ifu_bp_inst_mask_f = 1'b1; | ||||
|    end | ||||
| 
 | ||||
| 
 | ||||
|    logic [1:0]   ic_fetch_val_f; | ||||
|  | @ -253,7 +267,7 @@ import el2_pkg::*; | |||
|    logic [31:0] ifu_fetch_data_f; | ||||
|    logic ifc_fetch_req_f; | ||||
|    logic ifc_fetch_req_f_raw; | ||||
|    logic iccm_rd_ecc_double_err;  // This fetch has an iccm double error.
 | ||||
|    logic [1:0] iccm_rd_ecc_double_err;  // This fetch has an iccm double error.
 | ||||
| 
 | ||||
|    logic ifu_async_error_start; | ||||
| 
 | ||||
|  | @ -269,7 +283,10 @@ import el2_pkg::*; | |||
|  logic                       ifc_region_acc_fault_bf;       // Access fault. in ICCM region but offset is outside defined ICCM.
 | ||||
| 
 | ||||
|    // aligner
 | ||||
|    el2_ifu_aln_ctl #(.pt(pt)) aln (.*); | ||||
| 
 | ||||
|    el2_ifu_aln_ctl #(.pt(pt)) aln ( | ||||
|                                     .* | ||||
|                                     ); | ||||
| 
 | ||||
| 
 | ||||
|    // icache
 | ||||
|  | @ -316,29 +333,29 @@ import el2_pkg::*; | |||
|    logic        exu_flush_final_d1; | ||||
|    assign mppc_ns[31:1] = `EXU.i0_flush_upper_x ? `EXU.exu_i0_pc_x : `EXU.dec_i0_pc_d; | ||||
|    assign mppc_ns[0] = 1'b0; | ||||
|    rvdff #(33)  mdseal_ff (.*, .din({mppc_ns[31:0], exu_flush_final}), .dout({mppc[31:0], exu_flush_final_d1})); | ||||
|    rvdff #(33)  junk_ff (.*, .clk(active_clk), .din({mppc_ns[31:0], exu_flush_final}), .dout({mppc[31:0], exu_flush_final_d1})); | ||||
|    logic  tmp_bnk; | ||||
|    assign tmp_bnk = bp.btb_sel_f[1]; | ||||
|    assign tmp_bnk = bpred.bp.btb_sel_f[1]; | ||||
| 
 | ||||
|    always @(negedge clk) begin | ||||
|       if(`DEC.tlu.mcyclel[31:0] == 32'h0000_0010) begin | ||||
|          $display("BTB_CONFIG: %d",pt.BTB_ARRAY_DEPTH*4); | ||||
|          $display("BTB_CONFIG: %d",pt.BTB_SIZE); | ||||
|          `ifndef BP_NOGSHARE | ||||
|          $display("BHT_CONFIG: %d gshare: 1",pt.BHT_ARRAY_DEPTH*4); | ||||
|          $display("BHT_CONFIG: %d gshare: 1",pt.BHT_SIZE); | ||||
|          `else | ||||
|          $display("BHT_CONFIG: %d gshare: 0",pt.BHT_ARRAY_DEPTH*4); | ||||
|          $display("BHT_CONFIG: %d gshare: 0",pt.BHT_SIZE); | ||||
|          `endif | ||||
|          $display("RS_CONFIG: %d", pt.RET_STACK_SIZE); | ||||
|       end | ||||
|        if(exu_flush_final_d1 & ~(dec_tlu_br0_r_pkt.br_error | dec_tlu_br0_r_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[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO], 1'b0, exu_mp_call, exu_mp_ret, exu_mp_ataken, exu_mp_hist[1:0], exu_mp_valid, exu_mp_btag[pt.BTB_BTAG_SIZE-1:0], {exu_flush_path_final[31:1], 1'b0}, exu_mp_eghr[pt.BHT_GHR_SIZE-1:0], exu_mp_valid, bp.bht_wr_addr0, mppc[31:0], exu_mp_pkt.way); | ||||
|          $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[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO], 1'b0, exu_mp_call, exu_mp_ret, exu_mp_ataken, exu_mp_hist[1:0], exu_mp_valid, exu_mp_btag[pt.BTB_BTAG_SIZE-1:0], {exu_flush_path_final[31:1], 1'b0}, exu_mp_eghr[pt.BHT_GHR_SIZE-1:0], exu_mp_valid, bpred.bp.bht_wr_addr0, mppc[31:0], exu_mp_pkt.way); | ||||
| 
 | ||||
|      for(int i = 0; i < 8; i++) begin | ||||
|       if(ifu_bp_valid_f[i] & ifc_fetch_req_f) | ||||
|         $display("%7d BTB_HIT : index: %0h bank: %0h call: %b ret: %b taken: %b strength: %b tag: %h targ: %0h ghr: %4b ghr_index: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,btb_rd_addr_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO],bp.btb_sel_f[1], bp.btb_rd_call_f, bp.btb_rd_ret_f, ifu_bp_hist1_f[tmp_bnk], ifu_bp_hist0_f[tmp_bnk], bp.fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0], {ifu_bp_btb_target_f[31:1], 1'b0}, bp.fghr[pt.BHT_GHR_SIZE-1:0], bp.bht_rd_addr_f, ifu_bp_way_f[tmp_bnk]); | ||||
|         $display("%7d BTB_HIT : index: %0h bank: %0h call: %b ret: %b taken: %b strength: %b tag: %h targ: %0h ghr: %4b ghr_index: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,btb_rd_addr_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO],bpred.bp.btb_sel_f[1], bpred.bp.btb_rd_call_f, bpred.bp.btb_rd_ret_f, ifu_bp_hist1_f[tmp_bnk], ifu_bp_hist0_f[tmp_bnk], bpred.bp.fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0], {ifu_bp_btb_target_f[31:1], 1'b0}, bpred.bp.fghr[pt.BHT_GHR_SIZE-1:0], bpred.bp.bht_rd_addr_f, ifu_bp_way_f[tmp_bnk]); | ||||
|      end | ||||
|       if(dec_tlu_br0_r_pkt.valid & ~(dec_tlu_br0_r_pkt.br_error | dec_tlu_br0_r_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[pt.BHT_ADDR_HI:pt.BHT_ADDR_LO],{dec_tlu_br0_r_pkt.middle}, dec_tlu_br0_r_pkt.hist, dec_tlu_br0_r_pkt.way); | ||||
|         $display("%7d BTB_UPD0: ghr_index: %0h bank: %0h hist: %h  way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,bpred.bp.br0_hashed_wb[pt.BHT_ADDR_HI:pt.BHT_ADDR_LO],{dec_tlu_br0_r_pkt.middle}, dec_tlu_br0_r_pkt.hist, dec_tlu_br0_r_pkt.way); | ||||
| 
 | ||||
|       if(dec_tlu_br0_r_pkt.br_error | dec_tlu_br0_r_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,exu_i0_br_index_r[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO],1'b0, dec_tlu_br0_r_pkt.br_start_error, {exu_flush_path_final[31:1], 1'b0}, dec_tlu_br0_r_pkt.way); | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -25,31 +25,21 @@ import el2_pkg::*; | |||
|  ) | ||||
|   ( | ||||
| 
 | ||||
|    input logic                                    scan_mode, | ||||
|    input logic                                    rst_l, | ||||
|    input logic                                    clk, | ||||
|    input logic                                    active_clk, | ||||
|    input logic                                    scan_mode,                // Flop scan mode control
 | ||||
|    input logic                                    rst_l,                    // reset, active low
 | ||||
|    input logic                                    clk,                      // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic                                    active_clk,               // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
| 
 | ||||
|    input logic                                    ifu_async_error_start,    // ecc/parity related errors with current fetch - not sent down the pipe
 | ||||
| 
 | ||||
|    input logic                                    iccm_rd_ecc_double_err,   // This fetch has a double ICCM ecc  error.
 | ||||
|    input logic [1:0]                              iccm_rd_ecc_double_err,   // This fetch has a double ICCM ecc  error.
 | ||||
| 
 | ||||
|    input logic                                    ic_access_fault_f,        // Instruction access fault for the current fetch.
 | ||||
|    input logic [1:0]                              ic_access_fault_f,        // Instruction access fault for the current fetch.
 | ||||
|    input logic [1:0]                              ic_access_fault_type_f,   // Instruction access fault types
 | ||||
|    input logic [pt.BHT_GHR_SIZE-1:0]              ifu_bp_fghr_f,            // fetch GHR
 | ||||
|    input logic [31:1]                             ifu_bp_btb_target_f,      // predicted RET target
 | ||||
|    input logic [11:0]                             ifu_bp_poffset_f,         // predicted target offset
 | ||||
| 
 | ||||
|    input logic [1:0]                              ifu_bp_hist0_f,           // history counters for all 4 potential branches, bit 1, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_hist1_f,           // history counters for all 4 potential branches, bit 1, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_pc4_f,             // pc4 indication, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_way_f,             // way indication, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_valid_f,           // branch valid, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_ret_f,             // predicted ret indication, right justified
 | ||||
| 
 | ||||
|    input logic                                    exu_flush_final,          // Flush from the pipeline.
 | ||||
| 
 | ||||
|    input logic                                    dec_i0_decode_d, | ||||
|    input logic                                    dec_i0_decode_d,          // Valid instruction at D-stage and not blocked
 | ||||
| 
 | ||||
|    input logic [31:0]                             ifu_fetch_data_f,         // fetch data in memory format - not right justified
 | ||||
| 
 | ||||
|  | @ -61,7 +51,7 @@ import el2_pkg::*; | |||
|    output logic                                   ifu_i0_valid,             // Instruction 0 is valid
 | ||||
|    output logic                                   ifu_i0_icaf,              // Instruction 0 has access fault
 | ||||
|    output logic [1:0]                             ifu_i0_icaf_type,         // Instruction 0 access fault type
 | ||||
|    output logic                                   ifu_i0_icaf_f1,           // Instruction 0 has access fault on second fetch group
 | ||||
|    output logic                                   ifu_i0_icaf_second,       // Instruction 0 has access fault on second 2B of 4B inst
 | ||||
| 
 | ||||
|    output logic                                   ifu_i0_dbecc,             // Instruction 0 has double bit ecc error
 | ||||
|    output logic [31:0]                            ifu_i0_instr,             // Instruction 0
 | ||||
|  | @ -70,10 +60,28 @@ import el2_pkg::*; | |||
| 
 | ||||
|    output logic                                   ifu_fb_consume1,          // Consumed one buffer. To fetch control fetch for buffer mass balance
 | ||||
|    output logic                                   ifu_fb_consume2,          // Consumed two buffers.To fetch control fetch for buffer mass balance
 | ||||
| 
 | ||||
| 
 | ||||
|    input logic [pt.BHT_GHR_SIZE-1:0]              ifu_bp_fghr_f,            // fetch GHR
 | ||||
|    input logic [31:1]                             ifu_bp_btb_target_f,      // predicted RET target
 | ||||
|    input logic [11:0]                             ifu_bp_poffset_f,         // predicted target offset
 | ||||
|    input logic [1:0] [$clog2(pt.BTB_SIZE)-1:0]    ifu_bp_fa_index_f,        // predicted branch index (fully associative option)
 | ||||
| 
 | ||||
|    input logic [1:0]                              ifu_bp_hist0_f,           // history counters for all 4 potential branches, bit 1, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_hist1_f,           // history counters for all 4 potential branches, bit 1, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_pc4_f,             // pc4 indication, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_way_f,             // way indication, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_valid_f,           // branch valid, right justified
 | ||||
|    input logic [1:0]                              ifu_bp_ret_f,             // predicted ret indication, right justified
 | ||||
| 
 | ||||
| 
 | ||||
|    output el2_br_pkt_t                           i0_brp,                   // Branch packet for I0.
 | ||||
|    output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]   ifu_i0_bp_index,          // BP index
 | ||||
|    output logic [pt.BHT_GHR_SIZE-1:0]             ifu_i0_bp_fghr,           // BP FGHR
 | ||||
|    output logic [pt.BTB_BTAG_SIZE-1:0]            ifu_i0_bp_btag,           // BP tag
 | ||||
| 
 | ||||
|    output logic [$clog2(pt.BTB_SIZE)-1:0]         ifu_i0_fa_index,          // Fully associt btb index
 | ||||
| 
 | ||||
|    output logic                                   ifu_pmu_instr_aligned,    // number of inst aligned this cycle
 | ||||
| 
 | ||||
|    output logic [15:0]                            ifu_i0_cinst              // 16b compress inst for i0
 | ||||
|  | @ -90,11 +98,6 @@ import el2_pkg::*; | |||
|    logic [1:0]                                    f0val_in, f0val; | ||||
|    logic [1:0]                                    sf1val, sf0val; | ||||
| 
 | ||||
|    logic [31:1]                                   f2pc_in, f2pc; | ||||
|    logic [31:1]                                   f1pc_in, f1pc; | ||||
|    logic [31:1]                                   f0pc_in, f0pc; | ||||
|    logic [31:1]                                   sf1pc; | ||||
| 
 | ||||
|    logic [31:0]                                   aligndata; | ||||
|    logic                                          first4B, first2B; | ||||
| 
 | ||||
|  | @ -105,8 +108,6 @@ import el2_pkg::*; | |||
|    logic                                          f2_valid, sf1_valid, sf0_valid; | ||||
| 
 | ||||
|    logic [31:0]                                   ifirst; | ||||
|    logic [31:1]                                   f0pc_plus1; | ||||
|    logic [31:1]                                   f1pc_plus1; | ||||
|    logic [1:0]                                    alignval; | ||||
|    logic [31:1]                                   firstpc, secondpc; | ||||
| 
 | ||||
|  | @ -119,6 +120,8 @@ import el2_pkg::*; | |||
|    logic [1:0]                                    f1hist0; | ||||
|    logic [1:0]                                    f0hist0; | ||||
| 
 | ||||
|    logic [1:0][$clog2(pt.BTB_SIZE)-1:0]           f0index, f1index, alignindex; | ||||
| 
 | ||||
|    logic [1:0]                                    f1ictype; | ||||
|    logic [1:0]                                    f0ictype; | ||||
| 
 | ||||
|  | @ -146,10 +149,10 @@ import el2_pkg::*; | |||
| 
 | ||||
|    logic [31:1]                                   f1prett; | ||||
|    logic [31:1]                                   f0prett; | ||||
|    logic                                          f1dbecc; | ||||
|    logic                                          f0dbecc; | ||||
|    logic                                          f1icaf; | ||||
|    logic                                          f0icaf; | ||||
|    logic [1:0]                                    f1dbecc; | ||||
|    logic [1:0]                                    f0dbecc; | ||||
|    logic [1:0]                                    f1icaf; | ||||
|    logic [1:0]                                    f0icaf; | ||||
| 
 | ||||
|    logic [1:0]                                    aligndbecc; | ||||
|    logic [1:0]                                    alignicaf; | ||||
|  | @ -159,10 +162,6 @@ import el2_pkg::*; | |||
| 
 | ||||
|    logic                                          first_legal; | ||||
| 
 | ||||
|    logic                                          f2_wr_en; | ||||
|    logic                                          f0_shift_wr_en; | ||||
|    logic                                          f1_shift_wr_en; | ||||
| 
 | ||||
|    logic [1:0]                                    wrptr, wrptr_in; | ||||
|    logic [1:0]                                    rdptr, rdptr_in; | ||||
|    logic [2:0]                                    qwen; | ||||
|  | @ -185,16 +184,17 @@ import el2_pkg::*; | |||
|    logic [2:0]                                    qren; | ||||
| 
 | ||||
|    logic                                          consume_fb1, consume_fb0; | ||||
|    logic [1:1]                                    icaf_eff; | ||||
|    logic [1:0]                                    icaf_eff; | ||||
| 
 | ||||
|    localparam                                     BRDATA_SIZE  = 12; | ||||
|    localparam                                     BRDATA_WIDTH =  6; | ||||
|    localparam                                     BRDATA_SIZE  = pt.BTB_ENABLE ? 16+($clog2(pt.BTB_SIZE)*2*pt.BTB_FULLYA) : 2; | ||||
|    localparam                                     BRDATA_WIDTH = pt.BTB_ENABLE ? 8+($clog2(pt.BTB_SIZE)*pt.BTB_FULLYA) : 1; | ||||
|    logic [BRDATA_SIZE-1:0]                        brdata_in, brdata2, brdata1, brdata0; | ||||
|    logic [BRDATA_SIZE-1:0]                        brdata1eff, brdata0eff; | ||||
|    logic [BRDATA_SIZE-1:0]                        brdata1final, brdata0final; | ||||
| 
 | ||||
|    localparam                                     MHI   = 46+pt.BHT_GHR_SIZE; | ||||
|    localparam                                     MSIZE = 47+pt.BHT_GHR_SIZE; | ||||
|    localparam                                     MHI   = 1+(pt.BTB_ENABLE * (43+pt.BHT_GHR_SIZE)); | ||||
|    localparam                                     MSIZE = 2+(pt.BTB_ENABLE * (43+pt.BHT_GHR_SIZE)); | ||||
| 
 | ||||
|    logic [MHI:0]                                  misc_data_in, misc2, misc1, misc0; | ||||
|    logic [MHI:0]                                  misc1eff, misc0eff; | ||||
| 
 | ||||
|  | @ -204,40 +204,45 @@ import el2_pkg::*; | |||
| 
 | ||||
|    assign error_stall_in = (error_stall | ifu_async_error_start) & ~exu_flush_final; | ||||
| 
 | ||||
|    rvdff  #(1)            error_stallff   (.*, .clk(active_clk),    .din(error_stall_in),         .dout(error_stall)); | ||||
|    rvdff #(.WIDTH(7))  bundle1ff (.*, | ||||
|                                   .clk(active_clk), | ||||
|                                   .din ({wrptr_in[1:0],rdptr_in[1:0],q2off_in,q1off_in,q0off_in}), | ||||
|                                   .dout({wrptr[1:0],   rdptr[1:0],   q2off,   q1off,   q0off}) | ||||
|                                   ); | ||||
| 
 | ||||
|    rvdff  #(2)            wrpff       (.*, .clk(active_clk),    .din(wrptr_in[1:0]),              .dout(wrptr[1:0])); | ||||
|    rvdff  #(2)            rdpff       (.*, .clk(active_clk),    .din(rdptr_in[1:0]),              .dout(rdptr[1:0])); | ||||
|    rvdffie #(.WIDTH(7),.OVERRIDE(1))  bundle2ff (.*, | ||||
|                                                  .din ({error_stall_in,f2val_in[1:0],f1val_in[1:0],f0val_in[1:0]}), | ||||
|                                                  .dout({error_stall,   f2val[1:0],   f1val[1:0],   f0val[1:0]   }) | ||||
|                                                  ); | ||||
| 
 | ||||
|    rvdff  #(2)            f2valff     (.*, .clk(active_clk),    .din(f2val_in[1:0]),              .dout(f2val[1:0])); | ||||
|    rvdff  #(2)            f1valff     (.*, .clk(active_clk),    .din(f1val_in[1:0]),              .dout(f1val[1:0])); | ||||
|    rvdff  #(2)            f0valff     (.*, .clk(active_clk),    .din(f0val_in[1:0]),              .dout(f0val[1:0])); | ||||
| if(pt.BTB_ENABLE==1) begin | ||||
|    rvdffe #(BRDATA_SIZE)  brdata2ff   (.*, .clk(clk), .en(qwen[2]),        .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata2[BRDATA_SIZE-1:0])); | ||||
|    rvdffe #(BRDATA_SIZE)  brdata1ff   (.*, .clk(clk), .en(qwen[1]),        .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata1[BRDATA_SIZE-1:0])); | ||||
|    rvdffe #(BRDATA_SIZE)  brdata0ff   (.*, .clk(clk), .en(qwen[0]),        .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata0[BRDATA_SIZE-1:0])); | ||||
|    rvdffe #(MSIZE)        misc2ff     (.*, .clk(clk), .en(qwen[2]),        .din(misc_data_in[MHI:0]),        .dout(misc2[MHI:0])); | ||||
|    rvdffe #(MSIZE)        misc1ff     (.*, .clk(clk), .en(qwen[1]),        .din(misc_data_in[MHI:0]),        .dout(misc1[MHI:0])); | ||||
|    rvdffe #(MSIZE)        misc0ff     (.*, .clk(clk), .en(qwen[0]),        .din(misc_data_in[MHI:0]),        .dout(misc0[MHI:0])); | ||||
| end | ||||
| else begin | ||||
| 
 | ||||
|    rvdff  #(1)            q2offsetff  (.*, .clk(active_clk),    .din(q2off_in),                   .dout(q2off)); | ||||
|    rvdff  #(1)            q1offsetff  (.*, .clk(active_clk),    .din(q1off_in),                   .dout(q1off)); | ||||
|    rvdff  #(1)            q0offsetff  (.*, .clk(active_clk),    .din(q0off_in),                   .dout(q0off)); | ||||
|    rvdffe #(31)           f2pcff      (.*, .en(f2_wr_en),       .din(f2pc_in[31:1]),              .dout(f2pc[31:1])); | ||||
|    rvdffe #(31)           f1pcff      (.*, .en(f1_shift_wr_en), .din(f1pc_in[31:1]),              .dout(f1pc[31:1])); | ||||
|    rvdffe #(31)           f0pcff      (.*, .en(f0_shift_wr_en), .din(f0pc_in[31:1]),              .dout(f0pc[31:1])); | ||||
|    rvdffe #(BRDATA_SIZE)  brdata2ff   (.*, .en(qwen[2]),        .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata2[BRDATA_SIZE-1:0])); | ||||
|    rvdffe #(BRDATA_SIZE)  brdata1ff   (.*, .en(qwen[1]),        .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata1[BRDATA_SIZE-1:0])); | ||||
|    rvdffe #(BRDATA_SIZE)  brdata0ff   (.*, .en(qwen[0]),        .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata0[BRDATA_SIZE-1:0])); | ||||
|    rvdffe #(MSIZE)        misc2ff     (.*, .en(qwen[2]),        .din(misc_data_in[MHI:0]),        .dout(misc2[MHI:0])); | ||||
|    rvdffe #(MSIZE)        misc1ff     (.*, .en(qwen[1]),        .din(misc_data_in[MHI:0]),        .dout(misc1[MHI:0])); | ||||
|    rvdffe #(MSIZE)        misc0ff     (.*, .en(qwen[0]),        .din(misc_data_in[MHI:0]),        .dout(misc0[MHI:0])); | ||||
|    rvdffie #((MSIZE*3)+(BRDATA_SIZE*3))    miscff      (.*, | ||||
|                                                         .din({qwen[2] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc2[MHI:0], brdata2[BRDATA_SIZE-1:0]}, | ||||
|                                                               qwen[1] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc1[MHI:0], brdata1[BRDATA_SIZE-1:0]}, | ||||
|                                                               qwen[0] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc0[MHI:0], brdata0[BRDATA_SIZE-1:0]}}), | ||||
|                                                         .dout({misc2[MHI:0],misc1[MHI:0],misc0[MHI:0], | ||||
|                                                                brdata2[BRDATA_SIZE-1:0], brdata1[BRDATA_SIZE-1:0], brdata0[BRDATA_SIZE-1:0]}) | ||||
|                                                         ); | ||||
| end | ||||
| 
 | ||||
|    rvdffe #(32)           q2ff        (.*, .en(qwen[2]),        .din(ifu_fetch_data_f[31:0]),     .dout(q2[31:0])); | ||||
|    rvdffe #(32)           q1ff        (.*, .en(qwen[1]),        .din(ifu_fetch_data_f[31:0]),     .dout(q1[31:0])); | ||||
|    rvdffe #(32)           q0ff        (.*, .en(qwen[0]),        .din(ifu_fetch_data_f[31:0]),     .dout(q0[31:0])); | ||||
|   logic [31:1] q2pc, q1pc, q0pc; | ||||
| 
 | ||||
|    rvdffe #(31)           q2pcff        (.*, .clk(clk), .en(qwen[2]),        .din(ifu_fetch_pc[31:1]),     .dout(q2pc[31:1])); | ||||
|    rvdffe #(31)           q1pcff        (.*, .clk(clk), .en(qwen[1]),        .din(ifu_fetch_pc[31:1]),     .dout(q1pc[31:1])); | ||||
|    rvdffe #(31)           q0pcff        (.*, .clk(clk), .en(qwen[0]),        .din(ifu_fetch_pc[31:1]),     .dout(q0pc[31:1])); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign f2_wr_en           =  fetch_to_f2; | ||||
|    assign f1_shift_wr_en     =  fetch_to_f1 | shift_f2_f1 | f1_shift_2B; | ||||
|    assign f0_shift_wr_en     =  fetch_to_f0 | shift_f2_f0 | shift_f1_f0 | shift_2B | shift_4B; | ||||
| 
 | ||||
|    rvdffe #(32)           q2ff        (.*, .clk(clk), .en(qwen[2]),        .din(ifu_fetch_data_f[31:0]),     .dout(q2[31:0])); | ||||
|    rvdffe #(32)           q1ff        (.*, .clk(clk), .en(qwen[1]),        .din(ifu_fetch_data_f[31:0]),     .dout(q1[31:0])); | ||||
|    rvdffe #(32)           q0ff        (.*, .clk(clk), .en(qwen[0]),        .din(ifu_fetch_data_f[31:0]),     .dout(q0[31:0])); | ||||
| 
 | ||||
| 
 | ||||
|    // new queue control logic
 | ||||
|  | @ -297,40 +302,64 @@ import el2_pkg::*; | |||
| 
 | ||||
|    // misc data that is associated with each fetch buffer
 | ||||
| 
 | ||||
|    assign misc_data_in[MHI:0] = { iccm_rd_ecc_double_err, | ||||
|                                   ic_access_fault_f, | ||||
|                                   ic_access_fault_type_f[1:0], | ||||
|                                   ifu_bp_btb_target_f[31:1], | ||||
|                                   ifu_bp_poffset_f[11:0], | ||||
|                                   ifu_bp_fghr_f[pt.BHT_GHR_SIZE-1:0] | ||||
|                                   }; | ||||
|    if(pt.BTB_ENABLE==1) | ||||
|      assign misc_data_in[MHI:0] = { | ||||
| 
 | ||||
|                                     ic_access_fault_type_f[1:0], | ||||
|                                     ifu_bp_btb_target_f[31:1], | ||||
|                                     ifu_bp_poffset_f[11:0], | ||||
|                                     ifu_bp_fghr_f[pt.BHT_GHR_SIZE-1:0] | ||||
|                                     }; | ||||
|    else | ||||
|      assign misc_data_in[MHI:0] = { | ||||
|                                     ic_access_fault_type_f[1:0] | ||||
|                                     }; | ||||
| 
 | ||||
| 
 | ||||
|    assign {misc1eff[MHI:0],misc0eff[MHI:0]} = (({MSIZE*2{qren[0]}} & {misc1[MHI:0],misc0[MHI:0]}) | | ||||
|                                                ({MSIZE*2{qren[1]}} & {misc2[MHI:0],misc1[MHI:0]}) | | ||||
|                                                ({MSIZE*2{qren[2]}} & {misc0[MHI:0],misc2[MHI:0]})); | ||||
| 
 | ||||
|    assign { f1dbecc, | ||||
|             f1icaf, | ||||
|    if(pt.BTB_ENABLE==1) begin | ||||
|    assign { | ||||
|             f1ictype[1:0], | ||||
|             f1prett[31:1], | ||||
|             f1poffset[11:0], | ||||
|             f1fghr[pt.BHT_GHR_SIZE-1:0] | ||||
|             } = misc1eff[MHI:0]; | ||||
| 
 | ||||
|    assign { f0dbecc, | ||||
|             f0icaf, | ||||
|    assign { | ||||
|             f0ictype[1:0], | ||||
|             f0prett[31:1], | ||||
|             f0poffset[11:0], | ||||
|             f0fghr[pt.BHT_GHR_SIZE-1:0] | ||||
|             } = misc0eff[MHI:0]; | ||||
| 
 | ||||
|       if(pt.BTB_FULLYA) begin | ||||
|          assign brdata_in[BRDATA_SIZE-1:0] = { | ||||
|                                                ifu_bp_fa_index_f[1], iccm_rd_ecc_double_err[1],ic_access_fault_f[1],ifu_bp_hist1_f[1],ifu_bp_hist0_f[1],ifu_bp_pc4_f[1],ifu_bp_way_f[1],ifu_bp_valid_f[1],ifu_bp_ret_f[1], | ||||
|                                                ifu_bp_fa_index_f[0], iccm_rd_ecc_double_err[0],ic_access_fault_f[0],ifu_bp_hist1_f[0],ifu_bp_hist0_f[0],ifu_bp_pc4_f[0],ifu_bp_way_f[0],ifu_bp_valid_f[0],ifu_bp_ret_f[0] | ||||
|                                                }; | ||||
|          assign {f0index[1],f0dbecc[1],f0icaf[1],f0hist1[1],f0hist0[1],f0pc4[1],f0way[1],f0brend[1],f0ret[1], | ||||
|                  f0index[0],f0dbecc[0],f0icaf[0],f0hist1[0],f0hist0[0],f0pc4[0],f0way[0],f0brend[0],f0ret[0]} = brdata0final[BRDATA_SIZE-1:0]; | ||||
| 
 | ||||
|          assign {f1index[1],f1dbecc[1],f1icaf[1],f1hist1[1],f1hist0[1],f1pc4[1],f1way[1],f1brend[1],f1ret[1], | ||||
|                  f1index[0],f1dbecc[0],f1icaf[0],f1hist1[0],f1hist0[0],f1pc4[0],f1way[0],f1brend[0],f1ret[0]} = brdata1final[BRDATA_SIZE-1:0]; | ||||
| 
 | ||||
|       end | ||||
|       else begin | ||||
|          assign brdata_in[BRDATA_SIZE-1:0] = { | ||||
|                                                iccm_rd_ecc_double_err[1],ic_access_fault_f[1],ifu_bp_hist1_f[1],ifu_bp_hist0_f[1],ifu_bp_pc4_f[1],ifu_bp_way_f[1],ifu_bp_valid_f[1],ifu_bp_ret_f[1], | ||||
|                                                iccm_rd_ecc_double_err[0],ic_access_fault_f[0],ifu_bp_hist1_f[0],ifu_bp_hist0_f[0],ifu_bp_pc4_f[0],ifu_bp_way_f[0],ifu_bp_valid_f[0],ifu_bp_ret_f[0] | ||||
|                                                }; | ||||
|          assign {f0dbecc[1],f0icaf[1],f0hist1[1],f0hist0[1],f0pc4[1],f0way[1],f0brend[1],f0ret[1], | ||||
|                  f0dbecc[0],f0icaf[0],f0hist1[0],f0hist0[0],f0pc4[0],f0way[0],f0brend[0],f0ret[0]} = brdata0final[BRDATA_SIZE-1:0]; | ||||
| 
 | ||||
|          assign {f1dbecc[1],f1icaf[1],f1hist1[1],f1hist0[1],f1pc4[1],f1way[1],f1brend[1],f1ret[1], | ||||
|                  f1dbecc[0],f1icaf[0],f1hist1[0],f1hist0[0],f1pc4[0],f1way[0],f1brend[0],f1ret[0]} = brdata1final[BRDATA_SIZE-1:0]; | ||||
| 
 | ||||
|       end | ||||
| 
 | ||||
|    assign brdata_in[BRDATA_SIZE-1:0] = { | ||||
|                               ifu_bp_hist1_f[1],ifu_bp_hist0_f[1],ifu_bp_pc4_f[1],ifu_bp_way_f[1],ifu_bp_valid_f[1],ifu_bp_ret_f[1], | ||||
|                               ifu_bp_hist1_f[0],ifu_bp_hist0_f[0],ifu_bp_pc4_f[0],ifu_bp_way_f[0],ifu_bp_valid_f[0],ifu_bp_ret_f[0] | ||||
|                               }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -344,11 +373,37 @@ import el2_pkg::*; | |||
|    assign brdata1final[BRDATA_SIZE-1:0] = (({BRDATA_SIZE{q1sel[0]}} & {                     brdata1eff[2*BRDATA_WIDTH-1:0]}) | | ||||
|                                            ({BRDATA_SIZE{q1sel[1]}} & {{BRDATA_WIDTH{1'b0}},brdata1eff[BRDATA_SIZE-1:BRDATA_WIDTH]})); | ||||
| 
 | ||||
|    assign {f0hist1[1],f0hist0[1],f0pc4[1],f0way[1],f0brend[1],f0ret[1], | ||||
|            f0hist1[0],f0hist0[0],f0pc4[0],f0way[0],f0brend[0],f0ret[0]} = brdata0final[BRDATA_SIZE-1:0]; | ||||
|    end // if (pt.BTB_ENABLE==1)
 | ||||
|    else begin | ||||
|       assign { | ||||
|                f1ictype[1:0] | ||||
|                } = misc1eff[MHI:0]; | ||||
| 
 | ||||
|    assign {f1hist1[1],f1hist0[1],f1pc4[1],f1way[1],f1brend[1],f1ret[1], | ||||
|            f1hist1[0],f1hist0[0],f1pc4[0],f1way[0],f1brend[0],f1ret[0]} = brdata1final[BRDATA_SIZE-1:0]; | ||||
|       assign { | ||||
|                f0ictype[1:0] | ||||
|                } = misc0eff[MHI:0]; | ||||
| 
 | ||||
|       assign brdata_in[BRDATA_SIZE-1:0] = { | ||||
|                                             iccm_rd_ecc_double_err[1],ic_access_fault_f[1], | ||||
|                                             iccm_rd_ecc_double_err[0],ic_access_fault_f[0] | ||||
|                                             }; | ||||
|       assign {f0dbecc[1],f0icaf[1], | ||||
|               f0dbecc[0],f0icaf[0]} = brdata0final[BRDATA_SIZE-1:0]; | ||||
| 
 | ||||
|       assign {f1dbecc[1],f1icaf[1], | ||||
|               f1dbecc[0],f1icaf[0]} = brdata1final[BRDATA_SIZE-1:0]; | ||||
| 
 | ||||
|       assign {brdata1eff[BRDATA_SIZE-1:0],brdata0eff[BRDATA_SIZE-1:0]} = (({BRDATA_SIZE*2{qren[0]}} & {brdata1[BRDATA_SIZE-1:0],brdata0[BRDATA_SIZE-1:0]}) | | ||||
|                                                                           ({BRDATA_SIZE*2{qren[1]}} & {brdata2[BRDATA_SIZE-1:0],brdata1[BRDATA_SIZE-1:0]}) | | ||||
|                                                                        ({BRDATA_SIZE*2{qren[2]}} & {brdata0[BRDATA_SIZE-1:0],brdata2[BRDATA_SIZE-1:0]})); | ||||
| 
 | ||||
|       assign brdata0final[BRDATA_SIZE-1:0] = (({BRDATA_SIZE{q0sel[0]}} & {                     brdata0eff[2*BRDATA_WIDTH-1:0]}) | | ||||
|                                               ({BRDATA_SIZE{q0sel[1]}} & {{BRDATA_WIDTH{1'b0}},brdata0eff[BRDATA_SIZE-1:BRDATA_WIDTH]})); | ||||
| 
 | ||||
|       assign brdata1final[BRDATA_SIZE-1:0] = (({BRDATA_SIZE{q1sel[0]}} & {                     brdata1eff[2*BRDATA_WIDTH-1:0]}) | | ||||
|                                               ({BRDATA_SIZE{q1sel[1]}} & {{BRDATA_WIDTH{1'b0}},brdata1eff[BRDATA_SIZE-1:BRDATA_WIDTH]})); | ||||
| 
 | ||||
|    end // else: !if(pt.BTB_ENABLE==1)
 | ||||
| 
 | ||||
| 
 | ||||
|    // possible states of { sf0_valid, sf1_valid, f2_valid }
 | ||||
|  | @ -391,28 +446,6 @@ import el2_pkg::*; | |||
|                                ( sf0_valid &  sf1_valid & ~f2_valid & ifvalid); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign f0pc_plus1[31:1]   =  f0pc[31:1] + 31'd1; | ||||
|    assign f1pc_plus1[31:1]   =  f1pc[31:1] + 31'd1; | ||||
| 
 | ||||
|    assign f2pc_in[31:1]      =  ifu_fetch_pc[31:1]; | ||||
| 
 | ||||
| 
 | ||||
|    assign sf1pc[31:1]        = ({31{ f1_shift_2B}} & f1pc_plus1[31:1]) | | ||||
|                                ({31{~f1_shift_2B}} & f1pc[31:1]      ); | ||||
| 
 | ||||
|    assign f1pc_in[31:1]      = ({31{ fetch_to_f1               }} & ifu_fetch_pc[31:1]) | | ||||
|                                ({31{                shift_f2_f1}} & f2pc[31:1]        ) | | ||||
|                                ({31{~fetch_to_f1 & ~shift_f2_f1}} & sf1pc[31:1]       ); | ||||
| 
 | ||||
| 
 | ||||
|    assign f0pc_in[31:1]      = ({31{ fetch_to_f0                              }} & ifu_fetch_pc[31:1]) | | ||||
|                                ({31{                shift_f2_f0               }} & f2pc[31:1]        ) | | ||||
|                                ({31{                               shift_f1_f0}} & sf1pc[31:1]       ) | | ||||
|                                ({31{~fetch_to_f0 & ~shift_f2_f0 & ~shift_f1_f0}} & f0pc_plus1[31:1]  ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign f2val_in[1:0]      = ({2{ fetch_to_f2 &                               ~exu_flush_final}} & ifu_fetch_val[1:0]) | | ||||
|                                ({2{~fetch_to_f2 & ~shift_f2_f1 & ~shift_f2_f0 & ~exu_flush_final}} & f2val[1:0]        ); | ||||
| 
 | ||||
|  | @ -434,11 +467,6 @@ import el2_pkg::*; | |||
|                                ({2{                               shift_f1_f0 & ~exu_flush_final}} & sf1val[1:0]       ) | | ||||
|                                ({2{~fetch_to_f0 & ~shift_f2_f0 & ~shift_f1_f0 & ~exu_flush_final}} & sf0val[1:0]       ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign {q1eff[31:0],q0eff[31:0]} = (({64{qren[0]}} & {q1[31:0],q0[31:0]}) | | ||||
|                                        ({64{qren[1]}} & {q2[31:0],q1[31:0]}) | | ||||
|                                        ({64{qren[2]}} & {q0[31:0],q2[31:0]})); | ||||
|  | @ -448,6 +476,16 @@ import el2_pkg::*; | |||
| 
 | ||||
|    assign q1final[15:0]      = ({16{q1sel[0]}} & q1eff[15:0] ) | | ||||
|                                ({16{q1sel[1]}} & q1eff[31:16]); | ||||
|    logic [31:1] q0pceff, q0pcfinal; | ||||
|    logic [31:1] q1pceff; | ||||
| 
 | ||||
|    assign {q1pceff[31:1],q0pceff[31:1]} = (({62{qren[0]}} & {q1pc[31:1],q0pc[31:1]}) | | ||||
|                                            ({62{qren[1]}} & {q2pc[31:1],q1pc[31:1]}) | | ||||
|                                            ({62{qren[2]}} & {q0pc[31:1],q2pc[31:1]})); | ||||
| 
 | ||||
| 
 | ||||
|    assign q0pcfinal[31:1]      = ({31{q0sel[0]}} & ( q0pceff[31:1])) | | ||||
|                                  ({31{q0sel[1]}} & ( q0pceff[31:1] + 31'd1)); | ||||
| 
 | ||||
|    assign aligndata[31:0]    = ({32{ f0val[1]           }} & {q0final[31:0]}) | | ||||
|                                ({32{~f0val[1] & f0val[0]}} & {q1final[15:0],q0final[15:0]}); | ||||
|  | @ -455,19 +493,26 @@ import el2_pkg::*; | |||
|    assign alignval[1:0]      = ({ 2{ f0val[1]           }} & {2'b11}) | | ||||
|                                ({ 2{~f0val[1] & f0val[0]}} & {f1val[0],1'b1}); | ||||
| 
 | ||||
|    assign alignicaf[1:0]     = ({ 2{ f0val[1]           }} & {{2{f0icaf}}}) | | ||||
|                                ({ 2{~f0val[1] & f0val[0]}} & {f1icaf,f0icaf}); | ||||
|    assign alignicaf[1:0]    = ({ 2{ f0val[1]           }} &  f0icaf[1:0]          ) | | ||||
|                               ({ 2{~f0val[1] & f0val[0]}} & {f1icaf[0],f0icaf[0]}); | ||||
| 
 | ||||
|    assign aligndbecc[1:0]    = ({ 2{ f0val[1]           }} & {{2{f0dbecc}}}) | | ||||
|                                ({ 2{~f0val[1] & f0val[0]}} & {f1dbecc,f0dbecc}); | ||||
|    assign aligndbecc[1:0]    = ({ 2{ f0val[1]           }} &  f0dbecc[1:0]          ) | | ||||
|                               ({ 2{~f0val[1] & f0val[0]}} & {f1dbecc[0],f0dbecc[0]}); | ||||
| 
 | ||||
|    if (pt.BTB_ENABLE==1) begin | ||||
| 
 | ||||
|    // for branch prediction
 | ||||
| 
 | ||||
|    assign alignbrend[1:0]    = ({ 2{ f0val[1]           }} &  f0brend[1:0]          ) | | ||||
|                                ({ 2{~f0val[1] & f0val[0]}} & {f1brend[0],f0brend[0]}); | ||||
| 
 | ||||
|    assign alignpc4[1:0]      = ({ 2{ f0val[1]           }} &  f0pc4[1:0]        ) | | ||||
|                                ({ 2{~f0val[1] & f0val[0]}} & {f1pc4[0],f0pc4[0]}); | ||||
| 
 | ||||
|       if(pt.BTB_FULLYA) begin | ||||
|          assign alignindex[0]      = f0index[0]; | ||||
|          assign alignindex[1]      = f0val[1] ? f0index[1] : f1index[0]; | ||||
|       end | ||||
| 
 | ||||
|    assign alignret[1:0]      = ({ 2{ f0val[1]           }} &  f0ret[1:0]        ) | | ||||
|                                ({ 2{~f0val[1] & f0val[0]}} & {f1ret[0],f0ret[0]}); | ||||
|  | @ -481,20 +526,23 @@ import el2_pkg::*; | |||
|    assign alignhist0[1:0]    = ({ 2{ f0val[1]           }} &  f0hist0[1:0]          ) | | ||||
|                                ({ 2{~f0val[1] & f0val[0]}} & {f1hist0[0],f0hist0[0]}); | ||||
| 
 | ||||
|    assign secondpc[31:1]     = ({31{ f0val[1]           }} &  (q0pceff[31:1] + 31'd1)) | | ||||
|                                // you need the base pc for 2nd one only (4B max, 2B for the 1st and 2B for the 2nd)
 | ||||
|                                ({31{~f0val[1] & f0val[0]}} &   q1pceff[31:1]      ); | ||||
| 
 | ||||
| 
 | ||||
|    assign firstpc[31:1]      =  q0pcfinal[31:1]; | ||||
|       end // if (pt.BTB_ENABLE==1)
 | ||||
| 
 | ||||
|    assign alignfromf1[1]     =      ~f0val[1] & f0val[0]; | ||||
| 
 | ||||
|    assign secondpc[31:1]     = ({31{ f0val[1]           }} &  f0pc_plus1[31:1]) | | ||||
|                                ({31{~f0val[1] & f0val[0]}} &  f1pc[31:1]      ); | ||||
| 
 | ||||
|    assign ifu_i0_pc[31:1]    =  q0pcfinal[31:1]; | ||||
| 
 | ||||
|    assign ifu_i0_pc[31:1]    =  f0pc[31:1]; | ||||
| 
 | ||||
|    assign firstpc[31:1]      =  f0pc[31:1]; | ||||
| 
 | ||||
|    assign ifu_i0_pc4         =  first4B; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign ifu_i0_cinst[15:0] = aligndata[15:0]; | ||||
| 
 | ||||
|    assign first4B            = (aligndata[1:0] == 2'b11); | ||||
|  | @ -510,9 +558,9 @@ import el2_pkg::*; | |||
|    assign ifu_i0_icaf_type[1:0] = (first4B & ~f0val[1] & f0val[0] & ~alignicaf[0] & ~aligndbecc[0]) ? f1ictype[1:0] : f0ictype[1:0]; | ||||
| 
 | ||||
| 
 | ||||
|    assign icaf_eff[1]        =  alignicaf[1] | aligndbecc[1]; | ||||
|    assign icaf_eff[1:0] = alignicaf[1:0] | aligndbecc[1:0]; | ||||
| 
 | ||||
|    assign ifu_i0_icaf_f1     =  first4B & icaf_eff[1] & alignfromf1[1]; | ||||
|    assign ifu_i0_icaf_second = first4B & ~icaf_eff[0] & icaf_eff[1]; | ||||
| 
 | ||||
|    assign ifu_i0_dbecc       = (first4B & (|aligndbecc[1:0])) | | ||||
|                                (first2B &   aligndbecc[0]   ); | ||||
|  | @ -521,23 +569,38 @@ import el2_pkg::*; | |||
|    assign ifirst[31:0]       =  aligndata[31:0]; | ||||
| 
 | ||||
| 
 | ||||
|    assign ifu_i0_instr[31:0] = ({32{first4B}} & ifirst[31:0]) | | ||||
|                                ({32{first2B}} & uncompress0[31:0]); | ||||
|    assign ifu_i0_instr[31:0] = ({32{first4B & alignval[1]}} & ifirst[31:0]) | | ||||
|                                ({32{first2B & alignval[0]}} & uncompress0[31:0]); | ||||
| 
 | ||||
| if(pt.BTB_ENABLE==1) begin | ||||
| 
 | ||||
|    // if you detect br does not start on instruction boundary
 | ||||
| 
 | ||||
|    el2_btb_addr_hash #(.pt(pt)) firsthash (.pc(firstpc [pt.BTB_INDEX3_HI:pt.BTB_INDEX1_LO]), .hash(firstpc_hash [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO])); | ||||
|    el2_btb_addr_hash #(.pt(pt)) secondhash(.pc(secondpc[pt.BTB_INDEX3_HI:pt.BTB_INDEX1_LO]), .hash(secondpc_hash[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO])); | ||||
|    el2_btb_addr_hash #(.pt(pt)) firsthash (.pc(firstpc [pt.BTB_INDEX3_HI:pt.BTB_INDEX1_LO]), | ||||
|                                             .hash(firstpc_hash [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO])); | ||||
|    el2_btb_addr_hash #(.pt(pt)) secondhash(.pc(secondpc[pt.BTB_INDEX3_HI:pt.BTB_INDEX1_LO]), | ||||
|                                             .hash(secondpc_hash[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO])); | ||||
| 
 | ||||
|    if(pt.BTB_FULLYA) begin | ||||
|       assign firstbrtag_hash = firstpc; | ||||
|       assign secondbrtag_hash = secondpc; | ||||
|    end | ||||
|    else begin | ||||
|       if(pt.BTB_BTAG_FOLD) begin : btbfold | ||||
|          el2_btb_tag_hash_fold #(.pt(pt)) first_brhash (.pc(firstpc [pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), | ||||
|                                                          .hash(firstbrtag_hash [pt.BTB_BTAG_SIZE-1:0])); | ||||
|          el2_btb_tag_hash_fold #(.pt(pt)) second_brhash(.pc(secondpc[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), | ||||
|                                                          .hash(secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0])); | ||||
|       end | ||||
|       else begin | ||||
|          el2_btb_tag_hash #(.pt(pt)) first_brhash (.pc(firstpc [pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), | ||||
|                                                     .hash(firstbrtag_hash [pt.BTB_BTAG_SIZE-1:0])); | ||||
|          el2_btb_tag_hash #(.pt(pt)) second_brhash(.pc(secondpc[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), | ||||
|                                                     .hash(secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0])); | ||||
|       end | ||||
|    end // else: !if(pt.BTB_FULLYA)
 | ||||
| 
 | ||||
| 
 | ||||
| if(pt.BTB_BTAG_FOLD) begin : btbfold | ||||
|    el2_btb_tag_hash_fold #(.pt(pt)) first_brhash (.pc(firstpc [pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), .hash(firstbrtag_hash [pt.BTB_BTAG_SIZE-1:0])); | ||||
|    el2_btb_tag_hash_fold #(.pt(pt)) second_brhash(.pc(secondpc[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), .hash(secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0])); | ||||
| end | ||||
| else begin | ||||
|    el2_btb_tag_hash #(.pt(pt)) first_brhash (.pc(firstpc [pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), .hash(firstbrtag_hash [pt.BTB_BTAG_SIZE-1:0])); | ||||
|    el2_btb_tag_hash #(.pt(pt)) second_brhash(.pc(secondpc[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), .hash(secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0])); | ||||
| end | ||||
|    // start_indexing - you want pc to be based on where the end of branch is prediction
 | ||||
|    // normal indexing pc based that's incorrect now for pc4 cases it's pc4 + 2
 | ||||
| 
 | ||||
|  | @ -578,7 +641,12 @@ end | |||
|       i0_brp.br_error        = (i0_brp.valid &  i0_brp_pc4 &  first2B) | | ||||
|                                (i0_brp.valid & ~i0_brp_pc4 &  first4B); | ||||
| 
 | ||||
|    end | ||||
|       if(pt.BTB_FULLYA) | ||||
|         ifu_i0_fa_index = (first2B | alignbrend[0])  ?  alignindex[0]  :  alignindex[1]; | ||||
|       else | ||||
|         ifu_i0_fa_index = '0; | ||||
| 
 | ||||
|  end | ||||
| 
 | ||||
| 
 | ||||
|    assign ifu_i0_bp_index[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] = (first2B | alignbrend[0])  ?  firstpc_hash[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]  : | ||||
|  | @ -589,11 +657,18 @@ end | |||
| 
 | ||||
|    assign ifu_i0_bp_btag[pt.BTB_BTAG_SIZE-1:0]           = (first2B | alignbrend[0])  ?  firstbrtag_hash[pt.BTB_BTAG_SIZE-1:0]  : | ||||
|                                                                                          secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0]; | ||||
| 
 | ||||
| end | ||||
| else begin | ||||
|    assign i0_brp = '0; | ||||
|    assign ifu_i0_bp_index = '0; | ||||
|    assign ifu_i0_bp_fghr = '0; | ||||
|    assign ifu_i0_bp_btag = '0; | ||||
| end // else: !if(pt.BTB_ENABLE==1)
 | ||||
| 
 | ||||
|    // decompress
 | ||||
| 
 | ||||
|    el2_ifu_compress_ctl compress0 (.din(aligndata[15:0]), .dout(uncompress0[31:0])); | ||||
|    // quiet inputs for 4B inst
 | ||||
|    el2_ifu_compress_ctl compress0 (.din((first2B) ? aligndata[15:0] : '0), .dout(uncompress0[31:0])); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -604,8 +679,6 @@ end | |||
| 
 | ||||
|    // compute how many bytes are being shifted from f0
 | ||||
| 
 | ||||
|    // assign shift_0B        = ~i0_shift;
 | ||||
| 
 | ||||
|    assign shift_2B           =  i0_shift & first2B; | ||||
| 
 | ||||
|    assign shift_4B           =  i0_shift & first4B; | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -32,7 +32,6 @@ import el2_pkg::*; | |||
|   ( | ||||
| 
 | ||||
|    input logic clk, | ||||
|    input logic active_clk, | ||||
|    input logic rst_l, | ||||
| 
 | ||||
|    input logic ic_hit_f,      // Icache hit, enables F address capture
 | ||||
|  | @ -44,6 +43,8 @@ import el2_pkg::*; | |||
|    input logic [pt.BHT_GHR_SIZE-1:0] exu_i0_br_fghr_r, // fghr to bp
 | ||||
|    input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] exu_i0_br_index_r, // bp index
 | ||||
| 
 | ||||
|    input logic [$clog2(pt.BTB_SIZE)-1:0] dec_fa_error_index, // Fully associative btb error index
 | ||||
| 
 | ||||
|    input logic dec_tlu_flush_lower_wb, // used to move EX4 RS to EX1 and F
 | ||||
|    input logic dec_tlu_flush_leak_one_wb, // don't hit for leak one fetches
 | ||||
| 
 | ||||
|  | @ -72,10 +73,21 @@ import el2_pkg::*; | |||
|    output logic [1:0] ifu_bp_valid_f, // branch valid, right justified
 | ||||
|    output logic [11:0] ifu_bp_poffset_f, // predicted target
 | ||||
| 
 | ||||
|    output logic [1:0] [$clog2(pt.BTB_SIZE)-1:0]    ifu_bp_fa_index_f, // predicted branch index (fully associative option)
 | ||||
| 
 | ||||
|    input  logic       scan_mode | ||||
|    ); | ||||
| 
 | ||||
|    localparam TAG_START=16+pt.BTB_BTAG_SIZE; | ||||
| 
 | ||||
|    localparam BTB_DWIDTH =  pt.BTB_TOFFSET_SIZE+pt.BTB_BTAG_SIZE+5; | ||||
|    localparam BTB_DWIDTH_TOP =  int'(pt.BTB_TOFFSET_SIZE)+int'(pt.BTB_BTAG_SIZE)+4; | ||||
|    localparam BTB_FA_INDEX = $clog2(pt.BTB_SIZE)-1; | ||||
|    localparam FA_CMP_LOWER = $clog2(pt.ICACHE_LN_SZ); | ||||
|    localparam FA_TAG_END_UPPER= 5+int'(pt.BTB_TOFFSET_SIZE)+int'(FA_CMP_LOWER)-1; // must cast to int or vcs build fails
 | ||||
|    localparam FA_TAG_START_LOWER = 3+int'(pt.BTB_TOFFSET_SIZE)+int'(FA_CMP_LOWER); | ||||
|    localparam FA_TAG_END_LOWER = 5+int'(pt.BTB_TOFFSET_SIZE); | ||||
| 
 | ||||
|    localparam TAG_START=BTB_DWIDTH-1; | ||||
|    localparam PC4=4; | ||||
|    localparam BOFF=3; | ||||
|    localparam CALL=2; | ||||
|  | @ -84,10 +96,11 @@ import el2_pkg::*; | |||
| 
 | ||||
|    localparam LRU_SIZE=pt.BTB_ARRAY_DEPTH; | ||||
|    localparam NUM_BHT_LOOP = (pt.BHT_ARRAY_DEPTH > 16 ) ? 16 : pt.BHT_ARRAY_DEPTH; | ||||
|    localparam NUM_BHT_LOOP_INNER_HI =  (pt.BHT_ARRAY_DEPTH > 16 ) ? pt.BHT_ADDR_LO+3 : pt.BHT_ADDR_HI; | ||||
|    localparam NUM_BHT_LOOP_OUTER_LO =  (pt.BHT_ARRAY_DEPTH > 16 ) ? pt.BHT_ADDR_LO+4 : pt.BHT_ADDR_LO; | ||||
|    localparam NUM_BHT_LOOP_INNER_HI =  (pt.BHT_ARRAY_DEPTH > 16 ) ?pt.BHT_ADDR_LO+3 : pt.BHT_ADDR_HI; | ||||
|    localparam NUM_BHT_LOOP_OUTER_LO =  (pt.BHT_ARRAY_DEPTH > 16 ) ?pt.BHT_ADDR_LO+4 : pt.BHT_ADDR_LO; | ||||
|    localparam BHT_NO_ADDR_MATCH  = ( pt.BHT_ARRAY_DEPTH <= 16 ); | ||||
| 
 | ||||
| 
 | ||||
|    logic exu_mp_valid_write; | ||||
|    logic exu_mp_ataken; | ||||
|    logic exu_mp_valid; // conditional branch mispredict
 | ||||
|  | @ -120,13 +133,12 @@ import el2_pkg::*; | |||
|    logic              rs_push, rs_pop, rs_hold; | ||||
|    logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] btb_rd_addr_p1_f, btb_wr_addr, btb_rd_addr_f; | ||||
|    logic [pt.BTB_BTAG_SIZE-1:0] btb_wr_tag, fetch_rd_tag_f, fetch_rd_tag_p1_f; | ||||
|    logic [16+pt.BTB_BTAG_SIZE:0]        btb_wr_data; | ||||
|    logic [BTB_DWIDTH-1:0]        btb_wr_data; | ||||
|    logic               btb_wr_en_way0, btb_wr_en_way1; | ||||
| 
 | ||||
| 
 | ||||
|    logic               dec_tlu_error_wb, btb_valid, dec_tlu_br0_middle_wb; | ||||
|    logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]        btb_error_addr_wb; | ||||
| 
 | ||||
|    logic branch_error_collision_f, fetch_mp_collision_f, branch_error_collision_p1_f, fetch_mp_collision_p1_f; | ||||
| 
 | ||||
|    logic  branch_error_bank_conflict_f; | ||||
|  | @ -142,17 +154,17 @@ import el2_pkg::*; | |||
| 
 | ||||
|    logic leak_one_f, leak_one_f_d1; | ||||
| 
 | ||||
|    logic [LRU_SIZE-1:0][16+pt.BTB_BTAG_SIZE:0]  btb_bank0_rd_data_way0_out ; | ||||
|    logic [LRU_SIZE-1:0][BTB_DWIDTH-1:0]  btb_bank0_rd_data_way0_out ; | ||||
| 
 | ||||
|    logic [LRU_SIZE-1:0][16+pt.BTB_BTAG_SIZE:0]  btb_bank0_rd_data_way1_out ; | ||||
|    logic [LRU_SIZE-1:0][BTB_DWIDTH-1:0]  btb_bank0_rd_data_way1_out ; | ||||
| 
 | ||||
|    logic                [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way0_f ; | ||||
|    logic                [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way1_f ; | ||||
|    logic                [BTB_DWIDTH-1:0] btb_bank0_rd_data_way0_f ; | ||||
|    logic                [BTB_DWIDTH-1:0] btb_bank0_rd_data_way1_f ; | ||||
| 
 | ||||
|    logic                [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way0_p1_f ; | ||||
|    logic                [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way1_p1_f ; | ||||
|    logic                [BTB_DWIDTH-1:0] btb_bank0_rd_data_way0_p1_f ; | ||||
|    logic                [BTB_DWIDTH-1:0] btb_bank0_rd_data_way1_p1_f ; | ||||
| 
 | ||||
|    logic                [16+pt.BTB_BTAG_SIZE:0] btb_vbank0_rd_data_f, btb_vbank1_rd_data_f; | ||||
|    logic                [BTB_DWIDTH-1:0] btb_vbank0_rd_data_f, btb_vbank1_rd_data_f; | ||||
| 
 | ||||
|    logic                                         final_h; | ||||
|    logic                                         btb_fg_crossing_f; | ||||
|  | @ -167,10 +179,10 @@ import el2_pkg::*; | |||
|    logic [31:2] fetch_addr_p1_f; | ||||
| 
 | ||||
| 
 | ||||
|    logic exu_mp_way, exu_mp_way_f, dec_tlu_br0_way_wb, dec_tlu_way_wb, dec_tlu_way_wb_f; | ||||
|    logic                [16+pt.BTB_BTAG_SIZE:0] btb_bank0e_rd_data_f, btb_bank0e_rd_data_p1_f; | ||||
|    logic exu_mp_way, exu_mp_way_f, dec_tlu_br0_way_wb, dec_tlu_way_wb; | ||||
|    logic                [BTB_DWIDTH-1:0] btb_bank0e_rd_data_f, btb_bank0e_rd_data_p1_f; | ||||
| 
 | ||||
|    logic                [16+pt.BTB_BTAG_SIZE:0] btb_bank0o_rd_data_f; | ||||
|    logic                [BTB_DWIDTH-1:0] btb_bank0o_rd_data_f; | ||||
| 
 | ||||
|    logic [1:0] tag_match_way0_expanded_f, tag_match_way1_expanded_f; | ||||
| 
 | ||||
|  | @ -178,7 +190,7 @@ import el2_pkg::*; | |||
|     logic [1:0]                                  bht_bank0_rd_data_f; | ||||
|     logic [1:0]                                  bht_bank1_rd_data_f; | ||||
|     logic [1:0]                                  bht_bank0_rd_data_p1_f; | ||||
| logic exu_flush_final_d1; | ||||
|    genvar                                        j, i; | ||||
| 
 | ||||
|    assign exu_mp_valid = exu_mp_pkt.misp & ~leak_one_f; // conditional branch mispredict
 | ||||
|    assign exu_mp_boffset = exu_mp_pkt.boffset;  // branch offset
 | ||||
|  | @ -229,6 +241,12 @@ logic exu_flush_final_d1; | |||
|    assign branch_error_bank_conflict_f = branch_error_collision_f & dec_tlu_error_wb; | ||||
|    assign branch_error_bank_conflict_p1_f = branch_error_collision_p1_f & dec_tlu_error_wb; | ||||
| 
 | ||||
|    // set on leak one, hold until next flush without leak one
 | ||||
|    assign leak_one_f = (dec_tlu_flush_leak_one_wb & dec_tlu_flush_lower_wb) | (leak_one_f_d1 & ~dec_tlu_flush_lower_wb); | ||||
| 
 | ||||
| logic exu_flush_final_d1; | ||||
| 
 | ||||
|  if(!pt.BTB_FULLYA) begin | ||||
|    assign fetch_mp_collision_f = ( (exu_mp_btag[pt.BTB_BTAG_SIZE-1:0] == fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]) & | ||||
|                                     exu_mp_valid & ifc_fetch_req_f & | ||||
|                                     (exu_mp_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] == btb_rd_addr_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]) | ||||
|  | @ -237,26 +255,18 @@ logic exu_flush_final_d1; | |||
|                                        exu_mp_valid & ifc_fetch_req_f & | ||||
|                                        (exu_mp_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] == btb_rd_addr_p1_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]) | ||||
|                                        ); | ||||
|    // set on leak one, hold until next flush without leak one
 | ||||
|    assign leak_one_f = (dec_tlu_flush_leak_one_wb & dec_tlu_flush_lower_wb) | (leak_one_f_d1 & ~dec_tlu_flush_lower_wb); | ||||
| 
 | ||||
| 
 | ||||
|    rvdff #(4) coll_ff (.*, .clk(active_clk), | ||||
|                          .din({exu_flush_final, exu_mp_way, dec_tlu_way_wb, leak_one_f}), | ||||
|                         .dout({exu_flush_final_d1, exu_mp_way_f, dec_tlu_way_wb_f, leak_one_f_d1})); | ||||
| 
 | ||||
|    // 2 -way SA, figure out the way hit and mux accordingly
 | ||||
|    assign tag_match_way0_f = btb_bank0_rd_data_way0_f[BV] & (btb_bank0_rd_data_way0_f[TAG_START:17] == fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]) & | ||||
|                               ~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & ifc_fetch_req_f & ~leak_one_f; | ||||
|                               ~(dec_tlu_way_wb & branch_error_bank_conflict_f) & ifc_fetch_req_f & ~leak_one_f; | ||||
| 
 | ||||
|    assign tag_match_way1_f = btb_bank0_rd_data_way1_f[BV] & (btb_bank0_rd_data_way1_f[TAG_START:17] == fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]) & | ||||
|                               ~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & ifc_fetch_req_f & ~leak_one_f; | ||||
|                               ~(dec_tlu_way_wb & branch_error_bank_conflict_f) & ifc_fetch_req_f & ~leak_one_f; | ||||
| 
 | ||||
|    assign tag_match_way0_p1_f = btb_bank0_rd_data_way0_p1_f[BV] & (btb_bank0_rd_data_way0_p1_f[TAG_START:17] == fetch_rd_tag_p1_f[pt.BTB_BTAG_SIZE-1:0]) & | ||||
|                               ~(dec_tlu_way_wb_f & branch_error_bank_conflict_p1_f) & ifc_fetch_req_f & ~leak_one_f; | ||||
|                               ~(dec_tlu_way_wb & branch_error_bank_conflict_p1_f) & ifc_fetch_req_f & ~leak_one_f; | ||||
| 
 | ||||
|    assign tag_match_way1_p1_f = btb_bank0_rd_data_way1_p1_f[BV] & (btb_bank0_rd_data_way1_p1_f[TAG_START:17] == fetch_rd_tag_p1_f[pt.BTB_BTAG_SIZE-1:0]) & | ||||
|                               ~(dec_tlu_way_wb_f & branch_error_bank_conflict_p1_f) & ifc_fetch_req_f & ~leak_one_f; | ||||
|                               ~(dec_tlu_way_wb & branch_error_bank_conflict_p1_f) & ifc_fetch_req_f & ~leak_one_f; | ||||
| 
 | ||||
| 
 | ||||
|    // Both ways could hit, use the offset bit to reorder
 | ||||
|  | @ -276,21 +286,22 @@ logic exu_flush_final_d1; | |||
|    assign wayhit_f[1:0] = tag_match_way0_expanded_f[1:0] | tag_match_way1_expanded_f[1:0]; | ||||
|    assign wayhit_p1_f[1:0] = tag_match_way0_expanded_p1_f[1:0] | tag_match_way1_expanded_p1_f[1:0]; | ||||
| 
 | ||||
|    assign btb_bank0o_rd_data_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_f[1]}} & btb_bank0_rd_data_way0_f[16+pt.BTB_BTAG_SIZE:0]) | | ||||
|                                                             ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_f[1]}} & btb_bank0_rd_data_way1_f[16+pt.BTB_BTAG_SIZE:0]) ); | ||||
|    assign btb_bank0e_rd_data_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_f[0]}} & btb_bank0_rd_data_way0_f[16+pt.BTB_BTAG_SIZE:0]) | | ||||
|                                                             ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_f[0]}} & btb_bank0_rd_data_way1_f[16+pt.BTB_BTAG_SIZE:0]) ); | ||||
|    assign btb_bank0o_rd_data_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_f[1]}} & btb_bank0_rd_data_way0_f[BTB_DWIDTH-1:0]) | | ||||
|                                                             ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_f[1]}} & btb_bank0_rd_data_way1_f[BTB_DWIDTH-1:0]) ); | ||||
|    assign btb_bank0e_rd_data_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_f[0]}} & btb_bank0_rd_data_way0_f[BTB_DWIDTH-1:0]) | | ||||
|                                                             ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_f[0]}} & btb_bank0_rd_data_way1_f[BTB_DWIDTH-1:0]) ); | ||||
| 
 | ||||
|    assign btb_bank0e_rd_data_p1_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_p1_f[0]}} & btb_bank0_rd_data_way0_p1_f[16+pt.BTB_BTAG_SIZE:0]) | | ||||
|                                                                ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_p1_f[0]}} & btb_bank0_rd_data_way1_p1_f[16+pt.BTB_BTAG_SIZE:0]) ); | ||||
|    assign btb_bank0e_rd_data_p1_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_p1_f[0]}} & btb_bank0_rd_data_way0_p1_f[BTB_DWIDTH-1:0]) | | ||||
|                                                                ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_p1_f[0]}} & btb_bank0_rd_data_way1_p1_f[BTB_DWIDTH-1:0]) ); | ||||
| 
 | ||||
|    // virtual bank order
 | ||||
| 
 | ||||
|    assign btb_vbank0_rd_data_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{fetch_start_f[0]}} &  btb_bank0e_rd_data_f[16+pt.BTB_BTAG_SIZE:0]) | | ||||
|                                                             ({17+pt.BTB_BTAG_SIZE{fetch_start_f[1]}} &  btb_bank0o_rd_data_f[16+pt.BTB_BTAG_SIZE:0]) ); | ||||
|    assign btb_vbank1_rd_data_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{fetch_start_f[0]}} &  btb_bank0o_rd_data_f[16+pt.BTB_BTAG_SIZE:0]) | | ||||
|                                                             ({17+pt.BTB_BTAG_SIZE{fetch_start_f[1]}} &  btb_bank0e_rd_data_p1_f[16+pt.BTB_BTAG_SIZE:0]) ); | ||||
|    assign btb_vbank0_rd_data_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{fetch_start_f[0]}} &  btb_bank0e_rd_data_f[BTB_DWIDTH-1:0]) | | ||||
|                                                             ({17+pt.BTB_BTAG_SIZE{fetch_start_f[1]}} &  btb_bank0o_rd_data_f[BTB_DWIDTH-1:0]) ); | ||||
|    assign btb_vbank1_rd_data_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{fetch_start_f[0]}} &  btb_bank0o_rd_data_f[BTB_DWIDTH-1:0]) | | ||||
|                                                             ({17+pt.BTB_BTAG_SIZE{fetch_start_f[1]}} &  btb_bank0e_rd_data_p1_f[BTB_DWIDTH-1:0]) ); | ||||
| 
 | ||||
|    assign way_raw[1:0] =  tag_match_vway1_expanded_f[1:0] | (~vwayhit_f[1:0] & btb_vlru_rd_f[1:0]); | ||||
| 
 | ||||
|    // --------------------------------------------------------------------------------
 | ||||
|    // --------------------------------------------------------------------------------
 | ||||
|  | @ -306,8 +317,12 @@ logic exu_flush_final_d1; | |||
| 
 | ||||
|    assign mp_wrlru_b0[LRU_SIZE-1:0] = mp_wrindex_dec[LRU_SIZE-1:0] & {LRU_SIZE{exu_mp_valid}}; | ||||
| 
 | ||||
|    genvar     j, i; | ||||
| 
 | ||||
|    assign btb_lru_b0_hold[LRU_SIZE-1:0] = ~mp_wrlru_b0[LRU_SIZE-1:0] & ~fetch_wrlru_b0[LRU_SIZE-1:0]; | ||||
| 
 | ||||
|    // Forward the mp lru information to the fetch, avoids multiple way hits later
 | ||||
|    assign use_mp_way = fetch_mp_collision_f; | ||||
|    assign use_mp_way_p1 = fetch_mp_collision_p1_f; | ||||
| 
 | ||||
|    assign lru_update_valid_f = (vwayhit_f[0] | vwayhit_f[1]) & ifc_fetch_req_f & ~leak_one_f; | ||||
| 
 | ||||
|  | @ -317,18 +332,13 @@ logic exu_flush_final_d1; | |||
|    assign fetch_wrlru_p1_b0[LRU_SIZE-1:0] = fetch_wrindex_p1_dec[LRU_SIZE-1:0] & | ||||
|                                          {LRU_SIZE{lru_update_valid_f}}; | ||||
| 
 | ||||
|    assign btb_lru_b0_hold[LRU_SIZE-1:0] = ~mp_wrlru_b0[LRU_SIZE-1:0] & ~fetch_wrlru_b0[LRU_SIZE-1:0]; | ||||
| 
 | ||||
|    // Forward the mp lru information to the fetch, avoids multiple way hits later
 | ||||
|    assign use_mp_way = fetch_mp_collision_f; | ||||
|    assign use_mp_way_p1 = fetch_mp_collision_p1_f; | ||||
| 
 | ||||
| 
 | ||||
|    assign btb_lru_b0_ns[LRU_SIZE-1:0] = ( (btb_lru_b0_hold[LRU_SIZE-1:0] & btb_lru_b0_f[LRU_SIZE-1:0]) | | ||||
|                                           (mp_wrlru_b0[LRU_SIZE-1:0] & {LRU_SIZE{~exu_mp_way}}) | | ||||
|                                           (fetch_wrlru_b0[LRU_SIZE-1:0] & {LRU_SIZE{tag_match_way0_f}}) | | ||||
|                                           (fetch_wrlru_p1_b0[LRU_SIZE-1:0] & {LRU_SIZE{tag_match_way0_p1_f}}) ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign btb_lru_rd_f = use_mp_way ? exu_mp_way_f : |(fetch_wrindex_dec[LRU_SIZE-1:0] & btb_lru_b0_f[LRU_SIZE-1:0]); | ||||
| 
 | ||||
|    assign btb_lru_rd_p1_f = use_mp_way_p1 ? exu_mp_way_f : |(fetch_wrindex_p1_dec[LRU_SIZE-1:0] & btb_lru_b0_f[LRU_SIZE-1:0]); | ||||
|  | @ -340,12 +350,12 @@ logic exu_flush_final_d1; | |||
|    assign tag_match_vway1_expanded_f[1:0] = ( ({2{fetch_start_f[0]}} & {tag_match_way1_expanded_f[1:0]}) | | ||||
|                                                ({2{fetch_start_f[1]}} & {tag_match_way1_expanded_p1_f[0], tag_match_way1_expanded_f[1]}) ); | ||||
| 
 | ||||
|    assign way_raw[1:0] =  tag_match_vway1_expanded_f[1:0] | (~vwayhit_f[1:0] & btb_vlru_rd_f[1:0]); | ||||
| 
 | ||||
|    rvdffe #(LRU_SIZE) btb_lru_ff (.*, .en(ifc_fetch_req_f | exu_mp_valid), | ||||
|                                     .din(btb_lru_b0_ns[(LRU_SIZE)-1:0]), | ||||
|                                    .dout(btb_lru_b0_f[(LRU_SIZE)-1:0])); | ||||
| 
 | ||||
|  end // if (!pt.BTB_FULLYA)
 | ||||
|    // Detect end of cache line and mask as needed
 | ||||
|    logic eoc_near; | ||||
|    logic eoc_mask; | ||||
|  | @ -353,8 +363,6 @@ logic exu_flush_final_d1; | |||
|    assign eoc_mask = ~eoc_near| (|(~ifc_fetch_addr_f[2:1])); | ||||
| 
 | ||||
| 
 | ||||
|    assign vwayhit_f[1:0] = ( ({2{fetch_start_f[0]}} & {wayhit_f[1:0]}) | | ||||
|                               ({2{fetch_start_f[1]}} & {wayhit_p1_f[0], wayhit_f[1]})) & {eoc_mask, 1'b1}; | ||||
| 
 | ||||
|    // --------------------------------------------------------------------------------
 | ||||
|    // --------------------------------------------------------------------------------
 | ||||
|  | @ -456,7 +464,10 @@ logic exu_flush_final_d1; | |||
|                                          ({pt.BHT_GHR_SIZE{~exu_flush_final_d1 & ifc_fetch_req_f & ic_hit_f & ~leak_one_f_d1}} & merged_ghr[pt.BHT_GHR_SIZE-1:0]) | | ||||
|                                          ({pt.BHT_GHR_SIZE{~exu_flush_final_d1 & ~(ifc_fetch_req_f & ic_hit_f & ~leak_one_f_d1)}} & fghr[pt.BHT_GHR_SIZE-1:0])); | ||||
| 
 | ||||
|    rvdff #(pt.BHT_GHR_SIZE) fetchghr (.*, .clk(active_clk), .din(fghr_ns[pt.BHT_GHR_SIZE-1:0]), .dout(fghr[pt.BHT_GHR_SIZE-1:0])); | ||||
|    rvdffie #(.WIDTH(pt.BHT_GHR_SIZE+3),.OVERRIDE(1)) fetchghr (.*, | ||||
|                                           .din ({exu_flush_final, exu_mp_way, leak_one_f, fghr_ns[pt.BHT_GHR_SIZE-1:0]}), | ||||
|                                           .dout({exu_flush_final_d1, exu_mp_way_f, leak_one_f_d1, fghr[pt.BHT_GHR_SIZE-1:0]})); | ||||
| 
 | ||||
|    assign ifu_bp_fghr_f[pt.BHT_GHR_SIZE-1:0] = fghr[pt.BHT_GHR_SIZE-1:0]; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -502,7 +513,8 @@ assign use_fa_plus = (~bht_dir_f[0] & ~fetch_start_f[0] & ~btb_rd_pc4_f); | |||
|    assign bp_total_branch_offset_f =  bloc_f[1] ^ btb_rd_pc4_f; | ||||
| 
 | ||||
|    logic [31:2] adder_pc_in_f, ifc_fetch_adder_prior; | ||||
|    rvdffe #(30) faddrf_ff (.*, .en(ifc_fetch_req_f & ~ifu_bp_hit_taken_f & ic_hit_f), .din(ifc_fetch_addr_f[31:2]), .dout(ifc_fetch_adder_prior[31:2])); | ||||
|    rvdfflie #(.WIDTH(30), .LEFT(19)) faddrf_ff (.*, .en(ifc_fetch_req_f & ~ifu_bp_hit_taken_f & ic_hit_f), .din(ifc_fetch_addr_f[31:2]), .dout(ifc_fetch_adder_prior[31:2])); | ||||
| 
 | ||||
| 
 | ||||
|    assign ifu_bp_poffset_f[11:0] = btb_rd_tgt_f[11:0]; | ||||
| 
 | ||||
|  | @ -514,8 +526,9 @@ assign use_fa_plus = (~bht_dir_f[0] & ~fetch_start_f[0] & ~btb_rd_pc4_f); | |||
|                          .offset(btb_rd_tgt_f[11:0]), | ||||
|                          .dout(bp_btb_target_adder_f[31:1]) | ||||
|                          ); | ||||
|    // mux in the return stack address here for a predicted return assuming the RS is valid
 | ||||
|    assign ifu_bp_btb_target_f[31:1] = (btb_rd_ret_f & ~btb_rd_call_f & rets_out[0][0]) ? rets_out[0][31:1] : bp_btb_target_adder_f[31:1]; | ||||
|    // mux in the return stack address here for a predicted return assuming the RS is valid, quite if no prediction
 | ||||
|    assign ifu_bp_btb_target_f[31:1] = (({31{btb_rd_ret_f & ~btb_rd_call_f & rets_out[0][0] & ifu_bp_hit_taken_f}} & rets_out[0][31:1]) | | ||||
|                                        ({31{~(btb_rd_ret_f & ~btb_rd_call_f & rets_out[0][0]) & ifu_bp_hit_taken_f}} & bp_btb_target_adder_f[31:1]) ); | ||||
| 
 | ||||
| 
 | ||||
|    // ----------------------------------------------------------------------
 | ||||
|  | @ -539,7 +552,7 @@ assign use_fa_plus = (~bht_dir_f[0] & ~fetch_start_f[0] & ~btb_rd_pc4_f); | |||
| 
 | ||||
|    assign rsenable[0] = ~rs_hold; | ||||
| 
 | ||||
|    for (i=0; i<32'(pt.RET_STACK_SIZE); i++) begin : retstack | ||||
|    for (i=0; i<pt.RET_STACK_SIZE; i++) begin : retstack | ||||
| 
 | ||||
|       // for the last entry in the stack, we don't have a pop position
 | ||||
|       if(i==pt.RET_STACK_SIZE-1) begin | ||||
|  | @ -570,25 +583,38 @@ assign use_fa_plus = (~bht_dir_f[0] & ~fetch_start_f[0] & ~btb_rd_pc4_f); | |||
| 
 | ||||
|    assign btb_wr_tag[pt.BTB_BTAG_SIZE-1:0] = exu_mp_btag[pt.BTB_BTAG_SIZE-1:0]; | ||||
| 
 | ||||
| if(pt.BTB_BTAG_FOLD) begin : btbfold | ||||
|    el2_btb_tag_hash_fold #(.pt(pt)) rdtagf  (.hash(fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]),    .pc({ifc_fetch_addr_f[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]})); | ||||
|    el2_btb_tag_hash_fold #(.pt(pt)) rdtagp1f(.hash(fetch_rd_tag_p1_f[pt.BTB_BTAG_SIZE-1:0]), .pc({fetch_addr_p1_f[ pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]})); | ||||
| end | ||||
| else begin | ||||
|    el2_btb_tag_hash #(.pt(pt)) rdtagf(.hash(fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]), .pc({ifc_fetch_addr_f[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]})); | ||||
|    el2_btb_tag_hash #(.pt(pt)) rdtagp1f(.hash(fetch_rd_tag_p1_f[pt.BTB_BTAG_SIZE-1:0]), .pc({fetch_addr_p1_f[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]})); | ||||
| end | ||||
|    if(!pt.BTB_FULLYA) begin | ||||
| 
 | ||||
|    assign btb_wr_data[16+pt.BTB_BTAG_SIZE:0] = {btb_wr_tag[pt.BTB_BTAG_SIZE-1:0], exu_mp_tgt[11:0], exu_mp_pc4, exu_mp_boffset, exu_mp_call | exu_mp_ja, exu_mp_ret | exu_mp_ja, btb_valid} ; | ||||
|       if(pt.BTB_BTAG_FOLD) begin : btbfold | ||||
|          el2_btb_tag_hash_fold #(.pt(pt)) rdtagf  (.hash(fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]), | ||||
|                                                     .pc({ifc_fetch_addr_f[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]})); | ||||
|          el2_btb_tag_hash_fold #(.pt(pt)) rdtagp1f(.hash(fetch_rd_tag_p1_f[pt.BTB_BTAG_SIZE-1:0]), | ||||
|                                                     .pc({fetch_addr_p1_f[ pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]})); | ||||
|       end | ||||
|       else begin | ||||
|          el2_btb_tag_hash #(.pt(pt)) rdtagf(.hash(fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]), | ||||
|                                              .pc({ifc_fetch_addr_f[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]})); | ||||
|          el2_btb_tag_hash #(.pt(pt)) rdtagp1f(.hash(fetch_rd_tag_p1_f[pt.BTB_BTAG_SIZE-1:0]), | ||||
|                                                .pc({fetch_addr_p1_f[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]})); | ||||
|       end | ||||
| 
 | ||||
|    assign exu_mp_valid_write = exu_mp_valid & exu_mp_ataken; | ||||
|    assign btb_wr_en_way0 = ( ({{~exu_mp_way & exu_mp_valid_write & ~dec_tlu_error_wb}}) | | ||||
|                              ({{~dec_tlu_way_wb & dec_tlu_error_wb}})); | ||||
|       assign btb_wr_en_way0 = ( ({{~exu_mp_way & exu_mp_valid_write & ~dec_tlu_error_wb}}) | | ||||
|                                 ({{~dec_tlu_way_wb & dec_tlu_error_wb}})); | ||||
| 
 | ||||
|    assign btb_wr_en_way1 = ( ({{exu_mp_way & exu_mp_valid_write & ~dec_tlu_error_wb}}) | | ||||
|                              ({{dec_tlu_way_wb & dec_tlu_error_wb}})); | ||||
|    assign btb_wr_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] = dec_tlu_error_wb ? btb_error_addr_wb[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] : exu_mp_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]; | ||||
|       assign btb_wr_en_way1 = ( ({{exu_mp_way & exu_mp_valid_write & ~dec_tlu_error_wb}}) | | ||||
|                                 ({{dec_tlu_way_wb & dec_tlu_error_wb}})); | ||||
|       assign btb_wr_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] = dec_tlu_error_wb ? btb_error_addr_wb[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] : exu_mp_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]; | ||||
| 
 | ||||
| 
 | ||||
|       assign vwayhit_f[1:0] = ( ({2{fetch_start_f[0]}} & {wayhit_f[1:0]}) | | ||||
|                                 ({2{fetch_start_f[1]}} & {wayhit_p1_f[0], wayhit_f[1]})) & {eoc_mask, 1'b1}; | ||||
| 
 | ||||
|    end // if (!pt.BTB_FULLYA)
 | ||||
| 
 | ||||
|    assign btb_wr_data[BTB_DWIDTH-1:0] = {btb_wr_tag[pt.BTB_BTAG_SIZE-1:0], exu_mp_tgt[pt.BTB_TOFFSET_SIZE-1:0], exu_mp_pc4, exu_mp_boffset, | ||||
|                                                 exu_mp_call | exu_mp_ja, exu_mp_ret | exu_mp_ja, btb_valid} ; | ||||
| 
 | ||||
|    assign exu_mp_valid_write = exu_mp_valid & exu_mp_ataken & ~exu_mp_pkt.valid; | ||||
|    logic [1:0] bht_wr_data0, bht_wr_data2; | ||||
|    logic [1:0] bht_wr_en0, bht_wr_en2; | ||||
| 
 | ||||
|  | @ -622,46 +648,172 @@ end | |||
|    // BTB
 | ||||
|    // Entry -> tag[pt.BTB_BTAG_SIZE-1:0], toffset[11:0], pc4, boffset, call, ret, valid
 | ||||
| 
 | ||||
|    if(!pt.BTB_FULLYA) begin | ||||
| 
 | ||||
|     for (j=0 ; j<32'(LRU_SIZE) ; j++) begin : BTB_FLOPS | ||||
|       // Way 0
 | ||||
|           rvdffe #(17+pt.BTB_BTAG_SIZE) btb_bank0_way0 (.*, | ||||
|       for (j=0 ; j<LRU_SIZE ; j++) begin : BTB_FLOPS | ||||
|          // Way 0
 | ||||
|          rvdffe #(17+pt.BTB_BTAG_SIZE) btb_bank0_way0 (.*, | ||||
|                     .en(((btb_wr_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] == j) & btb_wr_en_way0)), | ||||
|                     .din        (btb_wr_data[16+pt.BTB_BTAG_SIZE:0]), | ||||
|                     .din        (btb_wr_data[BTB_DWIDTH-1:0]), | ||||
|                     .dout       (btb_bank0_rd_data_way0_out[j])); | ||||
| 
 | ||||
|       // Way 1
 | ||||
|           rvdffe #(17+pt.BTB_BTAG_SIZE) btb_bank0_way1 (.*, | ||||
|          // Way 1
 | ||||
|          rvdffe #(17+pt.BTB_BTAG_SIZE) btb_bank0_way1 (.*, | ||||
|                     .en(((btb_wr_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] == j) & btb_wr_en_way1)), | ||||
|                     .din        (btb_wr_data[16+pt.BTB_BTAG_SIZE:0]), | ||||
|                     .din        (btb_wr_data[BTB_DWIDTH-1:0]), | ||||
|                     .dout       (btb_bank0_rd_data_way1_out[j])); | ||||
| 
 | ||||
|     end | ||||
|       end | ||||
| 
 | ||||
| 
 | ||||
|     always_comb begin : BTB_rd_mux | ||||
|         btb_bank0_rd_data_way0_f[16+pt.BTB_BTAG_SIZE:0] = '0 ; | ||||
|         btb_bank0_rd_data_way1_f[16+pt.BTB_BTAG_SIZE:0] = '0 ; | ||||
|         btb_bank0_rd_data_way0_p1_f[16+pt.BTB_BTAG_SIZE:0] = '0 ; | ||||
|         btb_bank0_rd_data_way1_p1_f[16+pt.BTB_BTAG_SIZE:0] = '0 ; | ||||
|         btb_bank0_rd_data_way0_f[BTB_DWIDTH-1:0] = '0 ; | ||||
|         btb_bank0_rd_data_way1_f[BTB_DWIDTH-1:0] = '0 ; | ||||
|         btb_bank0_rd_data_way0_p1_f[BTB_DWIDTH-1:0] = '0 ; | ||||
|         btb_bank0_rd_data_way1_p1_f[BTB_DWIDTH-1:0] = '0 ; | ||||
| 
 | ||||
|         for (int j=0; j< LRU_SIZE; j++) begin | ||||
|           if (btb_rd_addr_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] == (pt.BTB_ADDR_HI-pt.BTB_ADDR_LO+1)'(j)) begin | ||||
| 
 | ||||
|            btb_bank0_rd_data_way0_f[16+pt.BTB_BTAG_SIZE:0] =  btb_bank0_rd_data_way0_out[j]; | ||||
|            btb_bank0_rd_data_way1_f[16+pt.BTB_BTAG_SIZE:0] =  btb_bank0_rd_data_way1_out[j]; | ||||
|            btb_bank0_rd_data_way0_f[BTB_DWIDTH-1:0] =  btb_bank0_rd_data_way0_out[j]; | ||||
|            btb_bank0_rd_data_way1_f[BTB_DWIDTH-1:0] =  btb_bank0_rd_data_way1_out[j]; | ||||
| 
 | ||||
|           end | ||||
|         end | ||||
|         for (int j=0; j< LRU_SIZE; j++) begin | ||||
|           if (btb_rd_addr_p1_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] == (pt.BTB_ADDR_HI-pt.BTB_ADDR_LO+1)'(j)) begin | ||||
| 
 | ||||
|            btb_bank0_rd_data_way0_p1_f[16+pt.BTB_BTAG_SIZE:0] =  btb_bank0_rd_data_way0_out[j]; | ||||
|            btb_bank0_rd_data_way1_p1_f[16+pt.BTB_BTAG_SIZE:0] =  btb_bank0_rd_data_way1_out[j]; | ||||
|            btb_bank0_rd_data_way0_p1_f[BTB_DWIDTH-1:0] =  btb_bank0_rd_data_way0_out[j]; | ||||
|            btb_bank0_rd_data_way1_p1_f[BTB_DWIDTH-1:0] =  btb_bank0_rd_data_way1_out[j]; | ||||
| 
 | ||||
|           end | ||||
|         end | ||||
|     end | ||||
| end // if (!pt.BTB_FULLYA)
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|       if(pt.BTB_FULLYA) begin : fa | ||||
| 
 | ||||
|          logic found1, hit0, hit1; | ||||
|          logic btb_used_reset, write_used; | ||||
|          logic [$clog2(pt.BTB_SIZE)-1:0] btb_fa_wr_addr0, hit0_index, hit1_index; | ||||
| 
 | ||||
|          logic [pt.BTB_SIZE-1:0]         btb_tag_hit, btb_offset_0, btb_offset_1, btb_used_ns, btb_used, | ||||
|                                          wr0_en, btb_upper_hit; | ||||
|          logic [pt.BTB_SIZE-1:0][BTB_DWIDTH-1:0] btbdata; | ||||
| 
 | ||||
|          // Fully Associative tag hash uses bits 31:3. Bits 2:1 are the offset bits used for the 4 tag comp banks
 | ||||
|          // Full tag used to speed up lookup. There is one 31:3 cmp per entry, and 4 2:1 cmps per entry.
 | ||||
| 
 | ||||
|          logic [FA_CMP_LOWER-1:1]  ifc_fetch_addr_p1_f; | ||||
| 
 | ||||
| 
 | ||||
|          assign ifc_fetch_addr_p1_f[FA_CMP_LOWER-1:1] = ifc_fetch_addr_f[FA_CMP_LOWER-1:1] + 1'b1; | ||||
| 
 | ||||
|          assign fetch_mp_collision_f = ( (exu_mp_btag[pt.BTB_BTAG_SIZE-1:0] == ifc_fetch_addr_f[31:1]) & | ||||
|                                       exu_mp_valid & ifc_fetch_req_f & ~exu_mp_pkt.way); | ||||
|          assign fetch_mp_collision_p1_f = ( (exu_mp_btag[pt.BTB_BTAG_SIZE-1:0] == {ifc_fetch_addr_f[31:FA_CMP_LOWER], ifc_fetch_addr_p1_f[FA_CMP_LOWER-1:1]}) & | ||||
|                                       exu_mp_valid & ifc_fetch_req_f & ~exu_mp_pkt.way); | ||||
| 
 | ||||
|       always_comb begin | ||||
|          btb_vbank0_rd_data_f = '0; | ||||
|          btb_vbank1_rd_data_f = '0; | ||||
|          btb_tag_hit = '0; | ||||
|          btb_upper_hit = '0; | ||||
|          btb_offset_0 = '0; | ||||
|          btb_offset_1 = '0; | ||||
| 
 | ||||
|          found1 = 1'b0; | ||||
|          hit0 = 1'b0; | ||||
|          hit1 = 1'b0; | ||||
|          hit0_index = '0; | ||||
|          hit1_index = '0; | ||||
|          btb_fa_wr_addr0 = '0; | ||||
| 
 | ||||
|          for(int i=0; i<pt.BTB_SIZE; i++) begin | ||||
|             // Break the cmp into chunks for lower area.
 | ||||
|             // Chunk1: FA 31:6 or 31:5 depending on icache line size
 | ||||
|             // Chunk2: FA 5:1 or 4:1 depending on icache line size
 | ||||
|             btb_upper_hit[i] = (btbdata[i][BTB_DWIDTH_TOP:FA_TAG_END_UPPER] == ifc_fetch_addr_f[31:FA_CMP_LOWER]) & btbdata[i][0] & ~wr0_en[i]; | ||||
|             btb_offset_0[i] = (btbdata[i][FA_TAG_START_LOWER:FA_TAG_END_LOWER] == ifc_fetch_addr_f[FA_CMP_LOWER-1:1]) & btb_upper_hit[i]; | ||||
|             btb_offset_1[i] = (btbdata[i][FA_TAG_START_LOWER:FA_TAG_END_LOWER] == ifc_fetch_addr_p1_f[FA_CMP_LOWER-1:1]) & btb_upper_hit[i]; | ||||
| 
 | ||||
|             if(~hit0) begin | ||||
|                if(btb_offset_0[i]) begin | ||||
|                   hit0_index[BTB_FA_INDEX:0] = (BTB_FA_INDEX+1)'(i); | ||||
|                   // hit unless we are also writing this entry at the same time
 | ||||
|                   hit0 = 1'b1; | ||||
|                end | ||||
|             end | ||||
|             if(~hit1) begin | ||||
|                if(btb_offset_1[i]) begin | ||||
|                   hit1_index[BTB_FA_INDEX:0] = (BTB_FA_INDEX+1)'(i); | ||||
|                   hit1 = 1'b1; | ||||
|                end | ||||
|             end | ||||
| 
 | ||||
| 
 | ||||
|             // Mux out the 2 potential branches
 | ||||
|             if(btb_offset_0[i] == 1'b1) | ||||
|               btb_vbank0_rd_data_f[BTB_DWIDTH-1:0] = fetch_mp_collision_f ? btb_wr_data : btbdata[i]; | ||||
|             if(btb_offset_1[i] == 1'b1) | ||||
|               btb_vbank1_rd_data_f[BTB_DWIDTH-1:0] = fetch_mp_collision_p1_f ? btb_wr_data : btbdata[i]; | ||||
| 
 | ||||
|             // find the first zero from bit zero in the used vector, this is the write address
 | ||||
|             if(~found1) begin | ||||
|                if(~btb_used[i]) begin | ||||
|                   btb_fa_wr_addr0[BTB_FA_INDEX:0] = i[BTB_FA_INDEX:0]; | ||||
|                   found1 = 1'b1; | ||||
|                end | ||||
|             end | ||||
|          end | ||||
|       end // always_comb begin
 | ||||
| 
 | ||||
| `ifdef RV_ASSERT_ON | ||||
|    btbhitonehot0: assert #0 ($onehot0(btb_offset_0)); | ||||
|    btbhitonehot1: assert #0 ($onehot0(btb_offset_1)); | ||||
| `endif | ||||
| 
 | ||||
|    assign vwayhit_f[1:0] = {hit1, hit0} & {eoc_mask, 1'b1}; | ||||
| 
 | ||||
|    // way bit is reused as the predicted bit
 | ||||
|    assign way_raw[1:0] =  vwayhit_f[1:0] | {fetch_mp_collision_p1_f, fetch_mp_collision_f}; | ||||
| 
 | ||||
|    for (j=0 ; j<pt.BTB_SIZE ; j++) begin : BTB_FAFLOPS | ||||
| 
 | ||||
|       assign wr0_en[j] = ((btb_fa_wr_addr0[BTB_FA_INDEX:0] == j) & (exu_mp_valid_write & ~exu_mp_pkt.way)) | | ||||
|                          ((dec_fa_error_index == j) & dec_tlu_error_wb); | ||||
| 
 | ||||
|       rvdffe #(BTB_DWIDTH) btb_fa (.*, .clk(clk), | ||||
|                                    .en  (wr0_en[j]), | ||||
|                                    .din (btb_wr_data[BTB_DWIDTH-1:0]), | ||||
|                                    .dout(btbdata[j])); | ||||
|    end // block: BTB_FAFLOPS
 | ||||
| 
 | ||||
|    assign ifu_bp_fa_index_f[1] = hit1 ? hit1_index : '0; | ||||
|    assign ifu_bp_fa_index_f[0] = hit0 ? hit0_index : '0; | ||||
| 
 | ||||
|    assign btb_used_reset = &btb_used[pt.BTB_SIZE-1:0]; | ||||
|    assign btb_used_ns[pt.BTB_SIZE-1:0] = ({pt.BTB_SIZE{vwayhit_f[1]}} & (32'b1 << hit1_index[BTB_FA_INDEX:0])) | | ||||
|                                          ({pt.BTB_SIZE{vwayhit_f[0]}} & (32'b1 << hit0_index[BTB_FA_INDEX:0])) | | ||||
|                                          ({pt.BTB_SIZE{exu_mp_valid_write & ~exu_mp_pkt.way & ~dec_tlu_error_wb}} & (32'b1 << btb_fa_wr_addr0[BTB_FA_INDEX:0])) | | ||||
|                                          ({pt.BTB_SIZE{btb_used_reset}} & {pt.BTB_SIZE{1'b0}}) | | ||||
|                                          ({pt.BTB_SIZE{~btb_used_reset & dec_tlu_error_wb}} & (btb_used[pt.BTB_SIZE-1:0] & ~(32'b1 << dec_fa_error_index[BTB_FA_INDEX:0]))) | | ||||
|                                          (~{pt.BTB_SIZE{btb_used_reset | dec_tlu_error_wb}} & btb_used[pt.BTB_SIZE-1:0]); | ||||
| 
 | ||||
|    assign write_used = btb_used_reset | ifu_bp_hit_taken_f | exu_mp_valid_write | dec_tlu_error_wb; | ||||
| 
 | ||||
| 
 | ||||
|    rvdffe #(pt.BTB_SIZE) btb_usedf (.*, .clk(clk), | ||||
|                     .en  (write_used), | ||||
|                     .din (btb_used_ns[pt.BTB_SIZE-1:0]), | ||||
|                     .dout(btb_used[pt.BTB_SIZE-1:0])); | ||||
| 
 | ||||
| end // block: fa
 | ||||
| 
 | ||||
| 
 | ||||
|    //-----------------------------------------------------------------------------
 | ||||
|    // BHT
 | ||||
|  | @ -676,11 +828,12 @@ end | |||
|    logic [1:0] [(pt.BHT_ARRAY_DEPTH/NUM_BHT_LOOP)-1:0][NUM_BHT_LOOP-1:0]           bht_bank_sel   ; | ||||
| 
 | ||||
|    for ( i=0; i<2; i++) begin : BANKS | ||||
|      for (genvar k=0 ; k < 32'((pt.BHT_ARRAY_DEPTH)/NUM_BHT_LOOP) ; k++) begin : BHT_CLK_GROUP | ||||
|      for (genvar k=0 ; k < (pt.BHT_ARRAY_DEPTH)/NUM_BHT_LOOP ; k++) begin : BHT_CLK_GROUP | ||||
|      assign bht_bank_clken[i][k]  = (bht_wr_en0[i] & ((bht_wr_addr0[pt.BHT_ADDR_HI: NUM_BHT_LOOP_OUTER_LO]==k) |  BHT_NO_ADDR_MATCH)) | | ||||
|                                     (bht_wr_en2[i] & ((bht_wr_addr2[pt.BHT_ADDR_HI: NUM_BHT_LOOP_OUTER_LO]==k) |  BHT_NO_ADDR_MATCH)); | ||||
| 
 | ||||
|      rvclkhdr bht_bank_grp_cgc ( .en(bht_bank_clken[i][k]), .l1clk(bht_bank_clk[i][k]), .* ); | ||||
| `ifndef RV_FPGA_OPTIMIZE | ||||
|      rvclkhdr bht_bank_grp_cgc ( .en(bht_bank_clken[i][k]), .l1clk(bht_bank_clk[i][k]), .* ); // ifndef RV_FPGA_OPTIMIZE
 | ||||
| `endif | ||||
| 
 | ||||
|      for (j=0 ; j<NUM_BHT_LOOP ; j++) begin : BHT_FLOPS | ||||
|        assign   bht_bank_sel[i][k][j]    = (bht_wr_en0[i] & (bht_wr_addr0[NUM_BHT_LOOP_INNER_HI :pt.BHT_ADDR_LO] == j) & ((bht_wr_addr0[pt.BHT_ADDR_HI: NUM_BHT_LOOP_OUTER_LO]==k) | BHT_NO_ADDR_MATCH)) | | ||||
|  | @ -690,9 +843,11 @@ end | |||
|                                                                                                                       bht_wr_data0[1:0]   ; | ||||
| 
 | ||||
| 
 | ||||
|           rvdffs #(2) bht_bank (.*, | ||||
|           rvdffs_fpga #(2) bht_bank (.*, | ||||
|                     .clk        (bht_bank_clk[i][k]), | ||||
|                     .en         (bht_bank_sel[i][k][j]), | ||||
|                     .rawclk     (clk), | ||||
|                     .clken      (bht_bank_sel[i][k][j]), | ||||
|                     .din        (bht_bank_wr_data[i][k][j]), | ||||
|                     .dout       (bht_bank_rd_data_out[i][(16*k)+j])); | ||||
| 
 | ||||
|  | @ -716,9 +871,6 @@ end | |||
|     end // block: BHT_rd_mux
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| function [1:0] countones; | ||||
|       input [1:0] valid; | ||||
| 
 | ||||
|  | @ -728,25 +880,5 @@ countones[1:0] = {2'b0, valid[1]} + | |||
|                  {2'b0, valid[0]}; | ||||
|       end | ||||
|    endfunction | ||||
|    function [2:0] newlru; // updated lru
 | ||||
|       input [2:0] lru;// current lru
 | ||||
|       input [1:0] used;// hit way
 | ||||
|       begin | ||||
| newlru[2] = (lru[2] & ~used[0]) | (~used[1] & ~used[0]); | ||||
| newlru[1] = (~used[1] & ~used[0]) | (used[0]); | ||||
| newlru[0] = (~lru[2] & lru[1] & ~used[1] & ~used[0]) | (~lru[1] & ~lru[0] & used[0]) | ( | ||||
|     ~lru[2] & lru[0] & used[0]) | (lru[0] & ~used[1] & ~used[0]); | ||||
|       end | ||||
|    endfunction //
 | ||||
| 
 | ||||
|    function [1:0] lru2way; // new repl way taking invalid ways into account
 | ||||
|       input [2:0] lru; // current lru
 | ||||
|       input [2:0] v; // current way valids
 | ||||
|       begin | ||||
|          lru2way[1] = (~lru[2] & lru[1] & ~lru[0] & v[1] & v[0]) | (lru[2] & lru[0] & v[1] & v[0]) | (~v[2] & v[1] & v[0]); | ||||
|          lru2way[0] = (lru[2] & ~lru[0] & v[2] & v[0]) | (~v[1] & v[0]); | ||||
|       end | ||||
|    endfunction | ||||
| 
 | ||||
| endmodule // el2_ifu_bp_ctl
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -23,8 +23,8 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
|   ( | ||||
|    input  logic [15:0] din, | ||||
|    output logic [31:0] dout | ||||
|    input  logic [15:0] din,        // 16-bit   compressed instruction
 | ||||
|    output logic [31:0] dout        // 32-bit uncompressed instruction
 | ||||
|    ); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -40,27 +40,27 @@ import el2_pkg::*; | |||
| 
 | ||||
|    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; | ||||
|    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; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,6 +1,6 @@ | |||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -24,22 +24,24 @@ import el2_pkg::*; | |||
| #( | ||||
| `include "el2_param.vh" | ||||
|  )( | ||||
|    input logic                                        clk, | ||||
|    input logic                                        rst_l, | ||||
|    input logic                                        clk_override, | ||||
|    input logic                                        clk,                                 // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic                                        active_clk,                          // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic                                        rst_l,                               // reset, active low
 | ||||
|    input logic                                        clk_override,                        // Override non-functional clock gating
 | ||||
| 
 | ||||
|    input logic                                        iccm_wren, | ||||
|    input logic                                        iccm_rden, | ||||
|    input logic [pt.ICCM_BITS-1:1]                     iccm_rw_addr, | ||||
|    input logic                                        iccm_wren,                           // ICCM write enable
 | ||||
|    input logic                                        iccm_rden,                           // ICCM read enable
 | ||||
|    input logic [pt.ICCM_BITS-1:1]                     iccm_rw_addr,                        // ICCM read/write address
 | ||||
|    input logic                                        iccm_buf_correct_ecc,                // ICCM is doing a single bit error correct cycle
 | ||||
|    input logic                                        iccm_correction_state,               // We are under a correction - This is needed to guard replacements when hit
 | ||||
|    input logic [2:0]                                  iccm_wr_size, | ||||
|    input logic [77:0]                                 iccm_wr_data, | ||||
|    input logic                                        iccm_correction_state,               // ICCM under a correction - This is needed to guard replacements when hit
 | ||||
|    input logic [2:0]                                  iccm_wr_size,                        // ICCM write size
 | ||||
|    input logic [77:0]                                 iccm_wr_data,                        // ICCM write data
 | ||||
| 
 | ||||
|    input el2_ccm_ext_in_pkt_t [pt.ICCM_NUM_BANKS-1:0] iccm_ext_in_pkt,                    // External packet
 | ||||
| 
 | ||||
|    output logic [63:0]                                iccm_rd_data, | ||||
|    output logic [77:0]                                iccm_rd_data_ecc, | ||||
|    input  logic                                       scan_mode | ||||
|    output logic [63:0]                                iccm_rd_data,                        // ICCM read data
 | ||||
|    output logic [77:0]                                iccm_rd_data_ecc,                    // ICCM read ecc
 | ||||
|    input  logic                                       scan_mode                            // Scan mode control
 | ||||
| 
 | ||||
| ); | ||||
| 
 | ||||
|  | @ -72,15 +74,32 @@ import el2_pkg::*; | |||
|    logic                                 redundant_data1_en; | ||||
|    logic                                 r0_addr_en, r1_addr_en; | ||||
| 
 | ||||
|    // Testing persistent flip
 | ||||
|    //   logic [3:0]                              not_iccm_bank_dout;
 | ||||
|    //   logic [15:3]                     ecc_insert_flip_in, ecc_insert_flip;
 | ||||
|    //   logic                                 flip_en, flip_match, flip_match_q;
 | ||||
|    //
 | ||||
|    //   assign      flip_in = (iccm_rw_addr[3:2] != 2'b00);    // dont flip when bank0 - this is to make some progress in DMA streaming cases
 | ||||
|    //   assign      flip_en = iccm_rden;
 | ||||
|    //
 | ||||
|    //   rvdffs #(1) flipmatch  (.*,
 | ||||
|    //                   .clk(clk),
 | ||||
|    //                   .din(flip_in),
 | ||||
|    //                   .en(flip_en),
 | ||||
|    //                   .dout(flip_match_q));
 | ||||
|    //
 | ||||
|    // end of testing flip
 | ||||
| 
 | ||||
| 
 | ||||
|    assign addr_incr[1:0]                    = (iccm_wr_size[1:0] == 2'b11) ?  2'b10: 2'b01; | ||||
|    assign addr_bank_inc[pt.ICCM_BITS-1 : 1] = iccm_rw_addr[pt.ICCM_BITS-1 : 1] + addr_incr[1:0]; | ||||
| 
 | ||||
|    for (genvar i=0; i<32'(pt.ICCM_NUM_BANKS)/2; i++) begin: mem_bank_data | ||||
|    for (genvar i=0; i<pt.ICCM_NUM_BANKS/2; i++) begin: mem_bank_data | ||||
|       assign iccm_bank_wr_data_vec[(2*i)]   = iccm_wr_data[38:0]; | ||||
|       assign iccm_bank_wr_data_vec[(2*i)+1] = iccm_wr_data[77:39]; | ||||
|    end | ||||
| 
 | ||||
|    for (genvar i=0; i<32'(pt.ICCM_NUM_BANKS); i++) begin: mem_bank | ||||
|    for (genvar i=0; i<pt.ICCM_NUM_BANKS; i++) begin: mem_bank | ||||
|       assign wren_bank[i]         = iccm_wren & ((iccm_rw_addr[pt.ICCM_BANK_HI:2] == i) | (addr_bank_inc[pt.ICCM_BANK_HI:2] == i)); | ||||
|       assign iccm_bank_wr_data[i] = iccm_bank_wr_data_vec[i]; | ||||
|       assign rden_bank[i]         = iccm_rden & ( (iccm_rw_addr[pt.ICCM_BANK_HI:2] == i) | (addr_bank_inc[pt.ICCM_BANK_HI:2] == i)); | ||||
|  | @ -98,7 +117,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|  `else | ||||
|  | @ -111,7 +141,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -124,7 +165,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -137,7 +189,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -149,7 +212,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -161,7 +235,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -173,7 +258,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -185,7 +281,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -197,7 +304,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -209,7 +327,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -221,7 +350,18 @@ import el2_pkg::*; | |||
|                                      .WE(wren_bank[i]), | ||||
|                                      .ADR(addr_bank[i]), | ||||
|                                      .D(iccm_bank_wr_data[i][38:0]), | ||||
|                                      .Q(iccm_bank_dout[i][38:0]) | ||||
|                                      .Q(iccm_bank_dout[i][38:0]), | ||||
|                                      .ROP ( ), | ||||
|                                      // These are used by SoC
 | ||||
|                                      .TEST1(iccm_ext_in_pkt[i].TEST1), | ||||
|                                      .RME(iccm_ext_in_pkt[i].RME), | ||||
|                                      .RM(iccm_ext_in_pkt[i].RM), | ||||
|                                      .LS(iccm_ext_in_pkt[i].LS), | ||||
|                                      .DS(iccm_ext_in_pkt[i].DS), | ||||
|                                      .SD(iccm_ext_in_pkt[i].SD) , | ||||
|                                      .TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM), | ||||
|                                      .BC1(iccm_ext_in_pkt[i].BC1), | ||||
|                                      .BC2(iccm_ext_in_pkt[i].BC2) | ||||
| 
 | ||||
|                                       ); | ||||
|      end // block: iccm
 | ||||
|  | @ -235,21 +375,20 @@ import el2_pkg::*; | |||
|                                                  ((addr_bank_inc[pt.ICCM_BITS-1:2]== redundant_address[0][pt.ICCM_BITS-1:2]) & (addr_bank_inc[3:2] == i)))); | ||||
| 
 | ||||
|    rvdff #(1) selred0  (.*, | ||||
|                    .clk(clk), | ||||
|                    .clk(active_clk), | ||||
|                    .din(sel_red0[i]), | ||||
|                    .dout(sel_red0_q[i])); | ||||
| 
 | ||||
|    rvdff #(1) selred1  (.*, | ||||
|                    .clk(clk), | ||||
|                    .clk(active_clk), | ||||
|                    .din(sel_red1[i]), | ||||
|                    .dout(sel_red1_q[i])); | ||||
| 
 | ||||
| 
 | ||||
|   // muxing out the memory data with the redundant data if the address matches
 | ||||
|     assign iccm_bank_dout_fn[i][38:0] = ({39{sel_red1_q[i]}}                         & redundant_data[1][38:0]) | | ||||
|                                         ({39{sel_red0_q[i]}}                         & redundant_data[0][38:0]) | | ||||
|                                         ({39{~sel_red0_q[i] & ~sel_red1_q[i]}}       & iccm_bank_dout[i][38:0]); | ||||
| 
 | ||||
|    assign iccm_bank_dout_fn[i][38:0] = ({39{sel_red1_q[i]}}                         & redundant_data[1][38:0]) | | ||||
|                                        ({39{sel_red0_q[i]}}                         & redundant_data[0][38:0]) | | ||||
|                                        ({39{~sel_red0_q[i] & ~sel_red1_q[i]}}       & iccm_bank_dout[i][38:0]); | ||||
| 
 | ||||
|   end : mem_bank | ||||
| // This section does the redundancy for tolerating single bit errors
 | ||||
|  | @ -261,31 +400,31 @@ import el2_pkg::*; | |||
|    assign redundant_lru_in        = iccm_buf_correct_ecc ? ~redundant_lru : (|sel_red0[pt.ICCM_NUM_BANKS-1:0]) ? 1'b1 : 1'b0; | ||||
| 
 | ||||
|    rvdffs #() red_lru  (.*,                               // LRU flop for the redundant replacements
 | ||||
|                    .clk(clk), | ||||
|                    .clk(active_clk), | ||||
|                    .en(redundant_lru_en), | ||||
|                    .din(redundant_lru_in), | ||||
|                    .dout(redundant_lru)); | ||||
| 
 | ||||
|     rvdffs #(pt.ICCM_BITS-2) r0_address  (.*,                 // Redundant Row 0 address
 | ||||
|                    .clk(clk), | ||||
|                    .clk(active_clk), | ||||
|                    .en(r0_addr_en), | ||||
|                    .din(iccm_rw_addr[pt.ICCM_BITS-1:2]), | ||||
|                    .dout(redundant_address[0][pt.ICCM_BITS-1:2])); | ||||
| 
 | ||||
|    rvdffs #(pt.ICCM_BITS-2) r1_address  (.*,                   // Redundant Row 0 address
 | ||||
|                    .clk(clk), | ||||
|                    .clk(active_clk), | ||||
|                    .en(r1_addr_en), | ||||
|                    .din(iccm_rw_addr[pt.ICCM_BITS-1:2]), | ||||
|                    .dout(redundant_address[1][pt.ICCM_BITS-1:2])); | ||||
| 
 | ||||
|     rvdffs #(1) r0_valid  (.*, | ||||
|                    .clk(clk),                                  // Redundant Row 0 Valid
 | ||||
|                    .clk(active_clk),                                  // Redundant Row 0 Valid
 | ||||
|                    .en(r0_addr_en), | ||||
|                    .din(1'b1), | ||||
|                    .dout(redundant_valid[0])); | ||||
| 
 | ||||
|    rvdffs #(1) r1_valid  (.*,                                   // Redundant Row 1 Valid
 | ||||
|                    .clk(clk), | ||||
|                    .clk(active_clk), | ||||
|                    .en(r1_addr_en), | ||||
|                    .din(1'b1), | ||||
|                    .dout(redundant_valid[1])); | ||||
|  | @ -302,7 +441,7 @@ import el2_pkg::*; | |||
|     assign redundant_data0_in[38:0] = (((iccm_rw_addr[2] == redundant_address[0][2]) & iccm_rw_addr[2]) | (redundant_address[0][2] & (iccm_wr_size[1:0] == 2'b11))) ? iccm_wr_data[77:39]  : iccm_wr_data[38:0]; | ||||
| 
 | ||||
|     rvdffs #(39) r0_data  (.*,                                 // Redundant Row 1 data
 | ||||
|                    .clk(clk), | ||||
|                    .clk(active_clk), | ||||
|                    .en(redundant_data0_en), | ||||
|                    .din(redundant_data0_in[38:0]), | ||||
|                    .dout(redundant_data[0][38:0])); | ||||
|  | @ -313,14 +452,14 @@ import el2_pkg::*; | |||
|    assign redundant_data1_in[38:0] = (((iccm_rw_addr[2] == redundant_address[1][2]) & iccm_rw_addr[2]) | (redundant_address[1][2] & (iccm_wr_size[1:0] == 2'b11))) ? iccm_wr_data[77:39]  : iccm_wr_data[38:0]; | ||||
| 
 | ||||
|     rvdffs #(39) r1_data  (.*,                                  // Redundant Row 1 data
 | ||||
|                    .clk(clk), | ||||
|                    .clk(active_clk), | ||||
|                    .en(redundant_data1_en), | ||||
|                    .din(redundant_data1_in[38:0]), | ||||
|                    .dout(redundant_data[1][38:0])); | ||||
| 
 | ||||
| 
 | ||||
|    rvdffs  #(pt.ICCM_BANK_HI)   rd_addr_lo_ff (.*, .din(iccm_rw_addr [pt.ICCM_BANK_HI:1]), .dout(iccm_rd_addr_lo_q[pt.ICCM_BANK_HI:1]), .en(1'b1));   // bit 0 of address is always 0
 | ||||
|    rvdffs  #(pt.ICCM_BANK_BITS) rd_addr_hi_ff (.*, .din(addr_bank_inc[pt.ICCM_BANK_HI:2]), .dout(iccm_rd_addr_hi_q[pt.ICCM_BANK_HI:2]), .en(1'b1)); | ||||
|    rvdffs  #(pt.ICCM_BANK_HI)   rd_addr_lo_ff (.*, .clk(active_clk), .din(iccm_rw_addr [pt.ICCM_BANK_HI:1]), .dout(iccm_rd_addr_lo_q[pt.ICCM_BANK_HI:1]), .en(1'b1));   // bit 0 of address is always 0
 | ||||
|    rvdffs  #(pt.ICCM_BANK_BITS) rd_addr_hi_ff (.*, .clk(active_clk), .din(addr_bank_inc[pt.ICCM_BANK_HI:2]), .dout(iccm_rd_addr_hi_q[pt.ICCM_BANK_HI:2]), .en(1'b1)); | ||||
| 
 | ||||
|    assign iccm_rd_data_pre[63:0] = {iccm_bank_dout_fn[iccm_rd_addr_hi_q][31:0], iccm_bank_dout_fn[iccm_rd_addr_lo_q[pt.ICCM_BANK_HI:2]][31:0]}; | ||||
|    assign iccm_data[63:0]        = 64'({16'b0, (iccm_rd_data_pre[63:0] >> (16*iccm_rd_addr_lo_q[1]))}); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -26,9 +26,8 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
|   ( | ||||
|    input logic clk, | ||||
|    input logic free_clk, | ||||
|    input logic active_clk, | ||||
|    input logic clk,                         // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic free_l2clk,                  // Clock always.                  Through one clock header.  For flops with    second header built in.
 | ||||
| 
 | ||||
|    input logic rst_l, // reset enable, from core pin
 | ||||
|    input logic scan_mode, // scan
 | ||||
|  | @ -76,7 +75,7 @@ import el2_pkg::*; | |||
| 
 | ||||
|    logic     fb_full_f_ns, fb_full_f; | ||||
|    logic     fb_right, fb_right2, fb_left, wfm, idle; | ||||
|    logic     sel_last_addr_bf, sel_btb_addr_bf, sel_next_addr_bf; | ||||
|    logic     sel_last_addr_bf, sel_next_addr_bf; | ||||
|    logic     miss_f, miss_a; | ||||
|    logic     flush_fb, dma_iccm_stall_any_f; | ||||
|    logic     mb_empty_mod, goto_idle, leave_idle; | ||||
|  | @ -95,13 +94,15 @@ import el2_pkg::*; | |||
|    logic     dma_stall; | ||||
|    assign dma_stall = ic_dma_active | dma_iccm_stall_any_f; | ||||
| 
 | ||||
|    rvdff #(2) ran_ff (.*, .clk(free_clk), .din({dma_iccm_stall_any, miss_f}), .dout({dma_iccm_stall_any_f, miss_a})); | ||||
| 
 | ||||
| 
 | ||||
|    // Fetch address mux
 | ||||
|    // - flush
 | ||||
|    // - Miss *or* flush during WFM (icache miss buffer is blocking)
 | ||||
|    // - Sequential
 | ||||
| 
 | ||||
| if(pt.BTB_ENABLE==1) begin | ||||
|    logic sel_btb_addr_bf; | ||||
| 
 | ||||
|    assign sel_last_addr_bf = ~exu_flush_final & (~ifc_fetch_req_f | ~ic_hit_f); | ||||
|    assign sel_btb_addr_bf  = ~exu_flush_final & ifc_fetch_req_f & ifu_bp_hit_taken_f & ic_hit_f; | ||||
|  | @ -114,6 +115,17 @@ import el2_pkg::*; | |||
|                   ({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path
 | ||||
| 
 | ||||
| 
 | ||||
| end // if (pt.BTB_ENABLE=1)
 | ||||
|    else begin | ||||
|    assign sel_last_addr_bf = ~exu_flush_final & (~ifc_fetch_req_f | ~ic_hit_f); | ||||
|    assign sel_next_addr_bf = ~exu_flush_final & ifc_fetch_req_f & ic_hit_f; | ||||
| 
 | ||||
| 
 | ||||
|    assign fetch_addr_bf[31:1] = ( ({31{exu_flush_final}} &  exu_flush_path_final[31:1]) | // FLUSH path
 | ||||
|                   ({31{sel_last_addr_bf}} & ifc_fetch_addr_f[31:1]) | // MISS path
 | ||||
|                   ({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path
 | ||||
| 
 | ||||
| end | ||||
|    assign fetch_addr_next[31:1] = {({ifc_fetch_addr_f[31:2]} + 31'b1), fetch_addr_next_1 }; | ||||
|    assign line_wrap = (fetch_addr_next[pt.ICACHE_TAG_INDEX_LO] ^ ifc_fetch_addr_f[pt.ICACHE_TAG_INDEX_LO]); | ||||
| 
 | ||||
|  | @ -186,8 +198,9 @@ import el2_pkg::*; | |||
|    assign idle     = state      == IDLE  ; | ||||
|    assign wfm      = state      == WFM   ; | ||||
| 
 | ||||
|    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_f_ns, fb_write_ns[3:0]}), .dout({fb_full_f, fb_write_f[3:0]})); | ||||
|    rvdffie #(10) fbwrite_ff (.*, .clk(free_l2clk), | ||||
|                           .din( {dma_iccm_stall_any, miss_f, ifc_fetch_req_bf, next_state[1:0], fb_full_f_ns, fb_write_ns[3:0]}), | ||||
|                           .dout({dma_iccm_stall_any_f, miss_a, ifc_fetch_req_f, state[1:0], fb_full_f, fb_write_f[3:0]})); | ||||
| 
 | ||||
|    assign ifu_pmu_fetch_stall = wfm | | ||||
|                 (ifc_fetch_req_bf_raw & | ||||
|  | @ -195,11 +208,10 @@ import el2_pkg::*; | |||
|                   dma_stall)); | ||||
| 
 | ||||
| 
 | ||||
|    rvdff #(1) req_ff (.*, .clk(active_clk), .din(ifc_fetch_req_bf), .dout(ifc_fetch_req_f)); | ||||
| 
 | ||||
|    assign ifc_fetch_addr_bf[31:1] = fetch_addr_bf[31:1]; | ||||
| 
 | ||||
|    rvdffe #(31) faddrf1_ff  (.*, .en(fetch_bf_en), .din(fetch_addr_bf[31:1]), .dout(ifc_fetch_addr_f[31:1])); | ||||
|    rvdffpcie #(31) faddrf1_ff  (.*, .en(fetch_bf_en), .din(fetch_addr_bf[31:1]), .dout(ifc_fetch_addr_f[31:1])); | ||||
| 
 | ||||
| 
 | ||||
|  if (pt.ICCM_ENABLE)  begin | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
|  //********************************************************************************
 | ||||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -27,18 +27,18 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
|   ( | ||||
|    input logic clk, | ||||
|    input logic free_clk,                                            // free clock always except during pause
 | ||||
|    input logic active_clk,                                          // Active always except during pause
 | ||||
|    input logic rst_l, | ||||
|    input logic clk,                                                 // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic active_clk,                                          // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic free_l2clk,                                          // Clock always.                  Through one clock header.  For flops with    second header built in.
 | ||||
|    input logic rst_l,                                               // reset, active low
 | ||||
| 
 | ||||
|    input logic                       exu_flush_final,               // Flush from the pipeline., includes flush lower
 | ||||
|    input logic                       dec_tlu_flush_lower_wb,        // Flush lower from the pipeline.
 | ||||
|    input logic                       dec_tlu_flush_err_wb,          // Flush from the pipeline due to perr.
 | ||||
|    input logic                       dec_tlu_i0_commit_cmt,          // committed i0 instruction
 | ||||
|    input logic                       dec_tlu_force_halt,             // force halt.
 | ||||
|    input logic                       dec_tlu_i0_commit_cmt,         // committed i0 instruction
 | ||||
|    input logic                       dec_tlu_force_halt,            // force halt.
 | ||||
| 
 | ||||
|    input logic [31:1]                ifc_fetch_addr_bf,                 // Fetch Address byte aligned always.      F1 stage.
 | ||||
|    input logic [31:1]                ifc_fetch_addr_bf,             // Fetch Address byte aligned always.      F1 stage.
 | ||||
|    input logic                       ifc_fetch_uncacheable_bf,      // The fetch request is uncacheable space. F1 stage
 | ||||
|    input logic                       ifc_fetch_req_bf,              // Fetch request. Comes with the address.  F1 stage
 | ||||
|    input logic                       ifc_fetch_req_bf_raw,          // Fetch request without some qualifications. Used for clock-gating. F1 stage
 | ||||
|  | @ -46,7 +46,7 @@ import el2_pkg::*; | |||
|    input logic                       ifc_region_acc_fault_bf,       // Access fault. in ICCM region but offset is outside defined ICCM.
 | ||||
|    input logic                       ifc_dma_access_ok,             // It is OK to give dma access to the ICCM. (ICCM is not busy this cycle).
 | ||||
|    input logic                       dec_tlu_fence_i_wb,            // Fence.i instruction is committing. Clear all Icache valids.
 | ||||
|    input logic                       ifu_bp_hit_taken_f,           // Branch is predicted taken. Kill the fetch next cycle.
 | ||||
|    input logic                       ifu_bp_hit_taken_f,            // Branch is predicted taken. Kill the fetch next cycle.
 | ||||
| 
 | ||||
|    input logic                       ifu_bp_inst_mask_f,            // tell ic which valids to kill because of a taken branch, right justified
 | ||||
| 
 | ||||
|  | @ -160,10 +160,10 @@ import el2_pkg::*; | |||
|    input  logic [1:0]                ifu_fetch_val, | ||||
|    // IFU control signals
 | ||||
|    output logic                      ic_hit_f,               // Hit in Icache(if Icache access) or ICCM access( ICCM always has ic_hit_f)
 | ||||
|    output logic                      ic_access_fault_f,      // Access fault (bus error or ICCM access in region but out of offset range).
 | ||||
|    output logic [1:0]                ic_access_fault_f,      // Access fault (bus error or ICCM access in region but out of offset range).
 | ||||
|    output logic [1:0]                ic_access_fault_type_f, // Access fault types
 | ||||
|    output logic                      iccm_rd_ecc_single_err, // This fetch has a single ICCM ecc  error.
 | ||||
|    output logic                      iccm_rd_ecc_double_err, // This fetch has a double ICCM ecc  error.
 | ||||
|    output logic [1:0]                iccm_rd_ecc_double_err, // This fetch has a double ICCM ecc  error.
 | ||||
|    output logic                      ic_error_start,         // This has any I$ errors ( data/tag/ecc/parity )
 | ||||
| 
 | ||||
|    output logic                      ifu_async_error_start,  // Or of the sb iccm, and all the icache errors sent to aligner to stop
 | ||||
|  | @ -184,7 +184,6 @@ import el2_pkg::*; | |||
|    input  logic         scan_mode | ||||
|    ); | ||||
| 
 | ||||
| 
 | ||||
| //  Create different defines for ICACHE and ICCM enable combinations
 | ||||
| 
 | ||||
|  localparam   NUM_OF_BEATS = 8 ; | ||||
|  | @ -219,6 +218,7 @@ import el2_pkg::*; | |||
| 
 | ||||
|    logic           ifu_wr_data_comb_err ; | ||||
|    logic           ifu_byp_data_err_new; | ||||
|    logic  [1:0]    ifu_byp_data_err_f; | ||||
|    logic           ifu_wr_cumulative_err_data; | ||||
|    logic           ifu_wr_cumulative_err; | ||||
|    logic           ifu_wr_data_comb_err_ff; | ||||
|  | @ -229,7 +229,7 @@ import el2_pkg::*; | |||
|    logic           ifc_iccm_access_f ; | ||||
|    logic           ifc_region_acc_fault_f; | ||||
|    logic           ifc_region_acc_fault_final_f; | ||||
|    logic           ifc_bus_acc_fault_f; | ||||
|    logic  [1:0]    ifc_bus_acc_fault_f; | ||||
|    logic           ic_act_miss_f; | ||||
|    logic           ic_miss_under_miss_f; | ||||
|    logic           ic_ignore_2nd_miss_f; | ||||
|  | @ -312,14 +312,12 @@ import el2_pkg::*; | |||
|    logic         ifu_pmu_bus_busy_in; | ||||
|    logic         ic_debug_ict_array_sel_in; | ||||
|    logic         ic_debug_ict_array_sel_ff; | ||||
|    logic         debug_data_clk; | ||||
|    logic         debug_data_clken; | ||||
|    logic         last_data_recieved_in ; | ||||
|    logic         last_data_recieved_ff ; | ||||
| 
 | ||||
|    logic                          ifu_bus_rvalid           ; | ||||
|    logic                          ifu_bus_rvalid_ff        ; | ||||
|    logic                          ifu_bus_rvalid_unq    ; | ||||
|    logic                          ifu_bus_rvalid_unq_ff    ; | ||||
|    logic                          ifu_bus_arready_unq       ; | ||||
|    logic                          ifu_bus_arready_unq_ff    ; | ||||
|  | @ -335,28 +333,28 @@ import el2_pkg::*; | |||
|    logic [63:0]                   ifu_bus_rsp_rdata; | ||||
|    logic [1:0]                    ifu_bus_rsp_opc; | ||||
| 
 | ||||
|   logic [pt.ICACHE_NUM_BEATS-1:0]    write_fill_data; | ||||
|   logic [pt.ICACHE_NUM_BEATS-1:0]    wr_data_c1_clk; | ||||
|   logic [pt.ICACHE_NUM_BEATS-1:0]    ic_miss_buff_data_valid_in; | ||||
|   logic [pt.ICACHE_NUM_BEATS-1:0]    ic_miss_buff_data_valid; | ||||
|   logic [pt.ICACHE_NUM_BEATS-1:0]    ic_miss_buff_data_error_in; | ||||
|   logic [pt.ICACHE_NUM_BEATS-1:0]    ic_miss_buff_data_error; | ||||
|   logic [pt.ICACHE_BEAT_ADDR_HI:1]    byp_fetch_index; | ||||
|   logic [pt.ICACHE_BEAT_ADDR_HI:2]    byp_fetch_index_0; | ||||
|   logic [pt.ICACHE_BEAT_ADDR_HI:2]    byp_fetch_index_1; | ||||
|   logic [pt.ICACHE_BEAT_ADDR_HI:3]    byp_fetch_index_inc; | ||||
|   logic [pt.ICACHE_BEAT_ADDR_HI:2]    byp_fetch_index_inc_0; | ||||
|   logic [pt.ICACHE_BEAT_ADDR_HI:2]    byp_fetch_index_inc_1; | ||||
|   logic          miss_buff_hit_unq_f ; | ||||
|   logic          stream_hit_f ; | ||||
|   logic          stream_miss_f ; | ||||
|   logic          stream_eol_f ; | ||||
|   logic          crit_byp_hit_f ; | ||||
|   logic [pt.IFU_BUS_TAG-1:0] other_tag ; | ||||
|   logic [(2*pt.ICACHE_NUM_BEATS)-1:0] [31:0] ic_miss_buff_data; | ||||
|   logic [63:0] ic_miss_buff_half; | ||||
|   logic        scnd_miss_req, scnd_miss_req_q, scnd_miss_req_ff2; | ||||
|   logic        scnd_miss_req_in; | ||||
|    logic [pt.ICACHE_NUM_BEATS-1:0]    write_fill_data; | ||||
|    logic [pt.ICACHE_NUM_BEATS-1:0]    wr_data_c1_clk; | ||||
|    logic [pt.ICACHE_NUM_BEATS-1:0]    ic_miss_buff_data_valid_in; | ||||
|    logic [pt.ICACHE_NUM_BEATS-1:0]    ic_miss_buff_data_valid; | ||||
|    logic [pt.ICACHE_NUM_BEATS-1:0]    ic_miss_buff_data_error_in; | ||||
|    logic [pt.ICACHE_NUM_BEATS-1:0]    ic_miss_buff_data_error; | ||||
|    logic [pt.ICACHE_BEAT_ADDR_HI:1]    byp_fetch_index; | ||||
|    logic [pt.ICACHE_BEAT_ADDR_HI:2]    byp_fetch_index_0; | ||||
|    logic [pt.ICACHE_BEAT_ADDR_HI:2]    byp_fetch_index_1; | ||||
|    logic [pt.ICACHE_BEAT_ADDR_HI:3]    byp_fetch_index_inc; | ||||
|    logic [pt.ICACHE_BEAT_ADDR_HI:2]    byp_fetch_index_inc_0; | ||||
|    logic [pt.ICACHE_BEAT_ADDR_HI:2]    byp_fetch_index_inc_1; | ||||
|    logic          miss_buff_hit_unq_f ; | ||||
|    logic          stream_hit_f ; | ||||
|    logic          stream_miss_f ; | ||||
|    logic          stream_eol_f ; | ||||
|    logic          crit_byp_hit_f ; | ||||
|    logic [pt.IFU_BUS_TAG-1:0] other_tag ; | ||||
|    logic [(2*pt.ICACHE_NUM_BEATS)-1:0] [31:0] ic_miss_buff_data; | ||||
|    logic [63:0] ic_miss_buff_half; | ||||
|    logic        scnd_miss_req, scnd_miss_req_q; | ||||
|    logic        scnd_miss_req_in; | ||||
| 
 | ||||
| 
 | ||||
|    logic [pt.ICCM_BITS-1:2]                iccm_ecc_corr_index_ff; | ||||
|  | @ -435,6 +433,7 @@ import el2_pkg::*; | |||
|    logic   ic_crit_wd_rdy;         // Critical fetch is ready to be bypassed.
 | ||||
| 
 | ||||
|    logic   ifu_bp_hit_taken_q_f; | ||||
|    logic   ifu_bus_rvalid_unq; | ||||
|    logic   bus_cmd_beat_en; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -443,11 +442,16 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
|    assign fetch_bf_f_c1_clken  = ifc_fetch_req_bf_raw | ifc_fetch_req_f | miss_pending | exu_flush_final | scnd_miss_req; | ||||
|    assign debug_c1_clken        = ic_debug_rd_en | ic_debug_wr_en ; | ||||
|    assign debug_c1_clken       = ic_debug_rd_en | ic_debug_wr_en ; | ||||
|    // C1 - 1 clock pulse for data
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    assign fetch_bf_f_c1_clk = 1'b0; | ||||
|    assign debug_c1_clk      = 1'b0; | ||||
| `else | ||||
|    rvclkhdr fetch_bf_f_c1_cgc    ( .en(fetch_bf_f_c1_clken),     .l1clk(fetch_bf_f_c1_clk), .* ); | ||||
|    rvclkhdr debug_c1_cgc         ( .en(debug_c1_clken),          .l1clk(debug_c1_clk), .* ); | ||||
| `endif | ||||
| 
 | ||||
|    rvclkhdr fetch_bf_f_c1_cgc   ( .en(fetch_bf_f_c1_clken),     .l1clk(fetch_bf_f_c1_clk), .* ); | ||||
|    rvclkhdr debug_c1_cgc         ( .en(debug_c1_clken),     .l1clk(debug_c1_clk), .* ); | ||||
| 
 | ||||
| // ------ end clock gating section ------------------------
 | ||||
| 
 | ||||
|  | @ -529,7 +533,7 @@ import el2_pkg::*; | |||
|          end | ||||
|       endcase | ||||
|    end | ||||
|    rvdffs #(($bits(miss_state_t))) miss_state_ff (.clk(free_clk), .din(miss_nxtstate), .dout({miss_state}), .en(miss_state_en),   .*); | ||||
|    rvdffs #(($bits(miss_state_t))) miss_state_ff (.clk(active_clk), .din(miss_nxtstate), .dout({miss_state}), .en(miss_state_en),   .*); | ||||
| 
 | ||||
|   logic    sel_hold_imb     ; | ||||
| 
 | ||||
|  | @ -554,14 +558,14 @@ import el2_pkg::*; | |||
| 
 | ||||
|    assign sel_hold_imb_scnd                                =((miss_state == SCND_MISS) | ic_miss_under_miss_f) & ~flush_final_f ; | ||||
|    assign way_status_mb_scnd_in[pt.ICACHE_STATUS_BITS-1:0] = (miss_state == SCND_MISS) ? way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0] : {way_status[pt.ICACHE_STATUS_BITS-1:0]} ; | ||||
|    assign tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0]          = (miss_state == SCND_MISS) ? tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0]          : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags}}); | ||||
|    assign tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0]          = (miss_state == SCND_MISS) ? tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0]          : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags & ~exu_flush_final}}); | ||||
|    assign uncacheable_miss_scnd_in   = sel_hold_imb_scnd ? uncacheable_miss_scnd_ff : ifc_fetch_uncacheable_bf ; | ||||
| 
 | ||||
| 
 | ||||
|    rvdff #(1)  unc_miss_scnd_ff    (.*, .clk(fetch_bf_f_c1_clk), .din (uncacheable_miss_scnd_in), .dout(uncacheable_miss_scnd_ff)); | ||||
|    rvdff #(31) imb_f_scnd_ff       (.*, .clk(fetch_bf_f_c1_clk), .din ({imb_scnd_in[31:1]}), .dout({imb_scnd_ff[31:1]})); | ||||
|    rvdff #(pt.ICACHE_STATUS_BITS)  mb_rep_wayf2_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({way_status_mb_scnd_in[pt.ICACHE_STATUS_BITS-1:0]}), .dout({way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0]})); | ||||
|    rvdff #(pt.ICACHE_NUM_WAYS)     mb_tagv_scnd_ff      (.*, .clk(fetch_bf_f_c1_clk), .din ({tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0]}), .dout({tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0]})); | ||||
|    rvdff_fpga #(1)  unc_miss_scnd_ff    (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din (uncacheable_miss_scnd_in), .dout(uncacheable_miss_scnd_ff)); | ||||
|    rvdffpcie #(31) imb_f_scnd_ff       (.*, .en(fetch_bf_f_c1_clken),  .din ({imb_scnd_in[31:1]}), .dout({imb_scnd_ff[31:1]})); | ||||
|    rvdff_fpga #(pt.ICACHE_STATUS_BITS)  mb_rep_wayf2_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din ({way_status_mb_scnd_in[pt.ICACHE_STATUS_BITS-1:0]}), .dout({way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0]})); | ||||
|    rvdff_fpga #(pt.ICACHE_NUM_WAYS)     mb_tagv_scnd_ff      (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din ({tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0]}), .dout({tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0]})); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -597,45 +601,40 @@ import el2_pkg::*; | |||
|                                                          miss_pending                            ? way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0] : | ||||
|                                                                                                   {way_status[pt.ICACHE_STATUS_BITS-1:0]} ; | ||||
|    assign tagv_mb_in[pt.ICACHE_NUM_WAYS-1:0]          = scnd_miss_req ? (tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0] | ({pt.ICACHE_NUM_WAYS {scnd_miss_index_match}} & replace_way_mb_any[pt.ICACHE_NUM_WAYS-1:0])) : | ||||
|                                                          miss_pending ? tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0]  : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags}}) ; | ||||
|                                                          miss_pending ? tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0]  : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags & ~exu_flush_final}}) ; | ||||
| 
 | ||||
|    assign reset_ic_in           = miss_pending & ~scnd_miss_req_q &  (reset_all_tags |  reset_ic_ff) ; | ||||
| 
 | ||||
|    rvdff #(1)  reset_ic_f (.*, .clk(free_clk), .din (reset_ic_in), .dout(reset_ic_ff)); | ||||
|    rvdff #(1)  uncache_ff (.*, .clk(active_clk), .din (ifc_fetch_uncacheable_bf), .dout(fetch_uncacheable_ff)); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    rvdff #(31) ifu_fetch_addr_f_ff (.*, | ||||
|                     .clk (fetch_bf_f_c1_clk), | ||||
|                     .din ({ifc_fetch_addr_bf[31:1]}), | ||||
|                     .dout({ifu_fetch_addr_int_f[31:1]})); | ||||
|    rvdffpcie #(31) ifu_fetch_addr_f_ff (.*, .en(fetch_bf_f_c1_clken), .din ({ifc_fetch_addr_bf[31:1]}), .dout({ifu_fetch_addr_int_f[31:1]})); | ||||
| 
 | ||||
|    assign vaddr_f[pt.ICACHE_BEAT_ADDR_HI:1] = ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:1] ; | ||||
| 
 | ||||
|    rvdff #(1)  unc_miss_ff     (.*, .clk(fetch_bf_f_c1_clk), .din (uncacheable_miss_in), .dout(uncacheable_miss_ff)); | ||||
|    rvdff #(31) imb_f_ff       (.*, .clk(fetch_bf_f_c1_clk), .din ({imb_in[31:1]}), .dout({imb_ff[31:1]})); | ||||
|    rvdffpcie #(31) imb_f_ff        (.*, .en(fetch_bf_f_c1_clken), .din (imb_in[31:1]), .dout(imb_ff[31:1])); | ||||
|    rvdff_fpga #(1) unc_miss_ff     (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk),  .din ( uncacheable_miss_in),               .dout( uncacheable_miss_ff)); | ||||
| 
 | ||||
| 
 | ||||
|    assign miss_addr_in[31:pt.ICACHE_BEAT_ADDR_HI+1]      = (~miss_pending                    ) ? imb_ff[31:pt.ICACHE_BEAT_ADDR_HI+1] : | ||||
|                                                            (                scnd_miss_req_q  ) ? imb_scnd_ff[31:pt.ICACHE_BEAT_ADDR_HI+1] : miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1] ; | ||||
| 
 | ||||
|    rvdff #(31-pt.ICACHE_BEAT_ADDR_HI) miss_f_ff       (.*, .clk(busclk_reset), .din ({miss_addr_in[31:pt.ICACHE_BEAT_ADDR_HI+1]}), .dout({miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1]})); | ||||
| 
 | ||||
|    rvdfflie #(.WIDTH(31-pt.ICACHE_BEAT_ADDR_HI),.LEFT(31-pt.ICACHE_BEAT_ADDR_HI-8)) miss_f_ff       (.*, .en(bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt), .din ({miss_addr_in[31:pt.ICACHE_BEAT_ADDR_HI+1]}), .dout({miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1]})); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    rvdff #(pt.ICACHE_STATUS_BITS)  mb_rep_wayf2_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({way_status_mb_in[pt.ICACHE_STATUS_BITS-1:0]}), .dout({way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0]})); | ||||
| 
 | ||||
|    rvdff #(pt.ICACHE_NUM_WAYS)  mb_tagv_ff      (.*, .clk(fetch_bf_f_c1_clk), .din ({tagv_mb_in[pt.ICACHE_NUM_WAYS-1:0]}), .dout({tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0]})); | ||||
| 
 | ||||
|    rvdff_fpga #(pt.ICACHE_STATUS_BITS)  mb_rep_wayf2_ff (.*, .clk(fetch_bf_f_c1_clk),  .clken(fetch_bf_f_c1_clken), .rawclk(clk),  .din ({way_status_mb_in[pt.ICACHE_STATUS_BITS-1:0]}), .dout({way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0]})); | ||||
|    rvdff_fpga #(pt.ICACHE_NUM_WAYS)     mb_tagv_ff      (.*, .clk(fetch_bf_f_c1_clk),  .clken(fetch_bf_f_c1_clken), .rawclk(clk),  .din ({tagv_mb_in[pt.ICACHE_NUM_WAYS-1:0]}), .dout({tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0]})); | ||||
| 
 | ||||
|    assign ifc_fetch_req_qual_bf  = ifc_fetch_req_bf  & ~((miss_state == CRIT_WRD_RDY) & flush_final_f) & ~stream_miss_f ;// & ~exu_flush_final ;
 | ||||
|    rvdff #(1) fetch_req_f_ff  (.*, .clk(active_clk),  .din(ifc_fetch_req_qual_bf), .dout(ifc_fetch_req_f_raw)); | ||||
| 
 | ||||
|    assign ifc_fetch_req_f       = ifc_fetch_req_f_raw & ~exu_flush_final ; | ||||
| 
 | ||||
|    rvdff #(1) ifu_iccm_acc_ff     (.*, .clk(fetch_bf_f_c1_clk), .din(ifc_iccm_access_bf),      .dout(ifc_iccm_access_f)); | ||||
|    rvdff #(1) ifu_iccm_reg_acc_ff (.*, .clk(fetch_bf_f_c1_clk), .din(ifc_region_acc_fault_final_bf), .dout(ifc_region_acc_fault_final_f)); | ||||
|    rvdff #(1) rgn_acc_ff          (.*, .clk(fetch_bf_f_c1_clk), .din(ifc_region_acc_fault_bf),       .dout(ifc_region_acc_fault_f)); | ||||
|    rvdff_fpga #(1) ifu_iccm_acc_ff     (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk),   .din(ifc_iccm_access_bf),      .dout(ifc_iccm_access_f)); | ||||
|    rvdff_fpga #(1) ifu_iccm_reg_acc_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk),   .din(ifc_region_acc_fault_final_bf), .dout(ifc_region_acc_fault_final_f)); | ||||
|    rvdff_fpga #(1) rgn_acc_ff          (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk),   .din(ifc_region_acc_fault_bf),       .dout(ifc_region_acc_fault_f)); | ||||
| 
 | ||||
| 
 | ||||
|    assign ifu_ic_req_addr_f[31:3]  = {miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1] , ic_req_addr_bits_hi_3[pt.ICACHE_BEAT_ADDR_HI:3] }; | ||||
|  | @ -654,7 +653,6 @@ import el2_pkg::*; | |||
| 
 | ||||
|   assign ic_rw_addr[31:1]      = ifu_ic_rw_int_addr[31:1] ; | ||||
| 
 | ||||
|   rvdff #(1) sel_mb_ff (.*, .clk(free_clk),  .din (sel_mb_addr), .dout(sel_mb_addr_ff)); | ||||
| 
 | ||||
| if (pt.ICACHE_ECC == 1) begin: icache_ecc_1 | ||||
|    logic [6:0]       ic_wr_ecc; | ||||
|  | @ -669,7 +667,7 @@ if (pt.ICACHE_ECC == 1) begin: icache_ecc_1 | |||
|                            .din    (ic_miss_buff_half[63:0]), | ||||
|                            .ecc_out(ic_miss_buff_ecc[6:0])); | ||||
| 
 | ||||
|    for (genvar i=0; i < 32'(pt.ICACHE_BANKS_WAY) ; i++) begin : ic_wr_data_loop | ||||
|    for (genvar i=0; i < pt.ICACHE_BANKS_WAY ; i++) begin : ic_wr_data_loop | ||||
|       assign ic_wr_data[i][70:0]  =  ic_wr_16bytes_data[((71*i)+70): (71*i)]; | ||||
|    end | ||||
| 
 | ||||
|  | @ -682,13 +680,15 @@ if (pt.ICACHE_ECC == 1) begin: icache_ecc_1 | |||
|   assign ifu_ic_debug_rd_data_in[70:0] = ic_debug_ict_array_sel_ff ? {2'b0,ictag_debug_rd_data[25:21],32'b0,ictag_debug_rd_data[20:0],{7-pt.ICACHE_STATUS_BITS{1'b0}}, way_status[pt.ICACHE_STATUS_BITS-1:0],3'b0,ic_debug_tag_val_rd_out} : | ||||
|                                                                      ic_debug_rd_data[70:0]; | ||||
| 
 | ||||
|   rvdff #(71) ifu_debug_data_ff (.*, .clk (debug_data_clk), | ||||
|                     .din ({ | ||||
|                            ifu_ic_debug_rd_data_in[70:0] | ||||
|                           }), | ||||
|                     .dout({ | ||||
|                            ifu_ic_debug_rd_data[70:0] | ||||
|                            })); | ||||
|   rvdffe #(71) ifu_debug_data_ff (.*, | ||||
|                                   .en (debug_data_clken), | ||||
|                                   .din ({ | ||||
|                                          ifu_ic_debug_rd_data_in[70:0] | ||||
|                                          }), | ||||
|                                   .dout({ | ||||
|                                          ifu_ic_debug_rd_data[70:0] | ||||
|                                          }) | ||||
|                                   ); | ||||
| 
 | ||||
|   assign ic_wr_16bytes_data[141:0] =  ifu_bus_rid_ff[0] ? {ic_wr_ecc[6:0] , ifu_bus_rdata_ff[63:0] ,  ic_miss_buff_ecc[6:0] , ic_miss_buff_half[63:0] } : | ||||
|                                                         {ic_miss_buff_ecc[6:0] ,  ic_miss_buff_half[63:0] , ic_wr_ecc[6:0] , ifu_bus_rdata_ff[63:0] } ; | ||||
|  | @ -709,7 +709,7 @@ else begin : icache_parity_1 | |||
| 
 | ||||
| 
 | ||||
|    for (genvar i=0; i < pt.ICACHE_BANKS_WAY ; i++) begin : ic_wr_data_loop | ||||
|       assign ic_wr_data[i][67:0]  =  ic_wr_16bytes_data[((68*i)+67): (68*i)]; | ||||
|       assign ic_wr_data[i][70:0]  =  {3'b0, ic_wr_16bytes_data[((68*i)+67): (68*i)]}; | ||||
|    end | ||||
| 
 | ||||
| 
 | ||||
|  | @ -722,13 +722,15 @@ else begin : icache_parity_1 | |||
|    assign ifu_ic_debug_rd_data_in[70:0] = ic_debug_ict_array_sel_ff ? {6'b0,ictag_debug_rd_data[21],32'b0,ictag_debug_rd_data[20:0],{7-pt.ICACHE_STATUS_BITS{1'b0}},way_status[pt.ICACHE_STATUS_BITS-1:0],3'b0,ic_debug_tag_val_rd_out} : | ||||
|                                                                       ic_debug_rd_data[70:0] ; | ||||
| 
 | ||||
|    rvdff #(71) ifu_debug_data_ff (.*, .clk (debug_data_clk), | ||||
|                     .din ({ | ||||
|                            ifu_ic_debug_rd_data_in[70:0] | ||||
|                           }), | ||||
|                     .dout({ | ||||
|                            ifu_ic_debug_rd_data[70:0] | ||||
|                            })); | ||||
|    rvdffe #(71) ifu_debug_data_ff (.*, | ||||
|                                    .en (debug_data_clken), | ||||
|                                    .din ({ | ||||
|                                           ifu_ic_debug_rd_data_in[70:0] | ||||
|                                           }), | ||||
|                                    .dout({ | ||||
|                                           ifu_ic_debug_rd_data[70:0] | ||||
|                                           }) | ||||
|                                    ); | ||||
| 
 | ||||
|    assign ic_wr_16bytes_data[135:0] =  ifu_bus_rid_ff[0] ? {ic_wr_parity[3:0] , ifu_bus_rdata_ff[63:0] ,  ic_miss_buff_parity[3:0] , ic_miss_buff_half[63:0] } : | ||||
|                                                         {ic_miss_buff_parity[3:0] ,  ic_miss_buff_half[63:0] , ic_wr_parity[3:0] , ifu_bus_rdata_ff[63:0] } ; | ||||
|  | @ -740,11 +742,9 @@ end | |||
|   assign ifu_wr_cumulative_err      = (ifu_wr_data_comb_err | ifu_wr_data_comb_err_ff) & ~reset_beat_cnt; | ||||
|   assign ifu_wr_cumulative_err_data =  ifu_wr_data_comb_err | ifu_wr_data_comb_err_ff ; | ||||
| 
 | ||||
|   rvdff #(1) cumul_err_ff (.*, .clk(free_clk),  .din (ifu_wr_cumulative_err), .dout(ifu_wr_data_comb_err_ff)); | ||||
| 
 | ||||
| 
 | ||||
|   assign sel_byp_data     =  (ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK)) & ~ifu_byp_data_err_new; | ||||
|   assign sel_ic_data      = ~(ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK)) & ~fetch_req_iccm_f ; | ||||
|   assign sel_byp_data     =  (ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK)); | ||||
|   assign sel_ic_data      = ~(ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK) | (miss_state == MISS_WAIT)) & ~fetch_req_iccm_f & ~ifc_region_acc_fault_final_f; | ||||
| 
 | ||||
|  if (pt.ICCM_ICACHE==1) begin: iccm_icache | ||||
|   assign sel_iccm_data    =  fetch_req_iccm_f  ; | ||||
|  | @ -779,14 +779,14 @@ if (pt.NO_ICCM_NO_ICACHE == 1 ) begin: no_iccm_no_icache | |||
| end | ||||
| 
 | ||||
| 
 | ||||
|   assign ifc_bus_acc_fault_f   =  ic_byp_hit_f & ifu_byp_data_err_new ; | ||||
|   assign ifc_bus_acc_fault_f[1:0]   =  {2{ic_byp_hit_f}} & ifu_byp_data_err_f[1:0] ; | ||||
|   assign ic_data_f[31:0]      = ic_final_data[31:0]; | ||||
| 
 | ||||
| 
 | ||||
| rvdff #(1) flush_final_ff (.*, .clk(free_clk), .din({exu_flush_final}), .dout({flush_final_f})); | ||||
| 
 | ||||
| assign fetch_req_f_qual       = ic_hit_f & ~exu_flush_final; | ||||
| assign ic_access_fault_f  = (ifc_region_acc_fault_final_f | ifc_bus_acc_fault_f)  & ~exu_flush_final; | ||||
| assign ic_access_fault_type_f[1:0] = iccm_rd_ecc_double_err        ? 2'b01 : | ||||
| assign ic_access_fault_f[1:0]  = ({2{ifc_region_acc_fault_final_f}} | ifc_bus_acc_fault_f[1:0])  & {2{~exu_flush_final}}; | ||||
| assign ic_access_fault_type_f[1:0] = |iccm_rd_ecc_double_err       ? 2'b01 : | ||||
|                                      ifc_region_acc_fault_f        ? 2'b10 : | ||||
|                                      ifc_region_acc_fault_memory_f ? 2'b11 :  2'b00 ; | ||||
| 
 | ||||
|  | @ -802,28 +802,33 @@ assign two_byte_instr    =  (ic_data_f[1:0] != 2'b11 )  ; | |||
|      logic [63:0]       ic_miss_buff_data_in; | ||||
|      assign ic_miss_buff_data_in[63:0] = ifu_bus_rsp_rdata[63:0]; | ||||
| 
 | ||||
|      for (genvar i=0; i<32'(pt.ICACHE_NUM_BEATS); i++) begin :  wr_flop | ||||
|        assign write_fill_data[i]        =   bus_ifu_wr_en & (  (pt.IFU_BUS_TAG)'(i)  == ifu_bus_rsp_tag[pt.IFU_BUS_TAG-1:0]); | ||||
|        rvclkhdr data_c1_cgc  ( .en(write_fill_data[i]),    .l1clk(wr_data_c1_clk[i]), .* ); | ||||
|        rvdff #(32) byp_data_0_ff (.*, | ||||
|                  .clk (wr_data_c1_clk[i]), | ||||
|                  .din (ic_miss_buff_data_in[31:0]), | ||||
|                  .dout(ic_miss_buff_data[i*2][31:0])); | ||||
|      for (genvar i=0; i<pt.ICACHE_NUM_BEATS; i++) begin :  wr_flop | ||||
| 
 | ||||
|        rvdff #(32) byp_data_1_ff (.*, | ||||
|                  .clk (wr_data_c1_clk[i]), | ||||
|                  .din (ic_miss_buff_data_in[63:32]), | ||||
|                  .dout(ic_miss_buff_data[i*2+1][31:0])); | ||||
|         assign write_fill_data[i]        =   bus_ifu_wr_en & (  (pt.IFU_BUS_TAG)'(i)  == ifu_bus_rsp_tag[pt.IFU_BUS_TAG-1:0]); | ||||
| 
 | ||||
|         rvdffe #(32) byp_data_0_ff (.*, | ||||
|                                     .en (write_fill_data[i]), | ||||
|                                     .din (ic_miss_buff_data_in[31:0]), | ||||
|                                     .dout(ic_miss_buff_data[i*2][31:0]) | ||||
|                                     ); | ||||
| 
 | ||||
|         rvdffe #(32) byp_data_1_ff (.*, | ||||
|                                     .en (write_fill_data[i]), | ||||
|                                     .din (ic_miss_buff_data_in[63:32]), | ||||
|                                     .dout(ic_miss_buff_data[i*2+1][31:0]) | ||||
|                                     ); | ||||
| 
 | ||||
|         assign ic_miss_buff_data_valid_in[i]  = write_fill_data[i] ? 1'b1  : (ic_miss_buff_data_valid[i]  & ~ic_act_miss_f) ; | ||||
| 
 | ||||
|         rvdff #(1) byp_data_valid_ff (.*, | ||||
|                   .clk (free_clk), | ||||
|                   .clk (active_clk), | ||||
|                   .din (ic_miss_buff_data_valid_in[i]), | ||||
|                   .dout(ic_miss_buff_data_valid[i])); | ||||
| 
 | ||||
|         assign ic_miss_buff_data_error_in[i]  = write_fill_data[i] ? bus_ifu_wr_data_error  : (ic_miss_buff_data_error[i]  & ~ic_act_miss_f) ; | ||||
| 
 | ||||
|         rvdff #(1) byp_data_error_ff (.*, | ||||
|                   .clk (free_clk), | ||||
|                   .clk (active_clk), | ||||
|                   .din (ic_miss_buff_data_error_in[i] ), | ||||
|                   .dout(ic_miss_buff_data_error[i])); | ||||
|      end | ||||
|  | @ -852,7 +857,6 @@ assign two_byte_instr    =  (ic_data_f[1:0] != 2'b11 )  ; | |||
|                                      (                        crit_wd_byp_ok_ff   & ~uncacheable_miss_ff &  ~exu_flush_final & ~ifu_bp_hit_taken_q_f) | | ||||
|                                      (ic_crit_wd_rdy_new_ff & ~fetch_req_icache_f & crit_wd_byp_ok_ff    &  ~exu_flush_final) ; | ||||
| 
 | ||||
|    rvdff #(1)           crit_wd_new_ff      (.*, .clk(free_clk),  .din(ic_crit_wd_rdy_new_in),   .dout(ic_crit_wd_rdy_new_ff)); | ||||
| 
 | ||||
|   assign byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:1]          =    ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:1]       ; | ||||
|   assign byp_fetch_index_0[pt.ICACHE_BEAT_ADDR_HI:2]        =   {ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:3],1'b0} ; | ||||
|  | @ -866,6 +870,13 @@ assign two_byte_instr    =  (ic_data_f[1:0] != 2'b11 )  ; | |||
|                                  ( ifu_fetch_addr_int_f[2] &  ~ifu_fetch_addr_int_f[1] &                                                                           ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] )  | | ||||
|                                  ( ifu_fetch_addr_int_f[2] &   ifu_fetch_addr_int_f[1] & (ic_miss_buff_data_error[byp_fetch_index_inc[pt.ICACHE_BEAT_ADDR_HI:3]] | ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] )) ; | ||||
| 
 | ||||
|   assign  ifu_byp_data_err_f[1:0]  =   (ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] )  ? 2'b11 : | ||||
|                                       ( ifu_fetch_addr_int_f[2] &  ifu_fetch_addr_int_f[1] &   ~(ic_miss_buff_data_error[byp_fetch_index[pt.ICACHE_BEAT_ADDR_HI:3]] ) & (~miss_wrap_f & ic_miss_buff_data_error[byp_fetch_index_inc[pt.ICACHE_BEAT_ADDR_HI:3]])) ? 2'b10 : 2'b00; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   assign ic_byp_data_only_pre_new[79:0] =  ({80{~ifu_fetch_addr_int_f[2]}} &   {ic_miss_buff_data[byp_fetch_index_inc_0][15:0],ic_miss_buff_data[byp_fetch_index_1][31:0]     , ic_miss_buff_data[byp_fetch_index_0][31:0]}) | | ||||
|                                            ({80{ ifu_fetch_addr_int_f[2]}} &   {ic_miss_buff_data[byp_fetch_index_inc_1][15:0],ic_miss_buff_data[byp_fetch_index_inc_0][31:0] , ic_miss_buff_data[byp_fetch_index_1][31:0]}) ; | ||||
| 
 | ||||
|  | @ -901,7 +912,8 @@ assign ic_miss_buff_half[63:0]    = {ic_miss_buff_data[{other_tag,1'b1}],ic_miss | |||
| /////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| 
 | ||||
| assign ic_rd_parity_final_err = ic_tag_perr & sel_ic_data & ~(ifc_region_acc_fault_final_f | ifc_bus_acc_fault_f) ; | ||||
| assign ic_rd_parity_final_err = ic_tag_perr & ~exu_flush_final & sel_ic_data & ~(ifc_region_acc_fault_final_f | (|ifc_bus_acc_fault_f)) & | ||||
|                                       (fetch_req_icache_f & ~reset_all_tags & (~miss_pending | (miss_state==HIT_U_MISS)) & ~sel_mb_addr_ff); | ||||
| 
 | ||||
| logic [pt.ICACHE_NUM_WAYS-1:0]                   perr_err_inv_way; | ||||
| logic [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]   perr_ic_index_ff; | ||||
|  | @ -910,13 +922,12 @@ logic                                         perr_sb_write_status   ; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    rvdffs #(pt.ICACHE_INDEX_HI-pt.ICACHE_TAG_INDEX_LO+1) perr_dat_ff    (.clk(active_clk), .din(ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]), .dout(perr_ic_index_ff[pt.ICACHE_INDEX_HI : pt.ICACHE_TAG_INDEX_LO]), .en(perr_sb_write_status),  .*); | ||||
|    rvdffe #(.WIDTH(pt.ICACHE_INDEX_HI-pt.ICACHE_TAG_INDEX_LO+1),.OVERRIDE(1)) perr_dat_ff    (.din(ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]), .dout(perr_ic_index_ff[pt.ICACHE_INDEX_HI : pt.ICACHE_TAG_INDEX_LO]), .en(perr_sb_write_status),  .*); | ||||
| 
 | ||||
|    assign perr_err_inv_way[pt.ICACHE_NUM_WAYS-1:0]   =  {pt.ICACHE_NUM_WAYS{perr_sel_invalidate}} ; | ||||
|    assign iccm_correct_ecc     = (perr_state == ECC_CORR); | ||||
|    assign dma_sb_err_state     = (perr_state == DMA_SB_ERR); | ||||
|    assign iccm_buf_correct_ecc = iccm_correct_ecc & ~dma_sb_err_state_ff; | ||||
|     rvdff  #((1))  dma_sb_err_ff  (.clk(active_clk), .din(dma_sb_err_state),   .dout(dma_sb_err_state_ff),   .*); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -965,7 +976,8 @@ logic                                         perr_sb_write_status   ; | |||
|          end | ||||
|       endcase | ||||
|    end | ||||
|    rvdffs #(($bits(perr_state_t))) perr_state_ff (.clk(free_clk), .din(perr_nxtstate), .dout({perr_state}), .en(perr_state_en),   .*); | ||||
| 
 | ||||
|    rvdffs #(($bits(perr_state_t))) perr_state_ff (.clk(active_clk), .din(perr_nxtstate), .dout({perr_state}), .en(perr_state_en),   .*); | ||||
| 
 | ||||
|    //////////////////////////////////// Create stop fetch State Machine /////////////////////////
 | ||||
|    //////////////////////////////////// Create stop fetch State Machine /////////////////////////
 | ||||
|  | @ -1013,29 +1025,30 @@ logic                                         perr_sb_write_status   ; | |||
|          end | ||||
|       endcase | ||||
|    end | ||||
|    rvdffs #(($bits(err_stop_state_t))) err_stop_state_ff (.clk(free_clk), .din(err_stop_nxtstate), .dout({err_stop_state}), .en(err_stop_state_en),   .*); | ||||
|    rvdffs #(($bits(err_stop_state_t))) err_stop_state_ff (.clk(active_clk), .din(err_stop_nxtstate), .dout({err_stop_state}), .en(err_stop_state_en),   .*); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    assign bus_ifu_bus_clk_en =  ifu_bus_clk_en ; | ||||
| 
 | ||||
|    rvclkhdr bus_clk_f(.en(bus_ifu_bus_clk_en), | ||||
|                    .l1clk(busclk), .*); | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    assign busclk = 1'b0; | ||||
|    assign busclk_force = 1'b0; | ||||
| `else | ||||
|    rvclkhdr bus_clk_f(.en(bus_ifu_bus_clk_en), .l1clk(busclk), .*); | ||||
|    rvclkhdr bus_clk(.en(bus_ifu_bus_clk_en | dec_tlu_force_halt), .l1clk(busclk_force), .*); | ||||
| `endif | ||||
| 
 | ||||
| 
 | ||||
|    rvclkhdr bus_clk(.en(bus_ifu_bus_clk_en | dec_tlu_force_halt), | ||||
|                    .l1clk(busclk_force), .*); | ||||
| 
 | ||||
|    rvdff #(1)           bus_clken_ff     (.*, .clk(free_clk), .din(bus_ifu_bus_clk_en), .dout(bus_ifu_bus_clk_en_ff)); | ||||
|    rvdff #(1)           scnd_mss_req_ff  (.*, .clk(free_clk), .din(scnd_miss_req_in),   .dout(scnd_miss_req_q)); | ||||
|    rvdff #(1)           scnd_mss_req_ff2 (.*, .clk(free_clk), .din(scnd_miss_req),      .dout(scnd_miss_req_ff2)); | ||||
|    assign  scnd_miss_req = scnd_miss_req_q & ~exu_flush_final; | ||||
| 
 | ||||
|    assign  ifc_bus_ic_req_ff_in  = (ic_act_miss_f | bus_cmd_req_hold | ifu_bus_cmd_valid) & ~dec_tlu_force_halt & ~((bus_cmd_beat_count== {pt.ICACHE_BEAT_BITS{1'b1}}) & ifu_bus_cmd_valid & ifu_bus_cmd_ready & miss_pending); | ||||
|    rvdff #(1) bus_ic_req_ff2(.*, .clk(busclk_force), .din(ifc_bus_ic_req_ff_in), .dout(ifu_bus_cmd_valid)); | ||||
| 
 | ||||
|    rvdff_fpga #(1) bus_ic_req_ff2(.*, .clk(busclk_force), .clken(bus_ifu_bus_clk_en | dec_tlu_force_halt), .rawclk(clk), .din(ifc_bus_ic_req_ff_in), .dout(ifu_bus_cmd_valid)); | ||||
| 
 | ||||
|    assign    bus_cmd_req_in  = (ic_act_miss_f | bus_cmd_req_hold) & ~bus_cmd_sent & ~dec_tlu_force_halt ; // hold until first command sent
 | ||||
|    // changes for making the bus blocking
 | ||||
|    rvdff #(1)  bus_cmd_req_ff  (.*,  .clk(free_clk), .din(bus_cmd_req_in), .dout(bus_cmd_req_hold)); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     // AXI command signals
 | ||||
|  | @ -1044,7 +1057,7 @@ logic                                         perr_sb_write_status   ; | |||
|     assign ifu_axi_arid[pt.IFU_BUS_TAG-1:0] = ((pt.IFU_BUS_TAG)'(bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0])) & {pt.IFU_BUS_TAG{ifu_bus_cmd_valid}}; | ||||
|     assign ifu_axi_araddr[31:0]          =   {ifu_ic_req_addr_f[31:3],3'b0}  & {32{ifu_bus_cmd_valid}}; | ||||
|     assign ifu_axi_arsize[2:0]           =  3'b011; | ||||
|     assign ifu_axi_arprot[2:0]           = '0; | ||||
|     assign ifu_axi_arprot[2:0]           = 3'b101; | ||||
|     assign ifu_axi_arcache[3:0]          = 4'b1111; | ||||
|     assign ifu_axi_arregion[3:0]         = ifu_ic_req_addr_f[31:28]; | ||||
|     assign ifu_axi_arlen[7:0]            = '0; | ||||
|  | @ -1077,12 +1090,12 @@ logic                                         perr_sb_write_status   ; | |||
|    assign ifu_bus_rvalid_unq      =  ifu_axi_rvalid ; | ||||
|    assign ifu_bus_arvalid         =  ifu_axi_arvalid ; | ||||
| 
 | ||||
|    rvdff #(1)               bus_rdy_ff      (.*, .clk(busclk), .din(ifu_bus_arready_unq),            .dout(ifu_bus_arready_unq_ff)); | ||||
|    rvdff #(1)               bus_rsp_vld_ff  (.*, .clk(busclk), .din(ifu_bus_rvalid_unq),             .dout(ifu_bus_rvalid_unq_ff)); | ||||
|    rvdff #(1)               bus_cmd_ff      (.*, .clk(busclk), .din(ifu_bus_arvalid),                .dout(ifu_bus_arvalid_ff)); | ||||
|    rvdff #(2)               bus_rsp_cmd_ff  (.*, .clk(busclk), .din(ifu_axi_rresp[1:0]),             .dout(ifu_bus_rresp_ff[1:0])); | ||||
|    rvdff #(64)              bus_data_ff     (.*, .clk(busclk), .din(ifu_axi_rdata[63:0]),            .dout(ifu_bus_rdata_ff[63:0])); | ||||
|    rvdff #(pt.IFU_BUS_TAG)  bus_rsp_tag_ff  (.*, .clk(busclk), .din(ifu_axi_rid[pt.IFU_BUS_TAG-1:0]),.dout(ifu_bus_rid_ff[pt.IFU_BUS_TAG-1:0])); | ||||
|    rvdff_fpga #(1)               bus_rdy_ff      (.*, .clk(busclk),  .clken(bus_ifu_bus_clk_en), .rawclk(clk), .din(ifu_bus_arready_unq),            .dout(ifu_bus_arready_unq_ff)); | ||||
|    rvdff_fpga #(1)               bus_rsp_vld_ff  (.*, .clk(busclk),  .clken(bus_ifu_bus_clk_en), .rawclk(clk), .din(ifu_bus_rvalid_unq),             .dout(ifu_bus_rvalid_unq_ff)); | ||||
|    rvdff_fpga #(1)               bus_cmd_ff      (.*, .clk(busclk),  .clken(bus_ifu_bus_clk_en), .rawclk(clk), .din(ifu_bus_arvalid),                .dout(ifu_bus_arvalid_ff)); | ||||
|    rvdff_fpga #(2)               bus_rsp_cmd_ff  (.*, .clk(busclk),  .clken(bus_ifu_bus_clk_en), .rawclk(clk), .din(ifu_axi_rresp[1:0]),             .dout(ifu_bus_rresp_ff[1:0])); | ||||
|    rvdff_fpga #(pt.IFU_BUS_TAG)  bus_rsp_tag_ff  (.*, .clk(busclk),  .clken(bus_ifu_bus_clk_en), .rawclk(clk), .din(ifu_axi_rid[pt.IFU_BUS_TAG-1:0]),.dout(ifu_bus_rid_ff[pt.IFU_BUS_TAG-1:0])); | ||||
|    rvdffe #(64)                  bus_data_ff     (.*, .clk(clk),     .din(ifu_axi_rdata[63:0]),            .dout(ifu_bus_rdata_ff[63:0]), .en(ifu_bus_clk_en & ifu_axi_rvalid)); | ||||
| 
 | ||||
|    assign ifu_bus_cmd_ready = ifu_axi_arready ; | ||||
|    assign ifu_bus_rsp_valid = ifu_axi_rvalid ; | ||||
|  | @ -1099,11 +1112,7 @@ logic                                         perr_sb_write_status   ; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    // Create write signals so we can write to the miss-buffer directly from
 | ||||
|    // the bus.
 | ||||
|    // Create write signals so we can write to the miss-buffer directly from the bus.
 | ||||
| 
 | ||||
|    assign ifu_bus_rvalid            =  ifu_bus_rsp_valid & bus_ifu_bus_clk_en ; | ||||
| 
 | ||||
|  | @ -1122,10 +1131,9 @@ logic                                         perr_sb_write_status   ; | |||
|                                                           ({pt.ICACHE_BEAT_BITS{bus_inc_data_beat_cnt}}   & (bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0] + {{pt.ICACHE_BEAT_BITS-1{1'b0}},1'b1})) | | ||||
|                                                           ({pt.ICACHE_BEAT_BITS{bus_hold_data_beat_cnt}}  &  bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0]); | ||||
| 
 | ||||
|    rvdff #(pt.ICACHE_BEAT_BITS)  bus_mb_beat_count_ff (.*, .clk(free_clk), .din ({bus_new_data_beat_count[pt.ICACHE_BEAT_BITS-1:0]}), .dout({bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0]})); | ||||
| 
 | ||||
|    assign last_data_recieved_in =  (bus_ifu_wr_en_ff &  bus_last_data_beat & ~scnd_miss_req) | (last_data_recieved_ff & ~ic_act_miss_f) ; | ||||
|    rvdff #(1)  last_beat_ff (.*, .clk(free_clk), .din (last_data_recieved_in), .dout(last_data_recieved_ff)); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| // Request Address Count
 | ||||
|  | @ -1134,7 +1142,7 @@ logic                                         perr_sb_write_status   ; | |||
|                                                            ( bus_cmd_sent                    ) ? (bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0] + 3'b001) : | ||||
|                                                                                                   bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0]; | ||||
| 
 | ||||
|    rvdff #(pt.ICACHE_BEAT_BITS)  bus_rd_addr_ff (.*,  .clk(busclk_reset), .din ({bus_new_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0]}), .dout({bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0]})); | ||||
|    rvdff_fpga #(pt.ICACHE_BEAT_BITS)  bus_rd_addr_ff (.*,  .clk(busclk_reset),  .clken (bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt), .rawclk(clk), .din ({bus_new_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0]}), .dout({bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0]})); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1150,11 +1158,15 @@ logic                                         perr_sb_write_status   ; | |||
|                                                           ({pt.ICACHE_BEAT_BITS{bus_inc_cmd_beat_cnt}}              & (bus_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0] + {{pt.ICACHE_BEAT_BITS-1{1'b0}}, 1'b1})) | | ||||
|                                                           ({pt.ICACHE_BEAT_BITS{bus_hold_cmd_beat_cnt}}             &  bus_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0]) ; | ||||
| 
 | ||||
|    rvclkhdr bus_clk_reset(.en(bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt), | ||||
|                    .l1clk(busclk_reset), .*); | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    assign busclk_reset = 1'b0; | ||||
| `else | ||||
|    rvclkhdr bus_clk_reset(.en(bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt), .l1clk(busclk_reset), .*); | ||||
| `endif | ||||
| 
 | ||||
| 
 | ||||
|    rvdffs #(pt.ICACHE_BEAT_BITS)  bus_cmd_beat_ff (.*, .clk(busclk_reset), .en (bus_cmd_beat_en), .din ({bus_new_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0]}), | ||||
| 
 | ||||
|    rvdffs_fpga #(pt.ICACHE_BEAT_BITS)  bus_cmd_beat_ff (.*, .clk(busclk_reset), .clken (bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt), .rawclk(clk), .en (bus_cmd_beat_en), .din ({bus_new_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0]}), | ||||
|                     .dout({bus_cmd_beat_count[pt.ICACHE_BEAT_BITS-1:0]})); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1166,12 +1178,26 @@ logic                                         perr_sb_write_status   ; | |||
|    assign  bus_ifu_wr_en_ff_wo_err  =  ifu_bus_rvalid_ff & miss_pending &  ~uncacheable_miss_ff; | ||||
| 
 | ||||
| 
 | ||||
|    rvdff #(1)  act_miss_ff (.*, .clk(free_clk), .din (ic_act_miss_f), .dout(ic_act_miss_f_delayed)); | ||||
|    rvdffie #(10) misc_ff | ||||
|        ( .*, | ||||
|          .clk(free_l2clk), | ||||
|          .din( {ic_act_miss_f,        ifu_wr_cumulative_err,exu_flush_final,  ic_crit_wd_rdy_new_in,bus_ifu_bus_clk_en,   scnd_miss_req_in,bus_cmd_req_in,  last_data_recieved_in, | ||||
| ifc_dma_access_ok_d,   dma_iccm_req}), | ||||
|          .dout({ic_act_miss_f_delayed,ifu_wr_data_comb_err_ff,  flush_final_f,ic_crit_wd_rdy_new_ff,bus_ifu_bus_clk_en_ff,scnd_miss_req_q, bus_cmd_req_hold,last_data_recieved_ff, | ||||
| ifc_dma_access_ok_prev,dma_iccm_req_f}) | ||||
|          ); | ||||
| 
 | ||||
|    rvdffie #(.WIDTH(pt.ICACHE_BEAT_BITS+5),.OVERRIDE(1)) misc1_ff | ||||
|        ( .*, | ||||
|          .clk(free_l2clk), | ||||
|          .din( {reset_ic_in,sel_mb_addr,   bus_new_data_beat_count[pt.ICACHE_BEAT_BITS-1:0],ifc_region_acc_fault_memory_bf,ic_debug_rd_en,       ic_debug_rd_en_ff}), | ||||
|          .dout({reset_ic_ff,sel_mb_addr_ff,bus_data_beat_count[pt.ICACHE_BEAT_BITS-1:0],    ifc_region_acc_fault_memory_f, ic_debug_rd_en_ff,ifu_ic_debug_rd_data_valid}) | ||||
|          ); | ||||
| 
 | ||||
|    assign    reset_tag_valid_for_miss = ic_act_miss_f_delayed & (miss_state == CRIT_BYP_OK) & ~uncacheable_miss_ff; | ||||
|    assign    bus_ifu_wr_data_error    = |ifu_bus_rsp_opc[1:0] &  ifu_bus_rvalid  & miss_pending; | ||||
|    assign    bus_ifu_wr_data_error_ff = |ifu_bus_rresp_ff[1:0] &  ifu_bus_rvalid_ff  & miss_pending; | ||||
| 
 | ||||
|    rvdff #(1)           dma_ok_prev_ff  (.*, .clk(free_clk),  .din(ifc_dma_access_ok_d), .dout(ifc_dma_access_ok_prev)); | ||||
| 
 | ||||
|    assign ic_crit_wd_rdy   =  ic_crit_wd_rdy_new_in | ic_crit_wd_rdy_new_ff ; | ||||
|    assign last_beat        =  bus_last_data_beat & bus_ifu_wr_en_ff; | ||||
|  | @ -1182,7 +1208,6 @@ logic                                         perr_sb_write_status   ; | |||
|    assign ifc_dma_access_ok_d  = ifc_dma_access_ok &  ~iccm_correct_ecc & ~iccm_dma_sb_error; | ||||
|    assign ifc_dma_access_q_ok  = ifc_dma_access_ok &  ~iccm_correct_ecc & ifc_dma_access_ok_prev &  (perr_state == ERR_IDLE)  & ~iccm_dma_sb_error; | ||||
|    assign iccm_ready           = ifc_dma_access_q_ok ; | ||||
|    rvdff #(1)  dma_req_ff (.*, .clk(free_clk), .din (dma_iccm_req), .dout(dma_iccm_req_f)); | ||||
| 
 | ||||
|    logic [1:0]        iccm_ecc_word_enable; | ||||
| 
 | ||||
|  | @ -1233,13 +1258,19 @@ logic                                         perr_sb_write_status   ; | |||
|          assign iccm_dma_rdata_in[63:0]      = iccm_dma_ecc_error_in ? {2{dma_mem_addr[31:0]}} : {iccm_dma_rdata_1_muxed[31:0], iccm_corrected_data[0]}; | ||||
|          assign iccm_dma_ecc_error_in   =   |(iccm_double_ecc_error[1:0]); | ||||
| 
 | ||||
|          rvdff #(3) dma_tag_ff1      (.*, .clk(free_clk), .din(dma_mem_tag[2:0]),        .dout(dma_mem_tag_ff[2:0])); | ||||
|          rvdff #(3) dma_tag_ff2      (.*, .clk(free_clk), .din(dma_mem_tag_ff[2:0]),     .dout(iccm_dma_rtag[2:0])); | ||||
|          rvdff #(2) dma_addr_bt3_ff  (.*, .clk(free_clk), .din(dma_mem_addr[3:2]),       .dout(dma_mem_addr_ff[3:2])); | ||||
|          rvdff #(1) ccm_rdy_in_ff    (.*, .clk(free_clk), .din(iccm_dma_rden),           .dout(iccm_dma_rvalid_in)); | ||||
|          rvdff #(1) ccm_rdy_ff       (.*, .clk(free_clk), .din(iccm_dma_rvalid_in),      .dout(iccm_dma_rvalid)); | ||||
|          rvdff #(1) ccm_err_ff       (.*, .clk(free_clk), .din(iccm_dma_ecc_error_in),   .dout(iccm_dma_ecc_error)); | ||||
|          rvdff #(64)dma_data_ff      (.*, .clk(free_clk), .din(iccm_dma_rdata_in[63:0]), .dout(iccm_dma_rdata[63:0])); | ||||
|          rvdffe    #(64) dma_data_ff      (.*, .clk(clk), .en(iccm_dma_rvalid_in),  .din(iccm_dma_rdata_in[63:0]), .dout(iccm_dma_rdata[63:0])); | ||||
|          rvdffie   #(11) dma_misc_bits    (.*, .clk(free_l2clk), .din({dma_mem_tag[2:0], | ||||
|                                                                        dma_mem_tag_ff[2:0], | ||||
|                                                                        dma_mem_addr[3:2], | ||||
|                                                                        iccm_dma_rden, | ||||
|                                                                        iccm_dma_rvalid_in, | ||||
|                                                                        iccm_dma_ecc_error_in }), | ||||
|                                                                 .dout({dma_mem_tag_ff[2:0], | ||||
|                                                                        iccm_dma_rtag[2:0], | ||||
|                                                                        dma_mem_addr_ff[3:2], | ||||
|                                                                        iccm_dma_rvalid_in, | ||||
|                                                                        iccm_dma_rvalid, | ||||
|                                                                        iccm_dma_ecc_error })); | ||||
| 
 | ||||
|          assign iccm_rw_addr[pt.ICCM_BITS-1:1]    = (  ifc_dma_access_q_ok & dma_iccm_req  & ~iccm_correct_ecc) ? dma_mem_addr[pt.ICCM_BITS-1:1] : | ||||
|                                                  (~(ifc_dma_access_q_ok & dma_iccm_req) &  iccm_correct_ecc) ? {iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2],1'b0} : ifc_fetch_addr_bf[pt.ICCM_BITS-1:1] ; | ||||
|  | @ -1271,21 +1302,30 @@ logic                                         perr_sb_write_status   ; | |||
| end | ||||
| 
 | ||||
|   assign iccm_rd_ecc_single_err  = (|iccm_single_ecc_error[1:0] ) & ifc_iccm_access_f & ifc_fetch_req_f; | ||||
|   assign iccm_rd_ecc_double_err  = (|iccm_double_ecc_error[1:0] ) & ifc_iccm_access_f; | ||||
|   assign iccm_rd_ecc_double_err[1:0]  = ~ifu_fetch_addr_int_f[1] ? ({iccm_double_ecc_error[0], iccm_double_ecc_error[0]} ) & {2{ifc_iccm_access_f}} : | ||||
|                                                                    ({iccm_double_ecc_error[1], iccm_double_ecc_error[0]} ) & {2{ifc_iccm_access_f}} ; | ||||
| 
 | ||||
|   assign iccm_corrected_data_f_mux[31:0] = iccm_single_ecc_error[0] ? iccm_corrected_data[0] : iccm_corrected_data[1]; | ||||
|   assign iccm_corrected_ecc_f_mux[6:0]   = iccm_single_ecc_error[0] ? iccm_corrected_ecc[0]  : iccm_corrected_ecc[1]; | ||||
| 
 | ||||
|   assign iccm_ecc_write_status           = ((iccm_rd_ecc_single_err & ~iccm_rd_ecc_single_err_ff)  & ~exu_flush_final) | iccm_dma_sb_error; | ||||
|   assign iccm_rd_ecc_single_err_hold_in  = (iccm_rd_ecc_single_err | iccm_rd_ecc_single_err_ff) & ~exu_flush_final ; // & ~(perr_state == ERR_IDLE);
 | ||||
|   assign iccm_rd_ecc_single_err_hold_in  = (iccm_rd_ecc_single_err | iccm_rd_ecc_single_err_ff) & ~exu_flush_final ; | ||||
|   assign iccm_error_start                =  iccm_rd_ecc_single_err; | ||||
|   assign iccm_ecc_corr_index_in[pt.ICCM_BITS-1:2] = iccm_single_ecc_error[0] ? iccm_rw_addr_f[pt.ICCM_BITS-1:2] : iccm_rw_addr_f[pt.ICCM_BITS-1:2] + 1'b1 ; | ||||
| 
 | ||||
|    rvdff #(pt.ICCM_BITS-2) iccm_index_f   (.*, .clk(free_clk), .din(iccm_rw_addr[pt.ICCM_BITS-1:2]),     .dout(iccm_rw_addr_f[pt.ICCM_BITS-1:2])); | ||||
|    rvdff  #((1))          ecc_rr_ff    (.clk(free_clk),     .din(iccm_rd_ecc_single_err_hold_in),  .dout(iccm_rd_ecc_single_err_ff),            .*); | ||||
|    rvdffs #((32))         ecc_dat0_ff  (.clk(free_clk),     .din(iccm_corrected_data_f_mux[31:0]), .dout(iccm_ecc_corr_data_ff[31:0]),          .en(iccm_ecc_write_status),  .*); | ||||
|    rvdffs #((7))          ecc_dat1_ff  (.clk(free_clk),     .din(iccm_corrected_ecc_f_mux[6:0]),   .dout(iccm_ecc_corr_data_ff[38:32]),         .en(iccm_ecc_write_status),  .*); | ||||
|    rvdffs #((pt.ICCM_BITS-2))ecc_ind0_ff  (.clk(free_clk),     .din(iccm_ecc_corr_index_in[pt.ICCM_BITS-1:2]),   .dout(iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2]),.en(iccm_ecc_write_status),  .*); | ||||
|    rvdffie #(pt.ICCM_BITS-1) iccm_index_f   (.*, .clk(free_l2clk), .din({iccm_rw_addr[pt.ICCM_BITS-1:2], | ||||
|                                                                          iccm_rd_ecc_single_err_hold_in | ||||
|                                                                                                        }), | ||||
|                                                                   .dout({iccm_rw_addr_f[pt.ICCM_BITS-1:2], | ||||
|                                                                          iccm_rd_ecc_single_err_ff})); | ||||
| 
 | ||||
|    rvdffe #((39+(pt.ICCM_BITS-2)))      ecc_dat0_ff  ( | ||||
|                                                       .clk(clk), | ||||
|                                                       .din({iccm_corrected_ecc_f_mux[6:0],  iccm_corrected_data_f_mux[31:0],iccm_ecc_corr_index_in[pt.ICCM_BITS-1:2]}), | ||||
|                                                       .dout({iccm_ecc_corr_data_ff[38:0]   ,iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2]}), | ||||
|                                                       .en(iccm_ecc_write_status), | ||||
|                                                       .* | ||||
|                                                       ); | ||||
| 
 | ||||
|      end else begin : iccm_disabled | ||||
|          assign iccm_dma_rvalid = 1'b0 ; | ||||
|  | @ -1300,7 +1340,7 @@ end | |||
| 
 | ||||
| 
 | ||||
|          assign iccm_rd_ecc_single_err                 = 1'b0 ; | ||||
|          assign iccm_rd_ecc_double_err                 = 1'b0 ; | ||||
|          assign iccm_rd_ecc_double_err                 = '0 ; | ||||
|          assign iccm_rd_ecc_single_err_ff              = 1'b0 ; | ||||
|          assign iccm_error_start                         = 1'b0; | ||||
|          assign iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2]  =  '0; | ||||
|  | @ -1318,7 +1358,6 @@ end | |||
| ////// ICCM signals
 | ||||
| 
 | ||||
| 
 | ||||
| //  Use the equation below for more power savings.
 | ||||
|  assign   ic_rd_en    =  (ifc_fetch_req_bf & ~ifc_fetch_uncacheable_bf & ~ifc_iccm_access_bf  & | ||||
|                             ~(((miss_state == STREAM) & ~miss_state_en)                                       | | ||||
|                               ((miss_state == CRIT_BYP_OK) & ~miss_state_en)                                  | | ||||
|  | @ -1328,7 +1367,6 @@ end | |||
|                               ((miss_state == CRIT_BYP_OK) &  miss_state_en &  (miss_nxtstate == MISS_WAIT))  ))  | | ||||
|                              ( ifc_fetch_req_bf & exu_flush_final  & ~ifc_fetch_uncacheable_bf & ~ifc_iccm_access_bf )     ; | ||||
| 
 | ||||
| 
 | ||||
| logic   ic_real_rd_wp_unused; | ||||
| assign  ic_real_rd_wp_unused  =  (ifc_fetch_req_bf &  ~ifc_iccm_access_bf  &  ~ifc_region_acc_fault_final_bf & ~dec_tlu_fence_i_wb & ~stream_miss_f & ~ic_act_miss_f & | ||||
|                             ~(((miss_state == STREAM) & ~miss_state_en) | | ||||
|  | @ -1345,7 +1383,6 @@ assign  ic_real_rd_wp_unused  =  (ifc_fetch_req_bf &  ~ifc_iccm_access_bf  &  ~i | |||
| assign ic_wr_en[pt.ICACHE_NUM_WAYS-1:0] = bus_ic_wr_en[pt.ICACHE_NUM_WAYS-1:0] & {pt.ICACHE_NUM_WAYS{write_ic_16_bytes}}; | ||||
| assign ic_write_stall                =  write_ic_16_bytes &  ~((((miss_state== CRIT_BYP_OK) | ((miss_state==STREAM) & ~(exu_flush_final | ifu_bp_hit_taken_q_f  | stream_eol_f ))) & ~(bus_ifu_wr_en_ff & last_beat & ~uncacheable_miss_ff))); | ||||
| 
 | ||||
|    rvdff #(1) reset_all_tag_ff (.*, .clk(active_clk),  .din(dec_tlu_fence_i_wb), .dout(reset_all_tags)); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1361,26 +1398,36 @@ if (pt.ICACHE_ENABLE == 1 ) begin: icache_enabled | |||
|                                                                            ifu_status_wr_addr[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]; | ||||
| 
 | ||||
|    // status
 | ||||
|          rvdff #(pt.ICACHE_TAG_LO-pt.ICACHE_TAG_INDEX_LO) status_wr_addr_ff (.*,  .clk(free_clk), .din(ifu_status_wr_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]), | ||||
|                    .dout(ifu_status_wr_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO])); | ||||
| 
 | ||||
|          assign way_status_wr_en_w_debug = way_status_wr_en | (ic_debug_wr_en  & ic_debug_tag_array); | ||||
|          rvdff #(1) status_wren_ff (.*, .clk(free_clk),  .din(way_status_wr_en_w_debug), .dout(way_status_wr_en_ff)); | ||||
| 
 | ||||
|          assign way_status_new_w_debug[pt.ICACHE_STATUS_BITS-1:0]  = (ic_debug_wr_en  & ic_debug_tag_array) ? (pt.ICACHE_STATUS_BITS == 1) ? ic_debug_wr_data[4] : ic_debug_wr_data[6:4] : | ||||
|                                                 way_status_new[pt.ICACHE_STATUS_BITS-1:0] ; | ||||
|          rvdff #(pt.ICACHE_STATUS_BITS) status_data_ff (.*,  .clk(free_clk), .din(way_status_new_w_debug[pt.ICACHE_STATUS_BITS-1:0]), .dout(way_status_new_ff[pt.ICACHE_STATUS_BITS-1:0])); | ||||
| 
 | ||||
|    rvdffie #(.WIDTH(pt.ICACHE_TAG_LO-pt.ICACHE_TAG_INDEX_LO+1+pt.ICACHE_STATUS_BITS),.OVERRIDE(1))  status_misc_ff | ||||
|      (.*, | ||||
|       .clk(free_l2clk), | ||||
|       .din({ ifu_status_wr_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO], way_status_wr_en_w_debug, way_status_new_w_debug[pt.ICACHE_STATUS_BITS-1:0]}), | ||||
|       .dout({ifu_status_wr_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO],      way_status_wr_en_ff,      way_status_new_ff[pt.ICACHE_STATUS_BITS-1:0]} ) | ||||
|       ); | ||||
| 
 | ||||
|    logic [(pt.ICACHE_TAG_DEPTH/8)-1 : 0] way_status_clken; | ||||
|    logic [(pt.ICACHE_TAG_DEPTH/8)-1 : 0] way_status_clk; | ||||
| 
 | ||||
|    for (genvar i=0 ; i<32'(pt.ICACHE_TAG_DEPTH)/8 ; i++) begin : CLK_GRP_WAY_STATUS | ||||
|    for (genvar i=0 ; i<pt.ICACHE_TAG_DEPTH/8 ; i++) begin : CLK_GRP_WAY_STATUS | ||||
|       assign way_status_clken[i] = (ifu_status_wr_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO+3] == i ); | ||||
|       rvclkhdr way_status_cgc ( .en(way_status_clken[i]),   .l1clk(way_status_clk[i]), .* ); | ||||
|      `ifdef RV_FPGA_OPTIMIZE | ||||
|         assign way_status_clk[i] = 1'b0; | ||||
|      `else | ||||
|            rvclkhdr way_status_cgc ( .en(way_status_clken[i]),   .l1clk(way_status_clk[i]), .* ); | ||||
|      `endif | ||||
| 
 | ||||
| 
 | ||||
|       for (genvar j=0 ; j<8 ; j++) begin : WAY_STATUS | ||||
|          rvdffs #(pt.ICACHE_STATUS_BITS) ic_way_status (.*, | ||||
|          rvdffs_fpga #(pt.ICACHE_STATUS_BITS) ic_way_status (.*, | ||||
|                    .clk(way_status_clk[i]), | ||||
|                    .clken(way_status_clken[i]), | ||||
|                    .rawclk(clk), | ||||
|                    .en(((ifu_status_wr_addr_ff[pt.ICACHE_TAG_INDEX_LO+2:pt.ICACHE_TAG_INDEX_LO] == j) & way_status_wr_en_ff)), | ||||
|                    .din(way_status_new_ff[pt.ICACHE_STATUS_BITS-1:0]), | ||||
|                    .dout(way_status_out[8*i+j])); | ||||
|  | @ -1389,38 +1436,38 @@ if (pt.ICACHE_ENABLE == 1 ) begin: icache_enabled | |||
| 
 | ||||
|   always_comb begin : way_status_out_mux | ||||
|       way_status[pt.ICACHE_STATUS_BITS-1:0] = '0 ; | ||||
|       for (int j=0; j< 32'(pt.ICACHE_TAG_DEPTH); j++) begin : status_mux_loop | ||||
|       for (int j=0; j< pt.ICACHE_TAG_DEPTH; j++) begin : status_mux_loop | ||||
|         if (ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] == (pt.ICACHE_TAG_LO-pt.ICACHE_TAG_INDEX_LO)'(j)) begin : mux_out | ||||
|          way_status[pt.ICACHE_STATUS_BITS-1:0] =  way_status_out[j]; | ||||
|         end | ||||
|       end | ||||
|   end | ||||
| 
 | ||||
| assign ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] = ((ic_debug_rd_en | ic_debug_wr_en ) & ic_debug_tag_array) ? | ||||
|          assign ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] = ((ic_debug_rd_en | ic_debug_wr_en ) & ic_debug_tag_array) ? | ||||
|                                                                         ic_debug_addr[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] : | ||||
|                                                                         ifu_ic_rw_int_addr[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]; | ||||
| 
 | ||||
|          rvdff #(pt.ICACHE_TAG_LO-pt.ICACHE_TAG_INDEX_LO) tag_addr_ff (.*, .clk(free_clk), | ||||
|                    .din(ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO]), | ||||
|                    .dout(ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO])); | ||||
| 
 | ||||
|          assign ifu_tag_wren_w_debug[pt.ICACHE_NUM_WAYS-1:0] = ifu_tag_wren[pt.ICACHE_NUM_WAYS-1:0] | ic_debug_tag_wr_en[pt.ICACHE_NUM_WAYS-1:0] ; | ||||
|          rvdff #(pt.ICACHE_NUM_WAYS) tag_v_we_ff (.*, .clk(free_clk), | ||||
|                    .din(ifu_tag_wren_w_debug[pt.ICACHE_NUM_WAYS-1:0]), | ||||
|                    .dout(ifu_tag_wren_ff[pt.ICACHE_NUM_WAYS-1:0])); | ||||
| 
 | ||||
|          assign ic_valid_w_debug = (ic_debug_wr_en & ic_debug_tag_array) ? ic_debug_wr_data[0] : ic_valid; | ||||
|          rvdff #(1) tag_v_ff (.*, .clk(free_clk), | ||||
|                    .din(ic_valid_w_debug), | ||||
|                    .dout(ic_valid_ff)); | ||||
| 
 | ||||
|          rvdffie #(pt.ICACHE_TAG_LO-pt.ICACHE_TAG_INDEX_LO+pt.ICACHE_NUM_WAYS+1) tag_addr_ff (.*, | ||||
|                                                                                               .clk(free_l2clk), | ||||
|                                                                                               .din({ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO], | ||||
|                                                                                                     ifu_tag_wren_w_debug[pt.ICACHE_NUM_WAYS-1:0], | ||||
|                                                                                                     ic_valid_w_debug}), | ||||
|                                                                                               .dout({ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO], | ||||
|                                                                                                      ifu_tag_wren_ff[pt.ICACHE_NUM_WAYS-1:0], | ||||
|                                                                                                      ic_valid_ff}) | ||||
|                                                                                               ); | ||||
| 
 | ||||
| 
 | ||||
|    logic [pt.ICACHE_NUM_WAYS-1:0] [pt.ICACHE_TAG_DEPTH-1:0] ic_tag_valid_out ; | ||||
| 
 | ||||
|    logic [(pt.ICACHE_TAG_DEPTH/32)-1:0] [pt.ICACHE_NUM_WAYS-1:0] tag_valid_clken ; | ||||
|    logic [(pt.ICACHE_TAG_DEPTH/32)-1:0] [pt.ICACHE_NUM_WAYS-1:0] tag_valid_clk   ; | ||||
| 
 | ||||
|    for (genvar i=0 ; i<32'(pt.ICACHE_TAG_DEPTH)/32 ; i++) begin : CLK_GRP_TAG_VALID | ||||
|       for (genvar j=0; j<32'(pt.ICACHE_NUM_WAYS); j++) begin : way_clken | ||||
|    for (genvar i=0 ; i<pt.ICACHE_TAG_DEPTH/32 ; i++) begin : CLK_GRP_TAG_VALID | ||||
|       for (genvar j=0; j<pt.ICACHE_NUM_WAYS; j++) begin : way_clken | ||||
|       if (pt.ICACHE_TAG_DEPTH == 32 ) begin | ||||
|         assign tag_valid_clken[i][j] =  ifu_tag_wren_ff[j] | perr_err_inv_way[j] | reset_all_tags; | ||||
|       end else begin | ||||
|  | @ -1428,11 +1475,19 @@ assign ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] = ( | |||
|                                         ((perr_ic_index_ff     [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO+5] == i ) &  perr_err_inv_way[j]) | reset_all_tags); | ||||
|       end | ||||
| 
 | ||||
|       rvclkhdr way_status_cgc ( .en(tag_valid_clken[i][j]),   .l1clk(tag_valid_clk[i][j]), .* ); | ||||
|      `ifdef RV_FPGA_OPTIMIZE | ||||
|         assign tag_valid_clk[i][j]  = 1'b0; | ||||
|      `else | ||||
|            rvclkhdr way_status_cgc ( .en(tag_valid_clken[i][j]),   .l1clk(tag_valid_clk[i][j]), .* ); | ||||
|      `endif | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|       for (genvar k=0 ; k<32 ; k++) begin : TAG_VALID | ||||
|          rvdffs #(1) ic_way_tagvalid_dup (.*, | ||||
|          rvdffs_fpga #(1) ic_way_tagvalid_dup (.*, | ||||
|                    .clk(tag_valid_clk[i][j]), | ||||
|                    .clken(tag_valid_clken[i][j]), | ||||
|                    .rawclk(clk), | ||||
|                    .en(((ifu_ic_rw_int_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] == (k + 32*i)) & ifu_tag_wren_ff[j] ) | | ||||
|                        ((perr_ic_index_ff     [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] == (k + 32*i)) & perr_err_inv_way[j]) | reset_all_tags), | ||||
|                    .din(ic_valid_ff & ~reset_all_tags & ~perr_sel_invalidate), | ||||
|  | @ -1452,7 +1507,7 @@ assign ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] = ( | |||
|       end | ||||
|       end | ||||
|   end | ||||
| //   four-way set associative - three bits
 | ||||
|    //   four-way set associative - three bits
 | ||||
| //   each bit represents one branch point in a binary decision tree; let 1
 | ||||
| //   represent that the left side has been referenced more recently than the
 | ||||
| //   right side, and 0 vice-versa
 | ||||
|  | @ -1482,10 +1537,10 @@ assign ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] = ( | |||
|    assign replace_way_mb_any[0] = (~way_status_mb_ff[1] & ~way_status_mb_ff[0] & (&tagv_mb_ff[3:0])) | | ||||
|                                   (~tagv_mb_ff[0] ) ; | ||||
| 
 | ||||
|    assign way_status_hit_new[pt.ICACHE_STATUS_BITS-1:0] = ({3{ic_rd_hit[0]}} & {way_status[2] , 1'b1 , 1'b1}) | | ||||
|                                    ({3{ic_rd_hit[1]}} & {way_status[2] , 1'b0 , 1'b1}) | | ||||
|                                    ({3{ic_rd_hit[2]}} & {1'b1 ,way_status[1]  , 1'b0}) | | ||||
|                                    ({3{ic_rd_hit[3]}} & {1'b0 ,way_status[1]  , 1'b0}) ; | ||||
|    assign way_status_hit_new[pt.ICACHE_STATUS_BITS-1:0] = ({3{~exu_flush_final & ic_rd_hit[0]}} & {way_status[2] , 1'b1 , 1'b1}) | | ||||
|                                                           ({3{~exu_flush_final & ic_rd_hit[1]}} & {way_status[2] , 1'b0 , 1'b1}) | | ||||
|                                                           ({3{~exu_flush_final & ic_rd_hit[2]}} & {1'b1 ,way_status[1]  , 1'b0}) | | ||||
|                                                           ({3{~exu_flush_final & ic_rd_hit[3]}} & {1'b0 ,way_status[1]  , 1'b0}) ; | ||||
| 
 | ||||
|   assign way_status_rep_new[pt.ICACHE_STATUS_BITS-1:0] = ({3{replace_way_mb_any[0]}} & {way_status_mb_ff[2] , 1'b1 , 1'b1}) | | ||||
|                                    ({3{replace_way_mb_any[1]}} & {way_status_mb_ff[2] , 1'b0 , 1'b1}) | | ||||
|  | @ -1506,7 +1561,7 @@ assign ifu_ic_rw_int_addr_w_debug[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] = ( | |||
| 
 | ||||
|   assign way_status_wr_en  = (bus_ifu_wr_en_ff_q  & last_beat) | ic_act_hit_f; | ||||
| 
 | ||||
|    for (genvar i=0; i<32'(pt.ICACHE_NUM_WAYS); i++) begin  : bus_wren_loop | ||||
|    for (genvar i=0; i<pt.ICACHE_NUM_WAYS; i++) begin  : bus_wren_loop | ||||
|       assign bus_wren[i]           = bus_ifu_wr_en_ff_q & replace_way_mb_any[i] & miss_pending ; | ||||
|       assign bus_wren_last[i]      = bus_ifu_wr_en_ff_wo_err & replace_way_mb_any[i] & miss_pending & bus_last_data_beat; | ||||
|       assign ifu_tag_wren[i]       = bus_wren_last[i] | wren_reset_miss[i]; | ||||
|  | @ -1528,7 +1583,7 @@ end else begin: icache_disabled | |||
| 
 | ||||
| end | ||||
| 
 | ||||
|    assign ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0] = ic_tag_valid_unq[pt.ICACHE_NUM_WAYS-1:0]   & {pt.ICACHE_NUM_WAYS{(~fetch_uncacheable_ff & ifc_fetch_req_f) }} ; | ||||
|    assign ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0] = ic_tag_valid_unq[pt.ICACHE_NUM_WAYS-1:0]   & {pt.ICACHE_NUM_WAYS{(~fetch_uncacheable_ff & ifc_fetch_req_f_raw) }} ; | ||||
|    assign ic_debug_tag_val_rd_out           = |(ic_tag_valid_unq[pt.ICACHE_NUM_WAYS-1:0] &  ic_debug_way_ff[pt.ICACHE_NUM_WAYS-1:0]   & {pt.ICACHE_NUM_WAYS{ic_debug_rd_en_ff}}) ; | ||||
| ///////////////////////////////////////////
 | ||||
| // PMU signals
 | ||||
|  | @ -1536,19 +1591,21 @@ end | |||
| 
 | ||||
|  assign ifu_pmu_ic_miss_in   = ic_act_miss_f ; | ||||
|  assign ifu_pmu_ic_hit_in    = ic_act_hit_f  ; | ||||
|  assign ifu_pmu_bus_error_in = ifc_bus_acc_fault_f; | ||||
|  assign ifu_pmu_bus_error_in = |ifc_bus_acc_fault_f; | ||||
|  assign ifu_pmu_bus_trxn_in  = bus_cmd_sent ; | ||||
|  assign ifu_pmu_bus_busy_in  = ifu_bus_arvalid_ff & ~ifu_bus_arready_ff & miss_pending ; | ||||
| 
 | ||||
|    rvdff #(5) ifu_pmu_sigs_ff (.*, | ||||
|                     .clk (active_clk), | ||||
|                     .din ({ifu_pmu_ic_miss_in, | ||||
|    rvdffie #(9) ifu_pmu_sigs_ff (.*, | ||||
|                     .clk (free_l2clk), | ||||
|                     .din ({ifc_fetch_uncacheable_bf, ifc_fetch_req_qual_bf, dma_sb_err_state, dec_tlu_fence_i_wb, | ||||
|                            ifu_pmu_ic_miss_in, | ||||
|                            ifu_pmu_ic_hit_in, | ||||
|                            ifu_pmu_bus_error_in, | ||||
|                            ifu_pmu_bus_busy_in, | ||||
|                            ifu_pmu_bus_trxn_in | ||||
|                           }), | ||||
|                     .dout({ifu_pmu_ic_miss, | ||||
|                     .dout({fetch_uncacheable_ff, ifc_fetch_req_f_raw, dma_sb_err_state_ff, reset_all_tags, | ||||
|                            ifu_pmu_ic_miss, | ||||
|                            ifu_pmu_ic_hit, | ||||
|                            ifu_pmu_bus_error, | ||||
|                            ifu_pmu_bus_busy, | ||||
|  | @ -1577,7 +1634,8 @@ assign ic_debug_tag_wr_en[pt.ICACHE_NUM_WAYS-1:0] = {pt.ICACHE_NUM_WAYS{ic_debug | |||
| 
 | ||||
| assign ic_debug_ict_array_sel_in      =  ic_debug_rd_en & ic_debug_tag_array ; | ||||
| 
 | ||||
| rvdff #(01+pt.ICACHE_NUM_WAYS) ifu_debug_sel_ff (.*, .clk (debug_c1_clk), | ||||
| rvdff_fpga #(01+pt.ICACHE_NUM_WAYS) ifu_debug_sel_ff (.*, .clk (debug_c1_clk), | ||||
|                     .clken(debug_c1_clken), .rawclk(clk), | ||||
|                     .din ({ic_debug_ict_array_sel_in, | ||||
|                            ic_debug_way[pt.ICACHE_NUM_WAYS-1:0] | ||||
|                           }), | ||||
|  | @ -1586,25 +1644,10 @@ rvdff #(01+pt.ICACHE_NUM_WAYS) ifu_debug_sel_ff (.*, .clk (debug_c1_clk), | |||
|                            })); | ||||
| 
 | ||||
| 
 | ||||
| rvdff #(1) ifu_debug_rd_en_ff (.*,.clk(free_clk), | ||||
|                     .din ({ | ||||
|                            ic_debug_rd_en | ||||
|                           }), | ||||
|                     .dout({ | ||||
|                            ic_debug_rd_en_ff | ||||
|                            })); | ||||
| 
 | ||||
| 
 | ||||
| assign debug_data_clken  =  ic_debug_rd_en_ff; | ||||
| rvclkhdr debug_data_c1_cgc ( .en(debug_data_clken),   .l1clk(debug_data_clk), .* ); | ||||
| 
 | ||||
| rvdff #(1) ifu_debug_valid_ff (.*, .clk(free_clk), | ||||
|                     .din ({ | ||||
|                            ic_debug_rd_en_ff | ||||
|                           }), | ||||
|                     .dout({ | ||||
|                            ifu_ic_debug_rd_data_valid | ||||
|                            })); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1623,7 +1666,6 @@ rvdff #(1) ifu_debug_valid_ff (.*, .clk(free_clk), | |||
| 
 | ||||
|    assign ifc_region_acc_fault_final_bf = ifc_region_acc_fault_bf | ifc_region_acc_fault_memory_bf; | ||||
| 
 | ||||
| rvdff #(1) acc_f_m_ff (.*, .clk(free_clk),  .din ( ifc_region_acc_fault_memory_bf ), .dout( ifc_region_acc_fault_memory_f )); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| //********************************************************************************
 | ||||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -41,11 +41,10 @@ module el2_ifu_tb_memread; | |||
|       clk=0; | ||||
|       rst_l=0; | ||||
| 
 | ||||
|       // initialize the reads and populate the istruction arrays
 | ||||
|       // initialize the reads and populate the instruction arrays
 | ||||
|       $readmemh ("left64k", compressed ); | ||||
|       $readmemh ("right64k", expected ); | ||||
| 
 | ||||
| 
 | ||||
|       $dumpfile ("top.vcd"); | ||||
|       $dumpvars; | ||||
|       $dumpon; | ||||
|  |  | |||
|  | @ -4,13 +4,13 @@ | |||
| package el2_pkg; | ||||
| 
 | ||||
| typedef struct packed { | ||||
|                        logic [1:0] rv_i_valid_ip; | ||||
|                        logic [31:0] rv_i_insn_ip; | ||||
|                        logic [31:0] rv_i_address_ip; | ||||
|                        logic [1:0] rv_i_exception_ip; | ||||
|                        logic [4:0] rv_i_ecause_ip; | ||||
|                        logic [1:0] rv_i_interrupt_ip; | ||||
|                        logic [31:0] rv_i_tval_ip; | ||||
|                        logic  trace_rv_i_valid_ip; | ||||
|                        logic [31:0] trace_rv_i_insn_ip; | ||||
|                        logic [31:0] trace_rv_i_address_ip; | ||||
|                        logic  trace_rv_i_exception_ip; | ||||
|                        logic [4:0] trace_rv_i_ecause_ip; | ||||
|                        logic  trace_rv_i_interrupt_ip; | ||||
|                        logic [31:0] trace_rv_i_tval_ip; | ||||
|                        } el2_trace_pkt_t; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -76,36 +76,41 @@ typedef struct packed { | |||
|                        logic valid; | ||||
|                        logic br_error; | ||||
|                        logic br_start_error; | ||||
|                        logic [31:1] prett; | ||||
|                        logic pcall; | ||||
|                        logic pret; | ||||
|                        logic pja; | ||||
|                        logic way; | ||||
|                        logic pret; | ||||
|                        // for power use the pret bit to clock the prett field
 | ||||
|                        logic [31:1] prett; | ||||
|                        } el2_predict_pkt_t; | ||||
| 
 | ||||
| typedef struct packed { | ||||
|                        logic legal; | ||||
|                        // unlikely to change
 | ||||
|                        logic icaf; | ||||
|                        logic icaf_f1; | ||||
|                        logic icaf_second; | ||||
|                        logic [1:0] icaf_type; | ||||
|                        logic fence_i; | ||||
|                        logic [3:0] i0trigger; | ||||
|                        el2_inst_pkt_t pmu_i0_itype;        // pmu - instruction type
 | ||||
|                        logic pmu_i0_br_unpred;     // pmu
 | ||||
|                        logic pmu_divide; | ||||
|                        // likely to change
 | ||||
|                        logic legal; | ||||
|                        logic pmu_lsu_misaligned; | ||||
|                        el2_inst_pkt_t pmu_i0_itype;        // pmu - instruction type
 | ||||
|                        } el2_trap_pkt_t; | ||||
| 
 | ||||
| typedef struct packed { | ||||
|                        logic [4:0] i0rd; | ||||
|                        logic i0load; | ||||
|                        logic i0store; | ||||
|                        // unlikely to change
 | ||||
|                        logic i0div; | ||||
|                        logic i0v; | ||||
|                        logic i0valid; | ||||
|                        logic csrwen; | ||||
|                        logic csrwonly; | ||||
|                        logic [11:0] csrwaddr; | ||||
|                        // likely to change
 | ||||
|                        logic [4:0] i0rd; | ||||
|                        logic i0load; | ||||
|                        logic i0store; | ||||
|                        logic i0v; | ||||
|                        logic i0valid; | ||||
|                        } el2_dest_pkt_t; | ||||
| 
 | ||||
| typedef struct packed { | ||||
|  | @ -122,6 +127,31 @@ typedef struct packed { | |||
| 
 | ||||
| 
 | ||||
| typedef struct packed { | ||||
|                        logic clz; | ||||
|                        logic ctz; | ||||
|                        logic pcnt; | ||||
|                        logic sext_b; | ||||
|                        logic sext_h; | ||||
|                        logic slo; | ||||
|                        logic sro; | ||||
|                        logic min; | ||||
|                        logic max; | ||||
|                        logic pack; | ||||
|                        logic packu; | ||||
|                        logic packh; | ||||
|                        logic rol; | ||||
|                        logic ror; | ||||
|                        logic grev; | ||||
|                        logic gorc; | ||||
|                        logic zbb; | ||||
|                        logic sbset; | ||||
|                        logic sbclr; | ||||
|                        logic sbinv; | ||||
|                        logic sbext; | ||||
|                        logic sh1add; | ||||
|                        logic sh2add; | ||||
|                        logic sh3add; | ||||
|                        logic zba; | ||||
|                        logic land; | ||||
|                        logic lor; | ||||
|                        logic lxor; | ||||
|  | @ -145,6 +175,9 @@ typedef struct packed { | |||
| 
 | ||||
| typedef struct packed { | ||||
|                        logic fast_int; | ||||
| /* verilator lint_off SYMRSVDWORD */ | ||||
|                        logic stack; | ||||
| /* verilator lint_on SYMRSVDWORD */ | ||||
|                        logic by; | ||||
|                        logic half; | ||||
|                        logic word; | ||||
|  | @ -160,15 +193,61 @@ typedef struct packed { | |||
|                        } el2_lsu_pkt_t; | ||||
| 
 | ||||
| typedef struct packed { | ||||
|                       logic exc_valid; | ||||
|                       logic single_ecc_error; | ||||
|                       logic inst_type;   //0: Load, 1: Store
 | ||||
|                       //logic dma_valid;
 | ||||
|                       logic exc_type;    //0: MisAligned, 1: Access Fault
 | ||||
|                       logic [3:0] mscause; | ||||
|                       logic [31:0] addr; | ||||
|                       logic single_ecc_error; | ||||
|                       logic exc_valid; | ||||
|                       } el2_lsu_error_pkt_t; | ||||
| 
 | ||||
| typedef struct packed { | ||||
|                        logic clz; | ||||
|                        logic ctz; | ||||
|                        logic pcnt; | ||||
|                        logic sext_b; | ||||
|                        logic sext_h; | ||||
|                        logic slo; | ||||
|                        logic sro; | ||||
|                        logic min; | ||||
|                        logic max; | ||||
|                        logic pack; | ||||
|                        logic packu; | ||||
|                        logic packh; | ||||
|                        logic rol; | ||||
|                        logic ror; | ||||
|                        logic grev; | ||||
|                        logic gorc; | ||||
|                        logic zbb; | ||||
|                        logic sbset; | ||||
|                        logic sbclr; | ||||
|                        logic sbinv; | ||||
|                        logic sbext; | ||||
|                        logic zbs; | ||||
|                        logic bext; | ||||
|                        logic bdep; | ||||
|                        logic zbe; | ||||
|                        logic clmul; | ||||
|                        logic clmulh; | ||||
|                        logic clmulr; | ||||
|                        logic zbc; | ||||
|                        logic shfl; | ||||
|                        logic unshfl; | ||||
|                        logic zbp; | ||||
|                        logic crc32_b; | ||||
|                        logic crc32_h; | ||||
|                        logic crc32_w; | ||||
|                        logic crc32c_b; | ||||
|                        logic crc32c_h; | ||||
|                        logic crc32c_w; | ||||
|                        logic zbr; | ||||
|                        logic bfp; | ||||
|                        logic zbf; | ||||
|                        logic sh1add; | ||||
|                        logic sh2add; | ||||
|                        logic sh3add; | ||||
|                        logic zba; | ||||
|                        logic alu; | ||||
|                        logic rs1; | ||||
|                        logic rs2; | ||||
|  | @ -233,6 +312,7 @@ typedef struct packed { | |||
|                        logic clmulh; | ||||
|                        logic clmulr; | ||||
|                        logic grev; | ||||
|                        logic gorc; | ||||
|                        logic shfl; | ||||
|                        logic unshfl; | ||||
|                        logic crc32_b; | ||||
|  | @ -320,6 +400,6 @@ typedef struct packed { | |||
|                         logic         icache_rd_valid; | ||||
|                         logic         icache_wr_valid; | ||||
|             } el2_cache_debug_pkt_t; | ||||
| 
 | ||||
| //`endif
 | ||||
| 
 | ||||
| endpackage // el2_pkg
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -119,8 +119,8 @@ import el2_pkg::*; | |||
|    // 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; | ||||
|    logic                    ahb_addr_clk_en, buf_rdata_clk_en; | ||||
|    logic                    bus_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; | ||||
|  | @ -130,8 +130,6 @@ import el2_pkg::*; | |||
|    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; | ||||
|  | @ -163,7 +161,7 @@ import el2_pkg::*; | |||
|      endcase | ||||
|    end // always_comb begin
 | ||||
| 
 | ||||
|     rvdffs #($bits(state_t)) state_reg (.*, .din(buf_nxtstate), .dout({buf_state}), .en(buf_state_en), .clk(ahb_clk)); | ||||
|     rvdffs_fpga #($bits(state_t)) state_reg (.*, .din(buf_nxtstate), .dout({buf_state}), .en(buf_state_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(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])) | | ||||
|  | @ -188,24 +186,16 @@ import el2_pkg::*; | |||
|                              (ahb_hresp_q & ~ahb_hready_q); | ||||
| 
 | ||||
|    // 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
 | ||||
|    rvdff_fpga  #(.WIDTH(64)) buf_rdata_ff     (.din(axi_rdata[63:0]),   .dout(buf_rdata[63:0]), .clk(buf_rdata_clk), .clken(buf_rdata_clk_en), .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(1))  buf_read_error_ff(.din(buf_read_error_in), .dout(buf_read_error),  .clk(bus_clk),       .clken(bus_clk_en),       .rawclk(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), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))  hresp_ff  (.din(ahb_hresp),          .dout(ahb_hresp_q),       .clk(bus_clk),      .clken(bus_clk_en),      .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))  hready_ff (.din(ahb_hready),         .dout(ahb_hready_q),      .clk(bus_clk),      .clken(bus_clk_en),      .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(2))  htrans_ff (.din(ahb_htrans_in[1:0]), .dout(ahb_htrans_q[1:0]), .clk(bus_clk),      .clken(bus_clk_en),      .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(3))  hsize_ff  (.din(ahb_hsize[2:0]),     .dout(ahb_hsize_q[2:0]),  .clk(ahb_addr_clk), .clken(ahb_addr_clk_en), .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))  hwrite_ff (.din(ahb_hwrite),         .dout(ahb_hwrite_q),      .clk(ahb_addr_clk), .clken(ahb_addr_clk_en), .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(32)) haddr_ff  (.din(ahb_haddr[31:0]),    .dout(ahb_haddr_q[31:0]), .clk(ahb_addr_clk), .clken(ahb_addr_clk_en), .rawclk(clk), .*); | ||||
| 
 | ||||
|    // Address check  dccm
 | ||||
|    rvrangecheck #(.CCM_SADR(pt.DCCM_SADR), | ||||
|  | @ -240,12 +230,12 @@ import el2_pkg::*; | |||
|    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), .*); | ||||
|    rvdffsc_fpga #(.WIDTH(1))  cmdbuf_vldff      (.din(1'b1),              .dout(cmdbuf_vld),         .en(cmdbuf_wr_en), .clear(cmdbuf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga  #(.WIDTH(1))  cmdbuf_writeff    (.din(ahb_hwrite_q),      .dout(cmdbuf_write),       .en(cmdbuf_wr_en),                     .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga  #(.WIDTH(2))  cmdbuf_sizeff     (.din(ahb_hsize_q[1:0]),  .dout(cmdbuf_size[1:0]),   .en(cmdbuf_wr_en),                     .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga  #(.WIDTH(8))  cmdbuf_wstrbff    (.din(master_wstrb[7:0]), .dout(cmdbuf_wstrb[7:0]),  .en(cmdbuf_wr_en),                     .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffe       #(.WIDTH(32)) cmdbuf_addrff     (.din(ahb_haddr_q[31:0]), .dout(cmdbuf_addr[31:0]),  .en(cmdbuf_wr_en & bus_clk_en),        .clk(clk), .*); | ||||
|    rvdffe       #(.WIDTH(64)) cmdbuf_wdataff    (.din(ahb_hwdata[63:0]),  .dout(cmdbuf_wdata[63:0]), .en(cmdbuf_wr_en & bus_clk_en),        .clk(clk), .*); | ||||
| 
 | ||||
|    // AXI Write Command Channel
 | ||||
|    assign axi_awvalid           = cmdbuf_vld & cmdbuf_write; | ||||
|  | @ -274,11 +264,22 @@ import el2_pkg::*; | |||
|    assign axi_rready            = 1'b1; | ||||
| 
 | ||||
|    // Clock header logic
 | ||||
|    rvclkhdr bus_cgc        (.en(bus_clk_en),       .l1clk(bus_clk),       .*); | ||||
|    assign ahb_addr_clk_en = bus_clk_en & (ahb_hready & ahb_htrans[1]); | ||||
|    assign buf_rdata_clk_en    = bus_clk_en & buf_rdata_en; | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    assign bus_clk = 1'b0; | ||||
|    assign ahb_addr_clk = 1'b0; | ||||
|    assign buf_rdata_clk = 1'b0; | ||||
| `else | ||||
|    rvclkhdr bus_cgc       (.en(bus_clk_en),       .l1clk(bus_clk),       .*); | ||||
|    rvclkhdr ahb_addr_cgc  (.en(ahb_addr_clk_en),  .l1clk(ahb_addr_clk),  .*); | ||||
|    rvclkhdr buf_rdata_cgc (.en(buf_rdata_clk_en), .l1clk(buf_rdata_clk), .*); | ||||
| `endif | ||||
| 
 | ||||
| `ifdef RV_ASSERT_ON | ||||
|    property ahb_error_protocol; | ||||
|       @(posedge ahb_clk) (ahb_hready & ahb_hresp) |-> (~$past(ahb_hready) & $past(ahb_hresp)); | ||||
|       @(posedge bus_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"); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -28,10 +28,12 @@ import el2_pkg::*; | |||
| ,parameter TAG  = 1) ( | ||||
| 
 | ||||
|    input                   clk, | ||||
|    input                   free_clk, | ||||
|    input                   rst_l, | ||||
|    input                   scan_mode, | ||||
|    input                   bus_clk_en, | ||||
|    input                   clk_override, | ||||
|    input                   dec_tlu_force_halt, | ||||
| 
 | ||||
|    // AXI signals
 | ||||
|    // AXI Write Channels
 | ||||
|  | @ -105,9 +107,6 @@ import el2_pkg::*; | |||
|    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; | ||||
|  | @ -169,15 +168,15 @@ import el2_pkg::*; | |||
|    logic [31:0]                last_bus_addr; | ||||
| 
 | ||||
|    // Clocks
 | ||||
|    logic                       buf_clken, slvbuf_clken; | ||||
|    logic                       ahbm_addr_clken; | ||||
|    logic                       buf_clken; | ||||
|    logic                       ahbm_data_clken; | ||||
| 
 | ||||
|    logic                       buf_clk, slvbuf_clk; | ||||
|    logic                       ahbm_clk; | ||||
|    logic                       ahbm_addr_clk; | ||||
|    logic                       buf_clk; | ||||
|    logic                       bus_clk; | ||||
|    logic                       ahbm_data_clk; | ||||
| 
 | ||||
|    logic                       dec_tlu_force_halt_bus, dec_tlu_force_halt_bus_ns, dec_tlu_force_halt_bus_q; | ||||
| 
 | ||||
|    // Function to get the length from byte enable
 | ||||
|    function automatic logic [1:0] get_write_size; | ||||
|       input logic [7:0] byteen; | ||||
|  | @ -210,6 +209,7 @@ import el2_pkg::*; | |||
|       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 | ||||
|  | @ -219,12 +219,16 @@ import el2_pkg::*; | |||
|       end | ||||
|    endfunction // get_nextbyte_ptr
 | ||||
| 
 | ||||
|    // Create bus synchronized version of force halt
 | ||||
|    assign dec_tlu_force_halt_bus = dec_tlu_force_halt | dec_tlu_force_halt_bus_q; | ||||
|    assign dec_tlu_force_halt_bus_ns = ~bus_clk_en & dec_tlu_force_halt_bus; | ||||
|    rvdff  #(.WIDTH(1))   force_halt_busff(.din(dec_tlu_force_halt_bus_ns), .dout(dec_tlu_force_halt_bus_q), .clk(free_clk), .*); | ||||
| 
 | ||||
|    // 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 wrbuf_rst      = (wrbuf_cmd_sent & ~wrbuf_en) | dec_tlu_force_halt_bus; | ||||
| 
 | ||||
|    assign axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent) & master_ready; | ||||
|    assign axi_wready  = ~(wrbuf_data_vld & ~wrbuf_cmd_sent) & master_ready; | ||||
|  | @ -251,13 +255,6 @@ import el2_pkg::*; | |||
|    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; | ||||
|  | @ -378,7 +375,7 @@ import el2_pkg::*; | |||
|       endcase | ||||
|    end | ||||
| 
 | ||||
|    assign buf_rst              = 1'b0; | ||||
|    assign buf_rst              = dec_tlu_force_halt_bus; | ||||
|    assign cmd_done_rst         = slave_valid_pre; | ||||
|    assign buf_addr_in[31:3]    = master_addr[31:3]; | ||||
|    assign buf_addr_in[2:0]     = (buf_aligned_in & (master_opc[2:1] == 2'b01)) ? get_write_addr(master_byteen[7:0]) : master_addr[2:0]; | ||||
|  | @ -393,7 +390,8 @@ import el2_pkg::*; | |||
|                                    (master_byteen[7:0] == 8'hf)  | (master_byteen[7:0] == 8'hf0)  | (master_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_haddr[31:3] = bypass_en ? master_addr[31:3]  : buf_addr[31:3]; | ||||
|    assign ahb_haddr[2:0]  = {3{(ahb_htrans == 2'b10)}} & buf_cmd_byte_ptr[2:0];    // Trxn should be aligned during IDLE
 | ||||
|    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; | ||||
|  | @ -402,7 +400,7 @@ import el2_pkg::*; | |||
|    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_valid          = slave_valid_pre;// & (~slvbuf_posted_write | slvbuf_error);
 | ||||
|    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]); | ||||
|  | @ -411,53 +409,57 @@ import el2_pkg::*; | |||
|    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), .*); | ||||
|    rvdffsc_fpga #(.WIDTH(1))   wrbuf_vldff     (.din(1'b1),              .dout(wrbuf_vld),          .en(wrbuf_en),      .clear(wrbuf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffsc_fpga #(.WIDTH(1))   wrbuf_data_vldff(.din(1'b1),              .dout(wrbuf_data_vld),     .en(wrbuf_data_en), .clear(wrbuf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga  #(.WIDTH(TAG)) wrbuf_tagff     (.din(axi_awid[TAG-1:0]), .dout(wrbuf_tag[TAG-1:0]), .en(wrbuf_en),                         .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga  #(.WIDTH(3))   wrbuf_sizeff    (.din(axi_awsize[2:0]),   .dout(wrbuf_size[2:0]),    .en(wrbuf_en),                         .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffe       #(.WIDTH(32))  wrbuf_addrff    (.din(axi_awaddr[31:0]),  .dout(wrbuf_addr[31:0]),   .en(wrbuf_en & bus_clk_en),            .clk(clk), .*); | ||||
|    rvdffe       #(.WIDTH(64))  wrbuf_dataff    (.din(axi_wdata[63:0]),   .dout(wrbuf_data[63:0]),   .en(wrbuf_data_en & bus_clk_en),       .clk(clk), .*); | ||||
|    rvdffs_fpga  #(.WIDTH(8))   wrbuf_byteenff  (.din(axi_wstrb[7:0]),    .dout(wrbuf_byteen[7:0]),  .en(wrbuf_data_en),                    .clk(bus_clk), .clken(bus_clk_en), .rawclk(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), .*); | ||||
|    rvdffs_fpga #(.WIDTH(32))   last_bus_addrff (.din(ahb_haddr[31:0]),   .dout(last_bus_addr[31:0]), .en(last_addr_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(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), .*); | ||||
|    rvdffsc_fpga #(.WIDTH($bits(state_t))) buf_state_ff  (.din(buf_nxtstate),        .dout({buf_state}),      .en(buf_state_en), .clear(buf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(1))               buf_writeff   (.din(buf_write_in),        .dout(buf_write),        .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(TAG))             buf_tagff     (.din(buf_tag_in[TAG-1:0]), .dout(buf_tag[TAG-1:0]), .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*); | ||||
|    rvdffe      #(.WIDTH(32))              buf_addrff    (.din(buf_addr_in[31:0]),   .dout(buf_addr[31:0]),   .en(buf_wr_en & bus_clk_en),        .clk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(2))               buf_sizeff    (.din(buf_size_in[1:0]),    .dout(buf_size[1:0]),    .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(1))               buf_alignedff (.din(buf_aligned_in),      .dout(buf_aligned),      .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(8))               buf_byteenff  (.din(buf_byteen_in[7:0]),  .dout(buf_byteen[7:0]),  .en(buf_wr_en),                     .clk(buf_clk), .clken(buf_clken),  .rawclk(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),   .clk(clk), .*); | ||||
| 
 | ||||
| 
 | ||||
|    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), .*); | ||||
|    rvdffs_fpga #(.WIDTH(1))   slvbuf_writeff  (.din(buf_write),        .dout(slvbuf_write),        .en(slvbuf_wr_en),    .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(TAG)) slvbuf_tagff    (.din(buf_tag[TAG-1:0]), .dout(slvbuf_tag[TAG-1:0]), .en(slvbuf_wr_en),    .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(1))   slvbuf_errorff  (.din(slvbuf_error_in),  .dout(slvbuf_error),        .en(slvbuf_error_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(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), .*); | ||||
|    rvdffsc_fpga #(.WIDTH(1)) buf_cmd_doneff     (.din(1'b1),                  .dout(cmd_doneQ),              .en(cmd_done),            .clear(cmd_done_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.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(bus_clk), .clken(bus_clk_en), .rawclk(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), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))  hready_ff (.din(ahb_hready),       .dout(ahb_hready_q),       .clk(bus_clk),       .clken(bus_clk_en),      .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(2))  htrans_ff (.din(ahb_htrans[1:0]),  .dout(ahb_htrans_q[1:0]),  .clk(bus_clk),       .clken(bus_clk_en),      .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))  hwrite_ff (.din(ahb_hwrite),       .dout(ahb_hwrite_q),       .clk(bus_clk),       .clken(bus_clk_en),      .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))  hresp_ff  (.din(ahb_hresp),        .dout(ahb_hresp_q),        .clk(bus_clk),       .clken(bus_clk_en),      .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(64)) hrdata_ff (.din(ahb_hrdata[63:0]), .dout(ahb_hrdata_q[63:0]), .clk(ahbm_data_clk), .clken(ahbm_data_clken), .rawclk(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), .*); | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    assign bus_clk = 1'b0; | ||||
|    assign buf_clk = 1'b0; | ||||
|    assign ahbm_data_clk = 1'b0; | ||||
| `else | ||||
|    rvclkhdr bus_cgc       (.en(bus_clk_en),      .l1clk(bus_clk),       .*); | ||||
|    rvclkhdr buf_cgc       (.en(buf_clken),       .l1clk(buf_clk), .*); | ||||
|    rvclkhdr ahbm_data_cgc (.en(ahbm_data_clken), .l1clk(ahbm_data_clk), .*); | ||||
| `endif | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_ASSERT_ON | ||||
|    property ahb_trxn_aligned; | ||||
|      @(posedge ahbm_clk) ahb_htrans[1]  |-> ((ahb_hsize[2:0] == 3'h0)                              | | ||||
|      @(posedge bus_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))); | ||||
|  | @ -466,7 +468,7 @@ import el2_pkg::*; | |||
|      $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)); | ||||
|       @(posedge bus_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"); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -29,7 +29,7 @@ if (SHORT == 1) begin | |||
|    assign dout = din; | ||||
| end | ||||
| else begin | ||||
| `ifdef CLOCKGATE | ||||
| `ifdef RV_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 | ||||
|  | @ -85,7 +85,85 @@ else begin | |||
| end | ||||
| endmodule | ||||
| 
 | ||||
| module rvdffe #( parameter WIDTH=1, SHORT=0 ) | ||||
| // _fpga versions
 | ||||
| module rvdff_fpga #( parameter WIDTH=1, SHORT=0 ) | ||||
|    ( | ||||
|      input logic [WIDTH-1:0] din, | ||||
|      input logic           clk, | ||||
|      input logic           clken, | ||||
|      input logic           rawclk, | ||||
|      input logic           rst_l, | ||||
| 
 | ||||
|      output logic [WIDTH-1:0] dout | ||||
|      ); | ||||
| 
 | ||||
| if (SHORT == 1) begin | ||||
|    assign dout = din; | ||||
| end | ||||
| else begin | ||||
|    `ifdef RV_FPGA_OPTIMIZE | ||||
|     rvdffs #(WIDTH) dffs (.clk(rawclk), .en(clken), .*); | ||||
| `else | ||||
|     rvdff #(WIDTH)  dff (.*); | ||||
| `endif | ||||
| end | ||||
| endmodule | ||||
| 
 | ||||
| // rvdff with 2:1 input mux to flop din iff sel==1
 | ||||
| module rvdffs_fpga #( parameter WIDTH=1, SHORT=0 ) | ||||
|    ( | ||||
|      input logic [WIDTH-1:0] din, | ||||
|      input logic             en, | ||||
|      input logic           clk, | ||||
|      input logic           clken, | ||||
|      input logic           rawclk, | ||||
|      input logic           rst_l, | ||||
| 
 | ||||
|      output logic [WIDTH-1:0] dout | ||||
|      ); | ||||
| 
 | ||||
| if (SHORT == 1) begin : genblock | ||||
|    assign dout = din; | ||||
| end | ||||
| else begin : genblock | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    rvdffs #(WIDTH)   dffs (.clk(rawclk), .en(clken & en), .*); | ||||
| `else | ||||
|    rvdffs #(WIDTH)   dffs (.*); | ||||
| `endif | ||||
| end | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // rvdff with en and clear
 | ||||
| module rvdffsc_fpga #( parameter WIDTH=1, SHORT=0 ) | ||||
|    ( | ||||
|      input logic [WIDTH-1:0] din, | ||||
|      input logic             en, | ||||
|      input logic             clear, | ||||
|      input logic             clk, | ||||
|      input logic             clken, | ||||
|      input logic             rawclk, | ||||
|      input logic             rst_l, | ||||
| 
 | ||||
|      output logic [WIDTH-1:0] dout | ||||
|      ); | ||||
| 
 | ||||
|    logic [WIDTH-1:0]          din_new; | ||||
| if (SHORT == 1) begin | ||||
|    assign dout = din; | ||||
| end | ||||
| else begin | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    rvdffs  #(WIDTH)   dffs  (.clk(rawclk), .din(din[WIDTH-1:0] & {WIDTH{~clear}}),.en((en | clear) & clken), .*); | ||||
| `else | ||||
|    rvdffsc #(WIDTH)   dffsc (.*); | ||||
| `endif | ||||
| end | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
| module rvdffe #( parameter WIDTH=1, SHORT=0, OVERRIDE=0 ) | ||||
|    ( | ||||
|      input  logic [WIDTH-1:0] din, | ||||
|      input  logic           en, | ||||
|  | @ -104,8 +182,8 @@ if (SHORT == 1) begin : genblock | |||
| end | ||||
| else begin : genblock | ||||
| 
 | ||||
| `ifndef PHYSICAL | ||||
|    if (WIDTH >= 8) begin: genblock | ||||
| `ifndef RV_PHYSICAL | ||||
|    if (WIDTH >= 8 || OVERRIDE==1) begin: genblock | ||||
| `endif | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|  | @ -115,15 +193,226 @@ else begin : genblock | |||
|       rvdff #(WIDTH) dff (.*, .clk(l1clk)); | ||||
| `endif | ||||
| 
 | ||||
| `ifndef PHYSICAL | ||||
| `ifndef RV_PHYSICAL | ||||
|    end | ||||
|    else | ||||
|       $error("%m: rvdffe width must be >= 8"); | ||||
|       $error("%m: rvdffe must be WIDTH >= 8"); | ||||
| `endif | ||||
| end // else: !if(SHORT == 1)
 | ||||
| 
 | ||||
| endmodule // rvdffe
 | ||||
| 
 | ||||
| 
 | ||||
| module rvdffpcie #( parameter WIDTH=31 ) | ||||
|    ( | ||||
|      input  logic [WIDTH-1:0] din, | ||||
|      input  logic             clk, | ||||
|      input  logic             rst_l, | ||||
|      input  logic             en, | ||||
|      input  logic             scan_mode, | ||||
|      output logic [WIDTH-1:0] dout | ||||
|      ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    if (WIDTH == 31) begin: genblock | ||||
| `endif | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|       rvdffs #(WIDTH) dff ( .* ); | ||||
| `else | ||||
| 
 | ||||
|       rvdfflie #(.WIDTH(WIDTH), .LEFT(19)) dff (.*); | ||||
| 
 | ||||
| `endif | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    end | ||||
|    else | ||||
|       $error("%m: rvdffpcie width must be 31"); | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| // format: { LEFT, EXTRA }
 | ||||
| // LEFT # of bits will be done with rvdffie, all else EXTRA with rvdffe
 | ||||
| module rvdfflie #( parameter WIDTH=16, LEFT=8 ) | ||||
|    ( | ||||
|      input  logic [WIDTH-1:0] din, | ||||
|      input  logic             clk, | ||||
|      input  logic             rst_l, | ||||
|      input  logic             en, | ||||
|      input  logic             scan_mode, | ||||
|      output logic [WIDTH-1:0] dout | ||||
|      ); | ||||
| 
 | ||||
|    localparam EXTRA = WIDTH-LEFT; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|    localparam LMSB = WIDTH-1; | ||||
|    localparam LLSB = LMSB-LEFT+1; | ||||
|    localparam XMSB = LLSB-1; | ||||
|    localparam XLSB = LLSB-EXTRA; | ||||
| 
 | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    if (WIDTH >= 16 && LEFT >= 8 && EXTRA >= 8) begin: genblock | ||||
| `endif | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|       rvdffs #(WIDTH) dff ( .* ); | ||||
| `else | ||||
| 
 | ||||
|       rvdffiee #(LEFT)  dff_left  (.*, .din(din[LMSB:LLSB]), .dout(dout[LMSB:LLSB])); | ||||
| 
 | ||||
| 
 | ||||
|       rvdffe  #(EXTRA)  dff_extra (.*, .din(din[XMSB:XLSB]), .dout(dout[XMSB:XLSB])); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| `endif | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    end | ||||
|    else | ||||
|       $error("%m: rvdfflie musb be WIDTH >= 16 && LEFT >= 8 && EXTRA >= 8"); | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| // special power flop for predict packet
 | ||||
| // format: { LEFT, RIGHT==31 }
 | ||||
| // LEFT # of bits will be done with rvdffe; RIGHT is enabled by LEFT[LSB] & en
 | ||||
| module rvdffppe #( parameter WIDTH=32 ) | ||||
|    ( | ||||
|      input  logic [WIDTH-1:0] din, | ||||
|      input  logic             clk, | ||||
|      input  logic             rst_l, | ||||
|      input  logic             en, | ||||
|      input  logic             scan_mode, | ||||
|      output logic [WIDTH-1:0] dout | ||||
|      ); | ||||
| 
 | ||||
|    localparam RIGHT = 31; | ||||
|    localparam LEFT = WIDTH - RIGHT; | ||||
| 
 | ||||
|    localparam LMSB = WIDTH-1; | ||||
|    localparam LLSB = LMSB-LEFT+1; | ||||
|    localparam RMSB = LLSB-1; | ||||
|    localparam RLSB = LLSB-RIGHT; | ||||
| 
 | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    if (WIDTH>=32 && LEFT>=8 && RIGHT>=8) begin: genblock | ||||
| `endif | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|       rvdffs #(WIDTH) dff ( .* ); | ||||
| `else | ||||
|       rvdffe #(LEFT)     dff_left (.*, .din(din[LMSB:LLSB]), .dout(dout[LMSB:LLSB])); | ||||
| 
 | ||||
|       rvdffe #(RIGHT)   dff_right (.*, .din(din[RMSB:RLSB]), .dout(dout[RMSB:RLSB]), .en(en & din[LLSB]));  // qualify with pret
 | ||||
| 
 | ||||
| 
 | ||||
| `endif | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    end | ||||
|    else | ||||
|       $error("%m: must be WIDTH>=32 && LEFT>=8 && RIGHT>=8"); | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| module rvdffie #( parameter WIDTH=1, OVERRIDE=0 ) | ||||
|    ( | ||||
|      input  logic [WIDTH-1:0] din, | ||||
| 
 | ||||
|      input  logic           clk, | ||||
|      input  logic           rst_l, | ||||
|      input  logic             scan_mode, | ||||
|      output logic [WIDTH-1:0] dout | ||||
|      ); | ||||
| 
 | ||||
|    logic                      l1clk; | ||||
|    logic                      en; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    if (WIDTH >= 8 || OVERRIDE==1) begin: genblock | ||||
| `endif | ||||
| 
 | ||||
|       assign en = |(din ^ dout); | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|       rvdffs #(WIDTH) dff ( .* ); | ||||
| `else | ||||
|       rvclkhdr clkhdr ( .* ); | ||||
|       rvdff #(WIDTH) dff (.*, .clk(l1clk)); | ||||
| `endif | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    end | ||||
|    else | ||||
|      $error("%m: rvdffie must be WIDTH >= 8"); | ||||
| `endif | ||||
| 
 | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // ie flop but it has an .en input
 | ||||
| module rvdffiee #( parameter WIDTH=1, OVERRIDE=0 ) | ||||
|    ( | ||||
|      input  logic [WIDTH-1:0] din, | ||||
| 
 | ||||
|      input  logic           clk, | ||||
|      input  logic           rst_l, | ||||
|      input  logic           scan_mode, | ||||
|      input  logic           en, | ||||
|      output logic [WIDTH-1:0] dout | ||||
|      ); | ||||
| 
 | ||||
|    logic                      l1clk; | ||||
|    logic                      final_en; | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    if (WIDTH >= 8 || OVERRIDE==1) begin: genblock | ||||
| `endif | ||||
| 
 | ||||
|       assign final_en = (|(din ^ dout)) & en; | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|       rvdffs #(WIDTH) dff ( .*, .en(final_en) ); | ||||
| `else | ||||
|       rvdffe #(WIDTH) dff (.*,  .en(final_en)); | ||||
| `endif | ||||
| 
 | ||||
| `ifndef RV_PHYSICAL | ||||
|    end | ||||
|    else | ||||
|       $error("%m: rvdffie width must be >= 8"); | ||||
| `endif | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| module rvsyncss #(parameter WIDTH = 251) | ||||
|    ( | ||||
|      input  logic                 clk, | ||||
|  | @ -139,6 +428,23 @@ module rvsyncss #(parameter WIDTH = 251) | |||
| 
 | ||||
| endmodule // rvsyncss
 | ||||
| 
 | ||||
| module rvsyncss_fpga #(parameter WIDTH = 251) | ||||
|    ( | ||||
|      input  logic                 gw_clk, | ||||
|      input  logic                 rawclk, | ||||
|      input  logic                 clken, | ||||
|      input  logic                 rst_l, | ||||
|      input  logic [WIDTH-1:0]     din, | ||||
|      output logic [WIDTH-1:0]     dout | ||||
|      ); | ||||
| 
 | ||||
|    logic [WIDTH-1:0]              din_ff1; | ||||
| 
 | ||||
|    rvdff_fpga #(WIDTH) sync_ff1  (.*, .clk(gw_clk), .rawclk(rawclk), .clken(clken), .din (din[WIDTH-1:0]),     .dout(din_ff1[WIDTH-1:0])); | ||||
|    rvdff_fpga #(WIDTH) sync_ff2  (.*, .clk(gw_clk), .rawclk(rawclk), .clken(clken), .din (din_ff1[WIDTH-1:0]), .dout(dout[WIDTH-1:0])); | ||||
| 
 | ||||
| endmodule // rvsyncss
 | ||||
| 
 | ||||
| module rvlsadder | ||||
|   ( | ||||
|     input logic [31:0] rs1, | ||||
|  | @ -468,6 +774,7 @@ module `TEC_RV_ICG | |||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| `ifndef RV_FPGA_OPTIMIZE | ||||
| module rvclkhdr | ||||
|   ( | ||||
|    input  logic en, | ||||
|  | @ -477,11 +784,12 @@ module rvclkhdr | |||
|    ); | ||||
| 
 | ||||
|    logic   SE; | ||||
|    assign       SE = scan_mode; | ||||
|    assign       SE = 0; | ||||
| 
 | ||||
|    `TEC_RV_ICG clkhdr ( .*, .EN(en), .CK(clk), .Q(l1clk)); | ||||
| 
 | ||||
| endmodule // rvclkhdr
 | ||||
| `endif | ||||
| 
 | ||||
| module rvoclkhdr | ||||
|   ( | ||||
|  | @ -492,7 +800,7 @@ module rvoclkhdr | |||
|    ); | ||||
| 
 | ||||
|    logic   SE; | ||||
|    assign       SE = scan_mode; | ||||
|    assign       SE = 0; | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    assign l1clk = clk; | ||||
|  |  | |||
|  | @ -16,7 +16,17 @@ | |||
| `define EL2_LOCAL_RAM_TEST_IO          \ | ||||
| input logic WE,              \ | ||||
| input logic ME,              \ | ||||
| input logic CLK | ||||
| input logic CLK,             \ | ||||
| input logic TEST1,           \ | ||||
| input logic RME,             \ | ||||
| input logic  [3:0] RM,       \ | ||||
| input logic LS,              \ | ||||
| input logic DS,              \ | ||||
| input logic SD,              \ | ||||
| input logic TEST_RNM,        \ | ||||
| input logic BC1,             \ | ||||
| input logic BC2,             \ | ||||
| output logic ROP | ||||
| 
 | ||||
| `define EL2_RAM(depth, width)              \ | ||||
| module ram_``depth``x``width(               \ | ||||
|  | @ -26,11 +36,22 @@ module ram_``depth``x``width(               \ | |||
|     `EL2_LOCAL_RAM_TEST_IO                 \ | ||||
| );                                          \ | ||||
| reg [(width-1):0] ram_core [(depth-1):0];   \ | ||||
|                                             \ | ||||
| always @(posedge CLK) begin              \ | ||||
| `ifdef GTLSIM                               \ | ||||
| integer i;                                  \ | ||||
| initial begin                               \ | ||||
|    for (i=0; i<depth; i=i+1)                \ | ||||
|      ram_core[i] = '0;                      \ | ||||
| end                                         \ | ||||
| `endif                                      \ | ||||
| always @(posedge CLK) begin                 \ | ||||
| `ifdef GTLSIM                               \ | ||||
|    if (ME && WE) ram_core[ADR] <= D;        \ | ||||
| `else                                       \ | ||||
|    if (ME && WE) begin ram_core[ADR] <= D; Q <= 'x; end  \ | ||||
| `endif                                      \ | ||||
|    if (ME && ~WE) Q <= ram_core[ADR];       \ | ||||
| end                                         \ | ||||
| assign ROP = ME;                            \ | ||||
|                                             \ | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -42,12 +63,22 @@ module ram_be_``depth``x``width(            \ | |||
|     `EL2_LOCAL_RAM_TEST_IO                 \ | ||||
| );                                          \ | ||||
| reg [(width-1):0] ram_core [(depth-1):0];   \ | ||||
|                                             \ | ||||
| always @(posedge CLK) begin              \ | ||||
|    if (ME && WE) ram_core[ADR] = D & WEM | ~WEM & ram_core[ADR];\ | ||||
|    if (ME && ~WE) Q <= ram_core[ADR];       \ | ||||
| `ifdef GTLSIM                               \ | ||||
| integer i;                                  \ | ||||
| initial begin                               \ | ||||
|    for (i=0; i<depth; i=i+1)                \ | ||||
|      ram_core[i] = '0;                      \ | ||||
| end                                         \ | ||||
|                                             \ | ||||
| `endif                                      \ | ||||
| always @(posedge CLK) begin                 \ | ||||
| `ifdef GTLSIM                               \ | ||||
|    if (ME && WE)       ram_core[ADR] <= D & WEM | ~WEM & ram_core[ADR];      \ | ||||
| `else                                       \ | ||||
|    if (ME && WE) begin ram_core[ADR] <= D & WEM | ~WEM & ram_core[ADR]; Q <= 'x; end  \ | ||||
| `endif                                      \ | ||||
|    if (ME && ~WE) Q <= ram_core[ADR];          \ | ||||
| end                                         \ | ||||
| assign ROP = ME;                            \ | ||||
|                                             \ | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -61,7 +92,11 @@ output logic [(width-1):0] Q, | |||
| reg [(width-1):0] ram_core [(depth-1):0]; | ||||
| 
 | ||||
| always @(posedge CLK) begin | ||||
|    if (ME && WE) ram_core[ADR] = D; | ||||
| `ifdef GTLSIM | ||||
|    if (ME && WE)       ram_core[ADR] <= D; | ||||
| `else | ||||
|    if (ME && WE) begin ram_core[ADR] <= D; Q <= 'x; end | ||||
| `endif | ||||
|    if (ME && ~WE) Q <= ram_core[ADR]; | ||||
| end | ||||
| endmodule | ||||
|  | @ -172,6 +207,7 @@ endmodule | |||
| `EL2_RAM_BE(256, 52) | ||||
| `EL2_RAM_BE(128, 52) | ||||
| `EL2_RAM_BE(64, 52) | ||||
| `EL2_RAM_BE(32, 52) | ||||
| `EL2_RAM_BE(4096, 104) | ||||
| `EL2_RAM_BE(2048, 104) | ||||
| `EL2_RAM_BE(1024, 104) | ||||
|  | @ -179,6 +215,7 @@ endmodule | |||
| `EL2_RAM_BE(256, 104) | ||||
| `EL2_RAM_BE(128, 104) | ||||
| `EL2_RAM_BE(64, 104) | ||||
| `EL2_RAM_BE(32, 104) | ||||
| `EL2_RAM_BE(4096, 44) | ||||
| `EL2_RAM_BE(2048, 44) | ||||
| `EL2_RAM_BE(1024, 44) | ||||
|  | @ -186,6 +223,7 @@ endmodule | |||
| `EL2_RAM_BE(256, 44) | ||||
| `EL2_RAM_BE(128, 44) | ||||
| `EL2_RAM_BE(64, 44) | ||||
| `EL2_RAM_BE(32, 44) | ||||
| `EL2_RAM_BE(4096, 88) | ||||
| `EL2_RAM_BE(2048, 88) | ||||
| `EL2_RAM_BE(1024, 88) | ||||
|  | @ -193,6 +231,8 @@ endmodule | |||
| `EL2_RAM_BE(256, 88) | ||||
| `EL2_RAM_BE(128, 88) | ||||
| `EL2_RAM_BE(64, 88) | ||||
| `EL2_RAM_BE(32, 88) | ||||
| `EL2_RAM(64, 39) | ||||
| 
 | ||||
| 
 | ||||
| `undef EL2_RAM | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -43,7 +43,6 @@ import el2_pkg::*; | |||
|    input logic                             dec_tlu_sideeffect_posted_disable, // disable the posted sideeffect load store 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
 | ||||
|  | @ -58,6 +57,7 @@ import el2_pkg::*; | |||
|    output logic                            lsu_store_stall_any,   // This is for blocking stores in the decode
 | ||||
|    output logic                            lsu_fastint_stall_any, // Stall the fastint in decode-1 stage
 | ||||
|    output logic                            lsu_idle_any,          // lsu buffers are empty and no instruction in the pipeline. Doesn't include DMA
 | ||||
|    output logic                            lsu_active,            // Used to turn off top level clk
 | ||||
| 
 | ||||
|    output logic [31:1]                     lsu_fir_addr,        // fast interrupt address
 | ||||
|    output logic [1:0]                      lsu_fir_error,       // Error during fast interrupt lookup
 | ||||
|  | @ -78,7 +78,6 @@ import el2_pkg::*; | |||
|    output logic [pt.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_load_external_m,        // PMU : Bus loads
 | ||||
|    output logic                            lsu_pmu_store_external_m,       // PMU : Bus loads
 | ||||
|    output logic                            lsu_pmu_misaligned_m,           // PMU : misaligned
 | ||||
|  | @ -175,14 +174,13 @@ import el2_pkg::*; | |||
|    output logic [63:0]                     dccm_dma_rdata,      // lsu data for DMA dccm read
 | ||||
|    output logic                            dccm_ready,          // lsu ready for DMA access
 | ||||
| 
 | ||||
|    input logic                             scan_mode,           // scan
 | ||||
|    input logic                             clk, | ||||
|    input logic                             free_clk, | ||||
|    input logic                             rst_l | ||||
|    input logic                             scan_mode,           // scan mode
 | ||||
|    input logic                             clk,                 // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic                             active_clk,          // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic                             rst_l                // reset, active low
 | ||||
| 
 | ||||
|    ); | ||||
| 
 | ||||
| 
 | ||||
|    logic        lsu_dccm_rden_m; | ||||
|    logic        lsu_dccm_rden_r; | ||||
|    logic [31:0] store_data_m; | ||||
|  | @ -224,6 +222,7 @@ import el2_pkg::*; | |||
| 
 | ||||
|    logic        addr_in_dccm_d, addr_in_dccm_m, addr_in_dccm_r; | ||||
|    logic        addr_in_pic_d, addr_in_pic_m, addr_in_pic_r; | ||||
|    logic        ldst_dual_d, ldst_dual_m, ldst_dual_r; | ||||
|    logic        addr_external_m; | ||||
| 
 | ||||
|    logic                          stbuf_reqvld_any; | ||||
|  | @ -249,7 +248,6 @@ import el2_pkg::*; | |||
|    logic        lsu_bus_buffer_pend_any; | ||||
|    logic        lsu_bus_buffer_empty_any; | ||||
|    logic        lsu_bus_buffer_full_any; | ||||
|    logic        lsu_bus_idle_any; | ||||
|    logic        lsu_busreq_m; | ||||
|    logic [31:0] bus_read_data_m; | ||||
| 
 | ||||
|  | @ -262,6 +260,8 @@ import el2_pkg::*; | |||
|    logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_lo, dma_dccm_wdata_ecc_hi; | ||||
| 
 | ||||
|    // Clocks
 | ||||
|    logic        lsu_busm_clken; | ||||
|    logic        lsu_bus_obuf_c1_clken; | ||||
|    logic        lsu_c1_m_clk, lsu_c1_r_clk; | ||||
|    logic        lsu_c2_m_clk, lsu_c2_r_clk; | ||||
|    logic        lsu_store_c1_m_clk, lsu_store_c1_r_clk; | ||||
|  | @ -288,9 +288,10 @@ import el2_pkg::*; | |||
|    // There can't be any inpipe forwarding from non-dma packet to dma packet since they can be flushed so we can't have st in r when dma is in m
 | ||||
|    assign dma_mem_tag_d[2:0]   = dma_mem_tag[2:0]; | ||||
|    assign ldst_nodma_mtor = (lsu_pkt_m.valid & ~lsu_pkt_m.dma & (addr_in_dccm_m | addr_in_pic_m) & lsu_pkt_m.store); | ||||
| 
 | ||||
|    assign dccm_ready = ~(dec_lsu_valid_raw_d | ldst_nodma_mtor | ld_single_ecc_error_r_ff); | ||||
| 
 | ||||
|    assign dma_dccm_wen = dma_dccm_req & dma_mem_write & addr_in_dccm_d; | ||||
|    assign dma_dccm_wen = dma_dccm_req & dma_mem_write & addr_in_dccm_d & dma_mem_sz[1];   // Perform DMA writes only for word/dword
 | ||||
|    assign dma_pic_wen  = dma_dccm_req & dma_mem_write & addr_in_pic_d; | ||||
|    assign {dma_dccm_wdata_hi[31:0], dma_dccm_wdata_lo[31: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
 | ||||
| 
 | ||||
|  | @ -299,16 +300,19 @@ import el2_pkg::*; | |||
|    assign flush_m_up = dec_tlu_flush_lower_r; | ||||
|    assign flush_r    = dec_tlu_i0_kill_writeb_r; | ||||
| 
 | ||||
|    // lsu idle
 | ||||
|    // lsu halt idle. This is used for entering the halt mode. Also, DMA accesses are allowed during fence.
 | ||||
|    // Indicates non-idle if there is a instruction valid in d-r or read/write buffers are non-empty since they can come with error
 | ||||
|    // Store buffer now have only non-dma dccm stores
 | ||||
|    // stbuf_empty not needed since it has only dccm stores
 | ||||
|    assign lsu_idle_any = ~((lsu_pkt_m.valid & ~lsu_pkt_m.dma) | | ||||
|                            (lsu_pkt_r.valid & ~lsu_pkt_r.dma)) & | ||||
|                            lsu_bus_buffer_empty_any & lsu_bus_idle_any; | ||||
|                            lsu_bus_buffer_empty_any; | ||||
| 
 | ||||
|    assign lsu_active = (lsu_pkt_m.valid | lsu_pkt_r.valid | ld_single_ecc_error_r_ff) | ~lsu_bus_buffer_empty_any;  // This includes DMA. Used for gating top clock
 | ||||
| 
 | ||||
|    // Instantiate the store buffer
 | ||||
|    assign store_stbuf_reqvld_r = lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_dccm_r & ~flush_r & ~lsu_pkt_r.dma; | ||||
|    assign store_stbuf_reqvld_r = lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_dccm_r & ~flush_r & (~lsu_pkt_r.dma | ((lsu_pkt_r.by | lsu_pkt_r.half) & ~lsu_double_ecc_error_r)); | ||||
| 
 | ||||
|    // Disable Forwarding for now
 | ||||
|    assign lsu_cmpen_m = lsu_pkt_m.valid & (lsu_pkt_m.load | lsu_pkt_m.store) & (addr_in_dccm_m | addr_in_pic_m); | ||||
|  | @ -316,6 +320,11 @@ import el2_pkg::*; | |||
|    // Bus signals
 | ||||
|    assign lsu_busreq_m = lsu_pkt_m.valid & ((lsu_pkt_m.load | lsu_pkt_m.store) & addr_external_m) & ~flush_m_up & ~lsu_exc_m & ~lsu_pkt_m.fast_int; | ||||
| 
 | ||||
|    // Dual signals
 | ||||
|    assign ldst_dual_d  = (lsu_addr_d[2] != end_addr_d[2]); | ||||
|    assign ldst_dual_m  = (lsu_addr_m[2] != end_addr_m[2]); | ||||
|    assign ldst_dual_r  = (lsu_addr_r[2] != end_addr_r[2]); | ||||
| 
 | ||||
|    // PMU signals
 | ||||
|    assign lsu_pmu_misaligned_m     = lsu_pkt_m.valid & ((lsu_pkt_m.half & lsu_addr_m[0]) | (lsu_pkt_m.word & (|lsu_addr_m[1:0]))); | ||||
|    assign lsu_pmu_load_external_m  = lsu_pkt_m.valid & lsu_pkt_m.load & addr_external_m; | ||||
|  | @ -358,18 +367,24 @@ import el2_pkg::*; | |||
| 
 | ||||
|    // Bus interface
 | ||||
|    el2_lsu_bus_intf #(.pt(pt)) bus_intf ( | ||||
|       .lsu_addr_m(lsu_addr_m[31:0] & {32{addr_external_m & lsu_pkt_m.valid}}), | ||||
|       .lsu_addr_r(lsu_addr_r[31:0] & {32{lsu_busreq_r}}), | ||||
| 
 | ||||
|       .end_addr_m(end_addr_m[31:0] & {32{addr_external_m & lsu_pkt_m.valid}}), | ||||
|       .end_addr_r(end_addr_r[31:0] & {32{lsu_busreq_r}}), | ||||
| 
 | ||||
|       .store_data_r(store_data_r[31:0] & {32{lsu_busreq_r}}), | ||||
|       .* | ||||
|    ); | ||||
| 
 | ||||
|    //Flops
 | ||||
|    rvdff #(3) dma_mem_tag_mff     (.*, .din(dma_mem_tag_d[2:0]), .dout(dma_mem_tag_m[2:0]), .clk(lsu_c1_m_clk)); | ||||
| 
 | ||||
|    rvdff #(2) lsu_raw_fwd_r_ff    (.*, .din({lsu_raw_fwd_hi_m, lsu_raw_fwd_lo_m}),     .dout({lsu_raw_fwd_hi_r, lsu_raw_fwd_lo_r}),     .clk(lsu_c2_r_clk)); | ||||
| 
 | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_ASSERT_ON | ||||
|    logic [1:0] store_data_bypass_sel; | ||||
|    assign store_data_bypass_sel[1:0] =  {lsu_p.store_data_bypass_d, lsu_p.store_data_bypass_m}; | ||||
| 
 | ||||
|    property exception_no_lsu_flush; | ||||
|       @(posedge clk)  disable iff(~rst_l) lsu_lsc_ctl.lsu_error_pkt_m.exc_valid |-> ##[1:2] (flush_r ); | ||||
|    endproperty | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -27,16 +27,16 @@ import el2_pkg::*; | |||
| #( | ||||
| `include "el2_param.vh" | ||||
|  )( | ||||
|    input logic          lsu_c2_m_clk,       // clock
 | ||||
|    input logic          rst_l,                       // reset
 | ||||
|    input logic          lsu_c2_m_clk,              // clock
 | ||||
|    input logic          rst_l,                     // reset
 | ||||
| 
 | ||||
|    input logic [31:0]   start_addr_d,              // start address for lsu
 | ||||
|    input logic [31:0]   end_addr_d,                // end address for lsu
 | ||||
|    input el2_lsu_pkt_t lsu_pkt_d,                 // packet in d
 | ||||
|    input logic [31:0]   dec_tlu_mrac_ff,             // CSR read
 | ||||
|    input logic [3:0]    rs1_region_d, | ||||
|    input logic [31:0]   dec_tlu_mrac_ff,           // CSR read
 | ||||
|    input logic [3:0]    rs1_region_d,              // address rs operand [31:28]
 | ||||
| 
 | ||||
|    input logic [31:0]   rs1_d, | ||||
|    input logic [31:0]   rs1_d,                     // address rs operand
 | ||||
| 
 | ||||
|    output logic         is_sideeffects_m,          // is sideffects space
 | ||||
|    output logic         addr_in_dccm_d,            // address in dccm
 | ||||
|  | @ -50,7 +50,7 @@ import el2_pkg::*; | |||
|    output logic         fir_dccm_access_error_d,   // Fast interrupt dccm access error
 | ||||
|    output logic         fir_nondccm_access_error_d,// Fast interrupt dccm access error
 | ||||
| 
 | ||||
|    input  logic         scan_mode | ||||
|    input  logic         scan_mode                  // Scan mode
 | ||||
| ); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -116,7 +116,7 @@ import el2_pkg::*; | |||
|    ); | ||||
| 
 | ||||
|    assign start_addr_dccm_or_pic  = start_addr_in_dccm_region_d | start_addr_in_pic_region_d; | ||||
|    assign base_reg_dccm_or_pic    = (rs1_region_d[3:0] == pt.DCCM_REGION) | (rs1_region_d[3:0] == pt.PIC_REGION); | ||||
|    assign base_reg_dccm_or_pic    = ((rs1_region_d[3:0] == pt.DCCM_REGION) & pt.DCCM_ENABLE) | (rs1_region_d[3:0] == pt.PIC_REGION); | ||||
|    assign addr_in_dccm_d          = (start_addr_in_dccm_d & end_addr_in_dccm_d); | ||||
|    assign addr_in_pic_d           = (start_addr_in_pic_d & end_addr_in_pic_d); | ||||
| 
 | ||||
|  | @ -154,7 +154,7 @@ import el2_pkg::*; | |||
|    assign regpred_access_fault_d  = (start_addr_dccm_or_pic ^ base_reg_dccm_or_pic);                   // 5. Region predication access fault: Base Address in DCCM/PIC and Final address in non-DCCM/non-PIC region or vice versa
 | ||||
|    assign picm_access_fault_d     = (addr_in_pic_d & ((start_addr_d[1:0] != 2'b0) | ~lsu_pkt_d.word));                                               // 6. Ld/St access to picm are not word aligned or word size
 | ||||
| 
 | ||||
|    if (pt.DCCM_REGION == pt.PIC_REGION) begin | ||||
|    if (pt.DCCM_ENABLE & (pt.DCCM_REGION == pt.PIC_REGION)) begin | ||||
|       assign unmapped_access_fault_d = ((start_addr_in_dccm_region_d & ~(start_addr_in_dccm_d | start_addr_in_pic_d)) |   // 0. Addr in dccm/pic region but not in dccm/pic offset
 | ||||
|                                         (end_addr_in_dccm_region_d & ~(end_addr_in_dccm_d | end_addr_in_pic_d))       |   // 0. Addr in dccm/pic region but not in dccm/pic offset
 | ||||
|                                         (start_addr_in_dccm_d & end_addr_in_pic_d)                                    |   // 0. DCCM -> PIC cross when DCCM/PIC in same region
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -28,15 +28,18 @@ import el2_pkg::*; | |||
| #( | ||||
| `include "el2_param.vh" | ||||
|  )( | ||||
|    input logic                          clk, | ||||
|    input logic                          rst_l, | ||||
|    input logic                          scan_mode, | ||||
|    input logic                          clk,                                // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic                          clk_override,                       // Override non-functional clock gating
 | ||||
|    input logic                          rst_l,                              // reset, active low
 | ||||
|    input logic                          scan_mode,                          // scan mode
 | ||||
|    input logic                          dec_tlu_external_ldfwd_disable,     // disable load to load forwarding for externals
 | ||||
|    input logic                          dec_tlu_wb_coalescing_disable,      // disable write buffer coalescing
 | ||||
|    input logic                          dec_tlu_sideeffect_posted_disable,  // Don't block the sideeffect load store to the bus
 | ||||
|    input logic                          dec_tlu_force_halt, | ||||
| 
 | ||||
|    // various clocks needed for the bus reads and writes
 | ||||
|    input logic                          lsu_bus_obuf_c1_clken, | ||||
|    input logic                          lsu_busm_clken, | ||||
|    input logic                          lsu_c2_r_clk, | ||||
|    input logic                          lsu_bus_ibuf_c1_clk, | ||||
|    input logic                          lsu_bus_obuf_c1_clk, | ||||
|  | @ -68,12 +71,11 @@ import el2_pkg::*; | |||
|    input logic                          ldst_dual_m,                    // load/store is unaligned at 32 bit boundary
 | ||||
|    input logic                          ldst_dual_r,                    // load/store is unaligned at 32 bit boundary
 | ||||
| 
 | ||||
|    input logic [7:0]                    ldst_byteen_ext_m, | ||||
|    input logic [7:0]                    ldst_byteen_ext_m,              // HI and LO signals
 | ||||
| 
 | ||||
|    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                         lsu_bus_idle_any,                 // No pending responses from the 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
 | ||||
|  | @ -87,11 +89,10 @@ import el2_pkg::*; | |||
|    output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_m,       // the tag of the external non block load
 | ||||
|    output logic                               lsu_nonblock_load_inv_r,       // invalidate signal for the cam entry for non block loads
 | ||||
|    output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_r,   // 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 [pt.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_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 [pt.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, | ||||
|  | @ -149,7 +150,6 @@ import el2_pkg::*; | |||
| 
 | ||||
| ); | ||||
| 
 | ||||
| 
 | ||||
|    // For Ld: IDLE -> WAIT -> CMD -> RESP -> DONE_PARTIAL(?) -> DONE_WAIT(?) -> 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_PARTIAL=3'b100, DONE_WAIT=3'b101, DONE=3'b110} state_t; | ||||
|  | @ -178,7 +178,7 @@ import el2_pkg::*; | |||
|    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_unsign, lsu_nonblock_dual; | ||||
|    logic                                lsu_nonblock_unsign; | ||||
|    logic                                lsu_nonblock_load_data_ready; | ||||
| 
 | ||||
|    logic [DEPTH-1:0]                    CmdPtr0Dec, CmdPtr1Dec; | ||||
|  | @ -191,10 +191,7 @@ import el2_pkg::*; | |||
|    logic [3:0]                          buf_numvld_any, buf_numvld_wrcmd_any, buf_numvld_cmd_any, buf_numvld_pend_any; | ||||
|    logic                                any_done_wait_state; | ||||
|    logic                                bus_sideeffect_pend; | ||||
|    logic [7:0]                          bus_pend_trxn, bus_pend_trxnQ, bus_pend_trxn_ns; | ||||
|    logic                                lsu_bus_cntr_overflow; | ||||
|    logic                                bus_coalescing_disable; | ||||
|    logic                                mdbhd_en; | ||||
| 
 | ||||
|    logic                                bus_addr_match_pending; | ||||
|    logic                                bus_cmd_sent, bus_cmd_ready; | ||||
|  | @ -219,7 +216,6 @@ import el2_pkg::*; | |||
|    logic   [DEPTH-1:0][DEPTH_LOG2-1:0]  buf_dualtag; | ||||
|    logic   [DEPTH-1:0]                  buf_ldfwd; | ||||
|    logic   [DEPTH-1:0][DEPTH_LOG2-1:0]  buf_ldfwdtag; | ||||
|    //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; | ||||
|  | @ -234,7 +230,6 @@ import el2_pkg::*; | |||
|    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; | ||||
|  | @ -263,7 +258,6 @@ import el2_pkg::*; | |||
|    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; | ||||
|  | @ -313,6 +307,7 @@ import el2_pkg::*; | |||
|    logic                               obuf_rst; | ||||
|    logic                               obuf_write_in; | ||||
|    logic                               obuf_nosend_in; | ||||
|    logic                               obuf_rdrsp_pend_en; | ||||
|    logic                               obuf_rdrsp_pend_in; | ||||
|    logic                               obuf_sideeffect_in; | ||||
|    logic                               obuf_aligned_in; | ||||
|  | @ -331,15 +326,15 @@ import el2_pkg::*; | |||
|    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 [pt.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 [DEPTH_LOG2-1:0]  lsu_imprecise_error_store_tag; | ||||
|    logic [63:0]            lsu_axi_rdata_q; | ||||
|    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 [pt.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 [pt.LSU_BUS_TAG-1:0]          lsu_imprecise_error_store_tag; | ||||
|    logic [63:0]                        lsu_axi_rdata_q; | ||||
| 
 | ||||
|    //------------------------------------------------------------------------------
 | ||||
|    // Load forwarding logic start
 | ||||
|  | @ -360,7 +355,7 @@ import el2_pkg::*; | |||
|    // Buffer hit logic for bus load forwarding
 | ||||
|    assign ldst_byteen_hi_m[3:0]   = ldst_byteen_ext_m[7:4]; | ||||
|    assign ldst_byteen_lo_m[3:0]   = ldst_byteen_ext_m[3:0]; | ||||
|    for (genvar i=0; i<32'(DEPTH); i++) begin | ||||
|    for (genvar i=0; i<DEPTH; i++) begin | ||||
|       assign ld_addr_hitvec_lo[i] = (lsu_addr_m[31:2] == buf_addr[i][31:2]) & buf_write[i] & (buf_state[i] != IDLE) & lsu_busreq_m; | ||||
|       assign ld_addr_hitvec_hi[i] = (end_addr_m[31:2] == buf_addr[i][31:2]) & buf_write[i] & (buf_state[i] != IDLE) & lsu_busreq_m; | ||||
|    end | ||||
|  | @ -368,7 +363,7 @@ import el2_pkg::*; | |||
|    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<32'(DEPTH); i++) begin | ||||
|      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_m[j]; | ||||
|          assign ld_byte_hitvec_hi[j][i] = ld_addr_hitvec_hi[i] & buf_byteen[i][j] & ldst_byteen_hi_m[j]; | ||||
| 
 | ||||
|  | @ -389,7 +384,7 @@ import el2_pkg::*; | |||
|    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<32'(DEPTH); i++) begin | ||||
|       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]; | ||||
|  | @ -428,7 +423,7 @@ import el2_pkg::*; | |||
|    assign ibuf_wr_en = lsu_busreq_r & lsu_commit_r & ~ibuf_byp; | ||||
|    assign ibuf_rst   = (ibuf_drain_vld & ~ibuf_wr_en) | dec_tlu_force_halt; | ||||
|    assign ibuf_force_drain = lsu_busreq_m & ~lsu_busreq_r & ibuf_valid & (lsu_pkt_m.load | (ibuf_addr[31:2] != lsu_addr_m[31:2]));  // Move the ibuf to buf if there is a non-colaescable ld/st in m but nothing in r
 | ||||
|    assign ibuf_drain_vld = ibuf_valid & (((ibuf_wr_en | (ibuf_timer == TIMER_LOG2'(TIMER_MAX))) & ~(ibuf_merge_en & ibuf_merge_in)) | ibuf_byp | ibuf_force_drain | ibuf_sideeffect | ~ibuf_write | bus_coalescing_disable); | ||||
|    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_r ? WrPtr1_r : WrPtr0_r); | ||||
|    assign ibuf_dualtag_in[DEPTH_LOG2-1:0] = WrPtr0_r; | ||||
|    assign ibuf_sz_in[1:0]   = {lsu_pkt_r.word, lsu_pkt_r.half}; | ||||
|  | @ -438,7 +433,7 @@ import el2_pkg::*; | |||
|       assign ibuf_data_in[(8*i)+7:(8*i)] = (ibuf_merge_en & ibuf_merge_in) ? (ldst_byteen_lo_r[i] ? store_data_lo_r[(8*i)+7:(8*i)] : ibuf_data[(8*i)+7:(8*i)]) : | ||||
|                                                                              (ldst_dual_r ? store_data_hi_r[(8*i)+7:(8*i)] : store_data_lo_r[(8*i)+7:(8*i)]); | ||||
|    end | ||||
|    assign ibuf_timer_in = ibuf_wr_en ? '0 : (ibuf_timer < TIMER_LOG2'(TIMER_MAX)) ? (ibuf_timer + 1'b1) : ibuf_timer; | ||||
|    assign ibuf_timer_in = ibuf_wr_en ? '0 : (ibuf_timer < TIMER_MAX) ? (ibuf_timer + 1'b1) : ibuf_timer; | ||||
| 
 | ||||
| 
 | ||||
|    assign ibuf_merge_en = lsu_busreq_r & lsu_commit_r & lsu_pkt_r.store & ibuf_valid & ibuf_write & (lsu_addr_r[31:2] == ibuf_addr[31:2]) & ~is_sideeffects_r & ~bus_coalescing_disable; | ||||
|  | @ -457,7 +452,6 @@ import el2_pkg::*; | |||
|    rvdffs  #(.WIDTH(1))              ibuf_dualff       (.din(ldst_dual_r),               .dout(ibuf_dual),       .en(ibuf_wr_en),                   .clk(lsu_bus_ibuf_c1_clk), .*); | ||||
|    rvdffs  #(.WIDTH(1))              ibuf_samedwff     (.din(ldst_samedw_r),             .dout(ibuf_samedw),     .en(ibuf_wr_en),                   .clk(lsu_bus_ibuf_c1_clk), .*); | ||||
|    rvdffs  #(.WIDTH(1))              ibuf_nomergeff    (.din(no_dword_merge_r),          .dout(ibuf_nomerge),    .en(ibuf_wr_en),                   .clk(lsu_bus_ibuf_c1_clk), .*); | ||||
|    //rvdffs  #(.WIDTH(1))              ibuf_nbff         (.din(lsu_nonblock_load_valid_r), .dout(ibuf_nb),         .en(ibuf_wr_en),                   .clk(lsu_bus_ibuf_c1_clk), .*);
 | ||||
|    rvdffs  #(.WIDTH(1))              ibuf_sideeffectff (.din(is_sideeffects_r),          .dout(ibuf_sideeffect), .en(ibuf_wr_en),                   .clk(lsu_bus_ibuf_c1_clk), .*); | ||||
|    rvdffs  #(.WIDTH(1))              ibuf_unsignff     (.din(lsu_pkt_r.unsign),          .dout(ibuf_unsign),     .en(ibuf_wr_en),                   .clk(lsu_bus_ibuf_c1_clk), .*); | ||||
|    rvdffs  #(.WIDTH(1))              ibuf_writeff      (.din(lsu_pkt_r.store),           .dout(ibuf_write),      .en(ibuf_wr_en),                   .clk(lsu_bus_ibuf_c1_clk), .*); | ||||
|  | @ -477,16 +471,16 @@ import el2_pkg::*; | |||
|    // 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_LOG2'(TIMER_MAX)) & | ||||
|    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] & ~buf_sideeffect[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_LOG2'(TIMER_MAX))) ? (obuf_wr_timer + 1'b1) : obuf_wr_timer); | ||||
|    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_m & ~lsu_busreq_r & ~ibuf_valid & (buf_numvld_cmd_any[3:0] == 4'b1) & (lsu_addr_m[31:2] != buf_addr[CmdPtr0][31:2]);   // Entry in m 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) & (~lsu_pkt_r.store | no_dword_merge_r); | ||||
| 
 | ||||
|    assign obuf_wr_en = ((ibuf_buf_byp & lsu_commit_r & ~(is_sideeffects_r & bus_sideeffect_pend)) | | ||||
|                         ((buf_state[CmdPtr0] == CMD) & found_cmdptr0 & ~buf_cmd_state_bus_en[CmdPtr0] & ~(buf_sideeffect[CmdPtr0] & bus_sideeffect_pend) & | ||||
|                          (~(buf_dual[CmdPtr0] & buf_samedw[CmdPtr0] & ~buf_write[CmdPtr0]) | found_cmdptr1 | buf_nomerge[CmdPtr0] | obuf_force_wr_en))) & | ||||
|                        (bus_cmd_ready | ~obuf_valid | obuf_nosend) & ~obuf_wr_wait & ~lsu_bus_cntr_overflow & ~bus_addr_match_pending & lsu_bus_clk_en; | ||||
|                        (bus_cmd_ready | ~obuf_valid | obuf_nosend) & ~obuf_wr_wait  & ~bus_addr_match_pending & lsu_bus_clk_en; | ||||
| 
 | ||||
|    assign obuf_rst   = ((bus_cmd_sent | (obuf_valid & obuf_nosend)) & ~obuf_wr_en & lsu_bus_clk_en) | dec_tlu_force_halt; | ||||
| 
 | ||||
|  | @ -505,10 +499,10 @@ import el2_pkg::*; | |||
|                                                               (obuf_sz_in[0] & ~obuf_addr_in[0]) | | ||||
|                                                               (obuf_sz_in[1] & ~(|obuf_addr_in[1:0]))); | ||||
| 
 | ||||
|    assign obuf_rdrsp_pend_in  = (~(obuf_wr_en & ~obuf_nosend_in) & obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag))) | | ||||
|                                 ((bus_cmd_sent & ~obuf_write) & ~dec_tlu_force_halt) ; | ||||
|    assign obuf_rdrsp_pend_in  = ((~(obuf_wr_en & ~obuf_nosend_in) & obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag))) | (bus_cmd_sent & ~obuf_write)) & ~dec_tlu_force_halt; | ||||
|    assign obuf_rdrsp_pend_en  = lsu_bus_clk_en | dec_tlu_force_halt; | ||||
|    assign obuf_rdrsp_tag_in[pt.LSU_BUS_TAG-1:0] = (bus_cmd_sent & ~obuf_write) ? obuf_tag0[pt.LSU_BUS_TAG-1:0] : obuf_rdrsp_tag[pt.LSU_BUS_TAG-1:0]; | ||||
|    // No ld to ld fwd for aligned & atomic64
 | ||||
|    // No ld to ld fwd for aligned
 | ||||
|    assign obuf_nosend_in      = (obuf_addr_in[31:3] == obuf_addr[31:3]) & obuf_aligned_in & ~obuf_sideeffect & ~obuf_write & ~obuf_write_in & ~dec_tlu_external_ldfwd_disable & | ||||
|                                 ((obuf_valid & ~obuf_nosend) | (obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag)))); | ||||
| 
 | ||||
|  | @ -516,9 +510,9 @@ import el2_pkg::*; | |||
|                                                 (buf_addr[CmdPtr0][2] ? {buf_byteen[CmdPtr0],4'b0} : {4'b0,buf_byteen[CmdPtr0]}); | ||||
|    assign obuf_byteen1_in[7:0] = ibuf_buf_byp ? (end_addr_r[2] ? {ldst_byteen_hi_r[3:0],4'b0} : {4'b0,ldst_byteen_hi_r[3: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_r[2] ? {store_data_lo_r[31:0],32'b0}    : {32'b0,store_data_lo_r[31:0]}) : | ||||
|    assign obuf_data0_in[63:0]  = ibuf_buf_byp ? (lsu_addr_r[2] ? {store_data_lo_r[31:0],32'b0} : {32'b0,store_data_lo_r[31:0]}) : | ||||
|                                                 (buf_addr[CmdPtr0][2] ? {buf_data[CmdPtr0],32'b0} : {32'b0,buf_data[CmdPtr0]}); | ||||
|    assign obuf_data1_in[63:0]  = ibuf_buf_byp ? (lsu_addr_r[2] ? {store_data_hi_r[31:0],32'b0} :{32'b0,store_data_hi_r[31:0]}) : | ||||
|    assign obuf_data1_in[63:0]  = ibuf_buf_byp ? (end_addr_r[2] ? {store_data_hi_r[31:0],32'b0} :{32'b0,store_data_hi_r[31:0]}) : | ||||
|                                                 (buf_addr[CmdPtr1][2] ? {buf_data[CmdPtr1],32'b0} : {32'b0,buf_data[CmdPtr1]}); | ||||
| 
 | ||||
|    for (genvar i=0 ;i<8; i++) begin | ||||
|  | @ -529,28 +523,27 @@ import el2_pkg::*; | |||
|    // 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_write[CmdPtr1] & (buf_addr[CmdPtr0][31:3] == buf_addr[CmdPtr1][31:3]) & ~bus_coalescing_disable & ~pt.BUILD_AXI_NATIVE) | | ||||
|                             (~buf_write[CmdPtr0] & buf_dual[CmdPtr0] & ~buf_dualhi[CmdPtr0] & buf_samedw[CmdPtr0]))) |  // CmdPtr0/CmdPtr1 are for same load which is within a DW
 | ||||
|                            (~buf_write[CmdPtr0] & buf_dual[CmdPtr0] & ~buf_dualhi[CmdPtr0] & buf_samedw[CmdPtr0])) |  // CmdPtr0/CmdPtr1 are for same load which is within a DW
 | ||||
|                           (ibuf_buf_byp & ldst_samedw_r & ldst_dual_r); | ||||
| 
 | ||||
| 
 | ||||
|    rvdff   #(.WIDTH(1))              obuf_wren_ff      (.din(obuf_wr_en),                  .dout(obuf_wr_enQ),                                        .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_free_c2_clk), .*); | ||||
|    rvdffs  #(.WIDTH(1))              obuf_nosend_ff    (.din(obuf_nosend_in),              .dout(obuf_nosend),     .en(obuf_wr_en),                   .clk(lsu_free_c2_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), .*); | ||||
|    rvdff   #(.WIDTH(1))              obuf_rdrsp_pend_ff(.din(obuf_rdrsp_pend_in),          .dout(obuf_rdrsp_pend),                                    .clk(lsu_busm_clk), .*); | ||||
|    rvdff   #(.WIDTH(pt.LSU_BUS_TAG)) obuf_rdrsp_tagff  (.din(obuf_rdrsp_tag_in),           .dout(obuf_rdrsp_tag),                                     .clk(lsu_busm_clk), .*); | ||||
|    rvdffs  #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag0ff       (.din(obuf_tag0_in),                .dout(obuf_tag0),       .en(obuf_wr_en),                   .clk(lsu_bus_obuf_c1_clk), .*); | ||||
|    rvdffs  #(.WIDTH(pt.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), .*); | ||||
|    rvdff_fpga  #(.WIDTH(1))              obuf_wren_ff      (.din(obuf_wr_en),                  .dout(obuf_wr_enQ),                                        .clk(lsu_busm_clk),        .clken(lsu_busm_clken), .rawclk(clk),        .*); | ||||
|    rvdffsc     #(.WIDTH(1))              obuf_valid_ff     (.din(1'b1),                        .dout(obuf_valid),      .en(obuf_wr_en), .clear(obuf_rst), .clk(lsu_free_c2_clk),                                                  .*); | ||||
|    rvdffs      #(.WIDTH(1))              obuf_nosend_ff    (.din(obuf_nosend_in),              .dout(obuf_nosend),     .en(obuf_wr_en),                   .clk(lsu_free_c2_clk),                                                  .*); | ||||
|    rvdffs      #(.WIDTH(1))              obuf_rdrsp_pend_ff(.din(obuf_rdrsp_pend_in),          .dout(obuf_rdrsp_pend), .en(obuf_rdrsp_pend_en),           .clk(lsu_free_c2_clk),                                                  .*); | ||||
|    rvdff_fpga  #(.WIDTH(1))              obuf_cmd_done_ff  (.din(obuf_cmd_done_in),            .dout(obuf_cmd_done),                                      .clk(lsu_busm_clk),        .clken(lsu_busm_clken),        .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(1))              obuf_data_done_ff (.din(obuf_data_done_in),           .dout(obuf_data_done),                                     .clk(lsu_busm_clk),        .clken(lsu_busm_clken),        .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(pt.LSU_BUS_TAG)) obuf_rdrsp_tagff  (.din(obuf_rdrsp_tag_in),           .dout(obuf_rdrsp_tag),                                     .clk(lsu_busm_clk),        .clken(lsu_busm_clken),        .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag0ff       (.din(obuf_tag0_in),                .dout(obuf_tag0),       .en(obuf_wr_en),                   .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag1ff       (.din(obuf_tag1_in),                .dout(obuf_tag1),       .en(obuf_wr_en),                   .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(1))              obuf_mergeff      (.din(obuf_merge_in),               .dout(obuf_merge),      .en(obuf_wr_en),                   .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(1))              obuf_writeff      (.din(obuf_write_in),               .dout(obuf_write),      .en(obuf_wr_en),                   .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(1))              obuf_sideeffectff (.din(obuf_sideeffect_in),          .dout(obuf_sideeffect), .en(obuf_wr_en),                   .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(2))              obuf_szff         (.din(obuf_sz_in[1:0]),             .dout(obuf_sz),         .en(obuf_wr_en),                   .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); | ||||
|    rvdffs_fpga #(.WIDTH(8))              obuf_byteenff     (.din(obuf_byteen_in[7:0]),         .dout(obuf_byteen),     .en(obuf_wr_en),                   .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); | ||||
|    rvdffe     #(.WIDTH(32))              obuf_addrff       (.din(obuf_addr_in[31:0]),          .dout(obuf_addr),       .en(obuf_wr_en),                                                                                           .*); | ||||
|    rvdffe     #(.WIDTH(64))              obuf_dataff       (.din(obuf_data_in[63:0]),          .dout(obuf_data),       .en(obuf_wr_en),                                                                                           .*); | ||||
|    rvdff_fpga #(.WIDTH(TIMER_LOG2))      obuf_timerff      (.din(obuf_wr_timer_in),            .dout(obuf_wr_timer),                                      .clk(lsu_busm_clk),        .clken(lsu_busm_clken), .rawclk(clk),        .*); | ||||
| 
 | ||||
| 
 | ||||
|    //------------------------------------------------------------------------------
 | ||||
|  | @ -565,27 +558,27 @@ import el2_pkg::*; | |||
|       found_wrptr1  = '0; | ||||
| 
 | ||||
|       // Find first write pointer
 | ||||
|       for (int i=0; i<32'(DEPTH); i++) begin | ||||
|       for (int i=0; i<DEPTH; i++) begin | ||||
|          if (~found_wrptr0) begin | ||||
|             WrPtr0_m[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i); | ||||
|             found_wrptr0 = (buf_state[i] == IDLE) & ~((ibuf_valid & (32'(ibuf_tag) == i))                                               | | ||||
|                                                       (lsu_busreq_r & ((32'(WrPtr0_r) == i) | (ldst_dual_r & (32'(WrPtr1_r) == i))))); | ||||
|             found_wrptr0 = (buf_state[i] == IDLE) & ~((ibuf_valid & (ibuf_tag == i))                                               | | ||||
|                                                       (lsu_busreq_r & ((WrPtr0_r == i) | (ldst_dual_r & (WrPtr1_r == i))))); | ||||
|          end | ||||
|       end | ||||
| 
 | ||||
|       // Find second write pointer
 | ||||
|       for (int i=0; i<32'(DEPTH); i++) begin | ||||
|       for (int i=0; i<DEPTH; i++) begin | ||||
|          if (~found_wrptr1) begin | ||||
|             WrPtr1_m[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i); | ||||
|             found_wrptr1 = (buf_state[i] == IDLE) & ~((ibuf_valid & (32'(ibuf_tag) == i))                                               | | ||||
|                                                       (lsu_busreq_m & (32'(WrPtr0_m) == i))                                         | | ||||
|                                                       (lsu_busreq_r & ((32'(WrPtr0_r) == i) | (ldst_dual_r & (32'(WrPtr1_r) == i))))); | ||||
|             found_wrptr1 = (buf_state[i] == IDLE) & ~((ibuf_valid & (ibuf_tag == i))                                               | | ||||
|                                                       (lsu_busreq_m & (WrPtr0_m == i))                                         | | ||||
|                                                       (lsu_busreq_r & ((WrPtr0_r == i) | (ldst_dual_r & (WrPtr1_r == i))))); | ||||
|          end | ||||
|       end | ||||
|    end | ||||
| 
 | ||||
|    // Get the command ptr
 | ||||
|    for (genvar i=0; i<32'(DEPTH); i++) begin | ||||
|    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]; | ||||
|  | @ -594,14 +587,13 @@ import el2_pkg::*; | |||
| 
 | ||||
|    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])); | ||||
|    assign RspPtr  = f_Enc8to3(8'(RspPtrDec[DEPTH-1:0])); | ||||
| 
 | ||||
|    // Age vector
 | ||||
|    for (genvar i=0; i<32'(DEPTH); i++) begin: GenAgeVec | ||||
|       for (genvar j=0; j<32'(DEPTH); j++) begin | ||||
|    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_r & (ibuf_byp | ldst_dual_r) & (i == WrPtr0_r) & (j == ibuf_tag))  |       // Set case for dual lo
 | ||||
|  | @ -609,7 +601,7 @@ import el2_pkg::*; | |||
|                                    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[i][j]    = buf_ageQ[i][j] & ~((buf_state[j] == CMD) & buf_cmd_state_bus_en[j]) & ~dec_tlu_force_halt;  // Reset case
 | ||||
| 
 | ||||
|          assign buf_age_younger[i][j] = (i == j) ? 1'b0: (~buf_age[i][j] & (buf_state[j] != IDLE));   // Younger entries
 | ||||
|       end | ||||
|  | @ -623,7 +615,7 @@ import el2_pkg::*; | |||
|                                             (ibuf_drain_vld & lsu_busreq_r & (ibuf_byp | ldst_dual_r) & (DEPTH_LOG2'(i) == WrPtr0_r) & (DEPTH_LOG2'(j) == ibuf_tag))  |       // Set case for dual lo
 | ||||
|                                             (ibuf_byp & lsu_busreq_r & ldst_dual_r & (DEPTH_LOG2'(i) == WrPtr1_r) & (DEPTH_LOG2'(j) == WrPtr0_r))); | ||||
|          assign buf_rspage_in[i][j] = buf_rspage_set[i][j] | buf_rspage[i][j]; | ||||
|          assign buf_rspage[i][j]    = buf_rspageQ[i][j] & ~((buf_state[j] == DONE) | (buf_state[j] == IDLE));  // Reset case
 | ||||
|          assign buf_rspage[i][j]    = buf_rspageQ[i][j] & ~((buf_state[j] == DONE) | (buf_state[j] == IDLE)) & ~dec_tlu_force_halt;  // Reset case
 | ||||
|          assign buf_rsp_pickage[i][j] = buf_rspageQ[i][j] & (buf_state[j] == DONE_WAIT); | ||||
|      end | ||||
|    end | ||||
|  | @ -631,7 +623,7 @@ import el2_pkg::*; | |||
|    //------------------------------------------------------------------------------
 | ||||
|    // Buffer logic
 | ||||
|    //------------------------------------------------------------------------------
 | ||||
|    for (genvar i=0; i<32'(DEPTH); i++) begin | ||||
|    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_r & (i == WrPtr1_r)) ? ldst_byteen_hi_r[3:0] : ldst_byteen_lo_r[3:0]); | ||||
|  | @ -641,7 +633,6 @@ import el2_pkg::*; | |||
|       assign buf_nomerge_in[i]    = ibuf_drainvec_vld[i] ? (ibuf_nomerge | ibuf_force_drain) : no_dword_merge_r; | ||||
|       assign buf_dualhi_in[i]     = ibuf_drainvec_vld[i] ? ibuf_dual : (ibuf_byp & ldst_dual_r & (i == WrPtr1_r));   // 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_r & (i == WrPtr1_r)) ? WrPtr0_r : WrPtr1_r); | ||||
|       //assign buf_nb_in[i]         = ibuf_drainvec_vld[i] ? ibuf_nb : lsu_nonblock_load_valid_r;
 | ||||
|       assign buf_sideeffect_in[i] = ibuf_drainvec_vld[i] ? ibuf_sideeffect : is_sideeffects_r; | ||||
|       assign buf_unsign_in[i]     = ibuf_drainvec_vld[i] ? ibuf_unsign : lsu_pkt_r.unsign; | ||||
|       assign buf_sz_in[i]         = ibuf_drainvec_vld[i] ? ibuf_sz : {lsu_pkt_r.word, lsu_pkt_r.half}; | ||||
|  | @ -651,15 +642,14 @@ import el2_pkg::*; | |||
|       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; | ||||
|          buf_ldfwd_en[i]          = '0; | ||||
|          buf_rst[i]               = dec_tlu_force_halt; | ||||
|          buf_ldfwd_en[i]          = dec_tlu_force_halt; | ||||
|          buf_ldfwd_in[i]          = '0; | ||||
|          buf_ldfwdtag_in[i]       = '0; | ||||
| 
 | ||||
|  | @ -671,10 +661,12 @@ import el2_pkg::*; | |||
|                      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_r[31:0]; | ||||
|                      buf_cmd_state_bus_en[i]  = '0; | ||||
|             end | ||||
|             WAIT: begin | ||||
|                      buf_nxtstate[i] = dec_tlu_force_halt ? IDLE : CMD; | ||||
|                      buf_state_en[i] = lsu_bus_clk_en | dec_tlu_force_halt; | ||||
|                      buf_cmd_state_bus_en[i]  = '0; | ||||
|             end | ||||
|             CMD: begin | ||||
|                      buf_nxtstate[i]          = dec_tlu_force_halt ? IDLE : (obuf_nosend & bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag)) ? DONE_WAIT : RESP; | ||||
|  | @ -689,7 +681,7 @@ import el2_pkg::*; | |||
|                      buf_data_in[i]           = buf_error_en[i] ? bus_rsp_rdata[31:0] : (buf_addr[i][2] ? bus_rsp_rdata[63:32] : bus_rsp_rdata[31:0]); | ||||
|             end | ||||
|             RESP: begin | ||||
|                      buf_nxtstate[i]           = (dec_tlu_force_halt | (buf_write[i] & ~(pt.BUILD_AXI_NATIVE & bus_rsp_write_error))) ? IDLE :    // Side-effect writes will be non-posted
 | ||||
|                      buf_nxtstate[i]           = (dec_tlu_force_halt | (buf_write[i] & ~bus_rsp_write_error)) ? IDLE :    // Side-effect writes will be non-posted
 | ||||
|                                                       (buf_dual[i] & ~buf_samedw[i] & ~buf_write[i] & (buf_state[buf_dualtag[i]] != DONE_PARTIAL)) ? DONE_PARTIAL : // Goto DONE_PARTIAL if this is the first return of dual
 | ||||
|                                                            (buf_ldfwd[i] | any_done_wait_state | | ||||
|                                                             (buf_dual[i] & ~buf_samedw[i] & ~buf_write[i] & buf_ldfwd[buf_dualtag[i]] & | ||||
|  | @ -704,19 +696,21 @@ import el2_pkg::*; | |||
|                       // 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  == (pt.LSU_BUS_TAG)'(i))) | | ||||
|                                                                                          (bus_rsp_read_error  & buf_ldfwd[i] & (bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_ldfwdtag[i]))) | | ||||
|                                                                                          (bus_rsp_write_error & pt.BUILD_AXI_NATIVE & (bus_rsp_write_tag == (pt.LSU_BUS_TAG)'(i)))); | ||||
|                                                                                          (bus_rsp_write_error & (bus_rsp_write_tag == (pt.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]; | ||||
|                      buf_cmd_state_bus_en[i]  = '0; | ||||
|             end | ||||
|             DONE_PARTIAL: begin   // Other part of dual load hasn't returned
 | ||||
|                      buf_nxtstate[i]           = dec_tlu_force_halt ? IDLE : (buf_ldfwd[i] | buf_ldfwd[buf_dualtag[i]] | any_done_wait_state) ? DONE_WAIT : DONE; | ||||
|                      buf_state_bus_en[i]       = bus_rsp_read & ((bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_dualtag[i])) | | ||||
|                                                                  //(buf_ldfwd[i] & (bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_ldfwdtag[i]))) |
 | ||||
|                                                                  (buf_ldfwd[buf_dualtag[i]] & (bus_rsp_read_tag == (pt.LSU_BUS_TAG)'(buf_ldfwdtag[buf_dualtag[i]])))); | ||||
|                      buf_state_en[i]           = (buf_state_bus_en[i] & lsu_bus_clk_en) | dec_tlu_force_halt; | ||||
|                      buf_cmd_state_bus_en[i]  = '0; | ||||
|             end | ||||
|             DONE_WAIT: begin  // WAIT state if there are multiple outstanding nb returns
 | ||||
|                       buf_nxtstate[i]           = dec_tlu_force_halt ? IDLE : DONE; | ||||
|                       buf_state_en[i]           = ((RspPtr == DEPTH_LOG2'(i)) | (buf_dual[i] & (buf_dualtag[i] == RspPtr))) | dec_tlu_force_halt; | ||||
|                       buf_cmd_state_bus_en[i]  = '0; | ||||
|             end | ||||
|             DONE: begin | ||||
|                      buf_nxtstate[i]           = IDLE; | ||||
|  | @ -724,11 +718,11 @@ import el2_pkg::*; | |||
|                      buf_state_en[i]           = 1'b1; | ||||
|                      buf_ldfwd_in[i]           = 1'b0; | ||||
|                      buf_ldfwd_en[i]           = buf_state_en[i]; | ||||
|                      buf_cmd_state_bus_en[i]  = '0; | ||||
|             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; | ||||
|  | @ -736,6 +730,7 @@ import el2_pkg::*; | |||
|                      buf_data_en[i]           = '0; | ||||
|                      buf_error_en[i]          = '0; | ||||
|                      buf_rst[i]               = '0; | ||||
|                      buf_cmd_state_bus_en[i]  = '0; | ||||
|             end | ||||
|          endcase | ||||
|       end | ||||
|  | @ -750,7 +745,6 @@ import el2_pkg::*; | |||
|       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_ldfwdff      (.din(buf_ldfwd_in[i]),             .dout(buf_ldfwd[i]),      .en(buf_ldfwd_en[i]),                                        .clk(lsu_bus_buf_c1_clk), .*); | ||||
|       rvdffs  #(.WIDTH(DEPTH_LOG2))     buf_ldfwdtagff   (.din(buf_ldfwdtag_in[i]),          .dout(buf_ldfwdtag[i]),   .en(buf_ldfwd_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), .*); | ||||
|  | @ -764,14 +758,14 @@ import el2_pkg::*; | |||
| 
 | ||||
|    // buffer full logic
 | ||||
|    always_comb begin | ||||
|       buf_numvld_any[3:0] =  4'(({3'b0,lsu_busreq_m} << ldst_dual_m) + | ||||
|                                 ({3'b0,lsu_busreq_r} << ldst_dual_r) + | ||||
|                                 {3'b0,ibuf_valid}); | ||||
|       buf_numvld_any[3:0] =  ({1'b0,lsu_busreq_m} << ldst_dual_m) + | ||||
|                              ({1'b0,lsu_busreq_r} << ldst_dual_r) + | ||||
|                              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; | ||||
|       any_done_wait_state = 1'b0; | ||||
|       for (int i=0; i<32'(DEPTH); i++) begin | ||||
|       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])}; | ||||
|  | @ -781,7 +775,7 @@ import el2_pkg::*; | |||
|    end | ||||
| 
 | ||||
|    assign lsu_bus_buffer_pend_any = (buf_numvld_pend_any != 0); | ||||
|    assign lsu_bus_buffer_full_any = (ldst_dual_d & dec_lsu_valid_raw_d) ? (buf_numvld_any[3:0] >= (DEPTH-1)) : (buf_numvld_any[3:0] == 4'(DEPTH)); | ||||
|    assign lsu_bus_buffer_full_any = (ldst_dual_d & dec_lsu_valid_raw_d) ? (buf_numvld_any[3:0] >= (DEPTH-1)) : (buf_numvld_any[3:0] == DEPTH); | ||||
|    assign lsu_bus_buffer_empty_any = ~(|buf_state[DEPTH-1:0]) & ~ibuf_valid & ~obuf_valid; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -797,9 +791,9 @@ import el2_pkg::*; | |||
|       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<32'(DEPTH); i++) begin | ||||
|       for (int i=0; i<DEPTH; i++) begin | ||||
|           // Use buf_rst[i] instead of buf_state_en[i] for timing
 | ||||
|           lsu_nonblock_load_data_ready      |= (buf_state[i] == DONE) & ~(pt.BUILD_AXI_NATIVE & buf_write[i]); | ||||
|           lsu_nonblock_load_data_ready      |= (buf_state[i] == DONE) & ~buf_write[i]; | ||||
|           lsu_nonblock_load_data_error      |= (buf_state[i] == DONE) & buf_error[i] & ~buf_write[i]; | ||||
|           lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0]   |= DEPTH_LOG2'(i) & {DEPTH_LOG2{((buf_state[i] == DONE) & ~buf_write[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_write[i] & (~buf_dual[i] | ~buf_dualhi[i]))}}; | ||||
|  | @ -810,7 +804,6 @@ import el2_pkg::*; | |||
|    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_ready & ~lsu_nonblock_load_data_error; | ||||
|  | @ -823,7 +816,7 @@ import el2_pkg::*; | |||
|    // 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<32'(DEPTH); i++) begin | ||||
|       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 | ||||
|  | @ -831,8 +824,8 @@ import el2_pkg::*; | |||
|    // 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<32'(DEPTH); i++) begin | ||||
|          bus_addr_match_pending |= (pt.BUILD_AXI_NATIVE & obuf_valid & (obuf_addr[31:3] == buf_addr[i][31:3]) & (buf_state[i] == RESP) & ~((obuf_tag0 == (pt.LSU_BUS_TAG)'(i)) | (obuf_merge & (obuf_tag1 == (pt.LSU_BUS_TAG)'(i))))); | ||||
|       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 == (pt.LSU_BUS_TAG)'(i)) | (obuf_merge & (obuf_tag1 == (pt.LSU_BUS_TAG)'(i))))); | ||||
|       end | ||||
|    end | ||||
| 
 | ||||
|  | @ -855,7 +848,7 @@ import el2_pkg::*; | |||
|    assign lsu_axi_awid[pt.LSU_BUS_TAG-1:0] = (pt.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_awprot[2:0]           = 3'b001; | ||||
|    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; | ||||
|  | @ -872,7 +865,7 @@ import el2_pkg::*; | |||
|    assign lsu_axi_arid[pt.LSU_BUS_TAG-1:0] = (pt.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_arprot[2:0]           = 3'b001; | ||||
|    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; | ||||
|  | @ -886,7 +879,7 @@ import el2_pkg::*; | |||
|    always_comb begin | ||||
|       lsu_imprecise_error_store_any = '0; | ||||
|       lsu_imprecise_error_store_tag = '0; | ||||
|       for (int i=0; i<32'(DEPTH); i++) begin | ||||
|       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 | ||||
|  | @ -894,36 +887,29 @@ import el2_pkg::*; | |||
|    assign lsu_imprecise_error_load_any       = lsu_nonblock_load_data_error & ~lsu_imprecise_error_store_any;   // This is to make sure we send only one imprecise error for load/store
 | ||||
|    assign lsu_imprecise_error_addr_any[31:0] = lsu_imprecise_error_store_any ? buf_addr[lsu_imprecise_error_store_tag] : buf_addr[lsu_nonblock_load_data_tag]; | ||||
| 
 | ||||
|    // Count the number of pending trxns for fence (doesn't apply to AXI)
 | ||||
|    assign bus_pend_trxnQ[7:0] = 8'b0; | ||||
|    assign bus_pend_trxn[7:0]    = 8'b0; | ||||
|    assign bus_pend_trxn_ns[7:0] = 8'b0; | ||||
|    assign lsu_bus_cntr_overflow = 1'b0; | ||||
|    assign lsu_bus_idle_any      = 1'b1; | ||||
| 
 | ||||
|    // PMU signals
 | ||||
|    assign lsu_pmu_bus_trxn  = (lsu_axi_awvalid & lsu_axi_awready) | (lsu_axi_wvalid & lsu_axi_wready) | (lsu_axi_arvalid & lsu_axi_arready); | ||||
|    assign lsu_pmu_bus_misaligned = lsu_busreq_r & ldst_dual_r & lsu_commit_r; | ||||
|    assign lsu_pmu_bus_error = lsu_imprecise_error_load_any | lsu_imprecise_error_store_any; | ||||
|    assign lsu_pmu_bus_busy  = (lsu_axi_awvalid & ~lsu_axi_awready) | (lsu_axi_wvalid & ~lsu_axi_wready) | (lsu_axi_arvalid & ~lsu_axi_arready); | ||||
| 
 | ||||
|    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_fpga #(.WIDTH(1))               lsu_axi_awvalid_ff (.din(lsu_axi_awvalid),                .dout(lsu_axi_awvalid_q),                .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))               lsu_axi_awready_ff (.din(lsu_axi_awready),                .dout(lsu_axi_awready_q),                .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))               lsu_axi_wvalid_ff  (.din(lsu_axi_wvalid),                 .dout(lsu_axi_wvalid_q),                 .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))               lsu_axi_wready_ff  (.din(lsu_axi_wready),                 .dout(lsu_axi_wready_q),                 .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))               lsu_axi_arvalid_ff (.din(lsu_axi_arvalid),                .dout(lsu_axi_arvalid_q),                .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga #(.WIDTH(1))               lsu_axi_arready_ff (.din(lsu_axi_arready),                .dout(lsu_axi_arready_q),                .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(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(pt.LSU_BUS_TAG)) lsu_axi_bid_ff     (.din(lsu_axi_bid[pt.LSU_BUS_TAG-1:0]),.dout(lsu_axi_bid_q[pt.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_fpga  #(.WIDTH(1))              lsu_axi_bvalid_ff  (.din(lsu_axi_bvalid),                 .dout(lsu_axi_bvalid_q),                 .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(1))              lsu_axi_bready_ff  (.din(lsu_axi_bready),                 .dout(lsu_axi_bready_q),                 .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(2))              lsu_axi_bresp_ff   (.din(lsu_axi_bresp[1:0]),             .dout(lsu_axi_bresp_q[1:0]),             .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(pt.LSU_BUS_TAG)) lsu_axi_bid_ff     (.din(lsu_axi_bid[pt.LSU_BUS_TAG-1:0]),.dout(lsu_axi_bid_q[pt.LSU_BUS_TAG-1:0]),.clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(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 | clk_override) & 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(pt.LSU_BUS_TAG)) lsu_axi_rid_ff     (.din(lsu_axi_rid[pt.LSU_BUS_TAG-1:0]),.dout(lsu_axi_rid_q[pt.LSU_BUS_TAG-1:0]),.clk(lsu_busm_clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(1))              lsu_axi_rvalid_ff  (.din(lsu_axi_rvalid),                 .dout(lsu_axi_rvalid_q),                 .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(1))              lsu_axi_rready_ff  (.din(lsu_axi_rready),                 .dout(lsu_axi_rready_q),                 .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(2))              lsu_axi_rresp_ff   (.din(lsu_axi_rresp[1:0]),             .dout(lsu_axi_rresp_q[1:0]),             .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
|    rvdff_fpga  #(.WIDTH(pt.LSU_BUS_TAG)) lsu_axi_rid_ff     (.din(lsu_axi_rid[pt.LSU_BUS_TAG-1:0]),.dout(lsu_axi_rid_q[pt.LSU_BUS_TAG-1:0]),.clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); | ||||
| 
 | ||||
|    rvdff #(.WIDTH(DEPTH_LOG2)) lsu_WrPtr0_rff (.din(WrPtr0_m), .dout(WrPtr0_r), .clk(lsu_c2_r_clk), .*); | ||||
|    rvdff #(.WIDTH(DEPTH_LOG2)) lsu_WrPtr1_rff (.din(WrPtr1_m), .dout(WrPtr1_r), .clk(lsu_c2_r_clk), .*); | ||||
|  | @ -931,15 +917,19 @@ import el2_pkg::*; | |||
|    rvdff #(.WIDTH(1)) lsu_busreq_rff (.din(lsu_busreq_m & ~flush_r & ~ld_full_hit_m),      .dout(lsu_busreq_r), .clk(lsu_c2_r_clk), .*); | ||||
|    rvdff #(.WIDTH(1)) lsu_nonblock_load_valid_rff  (.din(lsu_nonblock_load_valid_m),  .dout(lsu_nonblock_load_valid_r), .clk(lsu_c2_r_clk), .*); | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_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])); | ||||
|    for (genvar i=0; i<DEPTH; i++) begin: GenAssertAge | ||||
|       assert_bufempty_agevec: assert #0 (~(lsu_bus_buffer_empty_any & |(buf_age[i]))); | ||||
|    end | ||||
| 
 | ||||
|    assert_CmdPtr0Dec_onehot: assert #0 ($onehot0(CmdPtr0Dec[DEPTH-1:0] & ~{DEPTH{dec_tlu_force_halt}})); | ||||
|    assert_CmdPtr1Dec_onehot: assert #0 ($onehot0(CmdPtr1Dec[DEPTH-1:0] & ~{DEPTH{dec_tlu_force_halt}})); | ||||
| 
 | ||||
| `endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -27,23 +27,26 @@ import el2_pkg::*; | |||
| #( | ||||
| `include "el2_param.vh" | ||||
|  )( | ||||
|    input logic                          clk, | ||||
|    input logic                          rst_l, | ||||
|    input logic                          scan_mode, | ||||
|    input logic                          clk,                                // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic                          clk_override,                       // Override non-functional clock gating
 | ||||
|    input logic                          rst_l,                              // reset, active low
 | ||||
|    input logic                          scan_mode,                          // scan mode
 | ||||
|    input logic                          dec_tlu_external_ldfwd_disable,     // disable load to load forwarding for externals
 | ||||
|    input logic                          dec_tlu_wb_coalescing_disable,    // disable write buffer coalescing
 | ||||
|    input logic                          dec_tlu_sideeffect_posted_disable, // disable the posted sideeffect load store to the bus
 | ||||
|    input logic                          dec_tlu_wb_coalescing_disable,      // disable write buffer coalescing
 | ||||
|    input logic                          dec_tlu_sideeffect_posted_disable,  // disable the posted sideeffect load store to the bus
 | ||||
| 
 | ||||
|    // various clocks needed for the bus reads and writes
 | ||||
|    input logic                          lsu_c1_m_clk, | ||||
|    input logic                          lsu_c1_r_clk, | ||||
|    input logic                          lsu_c2_r_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_bus_obuf_c1_clken,              // obuf clock enable
 | ||||
|    input logic                          lsu_busm_clken,                     // bus clock enable
 | ||||
| 
 | ||||
|    input logic                          lsu_c1_r_clk,                       // r pipe single pulse clock
 | ||||
|    input logic                          lsu_c2_r_clk,                       // r pipe double pulse clock
 | ||||
|    input logic                          lsu_bus_ibuf_c1_clk,                // ibuf single pulse clock
 | ||||
|    input logic                          lsu_bus_obuf_c1_clk,                // obuf single pulse clock
 | ||||
|    input logic                          lsu_bus_buf_c1_clk,                 // buf  single pulse clock
 | ||||
|    input logic                          lsu_free_c2_clk,                    // free clock double pulse clock
 | ||||
|    input logic                          active_clk,                         // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic                          lsu_busm_clk,                       // bus clock
 | ||||
| 
 | ||||
|    input logic                          dec_lsu_valid_raw_d,               // Raw valid for address computation
 | ||||
|    input logic                          lsu_busreq_m,                      // bus request is in m
 | ||||
|  | @ -51,11 +54,9 @@ import el2_pkg::*; | |||
|    input                                el2_lsu_pkt_t lsu_pkt_m,          // lsu packet flowing down the pipe
 | ||||
|    input                                el2_lsu_pkt_t lsu_pkt_r,          // lsu packet flowing down the pipe
 | ||||
| 
 | ||||
|    input logic [31:0]                   lsu_addr_d,                        // lsu address flowing down the pipe
 | ||||
|    input logic [31:0]                   lsu_addr_m,                        // lsu address flowing down the pipe
 | ||||
|    input logic [31:0]                   lsu_addr_r,                        // lsu address flowing down the pipe
 | ||||
| 
 | ||||
|    input logic [31:0]                   end_addr_d,                        // lsu address flowing down the pipe
 | ||||
|    input logic [31:0]                   end_addr_m,                        // lsu address flowing down the pipe
 | ||||
|    input logic [31:0]                   end_addr_r,                        // lsu address flowing down the pipe
 | ||||
| 
 | ||||
|  | @ -64,14 +65,14 @@ import el2_pkg::*; | |||
| 
 | ||||
|    input logic                          lsu_commit_r,                      // lsu instruction in r commits
 | ||||
|    input logic                          is_sideeffects_m,                  // lsu attribute is side_effects
 | ||||
|    input logic                          flush_m_up,                           // flush
 | ||||
|    input logic                          flush_m_up,                        // flush
 | ||||
|    input logic                          flush_r,                           // flush
 | ||||
|    input logic                          ldst_dual_d, ldst_dual_m, ldst_dual_r, | ||||
| 
 | ||||
|    output logic                         lsu_busreq_r,                      // bus request is in r
 | ||||
|    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                         lsu_bus_idle_any,                  // NO pending responses from the bus
 | ||||
|    output logic [31:0]                  bus_read_data_m,                   // the bus return data
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -139,7 +140,6 @@ import el2_pkg::*; | |||
|    input  logic [pt.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 | ||||
| 
 | ||||
|  | @ -148,7 +148,6 @@ import el2_pkg::*; | |||
| 
 | ||||
| 
 | ||||
|    logic              lsu_bus_clk_en_q; | ||||
|    logic              ldst_dual_d, ldst_dual_m, ldst_dual_r; | ||||
| 
 | ||||
|    logic [3:0]        ldst_byteen_m, ldst_byteen_r; | ||||
|    logic [7:0]        ldst_byteen_ext_m, ldst_byteen_ext_r; | ||||
|  | @ -185,7 +184,6 @@ import el2_pkg::*; | |||
|    assign ldst_byteen_m[3:0] = ({4{lsu_pkt_m.by}}   & 4'b0001) | | ||||
|                                  ({4{lsu_pkt_m.half}} & 4'b0011) | | ||||
|                                  ({4{lsu_pkt_m.word}} & 4'b1111); | ||||
|    assign ldst_dual_d = (lsu_addr_d[2] != end_addr_d[2]); | ||||
| 
 | ||||
|    // Read/Write Buffer
 | ||||
|    el2_lsu_bus_buffer #(.pt(pt)) bus_buffer ( | ||||
|  | @ -263,106 +261,104 @@ import el2_pkg::*; | |||
| 
 | ||||
|    // Fifo flops
 | ||||
| 
 | ||||
|    rvdff #(.WIDTH(1)) clken_ff (.din(lsu_bus_clk_en), .dout(lsu_bus_clk_en_q), .clk(free_clk), .*); | ||||
|    rvdff #(.WIDTH(1)) clken_ff (.din(lsu_bus_clk_en), .dout(lsu_bus_clk_en_q), .clk(active_clk), .*); | ||||
| 
 | ||||
|    rvdff #(.WIDTH(1)) ldst_dual_mff (.din(ldst_dual_d), .dout(ldst_dual_m), .clk(lsu_c1_m_clk), .*); | ||||
|    rvdff #(.WIDTH(1)) ldst_dual_rff (.din(ldst_dual_m), .dout(ldst_dual_r), .clk(lsu_c1_r_clk), .*); | ||||
|    rvdff #(.WIDTH(1)) is_sideeffects_rff (.din(is_sideeffects_m), .dout(is_sideeffects_r), .clk(lsu_c1_r_clk), .*); | ||||
| 
 | ||||
|    rvdff #(4) lsu_byten_rff (.*, .din(ldst_byteen_m[3:0]), .dout(ldst_byteen_r[3:0]), .clk(lsu_c1_r_clk)); | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_ASSERT_ON | ||||
| 
 | ||||
|      // Assertion to check AXI write address is aligned to size
 | ||||
|      property lsu_axi_awaddr_aligned; | ||||
|        @(posedge lsu_busm_clk) disable iff(~rst_l) lsu_axi_awvalid |-> ((lsu_axi_awsize[2:0] == 3'h0)                                   | | ||||
|                                                                         ((lsu_axi_awsize[2:0] == 3'h1) & (lsu_axi_awaddr[0] == 1'b0))   | | ||||
|                                                                         ((lsu_axi_awsize[2:0] == 3'h2) & (lsu_axi_awaddr[1:0] == 2'b0)) | | ||||
|                                                                         ((lsu_axi_awsize[2:0] == 3'h3) & (lsu_axi_awaddr[2:0] == 3'b0))); | ||||
|      endproperty | ||||
|      assert_lsu_axi_awaddr_aligned: assert property (lsu_axi_awaddr_aligned) else | ||||
|        $display("Assertion lsu_axi_awaddr_aligned failed: lsu_axi_awvalid=1'b%b, lsu_axi_awsize=3'h%h, lsu_axi_awaddr=32'h%h",lsu_axi_awvalid, lsu_axi_awsize[2:0], lsu_axi_awaddr[31:0]); | ||||
|      // Assertion to check awvalid stays stable during entire bus clock
 | ||||
|   // Assertion to check AXI write address is aligned to size
 | ||||
|   property lsu_axi_awaddr_aligned; | ||||
|     @(posedge lsu_busm_clk) disable iff(~rst_l) lsu_axi_awvalid |-> ((lsu_axi_awsize[2:0] == 3'h0)                                   | | ||||
|                                                                      ((lsu_axi_awsize[2:0] == 3'h1) & (lsu_axi_awaddr[0] == 1'b0))   | | ||||
|                                                                      ((lsu_axi_awsize[2:0] == 3'h2) & (lsu_axi_awaddr[1:0] == 2'b0)) | | ||||
|                                                                      ((lsu_axi_awsize[2:0] == 3'h3) & (lsu_axi_awaddr[2:0] == 3'b0))); | ||||
|   endproperty | ||||
|   assert_lsu_axi_awaddr_aligned: assert property (lsu_axi_awaddr_aligned) else | ||||
|     $display("Assertion lsu_axi_awaddr_aligned failed: lsu_axi_awvalid=1'b%b, lsu_axi_awsize=3'h%h, lsu_axi_awaddr=32'h%h",lsu_axi_awvalid, lsu_axi_awsize[2:0], lsu_axi_awaddr[31:0]); | ||||
|   // Assertion to check awvalid stays stable during entire bus clock
 | ||||
| 
 | ||||
|      // Assertion to check AXI read address is aligned to size
 | ||||
|      property lsu_axi_araddr_aligned; | ||||
|        @(posedge lsu_busm_clk) disable iff(~rst_l) lsu_axi_arvalid |-> ((lsu_axi_arsize[2:0] == 3'h0)                                   | | ||||
|                                                                         ((lsu_axi_arsize[2:0] == 3'h1) & (lsu_axi_araddr[0] == 1'b0))   | | ||||
|                                                                         ((lsu_axi_arsize[2:0] == 3'h2) & (lsu_axi_araddr[1:0] == 2'b0)) | | ||||
|                                                                         ((lsu_axi_arsize[2:0] == 3'h3) & (lsu_axi_araddr[2:0] == 3'b0))); | ||||
|      endproperty | ||||
|      assert_lsu_axi_araddr_aligned: assert property (lsu_axi_araddr_aligned) else | ||||
|        $display("Assertion lsu_axi_araddr_aligned failed: lsu_axi_awvalid=1'b%b, lsu_axi_awsize=3'h%h, lsu_axi_araddr=32'h%h",lsu_axi_awvalid, lsu_axi_awsize[2:0], lsu_axi_araddr[31:0]); | ||||
|   // Assertion to check AXI read address is aligned to size
 | ||||
|   property lsu_axi_araddr_aligned; | ||||
|     @(posedge lsu_busm_clk) disable iff(~rst_l) lsu_axi_arvalid |-> ((lsu_axi_arsize[2:0] == 3'h0)                                   | | ||||
|                                                                      ((lsu_axi_arsize[2:0] == 3'h1) & (lsu_axi_araddr[0] == 1'b0))   | | ||||
|                                                                      ((lsu_axi_arsize[2:0] == 3'h2) & (lsu_axi_araddr[1:0] == 2'b0)) | | ||||
|                                                                      ((lsu_axi_arsize[2:0] == 3'h3) & (lsu_axi_araddr[2:0] == 3'b0))); | ||||
|   endproperty | ||||
|   assert_lsu_axi_araddr_aligned: assert property (lsu_axi_araddr_aligned) else | ||||
|     $display("Assertion lsu_axi_araddr_aligned failed: lsu_axi_awvalid=1'b%b, lsu_axi_awsize=3'h%h, lsu_axi_araddr=32'h%h",lsu_axi_awvalid, lsu_axi_awsize[2:0], lsu_axi_araddr[31:0]); | ||||
| 
 | ||||
|      // Assertion to check awvalid stays stable during entire bus clock
 | ||||
|     property lsu_axi_awvalid_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid != $past(lsu_axi_awvalid)) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_awvalid_stable: assert property (lsu_axi_awvalid_stable) else | ||||
|         $display("LSU AXI awvalid changed in middle of bus clock"); | ||||
|   // Assertion to check awvalid stays stable during entire bus clock
 | ||||
|  property lsu_axi_awvalid_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid != $past(lsu_axi_awvalid)) |-> ($past(lsu_bus_clk_en) | dec_tlu_force_halt); | ||||
|   endproperty | ||||
|   assert_lsu_axi_awvalid_stable: assert property (lsu_axi_awvalid_stable) else | ||||
|      $display("LSU AXI awvalid changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check awid stays stable during entire bus clock
 | ||||
|      property lsu_axi_awid_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid & (lsu_axi_awid[pt.LSU_BUS_TAG-1:0] != $past(lsu_axi_awid[pt.LSU_BUS_TAG-1:0]))) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_awid_stable: assert property (lsu_axi_awid_stable) else | ||||
|         $display("LSU AXI awid changed in middle of bus clock"); | ||||
|   // Assertion to check awid stays stable during entire bus clock
 | ||||
|   property lsu_axi_awid_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid & (lsu_axi_awid[pt.LSU_BUS_TAG-1:0] != $past(lsu_axi_awid[pt.LSU_BUS_TAG-1:0]))) |-> $past(lsu_bus_clk_en); | ||||
|   endproperty | ||||
|   assert_lsu_axi_awid_stable: assert property (lsu_axi_awid_stable) else | ||||
|      $display("LSU AXI awid changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check awaddr stays stable during entire bus clock
 | ||||
|      property lsu_axi_awaddr_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid & (lsu_axi_awaddr[31:0] != $past(lsu_axi_awaddr[31:0]))) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_awaddr_stable: assert property (lsu_axi_awaddr_stable) else | ||||
|         $display("LSU AXI awaddr changed in middle of bus clock"); | ||||
|   // Assertion to check awaddr stays stable during entire bus clock
 | ||||
|   property lsu_axi_awaddr_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid & (lsu_axi_awaddr[31:0] != $past(lsu_axi_awaddr[31:0]))) |-> $past(lsu_bus_clk_en); | ||||
|   endproperty | ||||
|   assert_lsu_axi_awaddr_stable: assert property (lsu_axi_awaddr_stable) else | ||||
|      $display("LSU AXI awaddr changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check awsize stays stable during entire bus clock
 | ||||
|      property lsu_axi_awsize_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid & (lsu_axi_awsize[2:0] != $past(lsu_axi_awsize[2:0]))) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_awsize_stable: assert property (lsu_axi_awsize_stable) else | ||||
|         $display("LSU AXI awsize changed in middle of bus clock"); | ||||
|   // Assertion to check awsize stays stable during entire bus clock
 | ||||
|   property lsu_axi_awsize_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid & (lsu_axi_awsize[2:0] != $past(lsu_axi_awsize[2:0]))) |-> $past(lsu_bus_clk_en); | ||||
|   endproperty | ||||
|   assert_lsu_axi_awsize_stable: assert property (lsu_axi_awsize_stable) else | ||||
|      $display("LSU AXI awsize changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check wstrb stays stable during entire bus clock
 | ||||
|      property lsu_axi_wstrb_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_wvalid & (lsu_axi_wstrb[7:0] != $past(lsu_axi_wstrb[7:0]))) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_wstrb_stable: assert property (lsu_axi_wstrb_stable) else | ||||
|         $display("LSU AXI wstrb changed in middle of bus clock"); | ||||
|   // Assertion to check wstrb stays stable during entire bus clock
 | ||||
|   property lsu_axi_wstrb_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_wvalid & (lsu_axi_wstrb[7:0] != $past(lsu_axi_wstrb[7:0]))) |-> $past(lsu_bus_clk_en); | ||||
|   endproperty | ||||
|   assert_lsu_axi_wstrb_stable: assert property (lsu_axi_wstrb_stable) else | ||||
|      $display("LSU AXI wstrb changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check wdata stays stable during entire bus clock
 | ||||
|      property lsu_axi_wdata_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_wvalid & (lsu_axi_wdata[63:0] != $past(lsu_axi_wdata[63:0]))) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_wdata_stable: assert property (lsu_axi_wdata_stable) else | ||||
|         $display("LSU AXI wdata changed in middle of bus clock"); | ||||
|   // Assertion to check wdata stays stable during entire bus clock
 | ||||
|   property lsu_axi_wdata_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_wvalid & (lsu_axi_wdata[63:0] != $past(lsu_axi_wdata[63:0]))) |-> $past(lsu_bus_clk_en); | ||||
|   endproperty | ||||
|   assert_lsu_axi_wdata_stable: assert property (lsu_axi_wdata_stable) else | ||||
|      $display("LSU AXI wdata changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check awvalid stays stable during entire bus clock
 | ||||
|      property lsu_axi_arvalid_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_arvalid != $past(lsu_axi_arvalid)) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_arvalid_stable: assert property (lsu_axi_arvalid_stable) else | ||||
|         $display("LSU AXI awvalid changed in middle of bus clock"); | ||||
|   // Assertion to check awvalid stays stable during entire bus clock
 | ||||
|   property lsu_axi_arvalid_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_arvalid != $past(lsu_axi_arvalid)) |-> ($past(lsu_bus_clk_en) | dec_tlu_force_halt); | ||||
|   endproperty | ||||
|   assert_lsu_axi_arvalid_stable: assert property (lsu_axi_arvalid_stable) else | ||||
|      $display("LSU AXI awvalid changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check awid stays stable during entire bus clock
 | ||||
|      property lsu_axi_arid_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_arvalid & (lsu_axi_arid[pt.LSU_BUS_TAG-1:0] != $past(lsu_axi_arid[pt.LSU_BUS_TAG-1:0]))) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_arid_stable: assert property (lsu_axi_arid_stable) else | ||||
|         $display("LSU AXI awid changed in middle of bus clock"); | ||||
|   // Assertion to check awid stays stable during entire bus clock
 | ||||
|   property lsu_axi_arid_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_arvalid & (lsu_axi_arid[pt.LSU_BUS_TAG-1:0] != $past(lsu_axi_arid[pt.LSU_BUS_TAG-1:0]))) |-> $past(lsu_bus_clk_en); | ||||
|   endproperty | ||||
|   assert_lsu_axi_arid_stable: assert property (lsu_axi_arid_stable) else | ||||
|      $display("LSU AXI awid changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check awaddr stays stable during entire bus clock
 | ||||
|      property lsu_axi_araddr_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_arvalid & (lsu_axi_araddr[31:0] != $past(lsu_axi_araddr[31:0]))) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_araddr_stable: assert property (lsu_axi_araddr_stable) else | ||||
|         $display("LSU AXI awaddr changed in middle of bus clock"); | ||||
|   // Assertion to check awaddr stays stable during entire bus clock
 | ||||
|   property lsu_axi_araddr_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_arvalid & (lsu_axi_araddr[31:0] != $past(lsu_axi_araddr[31:0]))) |-> $past(lsu_bus_clk_en); | ||||
|   endproperty | ||||
|   assert_lsu_axi_araddr_stable: assert property (lsu_axi_araddr_stable) else | ||||
|      $display("LSU AXI awaddr changed in middle of bus clock"); | ||||
| 
 | ||||
|      // Assertion to check awsize stays stable during entire bus clock
 | ||||
|      property lsu_axi_arsize_stable; | ||||
|         @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid & (lsu_axi_arsize[2:0] != $past(lsu_axi_arsize[2:0]))) |-> $past(lsu_bus_clk_en); | ||||
|      endproperty | ||||
|      assert_lsu_axi_arsize_stable: assert property (lsu_axi_arsize_stable) else | ||||
|         $display("LSU AXI awsize changed in middle of bus clock"); | ||||
|   // Assertion to check awsize stays stable during entire bus clock
 | ||||
|   property lsu_axi_arsize_stable; | ||||
|      @(posedge clk) disable iff(~rst_l)  (lsu_axi_awvalid & (lsu_axi_arsize[2:0] != $past(lsu_axi_arsize[2:0]))) |-> $past(lsu_bus_clk_en); | ||||
|   endproperty | ||||
|   assert_lsu_axi_arsize_stable: assert property (lsu_axi_arsize_stable) else | ||||
|      $display("LSU AXI awsize changed in middle of bus clock"); | ||||
| 
 | ||||
| `endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -28,13 +28,13 @@ import el2_pkg::*; | |||
| #( | ||||
| `include "el2_param.vh" | ||||
| )( | ||||
|    input logic      clk,                               // clock
 | ||||
|    input logic      free_clk,                          // clock
 | ||||
|    input logic      rst_l,                             // reset
 | ||||
|    input logic      clk,                               // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic      active_clk,                        // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic      rst_l,                             // reset, active low
 | ||||
|    input logic      dec_tlu_force_halt,                // This will be high till TLU goes to debug halt
 | ||||
| 
 | ||||
|    // Inputs
 | ||||
|    input logic      clk_override,                      // chciken bit to turn off clock gating
 | ||||
|    input logic      addr_in_dccm_m,                    // address in dccm
 | ||||
|    input logic      dma_dccm_req,                      // dma is active
 | ||||
|    input logic      ldst_stbuf_reqvld_r,               // allocating in to the store queue
 | ||||
| 
 | ||||
|  | @ -47,12 +47,15 @@ import el2_pkg::*; | |||
| 
 | ||||
|    input logic      lsu_bus_clk_en,                    // bus clock enable
 | ||||
| 
 | ||||
|    input el2_lsu_pkt_t  lsu_p,                             // lsu packet in decode
 | ||||
|    input el2_lsu_pkt_t  lsu_pkt_d,                         // lsu packet in d
 | ||||
|    input el2_lsu_pkt_t  lsu_pkt_m,                         // lsu packet in m
 | ||||
|    input el2_lsu_pkt_t  lsu_pkt_r,                         // lsu packet in r
 | ||||
|    input el2_lsu_pkt_t  lsu_p,                        // lsu packet in decode
 | ||||
|    input el2_lsu_pkt_t  lsu_pkt_d,                    // lsu packet in d
 | ||||
|    input el2_lsu_pkt_t  lsu_pkt_m,                    // lsu packet in m
 | ||||
|    input el2_lsu_pkt_t  lsu_pkt_r,                    // lsu packet in r
 | ||||
| 
 | ||||
|    // Outputs
 | ||||
|    output logic     lsu_bus_obuf_c1_clken,             // obuf clock enable
 | ||||
|    output logic     lsu_busm_clken,                    // bus clock enable
 | ||||
| 
 | ||||
|    output logic     lsu_c1_m_clk,                      // m pipe single pulse clock
 | ||||
|    output logic     lsu_c1_r_clk,                      // r pipe single pulse clock
 | ||||
| 
 | ||||
|  | @ -68,19 +71,19 @@ import el2_pkg::*; | |||
|    output logic     lsu_bus_buf_c1_clk,                // ibuf clock
 | ||||
|    output logic     lsu_busm_clk,                      // bus clock
 | ||||
| 
 | ||||
|    output logic     lsu_free_c2_clk, | ||||
|    output logic     lsu_free_c2_clk,                   // free double pulse clock
 | ||||
| 
 | ||||
|    input  logic     scan_mode | ||||
|    input  logic     scan_mode                          // Scan mode
 | ||||
| ); | ||||
| 
 | ||||
|    logic lsu_c1_d_clken, lsu_c1_m_clken, lsu_c1_r_clken; | ||||
|    logic lsu_c1_m_clken, lsu_c1_r_clken; | ||||
|    logic lsu_c2_m_clken, lsu_c2_r_clken; | ||||
|    logic lsu_c1_d_clken_q, lsu_c1_m_clken_q, lsu_c1_r_clken_q; | ||||
|    logic lsu_c1_m_clken_q, lsu_c1_r_clken_q; | ||||
|    logic lsu_store_c1_m_clken, lsu_store_c1_r_clken; | ||||
| 
 | ||||
| 
 | ||||
|    logic lsu_stbuf_c1_clken; | ||||
|    logic lsu_bus_ibuf_c1_clken, lsu_bus_obuf_c1_clken, lsu_bus_buf_c1_clken; | ||||
|    logic lsu_bus_ibuf_c1_clken, lsu_bus_buf_c1_clken; | ||||
| 
 | ||||
|    logic lsu_free_c1_clken, lsu_free_c1_clken_q, lsu_free_c2_clken; | ||||
| 
 | ||||
|  | @ -88,8 +91,7 @@ import el2_pkg::*; | |||
|    // Clock Enable logic
 | ||||
|    //-------------------------------------------------------------------------------------------
 | ||||
| 
 | ||||
|    assign lsu_c1_d_clken = lsu_p.valid | dma_dccm_req | clk_override; | ||||
|    assign lsu_c1_m_clken = lsu_pkt_d.valid | lsu_c1_d_clken_q | clk_override; | ||||
|    assign lsu_c1_m_clken = lsu_p.valid | dma_dccm_req | clk_override; | ||||
|    assign lsu_c1_r_clken = lsu_pkt_m.valid | lsu_c1_m_clken_q | clk_override; | ||||
| 
 | ||||
|    assign lsu_c2_m_clken = lsu_c1_m_clken | lsu_c1_m_clken_q | clk_override; | ||||
|  | @ -101,16 +103,15 @@ import el2_pkg::*; | |||
|    assign lsu_stbuf_c1_clken = ldst_stbuf_reqvld_r | stbuf_reqvld_any | stbuf_reqvld_flushed_any | clk_override; | ||||
|    assign lsu_bus_ibuf_c1_clken = lsu_busreq_r | clk_override; | ||||
|    assign lsu_bus_obuf_c1_clken = (lsu_bus_buffer_pend_any | lsu_busreq_r | clk_override) & lsu_bus_clk_en; | ||||
|    assign lsu_bus_buf_c1_clken  = ~lsu_bus_buffer_empty_any | lsu_busreq_r | clk_override; | ||||
|    assign lsu_bus_buf_c1_clken  = ~lsu_bus_buffer_empty_any | lsu_busreq_r | dec_tlu_force_halt | clk_override; | ||||
| 
 | ||||
|    assign lsu_free_c1_clken = (lsu_p.valid | lsu_pkt_d.valid | lsu_pkt_m.valid | lsu_pkt_r.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_free_c1_clkenff (.din(lsu_free_c1_clken), .dout(lsu_free_c1_clken_q), .clk(active_clk), .*); | ||||
| 
 | ||||
|    rvdff #(1) lsu_c1_d_clkenff (.din(lsu_c1_d_clken), .dout(lsu_c1_d_clken_q), .clk(lsu_free_c2_clk), .*); | ||||
|    rvdff #(1) lsu_c1_m_clkenff (.din(lsu_c1_m_clken), .dout(lsu_c1_m_clken_q), .clk(lsu_free_c2_clk), .*); | ||||
|    rvdff #(1) lsu_c1_r_clkenff (.din(lsu_c1_r_clken), .dout(lsu_c1_r_clken_q), .clk(lsu_free_c2_clk), .*); | ||||
| 
 | ||||
|  | @ -126,10 +127,17 @@ import el2_pkg::*; | |||
| 
 | ||||
|    rvoclkhdr lsu_stbuf_c1_cgc ( .en(lsu_stbuf_c1_clken), .l1clk(lsu_stbuf_c1_clk), .* ); | ||||
|    rvoclkhdr 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), .* ); | ||||
|    rvoclkhdr 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), .*); | ||||
|    assign lsu_busm_clken = (~lsu_bus_buffer_empty_any | lsu_busreq_r | clk_override) & lsu_bus_clk_en; | ||||
| 
 | ||||
| `ifdef RV_FPGA_OPTIMIZE | ||||
|    assign lsu_busm_clk = 1'b0; | ||||
|    assign lsu_bus_obuf_c1_clk = 1'b0; | ||||
| `else | ||||
|    rvclkhdr  lsu_bus_obuf_c1_cgc ( .en(lsu_bus_obuf_c1_clken), .l1clk(lsu_bus_obuf_c1_clk), .* ); | ||||
|    rvclkhdr  lsu_busm_cgc (.en(lsu_busm_clken), .l1clk(lsu_busm_clk), .*); | ||||
| `endif | ||||
| 
 | ||||
|    rvoclkhdr lsu_free_cgc (.en(lsu_free_c2_clken), .l1clk(lsu_free_c2_clk), .*); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -32,37 +32,41 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
|   ( | ||||
|    input logic                             lsu_c2_m_clk,     // clocks
 | ||||
|    input logic                             lsu_c2_r_clk,     // clocks
 | ||||
|    input logic                             lsu_c1_r_clk, | ||||
|    input logic                             lsu_store_c1_r_clk, | ||||
|    input logic                             lsu_free_c2_clk, | ||||
|    input logic                             clk, | ||||
|    input logic                             lsu_c2_m_clk,            // clocks
 | ||||
|    input logic                             lsu_c2_r_clk,            // clocks
 | ||||
|    input logic                             lsu_c1_r_clk,            // clocks
 | ||||
|    input logic                             lsu_store_c1_r_clk,      // clocks
 | ||||
|    input logic                             lsu_free_c2_clk,         // clocks
 | ||||
|    input logic                             clk_override,            // Override non-functional clock gating
 | ||||
|    input logic                             clk,                     // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
| 
 | ||||
|    input logic                             rst_l, | ||||
|    input logic                             rst_l,                   // reset, active low
 | ||||
| 
 | ||||
|    input                                   el2_lsu_pkt_t lsu_pkt_r,     // lsu packets
 | ||||
|    input                                   el2_lsu_pkt_t lsu_pkt_m,     // lsu packets
 | ||||
|    input                                   el2_lsu_pkt_t lsu_pkt_d, | ||||
|    input                                   el2_lsu_pkt_t lsu_pkt_r,// lsu packets
 | ||||
|    input                                   el2_lsu_pkt_t lsu_pkt_m,// lsu packets
 | ||||
|    input                                   el2_lsu_pkt_t lsu_pkt_d,// lsu packets
 | ||||
|    input logic                             addr_in_dccm_d,          // address maps to dccm
 | ||||
|    input logic                             addr_in_pic_d,           // address maps to pic
 | ||||
|    input logic                             addr_in_pic_m,           // address maps to pic
 | ||||
|    input logic                             addr_in_dccm_m, addr_in_dccm_r, | ||||
|    input logic                             addr_in_pic_r, | ||||
|    input logic                             addr_in_dccm_m, addr_in_dccm_r,   // address in dccm per pipe stage
 | ||||
|    input logic                             addr_in_pic_r,                    // address in pic  per pipe stage
 | ||||
|    input logic                             lsu_raw_fwd_lo_r, lsu_raw_fwd_hi_r, | ||||
|    input logic                             lsu_commit_r, | ||||
|    input logic                             lsu_commit_r,            // lsu instruction in r commits
 | ||||
|    input logic                             ldst_dual_m, ldst_dual_r,// load/store is unaligned at 32 bit boundary per pipe stage
 | ||||
| 
 | ||||
|    input logic [31:0]                      lsu_addr_d,              // starting byte address for loads
 | ||||
|    input logic [pt.DCCM_BITS-1:0]          lsu_addr_m,              // starting byte address for loads
 | ||||
|    input logic [31:0]                      lsu_addr_r,              // starting byte address for loads
 | ||||
|    // lsu address down the pipe
 | ||||
|    input logic [31:0]                      lsu_addr_d, | ||||
|    input logic [pt.DCCM_BITS-1:0]          lsu_addr_m, | ||||
|    input logic [31:0]                      lsu_addr_r, | ||||
| 
 | ||||
|    // lsu address down the pipe - needed to check unaligned
 | ||||
|    input logic [pt.DCCM_BITS-1:0]          end_addr_d, | ||||
|    input logic [pt.DCCM_BITS-1:0]          end_addr_m, | ||||
|    input logic [pt.DCCM_BITS-1:0]          end_addr_r, | ||||
| 
 | ||||
| 
 | ||||
|    input logic                             stbuf_reqvld_any,          // write enable
 | ||||
|    input logic [pt.LSU_SB_BITS-1:0]        stbuf_addr_any,            // stbuf address (aligned)
 | ||||
|    input logic                             stbuf_reqvld_any,        // write enable
 | ||||
|    input logic [pt.LSU_SB_BITS-1:0]        stbuf_addr_any,          // stbuf address (aligned)
 | ||||
| 
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]    stbuf_data_any,          // the read out from stbuf
 | ||||
|    input logic [pt.DCCM_ECC_WIDTH-1:0]     stbuf_ecc_any,           // the encoded data with ECC bits
 | ||||
|  | @ -71,8 +75,8 @@ import el2_pkg::*; | |||
|    input logic [pt.DCCM_BYTE_WIDTH-1:0]    stbuf_fwdbyteen_hi_m,    // stbuf fowarding to load
 | ||||
|    input logic [pt.DCCM_BYTE_WIDTH-1:0]    stbuf_fwdbyteen_lo_m,    // stbuf fowarding to load
 | ||||
| 
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   dccm_rdata_hi_r,          // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   dccm_rdata_lo_r,          // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   dccm_rdata_hi_r,         // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   dccm_rdata_lo_r,         // data from the dccm
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]    dccm_data_ecc_hi_r,      // data from the dccm + ecc
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]    dccm_data_ecc_lo_r, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   lsu_ld_data_r,           // right justified, ie load byte will have data at 7:0
 | ||||
|  | @ -88,8 +92,8 @@ import el2_pkg::*; | |||
|    input logic [pt.DCCM_ECC_WIDTH-1:0]     sec_data_ecc_hi_r_ff,    // the encoded data with ECC bits
 | ||||
|    input logic [pt.DCCM_ECC_WIDTH-1:0]     sec_data_ecc_lo_r_ff,    // the encoded data with ECC bits
 | ||||
| 
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   dccm_rdata_hi_m,          // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   dccm_rdata_lo_m,          // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   dccm_rdata_hi_m,         // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   dccm_rdata_lo_m,         // data from the dccm
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]    dccm_data_ecc_hi_m,      // data from the dccm + ecc
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]    dccm_data_ecc_lo_m, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   lsu_ld_data_m,           // right justified, ie load byte will have data at 7:0
 | ||||
|  | @ -98,58 +102,58 @@ import el2_pkg::*; | |||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]    sec_data_hi_m,           // corrected dccm data
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]    sec_data_lo_m,           // corrected dccm data
 | ||||
| 
 | ||||
|    input logic [31:0]                      store_data_m, | ||||
|    input logic                             dma_dccm_wen, | ||||
|    input logic                             dma_pic_wen, | ||||
|    input logic [2:0]                       dma_mem_tag_m, | ||||
|    input logic [31:0]                      dma_mem_addr,       // DMA address
 | ||||
|    input logic [63:0]                      dma_mem_wdata,      // DMA write data
 | ||||
|    input logic [31:0]                      dma_dccm_wdata_lo, | ||||
|    input logic [31:0]                      dma_dccm_wdata_hi, | ||||
|    input logic [pt.DCCM_ECC_WIDTH-1:0]     dma_dccm_wdata_ecc_hi,         // ECC bits for the DMA wdata
 | ||||
|    input logic [pt.DCCM_ECC_WIDTH-1:0]     dma_dccm_wdata_ecc_lo,         // ECC bits for the DMA wdata
 | ||||
|    input logic [31:0]                      store_data_m,            // Store data M-stage
 | ||||
|    input logic                             dma_dccm_wen,            // Perform DMA writes only for word/dword
 | ||||
|    input logic                             dma_pic_wen,             // Perform PIC writes
 | ||||
|    input logic [2:0]                       dma_mem_tag_m,           // DMA Buffer entry number M-stage
 | ||||
|    input logic [31:0]                      dma_mem_addr,            // DMA request address
 | ||||
|    input logic [63:0]                      dma_mem_wdata,           // DMA write data
 | ||||
|    input logic [31:0]                      dma_dccm_wdata_lo,       // Shift the dma data to lower bits to make it consistent to lsu stores
 | ||||
|    input logic [31:0]                      dma_dccm_wdata_hi,       // Shift the dma data to lower bits to make it consistent to lsu stores
 | ||||
|    input logic [pt.DCCM_ECC_WIDTH-1:0]     dma_dccm_wdata_ecc_hi,   // ECC bits for the DMA wdata
 | ||||
|    input logic [pt.DCCM_ECC_WIDTH-1:0]     dma_dccm_wdata_ecc_lo,   // ECC bits for the DMA wdata
 | ||||
| 
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   store_data_hi_r, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   store_data_lo_r, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   store_datafn_hi_r,        // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   store_datafn_lo_r,        // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   store_datafn_hi_r,       // data from the dccm
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0]   store_datafn_lo_r,       // data from the dccm
 | ||||
|    output logic [31:0]                     store_data_r,            // raw store data to be sent to bus
 | ||||
|    output logic                            ld_single_ecc_error_r, | ||||
|    output logic                            ld_single_ecc_error_r_ff, | ||||
| 
 | ||||
|    output logic [31:0]                     picm_mask_data_m,        // pic data to stbuf
 | ||||
|    output logic                            lsu_stbuf_commit_any,      // stbuf wins the dccm port or is to pic
 | ||||
|    output logic                            lsu_stbuf_commit_any,    // stbuf wins the dccm port or is to pic
 | ||||
|    output logic                            lsu_dccm_rden_m,         // dccm read
 | ||||
|    output logic                            lsu_dccm_rden_r,         // 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 [2:0]                      dccm_dma_rtag,             // DMA return tag
 | ||||
|    output logic [63:0]                     dccm_dma_rdata,            // dccm data to dma request
 | ||||
|    output logic                            dccm_dma_rvalid,         // dccm serviving the dma load
 | ||||
|    output logic                            dccm_dma_ecc_error,      // DMA load had ecc error
 | ||||
|    output logic [2:0]                      dccm_dma_rtag,           // DMA return tag
 | ||||
|    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 [pt.DCCM_BITS-1:0]         dccm_wr_addr_lo,          // dccm interface -- wr addr for lo bank
 | ||||
|    output logic [pt.DCCM_BITS-1:0]         dccm_wr_addr_hi,          // dccm interface -- wr addr for hi bank
 | ||||
|    output logic [pt.DCCM_BITS-1:0]         dccm_rd_addr_lo,          // dccm interface -- read address for lo bank
 | ||||
|    output logic [pt.DCCM_BITS-1:0]         dccm_rd_addr_hi,          // dccm interface -- read address for hi bank
 | ||||
|    output logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_wr_data_lo,          // dccm write data for lo bank
 | ||||
|    output logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_wr_data_hi,          // dccm write data for hi bank
 | ||||
|    output logic                            dccm_wren,               // dccm interface -- write
 | ||||
|    output logic                            dccm_rden,               // dccm interface -- write
 | ||||
|    output logic [pt.DCCM_BITS-1:0]         dccm_wr_addr_lo,         // dccm interface -- wr addr for lo bank
 | ||||
|    output logic [pt.DCCM_BITS-1:0]         dccm_wr_addr_hi,         // dccm interface -- wr addr for hi bank
 | ||||
|    output logic [pt.DCCM_BITS-1:0]         dccm_rd_addr_lo,         // dccm interface -- read address for lo bank
 | ||||
|    output logic [pt.DCCM_BITS-1:0]         dccm_rd_addr_hi,         // dccm interface -- read address for hi bank
 | ||||
|    output logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_wr_data_lo,         // dccm write data for lo bank
 | ||||
|    output logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_wr_data_hi,         // dccm write data for hi bank
 | ||||
| 
 | ||||
|    input logic [pt.DCCM_FDATA_WIDTH-1:0]   dccm_rd_data_lo,          // dccm read data back from the dccm
 | ||||
|    input logic [pt.DCCM_FDATA_WIDTH-1:0]   dccm_rd_data_hi,          // dccm read data back from the dccm
 | ||||
|    input logic [pt.DCCM_FDATA_WIDTH-1:0]   dccm_rd_data_lo,         // dccm read data back from the dccm
 | ||||
|    input logic [pt.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_rdaddr,        // address for pic read access
 | ||||
|    output logic [31:0]                     picm_wraddr,        // address for pic write access
 | ||||
|    output logic [31:0]                     picm_wr_data,       // write data
 | ||||
|    input logic [31:0]                      picm_rd_data,       // read data
 | ||||
|    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_rdaddr,             // address for pic read access
 | ||||
|    output logic [31:0]                     picm_wraddr,             // address for pic write access
 | ||||
|    output logic [31:0]                     picm_wr_data,            // write data
 | ||||
|    input logic [31:0]                      picm_rd_data,            // read data
 | ||||
| 
 | ||||
|    input logic                             scan_mode           // scan mode
 | ||||
|    input logic                             scan_mode                // scan mode
 | ||||
| ); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -183,11 +187,12 @@ import el2_pkg::*; | |||
|       logic [63:0]  picm_rd_data_r; | ||||
|       logic [63:32] lsu_ld_data_r_nc, lsu_ld_data_corr_r_nc; | ||||
|       logic [2:0]   dma_mem_tag_r; | ||||
|       logic         stbuf_fwddata_en; | ||||
| 
 | ||||
|       assign dccm_dma_rvalid      = lsu_pkt_r.valid & lsu_pkt_r.load & lsu_pkt_r.dma; | ||||
|       assign dccm_dma_ecc_error   = lsu_double_ecc_error_r; | ||||
|       assign dccm_dma_rtag[2:0]   = dma_mem_tag_r[2:0]; | ||||
|       assign dccm_dma_rdata[63:0] = lsu_rdata_corr_r; | ||||
|       assign dccm_dma_rdata[63:0] = ldst_dual_r ? lsu_rdata_corr_r[63:0] : {2{lsu_rdata_corr_r[31:0]}}; | ||||
|       assign {lsu_ld_data_r_nc[63:32], lsu_ld_data_r[31:0]}           = lsu_rdata_r[63:0] >> 8*lsu_addr_r[1:0]; | ||||
|       assign {lsu_ld_data_corr_r_nc[63:32], lsu_ld_data_corr_r[31:0]} = lsu_rdata_corr_r[63:0] >> 8*lsu_addr_r[1:0]; | ||||
| 
 | ||||
|  | @ -196,22 +201,23 @@ import el2_pkg::*; | |||
|       assign dccm_rdata_corr_r[63:0] = {sec_data_hi_r[31:0],sec_data_lo_r[31:0]}; | ||||
|       assign stbuf_fwddata_r[63:0]   = {stbuf_fwddata_hi_r[31:0], stbuf_fwddata_lo_r[31:0]}; | ||||
|       assign stbuf_fwdbyteen_r[7:0]  = {stbuf_fwdbyteen_hi_r[3:0], stbuf_fwdbyteen_lo_r[3:0]}; | ||||
|       assign stbuf_fwddata_en        = (|stbuf_fwdbyteen_hi_m[3:0]) | (|stbuf_fwdbyteen_lo_m[3:0]) | clk_override; | ||||
| 
 | ||||
|       for (genvar i=0; i<8; i++) begin: GenDMAData | ||||
|          assign lsu_rdata_corr_r[(8*i)+7:8*i]  = stbuf_fwdbyteen_r[i] ? stbuf_fwddata_r[(8*i)+7:8*i] : | ||||
|                                                                         (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] :  dccm_rdata_corr_r[(8*i)+7:8*i]); | ||||
|                                                                         (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] :  ({8{addr_in_dccm_r}} & dccm_rdata_corr_r[(8*i)+7:8*i])); | ||||
| 
 | ||||
|          assign lsu_rdata_r[(8*i)+7:8*i]       = stbuf_fwdbyteen_r[i] ? stbuf_fwddata_r[(8*i)+7:8*i] : | ||||
|                                                                         (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] :  dccm_rdata_r[(8*i)+7:8*i]); | ||||
|                                                                         (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] :  ({8{addr_in_dccm_r}} & dccm_rdata_r[(8*i)+7:8*i])); | ||||
|       end | ||||
|       rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_hi_r_ff    (.*, .din(dccm_rdata_hi_m[pt.DCCM_DATA_WIDTH-1:0]),                   .dout(dccm_rdata_hi_r[pt.DCCM_DATA_WIDTH-1:0]),                .en(lsu_dccm_rden_m)); | ||||
|       rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_lo_r_ff    (.*, .din(dccm_rdata_lo_m[pt.DCCM_DATA_WIDTH-1:0]),                   .dout(dccm_rdata_lo_r[pt.DCCM_DATA_WIDTH-1:0]),                .en(lsu_dccm_rden_m)); | ||||
|       rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_hi_r_ff    (.*, .din(dccm_rdata_hi_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(dccm_rdata_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en((lsu_dccm_rden_m & ldst_dual_m) | clk_override)); | ||||
|       rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_lo_r_ff    (.*, .din(dccm_rdata_lo_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(dccm_rdata_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_dccm_rden_m | clk_override)); | ||||
|       rvdffe #(2*pt.DCCM_ECC_WIDTH)  dccm_data_ecc_r_ff  (.*, .din({dccm_data_ecc_hi_m[pt.DCCM_ECC_WIDTH-1:0], dccm_data_ecc_lo_m[pt.DCCM_ECC_WIDTH-1:0]}), | ||||
|                                                               .dout({dccm_data_ecc_hi_r[pt.DCCM_ECC_WIDTH-1:0], dccm_data_ecc_lo_r[pt.DCCM_ECC_WIDTH-1:0]}),                                  .en(lsu_dccm_rden_m)); | ||||
|       rvdff #(8)                   stbuf_fwdbyteen_ff    (.*, .din({stbuf_fwdbyteen_hi_m[3:0], stbuf_fwdbyteen_lo_m[3:0]}),    .dout({stbuf_fwdbyteen_hi_r[3:0], stbuf_fwdbyteen_lo_r[3:0]}), .clk(lsu_c2_r_clk)); | ||||
|       rvdff #(64)                  stbuf_fwddata_ff      (.*, .din({stbuf_fwddata_hi_m[31:0], stbuf_fwddata_lo_m[31:0]}),      .dout({stbuf_fwddata_hi_r[31:0], stbuf_fwddata_lo_r[31:0]}),   .clk(lsu_c2_r_clk)); | ||||
|       rvdff #(32)                  picm_rddata_rff       (.*, .din(picm_rd_data_m[31:0]),                                      .dout(picm_rd_data_r[31:0]),                                   .clk(lsu_c2_r_clk)); | ||||
|       rvdff #(3)                   dma_mem_tag_rff       (.*, .din(dma_mem_tag_m[2:0]),                                        .dout(dma_mem_tag_r[2:0]),                                     .clk(lsu_c1_r_clk)); | ||||
|                                                               .dout({dccm_data_ecc_hi_r[pt.DCCM_ECC_WIDTH-1:0], dccm_data_ecc_lo_r[pt.DCCM_ECC_WIDTH-1:0]}),                                  .en(lsu_dccm_rden_m | clk_override)); | ||||
|       rvdff #(8)                   stbuf_fwdbyteen_ff    (.*, .din({stbuf_fwdbyteen_hi_m[3:0], stbuf_fwdbyteen_lo_m[3:0]}), .dout({stbuf_fwdbyteen_hi_r[3:0], stbuf_fwdbyteen_lo_r[3:0]}), .clk(lsu_c2_r_clk)); | ||||
|       rvdffe #(64)                 stbuf_fwddata_ff      (.*, .din({stbuf_fwddata_hi_m[31:0], stbuf_fwddata_lo_m[31:0]}),   .dout({stbuf_fwddata_hi_r[31:0], stbuf_fwddata_lo_r[31:0]}),   .en(stbuf_fwddata_en)); | ||||
|       rvdffe #(32)                 picm_rddata_rff       (.*, .din(picm_rd_data_m[31:0]),                                   .dout(picm_rd_data_r[31:0]),                                   .en(addr_in_pic_m | clk_override)); | ||||
|       rvdff #(3)                   dma_mem_tag_rff       (.*, .din(dma_mem_tag_m[2:0]),                                     .dout(dma_mem_tag_r[2:0]),                                     .clk(lsu_c1_r_clk)); | ||||
| 
 | ||||
|    end else begin: L2U_Plus1_0 | ||||
| 
 | ||||
|  | @ -225,7 +231,7 @@ import el2_pkg::*; | |||
|       assign dccm_dma_rvalid      = lsu_pkt_m.valid & lsu_pkt_m.load & lsu_pkt_m.dma; | ||||
|       assign dccm_dma_ecc_error   = lsu_double_ecc_error_m; | ||||
|       assign dccm_dma_rtag[2:0]   = dma_mem_tag_m[2:0]; | ||||
|       assign dccm_dma_rdata[63:0] = lsu_rdata_corr_m; | ||||
|       assign dccm_dma_rdata[63:0] = ldst_dual_m ? lsu_rdata_corr_m[63:0] : {2{lsu_rdata_corr_m[31:0]}}; | ||||
|       assign {lsu_ld_data_m_nc[63:32], lsu_ld_data_m[31:0]} = lsu_rdata_m[63:0] >> 8*lsu_addr_m[1:0]; | ||||
|       assign {lsu_ld_data_corr_m_nc[63:32], lsu_ld_data_corr_m[31:0]} = lsu_rdata_corr_m[63:0] >> 8*lsu_addr_m[1:0]; | ||||
| 
 | ||||
|  | @ -236,13 +242,13 @@ import el2_pkg::*; | |||
| 
 | ||||
|       for (genvar i=0; i<8; i++) begin: GenLoop | ||||
|          assign lsu_rdata_corr_m[(8*i)+7:8*i] = stbuf_fwdbyteen_m[i] ? stbuf_fwddata_m[(8*i)+7:8*i] : | ||||
|                                                                        (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : dccm_rdata_corr_m[(8*i)+7:8*i]); | ||||
|                                                                        (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : ({8{addr_in_dccm_m}} & dccm_rdata_corr_m[(8*i)+7:8*i])); | ||||
| 
 | ||||
|          assign lsu_rdata_m[(8*i)+7:8*i]      = stbuf_fwdbyteen_m[i] ? stbuf_fwddata_m[(8*i)+7:8*i] : | ||||
|                                                                        (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : dccm_rdata_m[(8*i)+7:8*i]); | ||||
|                                                                        (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : ({8{addr_in_dccm_m}} & dccm_rdata_m[(8*i)+7:8*i])); | ||||
|       end | ||||
| 
 | ||||
|       rvdff #(32) lsu_ld_data_corr_rff(.*, .din(lsu_ld_data_corr_m[31:0]), .dout(lsu_ld_data_corr_r[31:0]), .clk(lsu_c2_r_clk)); | ||||
|       rvdffe #(32) lsu_ld_data_corr_rff(.*, .din(lsu_ld_data_corr_m[31:0]), .dout(lsu_ld_data_corr_r[31:0]), .en((lsu_pkt_m.valid & lsu_pkt_m.load & (addr_in_pic_m | addr_in_dccm_m)) | clk_override)); | ||||
|    end | ||||
| 
 | ||||
|    assign kill_ecc_corr_lo_r = (((lsu_addr_d[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2]) | (end_addr_d[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2])) & lsu_pkt_d.valid & lsu_pkt_d.store & lsu_pkt_d.dma & addr_in_dccm_d) | | ||||
|  | @ -289,7 +295,7 @@ import el2_pkg::*; | |||
|                                                                                                 {stbuf_ecc_any[pt.DCCM_ECC_WIDTH-1:0],stbuf_data_any[pt.DCCM_DATA_WIDTH-1:0]}); | ||||
| 
 | ||||
|    // DCCM outputs
 | ||||
|    assign store_byteen_m[3:0] = {4{lsu_pkt_m.store}}  & | ||||
|    assign store_byteen_m[3:0] = {4{lsu_pkt_m.store}} & | ||||
|                                 (({4{lsu_pkt_m.by}}    & 4'b0001) | | ||||
|                                  ({4{lsu_pkt_m.half}}  & 4'b0011) | | ||||
|                                  ({4{lsu_pkt_m.word}}  & 4'b1111)); | ||||
|  | @ -330,7 +336,7 @@ import el2_pkg::*; | |||
|       end | ||||
| 
 | ||||
|       rvdff #(1)   dccm_wren_ff       (.*, .din(lsu_stbuf_commit_any),  .dout(dccm_wren_Q),             .clk(lsu_free_c2_clk));   // ECC load errors writing to dccm shouldn't fwd to stores in pipe
 | ||||
|       rvdffe #(32) dccm_wrdata_ff     (.*, .din(stbuf_data_any[31:0]),  .dout(dccm_wr_data_Q[31:0]),    .en(lsu_stbuf_commit_any), .clk(clk)); | ||||
|       rvdffe #(32) dccm_wrdata_ff     (.*, .din(stbuf_data_any[31:0]),  .dout(dccm_wr_data_Q[31:0]),    .en(lsu_stbuf_commit_any | clk_override), .clk(clk)); | ||||
|       rvdff #(1)   dccm_wrbyp_dm_loff (.*, .din(dccm_wr_bypass_d_m_lo), .dout(dccm_wr_bypass_d_m_lo_Q), .clk(lsu_free_c2_clk)); | ||||
|       rvdff #(1)   dccm_wrbyp_dm_hiff (.*, .din(dccm_wr_bypass_d_m_hi), .dout(dccm_wr_bypass_d_m_hi_Q), .clk(lsu_free_c2_clk)); | ||||
|       rvdff #(32)  store_data_rff     (.*, .din(store_data_m[31:0]),    .dout(store_data_r[31:0]),      .clk(lsu_store_c1_r_clk)); | ||||
|  | @ -356,8 +362,8 @@ import el2_pkg::*; | |||
|       end | ||||
|       assign store_data_r[31:0]      = 32'({store_data_hi_r[31:0],store_data_lo_r[31:0]} >> 8*lsu_addr_r[1:0]) & store_data_mask[31:0]; | ||||
| 
 | ||||
|       rvdff #(pt.DCCM_DATA_WIDTH) store_data_hi_rff (.*, .din(store_data_hi_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]),    .clk(lsu_store_c1_r_clk)); | ||||
|       rvdff #(pt.DCCM_DATA_WIDTH) store_data_lo_rff (.*, .din(store_data_lo_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]),    .clk(lsu_store_c1_r_clk)); | ||||
|       rvdffe #(pt.DCCM_DATA_WIDTH) store_data_hi_rff (.*, .din(store_data_hi_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en((ldst_dual_m & lsu_pkt_m.valid & lsu_pkt_m.store) | clk_override), .clk(clk)); | ||||
|       rvdff  #(pt.DCCM_DATA_WIDTH) store_data_lo_rff (.*, .din(store_data_lo_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .clk(lsu_store_c1_r_clk)); | ||||
| 
 | ||||
|    end | ||||
| 
 | ||||
|  | @ -383,23 +389,28 @@ import el2_pkg::*; | |||
|    if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable | ||||
|       rvdff #(1) dccm_rden_mff (.*, .din(lsu_dccm_rden_d), .dout(lsu_dccm_rden_m), .clk(lsu_c2_m_clk)); | ||||
|       rvdff #(1) dccm_rden_rff (.*, .din(lsu_dccm_rden_m), .dout(lsu_dccm_rden_r), .clk(lsu_c2_r_clk)); | ||||
| 
 | ||||
|       // ECC correction flops since dccm write happens next cycle
 | ||||
|       // We are writing to dccm in r+1 for ecc correction since fast_int needs to be blocked in decode - 1. We can probably write in r for plus0 configuration since we know ecc error in M.
 | ||||
|       // In that case these (_ff) flops are needed only in plus1 configuration
 | ||||
|       rvdff #(1) ld_double_ecc_error_rff    (.*, .din(lsu_double_ecc_error_r),   .dout(lsu_double_ecc_error_r_ff),   .clk(lsu_free_c2_clk)); | ||||
|       rvdff #(1) ld_single_ecc_error_hi_rff (.*, .din(ld_single_ecc_error_hi_r_ns), .dout(ld_single_ecc_error_hi_r_ff), .clk(lsu_free_c2_clk)); | ||||
|       rvdff #(1) ld_single_ecc_error_lo_rff (.*, .din(ld_single_ecc_error_lo_r_ns), .dout(ld_single_ecc_error_lo_r_ff), .clk(lsu_free_c2_clk)); | ||||
|       rvdffe #(pt.DCCM_BITS) ld_sec_addr_hi_rff (.*, .din(end_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk)); | ||||
|       rvdffe #(pt.DCCM_BITS) ld_sec_addr_lo_rff (.*, .din(lsu_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk)); | ||||
| 
 | ||||
|    end else begin: Gen_dccm_disable | ||||
|       assign lsu_dccm_rden_m = '0; | ||||
|       assign lsu_dccm_rden_r = '0; | ||||
| 
 | ||||
|       assign lsu_double_ecc_error_r_ff = 1'b0; | ||||
|       assign ld_single_ecc_error_hi_r_ff = 1'b0; | ||||
|       assign ld_single_ecc_error_lo_r_ff = 1'b0; | ||||
|       assign ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0] = '0; | ||||
|       assign ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0] = '0; | ||||
|    end | ||||
| 
 | ||||
|    // ECC correction flops since dccm write happens next cycle
 | ||||
|    // We are writing to dccm in r+1 for ecc correction since fast_int needs to be blocked in decode - 1. We can probably write in r for plus0 configuration since we know ecc error in M.
 | ||||
|    // In that case these (_ff) flops are needed only in plus1 configuration
 | ||||
|    rvdff #(1) ld_double_ecc_error_rff    (.*, .din(lsu_double_ecc_error_r),   .dout(lsu_double_ecc_error_r_ff),   .clk(lsu_free_c2_clk)); | ||||
|    rvdff #(1) ld_single_ecc_error_hi_rff (.*, .din(ld_single_ecc_error_hi_r_ns), .dout(ld_single_ecc_error_hi_r_ff), .clk(lsu_free_c2_clk)); | ||||
|    rvdff #(1) ld_single_ecc_error_lo_rff (.*, .din(ld_single_ecc_error_lo_r_ns), .dout(ld_single_ecc_error_lo_r_ff), .clk(lsu_free_c2_clk)); | ||||
|    rvdffe #(pt.DCCM_BITS) ld_sec_addr_hi_rff (.*, .din(end_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r), .clk(clk)); | ||||
|    rvdffe #(pt.DCCM_BITS) ld_sec_addr_lo_rff (.*, .din(lsu_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r), .clk(clk)); | ||||
| 
 | ||||
| `ifdef LSU_ASSERT_ON | ||||
|    assert_ecc_kill_lo: assert #0 (~(ld_single_ecc_error_lo_r & kill_ecc_corr_lo_r)); | ||||
|    assert_ecc_kill_hi: assert #0 (~(ld_single_ecc_error_hi_r & kill_ecc_corr_hi_r)); | ||||
| `ifdef RV_ASSERT_ON | ||||
| 
 | ||||
|    // Load single ECC error correction implies commit/dma
 | ||||
|    property ld_single_ecc_error_commit; | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -27,14 +27,27 @@ | |||
| // //********************************************************************************
 | ||||
| 
 | ||||
| 
 | ||||
| `define EL2_LOCAL_DCCM_RAM_TEST_PORTS    .TEST1(dccm_ext_in_pkt[i].TEST1),                      \ | ||||
|                                      .RME(dccm_ext_in_pkt[i].RME),                      \ | ||||
|                                      .RM(dccm_ext_in_pkt[i].RM),                        \ | ||||
|                                      .LS(dccm_ext_in_pkt[i].LS),                        \ | ||||
|                                      .DS(dccm_ext_in_pkt[i].DS),                        \ | ||||
|                                      .SD(dccm_ext_in_pkt[i].SD),                        \ | ||||
|                                      .TEST_RNM(dccm_ext_in_pkt[i].TEST_RNM),            \ | ||||
|                                      .BC1(dccm_ext_in_pkt[i].BC1),                      \ | ||||
|                                      .BC2(dccm_ext_in_pkt[i].BC2),                      \ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| module el2_lsu_dccm_mem | ||||
| import el2_pkg::*; | ||||
| #( | ||||
| `include "el2_param.vh" | ||||
|  )( | ||||
|    input logic         clk,                                             // clock
 | ||||
|    input logic         rst_l, | ||||
|    input logic         clk_override,                                    // clock override
 | ||||
|    input logic         clk,                                             // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic         active_clk,                                      // Clock only while core active.  Through two clock headers. For flops without second clock header built in.
 | ||||
|    input logic         rst_l,                                           // reset, active low
 | ||||
|    input logic         clk_override,                                    // Override non-functional clock gating
 | ||||
| 
 | ||||
|    input logic         dccm_wren,                                       // write enable
 | ||||
|    input logic         dccm_rden,                                       // read enable
 | ||||
|  | @ -44,6 +57,7 @@ import el2_pkg::*; | |||
|    input logic [pt.DCCM_BITS-1:0]  dccm_rd_addr_hi,                     // read address for the upper bank in case of a misaligned access
 | ||||
|    input logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_wr_data_lo,              // write data
 | ||||
|    input logic [pt.DCCM_FDATA_WIDTH-1:0]  dccm_wr_data_hi,              // write data
 | ||||
|    input el2_dccm_ext_in_pkt_t  [pt.DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt,    // the dccm packet from the soc
 | ||||
| 
 | ||||
|    output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo,              // read data from the lo bank
 | ||||
|    output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi,              // read data from the hi bank
 | ||||
|  | @ -78,10 +92,9 @@ import el2_pkg::*; | |||
|    assign dccm_rd_data_lo[pt.DCCM_FDATA_WIDTH-1:0]  = dccm_bank_dout[dccm_rd_addr_lo_q[pt.DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]][pt.DCCM_FDATA_WIDTH-1:0]; | ||||
|    assign dccm_rd_data_hi[pt.DCCM_FDATA_WIDTH-1:0]  = dccm_bank_dout[dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]][pt.DCCM_FDATA_WIDTH-1:0]; | ||||
| 
 | ||||
|    // Generate even/odd address
 | ||||
| 
 | ||||
|    // 8 Banks, 16KB each (2048 x 72)
 | ||||
|    for (genvar i=0; i<32'(pt.DCCM_NUM_BANKS); i++) begin: mem_bank | ||||
|    for (genvar i=0; i<pt.DCCM_NUM_BANKS; i++) begin: mem_bank | ||||
|       assign  wren_bank[i]        = dccm_wren & ((dccm_wr_addr_hi[2+:pt.DCCM_BANK_BITS] == i) | (dccm_wr_addr_lo[2+:pt.DCCM_BANK_BITS] == i)); | ||||
|       assign  rden_bank[i]        = dccm_rden & ((dccm_rd_addr_hi[2+:pt.DCCM_BANK_BITS] == i) | (dccm_rd_addr_lo[2+:pt.DCCM_BANK_BITS] == i)); | ||||
|       assign  addr_bank[i][(pt.DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? (((dccm_wr_addr_hi[2+:pt.DCCM_BANK_BITS] == i) & wr_unaligned) ? | ||||
|  | @ -98,7 +111,8 @@ import el2_pkg::*; | |||
|       // end clock gating section
 | ||||
| 
 | ||||
| `ifdef VERILATOR | ||||
|          el2_ram #(DCCM_INDEX_DEPTH,39)  ram ( | ||||
| 
 | ||||
|         el2_ram #(DCCM_INDEX_DEPTH,39)  ram ( | ||||
|                                   // Primary ports
 | ||||
|                                   .ME(dccm_clken[i]), | ||||
|                                   .CLK(clk), | ||||
|  | @ -106,10 +120,13 @@ import el2_pkg::*; | |||
|                                   .ADR(addr_bank[i]), | ||||
|                                   .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                   .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                   .ROP ( ), | ||||
|                                   // These are used by SoC
 | ||||
|                                   `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                   .* | ||||
|                                   ); | ||||
| 
 | ||||
| `else | ||||
| 
 | ||||
|       if (DCCM_INDEX_DEPTH == 32768) begin : dccm | ||||
|          ram_32768x39  dccm_bank ( | ||||
|                                   // Primary ports
 | ||||
|  | @ -119,6 +136,9 @@ import el2_pkg::*; | |||
|                                   .ADR(addr_bank[i]), | ||||
|                                   .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                   .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                   .ROP ( ), | ||||
|                                   // These are used by SoC
 | ||||
|                                   `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                   .* | ||||
|                                   ); | ||||
|       end | ||||
|  | @ -131,6 +151,9 @@ import el2_pkg::*; | |||
|                                   .ADR(addr_bank[i]), | ||||
|                                   .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                   .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                   .ROP ( ), | ||||
|                                   // These are used by SoC
 | ||||
|                                   `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                   .* | ||||
|                                   ); | ||||
|       end | ||||
|  | @ -143,6 +166,9 @@ import el2_pkg::*; | |||
|                                  .ADR(addr_bank[i]), | ||||
|                                  .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .ROP ( ), | ||||
|                                  // These are used by SoC
 | ||||
|                                  `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                  .* | ||||
|                                  ); | ||||
|       end | ||||
|  | @ -155,6 +181,9 @@ import el2_pkg::*; | |||
|                                  .ADR(addr_bank[i]), | ||||
|                                  .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .ROP ( ), | ||||
|                                  // These are used by SoC
 | ||||
|                                  `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                  .* | ||||
|                                  ); | ||||
|       end | ||||
|  | @ -167,6 +196,9 @@ import el2_pkg::*; | |||
|                                  .ADR(addr_bank[i]), | ||||
|                                  .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .ROP ( ), | ||||
|                                  // These are used by SoC
 | ||||
|                                  `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                  .* | ||||
|                                  ); | ||||
|       end | ||||
|  | @ -179,6 +211,9 @@ import el2_pkg::*; | |||
|                                  .ADR(addr_bank[i]), | ||||
|                                  .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .ROP ( ), | ||||
|                                  // These are used by SoC
 | ||||
|                                  `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                  .* | ||||
|                                  ); | ||||
|       end | ||||
|  | @ -191,6 +226,9 @@ import el2_pkg::*; | |||
|                                  .ADR(addr_bank[i]), | ||||
|                                  .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                  .ROP ( ), | ||||
|                                  // These are used by SoC
 | ||||
|                                  `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                  .* | ||||
|                                  ); | ||||
|       end | ||||
|  | @ -203,6 +241,9 @@ import el2_pkg::*; | |||
|                                 .ADR(addr_bank[i]), | ||||
|                                 .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                 .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                 .ROP ( ), | ||||
|                                 // These are used by SoC
 | ||||
|                                 `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                 .* | ||||
|                                 ); | ||||
|       end | ||||
|  | @ -215,15 +256,34 @@ import el2_pkg::*; | |||
|                                 .ADR(addr_bank[i]), | ||||
|                                 .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                 .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                 .ROP ( ), | ||||
|                                 // These are used by SoC
 | ||||
|                                 `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                 .* | ||||
|                                 ); | ||||
|       end | ||||
| `endif // VERILATOR
 | ||||
|       else if (DCCM_INDEX_DEPTH == 128) begin : dccm | ||||
|          ram_128x39  dccm_bank ( | ||||
|                                 // Primary ports
 | ||||
|                                 .ME(dccm_clken[i]), | ||||
|                                 .CLK(clk), | ||||
|                                 .WE(wren_bank[i]), | ||||
|                                 .ADR(addr_bank[i]), | ||||
|                                 .D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                 .Q(dccm_bank_dout[i][pt.DCCM_FDATA_WIDTH-1:0]), | ||||
|                                 .ROP ( ), | ||||
|                                 // These are used by SoC
 | ||||
|                                 `EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
|                                 .* | ||||
|                                 ); | ||||
|       end | ||||
| `endif | ||||
| 
 | ||||
|    end : mem_bank | ||||
| 
 | ||||
|    // Flops
 | ||||
|    rvdffs  #(pt.DCCM_BANK_BITS) rd_addr_lo_ff (.*, .din(dccm_rd_addr_lo[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .dout(dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .en(1'b1)); | ||||
|    rvdffs  #(pt.DCCM_BANK_BITS) rd_addr_hi_ff (.*, .din(dccm_rd_addr_hi[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .dout(dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .en(1'b1)); | ||||
|    rvdff  #(pt.DCCM_BANK_BITS) rd_addr_lo_ff (.*, .din(dccm_rd_addr_lo[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .dout(dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .clk(active_clk)); | ||||
|    rvdff  #(pt.DCCM_BANK_BITS) rd_addr_hi_ff (.*, .din(dccm_rd_addr_hi[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .dout(dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]), .clk(active_clk)); | ||||
| 
 | ||||
| `undef EL2_LOCAL_DCCM_RAM_TEST_PORTS | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -31,10 +31,11 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
| ( | ||||
|    input logic                           clk, | ||||
|    input logic                           lsu_c2_r_clk,     // clocks
 | ||||
|    input logic                           rst_l, | ||||
|    input logic                           scan_mode,           // scan
 | ||||
|    input logic                           clk,                // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
|    input logic                           lsu_c2_r_clk,       // clock
 | ||||
|    input logic                           clk_override,       // Override non-functional clock gating
 | ||||
|    input logic                           rst_l,              // reset, active low
 | ||||
|    input logic                           scan_mode,          // scan mode
 | ||||
| 
 | ||||
|    input el2_lsu_pkt_t                  lsu_pkt_m,          // packet in m
 | ||||
|    input el2_lsu_pkt_t                  lsu_pkt_r,          // packet in r
 | ||||
|  | @ -49,11 +50,11 @@ import el2_pkg::*; | |||
|    input logic  [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_r,          // data from the dccm
 | ||||
|    input logic  [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_r,          // data from the dccm
 | ||||
|    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_hi_r,       // data from the dccm + ecc
 | ||||
|    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_lo_r, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_r, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_r, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_r_ff, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_r_ff, | ||||
|    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_lo_r,       // data from the dccm + ecc
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_r,            // corrected dccm data R-stage
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_r,            // corrected dccm data R-stage
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_r_ff,         // corrected dccm data R+1 stage
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_r_ff,         // corrected dccm data R+1 stage
 | ||||
| 
 | ||||
|    input logic                           ld_single_ecc_error_r,     // ld has a single ecc error
 | ||||
|    input logic                           ld_single_ecc_error_r_ff,  // ld has a single ecc error
 | ||||
|  | @ -65,18 +66,18 @@ import el2_pkg::*; | |||
|    input logic  [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_m,           // raw data from mem
 | ||||
|    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_hi_m,        // ecc read out from mem
 | ||||
|    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_lo_m,        // ecc read out from mem
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_m, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_m, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_m,             // corrected dccm data M-stage
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_m,             // corrected dccm data M-stage
 | ||||
| 
 | ||||
|    input logic                           dma_dccm_wen, | ||||
|    input logic  [31:0]                   dma_dccm_wdata_lo, | ||||
|    input logic  [31:0]                   dma_dccm_wdata_hi, | ||||
|    input logic                           dma_dccm_wen,              // Perform DMA writes only for word/dword
 | ||||
|    input logic  [31:0]                   dma_dccm_wdata_lo,         // Shifted dma data to lower bits to make it consistent to lsu stores
 | ||||
|    input logic  [31:0]                   dma_dccm_wdata_hi,         // Shifted dma data to lower bits to make it consistent to lsu stores
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]  dma_dccm_wdata_ecc_hi,     // ECC bits for the DMA wdata
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]  dma_dccm_wdata_ecc_lo,     // ECC bits for the DMA wdata
 | ||||
| 
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]  stbuf_ecc_any, | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]  sec_data_ecc_hi_r_ff, | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]  sec_data_ecc_lo_r_ff, | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]  stbuf_ecc_any,             // Encoded data with ECC bits
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]  sec_data_ecc_hi_r_ff,      // Encoded data with ECC bits
 | ||||
|    output logic [pt.DCCM_ECC_WIDTH-1:0]  sec_data_ecc_lo_r_ff,      // Encoded data with ECC bits
 | ||||
| 
 | ||||
|    output logic                          single_ecc_error_hi_r,                   // sec detected
 | ||||
|    output logic                          single_ecc_error_lo_r,                   // sec detected on lower dccm bank
 | ||||
|  | @ -107,13 +108,12 @@ import el2_pkg::*; | |||
|    if (pt.LOAD_TO_USE_PLUS1 == 1) begin: L2U_Plus1_1 | ||||
|       logic        ldst_dual_m, ldst_dual_r; | ||||
|       logic        is_ldst_m; | ||||
|       logic        is_ldst_hi_m, is_ldst_lo_m; | ||||
|       logic        is_ldst_hi_r, is_ldst_lo_r; | ||||
| 
 | ||||
|       assign ldst_dual_r                                 = (lsu_addr_r[2] != end_addr_r[2]); | ||||
|       assign is_ldst_r                                   = lsu_pkt_r.valid & (lsu_pkt_r.load | lsu_pkt_r.store) & addr_in_dccm_r & lsu_dccm_rden_r; | ||||
|       assign is_ldst_lo_r                                = is_ldst_r & ~dec_tlu_core_ecc_disable; | ||||
|       assign is_ldst_hi_r                                = is_ldst_r & (ldst_dual_r | lsu_pkt_r.dma) & ~dec_tlu_core_ecc_disable;   // Always check the ECC Hi/Lo for DMA since we don't align for DMA
 | ||||
|       assign is_ldst_hi_r                                = is_ldst_r & ldst_dual_r & ~dec_tlu_core_ecc_disable;   // Always check the ECC Hi/Lo for DMA since we don't align for DMA
 | ||||
| 
 | ||||
|       assign is_ldst_hi_any                              = is_ldst_hi_r; | ||||
|       assign dccm_rdata_hi_any[pt.DCCM_DATA_WIDTH-1:0]   = dccm_rdata_hi_r[pt.DCCM_DATA_WIDTH-1:0]; | ||||
|  | @ -159,18 +159,18 @@ import el2_pkg::*; | |||
|       assign lsu_double_ecc_error_m                      = double_ecc_error_hi_m   | double_ecc_error_lo_m; | ||||
| 
 | ||||
|       // Flops
 | ||||
|       rvdff #(1) lsu_single_ecc_err_r    (.din(lsu_single_ecc_error_m), .dout(lsu_single_ecc_error_r), .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff #(1) lsu_double_ecc_err_r    (.din(lsu_double_ecc_error_m), .dout(lsu_double_ecc_error_r), .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff #(.WIDTH(1)) ldst_sec_lo_rff (.din(single_ecc_error_lo_any),  .dout(single_ecc_error_lo_r),  .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff #(.WIDTH(1)) ldst_sec_hi_rff (.din(single_ecc_error_hi_any),  .dout(single_ecc_error_hi_r),  .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_hi_rff (.din(sec_data_hi_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_lo_rff (.din(sec_data_lo_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff  #(1) lsu_single_ecc_err_r    (.din(lsu_single_ecc_error_m), .dout(lsu_single_ecc_error_r), .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff  #(1) lsu_double_ecc_err_r    (.din(lsu_double_ecc_error_m), .dout(lsu_double_ecc_error_r), .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff  #(.WIDTH(1)) ldst_sec_lo_rff (.din(single_ecc_error_lo_any),  .dout(single_ecc_error_lo_r),  .clk(lsu_c2_r_clk), .*); | ||||
|       rvdff  #(.WIDTH(1)) ldst_sec_hi_rff (.din(single_ecc_error_hi_any),  .dout(single_ecc_error_hi_r),  .clk(lsu_c2_r_clk), .*); | ||||
|       rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_hi_rff (.din(sec_data_hi_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_single_ecc_error_m | clk_override), .*); | ||||
|       rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_lo_rff (.din(sec_data_lo_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_single_ecc_error_m | clk_override), .*); | ||||
| 
 | ||||
|    end | ||||
| 
 | ||||
|    // Logic for ECC generation during write
 | ||||
|    assign dccm_wdata_lo_any[pt.DCCM_DATA_WIDTH-1:0] = ld_single_ecc_error_r_ff ? sec_data_lo_r_ff[pt.DCCM_DATA_WIDTH-1:0] : (dma_dccm_wen ? dma_dccm_wdata_lo[pt.DCCM_DATA_WIDTH-1:0] : stbuf_data_any[pt.DCCM_DATA_WIDTH-1:0]); | ||||
|    assign dccm_wdata_hi_any[pt.DCCM_DATA_WIDTH-1:0] = ld_single_ecc_error_r_ff ? sec_data_hi_r_ff[pt.DCCM_DATA_WIDTH-1:0] : (dma_dccm_wen ? dma_dccm_wdata_hi[pt.DCCM_DATA_WIDTH-1:0] : stbuf_data_any[pt.DCCM_DATA_WIDTH-1:0]); | ||||
|    assign dccm_wdata_hi_any[pt.DCCM_DATA_WIDTH-1:0] = ld_single_ecc_error_r_ff ? sec_data_hi_r_ff[pt.DCCM_DATA_WIDTH-1:0] : (dma_dccm_wen ? dma_dccm_wdata_hi[pt.DCCM_DATA_WIDTH-1:0] : 32'h0); | ||||
| 
 | ||||
|    assign sec_data_ecc_hi_r_ff[pt.DCCM_ECC_WIDTH-1:0]  = dccm_wdata_ecc_hi_any[pt.DCCM_ECC_WIDTH-1:0]; | ||||
|    assign sec_data_ecc_lo_r_ff[pt.DCCM_ECC_WIDTH-1:0]  = dccm_wdata_ecc_lo_any[pt.DCCM_ECC_WIDTH-1:0]; | ||||
|  | @ -232,11 +232,10 @@ import el2_pkg::*; | |||
|       assign double_ecc_error_hi_any = '0; | ||||
|       assign single_ecc_error_lo_any = '0; | ||||
|       assign double_ecc_error_lo_any = '0; | ||||
| 
 | ||||
|       assign stbuf_ecc_any[pt.DCCM_ECC_WIDTH-1:0] = '0; | ||||
|    end | ||||
| 
 | ||||
|    rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_hi_rplus1ff (.din(sec_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_hi_r_ff[pt.DCCM_DATA_WIDTH-1:0]), .en(ld_single_ecc_error_r), .clk(clk), .*); | ||||
|    rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_lo_rplus1ff (.din(sec_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_lo_r_ff[pt.DCCM_DATA_WIDTH-1:0]), .en(ld_single_ecc_error_r), .clk(clk), .*); | ||||
|    rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_hi_rplus1ff (.din(sec_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_hi_r_ff[pt.DCCM_DATA_WIDTH-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk), .*); | ||||
|    rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_lo_rplus1ff (.din(sec_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_lo_r_ff[pt.DCCM_DATA_WIDTH-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk), .*); | ||||
| 
 | ||||
| 
 | ||||
| endmodule // el2_lsu_ecc
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -30,38 +30,43 @@ import el2_pkg::*; | |||
| #( | ||||
| `include "el2_param.vh" | ||||
|  )( | ||||
|    input logic               rst_l, | ||||
|    input logic                rst_l,                     // reset, active low
 | ||||
|    input logic                clk_override,              // Override non-functional clock gating
 | ||||
|    input logic                clk,                       // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
 | ||||
| 
 | ||||
|    // clocks per pipe
 | ||||
|    input logic               lsu_c1_m_clk, | ||||
|    input logic               lsu_c1_r_clk, | ||||
|    input logic               lsu_c2_m_clk, | ||||
|    input logic               lsu_c2_r_clk, | ||||
|    input logic               lsu_store_c1_m_clk, | ||||
|    input logic                lsu_c1_m_clk, | ||||
|    input logic                lsu_c1_r_clk, | ||||
|    input logic                lsu_c2_m_clk, | ||||
|    input logic                lsu_c2_r_clk, | ||||
|    input logic                lsu_store_c1_m_clk, | ||||
| 
 | ||||
|    input  logic [31:0]        lsu_ld_data_r, | ||||
|    input  logic [31:0]        lsu_ld_data_corr_r,        // ECC corrected data
 | ||||
|    input logic                lsu_single_ecc_error_r, | ||||
|    input logic                lsu_double_ecc_error_r, | ||||
|    input logic [31:0]         lsu_ld_data_r,             // Load data R-stage
 | ||||
|    input logic [31:0]         lsu_ld_data_corr_r,        // ECC corrected data R-stage
 | ||||
|    input logic                lsu_single_ecc_error_r,    // ECC single bit error R-stage
 | ||||
|    input logic                lsu_double_ecc_error_r,    // ECC double bit error R-stage
 | ||||
| 
 | ||||
|    input  logic [31:0]        lsu_ld_data_m, | ||||
|    input logic                lsu_single_ecc_error_m, | ||||
|    input logic                lsu_double_ecc_error_m, | ||||
|    input logic [31:0]         lsu_ld_data_m,             // Load data M-stage
 | ||||
|    input logic                lsu_single_ecc_error_m,    // ECC single bit error M-stage
 | ||||
|    input logic                lsu_double_ecc_error_m,    // ECC double bit error M-stage
 | ||||
| 
 | ||||
|    input logic                flush_m_up, | ||||
|    input logic                flush_r, | ||||
|    input logic                flush_m_up,                // Flush M and D stage
 | ||||
|    input logic                flush_r,                   // Flush R-stage
 | ||||
|    input logic                ldst_dual_d,               // load/store is unaligned at 32 bit boundary D-stage
 | ||||
|    input logic                ldst_dual_m,               // load/store is unaligned at 32 bit boundary M-stage
 | ||||
|    input logic                ldst_dual_r,               // load/store is unaligned at 32 bit boundary R-stage
 | ||||
| 
 | ||||
|    input logic [31:0]         exu_lsu_rs1_d,        // address
 | ||||
|    input logic [31:0]         exu_lsu_rs2_d,        // store data
 | ||||
|    input logic [31:0]         exu_lsu_rs1_d,             // address
 | ||||
|    input logic [31:0]         exu_lsu_rs2_d,             // store data
 | ||||
| 
 | ||||
|    input el2_lsu_pkt_t       lsu_p,                // lsu control packet
 | ||||
|    input logic                dec_lsu_valid_raw_d,  // Raw valid for address computation
 | ||||
|    input logic [11:0]         dec_lsu_offset_d, | ||||
|    input el2_lsu_pkt_t       lsu_p,                     // lsu control packet
 | ||||
|    input logic                dec_lsu_valid_raw_d,       // Raw valid for address computation
 | ||||
|    input logic [11:0]         dec_lsu_offset_d,          // 12b offset for load/store addresses
 | ||||
| 
 | ||||
|    input  logic [31:0]        picm_mask_data_m, | ||||
|    input  logic [31:0]        bus_read_data_m, | ||||
|    output logic [31:0]        lsu_result_m, | ||||
|    output logic [31:0]        lsu_result_corr_r,     // This is the ECC corrected data going to RF
 | ||||
|    input  logic [31:0]        picm_mask_data_m,          // PIC data M-stage
 | ||||
|    input  logic [31:0]        bus_read_data_m,           // the bus return data
 | ||||
|    output logic [31:0]        lsu_result_m,              // lsu load data
 | ||||
|    output logic [31:0]        lsu_result_corr_r,         // This is the ECC corrected data going to RF
 | ||||
|    // lsu address down the pipe
 | ||||
|    output logic [31:0]        lsu_addr_d, | ||||
|    output logic [31:0]        lsu_addr_m, | ||||
|  | @ -73,15 +78,15 @@ import el2_pkg::*; | |||
|    // store data down the pipe
 | ||||
|    output logic [31:0]        store_data_m, | ||||
| 
 | ||||
|    input  logic [31:0]         dec_tlu_mrac_ff, | ||||
|    output logic                lsu_exc_m, | ||||
|    output logic                is_sideeffects_m, | ||||
|    output logic                lsu_commit_r, | ||||
|    output logic                lsu_single_ecc_error_incr, | ||||
|    output el2_lsu_error_pkt_t lsu_error_pkt_r, | ||||
|    input  logic [31:0]         dec_tlu_mrac_ff,          // CSR for memory region control
 | ||||
|    output logic                lsu_exc_m,                // Access or misaligned fault
 | ||||
|    output logic                is_sideeffects_m,         // is sideffects space
 | ||||
|    output logic                lsu_commit_r,             // lsu instruction in r commits
 | ||||
|    output logic                lsu_single_ecc_error_incr,// LSU inc SB error counter
 | ||||
|    output el2_lsu_error_pkt_t lsu_error_pkt_r,          // lsu exception packet
 | ||||
| 
 | ||||
|    output logic [31:1]         lsu_fir_addr,        // fast interrupt address
 | ||||
|    output logic [1:0]          lsu_fir_error,       // Error during fast interrupt lookup
 | ||||
|    output logic [31:1]         lsu_fir_addr,             // fast interrupt address
 | ||||
|    output logic [1:0]          lsu_fir_error,            // Error during fast interrupt lookup
 | ||||
| 
 | ||||
|    // address in dccm/pic/external per pipe stage
 | ||||
|    output logic               addr_in_dccm_d, | ||||
|  | @ -106,10 +111,11 @@ import el2_pkg::*; | |||
|    output el2_lsu_pkt_t      lsu_pkt_m, | ||||
|    output el2_lsu_pkt_t      lsu_pkt_r, | ||||
| 
 | ||||
|    input  logic               scan_mode | ||||
|    input  logic               scan_mode                  // Scan mode
 | ||||
| 
 | ||||
|    ); | ||||
| 
 | ||||
|    logic [31:3]        end_addr_pre_m, end_addr_pre_r; | ||||
|    logic [31:0]        full_addr_d; | ||||
|    logic [31:0]        full_end_addr_d; | ||||
|    logic [31:0]        lsu_rs1_d; | ||||
|  | @ -147,7 +153,6 @@ import el2_pkg::*; | |||
|    assign rs1_d[31:0] = (lsu_pkt_d.load_ldst_bypass_d) ? lsu_result_m[31:0] : rs1_d_raw[31:0]; | ||||
| 
 | ||||
|    // generate the ls address
 | ||||
|    // need to refine this is memory is only 128KB
 | ||||
|    rvlsadder   lsadder  (.rs1(rs1_d[31:0]), | ||||
|                        .offset(offset_d[11:0]), | ||||
|                        .dout(full_addr_d[31:0]) | ||||
|  | @ -205,8 +210,10 @@ import el2_pkg::*; | |||
| 
 | ||||
|       assign lsu_fir_error_m[1:0] = fir_nondccm_access_error_m ? 2'b11 : (fir_dccm_access_error_m ? 2'b10 : ((lsu_pkt_m.fast_int & lsu_double_ecc_error_m) ? 2'b01 : 2'b00)); | ||||
| 
 | ||||
|       rvdff #($bits(el2_lsu_error_pkt_t)) lsu_error_pkt_rff(.*, .din(lsu_error_pkt_m),      .dout(lsu_error_pkt_r),    .clk(lsu_c2_r_clk)); | ||||
|       rvdff #(2)                           lsu_fir_error_rff(.*, .din(lsu_fir_error_m[1:0]), .dout(lsu_fir_error[1:0]), .clk(lsu_c2_r_clk)); | ||||
|       rvdff  #(1)                             lsu_exc_valid_rff       (.*, .din(lsu_error_pkt_m.exc_valid),                        .dout(lsu_error_pkt_r.exc_valid),                        .clk(lsu_c2_r_clk)); | ||||
|       rvdff  #(1)                             lsu_single_ecc_error_rff(.*, .din(lsu_error_pkt_m.single_ecc_error),                 .dout(lsu_error_pkt_r.single_ecc_error),                 .clk(lsu_c2_r_clk)); | ||||
|       rvdffe #($bits(el2_lsu_error_pkt_t)-2) lsu_error_pkt_rff       (.*, .din(lsu_error_pkt_m[$bits(el2_lsu_error_pkt_t)-1:2]), .dout(lsu_error_pkt_r[$bits(el2_lsu_error_pkt_t)-1:2]), .en(lsu_error_pkt_m.exc_valid | lsu_error_pkt_m.single_ecc_error | clk_override)); | ||||
|       rvdff #(2)                              lsu_fir_error_rff       (.*, .din(lsu_fir_error_m[1:0]),                             .dout(lsu_fir_error[1:0]),                               .clk(lsu_c2_r_clk)); | ||||
|    end | ||||
| 
 | ||||
|    //Create DMA packet
 | ||||
|  | @ -247,7 +254,7 @@ import el2_pkg::*; | |||
|       assign lsu_ld_datafn_r[31:0]  = addr_external_r ? bus_read_data_r[31:0] : lsu_ld_data_r[31:0]; | ||||
|       assign lsu_ld_datafn_corr_r[31:0]  = addr_external_r ? bus_read_data_r[31:0] : lsu_ld_data_corr_r[31:0]; | ||||
| 
 | ||||
|       // this is really R stage but don't want to make all the changes to support M,R buses
 | ||||
|       // this is really R stage signal
 | ||||
|       assign lsu_result_m[31:0] = ({32{ lsu_pkt_r.unsign & lsu_pkt_r.by  }} & {24'b0,lsu_ld_datafn_r[7:0]}) | | ||||
|                                   ({32{ lsu_pkt_r.unsign & lsu_pkt_r.half}} & {16'b0,lsu_ld_datafn_r[15:0]}) | | ||||
|                                   ({32{~lsu_pkt_r.unsign & lsu_pkt_r.by  }} & {{24{  lsu_ld_datafn_r[7]}}, lsu_ld_datafn_r[7:0]}) | | ||||
|  | @ -304,8 +311,14 @@ import el2_pkg::*; | |||
|    rvdff #(32) samff (.*, .din(lsu_addr_d[31:0]), .dout(lsu_addr_m[31:0]), .clk(lsu_c1_m_clk)); | ||||
|    rvdff #(32) sarff (.*, .din(lsu_addr_m[31:0]), .dout(lsu_addr_r[31:0]), .clk(lsu_c1_r_clk)); | ||||
| 
 | ||||
|    rvdff #(32) end_addr_mff (.*, .din(end_addr_d[31:0]), .dout(end_addr_m[31:0]), .clk(lsu_c1_m_clk)); | ||||
|    rvdff #(32) end_addr_rff (.*, .din(end_addr_m[31:0]), .dout(end_addr_r[31:0]), .clk(lsu_c1_r_clk)); | ||||
|    assign end_addr_m[31:3] = ldst_dual_m ? end_addr_pre_m[31:3] : lsu_addr_m[31:3];       // This is for power saving
 | ||||
|    assign end_addr_r[31:3] = ldst_dual_r ? end_addr_pre_r[31:3] : lsu_addr_r[31:3];       // This is for power saving
 | ||||
| 
 | ||||
|    rvdffe #(29) end_addr_hi_mff (.*, .din(end_addr_d[31:3]), .dout(end_addr_pre_m[31:3]), .en((lsu_pkt_d.valid & ldst_dual_d) | clk_override)); | ||||
|    rvdffe #(29) end_addr_hi_rff (.*, .din(end_addr_m[31:3]), .dout(end_addr_pre_r[31:3]), .en((lsu_pkt_m.valid & ldst_dual_m) | clk_override)); | ||||
| 
 | ||||
|    rvdff #(3)  end_addr_lo_mff (.*, .din(end_addr_d[2:0]), .dout(end_addr_m[2:0]), .clk(lsu_c1_m_clk)); | ||||
|    rvdff #(3)  end_addr_lo_rff (.*, .din(end_addr_m[2:0]), .dout(end_addr_r[2:0]), .clk(lsu_c1_r_clk)); | ||||
| 
 | ||||
|    rvdff #(1) addr_in_dccm_mff(.din(addr_in_dccm_d), .dout(addr_in_dccm_m), .clk(lsu_c1_m_clk), .*); | ||||
|    rvdff #(1) addr_in_dccm_rff(.din(addr_in_dccm_m), .dout(addr_in_dccm_r), .clk(lsu_c1_r_clk), .*); | ||||
|  | @ -323,6 +336,6 @@ import el2_pkg::*; | |||
|    rvdff #(1) fir_dccm_access_error_mff    (.din(fir_dccm_access_error_d),    .dout(fir_dccm_access_error_m),    .clk(lsu_c1_m_clk), .*); | ||||
|    rvdff #(1) fir_nondccm_access_error_mff (.din(fir_nondccm_access_error_d), .dout(fir_nondccm_access_error_m), .clk(lsu_c1_m_clk), .*); | ||||
| 
 | ||||
|    rvdff #(32) bus_read_data_r_ff (.*, .din(bus_read_data_m[31:0]), .dout(bus_read_data_r[31:0]), .clk(lsu_c1_r_clk)); | ||||
|    rvdffe #(32) bus_read_data_r_ff (.*, .din(bus_read_data_m[31:0]), .dout(bus_read_data_r[31:0]), .en(addr_external_m | clk_override)); | ||||
| 
 | ||||
| endmodule | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -33,22 +33,20 @@ import el2_pkg::*; | |||
| `include "el2_param.vh" | ||||
|  ) | ||||
| ( | ||||
|    input logic                           clk,                                            // core clock
 | ||||
|    input logic                           rst_l,                                          // reset
 | ||||
|    input logic                           clk,                         // core clock
 | ||||
|    input logic                           rst_l,                       // reset
 | ||||
| 
 | ||||
|    input logic                           lsu_c1_m_clk,                                   // clock
 | ||||
|    input logic                           lsu_c1_r_clk,                                   // lsu pipe clock
 | ||||
|    input logic                           lsu_stbuf_c1_clk,                               // stbuf clock
 | ||||
|    input logic                           lsu_free_c2_clk,                                // free clk
 | ||||
|    input logic                           lsu_stbuf_c1_clk,            // stbuf clock
 | ||||
|    input logic                           lsu_free_c2_clk,             // free clk
 | ||||
| 
 | ||||
|    // Store Buffer input
 | ||||
|    input logic                           store_stbuf_reqvld_r,         // core instruction goes to stbuf
 | ||||
|    input logic                           lsu_commit_r,                 // lsu commits
 | ||||
|    input logic                           dec_lsu_valid_raw_d,          // Speculative decode valid
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]  store_data_hi_r,              // merged data from the dccm for stores. This is used for fwding
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]  store_data_lo_r,              // merged data from the dccm for stores. This is used for fwding
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]  store_datafn_hi_r,            // merged data from the dccm for stores
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]  store_datafn_lo_r,            // merged data from the dccm for stores
 | ||||
|    input logic                           store_stbuf_reqvld_r,        // core instruction goes to stbuf
 | ||||
|    input logic                           lsu_commit_r,                // lsu commits
 | ||||
|    input logic                           dec_lsu_valid_raw_d,         // Speculative decode valid
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]  store_data_hi_r,             // merged data from the dccm for stores. This is used for fwding
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]  store_data_lo_r,             // merged data from the dccm for stores. This is used for fwding
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]  store_datafn_hi_r,           // merged data from the dccm for stores
 | ||||
|    input logic [pt.DCCM_DATA_WIDTH-1:0]  store_datafn_lo_r,           // merged data from the dccm for stores
 | ||||
| 
 | ||||
|    // Store Buffer output
 | ||||
|    output logic                          stbuf_reqvld_any,            // stbuf is draining
 | ||||
|  | @ -61,28 +59,29 @@ import el2_pkg::*; | |||
|    output logic                          lsu_stbuf_empty_any,         // stbuf is empty
 | ||||
|    output logic                          ldst_stbuf_reqvld_r,         // needed for clocking
 | ||||
| 
 | ||||
|    input logic [pt.LSU_SB_BITS-1:0]      lsu_addr_d,                  // lsu address
 | ||||
|    input logic [31:0]                    lsu_addr_m, | ||||
|    input logic [31:0]                    lsu_addr_r, | ||||
|    input logic [pt.LSU_SB_BITS-1:0]      lsu_addr_d,                  // lsu address D-stage
 | ||||
|    input logic [31:0]                    lsu_addr_m,                  // lsu address M-stage
 | ||||
|    input logic [31:0]                    lsu_addr_r,                  // lsu address R-stage
 | ||||
| 
 | ||||
|    input logic [pt.LSU_SB_BITS-1:0]      end_addr_d,                  // lsu end addrress - needed to check unaligned
 | ||||
|    input logic [31:0]                    end_addr_m, | ||||
|    input logic [31:0]                    end_addr_r, | ||||
|    input logic [pt.LSU_SB_BITS-1:0]      end_addr_d,                  // lsu end address D-stage - needed to check unaligned
 | ||||
|    input logic [31:0]                    end_addr_m,                  // lsu end address M-stage - needed to check unaligned
 | ||||
|    input logic [31:0]                    end_addr_r,                  // lsu end address R-stage - needed to check unaligned
 | ||||
| 
 | ||||
|    input logic                           addr_in_dccm_m,               // address is in dccm
 | ||||
|    input logic                           addr_in_dccm_r,               // address is in dccm
 | ||||
|    input logic                           ldst_dual_d, ldst_dual_m, ldst_dual_r, | ||||
|    input logic                           addr_in_dccm_m,              // address is in dccm
 | ||||
|    input logic                           addr_in_dccm_r,              // address is in dccm
 | ||||
| 
 | ||||
|    // Forwarding signals
 | ||||
|    input logic                           lsu_cmpen_m,                 // needed for forwarding stbuf - load
 | ||||
|    input el2_lsu_pkt_t                  lsu_pkt_m, | ||||
|    input el2_lsu_pkt_t                  lsu_pkt_r, | ||||
|    input el2_lsu_pkt_t                  lsu_pkt_m,                   // LSU packet M-stage
 | ||||
|    input el2_lsu_pkt_t                  lsu_pkt_r,                   // LSU packet R-stage
 | ||||
| 
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_fwddata_hi_m,         // stbuf data
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_fwddata_lo_m, | ||||
|    output logic [pt.DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_m, | ||||
|    output logic [pt.DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_m, | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_fwddata_hi_m,          // stbuf data
 | ||||
|    output logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_fwddata_lo_m,          // stbuf data
 | ||||
|    output logic [pt.DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_m,        // stbuf data
 | ||||
|    output logic [pt.DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_m,        // stbuf data
 | ||||
| 
 | ||||
|    input  logic       scan_mode | ||||
|    input  logic       scan_mode                                       // Scan mode
 | ||||
| 
 | ||||
| ); | ||||
| 
 | ||||
|  | @ -115,15 +114,13 @@ import el2_pkg::*; | |||
|    logic [DEPTH_LOG2-1:0]  WrPtr, RdPtr; | ||||
|    logic [DEPTH_LOG2-1:0]  NxtWrPtr, NxtRdPtr; | ||||
|    logic [DEPTH_LOG2-1:0]  WrPtrPlus1, WrPtrPlus2, RdPtrPlus1; | ||||
|    logic                   ldst_dual_d, ldst_dual_m, ldst_dual_r; | ||||
| 
 | ||||
|    logic                   dual_stbuf_write_r; | ||||
| 
 | ||||
|    logic                   isdccmst_m, isdccmst_r; | ||||
|    logic [3:0]             stbuf_numvld_any, stbuf_specvld_any; | ||||
|    logic [1:0]             stbuf_specvld_m, stbuf_specvld_r;//, stbuf_eccvld_m, stbuf_eccvld_r;
 | ||||
|    logic [1:0]             stbuf_specvld_m, stbuf_specvld_r; | ||||
| 
 | ||||
|    logic                                       cmpen_hi_m, cmpen_lo_m; | ||||
|    logic [pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] cmpaddr_hi_m, cmpaddr_lo_m; | ||||
| 
 | ||||
|    // variables to detect matching from the store queue
 | ||||
|  | @ -165,12 +162,11 @@ import el2_pkg::*; | |||
|    assign WrPtrPlus2[DEPTH_LOG2-1:0]     = WrPtr[DEPTH_LOG2-1:0] + 2'b10; | ||||
| 
 | ||||
|    // ecc error on both hi/lo
 | ||||
|    assign ldst_dual_d          = (lsu_addr_d[2] != end_addr_d[2]); | ||||
|    assign dual_stbuf_write_r   = ldst_dual_r & store_stbuf_reqvld_r; | ||||
|    assign ldst_stbuf_reqvld_r  = (lsu_commit_r & store_stbuf_reqvld_r); //|
 | ||||
|    assign ldst_stbuf_reqvld_r  = ((lsu_commit_r | lsu_pkt_r.dma) & store_stbuf_reqvld_r); | ||||
| 
 | ||||
|   // Store Buffer coalescing
 | ||||
|    for (genvar i=0; i<32'(DEPTH); i++) begin: FindMatchEntry | ||||
|    for (genvar i=0; i<DEPTH; i++) begin: FindMatchEntry | ||||
|        assign store_matchvec_lo_r[i] = (stbuf_addr[i][pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == lsu_addr_r[pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) & stbuf_vld[i] & ~stbuf_dma_kill[i] & ~stbuf_reset[i]; | ||||
|        assign store_matchvec_hi_r[i] = (stbuf_addr[i][pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == end_addr_r[pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) & stbuf_vld[i] & ~stbuf_dma_kill[i] & dual_stbuf_write_r & ~stbuf_reset[i]; | ||||
|    end: FindMatchEntry | ||||
|  | @ -179,44 +175,51 @@ import el2_pkg::*; | |||
|    assign store_coalesce_hi_r = |store_matchvec_hi_r[DEPTH-1:0]; | ||||
| 
 | ||||
| 
 | ||||
|    // Allocate new in this entry if :
 | ||||
|    // 1. wrptr, single allocate, lo did not coalesce
 | ||||
|    // 2. wrptr, double allocate, lo ^ hi coalesced
 | ||||
|    // 3. wrptr + 1, double alloacte, niether lo or hi coalesced
 | ||||
|    // Also update if there is a hi or a lo coalesce to this entry
 | ||||
|    // Store Buffer instantiation
 | ||||
|    for (genvar i=0; i<32'(DEPTH); i++) begin: GenStBuf | ||||
|       assign stbuf_wr_en[i] = ldst_stbuf_reqvld_r & ( | ||||
|                                 ( (i == WrPtr[DEPTH_LOG2-1:0])      &  ~store_coalesce_lo_r)   |                                                    // Allocate : new Lo
 | ||||
|                                 ( (i == WrPtr[DEPTH_LOG2-1:0])      &  dual_stbuf_write_r & ~store_coalesce_hi_r) |                               // Allocate : only 1 new Write Either
 | ||||
|                                 ( (i == WrPtrPlus1[DEPTH_LOG2-1:0]) &  dual_stbuf_write_r & ~(store_coalesce_lo_r | store_coalesce_hi_r)) |     // Allocate2 : 2 new so Write Hi
 | ||||
|                                 store_matchvec_lo_r[i] | store_matchvec_hi_r[i]);                                                                 // Coalesced Write Lo or Hi
 | ||||
|       assign stbuf_reset[i] = (lsu_stbuf_commit_any | stbuf_reqvld_flushed_any) & (i == RdPtr[DEPTH_LOG2-1:0]); | ||||
|    if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable | ||||
|       // Allocate new in this entry if :
 | ||||
|       // 1. wrptr, single allocate, lo did not coalesce
 | ||||
|       // 2. wrptr, double allocate, lo ^ hi coalesced
 | ||||
|       // 3. wrptr + 1, double alloacte, niether lo or hi coalesced
 | ||||
|       // Also update if there is a hi or a lo coalesce to this entry
 | ||||
|       // Store Buffer instantiation
 | ||||
|       for (genvar i=0; i<DEPTH; i++) begin: GenStBuf | ||||
|          assign stbuf_wr_en[i] = ldst_stbuf_reqvld_r & ( | ||||
|                                    ( (i == WrPtr[DEPTH_LOG2-1:0])      &  ~store_coalesce_lo_r)   |                                                    // Allocate : new Lo
 | ||||
|                                    ( (i == WrPtr[DEPTH_LOG2-1:0])      &  dual_stbuf_write_r & ~store_coalesce_hi_r) |                               // Allocate : only 1 new Write Either
 | ||||
|                                    ( (i == WrPtrPlus1[DEPTH_LOG2-1:0]) &  dual_stbuf_write_r & ~(store_coalesce_lo_r | store_coalesce_hi_r)) |     // Allocate2 : 2 new so Write Hi
 | ||||
|                                    store_matchvec_lo_r[i] | store_matchvec_hi_r[i]);                                                                 // Coalesced Write Lo or Hi
 | ||||
|          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_r | store_stbuf_reqvld_r) & (i == WrPtr[DEPTH_LOG2-1:0]) & ~store_coalesce_lo_r) |   // lo allocated new entry
 | ||||
|                                                  store_matchvec_lo_r[i];                                                                                                           // lo coalesced in to this entry
 | ||||
|       assign stbuf_addrin[i][pt.LSU_SB_BITS-1:0]  = sel_lo[i] ? lsu_addr_r[pt.LSU_SB_BITS-1:0]       : end_addr_r[pt.LSU_SB_BITS-1:0]; | ||||
|       assign stbuf_byteenin[i][BYTE_WIDTH-1:0] = sel_lo[i] ? (stbuf_byteen[i][BYTE_WIDTH-1:0] | store_byteen_lo_r[BYTE_WIDTH-1:0])          : (stbuf_byteen[i][BYTE_WIDTH-1:0] | store_byteen_hi_r[BYTE_WIDTH-1:0]); | ||||
|       assign stbuf_datain[i][7:0]              = sel_lo[i] ? ((~stbuf_byteen[i][0] | store_byteen_lo_r[0]) ? store_datafn_lo_r[7:0]   : stbuf_data[i][7:0])    : | ||||
|                                                              ((~stbuf_byteen[i][0] | store_byteen_hi_r[0]) ? store_datafn_hi_r[7:0]   : stbuf_data[i][7:0]); | ||||
|       assign stbuf_datain[i][15:8]             = sel_lo[i] ? ((~stbuf_byteen[i][1] | store_byteen_lo_r[1]) ? store_datafn_lo_r[15:8]  : stbuf_data[i][15:8])    : | ||||
|                                                              ((~stbuf_byteen[i][1] | store_byteen_hi_r[1]) ? store_datafn_hi_r[15:8]  : stbuf_data[i][15:8]); | ||||
|       assign stbuf_datain[i][23:16]            = sel_lo[i] ? ((~stbuf_byteen[i][2] | store_byteen_lo_r[2]) ? store_datafn_lo_r[23:16] : stbuf_data[i][23:16])    : | ||||
|                                                              ((~stbuf_byteen[i][2] | store_byteen_hi_r[2]) ? store_datafn_hi_r[23:16] : stbuf_data[i][23:16]); | ||||
|       assign stbuf_datain[i][31:24]            = sel_lo[i] ? ((~stbuf_byteen[i][3] | store_byteen_lo_r[3]) ? store_datafn_lo_r[31:24] : stbuf_data[i][31:24])    : | ||||
|                                                              ((~stbuf_byteen[i][3] | store_byteen_hi_r[3]) ? store_datafn_hi_r[31:24] : stbuf_data[i][31:24]); | ||||
|          // Mux select for start/end address
 | ||||
|          assign sel_lo[i]                         = ((~ldst_dual_r | store_stbuf_reqvld_r) & (i == WrPtr[DEPTH_LOG2-1:0]) & ~store_coalesce_lo_r) |   // lo allocated new entry
 | ||||
|                                                     store_matchvec_lo_r[i];                                                                                                           // lo coalesced in to this entry
 | ||||
|          assign stbuf_addrin[i][pt.LSU_SB_BITS-1:0]  = sel_lo[i] ? lsu_addr_r[pt.LSU_SB_BITS-1:0]       : end_addr_r[pt.LSU_SB_BITS-1:0]; | ||||
|          assign stbuf_byteenin[i][BYTE_WIDTH-1:0] = sel_lo[i] ? (stbuf_byteen[i][BYTE_WIDTH-1:0] | store_byteen_lo_r[BYTE_WIDTH-1:0])          : (stbuf_byteen[i][BYTE_WIDTH-1:0] | store_byteen_hi_r[BYTE_WIDTH-1:0]); | ||||
|          assign stbuf_datain[i][7:0]              = sel_lo[i] ? ((~stbuf_byteen[i][0] | store_byteen_lo_r[0]) ? store_datafn_lo_r[7:0]   : stbuf_data[i][7:0])    : | ||||
|                                                                 ((~stbuf_byteen[i][0] | store_byteen_hi_r[0]) ? store_datafn_hi_r[7:0]   : stbuf_data[i][7:0]); | ||||
|          assign stbuf_datain[i][15:8]             = sel_lo[i] ? ((~stbuf_byteen[i][1] | store_byteen_lo_r[1]) ? store_datafn_lo_r[15:8]  : stbuf_data[i][15:8])    : | ||||
|                                                                 ((~stbuf_byteen[i][1] | store_byteen_hi_r[1]) ? store_datafn_hi_r[15:8]  : stbuf_data[i][15:8]); | ||||
|          assign stbuf_datain[i][23:16]            = sel_lo[i] ? ((~stbuf_byteen[i][2] | store_byteen_lo_r[2]) ? store_datafn_lo_r[23:16] : stbuf_data[i][23:16])    : | ||||
|                                                                 ((~stbuf_byteen[i][2] | store_byteen_hi_r[2]) ? store_datafn_hi_r[23:16] : stbuf_data[i][23:16]); | ||||
|          assign stbuf_datain[i][31:24]            = sel_lo[i] ? ((~stbuf_byteen[i][3] | store_byteen_lo_r[3]) ? store_datafn_lo_r[31:24] : stbuf_data[i][31:24])    : | ||||
|                                                                 ((~stbuf_byteen[i][3] | store_byteen_hi_r[3]) ? store_datafn_hi_r[31:24] : stbuf_data[i][31:24]); | ||||
| 
 | ||||
|       rvdffsc #(.WIDTH(1))              stbuf_vldff         (.din(1'b1),                                .dout(stbuf_vld[i]),                      .en(stbuf_wr_en[i]), .clear(stbuf_reset[i]), .clk(lsu_free_c2_clk), .*); | ||||
|       rvdffsc #(.WIDTH(1))              stbuf_killff        (.din(1'b1),                                .dout(stbuf_dma_kill[i]),                 .en(stbuf_dma_kill_en[i]), .clear(stbuf_reset[i]), .clk(lsu_free_c2_clk), .*); | ||||
|       rvdffe  #(.WIDTH(pt.LSU_SB_BITS)) stbuf_addrff        (.din(stbuf_addrin[i][pt.LSU_SB_BITS-1:0]), .dout(stbuf_addr[i][pt.LSU_SB_BITS-1:0]), .en(stbuf_wr_en[i]), .*); | ||||
|       rvdffsc #(.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]), .clear(stbuf_reset[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_wr_en[i]), .*); | ||||
|          rvdffsc #(.WIDTH(1))              stbuf_vldff         (.din(1'b1),                                .dout(stbuf_vld[i]),                      .en(stbuf_wr_en[i]), .clear(stbuf_reset[i]), .clk(lsu_free_c2_clk), .*); | ||||
|          rvdffsc #(.WIDTH(1))              stbuf_killff        (.din(1'b1),                                .dout(stbuf_dma_kill[i]),                 .en(stbuf_dma_kill_en[i]), .clear(stbuf_reset[i]), .clk(lsu_free_c2_clk), .*); | ||||
|          rvdffe  #(.WIDTH(pt.LSU_SB_BITS)) stbuf_addrff        (.din(stbuf_addrin[i][pt.LSU_SB_BITS-1:0]), .dout(stbuf_addr[i][pt.LSU_SB_BITS-1:0]), .en(stbuf_wr_en[i]), .*); | ||||
|          rvdffsc #(.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]), .clear(stbuf_reset[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_wr_en[i]), .*); | ||||
|       end | ||||
|    end else begin: Gen_dccm_disable | ||||
|       assign stbuf_wr_en[DEPTH-1:0] = '0; | ||||
|       assign stbuf_reset[DEPTH-1:0] = '0; | ||||
|       assign stbuf_vld[DEPTH-1:0]   = '0; | ||||
|       assign stbuf_dma_kill[DEPTH-1:0] = '0; | ||||
|       assign stbuf_addr[DEPTH-1:0]  = '0; | ||||
|       assign stbuf_byteen[DEPTH-1:0] = '0; | ||||
|       assign stbuf_data[DEPTH-1:0]   = '0; | ||||
|    end | ||||
| 
 | ||||
|    rvdff #(.WIDTH(1)) ldst_dual_mff (.din(ldst_dual_d), .dout(ldst_dual_m), .clk(lsu_c1_m_clk), .*); | ||||
|    rvdff #(.WIDTH(1)) ldst_dual_rff (.din(ldst_dual_m), .dout(ldst_dual_r), .clk(lsu_c1_r_clk), .*); | ||||
| 
 | ||||
|    // Store Buffer drain logic
 | ||||
|    assign stbuf_reqvld_flushed_any            = stbuf_vld[RdPtr] & stbuf_dma_kill[RdPtr]; | ||||
|    assign stbuf_reqvld_any                    = stbuf_vld[RdPtr] & ~stbuf_dma_kill[RdPtr] & ~(|stbuf_dma_kill_en[DEPTH-1:0]);  // Don't drain if some kill bit is being set this cycle
 | ||||
|  | @ -233,7 +236,7 @@ import el2_pkg::*; | |||
| 
 | ||||
|    always_comb begin | ||||
|       stbuf_numvld_any[3:0] = '0; | ||||
|       for (int i=0; i<32'(DEPTH); i++) begin | ||||
|       for (int i=0; i<DEPTH; i++) begin | ||||
|          stbuf_numvld_any[3:0] += {3'b0, stbuf_vld[i]}; | ||||
|       end | ||||
|    end | ||||
|  | @ -250,24 +253,22 @@ import el2_pkg::*; | |||
|    assign lsu_stbuf_empty_any = (stbuf_numvld_any[3:0] == 4'b0); | ||||
| 
 | ||||
|    // Load forwarding logic from the store queue
 | ||||
|    assign cmpen_hi_m                                        = lsu_cmpen_m & ldst_dual_m; | ||||
|    assign cmpaddr_hi_m[pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] = end_addr_m[pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]; | ||||
| 
 | ||||
|    assign cmpen_lo_m                                        = lsu_cmpen_m; | ||||
|    assign cmpaddr_lo_m[pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] = lsu_addr_m[pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]; | ||||
| 
 | ||||
|    always_comb begin: GenLdFwd | ||||
|       stbuf_fwdbyteen_hi_pre_m[BYTE_WIDTH-1:0]   = '0; | ||||
|       stbuf_fwdbyteen_lo_pre_m[BYTE_WIDTH-1:0]   = '0; | ||||
| 
 | ||||
|       for (int i=0; i<32'(DEPTH); i++) begin | ||||
|       for (int i=0; i<DEPTH; i++) begin | ||||
|          stbuf_match_hi[i] = (stbuf_addr[i][pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == cmpaddr_hi_m[pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) & stbuf_vld[i] & ~stbuf_dma_kill[i] & addr_in_dccm_m; | ||||
|          stbuf_match_lo[i] = (stbuf_addr[i][pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] == cmpaddr_lo_m[pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)]) & stbuf_vld[i] & ~stbuf_dma_kill[i] & addr_in_dccm_m; | ||||
| 
 | ||||
|          // Kill the store buffer entry if there is a dma store since it already updated the dccm
 | ||||
|          stbuf_dma_kill_en[i] = (stbuf_match_hi[i] | stbuf_match_lo[i]) & lsu_pkt_m.valid & lsu_pkt_m.dma & lsu_pkt_m.store; | ||||
| 
 | ||||
|          for (int j=0; j<32'(BYTE_WIDTH); j++) begin | ||||
|          for (int j=0; j<BYTE_WIDTH; j++) begin | ||||
|             stbuf_fwdbyteenvec_hi[i][j] = stbuf_match_hi[i] & stbuf_byteen[i][j] & stbuf_vld[i]; | ||||
|             stbuf_fwdbyteen_hi_pre_m[j]  |= stbuf_fwdbyteenvec_hi[i][j]; | ||||
| 
 | ||||
|  | @ -281,7 +282,7 @@ import el2_pkg::*; | |||
|       stbuf_fwddata_hi_pre_m[31:0]   = '0; | ||||
|       stbuf_fwddata_lo_pre_m[31:0]   = '0; | ||||
| 
 | ||||
|       for (int i=0; i<32'(DEPTH); i++) begin | ||||
|       for (int i=0; i<DEPTH; i++) begin | ||||
|          stbuf_fwddata_hi_pre_m[31:0] |= {32{stbuf_match_hi[i]}} & stbuf_data[i][31:0]; | ||||
|          stbuf_fwddata_lo_pre_m[31:0] |= {32{stbuf_match_lo[i]}} & stbuf_data[i][31:0]; | ||||
| 
 | ||||
|  | @ -305,7 +306,7 @@ import el2_pkg::*; | |||
|    assign ld_addr_rhit_hi_lo = (lsu_addr_m[31:2] == end_addr_r[31:2]) & lsu_pkt_r.valid & lsu_pkt_r.store & ~lsu_pkt_r.dma & dual_stbuf_write_r; | ||||
|    assign ld_addr_rhit_hi_hi = (end_addr_m[31:2] == end_addr_r[31:2]) & lsu_pkt_r.valid & lsu_pkt_r.store & ~lsu_pkt_r.dma & dual_stbuf_write_r; | ||||
| 
 | ||||
|    for (genvar i=0; i<32'(BYTE_WIDTH); i++) begin | ||||
|    for (genvar i=0; i<BYTE_WIDTH; i++) begin | ||||
|       assign ld_byte_rhit_lo_lo[i] = ld_addr_rhit_lo_lo & ldst_byteen_lo_r[i]; | ||||
|       assign ld_byte_rhit_lo_hi[i] = ld_addr_rhit_lo_hi & ldst_byteen_lo_r[i]; | ||||
|       assign ld_byte_rhit_hi_lo[i] = ld_addr_rhit_hi_lo & ldst_byteen_hi_r[i]; | ||||
|  | @ -335,11 +336,11 @@ import el2_pkg::*; | |||
|    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), .*); | ||||
| 
 | ||||
| `ifdef ASSERT_ON | ||||
| `ifdef RV_ASSERT_ON | ||||
| 
 | ||||
|    assert_stbuf_overflow: assert #0 (stbuf_specvld_any[2:0] <= DEPTH); | ||||
|    property stbuf_wren_store_dccm; | ||||
|       @(posedge clk)  disable iff(~rst_l) (|stbuf_wr_en[DEPTH-1:0]) |-> (lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_dccm_r & ~lsu_pkt_r.dma); | ||||
|       @(posedge clk)  disable iff(~rst_l) (|stbuf_wr_en[DEPTH-1:0]) |-> (lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_dccm_r); | ||||
|    endproperty | ||||
|    assert_stbuf_wren_store_dccm: assert property (stbuf_wren_store_dccm) else | ||||
|       $display("Illegal store buffer write"); | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 Western Digital Corporation or it's affiliates.
 | ||||
| // Copyright 2020 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.
 | ||||
|  | @ -27,29 +27,39 @@ import el2_pkg::*; | |||
| #( | ||||
| `include "el2_param.vh" | ||||
|  )( | ||||
|    input el2_trigger_pkt_t [3:0] trigger_pkt_any,        // trigger packet from dec
 | ||||
|    input el2_trigger_pkt_t [3:0] trigger_pkt_any,            // trigger packet from dec
 | ||||
|    input el2_lsu_pkt_t           lsu_pkt_m,                  // lsu packet
 | ||||
|    input logic [31:0]             lsu_addr_m,                 // address
 | ||||
|    input logic [31:0]             store_data_m,               // store data
 | ||||
| 
 | ||||
|    output logic [3:0]             lsu_trigger_match_m          // match result
 | ||||
|    output logic [3:0]             lsu_trigger_match_m         // match result
 | ||||
| ); | ||||
| 
 | ||||
|    logic               trigger_enable; | ||||
|    logic [3:0][31:0]  lsu_match_data; | ||||
|    logic [3:0]        lsu_trigger_data_match; | ||||
|    logic [31:0]       store_data_trigger_m; | ||||
|    logic [31:0]       ldst_addr_trigger_m; | ||||
| 
 | ||||
|    assign store_data_trigger_m[31:0] = {({16{lsu_pkt_m.word}} & store_data_m[31:16]),({8{(lsu_pkt_m.half | lsu_pkt_m.word)}} & store_data_m[15:8]), store_data_m[7:0]}; | ||||
|    // Generate the trigger enable (This is for power)
 | ||||
|    always_comb begin | ||||
|       trigger_enable = 1'b0; | ||||
|       for (int i=0; i<4; i++) begin | ||||
|          trigger_enable |= trigger_pkt_any[i].m; | ||||
|       end | ||||
|    end | ||||
| 
 | ||||
|    assign store_data_trigger_m[31:0] = {({16{lsu_pkt_m.word}} & store_data_m[31:16]),({8{(lsu_pkt_m.half | lsu_pkt_m.word)}} & store_data_m[15:8]), store_data_m[7:0]} & {32{trigger_enable}}; | ||||
|    assign ldst_addr_trigger_m[31:0]  = lsu_addr_m[31:0] & {32{trigger_enable}}; | ||||
| 
 | ||||
| 
 | ||||
|    for (genvar i=0; i<4; i++) begin | ||||
|       assign lsu_match_data[i][31:0] = ({32{~trigger_pkt_any[i].select}} & lsu_addr_m[31:0]) | | ||||
|       assign lsu_match_data[i][31:0] = ({32{~trigger_pkt_any[i].select}} & ldst_addr_trigger_m[31:0]) | | ||||
|                                        ({32{trigger_pkt_any[i].select & trigger_pkt_any[i].store}} & store_data_trigger_m[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_m[i] = lsu_pkt_m.valid & ~lsu_pkt_m.dma & | ||||
|       assign lsu_trigger_match_m[i] = lsu_pkt_m.valid & ~lsu_pkt_m.dma & trigger_enable & | ||||
|                                         ((trigger_pkt_any[i].store & lsu_pkt_m.store) | (trigger_pkt_any[i].load & lsu_pkt_m.load & ~trigger_pkt_any[i].select)) & | ||||
|                                         lsu_trigger_data_match[i]; | ||||
|    end | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -1,11 +1,38 @@ | |||
| # EL2 SweRV RISC-V Core<sup>TM</sup> 1.2 from Western Digital | ||||
| # EL2 SweRV RISC-V Core<sup>TM</sup> 1.3 from Western Digital | ||||
| 
 | ||||
| 
 | ||||
| * Multiple debug module compliance deviations and bugs reported by Codasip | ||||
| * Updates to debug module to level compliance to version 0.13.2 of debug spec | ||||
| * Trigger chaining compliance fixes | ||||
| * Power optimization improvements and clock gating improvements | ||||
|     * Significantly lower power in sleep as well as normal operation. | ||||
| * Enhanced debug memory abstract command to access internal as well as external memories | ||||
| * Added bit-manipulation support for Zba, Zbb, Zbc, Zbe, Zbf, Zbp, Zbr, Zbs (Jan 29, 2020 Draft spec). | ||||
|     * Zbs and Zbb are enabled by default. Use -set=bitmanip+zb*=1 to enable other sub-extensions. | ||||
| * Enhancements and additional configurations options for a faster divider | ||||
| * JTAG controller intial state issue fixed | ||||
| * Branch predictor fully-associative mode fo 8,16,32 entries. | ||||
| * Corner case bugs fixes related to  | ||||
|     * Bus protocol corner cases (ahb) | ||||
|     * Fetch bus error recording improved accuracy | ||||
|     * Branch predictor pathological timing cases fixes | ||||
|     * Fast interrupt with DCCM ECC errors priority bug | ||||
|     * MPC & PMU protocol cleanup | ||||
|     * Performance counter bug fixes (counting branch prediction events) | ||||
|     * Triggers and ECC correctable error overflows bug fixes | ||||
| 
 | ||||
| * Demo test-bench updates | ||||
|     * Handling bigger test sizes using associative arrays in external memory slaves,  | ||||
|     * simplified test building process and CCM loading functions (only program.hex is generated, no data.hex) | ||||
|     * Improved Makefile and example tests (see README) | ||||
|     * Generating crt0 and link.ld from swerv.config | ||||
|      | ||||
| # EL2 SweRV RISC-V Core<sup>TM</sup> 1.2 from Western Digital | ||||
| ## Release Notes | ||||
| 
 | ||||
| * Modified MSCAUSE encoding to be consistent with current internal specification | ||||
| * Added internal timers | ||||
| 
 | ||||
| 
 | ||||
| # EL2 SweRV RISC-V Core<sup>TM</sup> 1.1 from Western Digital | ||||
| 
 | ||||
| ## Release Notes | ||||
|  |  | |||
|  | @ -0,0 +1,26 @@ | |||
| // See LICENSE.SiFive for license details.
 | ||||
| 
 | ||||
| #include <cstdlib> | ||||
| #include "remote_bitbang.h" | ||||
| 
 | ||||
| remote_bitbang_t* jtag; | ||||
| extern "C" int jtag_tick | ||||
| ( | ||||
|  unsigned char * jtag_TCK, | ||||
|  unsigned char * jtag_TMS, | ||||
|  unsigned char * jtag_TDI, | ||||
|  unsigned char * jtag_TRSTn, | ||||
|  unsigned char * srstn, | ||||
|  unsigned char jtag_TDO | ||||
| ) | ||||
| { | ||||
|   if (!jtag) { | ||||
|     // TODO: Pass in real port number
 | ||||
|     jtag = new remote_bitbang_t(0); | ||||
|   } | ||||
| 
 | ||||
|   jtag->tick(jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn, srstn, jtag_TDO); | ||||
| 
 | ||||
|   return jtag->done() ? (jtag->exit_code() << 1 | 1) : 0; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,89 @@ | |||
| // See LICENSE.SiFive for license details. | ||||
| //VCS coverage exclude_file | ||||
| import "DPI-C" function int jtag_tick | ||||
| ( | ||||
|  output bit jtag_TCK, | ||||
|  output bit jtag_TMS, | ||||
|  output bit jtag_TDI, | ||||
|  output bit jtag_TRSTn, | ||||
|  output bit sysrstn, | ||||
| 
 | ||||
|  input bit  jtag_TDO | ||||
| ); | ||||
| 
 | ||||
| module SimJTAG #( | ||||
|                  parameter TICK_DELAY = 50 | ||||
|                  )( | ||||
| 
 | ||||
|                    input         clock, | ||||
|                    input         reset, | ||||
| 
 | ||||
|                    input         enable, | ||||
|                    input         init_done, | ||||
| 
 | ||||
|                    output        jtag_TCK, | ||||
|                    output        jtag_TMS, | ||||
|                    output        jtag_TDI, | ||||
|                    output        jtag_TRSTn, | ||||
|                    output        srstn, | ||||
| 
 | ||||
|                    input         jtag_TDO_data, | ||||
|                    input         jtag_TDO_driven, | ||||
| 
 | ||||
|                    output [31:0] exit | ||||
|                    ); | ||||
| 
 | ||||
|    reg [31:0]                    tickCounterReg; | ||||
|    wire [31:0]                   tickCounterNxt; | ||||
| 
 | ||||
|    assign tickCounterNxt = (tickCounterReg == 0) ? TICK_DELAY :  (tickCounterReg - 1); | ||||
| 
 | ||||
|    bit          r_reset; | ||||
| 
 | ||||
|    wire [31:0]  random_bits = $random; | ||||
| 
 | ||||
|    wire         #0.1 __jtag_TDO = jtag_TDO_driven ? | ||||
|                 jtag_TDO_data : random_bits[0]; | ||||
| 
 | ||||
|    bit          __jtag_TCK; | ||||
|    bit          __jtag_TMS; | ||||
|    bit          __jtag_TDI; | ||||
|    bit          __jtag_TRSTn; | ||||
|    int          __exit; | ||||
|    bit          sysrstn=1; | ||||
| 
 | ||||
|    reg          init_done_sticky; | ||||
| 
 | ||||
|    assign #0.1 jtag_TCK   = __jtag_TCK; | ||||
|    assign #0.1 jtag_TMS   = __jtag_TMS; | ||||
|    assign #0.1 jtag_TDI   = __jtag_TDI; | ||||
|    assign #0.1 jtag_TRSTn = __jtag_TRSTn; | ||||
|    assign srstn = sysrstn; | ||||
| 
 | ||||
|    assign #0.1 exit = __exit; | ||||
| 
 | ||||
|    always @(posedge clock) begin | ||||
|       r_reset <= reset; | ||||
|       if (reset || r_reset) begin | ||||
|          __exit = 0; | ||||
|          tickCounterReg <= TICK_DELAY; | ||||
|          init_done_sticky <= 1'b0; | ||||
|          __jtag_TCK = !__jtag_TCK; | ||||
|       end else begin | ||||
|          init_done_sticky <= init_done | init_done_sticky; | ||||
|          if (enable && init_done_sticky) begin | ||||
|             tickCounterReg <= tickCounterNxt; | ||||
|             if (tickCounterReg == 0) begin | ||||
|                __exit = jtag_tick( | ||||
|                                   __jtag_TCK, | ||||
|                                   __jtag_TMS, | ||||
|                                   __jtag_TDI, | ||||
|                                   __jtag_TRSTn, | ||||
|                                   sysrstn, | ||||
|                                   __jtag_TDO); | ||||
|             end | ||||
|          end // if (enable && init_done_sticky) | ||||
|       end // else: !if(reset || r_reset) | ||||
|    end // always @ (posedge clock) | ||||
| 
 | ||||
| endmodule | ||||
|  | @ -33,17 +33,20 @@ output logic HRESP, | |||
| output logic [63:0] HRDATA | ||||
| ); | ||||
| 
 | ||||
| parameter MEM_SIZE_DW = 8192; | ||||
| parameter MAILBOX_ADDR = 32'hD0580000; | ||||
| localparam MEM_SIZE = MEM_SIZE_DW*8; | ||||
| 
 | ||||
| logic Write; | ||||
| logic [31:0] Last_HADDR; | ||||
| logic write; | ||||
| logic [31:0] laddr, addr; | ||||
| logic [7:0] strb_lat; | ||||
| logic [63:0] rdata; | ||||
| 
 | ||||
| bit [7:0] mem [0:MEM_SIZE-1]; | ||||
| //bit [7:0] mem [int];
 | ||||
| //int kuku[int];
 | ||||
| bit [7:0] mem [bit[31:0]]; | ||||
| bit [7:0] wscnt; | ||||
| int dws = 0; | ||||
| int iws = 0; | ||||
| bit dws_rand; | ||||
| bit iws_rand; | ||||
| bit ok; | ||||
| 
 | ||||
| // Wires
 | ||||
| wire [63:0] WriteData = HWDATA; | ||||
|  | @ -51,50 +54,79 @@ wire [7:0] strb =  HSIZE == 3'b000 ? 8'h1 << HADDR[2:0] : | |||
|                    HSIZE == 3'b001 ? 8'h3 << {HADDR[2:1],1'b0} : | ||||
|                    HSIZE == 3'b010 ? 8'hf << {HADDR[2],2'b0} : 8'hff; | ||||
| 
 | ||||
| wire[31:0] addr = HADDR & (MEM_SIZE-1); | ||||
| wire[31:0] laddr = Last_HADDR & (MEM_SIZE-1); | ||||
| 
 | ||||
| wire mailbox_write   = Write && Last_HADDR==MAILBOX_ADDR; | ||||
| 
 | ||||
| wire [63:0] mem_dout =  {mem[{addr[31:3],3'd7}], | ||||
|                          mem[{addr[31:3],3'd6}], | ||||
|                          mem[{addr[31:3],3'd5}], | ||||
|                          mem[{addr[31:3],3'd4}], | ||||
|                          mem[{addr[31:3],3'd3}], | ||||
|                          mem[{addr[31:3],3'd2}], | ||||
|                          mem[{addr[31:3],3'd1}], | ||||
|                          mem[{addr[31:3],3'd0}]}; | ||||
| wire mailbox_write = write && laddr==MAILBOX_ADDR; | ||||
| 
 | ||||
| 
 | ||||
| always @ (negedge HCLK ) begin | ||||
|   if (Write) begin | ||||
|     if(strb_lat[7]) mem[{laddr[31:3],3'd7}] = HWDATA[63:56]; | ||||
|     if(strb_lat[6]) mem[{laddr[31:3],3'd6}] = HWDATA[55:48]; | ||||
|     if(strb_lat[5]) mem[{laddr[31:3],3'd5}] = HWDATA[47:40]; | ||||
|     if(strb_lat[4]) mem[{laddr[31:3],3'd4}] = HWDATA[39:32]; | ||||
|     if(strb_lat[3]) mem[{laddr[31:3],3'd3}] = HWDATA[31:24]; | ||||
|     if(strb_lat[2]) mem[{laddr[31:3],3'd2}] = HWDATA[23:16]; | ||||
|     if(strb_lat[1]) mem[{laddr[31:3],3'd1}] = HWDATA[15:08]; | ||||
|     if(strb_lat[0]) mem[{laddr[31:3],3'd0}] = HWDATA[07:00]; | ||||
|   end | ||||
| initial begin | ||||
|     if ($value$plusargs("iws=%d", iws)); | ||||
|     if ($value$plusargs("dws=%d", dws)); | ||||
|     dws_rand = dws < 0; | ||||
|     iws_rand = iws < 0; | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| assign HREADYOUT = 1; | ||||
| 
 | ||||
| always @ (negedge HCLK ) begin | ||||
|     if(HREADY) | ||||
|         addr = HADDR; | ||||
|     if (write & HREADY) begin | ||||
|         if(strb_lat[7]) mem[{laddr[31:3],3'd7}] = HWDATA[63:56]; | ||||
|         if(strb_lat[6]) mem[{laddr[31:3],3'd6}] = HWDATA[55:48]; | ||||
|         if(strb_lat[5]) mem[{laddr[31:3],3'd5}] = HWDATA[47:40]; | ||||
|         if(strb_lat[4]) mem[{laddr[31:3],3'd4}] = HWDATA[39:32]; | ||||
|         if(strb_lat[3]) mem[{laddr[31:3],3'd3}] = HWDATA[31:24]; | ||||
|         if(strb_lat[2]) mem[{laddr[31:3],3'd2}] = HWDATA[23:16]; | ||||
|         if(strb_lat[1]) mem[{laddr[31:3],3'd1}] = HWDATA[15:08]; | ||||
|         if(strb_lat[0]) mem[{laddr[31:3],3'd0}] = HWDATA[07:00]; | ||||
|     end | ||||
|     if(HREADY & HSEL & |HTRANS) begin | ||||
| `ifdef VERILATOR | ||||
|         if(iws_rand & ~HPROT[0]) | ||||
|             iws = $random & 15; | ||||
|         if(dws_rand & HPROT[0]) | ||||
|             dws = $random & 15; | ||||
| `else | ||||
|         if(iws_rand & ~HPROT[0]) | ||||
|             ok = std::randomize(iws) with {iws dist {0:=10, [1:3]:/2, [4:15]:/1};}; | ||||
|         if(dws_rand & HPROT[0]) | ||||
|             ok = std::randomize(dws) with {dws dist {0:=10, [1:3]:/2, [4:15]:/1};}; | ||||
| `endif | ||||
|     end | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| assign HRDATA = HREADY ? rdata : ~rdata; | ||||
| assign HREADYOUT = wscnt == 0; | ||||
| assign HRESP = 0; | ||||
| 
 | ||||
| always @(posedge HCLK or negedge HRESETn) begin | ||||
|   if(~HRESETn) begin | ||||
|     Last_HADDR  <= 32'b0; | ||||
|     Write <= 1'b0; | ||||
|     HRDATA <= '0; | ||||
|   end else begin | ||||
|     Last_HADDR  <= HADDR; | ||||
|     Write <= HWRITE & |HTRANS; | ||||
|     if(|HTRANS & ~HWRITE) | ||||
|         HRDATA <= mem_dout; | ||||
|     strb_lat    <= strb; | ||||
|   end | ||||
|     if(~HRESETn) begin | ||||
|         laddr <= 32'b0; | ||||
|         write <= 1'b0; | ||||
|         rdata <= '0; | ||||
|         wscnt <= 0; | ||||
|     end | ||||
|     else begin | ||||
|         if(HREADY & HSEL) begin | ||||
|             laddr <= HADDR; | ||||
|             write <= HWRITE & |HTRANS; | ||||
|             if(|HTRANS & ~HWRITE) | ||||
|                 rdata <= {mem[{addr[31:3],3'd7}], | ||||
|                           mem[{addr[31:3],3'd6}], | ||||
|                           mem[{addr[31:3],3'd5}], | ||||
|                           mem[{addr[31:3],3'd4}], | ||||
|                           mem[{addr[31:3],3'd3}], | ||||
|                           mem[{addr[31:3],3'd2}], | ||||
|                           mem[{addr[31:3],3'd1}], | ||||
|                           mem[{addr[31:3],3'd0}]}; | ||||
|             strb_lat <= strb; | ||||
|         end | ||||
|     end | ||||
|     if(HREADY & HSEL & |HTRANS) | ||||
|         wscnt <= HPROT[0] ? dws[7:0] : iws[7:0]; | ||||
|     else if(wscnt != 0) | ||||
|         wscnt <= wscnt-1; | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
|  | @ -142,14 +174,11 @@ output reg [TAGW-1:0]   bid | |||
| parameter MAILBOX_ADDR = 32'hD0580000; | ||||
| parameter MEM_SIZE_DW = 8192; | ||||
| 
 | ||||
| bit [7:0] mem [0:MEM_SIZE_DW*8-1]; | ||||
| bit [7:0] mem [bit[31:0]]; | ||||
| bit [63:0] memdata; | ||||
| wire [31:0] waddr, raddr; | ||||
| wire [63:0] WriteData; | ||||
| wire mailbox_write; | ||||
| 
 | ||||
| assign raddr = araddr & (MEM_SIZE_DW*8-1); | ||||
| assign waddr = awaddr & (MEM_SIZE_DW*8-1); | ||||
| 
 | ||||
| assign mailbox_write = awvalid && awaddr==MAILBOX_ADDR && rst_l; | ||||
| assign WriteData = wdata; | ||||
|  | @ -169,17 +198,17 @@ always @ ( posedge aclk or negedge rst_l) begin | |||
| end | ||||
| 
 | ||||
| always @ ( negedge aclk) begin | ||||
|     if(arvalid) memdata <= {mem[raddr+7], mem[raddr+6], mem[raddr+5], mem[raddr+4], | ||||
|                             mem[raddr+3], mem[raddr+2], mem[raddr+1], mem[raddr]}; | ||||
|     if(arvalid) memdata <= {mem[araddr+7], mem[araddr+6], mem[araddr+5], mem[araddr+4], | ||||
|                             mem[araddr+3], mem[araddr+2], mem[araddr+1], mem[araddr]}; | ||||
|     if(awvalid) begin | ||||
|         if(wstrb[7]) mem[waddr+7] = wdata[63:56]; | ||||
|         if(wstrb[6]) mem[waddr+6] = wdata[55:48]; | ||||
|         if(wstrb[5]) mem[waddr+5] = wdata[47:40]; | ||||
|         if(wstrb[4]) mem[waddr+4] = wdata[39:32]; | ||||
|         if(wstrb[3]) mem[waddr+3] = wdata[31:24]; | ||||
|         if(wstrb[2]) mem[waddr+2] = wdata[23:16]; | ||||
|         if(wstrb[1]) mem[waddr+1] = wdata[15:08]; | ||||
|         if(wstrb[0]) mem[waddr+0] = wdata[07:00]; | ||||
|         if(wstrb[7]) mem[awaddr+7] = wdata[63:56]; | ||||
|         if(wstrb[6]) mem[awaddr+6] = wdata[55:48]; | ||||
|         if(wstrb[5]) mem[awaddr+5] = wdata[47:40]; | ||||
|         if(wstrb[4]) mem[awaddr+4] = wdata[39:32]; | ||||
|         if(wstrb[3]) mem[awaddr+3] = wdata[31:24]; | ||||
|         if(wstrb[2]) mem[awaddr+2] = wdata[23:16]; | ||||
|         if(wstrb[1]) mem[awaddr+1] = wdata[15:08]; | ||||
|         if(wstrb[0]) mem[awaddr+0] = wdata[07:00]; | ||||
|     end | ||||
| end | ||||
| 
 | ||||
|  | @ -193,3 +222,4 @@ assign rlast   = 1'b1; | |||
| 
 | ||||
| endmodule | ||||
| `endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,35 +1,6 @@ | |||
| #include "defines.h" | ||||
| 
 | ||||
| #define ITERATIONS 1 | ||||
| extern int STACK; | ||||
| void main(); | ||||
| 
 | ||||
| 
 | ||||
| #define STDOUT 0xd0580000 | ||||
| 
 | ||||
| __asm (".section .text"); | ||||
| __asm (".global _start"); | ||||
| __asm ("_start:"); | ||||
| 
 | ||||
| // Enable Caches in MRAC
 | ||||
| __asm ("li t0, 0x5f555555"); | ||||
| __asm ("csrw 0x7c0, t0"); | ||||
| 
 | ||||
| // Set stack pointer.
 | ||||
| __asm ("la sp, STACK"); | ||||
| 
 | ||||
| __asm ("jal main"); | ||||
| 
 | ||||
| // Write 0xff to STDOUT for TB to termiate test.
 | ||||
| __asm (".global _finish"); | ||||
| __asm ("_finish:"); | ||||
| __asm ("li t0, 0xd0580000"); | ||||
| __asm ("addi t1, zero, 0xff"); | ||||
| __asm ("sb t1, 0(t0)"); | ||||
| __asm ("beq x0, x0, _finish"); | ||||
| __asm (".rept 10"); | ||||
| __asm ("nop"); | ||||
| __asm (".endr"); | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -1200,7 +1171,7 @@ MAIN_RETURN_TYPE main(int argc, char *argv[]) { | |||
|         ee_printf("Total time (secs): %d\n",time_in_secs(total_time)); | ||||
|         if (time_in_secs(total_time) > 0) | ||||
| //              ee_printf("Iterations/Sec   : %d\n",default_num_contexts*results[0].iterations/time_in_secs(total_time));
 | ||||
|                 ee_printf("Iterat/Sec/MHz   : %d.%d\n",1000*default_num_contexts*results[0].iterations/time_in_secs(total_time), | ||||
|                 ee_printf("Iterat/Sec/MHz   : %d.%02d\n",1000*default_num_contexts*results[0].iterations/time_in_secs(total_time), | ||||
|                              100000*default_num_contexts*results[0].iterations/time_in_secs(total_time) % 100); | ||||
| #endif | ||||
|         if (time_in_secs(total_time) < 10) { | ||||
|  | @ -2182,213 +2153,6 @@ void portable_fini(core_portable *p) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| #include <stdarg.h> | ||||
| 
 | ||||
| // Special address. Writing (store byte instruction) to this address
 | ||||
| // causes the simulator to write to the console.
 | ||||
| volatile char __whisper_console_io = 0; | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPutc(char c) | ||||
| { | ||||
| //  __whisper_console_io = c;
 | ||||
| //  __whisper_console_io = c;
 | ||||
|   *(volatile char*)(STDOUT) = c; | ||||
|   return c; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPuts(const char* s) | ||||
| { | ||||
|   while (*s) | ||||
|     whisperPutc(*s++); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPrintDecimal(int value) | ||||
| { | ||||
|   char buffer[20]; | ||||
|   int charCount = 0; | ||||
| 
 | ||||
|   unsigned neg = value < 0; | ||||
|   if (neg) | ||||
|     { | ||||
|       value = -value; | ||||
|       whisperPutc('-'); | ||||
|     } | ||||
| 
 | ||||
|   do | ||||
|     { | ||||
|       char c = '0' + (value % 10); | ||||
|       value = value / 10; | ||||
|       buffer[charCount++] = c; | ||||
|     } | ||||
|   while (value); | ||||
| 
 | ||||
|   char* p = buffer + charCount - 1; | ||||
|   for (unsigned i = 0; i < charCount; ++i) | ||||
|     whisperPutc(*p--); | ||||
| 
 | ||||
|   if (neg) | ||||
|     charCount++; | ||||
| 
 | ||||
|   return charCount; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPrintInt(int value, int base) | ||||
| { | ||||
|   if (base == 10) | ||||
|     return whisperPrintDecimal(value); | ||||
| 
 | ||||
|   char buffer[20]; | ||||
|   int charCount = 0; | ||||
| 
 | ||||
|   unsigned uu = value; | ||||
| 
 | ||||
|   if (base == 8) | ||||
|     { | ||||
|       do | ||||
|         { | ||||
|           char c = '0' + (uu & 7); | ||||
|           buffer[charCount++] = c; | ||||
|           uu >>= 3; | ||||
|         } | ||||
|       while (uu); | ||||
|     } | ||||
|   else if (base == 16) | ||||
|     { | ||||
|       do | ||||
|         { | ||||
|           int digit = uu & 0xf; | ||||
|           char c = digit < 10 ? '0' + digit : 'a' + digit; | ||||
|           buffer[charCount++] = c; | ||||
|           uu >>= 4; | ||||
|         } | ||||
|       while (uu); | ||||
|     } | ||||
|   else | ||||
|     return -1; | ||||
| 
 | ||||
|   char* p = buffer + charCount - 1; | ||||
|   for (unsigned i = 0; i < charCount; ++i) | ||||
|     whisperPutc(*p--); | ||||
| 
 | ||||
|   return charCount; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| whisperPrintfImpl(const char* format, va_list ap) | ||||
| { | ||||
|   int count = 0;  // Printed character count
 | ||||
| 
 | ||||
|   for (const char* fp = format; *fp; fp++) | ||||
|     { | ||||
|       if (*fp != '%') | ||||
|         { | ||||
|           whisperPutc(*fp); | ||||
|           ++count; | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|       ++fp;  // Skip %
 | ||||
| 
 | ||||
|       if (*fp == 0) | ||||
|         break; | ||||
| 
 | ||||
|       if (*fp == '%') | ||||
|         { | ||||
|           whisperPutc('%'); | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|       if (*fp == '-') | ||||
|         { | ||||
|           fp++;  // Pad right not yet implemented.
 | ||||
|         } | ||||
| 
 | ||||
|       while (*fp == '0') | ||||
|         { | ||||
|           fp++;  // Pad zero not yet implented.
 | ||||
|         } | ||||
| 
 | ||||
|       if (*fp == '*') | ||||
|         { | ||||
|           int width = va_arg(ap, int); | ||||
|           fp++;  // Width not yet implemented.
 | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           while (*fp >= '0' && *fp <= '9') | ||||
|             ++fp;   // Width not yet implemented.
 | ||||
|         } | ||||
| 
 | ||||
|       switch (*fp) | ||||
|         { | ||||
|         case 'd': | ||||
|           count += whisperPrintDecimal(va_arg(ap, int)); | ||||
|           break; | ||||
| 
 | ||||
|         case 'u': | ||||
|           count += whisperPrintDecimal((unsigned) va_arg(ap, unsigned)); | ||||
|           break; | ||||
| 
 | ||||
|         case 'x': | ||||
|         case 'X': | ||||
|           count += whisperPrintInt(va_arg(ap, int), 16); | ||||
|           break; | ||||
| 
 | ||||
|         case 'o': | ||||
|           count += whisperPrintInt(va_arg(ap, int), 8); | ||||
|           break; | ||||
| 
 | ||||
|         case 'c': | ||||
|           whisperPutc(va_arg(ap, int)); | ||||
|           ++count; | ||||
|           break; | ||||
| 
 | ||||
|         case 's': | ||||
|           count += whisperPuts(va_arg(ap, char*)); | ||||
|           break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   return count; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| whisperPrintf(const char* format, ...) | ||||
| { | ||||
|   va_list ap; | ||||
| 
 | ||||
|   va_start(ap, format); | ||||
|   int code = whisperPrintfImpl(format, ap); | ||||
|   va_end(ap); | ||||
| 
 | ||||
|   return code; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| printf(const char* format, ...) | ||||
| { | ||||
|   va_list ap; | ||||
| 
 | ||||
|   va_start(ap, format); | ||||
|   int code = whisperPrintfImpl(format, ap); | ||||
|   va_end(ap); | ||||
| 
 | ||||
|   return code; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void* memset(void* s, int c, size_t n) | ||||
| { | ||||
|   asm("mv t0, a0"); | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| hello_world.ld | ||||
|  | @ -0,0 +1,2 @@ | |||
| TEST_CFLAGS = -finline-limit=400 -mbranch-cost=1 -Ofast -fno-code-hoisting -funroll-all-loops | ||||
| OFILES = crt0.o printf.o cmark.o | ||||
|  | @ -0,0 +1 @@ | |||
| cmark.mki | ||||
|  | @ -1,17 +1,18 @@ | |||
| 
 | ||||
| OUTPUT_ARCH( "riscv" ) | ||||
| ENTRY(_start) | ||||
| MEMORY { | ||||
|     EXTCODE : ORIGIN = 0,          LENGTH = 0x10000 | ||||
|     EXTDATA : ORIGIN = 0x10000,    LENGTH = 0x10000 | ||||
|     ICCM    : ORIGIN = 0xee000000, LENGTH = 0x80000 | ||||
|     DCCM    : ORIGIN = 0xf0040000, LENGTH = 0x10000 | ||||
| } | ||||
| 
 | ||||
| SECTIONS { | ||||
|   .text_init : {*(.text_init)} > EXTCODE | ||||
|   init_end = .; | ||||
|   .data.ctl : AT(0x1ffec) { LONG(ADDR(.text)); LONG(text_end); LONG(LOADADDR(.text)); LONG(0xf0040000); LONG(STACK)}>EXTDATA | ||||
|   .text : AT(init_end)  { *(.text) *(.text.startup)} > ICCM | ||||
|    text_end = .; | ||||
|   .data  : AT(0x10000)  { *(.*data) *(.rodata*) STACK = ALIGN(16) + 0x8000;} > DCCM | ||||
|   .text   : { crt0.o (.text*) } | ||||
|  _end = .; | ||||
|   . = 0xee000000 ; | ||||
|   .text.init   : { cmark.o (.text*) } | ||||
|   . = 0xd0580000; | ||||
|   .data.io .  : { *(.data.io) } | ||||
|   . = 0xf0040000; | ||||
|   .data  :  { *(.*data) *(.rodata*) *(.sbss) STACK = ALIGN(16) + 0x1000;} | ||||
|   .bss : { *(.bss) } | ||||
|   . = 0xfffffff0; | ||||
|   .iccm.ctl : { LONG(0xee000000); LONG(0xee008000) } | ||||
|   . = 0xfffffff8; | ||||
|   .data.ctl : { LONG(0xf0040000); LONG(STACK) } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,2 @@ | |||
| TEST_CFLAGS = -g -O3 -funroll-all-loops | ||||
| OFILES = crt0.o printf.o cmark.o | ||||
|  | @ -0,0 +1,48 @@ | |||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # Copyright 2020 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. | ||||
| # | ||||
| // startup code to support HLL programs | ||||
| 
 | ||||
| #include "defines.h" | ||||
| 
 | ||||
| .section .text.init | ||||
| .global _start
 | ||||
| _start: | ||||
| 
 | ||||
| // enable caching, except region 0xd | ||||
|         li t0, 0x59555555 | ||||
|         csrw 0x7c0, t0 | ||||
| 
 | ||||
|         la sp, STACK | ||||
| 
 | ||||
|         call main | ||||
| 
 | ||||
| 
 | ||||
| .global _finish
 | ||||
| _finish: | ||||
|         la t0, tohost | ||||
|         li t1, 0xff | ||||
|         sb t1, 0(t0) // DemoTB test termination | ||||
|         li t1, 1 | ||||
|         sw t1, 0(t0) // Whisper test termination | ||||
|         beq x0, x0, _finish | ||||
|         .rept 10
 | ||||
|         nop | ||||
|         .endr | ||||
| 
 | ||||
| .section .data.io | ||||
| .global tohost
 | ||||
| tohost: .word 0 | ||||
| 
 | ||||
|  | @ -0,0 +1,12 @@ | |||
| OUTPUT_ARCH( "riscv" ) | ||||
| ENTRY(_start) | ||||
| 
 | ||||
| SECTIONS { | ||||
|     . = 0x80000000; | ||||
|   .text   : { *(.text*) } | ||||
|  _end = .; | ||||
|   .data  :  { *(.*data) *(.rodata*) *(.sbss) STACK = ALIGN(16) + 0x1000;} | ||||
|   .bss : { *(.bss) } | ||||
|   . = 0xd0580000; | ||||
|   .data.io .  : { *(.data.io) } | ||||
| } | ||||
|  | @ -1,12 +1,14 @@ | |||
| 
 | ||||
| OUTPUT_ARCH( "riscv" ) | ||||
| ENTRY(_start) | ||||
| 
 | ||||
| SECTIONS { | ||||
|   .text   : { *(.text*) } | ||||
|  _end = .; | ||||
|   . = 0x1fff8; | ||||
|   .data.ctl : { LONG(0xf0040000); LONG(STACK) } | ||||
|   . = 0xd0580000; | ||||
|   .data.io .  : { *(.data.io) } | ||||
|   . = 0xf0040000; | ||||
|   .data  : AT(0x10000)  { *(.*data) *(.rodata*) STACK = ALIGN(16) + 0x8000;} | ||||
|   .data  :  { *(.*data) *(.rodata*) *(.sbss) STACK = ALIGN(16) + 0x1000;} | ||||
|   .bss : { *(.bss) } | ||||
|   . = 0xfffffff8; | ||||
|   .data.ctl : { LONG(0xf0040000); LONG(STACK) } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,310 @@ | |||
| // SPDX-License-Identifier: Apache-2.0
 | ||||
| // Copyright 2020 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 <stdarg.h> | ||||
| #include <stdint.h> | ||||
| extern volatile char tohost; | ||||
| 
 | ||||
| static int | ||||
| whisperPutc(char c) | ||||
| { | ||||
|   tohost = c; | ||||
|   return c; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPuts(const char* s) | ||||
| { | ||||
|   while (*s) | ||||
|     whisperPutc(*s++); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPrintUnsigned(unsigned value, int width, char pad) | ||||
| { | ||||
|   char buffer[20]; | ||||
|   int charCount = 0; | ||||
| 
 | ||||
|   do | ||||
|     { | ||||
|       char c = '0' + (value % 10); | ||||
|       value = value / 10; | ||||
|       buffer[charCount++] = c; | ||||
|     } | ||||
|   while (value); | ||||
| 
 | ||||
|   for (int i = charCount; i < width; ++i) | ||||
|     whisperPutc(pad); | ||||
| 
 | ||||
|   char* p = buffer + charCount - 1; | ||||
|   for (int i = 0; i < charCount; ++i) | ||||
|     whisperPutc(*p--); | ||||
| 
 | ||||
|   return charCount; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPrintDecimal(int value, int width, char pad) | ||||
| { | ||||
|   char buffer[20]; | ||||
|   int charCount = 0; | ||||
| 
 | ||||
|   unsigned neg = value < 0; | ||||
|   if (neg) | ||||
|     { | ||||
|       value = -value; | ||||
|       whisperPutc('-'); | ||||
|       width--; | ||||
|     } | ||||
| 
 | ||||
|   do | ||||
|     { | ||||
|       char c = '0' + (value % 10); | ||||
|       value = value / 10; | ||||
|       buffer[charCount++] = c; | ||||
|     } | ||||
|   while (value); | ||||
| 
 | ||||
|   for (int i = charCount; i < width; ++i) | ||||
|     whisperPutc(pad); | ||||
| 
 | ||||
|   char* p = buffer + charCount - 1; | ||||
|   for (int i = 0; i < charCount; ++i) | ||||
|     whisperPutc(*p--); | ||||
| 
 | ||||
|   if (neg) | ||||
|     charCount++; | ||||
| 
 | ||||
|   return charCount; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPrintInt(int value, int width, int pad, int base) | ||||
| { | ||||
|   if (base == 10) | ||||
|     return whisperPrintDecimal(value, width, pad); | ||||
| 
 | ||||
|   char buffer[20]; | ||||
|   int charCount = 0; | ||||
| 
 | ||||
|   unsigned uu = value; | ||||
| 
 | ||||
|   if (base == 8) | ||||
|     { | ||||
|       do | ||||
|         { | ||||
|           char c = '0' + (uu & 7); | ||||
|           buffer[charCount++] = c; | ||||
|           uu >>= 3; | ||||
|         } | ||||
|       while (uu); | ||||
|     } | ||||
|   else if (base == 16) | ||||
|     { | ||||
|       do | ||||
|         { | ||||
|           int digit = uu & 0xf; | ||||
|           char c = digit < 10 ? '0' + digit : 'a' + digit - 10; | ||||
|           buffer[charCount++] = c; | ||||
|           uu >>= 4; | ||||
|         } | ||||
|       while (uu); | ||||
|     } | ||||
|   else | ||||
|     return -1; | ||||
| 
 | ||||
|   char* p = buffer + charCount - 1; | ||||
|   for (unsigned i = 0; i < charCount; ++i) | ||||
|     whisperPutc(*p--); | ||||
| 
 | ||||
|   return charCount; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| // Print with g format
 | ||||
| static int | ||||
| whisperPrintDoubleG(double value) | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // Print with f format
 | ||||
| static int | ||||
| whisperPrintDoubleF(double value) | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| int | ||||
| whisperPrintfImpl(const char* format, va_list ap) | ||||
| { | ||||
|   int count = 0;  // Printed character count
 | ||||
| 
 | ||||
|   for (const char* fp = format; *fp; fp++) | ||||
|     { | ||||
|       char pad = ' '; | ||||
|       int width = 0;  // Field width
 | ||||
| 
 | ||||
|       if (*fp != '%') | ||||
|         { | ||||
|           whisperPutc(*fp); | ||||
|           ++count; | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|       ++fp;  // Skip %
 | ||||
| 
 | ||||
|       if (*fp == 0) | ||||
|         break; | ||||
| 
 | ||||
|       if (*fp == '%') | ||||
|         { | ||||
|           whisperPutc('%'); | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|       while (*fp == '0') | ||||
|         { | ||||
|           pad = '0'; | ||||
|           fp++;  // Pad zero not yet implented.
 | ||||
|         } | ||||
| 
 | ||||
|       if (*fp == '-') | ||||
|         { | ||||
|           fp++;  // Pad right not yet implemented.
 | ||||
|         } | ||||
| 
 | ||||
|       if (*fp == '*') | ||||
|         { | ||||
|           int outWidth = va_arg(ap, int); | ||||
|           fp++;  // Width not yet implemented.
 | ||||
|         } | ||||
|       else if (*fp >= '0' && *fp <= '9') | ||||
|         {    // Width not yet implemented.
 | ||||
|           while (*fp >= '0' && *fp <= '9') | ||||
|             width = width * 10 + (*fp++ - '0'); | ||||
|         } | ||||
| 
 | ||||
|       switch (*fp) | ||||
|         { | ||||
|         case 'd': | ||||
|           count += whisperPrintDecimal(va_arg(ap, int), width, pad); | ||||
|           break; | ||||
| 
 | ||||
|         case 'u': | ||||
|           count += whisperPrintUnsigned((unsigned) va_arg(ap, unsigned), width, pad); | ||||
|           break; | ||||
| 
 | ||||
|         case 'x': | ||||
|         case 'X': | ||||
|           count += whisperPrintInt(va_arg(ap, int), width, pad, 16); | ||||
|           break; | ||||
| 
 | ||||
|         case 'o': | ||||
|           count += whisperPrintInt(va_arg(ap, int), width, pad, 8); | ||||
|           break; | ||||
| 
 | ||||
|         case 'c': | ||||
|           whisperPutc(va_arg(ap, int)); | ||||
|           ++count; | ||||
|           break; | ||||
| 
 | ||||
|         case 's': | ||||
|           count += whisperPuts(va_arg(ap, char*)); | ||||
|           break; | ||||
| /*
 | ||||
|         case 'g': | ||||
|           count += whisperPrintDoubleG(va_arg(ap, double)); | ||||
|           break; | ||||
| 
 | ||||
|         case 'f': | ||||
|           count += whisperPrintDoubleF(va_arg(ap, double)); | ||||
| */ | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   return count; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| whisperPrintf(const char* format, ...) | ||||
| { | ||||
|   va_list ap; | ||||
| 
 | ||||
|   va_start(ap, format); | ||||
|   int code = whisperPrintfImpl(format, ap); | ||||
|   va_end(ap); | ||||
| 
 | ||||
|   return code; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| putchar(int c) | ||||
| { | ||||
|   return whisperPutc(c); | ||||
| } | ||||
| 
 | ||||
| struct FILE; | ||||
| 
 | ||||
| int | ||||
| putc(int c, struct FILE* f) | ||||
| { | ||||
|   return whisperPutc(c); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| puts(const char* s) | ||||
| { | ||||
|   return whisperPuts(s); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| printf(const char* format, ...) | ||||
| { | ||||
|   va_list ap; | ||||
| 
 | ||||
|   va_start(ap, format); | ||||
|   int code = whisperPrintfImpl(format, ap); | ||||
|   va_end(ap); | ||||
| 
 | ||||
|   return code; | ||||
| } | ||||
| 
 | ||||
| // function to read cpu mcycle csr for performance measurements
 | ||||
| // simplified version
 | ||||
| uint64_t get_mcycle(){ | ||||
| unsigned int mcyclel; | ||||
| unsigned int mcycleh0 = 0, mcycleh1=1; | ||||
| uint64_t cycles; | ||||
| 
 | ||||
| while(mcycleh0 != mcycleh1) { | ||||
|     asm volatile ("csrr %0,mcycleh"  : "=r" (mcycleh0) ); | ||||
|     asm volatile ("csrr %0,mcycle"   : "=r" (mcyclel)  ); | ||||
|     asm volatile ("csrr %0,mcycleh"  : "=r" (mcycleh1) ); | ||||
| } | ||||
| cycles = mcycleh1; | ||||
| return (cycles << 32) | mcyclel; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,374 @@ | |||
| // 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. | ||||
| // | ||||
| 
 | ||||
| // Run time disassembler functions | ||||
| // supports  RISCV extentions I, C, M | ||||
| 
 | ||||
| bit[31:0] gpr[32]; | ||||
| 
 | ||||
| // main DASM function | ||||
| function string dasm(input[31:0] opcode, input[31:0] pc, input[4:0] regn, input[31:0] regv); | ||||
|     if(regn) gpr[regn] = regv; | ||||
| 
 | ||||
|     if( opcode[1:0] == 2'b11 ) return dasm32(opcode, pc); | ||||
|     else return dasm16(opcode, pc); | ||||
| endfunction | ||||
| 
 | ||||
| 
 | ||||
| ///////////////// 16 bits instructions /////////////////////// | ||||
| 
 | ||||
| function string dasm16( input[31:0] opcode, input[31:0] pc); | ||||
|     case(opcode[1:0]) | ||||
|     0: return dasm16_0(opcode); | ||||
|     1: return dasm16_1(opcode, pc); | ||||
|     2: return dasm16_2(opcode); | ||||
|     endcase | ||||
|     return $sformatf(".short 0x%h", opcode[15:0]); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_0( input[31:0] opcode); | ||||
|     case(opcode[15:13]) | ||||
|     3'b000: return dasm16_ciw(opcode); | ||||
|     3'b001: return {"c.fld", dasm16_cl(opcode)}; | ||||
|     3'b010: return {"c.lw",  dasm16_cl(opcode)}; | ||||
|     3'b011: return {"c.flw", dasm16_cl(opcode)}; | ||||
|     3'b101: return {"c.fsd", dasm16_cl(opcode)}; | ||||
|     3'b110: return {"c.sw",  dasm16_cl(opcode)}; | ||||
|     3'b111: return {"c.fsw", dasm16_cl(opcode)}; | ||||
|     endcase | ||||
|     return $sformatf(".short 0x%h", opcode[15:0]); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_ciw( input[31:0] opcode); | ||||
| int imm; | ||||
|     imm=0; | ||||
|     if(opcode[15:0] == 0) return ".short 0"; | ||||
|     {imm[5:4],imm[9:6],imm[2],imm[3]} = opcode[12:5]; | ||||
|     return $sformatf("c.addi4spn %s, 0x%0h", abi_reg[opcode[4:2]+8], imm); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_cl( input[31:0] opcode); | ||||
| int imm; | ||||
|     imm=0; | ||||
|     imm[5:3] = opcode[12:10]; | ||||
|     imm[7:6] = opcode[6:5]; | ||||
| 
 | ||||
|     return $sformatf(" %s, %0d(%s) [%h]", abi_reg[opcode[4:2]+8], imm, abi_reg[opcode[9:7]+8], gpr[opcode[9:7]+8]+imm); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_1( input[31:0] opcode, input[31:0] pc); | ||||
|     case(opcode[15:13]) | ||||
|     3'b000: return opcode[11:7]==0 ? "c.nop" : {"c.addi",dasm16_ci(opcode)}; | ||||
|     3'b001: return {"c.jal", dasm16_cj(opcode, pc)}; | ||||
|     3'b010: return {"c.li",  dasm16_ci(opcode)}; | ||||
|     3'b011: return dasm16_1_3(opcode); | ||||
|     3'b100: return dasm16_cr(opcode); | ||||
|     3'b101: return {"c.j", dasm16_cj(opcode, pc)}; | ||||
|     3'b110: return {"c.beqz", dasm16_cb(opcode, pc)}; | ||||
|     3'b111: return {"c.bnez", dasm16_cb(opcode, pc)}; | ||||
|     endcase | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_ci( input[31:0] opcode); | ||||
| int imm; | ||||
|     imm=0; | ||||
|     imm[4:0] = opcode[6:2]; | ||||
|     if(opcode[12]) imm [31:5] = '1; | ||||
|     return $sformatf(" %s, %0d", abi_reg[opcode[11:7]], imm); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_cj( input[31:0] opcode, input[31:0] pc); | ||||
| bit[31:0] imm; | ||||
|     imm=0; | ||||
|     {imm[11],imm[4],imm[9:8],imm[10],imm[6], imm[7],imm[3:1], imm[5]} = opcode[12:2]; | ||||
|     if(opcode[12]) imm [31:12] = '1; | ||||
|     return $sformatf(" 0x%h", imm+pc); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_cb( input[31:0] opcode, input[31:0] pc); | ||||
| bit[31:0] imm; | ||||
|     imm=0; | ||||
|     {imm[11],imm[4:3]} = opcode[12:10]; | ||||
|     {imm[7], imm[6],imm[2:1], imm[5]} = opcode[6:2]; | ||||
|     if(opcode[12]) imm [31:9] = '1; | ||||
|     return $sformatf(" %s, 0x%h",abi_reg[opcode[9:7]+8], imm+pc); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_cr( input[31:0] opcode); | ||||
| bit[31:0] imm; | ||||
| 
 | ||||
|     imm = 0; | ||||
|     imm[4:0] = opcode[6:2]; | ||||
|     if(opcode[5]) imm [31:5] = '1; | ||||
|     case(opcode[11:10]) | ||||
|     0: return $sformatf("c.srli %s, %0d",  abi_reg[opcode[9:7]+8], imm[5:0]); | ||||
|     1: return $sformatf("c.srai %s, %0d",  abi_reg[opcode[9:7]+8], imm[5:0]); | ||||
|     2: return $sformatf("c.andi %s, 0x%h", abi_reg[opcode[9:7]+8], imm); | ||||
|     endcase | ||||
| 
 | ||||
|     case(opcode[6:5]) | ||||
|     0: return $sformatf("c.sub %s, %s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]); | ||||
|     1: return $sformatf("c.xor %s, %s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]); | ||||
|     2: return $sformatf("c.or  %s, %s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]); | ||||
|     3: return $sformatf("c.and %s, %s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]); | ||||
|     endcase | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_1_3( input[31:0] opcode); | ||||
| int imm; | ||||
| 
 | ||||
|     imm=0; | ||||
|     if(opcode[11:7] == 2) begin | ||||
|         {imm[4], imm[6],imm[8:7], imm[5]} = opcode[6:2]; | ||||
|         if(opcode[12]) imm [31:9] = '1; | ||||
|         return $sformatf("c.addi16sp %0d", imm); | ||||
|     end | ||||
|     else begin | ||||
|     //    {imm[4], imm[6],imm[8:7], imm[5]} = opcode[6:2]; | ||||
|         imm[16:12] = opcode[6:2]; | ||||
|         if(opcode[12]) imm [31:17] = '1; | ||||
|         return $sformatf("c.lui %3s, 0x%h", abi_reg[opcode[11:7]], imm); | ||||
| 
 | ||||
|     end | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_2( input[31:0] opcode); | ||||
|     case(opcode[15:13]) | ||||
|     3'b000: return {"c.slli",  dasm16_ci(opcode)}; | ||||
|     3'b001: return {"c.fldsp", dasm16_cls(opcode,1)}; | ||||
|     3'b010: return {"c.lwsp",  dasm16_cls(opcode)}; | ||||
|     3'b011: return {"c.flwsp", dasm16_cls(opcode)}; | ||||
|     3'b101: return {"c.fsdsp", dasm16_css(opcode,1)}; | ||||
|     3'b110: return {"c.swsp",  dasm16_css(opcode)}; | ||||
|     3'b111: return {"c.fswsp", dasm16_css(opcode)}; | ||||
|     endcase | ||||
|     if(opcode[12]) begin | ||||
|         if(opcode[12:2] == 0) return "c.ebreak"; | ||||
|         else if(opcode[6:2] == 0) return $sformatf("c.jalr %s", abi_reg[opcode[11:7]]); | ||||
|         else return $sformatf("c.add %s, %s", abi_reg[opcode[11:7]], abi_reg[opcode[6:2]]); | ||||
|     end | ||||
|     else begin | ||||
|         if(opcode[6:2] == 0) return $sformatf("c.jr %s", abi_reg[opcode[11:7]]); | ||||
|         else return $sformatf("c.mv %s, %s", abi_reg[opcode[11:7]], abi_reg[opcode[6:2]]); | ||||
|     end | ||||
| endfunction | ||||
| 
 | ||||
| 
 | ||||
| function string dasm16_cls( input[31:0] opcode, input sh1=0); | ||||
| bit[31:0] imm; | ||||
|     imm=0; | ||||
|     if(sh1) {imm[4:3],imm[8:6]} = opcode[6:2]; | ||||
|     else    {imm[4:2],imm[7:6]} = opcode[6:2]; | ||||
|     imm[5] = opcode[12]; | ||||
|     return $sformatf(" %s, 0x%0h [%h]", abi_reg[opcode[11:7]], imm, gpr[2]+imm); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm16_css( input[31:0] opcode, input sh1=0); | ||||
| bit[31:0] imm; | ||||
|     imm=0; | ||||
|     if(sh1) {imm[5:3],imm[8:6]} = opcode[12:7]; | ||||
|     else {imm[5:2],imm[7:6]} = opcode[12:7]; | ||||
|     return $sformatf(" %s, 0x%0h [%h]", abi_reg[opcode[6:2]], imm, gpr[2]+imm); | ||||
| endfunction | ||||
| 
 | ||||
| ///////////////// 32 bit instructions /////////////////////// | ||||
| 
 | ||||
| function string dasm32( input[31:0] opcode, input[31:0] pc); | ||||
|     case(opcode[6:0]) | ||||
|     7'b0110111: return {"lui",   dasm32_u(opcode)}; | ||||
|     7'b0010111: return {"auipc", dasm32_u(opcode)}; | ||||
|     7'b1101111: return {"jal",   dasm32_j(opcode,pc)}; | ||||
|     7'b1100111: return {"jalr",  dasm32_jr(opcode,pc)}; | ||||
|     7'b1100011: return dasm32_b(opcode,pc); | ||||
|     7'b0000011: return dasm32_l(opcode); | ||||
|     7'b0100011: return dasm32_s(opcode); | ||||
|     7'b0010011: return dasm32_ai(opcode); | ||||
|     7'b0110011: return dasm32_ar(opcode); | ||||
|     7'b0001111: return {"fence", dasm32_fence(opcode)}; | ||||
|     7'b1110011: return dasm32_e(opcode); | ||||
| 
 | ||||
|     endcase | ||||
|     return $sformatf(".long 0x%h", opcode); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_u( input[31:0] opcode); | ||||
| bit[31:0] imm; | ||||
|     imm=0; | ||||
|     imm[31:12] = opcode[31:12]; | ||||
|     return $sformatf(" %s, 0x%0h", abi_reg[opcode[11:7]], imm); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_j( input[31:0] opcode, input[31:0] pc); | ||||
| int imm; | ||||
|     imm=0; | ||||
|     {imm[20], imm[10:1], imm[11], imm[19:12]} = opcode[31:12]; | ||||
|     if(opcode[31]) imm[31:20] = '1; | ||||
|     return $sformatf(" %s, 0x%0h",abi_reg[opcode[11:7]], imm+pc); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_jr( input[31:0] opcode, input[31:0] pc); | ||||
| int imm; | ||||
|     imm=0; | ||||
|     imm[11:1] = opcode[31:19]; | ||||
|     if(opcode[31]) imm[31:12] = '1; | ||||
|     return $sformatf(" %s, %s, 0x%0h",abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm+pc); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_b( input[31:0] opcode, input[31:0] pc); | ||||
| int imm; | ||||
| string mn; | ||||
|     imm=0; | ||||
|     {imm[12],imm[10:5]} = opcode[31:25]; | ||||
|     {imm[4:1],imm[11]} = opcode[11:7]; | ||||
|     if(opcode[31]) imm[31:12] = '1; | ||||
|     case(opcode[14:12]) | ||||
|     0: mn = "beq"; | ||||
|     1: mn = "bne"; | ||||
|     2,3 : return $sformatf(".long 0x%h", opcode); | ||||
|     4: mn = "blt"; | ||||
|     5: mn = "bge"; | ||||
|     6: mn = "bltu"; | ||||
|     7: mn = "bgeu"; | ||||
|     endcase | ||||
|     return $sformatf("%s %s, %s, 0x%0h", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm+pc); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_l( input[31:0] opcode); | ||||
| int imm; | ||||
| string mn; | ||||
|     imm=0; | ||||
|     imm[11:0] = opcode[31:20]; | ||||
|     if(opcode[31]) imm[31:12] = '1; | ||||
|     case(opcode[14:12]) | ||||
|     0: mn = "lb"; | ||||
|     1: mn = "lh"; | ||||
|     2: mn = "lw"; | ||||
|     4: mn = "lbu"; | ||||
|     5: mn = "lhu"; | ||||
|     default : return $sformatf(".long 0x%h", opcode); | ||||
|     endcase | ||||
|     return $sformatf("%s %s, %0d(%s) [%h]", mn, abi_reg[opcode[11:7]], imm, abi_reg[opcode[19:15]], imm+gpr[opcode[19:15]]); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_s( input[31:0] opcode); | ||||
| int imm; | ||||
| string mn; | ||||
|     imm=0; | ||||
|     imm[11:5] = opcode[31:25]; | ||||
|     imm[4:0] = opcode[11:7]; | ||||
|     if(opcode[31]) imm[31:12] = '1; | ||||
|     case(opcode[14:12]) | ||||
|     0: mn = "sb"; | ||||
|     1: mn = "sh"; | ||||
|     2: mn = "sw"; | ||||
|     default : return $sformatf(".long 0x%h", opcode); | ||||
|     endcase | ||||
|     return $sformatf("%s %s, %0d(%s) [%h]", mn, abi_reg[opcode[24:20]], imm, abi_reg[opcode[19:15]], imm+gpr[opcode[19:15]]); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_ai( input[31:0] opcode); | ||||
| int imm; | ||||
| string mn; | ||||
|     imm=0; | ||||
|     imm[11:0] = opcode[31:20]; | ||||
|     if(opcode[31]) imm[31:12] = '1; | ||||
|     case(opcode[14:12]) | ||||
|     0: mn = "addi"; | ||||
|     2: mn = "slti"; | ||||
|     3: mn = "sltiu"; | ||||
|     4: mn = "xori"; | ||||
|     6: mn = "ori"; | ||||
|     7: mn = "andi"; | ||||
|     default: return dasm32_si(opcode); | ||||
| endcase | ||||
| 
 | ||||
| return $sformatf("%s %s, %s, %0d", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_si( input[31:0] opcode); | ||||
| int imm; | ||||
| string mn; | ||||
|     imm = opcode[24:20]; | ||||
|     case(opcode[14:12]) | ||||
|     1: mn = "slli"; | ||||
|     5: mn = opcode[30] ? "srli": "srai"; | ||||
|     endcase | ||||
| 
 | ||||
|     return $sformatf("%s %s, %s, %0d", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm); | ||||
| endfunction | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| function string dasm32_ar( input[31:0] opcode); | ||||
| string mn; | ||||
|     if(opcode[25]) | ||||
|         case(opcode[14:12]) | ||||
|         0: mn = "mul"; | ||||
|         1: mn = "mulh"; | ||||
|         2: mn = "mulhsu"; | ||||
|         3: mn = "mulhu"; | ||||
|         4: mn = "div"; | ||||
|         5: mn = "divu"; | ||||
|         6: mn = "rem"; | ||||
|         7: mn = "remu"; | ||||
|         endcase | ||||
|     else | ||||
|         case(opcode[14:12]) | ||||
|         0: mn = opcode[30]? "sub":"add"; | ||||
|         1: mn = "sll"; | ||||
|         2: mn = "slt"; | ||||
|         3: mn = "sltu"; | ||||
|         4: mn = "xor"; | ||||
|         5: mn = opcode[30]? "sra" :"srl"; | ||||
|         6: mn = "or"; | ||||
|         7: mn = "and"; | ||||
|         endcase | ||||
|     return $sformatf("%s %s, %s, %s", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], abi_reg[opcode[24:20]]); | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_fence( input[31:0] opcode); | ||||
|     return  opcode[12] ? ".i" : ""; | ||||
| endfunction | ||||
| 
 | ||||
| function string dasm32_e(input[31:0] opcode); | ||||
|     if(opcode[31:7] == 0) return "ecall"; | ||||
|     else if({opcode[31:21],opcode [19:7]} == 0) return "ebreak"; | ||||
|     else | ||||
|         case(opcode[14:12]) | ||||
|         1: return {"csrrw", dasm32_csr(opcode)}; | ||||
|         2: return {"csrrs", dasm32_csr(opcode)}; | ||||
|         3: return {"csrrc", dasm32_csr(opcode)}; | ||||
|         5: return {"csrrwi", dasm32_csr(opcode, 1)}; | ||||
|         6: return {"csrrsi", dasm32_csr(opcode, 1)}; | ||||
|         7: return {"csrrci", dasm32_csr(opcode, 1)}; | ||||
|         endcase | ||||
| 
 | ||||
| endfunction | ||||
| 
 | ||||
| 
 | ||||
| function string dasm32_csr(input[31:0] opcode, input im=0); | ||||
| bit[11:0] csr; | ||||
|     csr = opcode[31:20]; | ||||
|     if(im) begin | ||||
|         return $sformatf(" %s, csr_%0h, 0x%h",  abi_reg[opcode[11:7]], csr, opcode[19:15]); | ||||
|     end | ||||
|     else begin | ||||
|         return $sformatf(" %s, csr_%0h, %s",  abi_reg[opcode[11:7]], csr, abi_reg[opcode[19:15]]); | ||||
|     end | ||||
| 
 | ||||
| endfunction | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1,5 +1,7 @@ | |||
| +libext+.v+.sv | ||||
| //-y $SYNOPSYS_SYN_ROOT/dw/sim_ver | ||||
| +define+RV_OPENSOURCE | ||||
| +incdir+$RV_ROOT/testbench | ||||
| $RV_ROOT/design/el2_swerv_wrapper.sv | ||||
| $RV_ROOT/design/el2_mem.sv | ||||
| $RV_ROOT/design/el2_pic_ctrl.sv | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,26 @@ | |||
| @80000000 | ||||
| 73 10 20 B0 73 10 20 B8 B7 00 00 EE 73 90 50 30 | ||||
| B7 50 55 5F 93 80 50 55 73 90 00 7C B7 01 58 D0 | ||||
| 17 02 00 00 13 02 E2 0E 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 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| @8000010E | ||||
| 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 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 45 4C 32 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 2D 2D 2D 2D 0A 00 | ||||
|  | @ -0,0 +1,28 @@ | |||
| @00000000 | ||||
| 73 10 20 B0 73 10 20 B8 B7 00 00 EE 73 90 50 30 | ||||
| B7 50 55 5F 93 80 50 55 73 90 00 7C B7 01 58 D0 | ||||
| 17 02 04 F0 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 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| @F0040000 | ||||
| 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 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 45 4C 32 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 2D 2D 2D 2D 0A 00 | ||||
| @FFFFFFF8 | ||||
| 00 00 04 F0 70 10 04 F0 | ||||
|  | @ -0,0 +1,32 @@ | |||
| @00000000 | ||||
| B7 50 55 5F 93 80 50 55 73 90 00 7C 91 41 73 90 | ||||
| 91 7F B7 01 00 EE 17 02 01 00 13 02 62 06 97 02 | ||||
| 01 00 93 82 E2 08 03 23 02 00 23 A0 61 00 11 02 | ||||
| 91 01 E3 6A 52 FE 0F 10 00 00 97 00 00 EE E7 80 | ||||
| 60 FC B7 01 58 D0 93 02 F0 0F 23 80 51 00 E3 0A | ||||
| 00 FE 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 | ||||
| 01 00 01 00 01 00 01 00 01 00 | ||||
| @00010000 | ||||
| 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 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 | ||||
| 45 4C 32 20 49 43 43 4D 20 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 | ||||
| 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 0A 00 | ||||
| @0001007C | ||||
| B7 01 58 D0 17 02 01 12 13 02 C2 FF 83 02 02 00 | ||||
| 23 80 51 00 05 02 E3 9B 02 FE 82 80 00 00 00 00 | ||||
| 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 | ||||
|  | @ -1,4 +1,4 @@ | |||
| database -open waves -into waves.shm -default | ||||
| probe -create tb_top -depth all -database waves | ||||
| probe -create tb_top -depth all -database waves -memories -all | ||||
| run | ||||
| exit | ||||
|  |  | |||
|  | @ -0,0 +1,209 @@ | |||
| // See LICENSE.Berkeley for license details.
 | ||||
| 
 | ||||
| #include <arpa/inet.h> | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cassert> | ||||
| #include <cstdio> | ||||
| #include <cstdlib> | ||||
| 
 | ||||
| #include "remote_bitbang.h" | ||||
| 
 | ||||
| /////////// remote_bitbang_t
 | ||||
| 
 | ||||
| remote_bitbang_t::remote_bitbang_t(uint16_t port) : | ||||
|   err(0), | ||||
|   socket_fd(0), | ||||
|   client_fd(0), | ||||
|   recv_start(0), | ||||
|   recv_end(0) | ||||
| { | ||||
|   socket_fd = socket(AF_INET, SOCK_STREAM, 0); | ||||
|   if (socket_fd == -1) { | ||||
|     fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n", | ||||
|             strerror(errno), errno); | ||||
|     abort(); | ||||
|   } | ||||
| 
 | ||||
|   fcntl(socket_fd, F_SETFL, O_NONBLOCK); | ||||
|   int reuseaddr = 1; | ||||
|   if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, | ||||
|                  sizeof(int)) == -1) { | ||||
|     fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n", | ||||
|             strerror(errno), errno); | ||||
|     abort(); | ||||
|   } | ||||
| 
 | ||||
|   struct sockaddr_in addr; | ||||
|   memset(&addr, 0, sizeof(addr)); | ||||
|   addr.sin_family = AF_INET; | ||||
|   addr.sin_addr.s_addr = INADDR_ANY; | ||||
|   addr.sin_port = htons(port); | ||||
| 
 | ||||
|   if (::bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) { | ||||
|     fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n", | ||||
|             strerror(errno), errno); | ||||
|     abort(); | ||||
|   } | ||||
| 
 | ||||
|   if (listen(socket_fd, 1) == -1) { | ||||
|     fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n", | ||||
|             strerror(errno), errno); | ||||
|     abort(); | ||||
|   } | ||||
| 
 | ||||
|   socklen_t addrlen = sizeof(addr); | ||||
|   if (getsockname(socket_fd, (struct sockaddr *) &addr, &addrlen) == -1) { | ||||
|     fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n", | ||||
|             strerror(errno), errno); | ||||
|     abort(); | ||||
|   } | ||||
| 
 | ||||
|   tck = 1; | ||||
|   tms = 1; | ||||
|   tdi = 1; | ||||
|   trstn = 1; | ||||
|   quit = 0; | ||||
|   srstn = 1; | ||||
| 
 | ||||
|   fprintf(stderr, "This emulator compiled with JTAG Remote Bitbang client. To enable, use +jtag_rbb_enable=1.\n"); | ||||
|   fprintf(stderr, "Listening on port %d\n", | ||||
|          ntohs(addr.sin_port)); | ||||
| } | ||||
| 
 | ||||
| void remote_bitbang_t::accept() | ||||
| { | ||||
| 
 | ||||
|   fprintf(stderr,"Attempting to accept client socket\n"); | ||||
|   int again = 1; | ||||
|   while (again != 0) { | ||||
|     client_fd = ::accept(socket_fd, NULL, NULL); | ||||
|     if (client_fd == -1) { | ||||
|       if (errno == EAGAIN) { | ||||
|         // No client waiting to connect right now.
 | ||||
|       } else { | ||||
|         fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno), | ||||
|                 errno); | ||||
|         again = 0; | ||||
|         abort(); | ||||
|       } | ||||
|     } else { | ||||
|       fcntl(client_fd, F_SETFL, O_NONBLOCK); | ||||
|       fprintf(stderr, "Accepted successfully."); | ||||
|       again = 0; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void remote_bitbang_t::tick( | ||||
|                             unsigned char * jtag_tck, | ||||
|                             unsigned char * jtag_tms, | ||||
|                             unsigned char * jtag_tdi, | ||||
|                             unsigned char * jtag_trstn, | ||||
|                             unsigned char * sysrstn, | ||||
|                             unsigned char jtag_tdo | ||||
|                             ) | ||||
| { | ||||
|   if (client_fd > 0) { | ||||
|     tdo = jtag_tdo; | ||||
|     execute_command(); | ||||
|   } else { | ||||
|     this->accept(); | ||||
|   } | ||||
| 
 | ||||
|   * jtag_tck = tck; | ||||
|   * jtag_tms = tms; | ||||
|   * jtag_tdi = tdi; | ||||
|   * jtag_trstn = trstn; | ||||
|   * sysrstn = srstn; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void remote_bitbang_t::reset(char cmd){ | ||||
|   trstn = ((cmd - 'r') & 2) ? 0 : 1; | ||||
|   srstn = ((cmd - 'r') & 1) ? 0 : 1; | ||||
| } | ||||
| 
 | ||||
| void remote_bitbang_t::set_pins(char _tck, char _tms, char _tdi){ | ||||
|   tck = _tck; | ||||
|   tms = _tms; | ||||
|   tdi = _tdi; | ||||
| } | ||||
| 
 | ||||
| void remote_bitbang_t::execute_command() | ||||
| { | ||||
|   char command; | ||||
|   int again = 1; | ||||
|   while (again) { | ||||
|     ssize_t num_read = read(client_fd, &command, sizeof(command)); | ||||
|     if (num_read == -1) { | ||||
|       if (errno == EAGAIN) { | ||||
|         // We'll try again the next call.
 | ||||
|         //fprintf(stderr, "Received no command. Will try again on the next call\n");
 | ||||
|       } else { | ||||
|         fprintf(stderr, "remote_bitbang failed to read on socket: %s (%d)\n", | ||||
|                 strerror(errno), errno); | ||||
|         again = 0; | ||||
|         abort(); | ||||
|       } | ||||
|     } else if (num_read == 0) { | ||||
|       fprintf(stderr, "No Command Received.\n"); | ||||
|       again = 1; | ||||
|     } else { | ||||
|       again = 0; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   //fprintf(stderr, "Received a command %c\n", command);
 | ||||
| 
 | ||||
|   int dosend = 0; | ||||
| 
 | ||||
|   char tosend = '?'; | ||||
| 
 | ||||
|   switch (command) { | ||||
|   case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break; | ||||
|   case 'b': /* fprintf(stderr, "_______\n"); */ break; | ||||
|   case 'r': | ||||
|   case 's': | ||||
|   case 'u': | ||||
|   case 't': reset(command); break; | ||||
|   case '0': set_pins(0, 0, 0); break; | ||||
|   case '1': set_pins(0, 0, 1); break; | ||||
|   case '2': set_pins(0, 1, 0); break; | ||||
|   case '3': set_pins(0, 1, 1); break; | ||||
|   case '4': set_pins(1, 0, 0); break; | ||||
|   case '5': set_pins(1, 0, 1); break; | ||||
|   case '6': set_pins(1, 1, 0); break; | ||||
|   case '7': set_pins(1, 1, 1); break; | ||||
|   case 'R': dosend = 1; tosend = tdo ? '1' : '0'; break; | ||||
|   case 'Q': quit = 1; break; | ||||
|   default: | ||||
|     fprintf(stderr, "remote_bitbang got unsupported command '%c'\n", | ||||
|             command); | ||||
|   } | ||||
| 
 | ||||
|   if (dosend){ | ||||
|     while (1) { | ||||
|       ssize_t bytes = write(client_fd, &tosend, sizeof(tosend)); | ||||
|       if (bytes == -1) { | ||||
|         fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno); | ||||
|         abort(); | ||||
|       } | ||||
|       if (bytes > 0) { | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (quit) { | ||||
|     // The remote disconnected.
 | ||||
|     fprintf(stderr, "Remote end disconnected\n"); | ||||
|     close(client_fd); | ||||
|     client_fd = 0; | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,61 @@ | |||
| // See LICENSE.Berkeley for license details.
 | ||||
| 
 | ||||
| #ifndef REMOTE_BITBANG_H | ||||
| #define REMOTE_BITBANG_H | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| class remote_bitbang_t | ||||
| { | ||||
| public: | ||||
|   // Create a new server, listening for connections from localhost on the given
 | ||||
|   // port.
 | ||||
|   remote_bitbang_t(uint16_t port); | ||||
| 
 | ||||
|   // Do a bit of work.
 | ||||
|   void tick(unsigned char * jtag_tck, | ||||
|             unsigned char * jtag_tms, | ||||
|             unsigned char * jtag_tdi, | ||||
|             unsigned char * jtag_trstn, | ||||
|             unsigned char * sysrstn, | ||||
|             unsigned char jtag_tdo); | ||||
| 
 | ||||
|   unsigned char done() {return quit;} | ||||
| 
 | ||||
|   int exit_code() {return err;} | ||||
| 
 | ||||
|  private: | ||||
| 
 | ||||
|   int err; | ||||
| 
 | ||||
|   unsigned char tck; | ||||
|   unsigned char tms; | ||||
|   unsigned char tdi; | ||||
|   unsigned char trstn; | ||||
|   unsigned char srstn; | ||||
|   unsigned char tdo; | ||||
|   unsigned char quit; | ||||
| 
 | ||||
|   int socket_fd; | ||||
|   int client_fd; | ||||
| 
 | ||||
|   static const ssize_t buf_size = 64 * 1024; | ||||
|   char recv_buf[buf_size]; | ||||
|   ssize_t recv_start, recv_end; | ||||
| 
 | ||||
|   // Check for a client connecting, and accept if there is one.
 | ||||
|   void accept(); | ||||
|   // Execute any commands the client has for us.
 | ||||
|   // But we only execute 1 because we need time for the
 | ||||
|   // simulation to run.
 | ||||
|   void execute_command(); | ||||
| 
 | ||||
|   // Reset. .
 | ||||
|   void reset(char cmd); | ||||
| 
 | ||||
|   void set_pins(char _tck, char _tms, char _tdi); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  | @ -13,10 +13,13 @@ | |||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| //
 | ||||
| `ifdef VERILATOR | ||||
| module tb_top ( input bit core_clk ); | ||||
| `else | ||||
| `ifndef VERILATOR | ||||
| module tb_top; | ||||
| `else | ||||
| module tb_top ( input bit core_clk ); | ||||
| `endif | ||||
| 
 | ||||
| `ifndef VERILATOR | ||||
|     bit                         core_clk; | ||||
| `endif | ||||
|     logic                       rst_l; | ||||
|  | @ -27,48 +30,48 @@ module tb_top; | |||
|     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]         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]         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        [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]         sb_hrdata       ; | ||||
|     logic        [63:0]         sb_hwdata       ; | ||||
|     logic                       sb_hready       ; | ||||
|     logic                       sb_hresp        ; | ||||
| 
 | ||||
|     logic        [31:0]         trace_rv_i_insn_ip; | ||||
|     logic        [31:0]         trace_rv_i_address_ip; | ||||
|     logic        [1:0]          trace_rv_i_valid_ip; | ||||
|     logic        [1:0]          trace_rv_i_exception_ip; | ||||
|     logic                       trace_rv_i_valid_ip; | ||||
|     logic                       trace_rv_i_exception_ip; | ||||
|     logic        [4:0]          trace_rv_i_ecause_ip; | ||||
|     logic        [1:0]          trace_rv_i_interrupt_ip; | ||||
|     logic                       trace_rv_i_interrupt_ip; | ||||
|     logic        [31:0]         trace_rv_i_tval_ip; | ||||
| 
 | ||||
|     logic                       o_debug_mode_status; | ||||
|  | @ -80,10 +83,10 @@ module tb_top; | |||
|     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        [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; | ||||
|  | @ -92,15 +95,15 @@ module tb_top; | |||
|     logic                       mpc_debug_run_ack; | ||||
|     logic                       debug_brkpt_status; | ||||
| 
 | ||||
|     bit        [31:0]           cycleCnt; | ||||
|     int                         cycleCnt; | ||||
|     logic                       mailbox_data_val; | ||||
| 
 | ||||
|     wire                        dma_hready_out; | ||||
|     int                         commit_count; | ||||
| 
 | ||||
|     logic                       wb_valid[1:0]; | ||||
|     logic [4:0]                 wb_dest[1:0]; | ||||
|     logic [31:0]                wb_data[1:0]; | ||||
|     logic                       wb_valid; | ||||
|     logic [4:0]                 wb_dest; | ||||
|     logic [31:0]                wb_data; | ||||
| 
 | ||||
| `ifdef RV_BUILD_AXI4 | ||||
|    //-------------------------- LSU AXI signals--------------------------
 | ||||
|  | @ -307,6 +310,7 @@ module tb_top; | |||
| 
 | ||||
| `endif | ||||
|     wire[63:0] WriteData; | ||||
|     string                      abi_reg[32]; // ABI register names
 | ||||
| 
 | ||||
| 
 | ||||
|     assign mailbox_write = lmem.mailbox_write; | ||||
|  | @ -345,40 +349,75 @@ module tb_top; | |||
| 
 | ||||
|     // trace monitor
 | ||||
|     always @(posedge core_clk) begin | ||||
|         wb_valid[0]  <= rvtop.swerv.dec.dec_i0_wen_r; | ||||
|         wb_dest[0]   <= rvtop.swerv.dec.dec_i0_waddr_r; | ||||
|         wb_data[0]   <= rvtop.swerv.dec.dec_i0_wdata_r; | ||||
|         if (trace_rv_i_valid_ip !== 0) begin | ||||
|         wb_valid  <= rvtop.swerv.dec.dec_i0_wen_r; | ||||
|         wb_dest   <= rvtop.swerv.dec.dec_i0_waddr_r; | ||||
|         wb_data   <= rvtop.swerv.dec.dec_i0_wdata_r; | ||||
|         if (trace_rv_i_valid_ip) begin | ||||
|            $fwrite(tp,"%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", trace_rv_i_valid_ip, 0, trace_rv_i_address_ip, | ||||
|                   0, trace_rv_i_insn_ip,trace_rv_i_exception_ip,trace_rv_i_ecause_ip, | ||||
|                   trace_rv_i_tval_ip,trace_rv_i_interrupt_ip); | ||||
|            // Basic trace - no exception register updates
 | ||||
|            // #1 0 ee000000 b0201073 c 0b02       00000000
 | ||||
|            for (int i=0; i<1; i++) | ||||
|                if (trace_rv_i_valid_ip[i]==1) begin | ||||
|                    commit_count++; | ||||
|                    $fwrite (el, "%10d : %6s 0 %h %h %s\n", cycleCnt, $sformatf("#%0d",commit_count), | ||||
|                           trace_rv_i_address_ip[31+i*32 -:32], trace_rv_i_insn_ip[31+i*32-:32], | ||||
|                           (wb_dest[i] !=0 && wb_data[0])?  $sformatf("r%0d=%h", wb_dest[i], wb_data[i]) : ""); | ||||
|                end | ||||
|            commit_count++; | ||||
|            $fwrite (el, "%10d : %8s 0 %h %h%13s ; %s\n", cycleCnt, $sformatf("#%0d",commit_count), | ||||
|                         trace_rv_i_address_ip, trace_rv_i_insn_ip, | ||||
|                         (wb_dest !=0 && wb_valid)?  $sformatf("%s=%h", abi_reg[wb_dest], wb_data) : "             ", | ||||
|                         dasm(trace_rv_i_insn_ip, trace_rv_i_address_ip, wb_dest & {5{wb_valid}}, wb_data) | ||||
|                    ); | ||||
|         end | ||||
|         if(rvtop.swerv.dec.dec_nonblock_load_wen) | ||||
|            $fwrite (el, "%10d : %32s=%h ; nbL\n", cycleCnt, abi_reg[rvtop.swerv.dec.dec_nonblock_load_waddr], rvtop.swerv.dec.lsu_nonblock_load_data); | ||||
|         if(rvtop.swerv.dec.exu_div_wren) | ||||
|            $fwrite (el, "%10d : %32s=%h ; nbD\n", cycleCnt, abi_reg[rvtop.swerv.dec.div_waddr_wb], rvtop.swerv.dec.exu_div_result); | ||||
|     end | ||||
| 
 | ||||
| 
 | ||||
|     initial begin | ||||
|         abi_reg[0] = "zero"; | ||||
|         abi_reg[1] = "ra"; | ||||
|         abi_reg[2] = "sp"; | ||||
|         abi_reg[3] = "gp"; | ||||
|         abi_reg[4] = "tp"; | ||||
|         abi_reg[5] = "t0"; | ||||
|         abi_reg[6] = "t1"; | ||||
|         abi_reg[7] = "t2"; | ||||
|         abi_reg[8] = "s0"; | ||||
|         abi_reg[9] = "s1"; | ||||
|         abi_reg[10] = "a0"; | ||||
|         abi_reg[11] = "a1"; | ||||
|         abi_reg[12] = "a2"; | ||||
|         abi_reg[13] = "a3"; | ||||
|         abi_reg[14] = "a4"; | ||||
|         abi_reg[15] = "a5"; | ||||
|         abi_reg[16] = "a6"; | ||||
|         abi_reg[17] = "a7"; | ||||
|         abi_reg[18] = "s2"; | ||||
|         abi_reg[19] = "s3"; | ||||
|         abi_reg[20] = "s4"; | ||||
|         abi_reg[21] = "s5"; | ||||
|         abi_reg[22] = "s6"; | ||||
|         abi_reg[23] = "s7"; | ||||
|         abi_reg[24] = "s8"; | ||||
|         abi_reg[25] = "s9"; | ||||
|         abi_reg[26] = "s10"; | ||||
|         abi_reg[27] = "s11"; | ||||
|         abi_reg[28] = "t3"; | ||||
|         abi_reg[29] = "t4"; | ||||
|         abi_reg[30] = "t5"; | ||||
|         abi_reg[31] = "t6"; | ||||
|     // tie offs
 | ||||
|         jtag_id[31:28] = 4'b1; | ||||
|         jtag_id[27:12] = '0; | ||||
|         jtag_id[11:1]  = 11'h45; | ||||
|         reset_vector = 32'h0; | ||||
|         reset_vector = `RV_RESET_VEC; | ||||
|         nmi_vector   = 32'hee000000; | ||||
|         nmi_int   = 0; | ||||
| 
 | ||||
|         $readmemh("data.hex",     lmem.mem); | ||||
|         $readmemh("program.hex",  lmem.mem); | ||||
|         $readmemh("program.hex",  imem.mem); | ||||
|         tp = $fopen("trace_port.csv","w"); | ||||
|         el = $fopen("exec.log","w"); | ||||
|         $fwrite (el, "//Cycle : #inst 0  pc opcode reg regnum value\n"); | ||||
|         $fwrite (el, "//   Cycle : #inst    0    pc    opcode    reg=value   ; mnemonic\n"); | ||||
|         fd = $fopen("console.log","w"); | ||||
|         commit_count = 0; | ||||
|         preload_dccm(); | ||||
|  | @ -691,6 +730,12 @@ el2_swerv_wrapper rvtop ( | |||
|     .dec_tlu_perfcnt2       (), | ||||
|     .dec_tlu_perfcnt3       (), | ||||
| 
 | ||||
| // remove mems DFT pins for opensource
 | ||||
|     .dccm_ext_in_pkt        ('0), | ||||
|     .iccm_ext_in_pkt        ('0), | ||||
|     .ic_data_ext_in_pkt     ('0), | ||||
|     .ic_tag_ext_in_pkt      ('0), | ||||
| 
 | ||||
|     .soft_int               ('0), | ||||
|     .core_id                ('0), | ||||
|     .scan_mode              ( 1'b0 ),         // To enable scan mode
 | ||||
|  | @ -900,16 +945,15 @@ axi_lsu_dma_bridge # (`RV_LSU_BUS_TAG,`RV_LSU_BUS_TAG ) bridge( | |||
| 
 | ||||
| task preload_iccm; | ||||
| bit[31:0] data; | ||||
| bit[31:0] addr, eaddr, saddr, faddr; | ||||
| int adr; | ||||
| bit[31:0] addr, eaddr, saddr; | ||||
| 
 | ||||
| /* | ||||
| addresses: | ||||
|  0xffec - ICCM start address to load | ||||
|  0xfff0 - ICCM end address to load | ||||
|  0xfff4 - imem start address | ||||
|  0xfffffff0 - ICCM start address to load | ||||
|  0xfffffff4 - ICCM end address to load | ||||
| */ | ||||
| 
 | ||||
| addr = 'hffec; | ||||
| addr = 'hffff_fff0; | ||||
| saddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; | ||||
| if ( (saddr < `RV_ICCM_SADR) || (saddr > `RV_ICCM_EADR)) return; | ||||
| `ifndef RV_ICCM_ENABLE | ||||
|  | @ -918,54 +962,50 @@ if ( (saddr < `RV_ICCM_SADR) || (saddr > `RV_ICCM_EADR)) return; | |||
|     $display("********************************************************"); | ||||
|     $finish; | ||||
| `endif | ||||
| init_iccm; | ||||
| addr = 'hfff0; | ||||
| addr += 4; | ||||
| eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; | ||||
| addr = 'hfff4; | ||||
| faddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; | ||||
| $display("ICCM pre-load from %h to %h", saddr, eaddr); | ||||
| 
 | ||||
| for(addr= saddr; addr <= eaddr; addr+=4) begin | ||||
|     adr = faddr & 'hffff; | ||||
|     data = {imem.mem[adr+3],imem.mem[adr+2],imem.mem[adr+1],imem.mem[adr]}; | ||||
|     data = {imem.mem[addr+3],imem.mem[addr+2],imem.mem[addr+1],imem.mem[addr]}; | ||||
|     slam_iccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data}); | ||||
|     faddr+=4; | ||||
| end | ||||
| 
 | ||||
| endtask | ||||
| 
 | ||||
| 
 | ||||
| task preload_dccm; | ||||
| bit[31:0] data; | ||||
| bit[31:0] addr, eaddr; | ||||
| int adr; | ||||
| bit[31:0] addr, saddr, eaddr; | ||||
| 
 | ||||
| /* | ||||
| addresses: | ||||
|  0xfff8 - DCCM start address to load | ||||
|  0xfffc - ICCM end address to load | ||||
|  0x0    - lmem start addres to load from | ||||
|  0xffff_fff8 - DCCM start address to load | ||||
|  0xffff_fffc - DCCM end address to load | ||||
| */ | ||||
| 
 | ||||
| addr = 'hfff8; | ||||
| eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; | ||||
| if (eaddr != `RV_DCCM_SADR) return; | ||||
| addr = 'hffff_fff8; | ||||
| saddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; | ||||
| if (saddr < `RV_DCCM_SADR || saddr > `RV_DCCM_EADR) return; | ||||
| `ifndef RV_DCCM_ENABLE | ||||
|     $display("********************************************************"); | ||||
|     $display("DCCM preload: there is no DCCM in SweRV, terminating !!!"); | ||||
|     $display("********************************************************"); | ||||
|     $finish; | ||||
| `endif | ||||
| addr = 'hfffc; | ||||
| addr += 4; | ||||
| eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; | ||||
| $display("DCCM pre-load from %h to %h", `RV_DCCM_SADR, eaddr); | ||||
| $display("DCCM pre-load from %h to %h", saddr, eaddr); | ||||
| 
 | ||||
| for(addr=`RV_DCCM_SADR; addr <= eaddr; addr+=4) begin | ||||
|     adr = addr & 'hffff; | ||||
|     data = {lmem.mem[adr+3],lmem.mem[adr+2],lmem.mem[adr+1],lmem.mem[adr]}; | ||||
| for(addr=saddr; addr <= eaddr; addr+=4) begin | ||||
|     data = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; | ||||
|     slam_dccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data}); | ||||
| end | ||||
| 
 | ||||
| endtask | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| `define ICCM_PATH `RV_TOP.mem.iccm.iccm | ||||
| `ifdef VERILATOR | ||||
| `define DRAM(bk) rvtop.mem.Gen_dccm_enable.dccm.mem_bank[bk].ram.ram_core | ||||
|  | @ -1116,5 +1156,8 @@ function int get_iccm_bank(input[31:0] addr,  output int bank_idx); | |||
| `endif | ||||
| endfunction | ||||
| 
 | ||||
| /* verilator lint_off CASEINCOMPLETE */ | ||||
| `include "dasm.svi" | ||||
| /* verilator lint_on CASEINCOMPLETE */ | ||||
| 
 | ||||
| endmodule | ||||
|  |  | |||
|  | @ -0,0 +1,14 @@ | |||
| export TEST = cmark | ||||
| #export CONF_PARAMS= -set=btb_size=512 -set=bht_size=2048 -set=iccm_size=128
 | ||||
| export CONF_PARAMS= -set=btb_size=512 -set=bht_size=2048 -set=iccm_enable=0 | ||||
| export OFILES = crt0.o cmark.o printf.o  | ||||
| export BUILD_PATH = $(shell pwd)/snapshots/default | ||||
| export TEST_CFLAGS = -finline-limit=400 -mbranch-cost=1 -Ofast -fno-code-hoisting -funroll-all-loops | ||||
| 
 | ||||
| program.hex: | ||||
| 	$(MAKE) -e -f $(RV_ROOT)/tools/make.common $(BUILD_PATH)/defines.h | ||||
| 	$(MAKE) -e -f $(RV_ROOT)/tools/make.common $@ | ||||
| 
 | ||||
| .DEFAULT: | ||||
| 	$(MAKE) -e program.hex | ||||
| 	$(MAKE) -e -f $(RV_ROOT)/tools/make.common $@ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,262 @@ | |||
| #include <stdarg.h> | ||||
| #include "defines.h" | ||||
| 
 | ||||
| static int | ||||
| whisperPutc(char c) | ||||
| { | ||||
| //  __whisper_console_io = c;
 | ||||
| //  __whisper_console_io = c;
 | ||||
|   *(volatile char*)(RV_SERIALIO) = c; | ||||
|   return c; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPuts(const char* s) | ||||
| { | ||||
|   while (*s) | ||||
|     whisperPutc(*s++); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPrintUnsigned(unsigned value, int width, char pad) | ||||
| { | ||||
|   char buffer[20]; | ||||
|   int charCount = 0; | ||||
| 
 | ||||
|   do | ||||
|     { | ||||
|       char c = '0' + (value % 10); | ||||
|       value = value / 10; | ||||
|       buffer[charCount++] = c; | ||||
|     } | ||||
|   while (value); | ||||
| 
 | ||||
|   for (int i = charCount; i < width; ++i) | ||||
|     whisperPutc(pad); | ||||
| 
 | ||||
|   char* p = buffer + charCount - 1; | ||||
|   for (int i = 0; i < charCount; ++i) | ||||
|     whisperPutc(*p--); | ||||
| 
 | ||||
|   return charCount; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPrintDecimal(int value, int width, char pad) | ||||
| { | ||||
|   char buffer[20]; | ||||
|   int charCount = 0; | ||||
| 
 | ||||
|   unsigned neg = value < 0; | ||||
|   if (neg) | ||||
|     { | ||||
|       value = -value; | ||||
|       whisperPutc('-'); | ||||
|       width--; | ||||
|     } | ||||
| 
 | ||||
|   do | ||||
|     { | ||||
|       char c = '0' + (value % 10); | ||||
|       value = value / 10; | ||||
|       buffer[charCount++] = c; | ||||
|     } | ||||
|   while (value); | ||||
| 
 | ||||
|   for (int i = charCount; i < width; ++i) | ||||
|     whisperPutc(pad); | ||||
| 
 | ||||
|   char* p = buffer + charCount - 1; | ||||
|   for (int i = 0; i < charCount; ++i) | ||||
|     whisperPutc(*p--); | ||||
| 
 | ||||
|   if (neg) | ||||
|     charCount++; | ||||
| 
 | ||||
|   return charCount; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| whisperPrintInt(int value, int width, int pad, int base) | ||||
| { | ||||
|   if (base == 10) | ||||
|     return whisperPrintDecimal(value, width, pad); | ||||
| 
 | ||||
|   char buffer[20]; | ||||
|   int charCount = 0; | ||||
| 
 | ||||
|   unsigned uu = value; | ||||
| 
 | ||||
|   if (base == 8) | ||||
|     { | ||||
|       do | ||||
|         { | ||||
|           char c = '0' + (uu & 7); | ||||
|           buffer[charCount++] = c; | ||||
|           uu >>= 3; | ||||
|         } | ||||
|       while (uu); | ||||
|     } | ||||
|   else if (base == 16) | ||||
|     { | ||||
|       do | ||||
|         { | ||||
|           int digit = uu & 0xf; | ||||
|           char c = digit < 10 ? '0' + digit : 'a' + digit - 10; | ||||
|           buffer[charCount++] = c; | ||||
|           uu >>= 4; | ||||
|         } | ||||
|       while (uu); | ||||
|     } | ||||
|   else | ||||
|     return -1; | ||||
| 
 | ||||
|   char* p = buffer + charCount - 1; | ||||
|   for (unsigned i = 0; i < charCount; ++i) | ||||
|     whisperPutc(*p--); | ||||
| 
 | ||||
|   return charCount; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| // Print with g format
 | ||||
| static int | ||||
| whisperPrintDoubleG(double value) | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // Print with f format
 | ||||
| static int | ||||
| whisperPrintDoubleF(double value) | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| whisperPrintfImpl(const char* format, va_list ap) | ||||
| { | ||||
|   int count = 0;  // Printed character count
 | ||||
| 
 | ||||
|   for (const char* fp = format; *fp; fp++) | ||||
|     { | ||||
|       char pad = ' '; | ||||
|       int width = 0;  // Field width
 | ||||
| 
 | ||||
|       if (*fp != '%') | ||||
|         { | ||||
|           whisperPutc(*fp); | ||||
|           ++count; | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|       ++fp;  // Skip %
 | ||||
| 
 | ||||
|       if (*fp == 0) | ||||
|         break; | ||||
| 
 | ||||
|       if (*fp == '%') | ||||
|         { | ||||
|           whisperPutc('%'); | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|       while (*fp == '0') | ||||
|         { | ||||
|           pad = '0'; | ||||
|           fp++;  // Pad zero not yet implented.
 | ||||
|         } | ||||
| 
 | ||||
|       if (*fp == '-') | ||||
|         { | ||||
|           fp++;  // Pad right not yet implemented.
 | ||||
|         } | ||||
| 
 | ||||
|       if (*fp == '*') | ||||
|         { | ||||
|           int outWidth = va_arg(ap, int); | ||||
|           fp++;  // Width not yet implemented.
 | ||||
|         } | ||||
|       else if (*fp >= '0' && *fp <= '9') | ||||
|         {    // Width not yet implemented.
 | ||||
|           while (*fp >= '0' && *fp <= '9') | ||||
|             width = width * 10 + (*fp++ - '0'); | ||||
|         } | ||||
| 
 | ||||
|       switch (*fp) | ||||
|         { | ||||
|         case 'd': | ||||
|           count += whisperPrintDecimal(va_arg(ap, int), width, pad); | ||||
|           break; | ||||
| 
 | ||||
|         case 'u': | ||||
|           count += whisperPrintUnsigned((unsigned) va_arg(ap, unsigned), width, pad); | ||||
|           break; | ||||
| 
 | ||||
|         case 'x': | ||||
|         case 'X': | ||||
|           count += whisperPrintInt(va_arg(ap, int), width, pad, 16); | ||||
|           break; | ||||
| 
 | ||||
|         case 'o': | ||||
|           count += whisperPrintInt(va_arg(ap, int), width, pad, 8); | ||||
|           break; | ||||
| 
 | ||||
|         case 'c': | ||||
|           whisperPutc(va_arg(ap, int)); | ||||
|           ++count; | ||||
|           break; | ||||
| 
 | ||||
|         case 's': | ||||
|           count += whisperPuts(va_arg(ap, char*)); | ||||
|           break; | ||||
| 
 | ||||
| #if 0 | ||||
|         case 'g': | ||||
|           count += whisperPrintDoubleG(va_arg(ap, double)); | ||||
|           break; | ||||
| 
 | ||||
|         case 'f': | ||||
|           count += whisperPrintDoubleF(va_arg(ap, double)); | ||||
| #endif | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   return count; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| whisperPrintf(const char* format, ...) | ||||
| { | ||||
|   va_list ap; | ||||
| 
 | ||||
|   va_start(ap, format); | ||||
|   int code = whisperPrintfImpl(format, ap); | ||||
|   va_end(ap); | ||||
| 
 | ||||
|   return code; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| printf(const char* format, ...) | ||||
| { | ||||
|   va_list ap; | ||||
| 
 | ||||
|   va_start(ap, format); | ||||
|   int code = whisperPrintfImpl(format, ap); | ||||
|   va_end(ap); | ||||
| 
 | ||||
|   return code; | ||||
| } | ||||
|  | @ -0,0 +1,7 @@ | |||
| This is dhrystone, compiled according to the spec: | ||||
|  1. Files dhry_1.c and dhry2_.c compiled separately. | ||||
|  2. No inlining. | ||||
|  to run in demo TB: | ||||
| 
 | ||||
|   make -f $RV_ROOT/tools/Makefile [<simulator>] TEST=dhry | ||||
| 
 | ||||
|  | @ -0,0 +1 @@ | |||
| ../../asm/crt0.s | ||||
|  | @ -0,0 +1,437 @@ | |||
| #pragma once | ||||
| 
 | ||||
| /*
 | ||||
|  **************************************************************************** | ||||
|  * | ||||
|  *                   "DHRYSTONE" Benchmark Program | ||||
|  *                   ----------------------------- | ||||
|  * | ||||
|  *  Version:    C, Version 2.1 | ||||
|  * | ||||
|  *  File:       dhry.h (part 1 of 3) | ||||
|  * | ||||
|  *  Date:       May 25, 1988 | ||||
|  * | ||||
|  *  Author:     Reinhold P. Weicker | ||||
|  *                      Siemens AG, E STE 35 | ||||
|  *                      Postfach 3240 | ||||
|  *                      8520 Erlangen | ||||
|  *                      Germany (West) | ||||
|  *                              Phone:  [xxx-49]-9131-7-20330 | ||||
|  *                                      (8-17 Central European Time) | ||||
|  *                              Usenet: ..!mcvax!unido!estevax!weicker | ||||
|  * | ||||
|  *              Original Version (in Ada) published in | ||||
|  *              "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), | ||||
|  *              pp. 1013 - 1030, together with the statistics | ||||
|  *              on which the distribution of statements etc. is based. | ||||
|  * | ||||
|  *              In this C version, the following C library functions are used: | ||||
|  *              - strcpy, strcmp (inside the measurement loop) | ||||
|  *              - printf, scanf (outside the measurement loop) | ||||
|  *              In addition, Berkeley UNIX system calls "times ()" or "time ()" | ||||
|  *              are used for execution time measurement. For measurements | ||||
|  *              on other systems, these calls have to be changed. | ||||
|  * | ||||
|  *  Collection of Results: | ||||
|  *              Reinhold Weicker (address see above) and | ||||
|  * | ||||
|  *              Rick Richardson | ||||
|  *              PC Research. Inc. | ||||
|  *              94 Apple Orchard Drive | ||||
|  *              Tinton Falls, NJ 07724 | ||||
|  *                      Phone:  (201) 389-8963 (9-17 EST) | ||||
|  *                      Usenet: ...!uunet!pcrat!rick | ||||
|  * | ||||
|  *      Please send results to Rick Richardson and/or Reinhold Weicker. | ||||
|  *      Complete information should be given on hardware and software used. | ||||
|  *      Hardware information includes: Machine type, CPU, type and size | ||||
|  *      of caches; for microprocessors: clock frequency, memory speed | ||||
|  *      (number of wait states). | ||||
|  *      Software information includes: Compiler (and runtime library) | ||||
|  *      manufacturer and version, compilation switches, OS version. | ||||
|  *      The Operating System version may give an indication about the | ||||
|  *      compiler; Dhrystone itself performs no OS calls in the measurement loop. | ||||
|  * | ||||
|  *      The complete output generated by the program should be mailed | ||||
|  *      such that at least some checks for correctness can be made. | ||||
|  * | ||||
|  *************************************************************************** | ||||
|  * | ||||
|  *  History:    This version C/2.1 has been made for two reasons: | ||||
|  * | ||||
|  *              1) There is an obvious need for a common C version of | ||||
|  *              Dhrystone, since C is at present the most popular system | ||||
|  *              programming language for the class of processors | ||||
|  *              (microcomputers, minicomputers) where Dhrystone is used most. | ||||
|  *              There should be, as far as possible, only one C version of | ||||
|  *              Dhrystone such that results can be compared without | ||||
|  *              restrictions. In the past, the C versions distributed | ||||
|  *              by Rick Richardson (Version 1.1) and by Reinhold Weicker | ||||
|  *              had small (though not significant) differences. | ||||
|  * | ||||
|  *              2) As far as it is possible without changes to the Dhrystone | ||||
|  *              statistics, optimizing compilers should be prevented from | ||||
|  *              removing significant statements. | ||||
|  * | ||||
|  *              This C version has been developed in cooperation with | ||||
|  *              Rick Richardson (Tinton Falls, NJ), it incorporates many | ||||
|  *              ideas from the "Version 1.1" distributed previously by | ||||
|  *              him over the UNIX network Usenet. | ||||
|  *              I also thank Chaim Benedelac (National Semiconductor), | ||||
|  *              David Ditzel (SUN), Earl Killian and John Mashey (MIPS), | ||||
|  *              Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) | ||||
|  *              for their help with comments on earlier versions of the | ||||
|  *              benchmark. | ||||
|  * | ||||
|  *  Changes:    In the initialization part, this version follows mostly | ||||
|  *              Rick Richardson's version distributed via Usenet, not the | ||||
|  *              version distributed earlier via floppy disk by Reinhold Weicker. | ||||
|  *              As a concession to older compilers, names have been made | ||||
|  *              unique within the first 8 characters. | ||||
|  *              Inside the measurement loop, this version follows the | ||||
|  *              version previously distributed by Reinhold Weicker. | ||||
|  * | ||||
|  *              At several places in the benchmark, code has been added, | ||||
|  *              but within the measurement loop only in branches that | ||||
|  *              are not executed. The intention is that optimizing compilers | ||||
|  *              should be prevented from moving code out of the measurement | ||||
|  *              loop, or from removing code altogether. Since the statements | ||||
|  *              that are executed within the measurement loop have NOT been | ||||
|  *              changed, the numbers defining the "Dhrystone distribution" | ||||
|  *              (distribution of statements, operand types and locality) | ||||
|  *              still hold. Except for sophisticated optimizing compilers, | ||||
|  *              execution times for this version should be the same as | ||||
|  *              for previous versions. | ||||
|  * | ||||
|  *              Since it has proven difficult to subtract the time for the | ||||
|  *              measurement loop overhead in a correct way, the loop check | ||||
|  *              has been made a part of the benchmark. This does have | ||||
|  *              an impact - though a very minor one - on the distribution | ||||
|  *              statistics which have been updated for this version. | ||||
|  * | ||||
|  *              All changes within the measurement loop are described | ||||
|  *              and discussed in the companion paper "Rationale for | ||||
|  *              Dhrystone version 2". | ||||
|  * | ||||
|  *              Because of the self-imposed limitation that the order and | ||||
|  *              distribution of the executed statements should not be | ||||
|  *              changed, there are still cases where optimizing compilers | ||||
|  *              may not generate code for some statements. To a certain | ||||
|  *              degree, this is unavoidable for small synthetic benchmarks. | ||||
|  *              Users of the benchmark are advised to check code listings | ||||
|  *              whether code is generated for all statements of Dhrystone. | ||||
|  * | ||||
|  *              Version 2.1 is identical to version 2.0 distributed via | ||||
|  *              the UNIX network Usenet in March 1988 except that it corrects | ||||
|  *              some minor deficiencies that were found by users of version 2.0. | ||||
|  *              The only change within the measurement loop is that a | ||||
|  *              non-executed "else" part was added to the "if" statement in | ||||
|  *              Func_3, and a non-executed "else" part removed from Proc_3. | ||||
|  * | ||||
|  *************************************************************************** | ||||
|  * | ||||
|  * Defines:     The following "Defines" are possible: | ||||
|  *              -DREG=register          (default: Not defined) | ||||
|  *                      As an approximation to what an average C programmer | ||||
|  *                      might do, the "register" storage class is applied | ||||
|  *                      (if enabled by -DREG=register) | ||||
|  *                      - for local variables, if they are used (dynamically) | ||||
|  *                        five or more times | ||||
|  *                      - for parameters if they are used (dynamically) | ||||
|  *                        six or more times | ||||
|  *                      Note that an optimal "register" strategy is | ||||
|  *                      compiler-dependent, and that "register" declarations | ||||
|  *                      do not necessarily lead to faster execution. | ||||
|  *              -DNOSTRUCTASSIGN        (default: Not defined) | ||||
|  *                      Define if the C compiler does not support | ||||
|  *                      assignment of structures. | ||||
|  *              -DNOENUMS               (default: Not defined) | ||||
|  *                      Define if the C compiler does not support | ||||
|  *                      enumeration types. | ||||
|  *              -DTIMES                 (default) | ||||
|  *              -DTIME | ||||
|  *                      The "times" function of UNIX (returning process times) | ||||
|  *                      or the "time" function (returning wallclock time) | ||||
|  *                      is used for measurement. | ||||
|  *                      For single user machines, "time ()" is adequate. For | ||||
|  *                      multi-user machines where you cannot get single-user | ||||
|  *                      access, use the "times ()" function. If you have | ||||
|  *                      neither, use a stopwatch in the dead of night. | ||||
|  *                      "printf"s are provided marking the points "Start Timer" | ||||
|  *                      and "Stop Timer". DO NOT use the UNIX "time(1)" | ||||
|  *                      command, as this will measure the total time to | ||||
|  *                      run this program, which will (erroneously) include | ||||
|  *                      the time to allocate storage (malloc) and to perform | ||||
|  *                      the initialization. | ||||
|  *              -DHZ=nnn | ||||
|  *                      In Berkeley UNIX, the function "times" returns process | ||||
|  *                      time in 1/HZ seconds, with HZ = 60 for most systems. | ||||
|  *                      CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY | ||||
|  *                      A VALUE. | ||||
|  * | ||||
|  *************************************************************************** | ||||
|  * | ||||
|  *  Compilation model and measurement (IMPORTANT): | ||||
|  * | ||||
|  *  This C version of Dhrystone consists of three files: | ||||
|  *  - dhry.h (this file, containing global definitions and comments) | ||||
|  *  - dhry_1.c (containing the code corresponding to Ada package Pack_1) | ||||
|  *  - dhry_2.c (containing the code corresponding to Ada package Pack_2) | ||||
|  * | ||||
|  *  The following "ground rules" apply for measurements: | ||||
|  *  - Separate compilation | ||||
|  *  - No procedure merging | ||||
|  *  - Otherwise, compiler optimizations are allowed but should be indicated | ||||
|  *  - Default results are those without register declarations | ||||
|  *  See the companion paper "Rationale for Dhrystone Version 2" for a more | ||||
|  *  detailed discussion of these ground rules. | ||||
|  * | ||||
|  *  For 16-Bit processors (e.g. 80186, 80286), times for all compilation | ||||
|  *  models ("small", "medium", "large" etc.) should be given if possible, | ||||
|  *  together with a definition of these models for the compiler system used. | ||||
|  * | ||||
|  ************************************************************************** | ||||
|  * | ||||
|  *  Dhrystone (C version) statistics: | ||||
|  * | ||||
|  *  [Comment from the first distribution, updated for version 2. | ||||
|  *   Note that because of language differences, the numbers are slightly | ||||
|  *   different from the Ada version.] | ||||
|  * | ||||
|  *  The following program contains statements of a high level programming | ||||
|  *  language (here: C) in a distribution considered representative: | ||||
|  * | ||||
|  *    assignments                  52 (51.0 %) | ||||
|  *    control statements           33 (32.4 %) | ||||
|  *    procedure, function calls    17 (16.7 %) | ||||
|  * | ||||
|  *  103 statements are dynamically executed. The program is balanced with | ||||
|  *  respect to the three aspects: | ||||
|  * | ||||
|  *    - statement type | ||||
|  *    - operand type | ||||
|  *    - operand locality | ||||
|  *         operand global, local, parameter, or constant. | ||||
|  * | ||||
|  *  The combination of these three aspects is balanced only approximately. | ||||
|  * | ||||
|  *  1. Statement Type: | ||||
|  *  -----------------             number | ||||
|  * | ||||
|  *     V1 = V2                     9 | ||||
|  *       (incl. V1 = F(..) | ||||
|  *     V = Constant               12 | ||||
|  *     Assignment,                 7 | ||||
|  *       with array element | ||||
|  *     Assignment,                 6 | ||||
|  *       with record component | ||||
|  *                                -- | ||||
|  *                                34       34 | ||||
|  * | ||||
|  *     X = Y +|-|"&&"|"|" Z        5 | ||||
|  *     X = Y +|-|"==" Constant     6 | ||||
|  *     X = X +|- 1                 3 | ||||
|  *     X = Y *|/ Z                 2 | ||||
|  *     X = Expression,             1 | ||||
|  *           two operators | ||||
|  *     X = Expression,             1 | ||||
|  *           three operators | ||||
|  *                                -- | ||||
|  *                                18       18 | ||||
|  * | ||||
|  *     if ....                    14 | ||||
|  *       with "else"      7 | ||||
|  *       without "else"   7 | ||||
|  *           executed        3 | ||||
|  *           not executed    4 | ||||
|  *     for ...                     7  |  counted every time | ||||
|  *     while ...                   4  |  the loop condition | ||||
|  *     do ... while                1  |  is evaluated | ||||
|  *     switch ...                  1 | ||||
|  *     break                       1 | ||||
|  *     declaration with            1 | ||||
|  *       initialization | ||||
|  *                                -- | ||||
|  *                                34       34 | ||||
|  * | ||||
|  *     P (...)  procedure call    11 | ||||
|  *       user procedure      10 | ||||
|  *       library procedure    1 | ||||
|  *     X = F (...) | ||||
|  *             function  call      6 | ||||
|  *       user function        5 | ||||
|  *       library function     1 | ||||
|  *                                -- | ||||
|  *                                17       17 | ||||
|  *                                        --- | ||||
|  *                                        103 | ||||
|  * | ||||
|  *    The average number of parameters in procedure or function calls | ||||
|  *    is 1.82 (not counting the function values aX * | ||||
|  * | ||||
|  *  2. Operators | ||||
|  *  ------------ | ||||
|  *                          number    approximate | ||||
|  *                                    percentage | ||||
|  * | ||||
|  *    Arithmetic             32          50.8 | ||||
|  * | ||||
|  *       +                     21          33.3 | ||||
|  *       -                      7          11.1 | ||||
|  *       *                      3           4.8 | ||||
|  *       / (int div)            1           1.6 | ||||
|  * | ||||
|  *    Comparison             27           42.8 | ||||
|  * | ||||
|  *       ==                     9           14.3 | ||||
|  *       /=                     4            6.3 | ||||
|  *       >                      1            1.6 | ||||
|  *       <                      3            4.8 | ||||
|  *       >=                     1            1.6 | ||||
|  *       <=                     9           14.3 | ||||
|  * | ||||
|  *    Logic                   4            6.3 | ||||
|  * | ||||
|  *       && (AND-THEN)          1            1.6 | ||||
|  *       |  (OR)                1            1.6 | ||||
|  *       !  (NOT)               2            3.2 | ||||
|  * | ||||
|  *                           --          ----- | ||||
|  *                           63          100.1 | ||||
|  * | ||||
|  * | ||||
|  *  3. Operand Type (counted once per operand reference): | ||||
|  *  --------------- | ||||
|  *                          number    approximate | ||||
|  *                                    percentage | ||||
|  * | ||||
|  *     Integer               175        72.3 % | ||||
|  *     Character              45        18.6 % | ||||
|  *     Pointer                12         5.0 % | ||||
|  *     String30                6         2.5 % | ||||
|  *     Array                   2         0.8 % | ||||
|  *     Record                  2         0.8 % | ||||
|  *                           ---       ------- | ||||
|  *                           242       100.0 % | ||||
|  * | ||||
|  *  When there is an access path leading to the final operand (e.g. a record | ||||
|  *  component), only the final data type on the access path is counted. | ||||
|  * | ||||
|  * | ||||
|  *  4. Operand Locality: | ||||
|  *  ------------------- | ||||
|  *                                number    approximate | ||||
|  *                                          percentage | ||||
|  * | ||||
|  *     local variable              114        47.1 % | ||||
|  *     global variable              22         9.1 % | ||||
|  *     parameter                    45        18.6 % | ||||
|  *        value                        23         9.5 % | ||||
|  *        reference                    22         9.1 % | ||||
|  *     function result               6         2.5 % | ||||
|  *     constant                     55        22.7 % | ||||
|  *                                 ---       ------- | ||||
|  *                                 242       100.0 % | ||||
|  * | ||||
|  * | ||||
|  *  The program does not compute anything meaningful, but it is syntactically | ||||
|  *  and semantically correct. All variables have a value assigned to them | ||||
|  *  before they are used as a source operand. | ||||
|  * | ||||
|  *  There has been no explicit effort to account for the effects of a | ||||
|  *  cache, or to balance the use of long or short displacements for code or | ||||
|  *  data. | ||||
|  * | ||||
|  *************************************************************************** | ||||
|  */ | ||||
| 
 | ||||
| /* Compiler and system dependent definitions: */ | ||||
| 
 | ||||
| #ifndef TIME | ||||
| #undef TIMES | ||||
| #define TIMES | ||||
| #endif | ||||
|                 /* Use times(2) time function unless    */ | ||||
|                 /* explicitly defined otherwise         */ | ||||
| 
 | ||||
| #ifdef MSC_CLOCK | ||||
| #undef HZ | ||||
| #undef TIMES | ||||
| #include <time.h> | ||||
| #define HZ      CLK_TCK | ||||
| #endif | ||||
|                 /* Use Microsoft C hi-res clock */ | ||||
| 
 | ||||
| #ifdef TIMES | ||||
| #include <sys/types.h> | ||||
| #include <sys/times.h> | ||||
| 
 | ||||
| #ifndef HZ | ||||
| #define HZ      100 | ||||
| #endif | ||||
|                 /* for "times" */ | ||||
| #endif | ||||
| 
 | ||||
| #define Mic_secs_Per_Second     1000000.0 | ||||
|                 /* Berkeley UNIX C returns process times in seconds/HZ */ | ||||
| 
 | ||||
| #ifdef  NOSTRUCTASSIGN | ||||
| #define structassign(d, s)      memcpy(&(d), &(s), sizeof(d)) | ||||
| #else | ||||
| #define structassign(d, s)      d = s | ||||
| #endif | ||||
| 
 | ||||
| #ifdef  NOENUM | ||||
| #define Ident_1 0 | ||||
| #define Ident_2 1 | ||||
| #define Ident_3 2 | ||||
| #define Ident_4 3 | ||||
| #define Ident_5 4 | ||||
|   typedef int   Enumeration; | ||||
| #else | ||||
|   typedef       enum    {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5} | ||||
|                 Enumeration; | ||||
| #endif | ||||
|         /* for boolean and enumeration types in Ada, Pascal */ | ||||
| 
 | ||||
| /* General definitions: */ | ||||
| 
 | ||||
| //#include <stdio.h>
 | ||||
|                 /* for strcpy, strcmp */ | ||||
| 
 | ||||
| #define Null 0 | ||||
|                 /* Value of a Null pointer */ | ||||
| #define true  1 | ||||
| #define false 0 | ||||
| 
 | ||||
| typedef int     One_Thirty; | ||||
| typedef int     One_Fifty; | ||||
| typedef char    Capital_Letter; | ||||
| typedef int     Boolean; | ||||
| typedef char    Str_30 [31]; | ||||
| typedef int     Arr_1_Dim [50]; | ||||
| typedef int     Arr_2_Dim [50] [50]; | ||||
| 
 | ||||
| typedef struct record | ||||
|     { | ||||
|     struct record *Ptr_Comp; | ||||
|     Enumeration    Discr; | ||||
|     union { | ||||
|           struct { | ||||
|                   Enumeration Enum_Comp; | ||||
|                   int         Int_Comp; | ||||
|                   char        Str_Comp [31]; | ||||
|                   } var_1; | ||||
|           struct { | ||||
|                   Enumeration E_Comp_2; | ||||
|                   char        Str_2_Comp [31]; | ||||
|                   } var_2; | ||||
|           struct { | ||||
|                   char        Ch_1_Comp; | ||||
|                   char        Ch_2_Comp; | ||||
|                   } var_3; | ||||
|           } variant; | ||||
|       } Rec_Type, *Rec_Pointer; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,2 @@ | |||
| OFILES = crt0.o dhry_1.o dhry_2.o printf.o | ||||
| TEST_CFLAGS = -g -O3 | ||||
|  | @ -0,0 +1,462 @@ | |||
| #define SWERV | ||||
| /*
 | ||||
|  **************************************************************************** | ||||
|  * | ||||
|  *                   "DHRYSTONE" Benchmark Program | ||||
|  *                   ----------------------------- | ||||
|  * | ||||
|  *  Version:    C, Version 2.1 | ||||
|  * | ||||
|  *  File:       dhry_1.c (part 2 of 3) | ||||
|  * | ||||
|  *  Date:       May 25, 1988 | ||||
|  * | ||||
|  *  Author:     Reinhold P. Weicker | ||||
|  * | ||||
|  **************************************************************************** | ||||
|  */ | ||||
| 
 | ||||
| #ifdef SWERV | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| extern uint64_t get_mcycle(); | ||||
| #endif | ||||
| 
 | ||||
| #include "dhry.h" | ||||
| 
 | ||||
| /* Global Variables: */ | ||||
| 
 | ||||
| Rec_Pointer     Ptr_Glob, | ||||
|                 Next_Ptr_Glob; | ||||
| int             Int_Glob; | ||||
| Boolean         Bool_Glob; | ||||
| char            Ch_1_Glob, | ||||
|                 Ch_2_Glob; | ||||
| int             Arr_1_Glob [50]; | ||||
| int             Arr_2_Glob [50] [50]; | ||||
| 
 | ||||
| Enumeration     Func_1 (); | ||||
|   /* forward declaration necessary since Enumeration may not simply be int */ | ||||
| 
 | ||||
| #ifndef REG | ||||
|         Boolean Reg = false; | ||||
| #define REG | ||||
|         /* REG becomes defined as empty */ | ||||
|         /* i.e. no register variables   */ | ||||
| #else | ||||
|         Boolean Reg = true; | ||||
| #endif | ||||
| 
 | ||||
| /* variables for time measurement: */ | ||||
| 
 | ||||
| #ifdef TIMES | ||||
| struct tms      time_info; | ||||
| #define Too_Small_Time (2*HZ) | ||||
|                 /* Measurements should last at least about 2 seconds */ | ||||
| #endif | ||||
| #ifdef TIME | ||||
| extern long     time(); | ||||
|                 /* see library function "time"  */ | ||||
| #define Too_Small_Time 2 | ||||
|                 /* Measurements should last at least 2 seconds */ | ||||
| #endif | ||||
| #ifdef MSC_CLOCK | ||||
| extern clock_t  clock(); | ||||
| #define Too_Small_Time (2*HZ) | ||||
| #endif | ||||
| 
 | ||||
| long | ||||
|                 Begin_Time, | ||||
|                 End_Time, | ||||
|                 User_Time; | ||||
| 
 | ||||
| float           Microseconds, | ||||
|                 Dhrystones_Per_Second; | ||||
| 
 | ||||
| /* end of variables for time measurement */ | ||||
| 
 | ||||
| 
 | ||||
| extern char* strcpy(char*, const char*); | ||||
| 
 | ||||
| extern Boolean Func_2 (Str_30, Str_30); | ||||
| extern void Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, | ||||
|                     One_Fifty *Int_Par_Ref); | ||||
| 
 | ||||
| extern void Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, | ||||
|                     int Int_1_Par_Val, int Int_2_Par_Val); | ||||
| 
 | ||||
| extern void Proc_6 (Enumeration Enum_Val_Par, | ||||
|                     Enumeration *Enum_Ref_Par); | ||||
| 
 | ||||
| void Proc_5(); | ||||
| void Proc_4(); | ||||
| 
 | ||||
| void Proc_1(Rec_Pointer Ptr_Val_Par); | ||||
| void Proc_2(One_Fifty *Int_Par_Ref); | ||||
| void Proc_3(Rec_Pointer *Ptr_Ref_Par); | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| main () | ||||
| /*****/ | ||||
| 
 | ||||
|   /* main program, corresponds to procedures        */ | ||||
|   /* Main and Proc_0 in the Ada version             */ | ||||
| { | ||||
|         One_Fifty       Int_1_Loc; | ||||
|   REG   One_Fifty       Int_2_Loc; | ||||
|         One_Fifty       Int_3_Loc; | ||||
|   REG   char            Ch_Index; | ||||
|         Enumeration     Enum_Loc; | ||||
|         Str_30          Str_1_Loc; | ||||
|         Str_30          Str_2_Loc; | ||||
|   REG   int             Run_Index; | ||||
|   REG   int             Number_Of_Runs; | ||||
| 
 | ||||
|   /* Initializations */ | ||||
| 
 | ||||
|   Rec_Type rec0; | ||||
|   Rec_Type rec1; | ||||
| 
 | ||||
|   Next_Ptr_Glob = &rec0; | ||||
|   Ptr_Glob = &rec1; | ||||
| 
 | ||||
|   Ptr_Glob->Ptr_Comp                    = Next_Ptr_Glob; | ||||
|   Ptr_Glob->Discr                       = Ident_1; | ||||
|   Ptr_Glob->variant.var_1.Enum_Comp     = Ident_3; | ||||
|   Ptr_Glob->variant.var_1.Int_Comp      = 40; | ||||
|   strcpy (Ptr_Glob->variant.var_1.Str_Comp, | ||||
|           "DHRYSTONE PROGRAM, SOME STRING"); | ||||
|   strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); | ||||
| 
 | ||||
|   Arr_2_Glob [8][7] = 10; | ||||
|         /* Was missing in published program. Without this statement,    */ | ||||
|         /* Arr_2_Glob [8][7] would have an undefined value.             */ | ||||
|         /* Warning: With 16-Bit processors and Number_Of_Runs > 32000,  */ | ||||
|         /* overflow may occur for this array element.                   */ | ||||
| 
 | ||||
|   printf ("\n"); | ||||
|   printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n"); | ||||
|   printf ("\n"); | ||||
|   if (Reg) | ||||
|   { | ||||
|     printf ("Program compiled with 'register' attribute\n"); | ||||
|     printf ("\n"); | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     printf ("Program compiled without 'register' attribute\n"); | ||||
|     printf ("\n"); | ||||
|   } | ||||
| 
 | ||||
|   #ifndef SWERV | ||||
|   printf ("Please give the number of runs through the benchmark: "); | ||||
|   { | ||||
|     int n = 1000; | ||||
|     scanf ("%d", &n); | ||||
|     Number_Of_Runs = n; | ||||
|   } | ||||
|   printf ("\n"); | ||||
|   #else | ||||
|   // We do not have scanf.  Hardwire number of runs.
 | ||||
|   Number_Of_Runs = 1000; | ||||
|   #endif | ||||
| 
 | ||||
|   printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs); | ||||
| 
 | ||||
|   /***************/ | ||||
|   /* Start timer */ | ||||
|   /***************/ | ||||
| 
 | ||||
| #ifdef SWERV | ||||
|     Begin_Time = get_mcycle(); | ||||
| #else | ||||
| 
 | ||||
| #ifdef TIMES | ||||
|   times (&time_info); | ||||
|   Begin_Time = (long) time_info.tms_utime; | ||||
| #endif | ||||
| #ifdef TIME | ||||
|   Begin_Time = time ( (long *) 0); | ||||
| #endif | ||||
| #ifdef MSC_CLOCK | ||||
|   Begin_Time = clock(); | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|   __asm("__perf_start:"); | ||||
| 
 | ||||
|   for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) | ||||
|   { | ||||
|     __asm("__loop_start:"); | ||||
| 
 | ||||
|     Proc_5(); | ||||
|     Proc_4(); | ||||
|       /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ | ||||
|     Int_1_Loc = 2; | ||||
|     Int_2_Loc = 3; | ||||
|     strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); | ||||
|     Enum_Loc = Ident_2; | ||||
|     Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); | ||||
|       /* Bool_Glob == 1 */ | ||||
|     while (Int_1_Loc < Int_2_Loc)  /* loop body executed once */ | ||||
|     { | ||||
|       Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; | ||||
|         /* Int_3_Loc == 7 */ | ||||
|       Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); | ||||
|         /* Int_3_Loc == 7 */ | ||||
|       Int_1_Loc += 1; | ||||
|     } /* while */ | ||||
|       /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ | ||||
|     Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); | ||||
|       /* Int_Glob == 5 */ | ||||
|     Proc_1 (Ptr_Glob); | ||||
|     for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) | ||||
|                              /* loop body executed twice */ | ||||
|     { | ||||
|       if (Enum_Loc == Func_1 (Ch_Index, 'C')) | ||||
|           /* then, not executed */ | ||||
|         { | ||||
|         Proc_6 (Ident_1, &Enum_Loc); | ||||
|         strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); | ||||
|         Int_2_Loc = Run_Index; | ||||
|         Int_Glob = Run_Index; | ||||
|         } | ||||
|     } | ||||
|       /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ | ||||
|     Int_2_Loc = Int_2_Loc * Int_1_Loc; | ||||
|     Int_1_Loc = Int_2_Loc / Int_3_Loc; | ||||
|     Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; | ||||
|       /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ | ||||
|     Proc_2 (&Int_1_Loc); | ||||
|       /* Int_1_Loc == 5 */ | ||||
| 
 | ||||
|   } /* loop "for Run_Index" */ | ||||
| 
 | ||||
|   __asm("__perf_end:"); | ||||
| 
 | ||||
|   /**************/ | ||||
|   /* Stop timer */ | ||||
|   /**************/ | ||||
| 
 | ||||
| #ifdef SWERV | ||||
|     End_Time = get_mcycle(); | ||||
|     printf("End_time=%d\n", (int) End_Time); | ||||
| #else | ||||
| #ifdef TIMES | ||||
|   times (&time_info); | ||||
|   End_Time = (long) time_info.tms_utime; | ||||
| #endif | ||||
| #ifdef TIME | ||||
|   End_Time = time ( (long *) 0); | ||||
| #endif | ||||
| #ifdef MSC_CLOCK | ||||
|   End_Time = clock(); | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|   printf ("Execution ends\n"); | ||||
|   printf ("\n"); | ||||
|   printf ("Final values of the variables used in the benchmark:\n"); | ||||
|   printf ("\n"); | ||||
|   printf ("Int_Glob:            %d\n", Int_Glob); | ||||
|   printf ("        should be:   %d\n", 5); | ||||
|   printf ("Bool_Glob:           %d\n", Bool_Glob); | ||||
|   printf ("        should be:   %d\n", 1); | ||||
|   printf ("Ch_1_Glob:           %c\n", Ch_1_Glob); | ||||
|   printf ("        should be:   %c\n", 'A'); | ||||
|   printf ("Ch_2_Glob:           %c\n", Ch_2_Glob); | ||||
|   printf ("        should be:   %c\n", 'B'); | ||||
|   printf ("Arr_1_Glob[8]:       %d\n", Arr_1_Glob[8]); | ||||
|   printf ("        should be:   %d\n", 7); | ||||
|   printf ("Arr_2_Glob[8][7]:    %d\n", Arr_2_Glob[8][7]); | ||||
|   printf ("        should be:   Number_Of_Runs + 10\n"); | ||||
|   printf ("Ptr_Glob->\n"); | ||||
|   printf ("  Ptr_Comp:          %d\n", (int) Ptr_Glob->Ptr_Comp); | ||||
|   printf ("        should be:   (implementation-dependent)\n"); | ||||
|   printf ("  Discr:             %d\n", Ptr_Glob->Discr); | ||||
|   printf ("        should be:   %d\n", 0); | ||||
|   printf ("  Enum_Comp:         %d\n", Ptr_Glob->variant.var_1.Enum_Comp); | ||||
|   printf ("        should be:   %d\n", 2); | ||||
|   printf ("  Int_Comp:          %d\n", Ptr_Glob->variant.var_1.Int_Comp); | ||||
|   printf ("        should be:   %d\n", 17); | ||||
|   printf ("  Str_Comp:          %s\n", Ptr_Glob->variant.var_1.Str_Comp); | ||||
|   printf ("        should be:   DHRYSTONE PROGRAM, SOME STRING\n"); | ||||
|   printf ("Next_Ptr_Glob->\n"); | ||||
|   printf ("  Ptr_Comp:          %d\n", (int) Next_Ptr_Glob->Ptr_Comp); | ||||
|   printf ("        should be:   (implementation-dependent), same as above\n"); | ||||
|   printf ("  Discr:             %d\n", Next_Ptr_Glob->Discr); | ||||
|   printf ("        should be:   %d\n", 0); | ||||
|   printf ("  Enum_Comp:         %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); | ||||
|   printf ("        should be:   %d\n", 1); | ||||
|   printf ("  Int_Comp:          %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); | ||||
|   printf ("        should be:   %d\n", 18); | ||||
|   printf ("  Str_Comp:          %s\n", | ||||
|                                 Next_Ptr_Glob->variant.var_1.Str_Comp); | ||||
|   printf ("        should be:   DHRYSTONE PROGRAM, SOME STRING\n"); | ||||
|   printf ("Int_1_Loc:           %d\n", Int_1_Loc); | ||||
|   printf ("        should be:   %d\n", 5); | ||||
|   printf ("Int_2_Loc:           %d\n", Int_2_Loc); | ||||
|   printf ("        should be:   %d\n", 13); | ||||
|   printf ("Int_3_Loc:           %d\n", Int_3_Loc); | ||||
|   printf ("        should be:   %d\n", 7); | ||||
|   printf ("Enum_Loc:            %d\n", Enum_Loc); | ||||
|   printf ("        should be:   %d\n", 1); | ||||
|   printf ("Str_1_Loc:           %s\n", Str_1_Loc); | ||||
|   printf ("        should be:   DHRYSTONE PROGRAM, 1'ST STRING\n"); | ||||
|   printf ("Str_2_Loc:           %s\n", Str_2_Loc); | ||||
|   printf ("        should be:   DHRYSTONE PROGRAM, 2'ND STRING\n"); | ||||
|   printf ("\n"); | ||||
| 
 | ||||
|   User_Time = End_Time - Begin_Time; | ||||
| 
 | ||||
|   if (User_Time < Too_Small_Time) | ||||
|   { | ||||
|     printf ("User time %d\n", User_Time); | ||||
|     printf ("Measured time too small to obtain meaningful results\n"); | ||||
|     printf ("Please increase number of runs\n"); | ||||
|     printf ("\n"); | ||||
|   } | ||||
|   else | ||||
|   { | ||||
| #ifdef SWERV | ||||
|     printf ("Run time = %d clocks for %d Dhrystones\n", User_Time, Number_Of_Runs ); | ||||
|     printf ("Dhrystones per Second per MHz: "); | ||||
|     printf ("%d.%02d", 1000000*Number_Of_Runs/User_Time,(100000000*Number_Of_Runs/User_Time) % 100); | ||||
| #else | ||||
| #ifdef TIME | ||||
|     Microseconds = (float) User_Time * Mic_secs_Per_Second | ||||
|                         / (float) Number_Of_Runs; | ||||
|     Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time; | ||||
| #else | ||||
|     Microseconds = (float) User_Time * Mic_secs_Per_Second | ||||
|                         / ((float) HZ * ((float) Number_Of_Runs)); | ||||
|     Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) | ||||
|                         / (float) User_Time; | ||||
| #endif | ||||
|     printf ("Microseconds for one run through Dhrystone: "); | ||||
|     printf ("%6.1f \n", Microseconds); | ||||
|     printf ("Dhrystones per Second:                      "); | ||||
|     printf ("%6.1f \n", Dhrystones_Per_Second); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|     printf ("\n"); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| Proc_1 (Ptr_Val_Par) | ||||
| /******************/ | ||||
| 
 | ||||
| REG Rec_Pointer Ptr_Val_Par; | ||||
|     /* executed once */ | ||||
| { | ||||
|   REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; | ||||
|                                         /* == Ptr_Glob_Next */ | ||||
|   /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */ | ||||
|   /* corresponds to "rename" in Ada, "with" in Pascal           */ | ||||
| 
 | ||||
|   structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); | ||||
|   Ptr_Val_Par->variant.var_1.Int_Comp = 5; | ||||
|   Next_Record->variant.var_1.Int_Comp | ||||
|         = Ptr_Val_Par->variant.var_1.Int_Comp; | ||||
|   Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; | ||||
|   Proc_3 (&Next_Record->Ptr_Comp); | ||||
|     /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
 | ||||
|                         == Ptr_Glob->Ptr_Comp */ | ||||
|   if (Next_Record->Discr == Ident_1) | ||||
|     /* then, executed */ | ||||
|   { | ||||
|     Next_Record->variant.var_1.Int_Comp = 6; | ||||
|     Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, | ||||
|            &Next_Record->variant.var_1.Enum_Comp); | ||||
|     Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; | ||||
|     Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, | ||||
|            &Next_Record->variant.var_1.Int_Comp); | ||||
|   } | ||||
|   else /* not executed */ | ||||
|     structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp); | ||||
| } /* Proc_1 */ | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| Proc_2 (Int_Par_Ref) | ||||
| /******************/ | ||||
|     /* executed once */ | ||||
|     /* *Int_Par_Ref == 1, becomes 4 */ | ||||
| 
 | ||||
| One_Fifty   *Int_Par_Ref; | ||||
| { | ||||
|   One_Fifty  Int_Loc; | ||||
|   Enumeration   Enum_Loc; | ||||
| 
 | ||||
|   Int_Loc = *Int_Par_Ref + 10; | ||||
|   do /* executed once */ | ||||
|     if (Ch_1_Glob == 'A') | ||||
|       /* then, executed */ | ||||
|     { | ||||
|       Int_Loc -= 1; | ||||
|       *Int_Par_Ref = Int_Loc - Int_Glob; | ||||
|       Enum_Loc = Ident_1; | ||||
|     } /* if */ | ||||
|   while (Enum_Loc != Ident_1); /* true */ | ||||
| } /* Proc_2 */ | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| Proc_3 (Ptr_Ref_Par) | ||||
| /******************/ | ||||
|     /* executed once */ | ||||
|     /* Ptr_Ref_Par becomes Ptr_Glob */ | ||||
| 
 | ||||
| Rec_Pointer *Ptr_Ref_Par; | ||||
| 
 | ||||
| { | ||||
|   if (Ptr_Glob != Null) | ||||
|     /* then, executed */ | ||||
|     *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; | ||||
|   Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); | ||||
| } /* Proc_3 */ | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| Proc_4 () /* without parameters */ | ||||
| /*******/ | ||||
|     /* executed once */ | ||||
| { | ||||
|   Boolean Bool_Loc; | ||||
| 
 | ||||
|   Bool_Loc = Ch_1_Glob == 'A'; | ||||
|   Bool_Glob = Bool_Loc | Bool_Glob; | ||||
|   Ch_2_Glob = 'B'; | ||||
| } /* Proc_4 */ | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| Proc_5 () /* without parameters */ | ||||
| /*******/ | ||||
|     /* executed once */ | ||||
| { | ||||
|   Ch_1_Glob = 'A'; | ||||
|   Bool_Glob = false; | ||||
| } /* Proc_5 */ | ||||
| 
 | ||||
| 
 | ||||
|         /* Procedure for the assignment of structures,          */ | ||||
|         /* if the C compiler doesn't support this feature       */ | ||||
| #ifdef  NOSTRUCTASSIGN | ||||
| memcpy (d, s, l) | ||||
| register char   *d; | ||||
| register char   *s; | ||||
| register int    l; | ||||
| { | ||||
|         while (l--) *d++ = *s++; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,212 @@ | |||
| /*
 | ||||
|  **************************************************************************** | ||||
|  * | ||||
|  *                   "DHRYSTONE" Benchmark Program | ||||
|  *                   ----------------------------- | ||||
|  * | ||||
|  *  Version:    C, Version 2.1 | ||||
|  * | ||||
|  *  File:       dhry_2.c (part 3 of 3) | ||||
|  * | ||||
|  *  Date:       May 25, 1988 | ||||
|  * | ||||
|  *  Author:     Reinhold P. Weicker | ||||
|  * | ||||
|  **************************************************************************** | ||||
|  */ | ||||
| 
 | ||||
| #include "dhry.h" | ||||
| 
 | ||||
| #ifndef REG | ||||
| #define REG | ||||
|         /* REG becomes defined as empty */ | ||||
|         /* i.e. no register variables   */ | ||||
| #endif | ||||
| 
 | ||||
| extern  int     Int_Glob; | ||||
| extern  char    Ch_1_Glob; | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| strcmp(const char* s1, const char* s2) | ||||
| { | ||||
|   while (*s1 && *s1 == *s2) | ||||
|     { | ||||
|       s1++; | ||||
|       s2++; | ||||
|     } | ||||
|   if (*s1 == *s2) | ||||
|     return 0; | ||||
|   return *s1 > *s2? 1 : -1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Boolean Func_3 (Enumeration Enum_Par_Val); | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| Proc_6 (Enum_Val_Par, Enum_Ref_Par) | ||||
| /*********************************/ | ||||
|     /* executed once */ | ||||
|     /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ | ||||
| 
 | ||||
| Enumeration  Enum_Val_Par; | ||||
| Enumeration *Enum_Ref_Par; | ||||
| { | ||||
|   *Enum_Ref_Par = Enum_Val_Par; | ||||
|   if (! Func_3 (Enum_Val_Par)) | ||||
|     /* then, not executed */ | ||||
|     *Enum_Ref_Par = Ident_4; | ||||
|   switch (Enum_Val_Par) | ||||
|   { | ||||
|     case Ident_1: | ||||
|       *Enum_Ref_Par = Ident_1; | ||||
|       break; | ||||
|     case Ident_2: | ||||
|       if (Int_Glob > 100) | ||||
|         /* then */ | ||||
|       *Enum_Ref_Par = Ident_1; | ||||
|       else *Enum_Ref_Par = Ident_4; | ||||
|       break; | ||||
|     case Ident_3: /* executed */ | ||||
|       *Enum_Ref_Par = Ident_2; | ||||
|       break; | ||||
|     case Ident_4: break; | ||||
|     case Ident_5: | ||||
|       *Enum_Ref_Par = Ident_3; | ||||
|       break; | ||||
|   } /* switch */ | ||||
| } /* Proc_6 */ | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref) | ||||
| /**********************************************/ | ||||
|     /* executed three times                                      */ | ||||
|     /* first call:      Int_1_Par_Val == 2, Int_2_Par_Val == 3,  */ | ||||
|     /*                  Int_Par_Ref becomes 7                    */ | ||||
|     /* second call:     Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ | ||||
|     /*                  Int_Par_Ref becomes 17                   */ | ||||
|     /* third call:      Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ | ||||
|     /*                  Int_Par_Ref becomes 18                   */ | ||||
| One_Fifty       Int_1_Par_Val; | ||||
| One_Fifty       Int_2_Par_Val; | ||||
| One_Fifty      *Int_Par_Ref; | ||||
| { | ||||
|   One_Fifty Int_Loc; | ||||
| 
 | ||||
|   Int_Loc = Int_1_Par_Val + 2; | ||||
|   *Int_Par_Ref = Int_2_Par_Val + Int_Loc; | ||||
| } /* Proc_7 */ | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val) | ||||
| /*********************************************************************/ | ||||
|     /* executed once      */ | ||||
|     /* Int_Par_Val_1 == 3 */ | ||||
|     /* Int_Par_Val_2 == 7 */ | ||||
| Arr_1_Dim       Arr_1_Par_Ref; | ||||
| Arr_2_Dim       Arr_2_Par_Ref; | ||||
| int             Int_1_Par_Val; | ||||
| int             Int_2_Par_Val; | ||||
| { | ||||
|   REG One_Fifty Int_Index; | ||||
|   REG One_Fifty Int_Loc; | ||||
| 
 | ||||
|   Int_Loc = Int_1_Par_Val + 5; | ||||
|   Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; | ||||
|   Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc]; | ||||
|   Arr_1_Par_Ref [Int_Loc+30] = Int_Loc; | ||||
|   for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) | ||||
|     Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; | ||||
|   Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1; | ||||
|   Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; | ||||
|   Int_Glob = 5; | ||||
| } /* Proc_8 */ | ||||
| 
 | ||||
| 
 | ||||
| Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val) | ||||
| /*************************************************/ | ||||
|     /* executed three times                                         */ | ||||
|     /* first call:      Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R'    */ | ||||
|     /* second call:     Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C'    */ | ||||
|     /* third call:      Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C'    */ | ||||
| 
 | ||||
| Capital_Letter   Ch_1_Par_Val; | ||||
| Capital_Letter   Ch_2_Par_Val; | ||||
| { | ||||
|   Capital_Letter        Ch_1_Loc; | ||||
|   Capital_Letter        Ch_2_Loc; | ||||
| 
 | ||||
|   Ch_1_Loc = Ch_1_Par_Val; | ||||
|   Ch_2_Loc = Ch_1_Loc; | ||||
|   if (Ch_2_Loc != Ch_2_Par_Val) | ||||
|     /* then, executed */ | ||||
|     return (Ident_1); | ||||
|   else  /* not executed */ | ||||
|   { | ||||
|     Ch_1_Glob = Ch_1_Loc; | ||||
|     return (Ident_2); | ||||
|    } | ||||
| } /* Func_1 */ | ||||
| 
 | ||||
| 
 | ||||
| Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref) | ||||
| /*************************************************/ | ||||
|     /* executed once */ | ||||
|     /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ | ||||
|     /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ | ||||
| 
 | ||||
| Str_30  Str_1_Par_Ref; | ||||
| Str_30  Str_2_Par_Ref; | ||||
| { | ||||
|   REG One_Thirty        Int_Loc; | ||||
|       Capital_Letter    Ch_Loc; | ||||
| 
 | ||||
|   Int_Loc = 2; | ||||
|   while (Int_Loc <= 2) /* loop body executed once */ | ||||
|     if (Func_1 (Str_1_Par_Ref[Int_Loc], | ||||
|                 Str_2_Par_Ref[Int_Loc+1]) == Ident_1) | ||||
|       /* then, executed */ | ||||
|     { | ||||
|       Ch_Loc = 'A'; | ||||
|       Int_Loc += 1; | ||||
|     } /* if, while */ | ||||
|   if (Ch_Loc >= 'W' && Ch_Loc < 'Z') | ||||
|     /* then, not executed */ | ||||
|     Int_Loc = 7; | ||||
|   if (Ch_Loc == 'R') | ||||
|     /* then, not executed */ | ||||
|     return (true); | ||||
|   else /* executed */ | ||||
|   { | ||||
|     if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) | ||||
|       /* then, not executed */ | ||||
|     { | ||||
|       Int_Loc += 7; | ||||
|       Int_Glob = Int_Loc; | ||||
|       return (true); | ||||
|     } | ||||
|     else /* executed */ | ||||
|       return (false); | ||||
|   } /* if Ch_Loc */ | ||||
| } /* Func_2 */ | ||||
| 
 | ||||
| 
 | ||||
| Boolean Func_3 (Enum_Par_Val) | ||||
| /***************************/ | ||||
|     /* executed once        */ | ||||
|     /* Enum_Par_Val == Ident_3 */ | ||||
| Enumeration Enum_Par_Val; | ||||
| { | ||||
|   Enumeration Enum_Loc; | ||||
| 
 | ||||
|   Enum_Loc = Enum_Par_Val; | ||||
|   if (Enum_Loc == Ident_3) | ||||
|     /* then, executed */ | ||||
|     return (true); | ||||
|   else /* not executed */ | ||||
|     return (false); | ||||
| } /* Func_3 */ | ||||
| 
 | ||||
|  | @ -0,0 +1 @@ | |||
| ../../asm/printf.c | ||||
|  | @ -0,0 +1,11 @@ | |||
| export TEST = hello_world | ||||
| export OFILES = crt0.o hello_world.o | ||||
| export BUILD_PATH = $(shell pwd)/snapshots/default | ||||
| 
 | ||||
| program.hex: | ||||
| 	$(MAKE) -e -f $(RV_ROOT)/tools/make.common $(BUILD_PATH)/defines.h | ||||
| 	$(MAKE) -e -f $(RV_ROOT)/tools/make.common $@ | ||||
| 
 | ||||
| .DEFAULT: | ||||
| 	$(MAKE) -e program.hex | ||||
| 	$(MAKE) -e -f $(RV_ROOT)/tools/make.common $@ | ||||
|  | @ -0,0 +1,42 @@ | |||
| // 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" | ||||
| 
 | ||||
| .section .text | ||||
| .global main
 | ||||
| 
 | ||||
| main: | ||||
|     li x3, RV_SERIALIO | ||||
|     la x4, hw_data | ||||
| 
 | ||||
| loop: | ||||
|    lb x5, 0(x4) | ||||
|    sb x5, 0(x3) | ||||
|    addi x4, x4, 1 | ||||
|    bnez x5, loop | ||||
|    ret | ||||
| 
 | ||||
| .data | ||||
| hw_data: | ||||
| .ascii "----------------------------------\n" | ||||
| .ascii "Hello World from SweRV EL2 @WDC !!\n"
 | ||||
| .ascii "----------------------------------\n" | ||||
| .byte 0
 | ||||
							
								
								
									
										100
									
								
								tools/Makefile
								
								
								
								
							
							
						
						
									
										100
									
								
								tools/Makefile
								
								
								
								
							|  | @ -14,6 +14,11 @@ | |||
| # limitations under the License.
 | ||||
| #
 | ||||
| 
 | ||||
| CONF_PARAMS = -set build_axi4 | ||||
| 
 | ||||
| TEST_CFLAGS = -g -O3 -funroll-all-loops | ||||
| ABI = -mabi=ilp32 -march=rv32imac | ||||
| 
 | ||||
| # Check for RV_ROOT
 | ||||
| ifeq (,$(wildcard ${RV_ROOT}/configs/swerv.config)) | ||||
| $(error env var RV_ROOT does not point to a valid dir! Exiting!) | ||||
|  | @ -29,6 +34,7 @@ IRUN = xrun | |||
| VCS = vcs | ||||
| VLOG = qverilog | ||||
| VERILATOR = verilator | ||||
| RIVEIRA = riviera | ||||
| GCC_PREFIX = riscv64-unknown-elf | ||||
| BUILD_DIR = snapshots/${snapshot} | ||||
| TBDIR = ${RV_ROOT}/testbench | ||||
|  | @ -37,24 +43,44 @@ TBDIR = ${RV_ROOT}/testbench | |||
| TEST = hello_world | ||||
| 
 | ||||
| # Define test name
 | ||||
| TEST_DIR = ${TBDIR}/asm | ||||
| ifneq (,$(wildcard $(TBDIR)/asm/$(TEST).s)) | ||||
| 	TEST_DIR = ${TBDIR}/asm | ||||
| else | ||||
| ifneq (,$(wildcard $(TBDIR)/asm/$(TEST).c)) | ||||
| 	TEST_DIR = ${TBDIR}/asm | ||||
| else | ||||
| ifneq (,$(wildcard $(TBDIR)/tests/$(TEST))) | ||||
| 	TEST_DIR = $(TBDIR)/tests/$(TEST) | ||||
| else  | ||||
| 	TEST_DIR = ${TBDIR}/asm | ||||
| endif | ||||
| endif | ||||
| endif | ||||
| HEX_DIR = ${TBDIR}/hex | ||||
| 
 | ||||
| OFILES = $(TEST).o | ||||
| 
 | ||||
| ifdef debug | ||||
|  DEBUG_PLUS = +dumpon | ||||
|  IRUN_DEBUG = -access +rc | ||||
|  IRUN_DEBUG_RUN = -input ${RV_ROOT}/testbench/input.tcl | ||||
|  VCS_DEBUG = -debug_access | ||||
|  VERILATOR_DEBUG = --trace | ||||
|  RIVIERA_DEBUG = +access +r | ||||
| endif | ||||
| 
 | ||||
| # provide specific link file
 | ||||
| ifeq (,$(wildcard $(TEST_DIR)/$(TEST).ld)) | ||||
| 	LINK = $(TBDIR)/link.ld | ||||
| 	LINK = $(BUILD_DIR)/link.ld | ||||
| else | ||||
| 	LINK = $(TEST_DIR)/$(TEST).ld | ||||
| endif | ||||
| 
 | ||||
| VPATH = $(TEST_DIR) $(BUILD_DIR) $(TBDIR) | ||||
| 
 | ||||
| -include $(TEST_DIR)/$(TEST).mki | ||||
| 
 | ||||
| 
 | ||||
| TBFILES = $(TBDIR)/tb_top.sv $(TBDIR)/ahb_sif.sv | ||||
| 
 | ||||
| defines  = $(BUILD_DIR)/common_defines.vh | ||||
|  | @ -69,27 +95,32 @@ 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="-O2" | ||||
| VERILATOR_MAKE_FLAGS = OPT_FAST="-Os" | ||||
| 
 | ||||
| # Targets
 | ||||
| all: clean verilator | ||||
| 
 | ||||
| clean: | ||||
| 	rm -rf *.log *.s *.hex *.dis *.tbl irun* vcs* simv* snapshots swerv* \
 | ||||
| 	verilator* *.exe obj* *.o ucli.key vc_hdrs.h csrc *.csv work | ||||
| 	verilator* *.exe obj* *.o ucli.key vc_hdrs.h csrc *.csv work\
 | ||||
| 	work dataset.asdb  library.cfg vsimsa.cfg  riviera-build wave.asdb | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ############ Model Builds ###############################
 | ||||
| 
 | ||||
| # If define files do not exist, then run swerv.config.
 | ||||
| ${BUILD_DIR}/defines.h : | ||||
| ${BUILD_DIR}/defines.h: | ||||
| 	BUILD_PATH=${BUILD_DIR} ${RV_ROOT}/configs/swerv.config -target=$(target) $(CONF_PARAMS) | ||||
| 
 | ||||
| verilator-build: ${TBFILES} ${BUILD_DIR}/defines.h test_tb_top.cpp | ||||
| 	echo '`undef ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh | ||||
| 	$(VERILATOR) '-UASSERT_ON' --cc -CFLAGS ${CFLAGS} $(defines) \
 | ||||
| 	echo '`undef RV_ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh | ||||
| 	$(VERILATOR)  --cc -CFLAGS ${CFLAGS} $(defines) \
 | ||||
| 	  $(includes) -I${RV_ROOT}/testbench -f ${RV_ROOT}/testbench/flist \
 | ||||
| 	  -Wno-WIDTH -Wno-UNOPTFLAT ${TBFILES} --top-module tb_top \
 | ||||
| 	  -exe test_tb_top.cpp --autoflush $(VERILATOR_DEBUG) | ||||
| 	cp ${RV_ROOT}/testbench/test_tb_top.cpp obj_dir/ | ||||
| 	$(MAKE) -C obj_dir/ -f Vtb_top.mk $(VERILATOR_MAKE_FLAGS) | ||||
| 	$(MAKE) -j -e -C obj_dir/ -f Vtb_top.mk $(VERILATOR_MAKE_FLAGS) | ||||
| 	touch verilator-build | ||||
| 
 | ||||
| vcs-build: ${TBFILES} ${BUILD_DIR}/defines.h | ||||
|  | @ -106,60 +137,79 @@ irun-build: ${TBFILES} ${BUILD_DIR}/defines.h | |||
| 	  -incdir ${RV_ROOT}/design/lib -incdir ${RV_ROOT}/design/include \
 | ||||
| 	  -vlog_ext +.vh+.h $(defines) -incdir $(BUILD_DIR) \
 | ||||
| 	  -f ${RV_ROOT}/testbench/flist -top tb_top  ${TBFILES} \
 | ||||
| 	  -I${RV_ROOT}/testbench -elaborate  -snapshot ${snapshot} | ||||
| 	  -I${RV_ROOT}/testbench -elaborate  -snapshot ${snapshot} $(profile) | ||||
| 	touch irun-build | ||||
| 
 | ||||
| riviera-build: ${TBFILES} ${BUILD_DIR}/defines.h | ||||
| 	vlib work | ||||
| 	vlog -work work \
 | ||||
| 		-err VCP2694 W1 \
 | ||||
| 		+incdir+${RV_ROOT}/design/lib \
 | ||||
| 		+incdir+${RV_ROOT}/design/include \
 | ||||
| 		+incdir+${BUILD_DIR} \
 | ||||
| 		-y ${RV_ROOT}/design/lib +libext+.v+.vh \
 | ||||
| 		$(defines) \
 | ||||
| 		-f ${RV_ROOT}/testbench/flist \
 | ||||
| 		${TBFILES} | ||||
| 	touch riviera-build | ||||
| 
 | ||||
| ############ TEST Simulation ###############################
 | ||||
| 
 | ||||
| verilator: program.hex verilator-build | ||||
| 	./obj_dir/Vtb_top | ||||
| 
 | ||||
| irun: program.hex irun-build | ||||
| 	$(IRUN) -64bit -abvglobalfailurelimit 1 +lic_queue -licqueue \
 | ||||
| 	  -status -xmlibdirpath . -xmlibdirname swerv.build \
 | ||||
| 	  -snapshot ${snapshot} -r $(snapshot) $(IRUN_DEBUG_RUN) | ||||
| 	  -snapshot ${snapshot} -r $(snapshot) $(IRUN_DEBUG_RUN) $(profile) | ||||
| 
 | ||||
| vcs: program.hex vcs-build | ||||
| 	./simv $(DEBUG_PLUS) +vcs+lic+wait  -l vcs.log | ||||
| 
 | ||||
| vlog: program.hex ${TBFILES} ${BUILD_DIR}/defines.h | ||||
| 	$(VLOG) -l vlog.log -sv -mfcu +incdir+${BUILD_DIR}+${RV_ROOT}/design/include+${RV_ROOT}/design/lib\
 | ||||
|         $(defines) -f ${RV_ROOT}/testbench/flist ${TBFILES} -R ${DEBUG_PLUS} | ||||
|         $(defines) -f ${RV_ROOT}/testbench/flist ${TBFILES}  -R +nowarn3829 +nowarn2583 ${DEBUG_PLUS} | ||||
| 
 | ||||
| riviera: program.hex riviera-build | ||||
| 	vsim -c -lib work ${DEBUG_PLUS} ${RIVIERA_DEBUG} tb_top -do "run -all; exit" -l riviera.log | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ############ TEST build ###############################
 | ||||
|      | ||||
| ifeq ($(shell which $(GCC_PREFIX)-gcc 2> /dev/null),) | ||||
| program.hex: ${BUILD_DIR}/defines.h | ||||
| 	@echo " !!! No $(GCC_PREFIX)-gcc in path, using canned hex files !!" | ||||
| 	cp ${HEX_DIR}/$(TEST).program.hex program.hex | ||||
| 	cp ${HEX_DIR}/$(TEST).data.hex data.hex | ||||
| 	cp ${HEX_DIR}/$(TEST).hex program.hex | ||||
| else | ||||
| ifneq (,$(wildcard $(TEST_DIR)/$(TEST).makefile)) | ||||
| program.hex: | ||||
| 	@echo Building $(TEST) via $(TEST_DIR)/$(TEST).makefile | ||||
| 	$(MAKE) -f $(TEST_DIR)/$(TEST).makefile | ||||
| else | ||||
| program.hex: $(TEST).o $(LINK) | ||||
| program.hex: $(OFILES) $(LINK) | ||||
| 	@echo Building $(TEST) | ||||
| 	$(GCC_PREFIX)-ld -m elf32lriscv --discard-none -T$(LINK) -o $(TEST).exe $(TEST).o | ||||
| 	$(GCC_PREFIX)-objcopy -O verilog --only-section ".data*" --change-section-lma .data*-0x10000 $(TEST).exe data.hex | ||||
| 	$(GCC_PREFIX)-objcopy -O verilog --only-section ".text*"  $(TEST).exe program.hex | ||||
| 	$(GCC_PREFIX)-gcc -Wl,-m,elf32lriscv -Wl,--discard-none -T$(LINK) -o $(TEST).exe $(OFILES) -nostartfiles -nostdlib $(TEST_LIBS) | ||||
| 	$(GCC_PREFIX)-objcopy -O verilog  $(TEST).exe program.hex | ||||
| 	$(GCC_PREFIX)-objdump -S  $(TEST).exe > $(TEST).dis | ||||
| 	$(GCC_PREFIX)-nm -f posix -C $(TEST).exe > $(TEST).tbl | ||||
| 	@echo Completed building $(TEST) | ||||
| 
 | ||||
| 
 | ||||
| %.o : %.s ${BUILD_DIR}/defines.h | ||||
| 	$(GCC_PREFIX)-cpp -I${BUILD_DIR}  $<  > $(TEST).cpp.s | ||||
| 	$(GCC_PREFIX)-as -march=rv32gc $(TEST).cpp.s -o $(TEST).o | ||||
| 	$(GCC_PREFIX)-cpp -I${BUILD_DIR}  $<  > $*.cpp.s | ||||
| 	$(GCC_PREFIX)-as ${ABI} $*.cpp.s -o $@ | ||||
| 
 | ||||
| TEST_CFLAGS = -g -O3 -funroll-all-loops | ||||
| ABI = -mabi=ilp32 -march=rv32imc | ||||
| 
 | ||||
| %.o : %.c ${BUILD_DIR}/defines.h | ||||
| 	$(GCC_PREFIX)-gcc -I${BUILD_DIR} ${TEST_CFLAGS} ${ABI} -nostdlib -c $< -o $@	 | ||||
| 	$(GCC_PREFIX)-gcc ${includes} ${TEST_CFLAGS} -DCOMPILER_FLAGS="\"${TEST_CFLAGS}\"" ${ABI} -nostdlib -c $< -o $@ | ||||
| 
 | ||||
| endif | ||||
| endif | ||||
| 
 | ||||
| 
 | ||||
| help: | ||||
| 	@echo Make sure the environment variable RV_ROOT is set. | ||||
| 	@echo Possible targets: verilator vcs irun vlog help clean all verilator-build irun-build vcs-build program.hex | ||||
| 	@echo Possible targets: verilator vcs irun vlog riviera help clean all verilator-build irun-build vcs-build riviera-build program.hex | ||||
| 
 | ||||
| .PHONY: help clean verilator vcs irun vlog riviera | ||||
| 
 | ||||
| .PHONY: help clean verilator vcs irun vlog | ||||
|  |  | |||
|  | @ -1,19 +1,4 @@ | |||
| #!/usr/bin/perl | ||||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # Copyright 2020 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. | ||||
| # | ||||
| 
 | ||||
| use Getopt::Long; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,19 +1,4 @@ | |||
| #!/usr/bin/perl | ||||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # Copyright 2020 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. | ||||
| # | ||||
| 
 | ||||
| use Getopt::Long; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										15
									
								
								tools/picmap
								
								
								
								
							
							
						
						
									
										15
									
								
								tools/picmap
								
								
								
								
							|  | @ -1,19 +1,4 @@ | |||
| #!/usr/bin/perl | ||||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # Copyright 2020 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. | ||||
| # | ||||
| 
 | ||||
| use Getopt::Long; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,19 +1,4 @@ | |||
| #!/usr/bin/perl | ||||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| # Copyright 2020 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. | ||||
| # | ||||
| 
 | ||||
| use Getopt::Long; | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ 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 ("       el2_cmp_and_mux  #(\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"); | ||||
|  | @ -51,7 +51,7 @@ 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 ("       el2_cmp_and_mux  #(\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"); | ||||
|  | @ -85,7 +85,7 @@ 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 ("       el2_cmp_and_mux  #(\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"); | ||||
|  | @ -106,7 +106,7 @@ 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 ("       el2_cmp_and_mux  #(\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"); | ||||
|  | @ -130,7 +130,7 @@ 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 ("       el2_cmp_and_mux  #(\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"); | ||||
|  | @ -151,7 +151,7 @@ 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 ("       el2_cmp_and_mux  #(\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"); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue