Branch 1.3
This commit is contained in:
parent
7570549cf7
commit
2d26189faf
58
README.md
58
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
|
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
|
├── tools # Scripts/Makefiles
|
||||||
└── testbench # (Very) simple testbench
|
└── testbench # (Very) simple testbench
|
||||||
├── asm # Example assembly files
|
├── asm # Example assembly files
|
||||||
└── hex # Canned demo hex files
|
├── hex # Canned demo hex files
|
||||||
|
└── tests # Example tests
|
||||||
|
|
||||||
## Dependencies
|
## 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*)
|
- 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.
|
installed so that it can be used to prepare RISCV binaries to run.
|
||||||
|
|
||||||
## Quickstart guide
|
## 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.
|
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
|
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 :
|
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
|
├── perl_configs.pl # Perl %configs hash for scripting
|
||||||
├── pic_map_auto.h # PIC memory map based on configure size
|
├── pic_map_auto.h # PIC memory map based on configure size
|
||||||
└── whisper.json # JSON file for swerv-iss
|
└── 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.
|
to the bus.
|
||||||
|
|
||||||
|
|
||||||
The simulation produces output on the screen like:
|
The simulation produces output on the screen like: u
|
||||||
```
|
```
|
||||||
|
|
||||||
VerilatorTB: Start of sim
|
VerilatorTB: Start of sim
|
||||||
|
@ -130,8 +140,6 @@ The simulation generates following files:
|
||||||
gtkwave or similar waveform viewers.
|
gtkwave or similar waveform viewers.
|
||||||
|
|
||||||
You can re-execute simulation using:
|
You can re-execute simulation using:
|
||||||
` ./obj_dir/Vtb_top `
|
|
||||||
or
|
|
||||||
`make -f $RV_ROOT/tools/Makefile verilator`
|
`make -f $RV_ROOT/tools/Makefile verilator`
|
||||||
|
|
||||||
|
|
||||||
|
@ -143,20 +151,20 @@ The simulation run/build command has following generic form:
|
||||||
where:
|
where:
|
||||||
```
|
```
|
||||||
<simulator> - can be 'verilator' (by default) 'irun' - Cadence xrun, 'vcs' - Synopsys VCS, 'vlog' Mentor Questa
|
<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.
|
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'
|
<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 - 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
|
<snapshot> - run and build executable model of custom CPU configuration, remember to provide 'snapshot' argument
|
||||||
for runs on custom configurations.
|
for runs on custom configurations.
|
||||||
|
CONF_PARAMS - allows to provide -set options to swerv.conf script to alter predefined EL2 targets parameters
|
||||||
```
|
```
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
make -f $RV_ROOT/tools/Makefile verilator TEST=cmark
|
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:
|
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]
|
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,
|
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
|
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
|
how to create `program.hex` file used by simulation. The private makefile should be in the same directory
|
||||||
as the test source.
|
as the test source. See examples in `testbench/asm` directory.
|
||||||
*(`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)*.
|
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.
|
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:
|
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_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
|
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 - coremark benchmark running with code and data in external memories
|
||||||
cmark_dccm - the same as above, running data and stack from DCCM (faster)
|
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.
|
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.
|
**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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -108,14 +108,14 @@ import el2_pkg::*;
|
||||||
|
|
||||||
// general inputs
|
// general inputs
|
||||||
input logic clk,
|
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 dbg_rst_l,
|
||||||
input logic clk_override,
|
input logic clk_override,
|
||||||
input logic scan_mode
|
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;
|
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;
|
state_t dbg_state;
|
||||||
|
@ -132,32 +132,43 @@ import el2_pkg::*;
|
||||||
|
|
||||||
// data 0
|
// data 0
|
||||||
logic [31:0] data0_din;
|
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
|
// data 1
|
||||||
logic [31:0] data1_din;
|
logic [31:0] data1_din;
|
||||||
logic data1_reg_wren, data1_reg_wren0;
|
logic data1_reg_wren, data1_reg_wren0, data1_reg_wren1;
|
||||||
// abstractcs
|
// abstractcs
|
||||||
logic abstractcs_busy_wren;
|
logic abstractcs_busy_wren;
|
||||||
logic abstractcs_busy_din;
|
logic abstractcs_busy_din;
|
||||||
logic [2:0] abstractcs_error_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_sel0, abstractcs_error_sel1, abstractcs_error_sel2, abstractcs_error_sel3, abstractcs_error_sel4, abstractcs_error_sel5, abstractcs_error_sel6;
|
||||||
logic abstractcs_error_selor;
|
logic dbg_sb_bus_error;
|
||||||
|
// abstractauto
|
||||||
|
logic abstractauto_reg_wren;
|
||||||
|
logic [1:0] abstractauto_reg;
|
||||||
|
|
||||||
// dmstatus
|
// dmstatus
|
||||||
logic dmstatus_resumeack_wren;
|
logic dmstatus_resumeack_wren;
|
||||||
logic dmstatus_resumeack_din;
|
logic dmstatus_resumeack_din;
|
||||||
logic dmstatus_havereset_wren;
|
logic dmstatus_haveresetn_wren;
|
||||||
logic dmstatus_havereset_rst;
|
|
||||||
logic dmstatus_resumeack;
|
logic dmstatus_resumeack;
|
||||||
logic dmstatus_unavail;
|
logic dmstatus_unavail;
|
||||||
logic dmstatus_running;
|
logic dmstatus_running;
|
||||||
logic dmstatus_halted;
|
logic dmstatus_halted;
|
||||||
logic dmstatus_havereset;
|
logic dmstatus_havereset, dmstatus_haveresetn;
|
||||||
|
|
||||||
// dmcontrol
|
// dmcontrol
|
||||||
|
logic resumereq;
|
||||||
logic dmcontrol_wren, dmcontrol_wren_Q;
|
logic dmcontrol_wren, dmcontrol_wren_Q;
|
||||||
// command
|
// 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 [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
|
// needed to send the read data back for dmi reads
|
||||||
logic [31:0] dmi_reg_rdata_din;
|
logic [31:0] dmi_reg_rdata_din;
|
||||||
|
|
||||||
|
@ -176,6 +187,7 @@ import el2_pkg::*;
|
||||||
logic [2:0] sbcs_sberror_din;
|
logic [2:0] sbcs_sberror_din;
|
||||||
logic sbcs_unaligned;
|
logic sbcs_unaligned;
|
||||||
logic sbcs_illegal_size;
|
logic sbcs_illegal_size;
|
||||||
|
logic [19:15] sbcs_reg_int;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
logic sbdata0_reg_wren0;
|
logic sbdata0_reg_wren0;
|
||||||
|
@ -197,6 +209,24 @@ import el2_pkg::*;
|
||||||
logic sbreadondata_access;
|
logic sbreadondata_access;
|
||||||
logic sbdata0wr_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_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_read, sb_bus_rsp_write;
|
||||||
logic sb_bus_rsp_error;
|
logic sb_bus_rsp_error;
|
||||||
|
@ -208,6 +238,14 @@ import el2_pkg::*;
|
||||||
logic [31:0] sbdata0_reg;
|
logic [31:0] sbdata0_reg;
|
||||||
logic [31:0] sbdata1_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;
|
logic dbg_dm_rst_l;
|
||||||
|
|
||||||
//clken
|
//clken
|
||||||
|
@ -219,10 +257,10 @@ import el2_pkg::*;
|
||||||
|
|
||||||
// clocking
|
// clocking
|
||||||
// used for the abstract commands.
|
// 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
|
// 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 dbg_free_cgc (.en(dbg_free_clken), .l1clk(dbg_free_clk), .*);
|
||||||
rvoclkhdr sb_free_cgc (.en(sb_free_clken), .l1clk(sb_free_clk), .*);
|
rvoclkhdr sb_free_cgc (.en(sb_free_clken), .l1clk(sb_free_clk), .*);
|
||||||
|
@ -231,23 +269,25 @@ import el2_pkg::*;
|
||||||
|
|
||||||
// Reset logic
|
// Reset logic
|
||||||
assign dbg_dm_rst_l = dbg_rst_l & (dmcontrol_reg[0] | scan_mode);
|
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
|
// 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
|
// 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[31:29] = 3'b1;
|
||||||
assign sbcs_reg[28:23] = '0;
|
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[11:5] = 7'h20;
|
||||||
assign sbcs_reg[4:0] = 5'b01111;
|
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]) |
|
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
|
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_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_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 #(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));
|
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]) |
|
assign sbcs_unaligned = ((sbcs_reg[19:17] == 3'b001) & sbaddress0_reg[0]) |
|
||||||
|
@ -296,6 +336,7 @@ import el2_pkg::*;
|
||||||
assign dmcontrol_wren = (dmi_reg_addr == 7'h10) & dmi_reg_en & dmi_reg_wr_en;
|
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 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 #(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));
|
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));
|
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
|
// dmstatus register bits that are implemented
|
||||||
// [19:18]-havereset,[17:16]-resume ack, [9:8]-halted, [3:0]-version
|
// [19:18]-havereset,[17:16]-resume ack, [9:8]-halted, [3:0]-version
|
||||||
// rest all the bits are zeroed out
|
// 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[31:20] = '0;
|
||||||
assign dmstatus_reg[19:18] = {2{dmstatus_havereset}};
|
assign dmstatus_reg[19:18] = {2{dmstatus_havereset}};
|
||||||
assign dmstatus_reg[15:14] = '0;
|
assign dmstatus_reg[15:14] = '0;
|
||||||
|
@ -314,18 +356,18 @@ import el2_pkg::*;
|
||||||
assign dmstatus_reg[9:8] = {2{dmstatus_halted}};
|
assign dmstatus_reg[9:8] = {2{dmstatus_halted}};
|
||||||
assign dmstatus_reg[3:0] = 4'h2;
|
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_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_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_rst = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[28] & dmi_reg_en & dmi_reg_wr_en;
|
assign dmstatus_havereset = ~dmstatus_haveresetn;
|
||||||
|
|
||||||
assign dmstatus_unavail = dmcontrol_reg[1] | ~rst_l;
|
assign dmstatus_unavail = dmcontrol_reg[1] | ~rst_l;
|
||||||
assign dmstatus_running = ~(dmstatus_unavail | dmstatus_halted);
|
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));
|
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));
|
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_haveresetn_reg (.din(1'b1), .dout(dmstatus_haveresetn), .en(dmstatus_haveresetn_wren), .rst_l(rst_l), .clk(dbg_free_clk));
|
||||||
|
|
||||||
// haltsum0 register
|
// haltsum0 register
|
||||||
assign haltsum0_reg[31:1] = '0;
|
assign haltsum0_reg[31:1] = '0;
|
||||||
|
@ -337,54 +379,76 @@ import el2_pkg::*;
|
||||||
assign abstractcs_reg[11] = '0;
|
assign abstractcs_reg[11] = '0;
|
||||||
assign abstractcs_reg[7:4] = '0;
|
assign abstractcs_reg[7:4] = '0;
|
||||||
assign abstractcs_reg[3:0] = 4'h2; // One data register
|
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] = 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
|
||||||
assign abstractcs_error_din[2:0] = ({3{abstractcs_error_sel0}} & 3'b001) | // writing command or abstractcs while a command was executing. Or accessing data0
|
abstractcs_error_sel2 ? 3'b011 : // exception while running command
|
||||||
({3{abstractcs_error_sel1}} & 3'b010) | // writing a non-zero command to cmd field of command
|
abstractcs_error_sel3 ? 3'b100 : // writing a comnand when not in the halted state
|
||||||
({3{abstractcs_error_sel2}} & 3'b011) | // exception while running command
|
abstractcs_error_sel4 ? 3'b101 : // Bus error
|
||||||
({3{abstractcs_error_sel3}} & 3'b100) | // writing a comnand when not in the halted state
|
abstractcs_error_sel5 ? 3'b111 : // unaligned or illegal size abstract memory command
|
||||||
({3{abstractcs_error_sel4}} & 3'b111) | // unaligned abstract memory command
|
abstractcs_error_sel6 ? (~dmi_reg_wdata[10:8] & abstractcs_reg[10:8]) : //W1C
|
||||||
({3{abstractcs_error_sel5}} & ~dmi_reg_wdata[10:8] & abstractcs_reg[10:8]) | // W1C
|
abstractcs_reg[10:8]; //hold
|
||||||
({3{~abstractcs_error_selor}} & abstractcs_reg[10:8]); // hold
|
|
||||||
|
|
||||||
rvdffs #(1) dmabstractcs_busy_reg (.din(abstractcs_busy_din), .dout(abstractcs_reg[12]), .en(abstractcs_busy_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk));
|
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));
|
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 register - implemented all the bits in this register
|
||||||
// command[16] = 1: write, 0: read
|
// command[16] = 1: write, 0: read
|
||||||
// Size - 2, Bits Not implemented: 23 (aamvirtual), 19-autoincrement, 18-postexec, 17-transfer
|
assign execute_command_ns = command_wren |
|
||||||
assign command_wren = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en & (dbg_state == HALTED);
|
(dmi_reg_en & ~abstractcs_reg[12] & (((dmi_reg_addr == 7'h4) & abstractauto_reg[0]) | ((dmi_reg_addr == 7'h5) & abstractauto_reg[1])));
|
||||||
assign command_din[31:0] = {dmi_reg_wdata[31:24],1'b0,dmi_reg_wdata[22:20],3'b0,dmi_reg_wdata[16:0]};
|
assign command_wren = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en;
|
||||||
rvdffe #(32) dmcommand_reg (.*, .din(command_din[31:0]), .dout(command_reg[31:0]), .en(command_wren), .rst_l(dbg_dm_rst_l));
|
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
|
// data0 reg
|
||||||
assign data0_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h4) & (dbg_state == HALTED));
|
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 == CMD_WAIT) & ~command_reg[16];
|
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;
|
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]) |
|
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_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));
|
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
|
// data 1
|
||||||
assign data1_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h5) & (dbg_state == HALTED));
|
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_wren = data1_reg_wren0;
|
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));
|
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.
|
// FSM to control the debug mode entry, command send/recieve, and Resume flow.
|
||||||
always_comb begin
|
always_comb begin
|
||||||
|
@ -392,45 +456,74 @@ import el2_pkg::*;
|
||||||
dbg_state_en = 1'b0;
|
dbg_state_en = 1'b0;
|
||||||
abstractcs_busy_wren = 1'b0;
|
abstractcs_busy_wren = 1'b0;
|
||||||
abstractcs_busy_din = 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_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)
|
case (dbg_state)
|
||||||
IDLE: begin
|
IDLE: begin
|
||||||
dbg_nxtstate = (dmstatus_reg[9] | dec_tlu_mpc_halted_only) ? HALTED : HALTING; // initiate the halt command to the core
|
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_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] & ~dmcontrol_reg[1]; // only when jtag has written the halt_req bit in the control. Removed debug mode qualification during MPC changes
|
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
|
end
|
||||||
HALTING : begin
|
HALTING : begin
|
||||||
dbg_nxtstate = dmcontrol_reg[1] ? IDLE : HALTED; // Goto HALTED once the core sends an ACK
|
dbg_nxtstate = HALTED; // Goto HALTED once the core sends an ACK
|
||||||
dbg_state_en = dmstatus_reg[9] | dmcontrol_reg[1]; // core indicates halted
|
dbg_state_en = dmstatus_reg[9] | dec_tlu_mpc_halted_only; // core indicates halted
|
||||||
end
|
end
|
||||||
HALTED: begin
|
HALTED: begin
|
||||||
// wait for halted to go away before send to resume. Else start of new command
|
// 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
|
(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 ???
|
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 == CMD_START); // write busy when a new command was written by jtag
|
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;
|
abstractcs_busy_din = 1'b1;
|
||||||
dbg_resume_req = dbg_state_en & (dbg_nxtstate == RESUMING); // single cycle pulse to core if resuming
|
dbg_resume_req = dbg_state_en & (dbg_nxtstate == RESUMING); // single cycle pulse to core if resuming
|
||||||
end
|
end
|
||||||
CMD_START: begin
|
CORE_CMD_START: begin
|
||||||
dbg_nxtstate = dmcontrol_reg[1] ? IDLE : (|abstractcs_reg[10:8]) ? CMD_DONE : CMD_WAIT; // new command sent to the core
|
// Don't execute the command if cmderror or transfer=0 for abstract register access
|
||||||
dbg_state_en = dbg_cmd_valid | (|abstractcs_reg[10:8]) | dmcontrol_reg[1];
|
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
|
end
|
||||||
CMD_WAIT: begin
|
CORE_CMD_WAIT: begin
|
||||||
dbg_nxtstate = dmcontrol_reg[1] ? IDLE : CMD_DONE;
|
dbg_nxtstate = CMD_DONE;
|
||||||
dbg_state_en = core_dbg_cmd_done | dmcontrol_reg[1]; // go to done state for one cycle after completing current command
|
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
|
end
|
||||||
CMD_DONE: begin
|
CMD_DONE: begin
|
||||||
dbg_nxtstate = dmcontrol_reg[1] ? IDLE : HALTED;
|
dbg_nxtstate = HALTED;
|
||||||
dbg_state_en = 1'b1;
|
dbg_state_en = 1'b1;
|
||||||
abstractcs_busy_wren = dbg_state_en; // remove the busy bit from the abstracts ( bit 12 )
|
abstractcs_busy_wren = dbg_state_en; // remove the busy bit from the abstracts ( bit 12 )
|
||||||
abstractcs_busy_din = 1'b0;
|
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
|
end
|
||||||
RESUMING : begin
|
RESUMING : begin
|
||||||
dbg_nxtstate = IDLE;
|
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
|
end
|
||||||
default : begin
|
default : begin
|
||||||
dbg_nxtstate = IDLE;
|
dbg_nxtstate = IDLE;
|
||||||
|
@ -439,16 +532,23 @@ import el2_pkg::*;
|
||||||
abstractcs_busy_din = 1'b0;
|
abstractcs_busy_din = 1'b0;
|
||||||
dbg_halt_req = 1'b0; // single pulse output to the core
|
dbg_halt_req = 1'b0; // single pulse output to the core
|
||||||
dbg_resume_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
|
end
|
||||||
endcase
|
endcase
|
||||||
end // always_comb begin
|
end // always_comb begin
|
||||||
|
|
||||||
assign dmi_reg_rdata_din[31:0] = ({32{dmi_reg_addr == 7'h4}} & data0_reg[31:0]) |
|
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'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'h11}} & dmstatus_reg[31:0]) |
|
||||||
({32{dmi_reg_addr == 7'h16}} & abstractcs_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'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'h40}} & haltsum0_reg[31:0]) |
|
||||||
({32{dmi_reg_addr == 7'h38}} & sbcs_reg[31:0]) |
|
({32{dmi_reg_addr == 7'h38}} & sbcs_reg[31:0]) |
|
||||||
({32{dmi_reg_addr == 7'h39}} & sbaddress0_reg[31:0]) |
|
({32{dmi_reg_addr == 7'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));
|
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
|
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), .*);
|
||||||
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));
|
|
||||||
|
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
|
// 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_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_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_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_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_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_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
|
// 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
|
// system bus FSM
|
||||||
always_comb begin
|
always_comb begin
|
||||||
|
@ -483,7 +598,7 @@ import el2_pkg::*;
|
||||||
case (sb_state)
|
case (sb_state)
|
||||||
SBIDLE: begin
|
SBIDLE: begin
|
||||||
sb_nxtstate = sbdata0wr_access ? WAIT_WR : WAIT_RD;
|
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_wren = sb_state_en; // set the single read bit if it is a singlread command
|
||||||
sbcs_sbbusy_din = 1'b1;
|
sbcs_sbbusy_din = 1'b1;
|
||||||
sbcs_sberror_wren = sbcs_wren & (|dmi_reg_wdata[14:12]); // write to clear the error bits
|
sbcs_sberror_wren = sbcs_wren & (|dmi_reg_wdata[14:12]); // write to clear the error bits
|
||||||
|
@ -491,13 +606,13 @@ import el2_pkg::*;
|
||||||
end
|
end
|
||||||
WAIT_RD: begin
|
WAIT_RD: begin
|
||||||
sb_nxtstate = (sbcs_unaligned | sbcs_illegal_size) ? DONE : CMD_RD;
|
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_wren = sbcs_unaligned | sbcs_illegal_size;
|
||||||
sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100;
|
sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100;
|
||||||
end
|
end
|
||||||
WAIT_WR: begin
|
WAIT_WR: begin
|
||||||
sb_nxtstate = (sbcs_unaligned | sbcs_illegal_size) ? DONE : CMD_WR;
|
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_wren = sbcs_unaligned | sbcs_illegal_size;
|
||||||
sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100;
|
sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100;
|
||||||
end
|
end
|
||||||
|
@ -534,8 +649,7 @@ import el2_pkg::*;
|
||||||
sb_state_en = 1'b1;
|
sb_state_en = 1'b1;
|
||||||
sbcs_sbbusy_wren = 1'b1; // reset the single read
|
sbcs_sbbusy_wren = 1'b1; // reset the single read
|
||||||
sbcs_sbbusy_din = 1'b0;
|
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
|
end
|
||||||
default : begin
|
default : begin
|
||||||
sb_nxtstate = SBIDLE;
|
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));
|
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
|
// Generic bus response signals
|
||||||
assign sb_bus_cmd_read = sb_axi_arvalid & sb_axi_arready;
|
assign sb_bus_cmd_read = sb_axi_arvalid & sb_axi_arready;
|
||||||
assign sb_bus_cmd_write_addr = sb_axi_awvalid & sb_axi_awready;
|
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])));
|
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
|
// AXI Request signals
|
||||||
assign sb_axi_awvalid = (sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR);
|
assign sb_axi_awvalid = sb_abmem_cmd_awvalid | sb_cmd_awvalid;
|
||||||
assign sb_axi_awaddr[31:0] = sbaddress0_reg[31:0];
|
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_awid[pt.SB_BUS_TAG-1:0] = '0;
|
||||||
assign sb_axi_awsize[2:0] = sbcs_reg[19:17];
|
assign sb_axi_awsize[2:0] = sb_axi_size[2:0];
|
||||||
assign sb_axi_awprot[2:0] = '0;
|
assign sb_axi_awprot[2:0] = 3'b001;
|
||||||
assign sb_axi_awcache[3:0] = 4'b1111;
|
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_awlen[7:0] = '0;
|
||||||
assign sb_axi_awburst[1:0] = 2'b01;
|
assign sb_axi_awburst[1:0] = 2'b01;
|
||||||
assign sb_axi_awqos[3:0] = '0;
|
assign sb_axi_awqos[3:0] = '0;
|
||||||
assign sb_axi_awlock = '0;
|
assign sb_axi_awlock = '0;
|
||||||
|
|
||||||
assign sb_axi_wvalid = (sb_state == CMD_WR) | (sb_state == CMD_WR_DATA);
|
assign sb_axi_wvalid = sb_abmem_cmd_wvalid | sb_cmd_wvalid;
|
||||||
assign sb_axi_wdata[63:0] = ({64{(sbcs_reg[19:17] == 3'h0)}} & {8{sbdata0_reg[7:0]}}) |
|
assign sb_axi_wdata[63:0] = ({64{(sb_axi_size[2:0] == 3'h0)}} & {8{sb_axi_wrdata[7:0]}}) |
|
||||||
({64{(sbcs_reg[19:17] == 3'h1)}} & {4{sbdata0_reg[15:0]}}) |
|
({64{(sb_axi_size[2:0] == 3'h1)}} & {4{sb_axi_wrdata[15:0]}}) |
|
||||||
({64{(sbcs_reg[19:17] == 3'h2)}} & {2{sbdata0_reg[31:0]}}) |
|
({64{(sb_axi_size[2:0] == 3'h2)}} & {2{sb_axi_wrdata[31:0]}}) |
|
||||||
({64{(sbcs_reg[19:17] == 3'h3)}} & {sbdata1_reg[31:0],sbdata0_reg[31:0]});
|
({64{(sb_axi_size[2:0] == 3'h3)}} & {sb_axi_wrdata[63:0]});
|
||||||
assign sb_axi_wstrb[7:0] = ({8{(sbcs_reg[19:17] == 3'h0)}} & (8'h1 << sbaddress0_reg[2:0])) |
|
assign sb_axi_wstrb[7:0] = ({8{(sb_axi_size[2:0] == 3'h0)}} & (8'h1 << sb_axi_addr[2:0])) |
|
||||||
({8{(sbcs_reg[19:17] == 3'h1)}} & (8'h3 << {sbaddress0_reg[2:1],1'b0})) |
|
({8{(sb_axi_size[2:0] == 3'h1)}} & (8'h3 << {sb_axi_addr[2:1],1'b0})) |
|
||||||
({8{(sbcs_reg[19:17] == 3'h2)}} & (8'hf << {sbaddress0_reg[2],2'b0})) |
|
({8{(sb_axi_size[2:0] == 3'h2)}} & (8'hf << {sb_axi_addr[2],2'b0})) |
|
||||||
({8{(sbcs_reg[19:17] == 3'h3)}} & 8'hff);
|
({8{(sb_axi_size[2:0] == 3'h3)}} & 8'hff);
|
||||||
assign sb_axi_wlast = '1;
|
assign sb_axi_wlast = '1;
|
||||||
|
|
||||||
assign sb_axi_arvalid = (sb_state == CMD_RD);
|
assign sb_axi_arvalid = sb_abmem_cmd_arvalid | sb_cmd_arvalid;
|
||||||
assign sb_axi_araddr[31:0] = sbaddress0_reg[31:0];
|
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_arid[pt.SB_BUS_TAG-1:0] = '0;
|
||||||
assign sb_axi_arsize[2:0] = sbcs_reg[19:17];
|
assign sb_axi_arsize[2:0] = sb_axi_size[2:0];
|
||||||
assign sb_axi_arprot[2:0] = '0;
|
assign sb_axi_arprot[2:0] = 3'b001;
|
||||||
assign sb_axi_arcache[3:0] = 4'b0;
|
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_arlen[7:0] = '0;
|
||||||
assign sb_axi_arburst[1:0] = 2'b01;
|
assign sb_axi_arburst[1:0] = 2'b01;
|
||||||
assign sb_axi_arqos[3:0] = '0;
|
assign sb_axi_arqos[3:0] = '0;
|
||||||
|
@ -600,14 +737,17 @@ import el2_pkg::*;
|
||||||
assign sb_axi_bready = 1'b1;
|
assign sb_axi_bready = 1'b1;
|
||||||
|
|
||||||
assign sb_axi_rready = 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)) |
|
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{sbcs_reg[19:17] == 3'h1}} & ((sb_axi_rdata[63:0] >> 16*sbaddress0_reg[2:1]) & 64'hffff)) |
|
({64{sb_axi_size == 3'h1}} & ((sb_axi_rdata[63:0] >> 16*sb_axi_addr[2:1]) & 64'hffff)) |
|
||||||
({64{sbcs_reg[19:17] == 3'h2}} & ((sb_axi_rdata[63:0] >> 32*sbaddress0_reg[2]) & 64'hffff_ffff)) |
|
({64{sb_axi_size == 3'h2}} & ((sb_axi_rdata[63:0] >> 32*sb_axi_addr[2]) & 64'hffff_ffff)) |
|
||||||
({64{sbcs_reg[19:17] == 3'h3}} & sb_axi_rdata[63:0]);
|
({64{sb_axi_size == 3'h3}} & sb_axi_rdata[63:0]);
|
||||||
|
|
||||||
`ifdef ASSERT_ON
|
`ifdef RV_ASSERT_ON
|
||||||
// assertion.
|
// assertion.
|
||||||
// when the resume_ack is asserted then the dec_tlu_dbg_halted should be 0
|
// 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));
|
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
|
`endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -209,6 +209,7 @@ csr[ csr_mpmc ] = { csr_mpmc }
|
||||||
csr[ csr_mcpc ] = { csr_mcpc presync postsync }
|
csr[ csr_mcpc ] = { csr_mcpc presync postsync }
|
||||||
csr[ csr_meicidpl ] = { csr_meicidpl }
|
csr[ csr_meicidpl ] = { csr_meicidpl }
|
||||||
csr[ csr_mcgc ] = { csr_mcgc }
|
csr[ csr_mcgc ] = { csr_mcgc }
|
||||||
|
csr[ csr_mcountinhibit] = { csr_mcountinhibit presync postsync }
|
||||||
csr[ csr_mfdc ] = { csr_mfdc presync postsync }
|
csr[ csr_mfdc ] = { csr_mfdc presync postsync }
|
||||||
csr[ csr_dcsr ] = { csr_dcsr }
|
csr[ csr_dcsr ] = { csr_dcsr }
|
||||||
csr[ csr_dpc ] = { csr_dpc }
|
csr[ csr_dpc ] = { csr_dpc }
|
||||||
|
|
|
@ -1,6 +1,146 @@
|
||||||
|
|
||||||
.definition
|
.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]
|
add = [0000000..........000.....0110011]
|
||||||
addi = [.................000.....0010011]
|
addi = [.................000.....0010011]
|
||||||
|
|
||||||
|
@ -206,15 +346,133 @@ rv32i = {
|
||||||
rem
|
rem
|
||||||
fence
|
fence
|
||||||
fence_i
|
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
|
pm_alu
|
||||||
}
|
}
|
||||||
|
|
||||||
.decode
|
.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[mul] = { mul rs1 rs2 rd low }
|
||||||
rv32i[mulh] = { mul rs1 rs2 rd rs1_sign rs2_sign }
|
rv32i[mulh] = { mul rs1 rs2 rd rs1_sign rs2_sign }
|
||||||
rv32i[mulhu] = { mul rs1 rs2 rd }
|
rv32i[mulhu] = { mul rs1 rs2 rd }
|
||||||
rv32i[mulhsu] = { mul rs1 rs2 rd rs1_sign }
|
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[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[div] = { div rs1 rs2 rd }
|
||||||
rv32i[divu] = { div rs1 rs2 rd unsign }
|
rv32i[divu] = { div rs1 rs2 rd unsign }
|
||||||
|
@ -321,3 +579,4 @@ rv32i[csrwi] = { alu rd csr_write csr_imm }
|
||||||
|
|
||||||
|
|
||||||
.end
|
.end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input logic 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_clk,
|
input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
|
||||||
input logic active_clk,
|
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, // Stall on external interrupt
|
||||||
output logic dec_extint_stall,
|
|
||||||
|
|
||||||
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_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 rst_l, // reset, active low
|
||||||
input logic [31:1] rst_vec, // reset vector, from core pins
|
input logic [31:1] rst_vec, // reset vector, from core pins
|
||||||
|
|
||||||
|
@ -60,7 +62,7 @@ import el2_pkg::*;
|
||||||
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
|
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
|
input logic [31:4] core_id, // CORE ID
|
||||||
//
|
|
||||||
// external MPC halt/run interface
|
// external MPC halt/run interface
|
||||||
input logic mpc_debug_halt_req, // Async halt request
|
input logic mpc_debug_halt_req, // Async halt request
|
||||||
input logic mpc_debug_run_req, // Async run request
|
input logic mpc_debug_run_req, // Async run request
|
||||||
|
@ -118,9 +120,9 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
input logic ifu_i0_icaf, // icache access fault
|
input logic ifu_i0_icaf, // icache access fault
|
||||||
input logic [1:0] ifu_i0_icaf_type,
|
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_icaf_second, // i0 has access fault on second 2B of 4B inst
|
||||||
input logic ifu_i0_dbecc, // icache/iccm double-bit error
|
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
|
||||||
|
@ -129,6 +131,7 @@ import el2_pkg::*;
|
||||||
input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index, // BP index
|
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.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.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 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_single_ecc_error_incr, // LSU inc SB error counter
|
||||||
|
@ -214,6 +217,8 @@ import el2_pkg::*;
|
||||||
input logic exu_i0_br_mp_r, // mispredict
|
input logic exu_i0_br_mp_r, // mispredict
|
||||||
input logic exu_i0_br_middle_r, // middle of bank
|
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
|
input logic exu_i0_br_way_r, // way hit or repl
|
||||||
|
|
||||||
output logic dec_i0_rs1_en_d, // Qualify GPR RS1 data
|
output logic dec_i0_rs1_en_d, // Qualify GPR RS1 data
|
||||||
|
@ -227,27 +232,29 @@ import el2_pkg::*;
|
||||||
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_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 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 [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 [3: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_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_result_r, // Result R-stage
|
||||||
output logic [31:0] dec_i0_rs2_bypass_data_d, // rs2 bypass data
|
|
||||||
|
|
||||||
output el2_lsu_pkt_t lsu_p, // lsu packet
|
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_mul_pkt_t mul_p, // mul packet
|
||||||
output el2_div_pkt_t div_p, // div packet
|
output el2_div_pkt_t div_p, // div packet
|
||||||
output logic dec_div_cancel, // cancel divide operation
|
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_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 [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_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_fence_i_r, // flush is a fence_i rfnpc, flush icache
|
||||||
|
@ -266,6 +273,8 @@ import el2_pkg::*;
|
||||||
output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] i0_predict_index_d, // DEC predict index
|
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 [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 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
|
||||||
|
@ -275,7 +284,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
input logic [15:0] ifu_i0_cinst, // 16b compressed instruction
|
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
|
// 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
|
||||||
|
@ -291,11 +300,12 @@ import el2_pkg::*;
|
||||||
output logic dec_tlu_lsu_clk_override, // override load/store clock domain gating
|
output logic dec_tlu_lsu_clk_override, // override load/store clock domain gating
|
||||||
output logic dec_tlu_bus_clk_override, // override bus clock domain gating
|
output logic dec_tlu_bus_clk_override, // override bus clock domain gating
|
||||||
output logic dec_tlu_pic_clk_override, // override PIC 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_dccm_clk_override, // override DCCM clock domain gating
|
||||||
output logic dec_tlu_icm_clk_override, // override ICCM 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
|
output logic dec_tlu_i0_commit_cmt, // committed i0 instruction
|
||||||
input logic scan_mode
|
input logic scan_mode // Flop scan mode control
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -317,6 +327,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
logic [31:0] dec_i0_instr_d;
|
logic [31:0] dec_i0_instr_d;
|
||||||
|
|
||||||
|
logic dec_tlu_trace_disable;
|
||||||
logic dec_tlu_pipelining_disable;
|
logic dec_tlu_pipelining_disable;
|
||||||
|
|
||||||
|
|
||||||
|
@ -328,7 +339,6 @@ import el2_pkg::*;
|
||||||
logic [31:0] dec_csr_wrdata_r; // csr write data at wb
|
logic [31:0] dec_csr_wrdata_r; // csr write data at wb
|
||||||
|
|
||||||
logic [11:0] dec_csr_rdaddr_d; // read address for csr
|
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 dec_csr_legal_d; // csr indicates legal operation
|
||||||
|
|
||||||
logic dec_csr_wen_unq_d; // valid csr with write - for csr legal
|
logic dec_csr_wen_unq_d; // valid csr with write - for csr legal
|
||||||
|
@ -347,7 +357,7 @@ import el2_pkg::*;
|
||||||
logic dec_i0_icaf_d;
|
logic dec_i0_icaf_d;
|
||||||
|
|
||||||
logic dec_i0_dbecc_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 [3:0] dec_i0_trigger_match_d;
|
||||||
logic dec_debug_fence_d;
|
logic dec_debug_fence_d;
|
||||||
logic dec_nonblock_load_wen;
|
logic dec_nonblock_load_wen;
|
||||||
|
@ -357,10 +367,10 @@ import el2_pkg::*;
|
||||||
logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] dec_i0_bp_index;
|
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.BHT_GHR_SIZE-1:0] dec_i0_bp_fghr;
|
||||||
logic [pt.BTB_BTAG_SIZE-1:0] dec_i0_bp_btag;
|
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 [31:1] dec_tlu_i0_pc_r;
|
||||||
logic dec_tlu_i0_kill_writeb_wb;
|
logic dec_tlu_i0_kill_writeb_wb;
|
||||||
logic dec_tlu_flush_lower_wb;
|
|
||||||
logic dec_tlu_i0_valid_r;
|
logic dec_tlu_i0_valid_r;
|
||||||
|
|
||||||
logic dec_pause_state;
|
logic dec_pause_state;
|
||||||
|
@ -369,18 +379,17 @@ import el2_pkg::*;
|
||||||
|
|
||||||
logic dec_tlu_flush_extint; // Fast ext int started
|
logic dec_tlu_flush_extint; // Fast ext int started
|
||||||
|
|
||||||
logic [31:0] dec_i0_inst_wb1;
|
logic [31:0] dec_i0_inst_wb;
|
||||||
logic [31:1] dec_i0_pc_wb1;
|
logic [31:1] dec_i0_pc_wb;
|
||||||
logic dec_tlu_i0_valid_wb1, dec_tlu_int_valid_wb1;
|
logic dec_tlu_i0_valid_wb1, dec_tlu_int_valid_wb1;
|
||||||
logic [4:0] dec_tlu_exc_cause_wb1;
|
logic [4:0] dec_tlu_exc_cause_wb1;
|
||||||
logic [31:0] dec_tlu_mtval_wb1;
|
logic [31:0] dec_tlu_mtval_wb1;
|
||||||
logic dec_tlu_i0_exc_valid_wb1;
|
logic dec_tlu_i0_exc_valid_wb1;
|
||||||
|
|
||||||
logic [4:0] div_waddr_wb;
|
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;
|
assign clk_override = dec_tlu_dec_clk_override;
|
||||||
|
|
||||||
|
@ -419,14 +428,17 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
// trace
|
// trace
|
||||||
assign rv_trace_pkt.rv_i_insn_ip = dec_i0_inst_wb1[31:0];
|
assign trace_rv_trace_pkt.trace_rv_i_insn_ip = dec_i0_inst_wb[31:0];
|
||||||
assign rv_trace_pkt.rv_i_address_ip = { dec_i0_pc_wb1[31:1], 1'b0};
|
assign trace_rv_trace_pkt.trace_rv_i_address_ip = { dec_i0_pc_wb[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 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 rv_trace_pkt.rv_i_exception_ip = {dec_tlu_int_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 rv_trace_pkt.rv_i_ecause_ip = dec_tlu_exc_cause_wb1[4:0]; // replicate across ports
|
assign trace_rv_trace_pkt.trace_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 trace_rv_trace_pkt.trace_rv_i_interrupt_ip = dec_tlu_int_valid_wb1;
|
||||||
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_tval_ip = dec_tlu_mtval_wb1[31:0]; // replicate across ports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// end trace
|
// end trace
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -47,7 +47,7 @@ import el2_pkg::*;
|
||||||
logic [31:1] w0v,w1v,w2v;
|
logic [31:1] w0v,w1v,w2v;
|
||||||
logic [31:1] gpr_wr_en;
|
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]);
|
assign gpr_wr_en[31:1] = (w0v[31:1] | w1v[31:1] | w2v[31:1]);
|
||||||
for ( genvar j=1; j<32; j++ ) begin : gpr
|
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]));
|
rvdffe #(32) gprff (.*, .en(gpr_wr_en[j]), .din(gpr_in[j][31:0]), .dout(gpr_out[j][31:0]));
|
||||||
|
@ -79,7 +79,7 @@ import el2_pkg::*;
|
||||||
end
|
end
|
||||||
end // always_comb begin
|
end // always_comb begin
|
||||||
|
|
||||||
`ifdef ASSERT_ON
|
`ifdef RV_ASSERT_ON
|
||||||
|
|
||||||
logic write_collision_unused;
|
logic write_collision_unused;
|
||||||
assign write_collision_unused = ( (w0v[31:1] == w1v[31:1]) & wen0 & wen1 ) |
|
assign write_collision_unused = ( (w0v[31:1] == w1v[31:1]) & wen0 & wen1 ) |
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -29,18 +29,21 @@ import el2_pkg::*;
|
||||||
input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index, // BP index
|
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.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.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_pc4, // i0 is 4B inst else 2B
|
input logic ifu_i0_pc4, // i0 is 4B inst else 2B
|
||||||
input logic ifu_i0_valid, // i0 valid from ifu
|
input logic ifu_i0_valid, // i0 valid from ifu
|
||||||
input logic ifu_i0_icaf, // i0 instruction access fault
|
input logic ifu_i0_icaf, // i0 instruction access fault
|
||||||
input logic [1:0] ifu_i0_icaf_type, // i0 instruction access fault type
|
input logic [1:0] ifu_i0_icaf_type, // i0 instruction access fault type
|
||||||
|
|
||||||
input logic ifu_i0_icaf_f1, // i0 has access fault on second fetch group
|
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 ifu_i0_dbecc, // i0 double-bit error
|
||||||
input logic [31:0] ifu_i0_instr, // i0 instruction from the aligner
|
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 [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
|
||||||
|
@ -53,8 +56,10 @@ import el2_pkg::*;
|
||||||
output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] dec_i0_bp_index, // i0 branch index
|
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.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 [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_i0_icaf_d, // i0 instruction access fault at decode
|
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 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 [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_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_wdata_rs1_d, // put debug write data onto rs1 source: machine is halted
|
||||||
|
@ -78,12 +83,12 @@ import el2_pkg::*;
|
||||||
|
|
||||||
logic [34:0] ifu_i0_pcdata, pc0;
|
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 };
|
ifu_i0_pc[31:1], ifu_i0_pc4 };
|
||||||
|
|
||||||
assign pc0[34:0] = ifu_i0_pcdata[34:0];
|
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];
|
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_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_instr_d[31:0] = ib0[31:0];
|
||||||
|
|
||||||
assign dec_i0_brp = i0_brp;
|
assign dec_i0_brp = i0_brp;
|
||||||
assign dec_i0_bp_index = ifu_i0_bp_index;
|
assign dec_i0_bp_index = ifu_i0_bp_index;
|
||||||
assign dec_i0_bp_fghr = ifu_i0_bp_fghr;
|
assign dec_i0_bp_fghr = ifu_i0_bp_fghr;
|
||||||
assign dec_i0_bp_btag = ifu_i0_bp_btag;
|
assign dec_i0_bp_btag = ifu_i0_bp_btag;
|
||||||
|
assign dec_i0_bp_fa_index = ifu_i0_fa_index;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -31,7 +31,7 @@ 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 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;
|
logic [3:0][31:0] dec_i0_match_data;
|
||||||
|
|
|
@ -173,6 +173,7 @@ always_comb begin
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
capture_dr: begin
|
capture_dr: begin
|
||||||
|
nsr[0] = 1'b0;
|
||||||
case(1)
|
case(1)
|
||||||
dr_en[0]: nsr = {{USER_DR_LENGTH-15{1'b0}}, idle, dmi_stat, abits, version};
|
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};
|
dr_en[1]: nsr = {{AWIDTH{1'b0}}, rd_data, rd_status};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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 [2:0] iccm_dma_rtag, // Tag of the DMA req
|
||||||
input logic [63:0] iccm_dma_rdata, // iccm data for DMA read
|
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_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
|
output logic dma_iccm_stall_any, // stall iccm pipe (bubble) so that DMA can proceed
|
||||||
input logic dccm_ready, // dccm ready to accept DMA request
|
input logic dccm_ready, // dccm ready to accept DMA request
|
||||||
|
@ -154,6 +155,10 @@ module el2_dma_ctrl #(
|
||||||
logic [DEPTH_PTR-1:0] RdPtr, NxtRdPtr;
|
logic [DEPTH_PTR-1:0] RdPtr, NxtRdPtr;
|
||||||
logic WrPtrEn, RdPtrEn, RspPtrEn;
|
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_error;
|
||||||
logic dma_dbg_cmd_done_q;
|
logic dma_dbg_cmd_done_q;
|
||||||
|
|
||||||
|
@ -193,6 +198,7 @@ module el2_dma_ctrl #(
|
||||||
|
|
||||||
logic fifo_full_spec_bus;
|
logic fifo_full_spec_bus;
|
||||||
logic dbg_dma_bubble_bus;
|
logic dbg_dma_bubble_bus;
|
||||||
|
logic stall_dma_in;
|
||||||
logic dma_fifo_ready;
|
logic dma_fifo_ready;
|
||||||
|
|
||||||
logic wrbuf_en, wrbuf_data_en;
|
logic wrbuf_en, wrbuf_data_en;
|
||||||
|
@ -225,14 +231,14 @@ module el2_dma_ctrl #(
|
||||||
|
|
||||||
// FIFO inputs
|
// FIFO inputs
|
||||||
assign fifo_addr_in[31:0] = dbg_cmd_valid ? dbg_cmd_addr[31:0] : bus_cmd_addr[31:0];
|
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_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_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_posted_write_in = ~dbg_cmd_valid & bus_cmd_posted_write;
|
||||||
assign fifo_dbg_in = dbg_cmd_valid;
|
assign fifo_dbg_in = dbg_cmd_valid;
|
||||||
|
|
||||||
for (genvar i=0 ;i<32'(DEPTH); i++) begin: GenFifo
|
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])) & (DEPTH_PTR'(i) == WrPtr[DEPTH_PTR-1:0]);
|
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])) |
|
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])) |
|
((dma_address_error | dma_alignment_error) & (i == RdPtr[DEPTH_PTR-1:0])) |
|
||||||
(dccm_dma_rvalid & (i == DEPTH_PTR'(dccm_dma_rtag[2: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};
|
{(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]} :
|
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] :
|
((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 #(1) fifo_valid_dff (.din(1'b1), .dout(fifo_valid[i]), .en(fifo_cmd_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
||||||
rvdffsc #(2) fifo_error_dff (.din(fifo_error_in[i]), .dout(fifo_error[i]), .en(fifo_error_en[i]), .clear(fifo_reset[i]), .clk(dma_free_clk), .*);
|
rvdffsc #(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
|
// 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_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'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'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
|
((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
|
//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_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_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] &
|
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
|
// 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_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);
|
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
|
// 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
|
// Nack counter, stall the lsu pipe if 7 nacks
|
||||||
assign dma_nack_count_csr[2:0] = dec_tlu_dma_qos_prty[2:0];
|
assign dma_nack_count_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_tag[2:0] = 3'(RdPtr);
|
||||||
assign dma_mem_addr_int[31:0] = fifo_addr[RdPtr];
|
assign dma_mem_addr_int[31:0] = fifo_addr[RdPtr];
|
||||||
assign dma_mem_sz_int[2:0] = fifo_sz[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_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 & ((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_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_byteen[7:0] = fifo_byteen[RdPtr];
|
||||||
assign dma_mem_write = fifo_write[RdPtr];
|
assign dma_mem_write = fifo_write[RdPtr];
|
||||||
assign dma_mem_wdata[63:0] = fifo_data[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;
|
assign dma_pmu_any_write = (dma_dccm_req | dma_iccm_req) & dma_mem_write;
|
||||||
|
|
||||||
// Address check dccm
|
// Address check dccm
|
||||||
|
if (pt.DCCM_ENABLE) begin: Gen_dccm_enable
|
||||||
rvrangecheck #(.CCM_SADR(pt.DCCM_SADR),
|
rvrangecheck #(.CCM_SADR(pt.DCCM_SADR),
|
||||||
.CCM_SIZE(pt.DCCM_SIZE)) addr_dccm_rangecheck (
|
.CCM_SIZE(pt.DCCM_SIZE)) addr_dccm_rangecheck (
|
||||||
.addr(dma_mem_addr_int[31:0]),
|
.addr(dma_mem_addr_int[31:0]),
|
||||||
.in_range(dma_mem_addr_in_dccm),
|
.in_range(dma_mem_addr_in_dccm),
|
||||||
.in_region(dma_mem_addr_in_dccm_region_nc)
|
.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
|
// Address check iccm
|
||||||
if (pt.ICCM_ENABLE) begin
|
if (pt.ICCM_ENABLE) begin: Gen_iccm_enable
|
||||||
rvrangecheck #(.CCM_SADR(pt.ICCM_SADR),
|
rvrangecheck #(.CCM_SADR(pt.ICCM_SADR),
|
||||||
.CCM_SIZE(pt.ICCM_SIZE)) addr_iccm_rangecheck (
|
.CCM_SIZE(pt.ICCM_SIZE)) addr_iccm_rangecheck (
|
||||||
.addr(dma_mem_addr_int[31:0]),
|
.addr(dma_mem_addr_int[31:0]),
|
||||||
.in_range(dma_mem_addr_in_iccm),
|
.in_range(dma_mem_addr_in_iccm),
|
||||||
.in_region(dma_mem_addr_in_iccm_region_nc)
|
.in_region(dma_mem_addr_in_iccm_region_nc)
|
||||||
);
|
);
|
||||||
end
|
end else begin: Gen_iccm_disable
|
||||||
else begin
|
|
||||||
assign dma_mem_addr_in_iccm = '0;
|
assign dma_mem_addr_in_iccm = '0;
|
||||||
assign dma_mem_addr_in_iccm_region_nc = '0;
|
assign dma_mem_addr_in_iccm_region_nc = '0;
|
||||||
end // else: !if(pt.ICCM_ENABLE)
|
end // else: !if(pt.ICCM_ENABLE)
|
||||||
|
@ -382,10 +403,9 @@ module el2_dma_ctrl #(
|
||||||
.in_region(dma_mem_addr_in_pic_region_nc)
|
.in_region(dma_mem_addr_in_pic_region_nc)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
rvdff #(1) fifo_full_bus_ff (.din(fifo_full_spec), .dout(fifo_full_spec_bus), .clk(dma_bus_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 #(1) dbg_dma_bubble_ff (.din(dbg_dma_bubble), .dout(dbg_dma_bubble_bus), .clk(dma_bus_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), .*);
|
rvdff #(1) dma_dbg_cmd_doneff (.din(dma_dbg_cmd_done), .dout(dma_dbg_cmd_done_q), .clk(free_clk), .*);
|
||||||
|
|
||||||
// Clock Gating logic
|
// Clock Gating logic
|
||||||
|
@ -394,7 +414,12 @@ module el2_dma_ctrl #(
|
||||||
|
|
||||||
rvoclkhdr dma_buffer_c1cgc ( .en(dma_buffer_c1_clken), .l1clk(dma_buffer_c1_clk), .* );
|
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), .*);
|
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), .*);
|
rvclkhdr dma_bus_cgc (.en(dma_bus_clk_en), .l1clk(dma_bus_clk), .*);
|
||||||
|
`endif
|
||||||
|
|
||||||
// Write channel buffer
|
// Write channel buffer
|
||||||
assign wrbuf_en = dma_axi_awvalid & dma_axi_awready;
|
assign wrbuf_en = dma_axi_awvalid & dma_axi_awready;
|
||||||
|
@ -403,22 +428,22 @@ module el2_dma_ctrl #(
|
||||||
assign wrbuf_rst = wrbuf_cmd_sent & ~wrbuf_en;
|
assign wrbuf_rst = wrbuf_cmd_sent & ~wrbuf_en;
|
||||||
assign wrbuf_data_rst = wrbuf_cmd_sent & ~wrbuf_data_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_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 #(.WIDTH(1)) wrbuf_data_vldff(.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_data_rst), .clk(dma_bus_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 #(.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_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 #(.WIDTH(3)) wrbuf_szff(.din(dma_axi_awsize[2:0]), .dout(wrbuf_sz[2:0]), .en(wrbuf_en), .clk(dma_bus_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(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), .*);
|
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), .*);
|
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
|
// Read channel buffer
|
||||||
assign rdbuf_en = dma_axi_arvalid & dma_axi_arready;
|
assign rdbuf_en = dma_axi_arvalid & dma_axi_arready;
|
||||||
assign rdbuf_cmd_sent = bus_cmd_sent & ~bus_cmd_write;
|
assign rdbuf_cmd_sent = bus_cmd_sent & ~bus_cmd_write;
|
||||||
assign rdbuf_rst = rdbuf_cmd_sent & ~rdbuf_en;
|
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), .*);
|
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 #(.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_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 #(.WIDTH(3)) rdbuf_szff(.din(dma_axi_arsize[2:0]), .dout(rdbuf_sz[2:0]), .en(rdbuf_en), .clk(dma_bus_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), .*);
|
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_awready = ~(wrbuf_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_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_in = ~axi_mstr_priority;
|
||||||
assign axi_mstr_prty_en = bus_cmd_sent;
|
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_valid = fifo_valid[RspPtr] & ~fifo_dbg[RspPtr] & fifo_done_bus[RspPtr];
|
||||||
assign axi_rsp_rdata[63:0] = fifo_data[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_valid = (dma_axi_bvalid | dma_axi_rvalid);
|
||||||
assign bus_rsp_sent = (dma_axi_bvalid & dma_axi_bready) | (dma_axi_rvalid & dma_axi_rready);
|
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
|
for (genvar i=0; i<DEPTH; i++) begin
|
||||||
assert_fifo_done_and_novalid: assert #0 (~fifo_done[i] | fifo_valid[i]);
|
assert_fifo_done_and_novalid: assert #0 (~fifo_done[i] | fifo_valid[i]);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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,
|
output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi,
|
||||||
|
|
||||||
//`ifdef pt.DCCM_ENABLE
|
//`ifdef pt.DCCM_ENABLE
|
||||||
|
input el2_dccm_ext_in_pkt_t [pt.DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt,
|
||||||
|
|
||||||
//`endif
|
//`endif
|
||||||
|
|
||||||
//ICCM ports
|
//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 [pt.ICCM_BITS-1:1] iccm_rw_addr,
|
||||||
input logic iccm_buf_correct_ecc, // ICCM is doing a single bit error correct cycle
|
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 ic_rd_en,
|
||||||
input logic [63:0] ic_premux_data, // Premux data to be muxed with each way of the Icache.
|
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 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 [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.
|
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
|
// DCCM Instantiation
|
||||||
if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable
|
if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable
|
||||||
el2_lsu_dccm_mem #(.pt(pt)) dccm (
|
el2_lsu_dccm_mem #(.pt(pt)) dccm (
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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 clk, // Core clock
|
||||||
input logic free_clk, // free clock
|
input logic free_clk, // free clock
|
||||||
input logic active_clk, // active clock
|
|
||||||
input logic rst_l, // Reset for all flops
|
input logic rst_l, // Reset for all flops
|
||||||
input logic clk_override, // Clock over-ride for gating
|
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 [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_rdaddr, // Address of the register
|
||||||
input logic [31:0] picm_wraddr, // 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 ID_BITS = 8 ;
|
||||||
localparam int GW_CONFIG[pt.PIC_TOTAL_INT_PLUS1-1:0] = '{default:0} ;
|
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 addr_intpend_base_match;
|
||||||
|
|
||||||
logic raddr_config_pic_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 [INTPRIORITY_BITS-1:0] selected_int_priority;
|
||||||
logic [INT_GRPS-1:0] [31:0] intpend_rd_part_out ;
|
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 config_reg;
|
||||||
logic intpriord;
|
logic intpriord;
|
||||||
logic config_reg_we ;
|
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_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 #(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_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(active_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(active_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));
|
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 ;
|
genvar i ;
|
||||||
for (i=0; i<pt.PIC_TOTAL_INT_PLUS1 ; i++) begin : SETREG
|
for (i=0; i<pt.PIC_TOTAL_INT_PLUS1 ; i++) begin : SETREG
|
||||||
|
@ -223,9 +228,27 @@ 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 #(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));
|
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));
|
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),
|
|
||||||
|
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]) ,
|
.extintsrc_req_sync(extintsrc_req_sync[i]) ,
|
||||||
.meigwctrl_polarity(gw_config_reg[i][0]) ,
|
.meigwctrl_polarity(gw_config_reg[i][0]) ,
|
||||||
.meigwctrl_type(gw_config_reg[i][1]) ,
|
.meigwctrl_type(gw_config_reg[i][1]) ,
|
||||||
|
@ -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 intpriority_reg[i] = {INTPRIORITY_BITS{1'b0}} ;
|
||||||
assign intenable_reg[i] = 1'b0 ;
|
assign intenable_reg[i] = 1'b0 ;
|
||||||
assign extintsrc_req_gw[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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,10 +291,14 @@ end
|
||||||
if (pt.PIC_2CYCLE == 1) begin : genblock
|
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] [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/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_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]} ;
|
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_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]} ;
|
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]} ;
|
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 ////////////
|
/// 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 (l=0; l<NUM_LEVELS ; l++) begin : LEVEL
|
||||||
for (m=0; m<=(pt.PIC_TOTAL_INT_PLUS1)/(2**(l+1)) ; m++) begin : COMPARE
|
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
|
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 ;
|
assign intpriord = config_reg ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Send the interrupt to the core if it is above the thresh-hold
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
/// ClaimId Reg and Corresponding PL
|
/// ClaimId Reg and Corresponding PL
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
assign pl_in_q[INTPRIORITY_BITS-1:0] = intpriord ? ~pl_in : pl_in ;
|
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 #(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));
|
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.
|
// Reads of register.
|
||||||
// 1- intpending
|
// 1- intpending
|
||||||
|
@ -471,9 +508,10 @@ endmodule // cmp_and_mux
|
||||||
|
|
||||||
|
|
||||||
module el2_configurable_gw (
|
module el2_configurable_gw (
|
||||||
input logic clk,
|
input logic gw_clk,
|
||||||
|
input logic rawclk,
|
||||||
|
input logic clken,
|
||||||
input logic rst_l,
|
input logic rst_l,
|
||||||
|
|
||||||
input logic extintsrc_req_sync ,
|
input logic extintsrc_req_sync ,
|
||||||
input logic meigwctrl_polarity ,
|
input logic meigwctrl_polarity ,
|
||||||
input logic meigwctrl_type ,
|
input logic meigwctrl_type ,
|
||||||
|
@ -486,7 +524,8 @@ module el2_configurable_gw (
|
||||||
logic gw_int_pending_in , gw_int_pending ;
|
logic gw_int_pending_in , gw_int_pending ;
|
||||||
|
|
||||||
assign gw_int_pending_in = (extintsrc_req_sync ^ meigwctrl_polarity) | (gw_int_pending & ~meigwclr) ;
|
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) ;
|
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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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,
|
input logic [31:1] nmi_vec,
|
||||||
output logic core_rst_l, // This is "rst_l | dbg_rst_l"
|
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_insn_ip,
|
||||||
output logic [31:0] trace_rv_i_address_ip,
|
output logic [31:0] trace_rv_i_address_ip,
|
||||||
output logic [1:0] trace_rv_i_valid_ip,
|
output logic trace_rv_i_valid_ip,
|
||||||
output logic [1:0] trace_rv_i_exception_ip,
|
output logic trace_rv_i_exception_ip,
|
||||||
output logic [4:0] trace_rv_i_ecause_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 [31:0] trace_rv_i_tval_ip,
|
||||||
|
|
||||||
|
|
||||||
output logic dccm_clk_override,
|
output logic dccm_clk_override,
|
||||||
output logic icm_clk_override,
|
output logic icm_clk_override,
|
||||||
output logic dec_tlu_core_ecc_disable,
|
output logic dec_tlu_core_ecc_disable,
|
||||||
|
@ -304,6 +308,7 @@ import el2_pkg::*;
|
||||||
output logic [1:0] dma_axi_rresp,
|
output logic [1:0] dma_axi_rresp,
|
||||||
output logic dma_axi_rlast,
|
output logic dma_axi_rlast,
|
||||||
|
|
||||||
|
|
||||||
//// AHB LITE BUS
|
//// AHB LITE BUS
|
||||||
output logic [31:0] haddr,
|
output logic [31:0] haddr,
|
||||||
output logic [2:0] hburst,
|
output logic [2:0] hburst,
|
||||||
|
@ -366,16 +371,11 @@ import el2_pkg::*;
|
||||||
input logic dbg_bus_clk_en,
|
input logic dbg_bus_clk_en,
|
||||||
input logic dma_bus_clk_en,
|
input logic dma_bus_clk_en,
|
||||||
|
|
||||||
|
|
||||||
// Debug ports
|
|
||||||
input logic dmi_reg_en, // read or write
|
input logic dmi_reg_en, // read or write
|
||||||
input logic [6:0] dmi_reg_addr, // address of DM register
|
input logic [6:0] dmi_reg_addr, // address of DM register
|
||||||
input logic dmi_reg_wr_en, // write instruction
|
input logic dmi_reg_wr_en, // write instruction
|
||||||
input logic [31:0] dmi_reg_wdata, // write data
|
input logic [31:0] dmi_reg_wdata, // write data
|
||||||
// outputs from the dbg back to jtag
|
|
||||||
output logic [31:0] dmi_reg_rdata,
|
output logic [31:0] dmi_reg_rdata,
|
||||||
input logic dmi_hard_reset,
|
|
||||||
|
|
||||||
|
|
||||||
input logic [pt.PIC_TOTAL_INT:1] extintsrc_req,
|
input logic [pt.PIC_TOTAL_INT:1] extintsrc_req,
|
||||||
input logic timer_int,
|
input logic timer_int,
|
||||||
|
@ -386,8 +386,6 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
`define ADDRWIDTH 32
|
|
||||||
|
|
||||||
logic [63:0] hwdata_nc;
|
logic [63:0] hwdata_nc;
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -517,6 +515,7 @@ import el2_pkg::*;
|
||||||
logic [1:0] dma_axi_arburst_int;
|
logic [1:0] dma_axi_arburst_int;
|
||||||
logic dma_axi_rready_int;
|
logic dma_axi_rready_int;
|
||||||
|
|
||||||
|
|
||||||
// Icache debug
|
// Icache debug
|
||||||
logic [70:0] ifu_ic_debug_rd_data; // diagnostic icache read data
|
logic [70:0] ifu_ic_debug_rd_data; // diagnostic icache read data
|
||||||
logic ifu_ic_debug_rd_data_valid; // diagnostic icache read data valid
|
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_rs1_d;
|
||||||
logic [31:0] gpr_i0_rs2_d;
|
logic [31:0] gpr_i0_rs2_d;
|
||||||
|
|
||||||
logic [31:0] dec_i0_rs1_bypass_data_d;
|
logic [31:0] dec_i0_result_r;
|
||||||
logic [31:0] dec_i0_rs2_bypass_data_d;
|
|
||||||
logic [31:0] exu_i0_result_x;
|
logic [31:0] exu_i0_result_x;
|
||||||
logic [31:1] exu_i0_pc_x;
|
logic [31:1] exu_i0_pc_x;
|
||||||
logic [31:1] exu_npc_r;
|
logic [31:1] exu_npc_r;
|
||||||
|
@ -546,10 +544,11 @@ import el2_pkg::*;
|
||||||
logic dec_i0_select_pc_d;
|
logic dec_i0_select_pc_d;
|
||||||
|
|
||||||
logic [31:1] dec_i0_pc_d;
|
logic [31:1] dec_i0_pc_d;
|
||||||
logic [1:0] dec_i0_rs1_bypass_en_d;
|
logic [3:0] dec_i0_rs1_bypass_en_d;
|
||||||
logic [1:0] dec_i0_rs2_bypass_en_d;
|
logic [3:0] dec_i0_rs2_bypass_en_d;
|
||||||
|
|
||||||
logic dec_i0_alu_decode_d;
|
logic dec_i0_alu_decode_d;
|
||||||
|
logic dec_i0_branch_d;
|
||||||
|
|
||||||
logic ifu_miss_state_idle;
|
logic ifu_miss_state_idle;
|
||||||
logic dec_tlu_flush_noredir_r;
|
logic dec_tlu_flush_noredir_r;
|
||||||
|
@ -568,6 +567,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
el2_lsu_pkt_t lsu_p;
|
el2_lsu_pkt_t lsu_p;
|
||||||
|
logic dec_qual_lsu_d;
|
||||||
|
|
||||||
logic dec_lsu_valid_raw_d;
|
logic dec_lsu_valid_raw_d;
|
||||||
logic [11:0] dec_lsu_offset_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_load_stall_any; // This is for blocking loads
|
||||||
logic lsu_store_stall_any; // This is for blocking stores
|
logic lsu_store_stall_any; // This is for blocking stores
|
||||||
logic lsu_idle_any; // doesn't include DMA
|
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
|
logic [31:1] lsu_fir_addr; // fast interrupt address
|
||||||
|
@ -597,11 +598,13 @@ import el2_pkg::*;
|
||||||
logic [31:0] lsu_nonblock_load_data;
|
logic [31:0] lsu_nonblock_load_data;
|
||||||
|
|
||||||
logic dec_csr_ren_d;
|
logic dec_csr_ren_d;
|
||||||
|
logic [31:0] dec_csr_rddata_d;
|
||||||
|
|
||||||
logic [31:0] exu_csr_rs1_x;
|
logic [31:0] exu_csr_rs1_x;
|
||||||
|
|
||||||
logic dec_tlu_i0_commit_cmt;
|
logic dec_tlu_i0_commit_cmt;
|
||||||
logic dec_tlu_flush_lower_r;
|
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_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
|
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 [1:0] ifu_i0_icaf_type;
|
||||||
|
|
||||||
|
|
||||||
logic ifu_i0_icaf_f1;
|
logic ifu_i0_icaf_second;
|
||||||
logic ifu_i0_dbecc;
|
logic ifu_i0_dbecc;
|
||||||
logic iccm_dma_sb_error;
|
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.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr;
|
||||||
logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag;
|
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;
|
el2_predict_pkt_t dec_i0_predict_p_d;
|
||||||
|
|
||||||
|
@ -699,7 +705,6 @@ import el2_pkg::*;
|
||||||
logic [31:0] picm_wr_data;
|
logic [31:0] picm_wr_data;
|
||||||
logic [31:0] picm_rd_data;
|
logic [31:0] picm_rd_data;
|
||||||
|
|
||||||
|
|
||||||
// feature disable from mfdc
|
// feature disable from mfdc
|
||||||
logic dec_tlu_external_ldfwd_disable; // disable external load forwarding
|
logic dec_tlu_external_ldfwd_disable; // disable external load forwarding
|
||||||
logic dec_tlu_bpred_disable;
|
logic dec_tlu_bpred_disable;
|
||||||
|
@ -716,6 +721,8 @@ import el2_pkg::*;
|
||||||
logic dec_tlu_dccm_clk_override;
|
logic dec_tlu_dccm_clk_override;
|
||||||
logic dec_tlu_icm_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 dccm_clk_override = dec_tlu_dccm_clk_override; // dccm memory
|
||||||
assign icm_clk_override = dec_tlu_icm_clk_override; // icache/iccm 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_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 [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 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_type; // 0:gpr 1:csr 2: memory
|
||||||
logic [1:0] dbg_cmd_size; // size of the abstract mem access debug command
|
logic [1:0] dbg_cmd_size; // size of the abstract mem access debug command
|
||||||
|
@ -776,7 +783,8 @@ import el2_pkg::*;
|
||||||
logic ifu_pmu_bus_trxn;
|
logic ifu_pmu_bus_trxn;
|
||||||
|
|
||||||
logic active_state;
|
logic active_state;
|
||||||
logic free_clk, active_clk;
|
logic free_clk;
|
||||||
|
logic active_clk;
|
||||||
logic dec_pause_state_cg;
|
logic dec_pause_state_cg;
|
||||||
|
|
||||||
logic lsu_nonblock_load_data_error;
|
logic lsu_nonblock_load_data_error;
|
||||||
|
@ -787,24 +795,37 @@ import el2_pkg::*;
|
||||||
logic [31:2] dec_tlu_meihap;
|
logic [31:2] dec_tlu_meihap;
|
||||||
logic dec_extint_stall;
|
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 lsu_fastint_stall_any;
|
||||||
|
|
||||||
|
|
||||||
logic [7:0] pic_claimid;
|
logic [7:0] pic_claimid;
|
||||||
logic [3:0] pic_pl, dec_tlu_meicurpl, dec_tlu_meipt;
|
logic [3:0] pic_pl, dec_tlu_meicurpl, dec_tlu_meipt;
|
||||||
logic mexintpend;
|
logic mexintpend;
|
||||||
logic mhwakeup;
|
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), .* );
|
logic dec_tlu_core_empty;
|
||||||
rvoclkhdr active_cg ( .en(active_state), .l1clk(active_clk), .* );
|
|
||||||
|
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;
|
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];
|
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 (
|
el2_dbg #(.pt(pt)) dbg (
|
||||||
|
.rst_l(core_rst_l),
|
||||||
|
.clk(free_l2clk),
|
||||||
.clk_override(dec_tlu_misc_clk_override),
|
.clk_override(dec_tlu_misc_clk_override),
|
||||||
|
|
||||||
// AXI signals
|
// AXI signals
|
||||||
|
@ -824,18 +847,19 @@ import el2_pkg::*;
|
||||||
.sb_axi_rvalid(sb_axi_rvalid_int),
|
.sb_axi_rvalid(sb_axi_rvalid_int),
|
||||||
.sb_axi_rdata(sb_axi_rdata_int[63:0]),
|
.sb_axi_rdata(sb_axi_rdata_int[63:0]),
|
||||||
.sb_axi_rresp(sb_axi_rresp_int[1: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!");
|
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
|
`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
|
// fetch
|
||||||
el2_ifu #(.pt(pt)) ifu (
|
el2_ifu #(.pt(pt)) ifu (
|
||||||
|
.clk(active_l2clk),
|
||||||
.rst_l(core_rst_l),
|
.rst_l(core_rst_l),
|
||||||
.dec_tlu_flush_err_wb (dec_tlu_flush_err_r ),
|
.dec_tlu_flush_err_wb (dec_tlu_flush_err_r ),
|
||||||
.dec_tlu_flush_noredir_wb (dec_tlu_flush_noredir_r ),
|
.dec_tlu_flush_noredir_wb (dec_tlu_flush_noredir_r ),
|
||||||
|
@ -855,17 +879,20 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
el2_dec #(.pt(pt)) dec (
|
el2_dec #(.pt(pt)) dec (
|
||||||
|
.clk(active_l2clk),
|
||||||
.dbg_cmd_wrdata(dbg_cmd_wrdata[1:0]),
|
.dbg_cmd_wrdata(dbg_cmd_wrdata[1:0]),
|
||||||
.rst_l(core_rst_l),
|
.rst_l(core_rst_l),
|
||||||
.*
|
.*
|
||||||
);
|
);
|
||||||
|
|
||||||
el2_exu #(.pt(pt)) exu (
|
el2_exu #(.pt(pt)) exu (
|
||||||
|
.clk(active_l2clk),
|
||||||
.rst_l(core_rst_l),
|
.rst_l(core_rst_l),
|
||||||
.*
|
.*
|
||||||
);
|
);
|
||||||
|
|
||||||
el2_lsu #(.pt(pt)) lsu (
|
el2_lsu #(.pt(pt)) lsu (
|
||||||
|
.clk(active_l2clk),
|
||||||
.rst_l(core_rst_l),
|
.rst_l(core_rst_l),
|
||||||
.clk_override(dec_tlu_lsu_clk_override),
|
.clk_override(dec_tlu_lsu_clk_override),
|
||||||
.dec_tlu_i0_kill_writeb_r(dec_tlu_i0_kill_writeb_r),
|
.dec_tlu_i0_kill_writeb_r(dec_tlu_i0_kill_writeb_r),
|
||||||
|
@ -888,8 +915,11 @@ import el2_pkg::*;
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
el2_pic_ctrl #(.pt(pt)) pic_ctrl_inst (
|
el2_pic_ctrl #(.pt(pt)) pic_ctrl_inst (
|
||||||
|
.clk(free_l2clk),
|
||||||
.clk_override(dec_tlu_pic_clk_override),
|
.clk_override(dec_tlu_pic_clk_override),
|
||||||
|
.io_clk_override(dec_tlu_picio_clk_override),
|
||||||
.picm_mken (picm_mken),
|
.picm_mken (picm_mken),
|
||||||
.extintsrc_req({extintsrc_req[pt.PIC_TOTAL_INT:1],1'b0}),
|
.extintsrc_req({extintsrc_req[pt.PIC_TOTAL_INT:1],1'b0}),
|
||||||
.pl(pic_pl[3:0]),
|
.pl(pic_pl[3:0]),
|
||||||
|
@ -900,6 +930,7 @@ import el2_pkg::*;
|
||||||
.*);
|
.*);
|
||||||
|
|
||||||
el2_dma_ctrl #(.pt(pt)) dma_ctrl (
|
el2_dma_ctrl #(.pt(pt)) dma_ctrl (
|
||||||
|
.clk(free_l2clk),
|
||||||
.rst_l(core_rst_l),
|
.rst_l(core_rst_l),
|
||||||
.clk_override(dec_tlu_misc_clk_override),
|
.clk_override(dec_tlu_misc_clk_override),
|
||||||
|
|
||||||
|
@ -927,8 +958,13 @@ import el2_pkg::*;
|
||||||
// AXI4 -> AHB Gasket for LSU
|
// AXI4 -> AHB Gasket for LSU
|
||||||
axi4_to_ahb #(.pt(pt),
|
axi4_to_ahb #(.pt(pt),
|
||||||
.TAG(pt.LSU_BUS_TAG)) lsu_axi4_to_ahb (
|
.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),
|
.clk_override(dec_tlu_bus_clk_override),
|
||||||
.bus_clk_en(lsu_bus_clk_en),
|
.bus_clk_en(lsu_bus_clk_en),
|
||||||
|
.dec_tlu_force_halt(dec_tlu_force_halt),
|
||||||
|
|
||||||
// AXI Write Channels
|
// AXI Write Channels
|
||||||
.axi_awvalid(lsu_axi_awvalid),
|
.axi_awvalid(lsu_axi_awvalid),
|
||||||
|
@ -983,9 +1019,12 @@ import el2_pkg::*;
|
||||||
|
|
||||||
axi4_to_ahb #(.pt(pt),
|
axi4_to_ahb #(.pt(pt),
|
||||||
.TAG(pt.IFU_BUS_TAG)) ifu_axi4_to_ahb (
|
.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),
|
.clk_override(dec_tlu_bus_clk_override),
|
||||||
.bus_clk_en(ifu_bus_clk_en),
|
.bus_clk_en(ifu_bus_clk_en),
|
||||||
|
.dec_tlu_force_halt(dec_tlu_force_halt),
|
||||||
|
|
||||||
// AHB-Lite signals
|
// AHB-Lite signals
|
||||||
.ahb_haddr(haddr[31:0]),
|
.ahb_haddr(haddr[31:0]),
|
||||||
|
@ -1040,8 +1079,12 @@ import el2_pkg::*;
|
||||||
// AXI4 -> AHB Gasket for System Bus
|
// AXI4 -> AHB Gasket for System Bus
|
||||||
axi4_to_ahb #(.pt(pt),
|
axi4_to_ahb #(.pt(pt),
|
||||||
.TAG(pt.SB_BUS_TAG)) sb_axi4_to_ahb (
|
.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),
|
.clk_override(dec_tlu_bus_clk_override),
|
||||||
.bus_clk_en(dbg_bus_clk_en),
|
.bus_clk_en(dbg_bus_clk_en),
|
||||||
|
.dec_tlu_force_halt(1'b0),
|
||||||
|
|
||||||
// AXI Write Channels
|
// AXI Write Channels
|
||||||
.axi_awvalid(sb_axi_awvalid),
|
.axi_awvalid(sb_axi_awvalid),
|
||||||
|
@ -1096,6 +1139,8 @@ import el2_pkg::*;
|
||||||
//AHB -> AXI4 Gasket for DMA
|
//AHB -> AXI4 Gasket for DMA
|
||||||
ahb_to_axi4 #(.pt(pt),
|
ahb_to_axi4 #(.pt(pt),
|
||||||
.TAG(pt.DMA_BUS_TAG)) dma_ahb_to_axi4 (
|
.TAG(pt.DMA_BUS_TAG)) dma_ahb_to_axi4 (
|
||||||
|
.clk(free_l2clk),
|
||||||
|
.rst_l(core_rst_l),
|
||||||
.clk_override(dec_tlu_bus_clk_override),
|
.clk_override(dec_tlu_bus_clk_override),
|
||||||
.bus_clk_en(dma_bus_clk_en),
|
.bus_clk_en(dma_bus_clk_en),
|
||||||
|
|
||||||
|
@ -1219,7 +1264,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
if (pt.BUILD_AHB_LITE == 1) begin
|
if (pt.BUILD_AHB_LITE == 1) begin
|
||||||
`ifdef ASSERT_ON
|
`ifdef RV_ASSERT_ON
|
||||||
property ahb_trxn_aligned;
|
property ahb_trxn_aligned;
|
||||||
@(posedge clk) disable iff(~rst_l) (lsu_htrans[1:0] != 2'b0) |-> ((lsu_hsize[2:0] == 3'h0) |
|
@(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)) |
|
((lsu_hsize[2:0] == 3'h1) & (lsu_haddr[0] == 1'b0)) |
|
||||||
|
@ -1244,15 +1289,19 @@ if (pt.BUILD_AHB_LITE == 1) begin
|
||||||
// unpack packet
|
// unpack packet
|
||||||
// also need retires_p==3
|
// 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_insn_ip[31:0] = trace_rv_trace_pkt.trace_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_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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -37,10 +37,10 @@ import el2_pkg::*;
|
||||||
|
|
||||||
output logic [31:0] trace_rv_i_insn_ip,
|
output logic [31:0] trace_rv_i_insn_ip,
|
||||||
output logic [31:0] trace_rv_i_address_ip,
|
output logic [31:0] trace_rv_i_address_ip,
|
||||||
output logic [1:0] trace_rv_i_valid_ip,
|
output logic trace_rv_i_valid_ip,
|
||||||
output logic [1:0] trace_rv_i_exception_ip,
|
output logic trace_rv_i_exception_ip,
|
||||||
output logic [4:0] trace_rv_i_ecause_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 [31:0] trace_rv_i_tval_ip,
|
||||||
|
|
||||||
// Bus signals
|
// Bus signals
|
||||||
|
@ -290,8 +290,13 @@ import el2_pkg::*;
|
||||||
input logic dbg_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 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 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,
|
||||||
|
|
||||||
// input logic ext_int,
|
|
||||||
input logic timer_int,
|
input logic timer_int,
|
||||||
input logic soft_int,
|
input logic soft_int,
|
||||||
input logic [pt.PIC_TOTAL_INT:1] extintsrc_req,
|
input logic [pt.PIC_TOTAL_INT:1] extintsrc_req,
|
||||||
|
@ -301,6 +306,7 @@ import el2_pkg::*;
|
||||||
output logic dec_tlu_perfcnt2,
|
output logic dec_tlu_perfcnt2,
|
||||||
output logic dec_tlu_perfcnt3,
|
output logic dec_tlu_perfcnt3,
|
||||||
|
|
||||||
|
// ports added by the soc team
|
||||||
input logic jtag_tck, // JTAG clk
|
input logic jtag_tck, // JTAG clk
|
||||||
input logic jtag_tms, // JTAG TMS
|
input logic jtag_tms, // JTAG TMS
|
||||||
input logic jtag_tdi, // JTAG tdi
|
input logic jtag_tdi, // JTAG tdi
|
||||||
|
@ -327,6 +333,8 @@ import el2_pkg::*;
|
||||||
input logic mbist_mode // to enable mbist
|
input logic mbist_mode // to enable mbist
|
||||||
);
|
);
|
||||||
|
|
||||||
|
logic active_l2clk;
|
||||||
|
logic free_l2clk;
|
||||||
|
|
||||||
// DCCM ports
|
// DCCM ports
|
||||||
logic dccm_wren;
|
logic dccm_wren;
|
||||||
|
@ -386,12 +394,6 @@ import el2_pkg::*;
|
||||||
|
|
||||||
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 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 dccm_clk_override;
|
||||||
logic icm_clk_override;
|
logic icm_clk_override;
|
||||||
|
@ -458,6 +460,7 @@ import el2_pkg::*;
|
||||||
logic dma_hresp;
|
logic dma_hresp;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// AHB
|
// AHB
|
||||||
assign hrdata[63:0] = '0;
|
assign hrdata[63:0] = '0;
|
||||||
assign hready = '0;
|
assign hready = '0;
|
||||||
|
@ -485,6 +488,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
`endif // `ifdef RV_BUILD_AXI4
|
`endif // `ifdef RV_BUILD_AXI4
|
||||||
|
|
||||||
|
|
||||||
`ifdef RV_BUILD_AHB_LITE
|
`ifdef RV_BUILD_AHB_LITE
|
||||||
wire lsu_axi_awvalid;
|
wire lsu_axi_awvalid;
|
||||||
wire lsu_axi_awready;
|
wire lsu_axi_awready;
|
||||||
|
@ -674,18 +678,27 @@ import el2_pkg::*;
|
||||||
|
|
||||||
`endif // `ifdef RV_BUILD_AHB_LITE
|
`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
|
// Instantiate the el2_swerv core
|
||||||
el2_swerv #(.pt(pt)) swerv (
|
el2_swerv #(.pt(pt)) swerv (
|
||||||
|
.clk(clk),
|
||||||
.*
|
.*
|
||||||
);
|
);
|
||||||
|
|
||||||
// Instantiate the mem
|
// Instantiate the mem
|
||||||
el2_mem #(.pt(pt)) mem (
|
el2_mem #(.pt(pt)) mem (
|
||||||
|
.clk(active_l2clk),
|
||||||
.rst_l(core_rst_l),
|
.rst_l(core_rst_l),
|
||||||
.*
|
.*
|
||||||
);
|
);
|
||||||
|
|
||||||
// Instantiate the JTAG/DMI
|
|
||||||
|
// JTAG/DMI instance
|
||||||
dmi_wrapper dmi_wrapper (
|
dmi_wrapper dmi_wrapper (
|
||||||
// JTAG signals
|
// JTAG signals
|
||||||
.trst_n (jtag_trst_n), // JTAG reset
|
.trst_n (jtag_trst_n), // JTAG reset
|
||||||
|
@ -693,21 +706,25 @@ import el2_pkg::*;
|
||||||
.tms (jtag_tms), // Test mode select
|
.tms (jtag_tms), // Test mode select
|
||||||
.tdi (jtag_tdi), // Test Data Input
|
.tdi (jtag_tdi), // Test Data Input
|
||||||
.tdo (jtag_tdo), // Test Data Output
|
.tdo (jtag_tdo), // Test Data Output
|
||||||
.tdoEnable (), // Test Data Output enable
|
.tdoEnable (),
|
||||||
|
|
||||||
// Processor Signals
|
// Processor Signals
|
||||||
.core_rst_n (dbg_rst_l), // Primary reset active low
|
.core_rst_n (dbg_rst_l), // Debug reset, active low
|
||||||
.core_clk (clk), // Core clock
|
.core_clk (clk), // Core clock
|
||||||
.jtag_id (jtag_id), // 32 bit JTAG ID
|
.jtag_id (jtag_id), // JTAG ID
|
||||||
.rd_data (dmi_reg_rdata), // 32 bit Read data from Processor
|
.rd_data (dmi_reg_rdata), // Read data from Processor
|
||||||
.reg_wr_data (dmi_reg_wdata), // 32 bit Write data to Processor
|
.reg_wr_data (dmi_reg_wdata), // Write data to Processor
|
||||||
.reg_wr_addr (dmi_reg_addr), // 32 bit Write address to Processor
|
.reg_wr_addr (dmi_reg_addr), // Write address to Processor
|
||||||
.reg_en (dmi_reg_en), // 1 bit Write interface bit to Processor
|
.reg_en (dmi_reg_en), // Write interface bit to Processor
|
||||||
.reg_wr_en (dmi_reg_wr_en), // 1 bit Write enable to Processor
|
.reg_wr_en (dmi_reg_wr_en), // 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
|
.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
|
endmodule
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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_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 [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_rs1_en_d, // Qualify GPR RS1 data
|
||||||
input logic dec_i0_rs2_en_d, // Qualify GPR RS2 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_rs1_d, // DEC data gpr
|
||||||
input logic [31:0] gpr_i0_rs2_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_immed_d, // DEC data immediate
|
||||||
input logic [31:0] dec_i0_rs1_bypass_data_d, // DEC bypass data
|
input logic [31:0] dec_i0_result_r, // DEC result in R-stage
|
||||||
input logic [31:0] dec_i0_rs2_bypass_data_d, // DEC bypass data
|
|
||||||
input logic [12:1] dec_i0_br_immed_d, // Branch immediate
|
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_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 dec_i0_select_pc_d, // PC select to RS1
|
||||||
input logic [31:1] dec_i0_pc_d, // Instruction PC
|
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 [3: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 [3: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 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_mul_pkt_t mul_p, // DEC {valid, operand signs, low, operand bypass}
|
||||||
input el2_div_pkt_t div_p, // DEC {valid, unsigned, rem}
|
input el2_div_pkt_t div_p, // DEC {valid, unsigned, rem}
|
||||||
input logic dec_div_cancel, // Cancel the divide operation
|
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_rs1_bypass_data_d;
|
||||||
logic [31:0] i0_rs2_bypass_data_d;
|
logic [31:0] i0_rs2_bypass_data_d;
|
||||||
logic i0_rs1_bypass_en_d;
|
logic i0_rs1_bypass_en_d;
|
||||||
logic i0_rs2_bypass_en_d;
|
logic i0_rs2_bypass_en_d;
|
||||||
logic [31:0] i0_rs1_d, i0_rs2_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 [31:1] pred_correct_npc_r;
|
||||||
logic i0_pred_correct_upper_r;
|
logic i0_pred_correct_upper_r;
|
||||||
logic [31:0] csr_rs1_in_d;
|
|
||||||
logic [31:1] i0_flush_path_upper_r;
|
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 x_ctl_en, r_ctl_en;
|
||||||
|
|
||||||
logic [pt.BHT_GHR_SIZE-1:0] ghr_d_ns, ghr_d;
|
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 final_predict_mp;
|
||||||
el2_predict_pkt_t i0_predict_newp_d;
|
el2_predict_pkt_t i0_predict_newp_d;
|
||||||
|
|
||||||
logic flush_lower_ff;
|
|
||||||
logic flush_in_d;
|
logic flush_in_d;
|
||||||
logic [31:0] alu_result_x;
|
logic [31:0] alu_result_x;
|
||||||
|
|
||||||
|
@ -148,6 +149,7 @@ import el2_pkg::*;
|
||||||
logic [31:1] i0_flush_path_x;
|
logic [31:1] i0_flush_path_x;
|
||||||
el2_predict_pkt_t i0_predict_p_x;
|
el2_predict_pkt_t i0_predict_p_x;
|
||||||
logic i0_pred_correct_upper_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;
|
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;
|
logic [PREDPIPESIZE-1:0] predpipe_d, predpipe_x, predpipe_r, final_predpipe_mp;
|
||||||
|
@ -155,52 +157,44 @@ 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] ) );
|
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 (.*, .en ( x_data_en ), .din( csr_rs1_in_d[31:0] ), .dout( exu_csr_rs1_x[31:0] ) );
|
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] ) );
|
||||||
rvdffe #($bits(el2_predict_pkt_t)) i_predictpacket_x_ff (.*, .en ( x_data_en ), .din( i0_predict_p_d ), .dout( i0_predict_p_x ) );
|
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 (.*, .en ( x_data_en ), .din( predpipe_d ), .dout( predpipe_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 (.*, .en ( r_data_en ), .din( predpipe_x ), .dout( predpipe_r ) );
|
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]} ),
|
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]} ) );
|
.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}),
|
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_pp_r ,pred_correct_npc_r[6:1],i0_pred_correct_upper_r}) );
|
.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]}),
|
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]) );
|
||||||
.dout({i0_flush_path_upper_r[31:1],pred_correct_npc_r[31:7]}) );
|
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)
|
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}),
|
||||||
begin
|
.dout({ghr_d[pt.BHT_GHR_SIZE-1:0] , mul_valid_x, i0_branch_x}) );
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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]
|
assign predpipe_d[PREDPIPESIZE-1:0]
|
||||||
= {i0_predict_fghr_d, i0_predict_index_d, i0_predict_btag_d};
|
= {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_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];
|
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]) |
|
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]}} & exu_i0_result_x[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]) |
|
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]}} & exu_i0_result_x[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]) |
|
assign i0_rs1_d[31:0] = ({32{ i0_rs1_bypass_en_d }} & i0_rs1_bypass_data_d[31:0]) |
|
||||||
|
@ -213,26 +207,23 @@ import el2_pkg::*;
|
||||||
({32{ i0_rs2_bypass_en_d }} & i0_rs2_bypass_data_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] ) |
|
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 }} & i0_rs1_bypass_data_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_tlu_meihap[31:2],2'b0});
|
({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] ) |
|
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 }} & i0_rs2_bypass_data_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] ) |
|
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]);
|
({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 = 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 = 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 x_ctl_en = dec_ctl_en[1];
|
||||||
assign r_ctl_en = dec_ctl_en[0];
|
assign r_ctl_en = dec_ctl_en[0];
|
||||||
|
|
||||||
|
@ -240,7 +231,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
el2_exu_alu_ctl #(.pt(pt)) i_alu (.*,
|
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
|
.pp_in ( i0_predict_newp_d ), // I
|
||||||
.valid_in ( dec_i0_alu_decode_d ), // I
|
.valid_in ( dec_i0_alu_decode_d ), // I
|
||||||
.flush_upper_x ( i0_flush_upper_x ), // 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
|
.brimm_in ( dec_i0_br_immed_d[12:1] ), // I
|
||||||
.ap ( i0_ap ), // I
|
.ap ( i0_ap ), // I
|
||||||
.csr_ren_in ( dec_csr_ren_d ), // 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
|
.result_ff ( alu_result_x[31:0] ), // O
|
||||||
.flush_upper_out ( i0_flush_upper_d ), // O
|
.flush_upper_out ( i0_flush_upper_d ), // O
|
||||||
.flush_final_out ( exu_flush_final ), // O
|
.flush_final_out ( exu_flush_final ), // O
|
||||||
|
@ -262,9 +254,9 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
el2_exu_mul_ctl #(.pt(pt)) i_mul (.*,
|
el2_exu_mul_ctl #(.pt(pt)) i_mul (.*,
|
||||||
.mul_p ( mul_p ), // I
|
.mul_p ( mul_p & {$bits(el2_mul_pkt_t){mul_p.valid}} ), // I
|
||||||
.rs1_in ( muldiv_rs1_d[31:0] ), // I
|
.rs1_in ( muldiv_rs1_d[31:0] & {32{mul_p.valid}} ), // I
|
||||||
.rs2_in ( muldiv_rs2_d[31:0] ), // I
|
.rs2_in ( i0_rs2_d[31:0] & {32{mul_p.valid}} ), // I
|
||||||
.result_x ( mul_result_x[31:0] )); // O
|
.result_x ( mul_result_x[31:0] )); // O
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,7 +265,7 @@ import el2_pkg::*;
|
||||||
.cancel ( dec_div_cancel ), // I
|
.cancel ( dec_div_cancel ), // I
|
||||||
.dp ( div_p ), // I
|
.dp ( div_p ), // I
|
||||||
.dividend ( muldiv_rs1_d[31:0] ), // 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
|
.finish_dly ( exu_div_wren ), // O
|
||||||
.out ( exu_div_result[31:0] )); // 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_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);
|
assign i0_taken_d = (i0_predict_p_d.ataken & dec_i0_alu_decode_d);
|
||||||
|
|
||||||
|
if(pt.BTB_ENABLE==1) begin
|
||||||
// maintain GHR at D
|
// maintain GHR at D
|
||||||
assign ghr_d_ns[pt.BHT_GHR_SIZE-1:0]
|
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}) |
|
= ({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_valid_r = i0_pp_r.valid;
|
||||||
assign exu_i0_br_mp_r = i0_pp_r.misp;
|
assign exu_i0_br_mp_r = i0_pp_r.misp;
|
||||||
assign exu_i0_br_way_r = i0_pp_r.way;
|
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_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_middle_r = i0_pp_r.pc4 ^ i0_pp_r.boffset;
|
||||||
assign exu_i0_br_start_error_r = i0_pp_r.br_start_error;
|
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 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.way = final_predict_mp.way;
|
||||||
assign exu_mp_pkt.misp = final_predict_mp.misp;
|
assign exu_mp_pkt.misp = final_predict_mp.misp;
|
||||||
assign exu_mp_pkt.pcall = final_predict_mp.pcall;
|
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];
|
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
|
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] :
|
assign exu_npc_r[31:1] = (i0_pred_correct_upper_r) ? pred_correct_npc_r[31:1] : i0_flush_path_upper_r[31:1];
|
||||||
i0_flush_path_upper_r[31:1];
|
|
||||||
|
|
||||||
|
|
||||||
endmodule // el2_exu
|
endmodule // el2_exu
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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 enable, // Clock enable
|
||||||
input logic valid_in, // Valid
|
input logic valid_in, // Valid
|
||||||
input el2_alu_pkt_t ap, // predecodes
|
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 signed [31:0] a_in, // A operand
|
||||||
input logic [31:0] b_in, // B operand
|
input logic [31:0] b_in, // B operand
|
||||||
input logic [31:1] pc_in, // for pc=pc+2,4 calculations
|
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 [31:0] aout;
|
||||||
logic cout,ov,neg;
|
logic cout,ov,neg;
|
||||||
logic [31:0] lout;
|
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 [31:0] sout;
|
||||||
logic sel_shift;
|
logic sel_shift;
|
||||||
logic sel_adder;
|
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]
|
// 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;
|
logic [31:0] bm;
|
||||||
|
|
||||||
assign bm[31:0] = ( ap.sub ) ? ~b_in[31:0] : b_in[31:0];
|
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]) |
|
assign ov = (~a_in[31] & ~bm[31] & aout[31]) |
|
||||||
( 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)) |
|
assign lt = (~ap.unsign & (neg ^ ov)) |
|
||||||
( ap.unsign & ~cout);
|
( ap.unsign & ~cout);
|
||||||
|
|
||||||
|
|
||||||
assign eq = (a_in[31:0] == b_in[31:0]);
|
assign eq = (a_in[31:0] == b_in[31:0]);
|
||||||
assign ne = ~eq;
|
assign ne = ~eq;
|
||||||
assign neg = aout[31];
|
assign neg = aout[31];
|
||||||
|
@ -126,39 +267,227 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assign lout[31:0] = ( {32{csr_ren_in}} & b_in[31:0] ) |
|
assign lout[31:0] = ( {32{csr_ren_in }} & csr_rddata_in[31:0] ) |
|
||||||
( {32{ap.land }} & a_in[31:0] & b_in[31:0] ) |
|
( {32{ap.land & ~ap_zbb}} & a_in[31:0] & b_in[31:0] ) |
|
||||||
( {32{ap.lor }} & (a_in[31:0] | b_in[31:0]) ) |
|
( {32{ap.lor & ~ap_zbb}} & (a_in[31:0] | b_in[31:0]) ) |
|
||||||
( {32{ap.lxor }} & (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
|
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.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[31:0] = a_in[31:0];
|
||||||
|
|
||||||
assign shift_extend[62:32] = ( {31{ap.sra}} & {31{a_in[31]}} ) |
|
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 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 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];
|
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_adder}} & aout[31:0] ) |
|
||||||
({32{sel_pc}} & {pcout[31:1],1'b0} ) |
|
({32{sel_pc}} & {pcout[31:1],1'b0} ) |
|
||||||
({32{ap.csr_write}} & csr_write_data[31:0] ) |
|
({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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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 mul_x_enable;
|
||||||
|
logic bit_x_enable;
|
||||||
logic signed [32:0] rs1_ext_in;
|
logic signed [32:0] rs1_ext_in;
|
||||||
logic signed [32:0] rs2_ext_in;
|
logic signed [32:0] rs2_ext_in;
|
||||||
logic [65:0] prod_x;
|
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 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 rs1_ext_in[32] = mul_p.rs1_sign & rs1_in[31];
|
||||||
assign rs2_ext_in[32] = mul_p.rs2_sign & rs2_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] rs1_x;
|
||||||
logic signed [32:0] rs2_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 #(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 (.*, .din( rs2_ext_in[32:0] ), .dout( rs2_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 prod_x[65:0] = rs1_x * rs2_x;
|
||||||
|
|
||||||
|
|
||||||
assign result_x[31:0] = ( {32{~low_x}} & prod_x[63:32] ) |
|
// * * * * * * * * * * * * * * * * * * BitManip : BEXT, BDEP * * * * * * * * * * * * * * * * * *
|
||||||
( {32{ low_x}} & prod_x[31:0] );
|
|
||||||
|
|
||||||
|
|
||||||
|
// *** 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
|
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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input logic free_clk,
|
input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in.
|
||||||
input logic active_clk,
|
input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
|
||||||
input logic 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 rst_l,
|
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 exu_flush_final, // flush, includes upper and lower
|
||||||
input logic dec_tlu_i0_commit_cmt , // committed i0
|
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 [63:0] ifu_axi_rdata,
|
||||||
input logic [1:0] ifu_axi_rresp,
|
input logic [1:0] ifu_axi_rresp,
|
||||||
|
|
||||||
|
|
||||||
input logic ifu_bus_clk_en,
|
input logic ifu_bus_clk_en,
|
||||||
|
|
||||||
input logic dma_iccm_req,
|
input logic dma_iccm_req,
|
||||||
|
@ -160,24 +159,24 @@ import el2_pkg::*;
|
||||||
output logic ifu_pmu_bus_trxn, // iside bus transactions
|
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 [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_valid, // Instruction 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_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 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 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:0] ifu_i0_instr, // Instruction 0 . From Aligner to Decode
|
||||||
output logic[31:1] ifu_i0_pc, // Instructio 0 pc. From Aligner to Decode
|
output logic[31:1] ifu_i0_pc, // Instruction 0 pc. From Aligner to Decode
|
||||||
output logic ifu_i0_pc4, // Instructio 0 is 4 byte. 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 logic ifu_miss_state_idle, // There is no outstanding miss. Cache miss state is idle.
|
||||||
|
|
||||||
|
output el2_br_pkt_t i0_brp, // Instruction 0 branch packet. From Aligner to Decode
|
||||||
output el2_br_pkt_t i0_brp, // Instructio 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.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.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 [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 el2_predict_pkt_t exu_mp_pkt, // mispredict packet
|
||||||
input logic [pt.BHT_GHR_SIZE-1:0] exu_mp_eghr, // execute ghr
|
input logic [pt.BHT_GHR_SIZE-1:0] exu_mp_eghr, // execute ghr
|
||||||
|
@ -188,11 +187,13 @@ import el2_pkg::*;
|
||||||
input el2_br_tlu_pkt_t dec_tlu_br0_r_pkt, // slot0 update/error pkt
|
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.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 [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,
|
input dec_tlu_flush_lower_wb,
|
||||||
|
|
||||||
output logic [15:0] ifu_i0_cinst,
|
output logic [15:0] ifu_i0_cinst,
|
||||||
|
|
||||||
|
|
||||||
/// Icache debug
|
/// Icache debug
|
||||||
input el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt ,
|
input el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt ,
|
||||||
output logic ifu_ic_debug_rd_data_valid,
|
output logic ifu_ic_debug_rd_data_valid,
|
||||||
|
@ -220,22 +221,16 @@ import el2_pkg::*;
|
||||||
logic ic_write_stall;
|
logic ic_write_stall;
|
||||||
logic ic_dma_active;
|
logic ic_dma_active;
|
||||||
logic ifc_dma_access_ok;
|
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 [1:0] ic_access_fault_type_f;
|
||||||
logic ifu_ic_mb_empty;
|
logic ifu_ic_mb_empty;
|
||||||
|
|
||||||
|
|
||||||
logic ic_hit_f;
|
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 [1:0] ifu_bp_way_f; // way indication; right justified
|
||||||
logic ifu_bp_hit_taken_f; // kill next fetch; taken target found
|
logic ifu_bp_hit_taken_f; // kill next fetch; taken target found
|
||||||
logic [31:1] ifu_bp_btb_target_f; // predicted target PC
|
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 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_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 [1:0] ifu_bp_hist0_f; // history counters for all 4 potential branches; right justified
|
||||||
logic [11:0] ifu_bp_poffset_f; // predicted target
|
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_pc4_f; // pc4 indication; right justified
|
||||||
logic [1:0] ifu_bp_valid_f; // branch valid, 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 [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
|
// branch predictor
|
||||||
|
if (pt.BTB_ENABLE==1) begin : bpred
|
||||||
el2_ifu_bp_ctl #(.pt(pt)) bp (.*);
|
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;
|
logic [1:0] ic_fetch_val_f;
|
||||||
|
@ -253,7 +267,7 @@ import el2_pkg::*;
|
||||||
logic [31:0] ifu_fetch_data_f;
|
logic [31:0] ifu_fetch_data_f;
|
||||||
logic ifc_fetch_req_f;
|
logic ifc_fetch_req_f;
|
||||||
logic ifc_fetch_req_f_raw;
|
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;
|
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.
|
logic ifc_region_acc_fault_bf; // Access fault. in ICCM region but offset is outside defined ICCM.
|
||||||
|
|
||||||
// aligner
|
// aligner
|
||||||
el2_ifu_aln_ctl #(.pt(pt)) aln (.*);
|
|
||||||
|
el2_ifu_aln_ctl #(.pt(pt)) aln (
|
||||||
|
.*
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// icache
|
// icache
|
||||||
|
@ -316,29 +333,29 @@ import el2_pkg::*;
|
||||||
logic exu_flush_final_d1;
|
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[31:1] = `EXU.i0_flush_upper_x ? `EXU.exu_i0_pc_x : `EXU.dec_i0_pc_d;
|
||||||
assign mppc_ns[0] = 1'b0;
|
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;
|
logic tmp_bnk;
|
||||||
assign tmp_bnk = bp.btb_sel_f[1];
|
assign tmp_bnk = bpred.bp.btb_sel_f[1];
|
||||||
|
|
||||||
always @(negedge clk) begin
|
always @(negedge clk) begin
|
||||||
if(`DEC.tlu.mcyclel[31:0] == 32'h0000_0010) 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
|
`ifndef BP_NOGSHARE
|
||||||
$display("BHT_CONFIG: %d gshare: 1",pt.BHT_ARRAY_DEPTH*4);
|
$display("BHT_CONFIG: %d gshare: 1",pt.BHT_SIZE);
|
||||||
`else
|
`else
|
||||||
$display("BHT_CONFIG: %d gshare: 0",pt.BHT_ARRAY_DEPTH*4);
|
$display("BHT_CONFIG: %d gshare: 0",pt.BHT_SIZE);
|
||||||
`endif
|
`endif
|
||||||
$display("RS_CONFIG: %d", pt.RET_STACK_SIZE);
|
$display("RS_CONFIG: %d", pt.RET_STACK_SIZE);
|
||||||
end
|
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))
|
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
|
for(int i = 0; i < 8; i++) begin
|
||||||
if(ifu_bp_valid_f[i] & ifc_fetch_req_f)
|
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
|
end
|
||||||
if(dec_tlu_br0_r_pkt.valid & ~(dec_tlu_br0_r_pkt.br_error | dec_tlu_br0_r_pkt.br_start_error))
|
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)
|
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);
|
$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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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 scan_mode, // Flop scan mode control
|
||||||
input logic rst_l,
|
input logic rst_l, // reset, active low
|
||||||
input logic 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,
|
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 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 [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 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
|
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_valid, // Instruction 0 is valid
|
||||||
output logic ifu_i0_icaf, // Instruction 0 has access fault
|
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 [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 ifu_i0_dbecc, // Instruction 0 has double bit ecc error
|
||||||
output logic [31:0] ifu_i0_instr, // Instruction 0
|
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_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
|
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 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.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.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 [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 ifu_pmu_instr_aligned, // number of inst aligned this cycle
|
||||||
|
|
||||||
output logic [15:0] ifu_i0_cinst // 16b compress inst for i0
|
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] f0val_in, f0val;
|
||||||
logic [1:0] sf1val, sf0val;
|
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 [31:0] aligndata;
|
||||||
logic first4B, first2B;
|
logic first4B, first2B;
|
||||||
|
|
||||||
|
@ -105,8 +108,6 @@ import el2_pkg::*;
|
||||||
logic f2_valid, sf1_valid, sf0_valid;
|
logic f2_valid, sf1_valid, sf0_valid;
|
||||||
|
|
||||||
logic [31:0] ifirst;
|
logic [31:0] ifirst;
|
||||||
logic [31:1] f0pc_plus1;
|
|
||||||
logic [31:1] f1pc_plus1;
|
|
||||||
logic [1:0] alignval;
|
logic [1:0] alignval;
|
||||||
logic [31:1] firstpc, secondpc;
|
logic [31:1] firstpc, secondpc;
|
||||||
|
|
||||||
|
@ -119,6 +120,8 @@ import el2_pkg::*;
|
||||||
logic [1:0] f1hist0;
|
logic [1:0] f1hist0;
|
||||||
logic [1:0] f0hist0;
|
logic [1:0] f0hist0;
|
||||||
|
|
||||||
|
logic [1:0][$clog2(pt.BTB_SIZE)-1:0] f0index, f1index, alignindex;
|
||||||
|
|
||||||
logic [1:0] f1ictype;
|
logic [1:0] f1ictype;
|
||||||
logic [1:0] f0ictype;
|
logic [1:0] f0ictype;
|
||||||
|
|
||||||
|
@ -146,10 +149,10 @@ import el2_pkg::*;
|
||||||
|
|
||||||
logic [31:1] f1prett;
|
logic [31:1] f1prett;
|
||||||
logic [31:1] f0prett;
|
logic [31:1] f0prett;
|
||||||
logic f1dbecc;
|
logic [1:0] f1dbecc;
|
||||||
logic f0dbecc;
|
logic [1:0] f0dbecc;
|
||||||
logic f1icaf;
|
logic [1:0] f1icaf;
|
||||||
logic f0icaf;
|
logic [1:0] f0icaf;
|
||||||
|
|
||||||
logic [1:0] aligndbecc;
|
logic [1:0] aligndbecc;
|
||||||
logic [1:0] alignicaf;
|
logic [1:0] alignicaf;
|
||||||
|
@ -159,10 +162,6 @@ import el2_pkg::*;
|
||||||
|
|
||||||
logic first_legal;
|
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] wrptr, wrptr_in;
|
||||||
logic [1:0] rdptr, rdptr_in;
|
logic [1:0] rdptr, rdptr_in;
|
||||||
logic [2:0] qwen;
|
logic [2:0] qwen;
|
||||||
|
@ -185,16 +184,17 @@ import el2_pkg::*;
|
||||||
logic [2:0] qren;
|
logic [2:0] qren;
|
||||||
|
|
||||||
logic consume_fb1, consume_fb0;
|
logic consume_fb1, consume_fb0;
|
||||||
logic [1:1] icaf_eff;
|
logic [1:0] icaf_eff;
|
||||||
|
|
||||||
localparam BRDATA_SIZE = 12;
|
localparam BRDATA_SIZE = pt.BTB_ENABLE ? 16+($clog2(pt.BTB_SIZE)*2*pt.BTB_FULLYA) : 2;
|
||||||
localparam BRDATA_WIDTH = 6;
|
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] brdata_in, brdata2, brdata1, brdata0;
|
||||||
logic [BRDATA_SIZE-1:0] brdata1eff, brdata0eff;
|
logic [BRDATA_SIZE-1:0] brdata1eff, brdata0eff;
|
||||||
logic [BRDATA_SIZE-1:0] brdata1final, brdata0final;
|
logic [BRDATA_SIZE-1:0] brdata1final, brdata0final;
|
||||||
|
|
||||||
localparam MHI = 46+pt.BHT_GHR_SIZE;
|
localparam MHI = 1+(pt.BTB_ENABLE * (43+pt.BHT_GHR_SIZE));
|
||||||
localparam MSIZE = 47+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] misc_data_in, misc2, misc1, misc0;
|
||||||
logic [MHI:0] misc1eff, misc0eff;
|
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;
|
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]));
|
rvdffie #(.WIDTH(7),.OVERRIDE(1)) bundle2ff (.*,
|
||||||
rvdff #(2) rdpff (.*, .clk(active_clk), .din(rdptr_in[1:0]), .dout(rdptr[1:0]));
|
.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]));
|
if(pt.BTB_ENABLE==1) begin
|
||||||
rvdff #(2) f1valff (.*, .clk(active_clk), .din(f1val_in[1:0]), .dout(f1val[1:0]));
|
rvdffe #(BRDATA_SIZE) brdata2ff (.*, .clk(clk), .en(qwen[2]), .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata2[BRDATA_SIZE-1:0]));
|
||||||
rvdff #(2) f0valff (.*, .clk(active_clk), .din(f0val_in[1:0]), .dout(f0val[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));
|
rvdffie #((MSIZE*3)+(BRDATA_SIZE*3)) miscff (.*,
|
||||||
rvdff #(1) q1offsetff (.*, .clk(active_clk), .din(q1off_in), .dout(q1off));
|
.din({qwen[2] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc2[MHI:0], brdata2[BRDATA_SIZE-1:0]},
|
||||||
rvdff #(1) q0offsetff (.*, .clk(active_clk), .din(q0off_in), .dout(q0off));
|
qwen[1] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc1[MHI:0], brdata1[BRDATA_SIZE-1:0]},
|
||||||
rvdffe #(31) f2pcff (.*, .en(f2_wr_en), .din(f2pc_in[31:1]), .dout(f2pc[31:1]));
|
qwen[0] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc0[MHI:0], brdata0[BRDATA_SIZE-1:0]}}),
|
||||||
rvdffe #(31) f1pcff (.*, .en(f1_shift_wr_en), .din(f1pc_in[31:1]), .dout(f1pc[31:1]));
|
.dout({misc2[MHI:0],misc1[MHI:0],misc0[MHI:0],
|
||||||
rvdffe #(31) f0pcff (.*, .en(f0_shift_wr_en), .din(f0pc_in[31:1]), .dout(f0pc[31:1]));
|
brdata2[BRDATA_SIZE-1:0], brdata1[BRDATA_SIZE-1:0], brdata0[BRDATA_SIZE-1:0]})
|
||||||
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]));
|
end
|
||||||
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]));
|
|
||||||
|
|
||||||
rvdffe #(32) q2ff (.*, .en(qwen[2]), .din(ifu_fetch_data_f[31:0]), .dout(q2[31:0]));
|
logic [31:1] q2pc, q1pc, q0pc;
|
||||||
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]));
|
|
||||||
|
|
||||||
|
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]));
|
||||||
|
|
||||||
|
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]));
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// new queue control logic
|
// new queue control logic
|
||||||
|
@ -297,40 +302,64 @@ import el2_pkg::*;
|
||||||
|
|
||||||
// misc data that is associated with each fetch buffer
|
// misc data that is associated with each fetch buffer
|
||||||
|
|
||||||
assign misc_data_in[MHI:0] = { iccm_rd_ecc_double_err,
|
if(pt.BTB_ENABLE==1)
|
||||||
ic_access_fault_f,
|
assign misc_data_in[MHI:0] = {
|
||||||
|
|
||||||
ic_access_fault_type_f[1:0],
|
ic_access_fault_type_f[1:0],
|
||||||
ifu_bp_btb_target_f[31:1],
|
ifu_bp_btb_target_f[31:1],
|
||||||
ifu_bp_poffset_f[11:0],
|
ifu_bp_poffset_f[11:0],
|
||||||
ifu_bp_fghr_f[pt.BHT_GHR_SIZE-1: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]}) |
|
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[1]}} & {misc2[MHI:0],misc1[MHI:0]}) |
|
||||||
({MSIZE*2{qren[2]}} & {misc0[MHI:0],misc2[MHI:0]}));
|
({MSIZE*2{qren[2]}} & {misc0[MHI:0],misc2[MHI:0]}));
|
||||||
|
|
||||||
assign { f1dbecc,
|
if(pt.BTB_ENABLE==1) begin
|
||||||
f1icaf,
|
assign {
|
||||||
f1ictype[1:0],
|
f1ictype[1:0],
|
||||||
f1prett[31:1],
|
f1prett[31:1],
|
||||||
f1poffset[11:0],
|
f1poffset[11:0],
|
||||||
f1fghr[pt.BHT_GHR_SIZE-1:0]
|
f1fghr[pt.BHT_GHR_SIZE-1:0]
|
||||||
} = misc1eff[MHI:0];
|
} = misc1eff[MHI:0];
|
||||||
|
|
||||||
assign { f0dbecc,
|
assign {
|
||||||
f0icaf,
|
|
||||||
f0ictype[1:0],
|
f0ictype[1:0],
|
||||||
f0prett[31:1],
|
f0prett[31:1],
|
||||||
f0poffset[11:0],
|
f0poffset[11:0],
|
||||||
f0fghr[pt.BHT_GHR_SIZE-1:0]
|
f0fghr[pt.BHT_GHR_SIZE-1:0]
|
||||||
} = misc0eff[MHI:0];
|
} = misc0eff[MHI:0];
|
||||||
|
|
||||||
|
if(pt.BTB_FULLYA) begin
|
||||||
assign brdata_in[BRDATA_SIZE-1:0] = {
|
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_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_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]
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -344,11 +373,37 @@ import el2_pkg::*;
|
||||||
assign brdata1final[BRDATA_SIZE-1:0] = (({BRDATA_SIZE{q1sel[0]}} & { brdata1eff[2*BRDATA_WIDTH-1:0]}) |
|
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]}));
|
({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],
|
end // if (pt.BTB_ENABLE==1)
|
||||||
f0hist1[0],f0hist0[0],f0pc4[0],f0way[0],f0brend[0],f0ret[0]} = brdata0final[BRDATA_SIZE-1:0];
|
else begin
|
||||||
|
assign {
|
||||||
|
f1ictype[1:0]
|
||||||
|
} = misc1eff[MHI:0];
|
||||||
|
|
||||||
assign {f1hist1[1],f1hist0[1],f1pc4[1],f1way[1],f1brend[1],f1ret[1],
|
assign {
|
||||||
f1hist1[0],f1hist0[0],f1pc4[0],f1way[0],f1brend[0],f1ret[0]} = brdata1final[BRDATA_SIZE-1:0];
|
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 }
|
// possible states of { sf0_valid, sf1_valid, f2_valid }
|
||||||
|
@ -391,28 +446,6 @@ import el2_pkg::*;
|
||||||
( sf0_valid & sf1_valid & ~f2_valid & ifvalid);
|
( 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]) |
|
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] );
|
({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{ 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] );
|
({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]}) |
|
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[1]}} & {q2[31:0],q1[31:0]}) |
|
||||||
({64{qren[2]}} & {q0[31:0],q2[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] ) |
|
assign q1final[15:0] = ({16{q1sel[0]}} & q1eff[15:0] ) |
|
||||||
({16{q1sel[1]}} & q1eff[31:16]);
|
({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]}) |
|
assign aligndata[31:0] = ({32{ f0val[1] }} & {q0final[31:0]}) |
|
||||||
({32{~f0val[1] & f0val[0]}} & {q1final[15:0],q0final[15: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}) |
|
assign alignval[1:0] = ({ 2{ f0val[1] }} & {2'b11}) |
|
||||||
({ 2{~f0val[1] & f0val[0]}} & {f1val[0],1'b1});
|
({ 2{~f0val[1] & f0val[0]}} & {f1val[0],1'b1});
|
||||||
|
|
||||||
assign alignicaf[1:0] = ({ 2{ f0val[1] }} & {{2{f0icaf}}}) |
|
assign alignicaf[1:0] = ({ 2{ f0val[1] }} & f0icaf[1:0] ) |
|
||||||
({ 2{~f0val[1] & f0val[0]}} & {f1icaf,f0icaf});
|
({ 2{~f0val[1] & f0val[0]}} & {f1icaf[0],f0icaf[0]});
|
||||||
|
|
||||||
assign aligndbecc[1:0] = ({ 2{ f0val[1] }} & {{2{f0dbecc}}}) |
|
assign aligndbecc[1:0] = ({ 2{ f0val[1] }} & f0dbecc[1:0] ) |
|
||||||
({ 2{~f0val[1] & f0val[0]}} & {f1dbecc,f0dbecc});
|
({ 2{~f0val[1] & f0val[0]}} & {f1dbecc[0],f0dbecc[0]});
|
||||||
|
|
||||||
|
if (pt.BTB_ENABLE==1) begin
|
||||||
|
|
||||||
// for branch prediction
|
// for branch prediction
|
||||||
|
|
||||||
assign alignbrend[1:0] = ({ 2{ f0val[1] }} & f0brend[1:0] ) |
|
assign alignbrend[1:0] = ({ 2{ f0val[1] }} & f0brend[1:0] ) |
|
||||||
({ 2{~f0val[1] & f0val[0]}} & {f1brend[0],f0brend[0]});
|
({ 2{~f0val[1] & f0val[0]}} & {f1brend[0],f0brend[0]});
|
||||||
|
|
||||||
assign alignpc4[1:0] = ({ 2{ f0val[1] }} & f0pc4[1:0] ) |
|
assign alignpc4[1:0] = ({ 2{ f0val[1] }} & f0pc4[1:0] ) |
|
||||||
({ 2{~f0val[1] & f0val[0]}} & {f1pc4[0],f0pc4[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] ) |
|
assign alignret[1:0] = ({ 2{ f0val[1] }} & f0ret[1:0] ) |
|
||||||
({ 2{~f0val[1] & f0val[0]}} & {f1ret[0],f0ret[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] ) |
|
assign alignhist0[1:0] = ({ 2{ f0val[1] }} & f0hist0[1:0] ) |
|
||||||
({ 2{~f0val[1] & f0val[0]}} & {f1hist0[0],f0hist0[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 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_pc4 = first4B;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assign ifu_i0_cinst[15:0] = aligndata[15:0];
|
assign ifu_i0_cinst[15:0] = aligndata[15:0];
|
||||||
|
|
||||||
assign first4B = (aligndata[1:0] == 2'b11);
|
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 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])) |
|
assign ifu_i0_dbecc = (first4B & (|aligndbecc[1:0])) |
|
||||||
(first2B & aligndbecc[0] );
|
(first2B & aligndbecc[0] );
|
||||||
|
@ -521,23 +569,38 @@ import el2_pkg::*;
|
||||||
assign ifirst[31:0] = aligndata[31:0];
|
assign ifirst[31:0] = aligndata[31:0];
|
||||||
|
|
||||||
|
|
||||||
assign ifu_i0_instr[31:0] = ({32{first4B}} & ifirst[31:0]) |
|
assign ifu_i0_instr[31:0] = ({32{first4B & alignval[1]}} & ifirst[31:0]) |
|
||||||
({32{first2B}} & uncompress0[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
|
// 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)) firsthash (.pc(firstpc [pt.BTB_INDEX3_HI:pt.BTB_INDEX1_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]));
|
.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_BTAG_FOLD) begin : btbfold
|
if(pt.BTB_FULLYA) begin
|
||||||
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]));
|
assign firstbrtag_hash = firstpc;
|
||||||
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]));
|
assign secondbrtag_hash = secondpc;
|
||||||
end
|
end
|
||||||
else begin
|
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]));
|
if(pt.BTB_BTAG_FOLD) begin : btbfold
|
||||||
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]));
|
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
|
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)
|
||||||
|
|
||||||
|
|
||||||
// start_indexing - you want pc to be based on where the end of branch is prediction
|
// 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
|
// normal indexing pc based that's incorrect now for pc4 cases it's pc4 + 2
|
||||||
|
|
||||||
|
@ -578,6 +641,11 @@ end
|
||||||
i0_brp.br_error = (i0_brp.valid & i0_brp_pc4 & first2B) |
|
i0_brp.br_error = (i0_brp.valid & i0_brp_pc4 & first2B) |
|
||||||
(i0_brp.valid & ~i0_brp_pc4 & first4B);
|
(i0_brp.valid & ~i0_brp_pc4 & first4B);
|
||||||
|
|
||||||
|
if(pt.BTB_FULLYA)
|
||||||
|
ifu_i0_fa_index = (first2B | alignbrend[0]) ? alignindex[0] : alignindex[1];
|
||||||
|
else
|
||||||
|
ifu_i0_fa_index = '0;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -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] :
|
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];
|
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
|
// 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
|
// compute how many bytes are being shifted from f0
|
||||||
|
|
||||||
// assign shift_0B = ~i0_shift;
|
|
||||||
|
|
||||||
assign shift_2B = i0_shift & first2B;
|
assign shift_2B = i0_shift & first2B;
|
||||||
|
|
||||||
assign shift_4B = i0_shift & first4B;
|
assign shift_4B = i0_shift & first4B;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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 clk,
|
||||||
input logic active_clk,
|
|
||||||
input logic rst_l,
|
input logic rst_l,
|
||||||
|
|
||||||
input logic ic_hit_f, // Icache hit, enables F address capture
|
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.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 [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_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
|
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 [1:0] ifu_bp_valid_f, // branch valid, right justified
|
||||||
output logic [11:0] ifu_bp_poffset_f, // predicted target
|
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
|
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 PC4=4;
|
||||||
localparam BOFF=3;
|
localparam BOFF=3;
|
||||||
localparam CALL=2;
|
localparam CALL=2;
|
||||||
|
@ -88,6 +100,7 @@ import el2_pkg::*;
|
||||||
localparam NUM_BHT_LOOP_OUTER_LO = (pt.BHT_ARRAY_DEPTH > 16 ) ?pt.BHT_ADDR_LO+4 : pt.BHT_ADDR_LO;
|
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 );
|
localparam BHT_NO_ADDR_MATCH = ( pt.BHT_ARRAY_DEPTH <= 16 );
|
||||||
|
|
||||||
|
|
||||||
logic exu_mp_valid_write;
|
logic exu_mp_valid_write;
|
||||||
logic exu_mp_ataken;
|
logic exu_mp_ataken;
|
||||||
logic exu_mp_valid; // conditional branch mispredict
|
logic exu_mp_valid; // conditional branch mispredict
|
||||||
|
@ -120,13 +133,12 @@ import el2_pkg::*;
|
||||||
logic rs_push, rs_pop, rs_hold;
|
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_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 [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 btb_wr_en_way0, btb_wr_en_way1;
|
||||||
|
|
||||||
|
|
||||||
logic dec_tlu_error_wb, btb_valid, dec_tlu_br0_middle_wb;
|
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 [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_collision_f, fetch_mp_collision_f, branch_error_collision_p1_f, fetch_mp_collision_p1_f;
|
||||||
|
|
||||||
logic branch_error_bank_conflict_f;
|
logic branch_error_bank_conflict_f;
|
||||||
|
@ -142,17 +154,17 @@ import el2_pkg::*;
|
||||||
|
|
||||||
logic leak_one_f, leak_one_f_d1;
|
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 [BTB_DWIDTH-1: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_way1_f ;
|
||||||
|
|
||||||
logic [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way0_p1_f ;
|
logic [BTB_DWIDTH-1: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_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 final_h;
|
||||||
logic btb_fg_crossing_f;
|
logic btb_fg_crossing_f;
|
||||||
|
@ -167,10 +179,10 @@ import el2_pkg::*;
|
||||||
logic [31:2] fetch_addr_p1_f;
|
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 exu_mp_way, exu_mp_way_f, dec_tlu_br0_way_wb, dec_tlu_way_wb;
|
||||||
logic [16+pt.BTB_BTAG_SIZE:0] btb_bank0e_rd_data_f, btb_bank0e_rd_data_p1_f;
|
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;
|
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_bank0_rd_data_f;
|
||||||
logic [1:0] bht_bank1_rd_data_f;
|
logic [1:0] bht_bank1_rd_data_f;
|
||||||
logic [1:0] bht_bank0_rd_data_p1_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_valid = exu_mp_pkt.misp & ~leak_one_f; // conditional branch mispredict
|
||||||
assign exu_mp_boffset = exu_mp_pkt.boffset; // branch offset
|
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_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;
|
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]) &
|
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_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])
|
(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_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])
|
(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
|
// 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]) &
|
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]) &
|
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]) &
|
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]) &
|
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
|
// 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_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 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]) |
|
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[16+pt.BTB_BTAG_SIZE: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[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]) |
|
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[16+pt.BTB_BTAG_SIZE: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]) |
|
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[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[BTB_DWIDTH-1:0]) );
|
||||||
|
|
||||||
// virtual bank order
|
// 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]) |
|
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[16+pt.BTB_BTAG_SIZE: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[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]) |
|
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[16+pt.BTB_BTAG_SIZE: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}};
|
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;
|
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] &
|
assign fetch_wrlru_p1_b0[LRU_SIZE-1:0] = fetch_wrindex_p1_dec[LRU_SIZE-1:0] &
|
||||||
{LRU_SIZE{lru_update_valid_f}};
|
{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]) |
|
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}}) |
|
(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_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}}) );
|
(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_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]);
|
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]}) |
|
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]}) );
|
({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),
|
rvdffe #(LRU_SIZE) btb_lru_ff (.*, .en(ifc_fetch_req_f | exu_mp_valid),
|
||||||
.din(btb_lru_b0_ns[(LRU_SIZE)-1:0]),
|
.din(btb_lru_b0_ns[(LRU_SIZE)-1:0]),
|
||||||
.dout(btb_lru_b0_f[(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
|
// Detect end of cache line and mask as needed
|
||||||
logic eoc_near;
|
logic eoc_near;
|
||||||
logic eoc_mask;
|
logic eoc_mask;
|
||||||
|
@ -353,8 +363,6 @@ logic exu_flush_final_d1;
|
||||||
assign eoc_mask = ~eoc_near| (|(~ifc_fetch_addr_f[2:1]));
|
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}} & 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]));
|
({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];
|
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;
|
assign bp_total_branch_offset_f = bloc_f[1] ^ btb_rd_pc4_f;
|
||||||
|
|
||||||
logic [31:2] adder_pc_in_f, ifc_fetch_adder_prior;
|
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];
|
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]),
|
.offset(btb_rd_tgt_f[11:0]),
|
||||||
.dout(bp_btb_target_adder_f[31:1])
|
.dout(bp_btb_target_adder_f[31:1])
|
||||||
);
|
);
|
||||||
// mux in the return stack address here for a predicted return assuming the RS is valid
|
// 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] = (btb_rd_ret_f & ~btb_rd_call_f & rets_out[0][0]) ? rets_out[0][31:1] : bp_btb_target_adder_f[31:1];
|
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;
|
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
|
// for the last entry in the stack, we don't have a pop position
|
||||||
if(i==pt.RET_STACK_SIZE-1) begin
|
if(i==pt.RET_STACK_SIZE-1) begin
|
||||||
|
@ -570,18 +583,21 @@ 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];
|
assign btb_wr_tag[pt.BTB_BTAG_SIZE-1:0] = exu_mp_btag[pt.BTB_BTAG_SIZE-1:0];
|
||||||
|
|
||||||
|
if(!pt.BTB_FULLYA) begin
|
||||||
|
|
||||||
if(pt.BTB_BTAG_FOLD) begin : btbfold
|
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)) rdtagf (.hash(fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]),
|
||||||
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]}));
|
.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
|
end
|
||||||
else begin
|
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)) rdtagf(.hash(fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]),
|
||||||
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]}));
|
.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
|
end
|
||||||
|
|
||||||
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} ;
|
|
||||||
|
|
||||||
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}}) |
|
assign btb_wr_en_way0 = ( ({{~exu_mp_way & exu_mp_valid_write & ~dec_tlu_error_wb}}) |
|
||||||
({{~dec_tlu_way_wb & dec_tlu_error_wb}}));
|
({{~dec_tlu_way_wb & dec_tlu_error_wb}}));
|
||||||
|
|
||||||
|
@ -589,6 +605,16 @@ end
|
||||||
({{dec_tlu_way_wb & 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_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_data0, bht_wr_data2;
|
||||||
logic [1:0] bht_wr_en0, bht_wr_en2;
|
logic [1:0] bht_wr_en0, bht_wr_en2;
|
||||||
|
|
||||||
|
@ -622,46 +648,172 @@ end
|
||||||
// BTB
|
// BTB
|
||||||
// Entry -> tag[pt.BTB_BTAG_SIZE-1:0], toffset[11:0], pc4, boffset, call, ret, valid
|
// 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
|
for (j=0 ; j<LRU_SIZE ; j++) begin : BTB_FLOPS
|
||||||
// Way 0
|
// Way 0
|
||||||
rvdffe #(17+pt.BTB_BTAG_SIZE) btb_bank0_way0 (.*,
|
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)),
|
.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]));
|
.dout (btb_bank0_rd_data_way0_out[j]));
|
||||||
|
|
||||||
// Way 1
|
// Way 1
|
||||||
rvdffe #(17+pt.BTB_BTAG_SIZE) btb_bank0_way1 (.*,
|
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)),
|
.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]));
|
.dout (btb_bank0_rd_data_way1_out[j]));
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
always_comb begin : BTB_rd_mux
|
always_comb begin : BTB_rd_mux
|
||||||
btb_bank0_rd_data_way0_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[16+pt.BTB_BTAG_SIZE:0] = '0 ;
|
btb_bank0_rd_data_way1_f[BTB_DWIDTH-1:0] = '0 ;
|
||||||
btb_bank0_rd_data_way0_p1_f[16+pt.BTB_BTAG_SIZE:0] = '0 ;
|
btb_bank0_rd_data_way0_p1_f[BTB_DWIDTH-1:0] = '0 ;
|
||||||
btb_bank0_rd_data_way1_p1_f[16+pt.BTB_BTAG_SIZE:0] = '0 ;
|
btb_bank0_rd_data_way1_p1_f[BTB_DWIDTH-1:0] = '0 ;
|
||||||
|
|
||||||
for (int j=0; j< LRU_SIZE; j++) begin
|
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
|
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_way0_f[BTB_DWIDTH-1: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_way1_f[BTB_DWIDTH-1:0] = btb_bank0_rd_data_way1_out[j];
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for (int j=0; j< LRU_SIZE; j++) begin
|
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
|
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_way0_p1_f[BTB_DWIDTH-1: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_way1_p1_f[BTB_DWIDTH-1:0] = btb_bank0_rd_data_way1_out[j];
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
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
|
// 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 ;
|
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 ( 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)) |
|
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));
|
(bht_wr_en2[i] & ((bht_wr_addr2[pt.BHT_ADDR_HI: NUM_BHT_LOOP_OUTER_LO]==k) | BHT_NO_ADDR_MATCH));
|
||||||
|
`ifndef RV_FPGA_OPTIMIZE
|
||||||
rvclkhdr bht_bank_grp_cgc ( .en(bht_bank_clken[i][k]), .l1clk(bht_bank_clk[i][k]), .* );
|
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
|
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)) |
|
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] ;
|
bht_wr_data0[1:0] ;
|
||||||
|
|
||||||
|
|
||||||
rvdffs #(2) bht_bank (.*,
|
rvdffs_fpga #(2) bht_bank (.*,
|
||||||
.clk (bht_bank_clk[i][k]),
|
.clk (bht_bank_clk[i][k]),
|
||||||
.en (bht_bank_sel[i][k][j]),
|
.en (bht_bank_sel[i][k][j]),
|
||||||
|
.rawclk (clk),
|
||||||
|
.clken (bht_bank_sel[i][k][j]),
|
||||||
.din (bht_bank_wr_data[i][k][j]),
|
.din (bht_bank_wr_data[i][k][j]),
|
||||||
.dout (bht_bank_rd_data_out[i][(16*k)+j]));
|
.dout (bht_bank_rd_data_out[i][(16*k)+j]));
|
||||||
|
|
||||||
|
@ -716,9 +871,6 @@ end
|
||||||
end // block: BHT_rd_mux
|
end // block: BHT_rd_mux
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function [1:0] countones;
|
function [1:0] countones;
|
||||||
input [1:0] valid;
|
input [1:0] valid;
|
||||||
|
|
||||||
|
@ -728,25 +880,5 @@ countones[1:0] = {2'b0, valid[1]} +
|
||||||
{2'b0, valid[0]};
|
{2'b0, valid[0]};
|
||||||
end
|
end
|
||||||
endfunction
|
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
|
endmodule // el2_ifu_bp_ctl
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input logic [15:0] din,
|
input logic [15:0] din, // 16-bit compressed instruction
|
||||||
output logic [31:0] dout
|
output logic [31:0] dout // 32-bit uncompressed instruction
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)(
|
)(
|
||||||
input logic 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 rst_l,
|
input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
|
||||||
input logic clk_override,
|
input logic rst_l, // reset, active low
|
||||||
|
input logic clk_override, // Override non-functional clock gating
|
||||||
|
|
||||||
input logic iccm_wren,
|
input logic iccm_wren, // ICCM write enable
|
||||||
input logic iccm_rden,
|
input logic iccm_rden, // ICCM read enable
|
||||||
input logic [pt.ICCM_BITS-1:1] iccm_rw_addr,
|
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_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 iccm_correction_state, // ICCM under a correction - This is needed to guard replacements when hit
|
||||||
input logic [2:0] iccm_wr_size,
|
input logic [2:0] iccm_wr_size, // ICCM write size
|
||||||
input logic [77:0] iccm_wr_data,
|
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 [63:0] iccm_rd_data, // ICCM read data
|
||||||
output logic [77:0] iccm_rd_data_ecc,
|
output logic [77:0] iccm_rd_data_ecc, // ICCM read ecc
|
||||||
input logic scan_mode
|
input logic scan_mode // Scan mode control
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -72,15 +74,32 @@ import el2_pkg::*;
|
||||||
logic redundant_data1_en;
|
logic redundant_data1_en;
|
||||||
logic r0_addr_en, r1_addr_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_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];
|
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)] = iccm_wr_data[38:0];
|
||||||
assign iccm_bank_wr_data_vec[(2*i)+1] = iccm_wr_data[77:39];
|
assign iccm_bank_wr_data_vec[(2*i)+1] = iccm_wr_data[77:39];
|
||||||
end
|
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 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 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));
|
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]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
`else
|
||||||
|
@ -111,7 +141,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -124,7 +165,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -137,7 +189,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -149,7 +212,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -161,7 +235,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -173,7 +258,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -185,7 +281,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -197,7 +304,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -209,7 +327,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -221,7 +350,18 @@ import el2_pkg::*;
|
||||||
.WE(wren_bank[i]),
|
.WE(wren_bank[i]),
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(iccm_bank_wr_data[i][38:0]),
|
.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
|
end // block: iccm
|
||||||
|
@ -235,12 +375,12 @@ 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))));
|
((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 (.*,
|
rvdff #(1) selred0 (.*,
|
||||||
.clk(clk),
|
.clk(active_clk),
|
||||||
.din(sel_red0[i]),
|
.din(sel_red0[i]),
|
||||||
.dout(sel_red0_q[i]));
|
.dout(sel_red0_q[i]));
|
||||||
|
|
||||||
rvdff #(1) selred1 (.*,
|
rvdff #(1) selred1 (.*,
|
||||||
.clk(clk),
|
.clk(active_clk),
|
||||||
.din(sel_red1[i]),
|
.din(sel_red1[i]),
|
||||||
.dout(sel_red1_q[i]));
|
.dout(sel_red1_q[i]));
|
||||||
|
|
||||||
|
@ -250,7 +390,6 @@ import el2_pkg::*;
|
||||||
({39{sel_red0_q[i]}} & redundant_data[0][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]);
|
({39{~sel_red0_q[i] & ~sel_red1_q[i]}} & iccm_bank_dout[i][38:0]);
|
||||||
|
|
||||||
|
|
||||||
end : mem_bank
|
end : mem_bank
|
||||||
// This section does the redundancy for tolerating single bit errors
|
// This section does the redundancy for tolerating single bit errors
|
||||||
// 2x 39 bit data values with address[hi:2] and a valid bit is needed to CAM and sub out the reads/writes to the particular locations
|
// 2x 39 bit data values with address[hi:2] and a valid bit is needed to CAM and sub out the reads/writes to the particular locations
|
||||||
|
@ -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;
|
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
|
rvdffs #() red_lru (.*, // LRU flop for the redundant replacements
|
||||||
.clk(clk),
|
.clk(active_clk),
|
||||||
.en(redundant_lru_en),
|
.en(redundant_lru_en),
|
||||||
.din(redundant_lru_in),
|
.din(redundant_lru_in),
|
||||||
.dout(redundant_lru));
|
.dout(redundant_lru));
|
||||||
|
|
||||||
rvdffs #(pt.ICCM_BITS-2) r0_address (.*, // Redundant Row 0 address
|
rvdffs #(pt.ICCM_BITS-2) r0_address (.*, // Redundant Row 0 address
|
||||||
.clk(clk),
|
.clk(active_clk),
|
||||||
.en(r0_addr_en),
|
.en(r0_addr_en),
|
||||||
.din(iccm_rw_addr[pt.ICCM_BITS-1:2]),
|
.din(iccm_rw_addr[pt.ICCM_BITS-1:2]),
|
||||||
.dout(redundant_address[0][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
|
rvdffs #(pt.ICCM_BITS-2) r1_address (.*, // Redundant Row 0 address
|
||||||
.clk(clk),
|
.clk(active_clk),
|
||||||
.en(r1_addr_en),
|
.en(r1_addr_en),
|
||||||
.din(iccm_rw_addr[pt.ICCM_BITS-1:2]),
|
.din(iccm_rw_addr[pt.ICCM_BITS-1:2]),
|
||||||
.dout(redundant_address[1][pt.ICCM_BITS-1:2]));
|
.dout(redundant_address[1][pt.ICCM_BITS-1:2]));
|
||||||
|
|
||||||
rvdffs #(1) r0_valid (.*,
|
rvdffs #(1) r0_valid (.*,
|
||||||
.clk(clk), // Redundant Row 0 Valid
|
.clk(active_clk), // Redundant Row 0 Valid
|
||||||
.en(r0_addr_en),
|
.en(r0_addr_en),
|
||||||
.din(1'b1),
|
.din(1'b1),
|
||||||
.dout(redundant_valid[0]));
|
.dout(redundant_valid[0]));
|
||||||
|
|
||||||
rvdffs #(1) r1_valid (.*, // Redundant Row 1 Valid
|
rvdffs #(1) r1_valid (.*, // Redundant Row 1 Valid
|
||||||
.clk(clk),
|
.clk(active_clk),
|
||||||
.en(r1_addr_en),
|
.en(r1_addr_en),
|
||||||
.din(1'b1),
|
.din(1'b1),
|
||||||
.dout(redundant_valid[1]));
|
.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];
|
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
|
rvdffs #(39) r0_data (.*, // Redundant Row 1 data
|
||||||
.clk(clk),
|
.clk(active_clk),
|
||||||
.en(redundant_data0_en),
|
.en(redundant_data0_en),
|
||||||
.din(redundant_data0_in[38:0]),
|
.din(redundant_data0_in[38:0]),
|
||||||
.dout(redundant_data[0][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];
|
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
|
rvdffs #(39) r1_data (.*, // Redundant Row 1 data
|
||||||
.clk(clk),
|
.clk(active_clk),
|
||||||
.en(redundant_data1_en),
|
.en(redundant_data1_en),
|
||||||
.din(redundant_data1_in[38:0]),
|
.din(redundant_data1_in[38:0]),
|
||||||
.dout(redundant_data[1][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_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 (.*, .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_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_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]))});
|
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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input logic 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_clk,
|
input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in.
|
||||||
input logic active_clk,
|
|
||||||
|
|
||||||
input logic rst_l, // reset enable, from core pin
|
input logic rst_l, // reset enable, from core pin
|
||||||
input logic scan_mode, // scan
|
input logic scan_mode, // scan
|
||||||
|
@ -76,7 +75,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
logic fb_full_f_ns, fb_full_f;
|
logic fb_full_f_ns, fb_full_f;
|
||||||
logic fb_right, fb_right2, fb_left, wfm, idle;
|
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 miss_f, miss_a;
|
||||||
logic flush_fb, dma_iccm_stall_any_f;
|
logic flush_fb, dma_iccm_stall_any_f;
|
||||||
logic mb_empty_mod, goto_idle, leave_idle;
|
logic mb_empty_mod, goto_idle, leave_idle;
|
||||||
|
@ -95,13 +94,15 @@ import el2_pkg::*;
|
||||||
logic dma_stall;
|
logic dma_stall;
|
||||||
assign dma_stall = ic_dma_active | dma_iccm_stall_any_f;
|
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
|
// Fetch address mux
|
||||||
// - flush
|
// - flush
|
||||||
// - Miss *or* flush during WFM (icache miss buffer is blocking)
|
// - Miss *or* flush during WFM (icache miss buffer is blocking)
|
||||||
// - Sequential
|
// - 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_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;
|
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
|
({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 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]);
|
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 idle = state == IDLE ;
|
||||||
assign wfm = state == WFM ;
|
assign wfm = state == WFM ;
|
||||||
|
|
||||||
rvdff #(2) fsm_ff (.*, .clk(active_clk), .din({next_state[1:0]}), .dout({state[1:0]}));
|
rvdffie #(10) fbwrite_ff (.*, .clk(free_l2clk),
|
||||||
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]}));
|
.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 |
|
assign ifu_pmu_fetch_stall = wfm |
|
||||||
(ifc_fetch_req_bf_raw &
|
(ifc_fetch_req_bf_raw &
|
||||||
|
@ -195,11 +208,10 @@ import el2_pkg::*;
|
||||||
dma_stall));
|
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];
|
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
|
if (pt.ICCM_ENABLE) begin
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -27,10 +27,10 @@ import el2_pkg::*;
|
||||||
`include "el2_param.vh"
|
`include "el2_param.vh"
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input logic 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_clk, // free clock always except during pause
|
input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
|
||||||
input logic active_clk, // Active always except during pause
|
input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in.
|
||||||
input logic rst_l,
|
input logic rst_l, // reset, active low
|
||||||
|
|
||||||
input logic exu_flush_final, // Flush from the pipeline., includes flush lower
|
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_lower_wb, // Flush lower from the pipeline.
|
||||||
|
@ -160,10 +160,10 @@ import el2_pkg::*;
|
||||||
input logic [1:0] ifu_fetch_val,
|
input logic [1:0] ifu_fetch_val,
|
||||||
// IFU control signals
|
// 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_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 [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_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 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
|
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
|
input logic scan_mode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Create different defines for ICACHE and ICCM enable combinations
|
// Create different defines for ICACHE and ICCM enable combinations
|
||||||
|
|
||||||
localparam NUM_OF_BEATS = 8 ;
|
localparam NUM_OF_BEATS = 8 ;
|
||||||
|
@ -219,6 +218,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
logic ifu_wr_data_comb_err ;
|
logic ifu_wr_data_comb_err ;
|
||||||
logic ifu_byp_data_err_new;
|
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_data;
|
||||||
logic ifu_wr_cumulative_err;
|
logic ifu_wr_cumulative_err;
|
||||||
logic ifu_wr_data_comb_err_ff;
|
logic ifu_wr_data_comb_err_ff;
|
||||||
|
@ -229,7 +229,7 @@ import el2_pkg::*;
|
||||||
logic ifc_iccm_access_f ;
|
logic ifc_iccm_access_f ;
|
||||||
logic ifc_region_acc_fault_f;
|
logic ifc_region_acc_fault_f;
|
||||||
logic ifc_region_acc_fault_final_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_act_miss_f;
|
||||||
logic ic_miss_under_miss_f;
|
logic ic_miss_under_miss_f;
|
||||||
logic ic_ignore_2nd_miss_f;
|
logic ic_ignore_2nd_miss_f;
|
||||||
|
@ -312,14 +312,12 @@ import el2_pkg::*;
|
||||||
logic ifu_pmu_bus_busy_in;
|
logic ifu_pmu_bus_busy_in;
|
||||||
logic ic_debug_ict_array_sel_in;
|
logic ic_debug_ict_array_sel_in;
|
||||||
logic ic_debug_ict_array_sel_ff;
|
logic ic_debug_ict_array_sel_ff;
|
||||||
logic debug_data_clk;
|
|
||||||
logic debug_data_clken;
|
logic debug_data_clken;
|
||||||
logic last_data_recieved_in ;
|
logic last_data_recieved_in ;
|
||||||
logic last_data_recieved_ff ;
|
logic last_data_recieved_ff ;
|
||||||
|
|
||||||
logic ifu_bus_rvalid ;
|
logic ifu_bus_rvalid ;
|
||||||
logic ifu_bus_rvalid_ff ;
|
logic ifu_bus_rvalid_ff ;
|
||||||
logic ifu_bus_rvalid_unq ;
|
|
||||||
logic ifu_bus_rvalid_unq_ff ;
|
logic ifu_bus_rvalid_unq_ff ;
|
||||||
logic ifu_bus_arready_unq ;
|
logic ifu_bus_arready_unq ;
|
||||||
logic ifu_bus_arready_unq_ff ;
|
logic ifu_bus_arready_unq_ff ;
|
||||||
|
@ -355,7 +353,7 @@ import el2_pkg::*;
|
||||||
logic [pt.IFU_BUS_TAG-1:0] other_tag ;
|
logic [pt.IFU_BUS_TAG-1:0] other_tag ;
|
||||||
logic [(2*pt.ICACHE_NUM_BEATS)-1:0] [31:0] ic_miss_buff_data;
|
logic [(2*pt.ICACHE_NUM_BEATS)-1:0] [31:0] ic_miss_buff_data;
|
||||||
logic [63:0] ic_miss_buff_half;
|
logic [63:0] ic_miss_buff_half;
|
||||||
logic scnd_miss_req, scnd_miss_req_q, scnd_miss_req_ff2;
|
logic scnd_miss_req, scnd_miss_req_q;
|
||||||
logic scnd_miss_req_in;
|
logic scnd_miss_req_in;
|
||||||
|
|
||||||
|
|
||||||
|
@ -435,6 +433,7 @@ import el2_pkg::*;
|
||||||
logic ic_crit_wd_rdy; // Critical fetch is ready to be bypassed.
|
logic ic_crit_wd_rdy; // Critical fetch is ready to be bypassed.
|
||||||
|
|
||||||
logic ifu_bp_hit_taken_q_f;
|
logic ifu_bp_hit_taken_q_f;
|
||||||
|
logic ifu_bus_rvalid_unq;
|
||||||
logic bus_cmd_beat_en;
|
logic bus_cmd_beat_en;
|
||||||
|
|
||||||
|
|
||||||
|
@ -445,9 +444,14 @@ 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 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
|
// 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 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), .* );
|
rvclkhdr debug_c1_cgc ( .en(debug_c1_clken), .l1clk(debug_c1_clk), .* );
|
||||||
|
`endif
|
||||||
|
|
||||||
|
|
||||||
// ------ end clock gating section ------------------------
|
// ------ end clock gating section ------------------------
|
||||||
|
|
||||||
|
@ -529,7 +533,7 @@ import el2_pkg::*;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
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 ;
|
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 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 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 ;
|
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_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));
|
||||||
rvdff #(31) imb_f_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({imb_scnd_in[31:1]}), .dout({imb_scnd_ff[31:1]}));
|
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 #(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_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 #(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 #(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] :
|
miss_pending ? way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0] :
|
||||||
{way_status[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])) :
|
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) ;
|
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));
|
|
||||||
|
|
||||||
|
|
||||||
|
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]}));
|
||||||
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]}));
|
|
||||||
|
|
||||||
assign vaddr_f[pt.ICACHE_BEAT_ADDR_HI:1] = ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI: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));
|
rvdffpcie #(31) imb_f_ff (.*, .en(fetch_bf_f_c1_clken), .din (imb_in[31:1]), .dout(imb_ff[31:1]));
|
||||||
rvdff #(31) imb_f_ff (.*, .clk(fetch_bf_f_c1_clk), .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] :
|
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] ;
|
( 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 ;
|
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 ;
|
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_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 #(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_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 #(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) 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] };
|
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] ;
|
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
|
if (pt.ICACHE_ECC == 1) begin: icache_ecc_1
|
||||||
logic [6:0] ic_wr_ecc;
|
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]),
|
.din (ic_miss_buff_half[63:0]),
|
||||||
.ecc_out(ic_miss_buff_ecc[6: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)];
|
assign ic_wr_data[i][70:0] = ic_wr_16bytes_data[((71*i)+70): (71*i)];
|
||||||
end
|
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} :
|
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];
|
ic_debug_rd_data[70:0];
|
||||||
|
|
||||||
rvdff #(71) ifu_debug_data_ff (.*, .clk (debug_data_clk),
|
rvdffe #(71) ifu_debug_data_ff (.*,
|
||||||
|
.en (debug_data_clken),
|
||||||
.din ({
|
.din ({
|
||||||
ifu_ic_debug_rd_data_in[70:0]
|
ifu_ic_debug_rd_data_in[70:0]
|
||||||
}),
|
}),
|
||||||
.dout({
|
.dout({
|
||||||
ifu_ic_debug_rd_data[70:0]
|
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] } :
|
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] } ;
|
{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
|
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
|
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} :
|
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] ;
|
ic_debug_rd_data[70:0] ;
|
||||||
|
|
||||||
rvdff #(71) ifu_debug_data_ff (.*, .clk (debug_data_clk),
|
rvdffe #(71) ifu_debug_data_ff (.*,
|
||||||
|
.en (debug_data_clken),
|
||||||
.din ({
|
.din ({
|
||||||
ifu_ic_debug_rd_data_in[70:0]
|
ifu_ic_debug_rd_data_in[70:0]
|
||||||
}),
|
}),
|
||||||
.dout({
|
.dout({
|
||||||
ifu_ic_debug_rd_data[70:0]
|
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] } :
|
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] } ;
|
{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 = (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 ;
|
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));
|
||||||
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) | (miss_state == MISS_WAIT)) & ~fetch_req_iccm_f & ~ifc_region_acc_fault_final_f;
|
||||||
assign sel_ic_data = ~(ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK)) & ~fetch_req_iccm_f ;
|
|
||||||
|
|
||||||
if (pt.ICCM_ICACHE==1) begin: iccm_icache
|
if (pt.ICCM_ICACHE==1) begin: iccm_icache
|
||||||
assign sel_iccm_data = fetch_req_iccm_f ;
|
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
|
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];
|
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 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_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 :
|
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_f ? 2'b10 :
|
||||||
ifc_region_acc_fault_memory_f ? 2'b11 : 2'b00 ;
|
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;
|
logic [63:0] ic_miss_buff_data_in;
|
||||||
assign ic_miss_buff_data_in[63:0] = ifu_bus_rsp_rdata[63:0];
|
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
|
for (genvar i=0; i<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]));
|
|
||||||
|
|
||||||
rvdff #(32) byp_data_1_ff (.*,
|
assign write_fill_data[i] = bus_ifu_wr_en & ( (pt.IFU_BUS_TAG)'(i) == ifu_bus_rsp_tag[pt.IFU_BUS_TAG-1:0]);
|
||||||
.clk (wr_data_c1_clk[i]),
|
|
||||||
|
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]),
|
.din (ic_miss_buff_data_in[63:32]),
|
||||||
.dout(ic_miss_buff_data[i*2+1][31:0]));
|
.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) ;
|
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 (.*,
|
rvdff #(1) byp_data_valid_ff (.*,
|
||||||
.clk (free_clk),
|
.clk (active_clk),
|
||||||
.din (ic_miss_buff_data_valid_in[i]),
|
.din (ic_miss_buff_data_valid_in[i]),
|
||||||
.dout(ic_miss_buff_data_valid[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) ;
|
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 (.*,
|
rvdff #(1) byp_data_error_ff (.*,
|
||||||
.clk (free_clk),
|
.clk (active_clk),
|
||||||
.din (ic_miss_buff_data_error_in[i] ),
|
.din (ic_miss_buff_data_error_in[i] ),
|
||||||
.dout(ic_miss_buff_data_error[i]));
|
.dout(ic_miss_buff_data_error[i]));
|
||||||
end
|
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) |
|
( 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) ;
|
(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[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} ;
|
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[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]] )) ;
|
( 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]}) |
|
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]}) ;
|
({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_NUM_WAYS-1:0] perr_err_inv_way;
|
||||||
logic [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO] perr_ic_index_ff;
|
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 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 iccm_correct_ecc = (perr_state == ECC_CORR);
|
||||||
assign dma_sb_err_state = (perr_state == DMA_SB_ERR);
|
assign dma_sb_err_state = (perr_state == DMA_SB_ERR);
|
||||||
assign iccm_buf_correct_ecc = iccm_correct_ecc & ~dma_sb_err_state_ff;
|
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
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
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 /////////////////////////
|
||||||
//////////////////////////////////// Create stop fetch State Machine /////////////////////////
|
//////////////////////////////////// Create stop fetch State Machine /////////////////////////
|
||||||
|
@ -1013,29 +1025,30 @@ logic perr_sb_write_status ;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
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 ;
|
assign bus_ifu_bus_clk_en = ifu_bus_clk_en ;
|
||||||
|
|
||||||
rvclkhdr bus_clk_f(.en(bus_ifu_bus_clk_en),
|
`ifdef RV_FPGA_OPTIMIZE
|
||||||
.l1clk(busclk), .*);
|
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 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);
|
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
|
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
|
// 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_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_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_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_arcache[3:0] = 4'b1111;
|
||||||
assign ifu_axi_arregion[3:0] = ifu_ic_req_addr_f[31:28];
|
assign ifu_axi_arregion[3:0] = ifu_ic_req_addr_f[31:28];
|
||||||
assign ifu_axi_arlen[7:0] = '0;
|
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_rvalid_unq = ifu_axi_rvalid ;
|
||||||
assign ifu_bus_arvalid = ifu_axi_arvalid ;
|
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_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 #(1) bus_rsp_vld_ff (.*, .clk(busclk), .din(ifu_bus_rvalid_unq), .dout(ifu_bus_rvalid_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 #(1) bus_cmd_ff (.*, .clk(busclk), .din(ifu_bus_arvalid), .dout(ifu_bus_arvalid_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 #(2) bus_rsp_cmd_ff (.*, .clk(busclk), .din(ifu_axi_rresp[1:0]), .dout(ifu_bus_rresp_ff[1:0]));
|
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 #(64) bus_data_ff (.*, .clk(busclk), .din(ifu_axi_rdata[63:0]), .dout(ifu_bus_rdata_ff[63: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]));
|
||||||
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]));
|
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_cmd_ready = ifu_axi_arready ;
|
||||||
assign ifu_bus_rsp_valid = ifu_axi_rvalid ;
|
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 ;
|
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_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]);
|
({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) ;
|
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
|
// 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_cmd_sent ) ? (bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0] + 3'b001) :
|
||||||
bus_rd_addr_count[pt.ICACHE_BEAT_BITS-1:0];
|
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_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]) ;
|
({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),
|
`ifdef RV_FPGA_OPTIMIZE
|
||||||
.l1clk(busclk_reset), .*);
|
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]}));
|
.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;
|
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 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 = |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;
|
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 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;
|
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_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 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 ;
|
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;
|
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_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]);
|
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]));
|
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]));
|
||||||
rvdff #(3) dma_tag_ff2 (.*, .clk(free_clk), .din(dma_mem_tag_ff[2:0]), .dout(iccm_dma_rtag[2:0]));
|
rvdffie #(11) dma_misc_bits (.*, .clk(free_l2clk), .din({dma_mem_tag[2:0],
|
||||||
rvdff #(2) dma_addr_bt3_ff (.*, .clk(free_clk), .din(dma_mem_addr[3:2]), .dout(dma_mem_addr_ff[3:2]));
|
dma_mem_tag_ff[2:0],
|
||||||
rvdff #(1) ccm_rdy_in_ff (.*, .clk(free_clk), .din(iccm_dma_rden), .dout(iccm_dma_rvalid_in));
|
dma_mem_addr[3:2],
|
||||||
rvdff #(1) ccm_rdy_ff (.*, .clk(free_clk), .din(iccm_dma_rvalid_in), .dout(iccm_dma_rvalid));
|
iccm_dma_rden,
|
||||||
rvdff #(1) ccm_err_ff (.*, .clk(free_clk), .din(iccm_dma_ecc_error_in), .dout(iccm_dma_ecc_error));
|
iccm_dma_rvalid_in,
|
||||||
rvdff #(64)dma_data_ff (.*, .clk(free_clk), .din(iccm_dma_rdata_in[63:0]), .dout(iccm_dma_rdata[63:0]));
|
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] :
|
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] ;
|
(~(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
|
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_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_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_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_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_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 ;
|
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]));
|
rvdffie #(pt.ICCM_BITS-1) iccm_index_f (.*, .clk(free_l2clk), .din({iccm_rw_addr[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), .*);
|
iccm_rd_ecc_single_err_hold_in
|
||||||
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), .*);
|
.dout({iccm_rw_addr_f[pt.ICCM_BITS-1:2],
|
||||||
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), .*);
|
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
|
end else begin : iccm_disabled
|
||||||
assign iccm_dma_rvalid = 1'b0 ;
|
assign iccm_dma_rvalid = 1'b0 ;
|
||||||
|
@ -1300,7 +1340,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
assign iccm_rd_ecc_single_err = 1'b0 ;
|
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_rd_ecc_single_err_ff = 1'b0 ;
|
||||||
assign iccm_error_start = 1'b0;
|
assign iccm_error_start = 1'b0;
|
||||||
assign iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2] = '0;
|
assign iccm_ecc_corr_index_ff[pt.ICCM_BITS-1:2] = '0;
|
||||||
|
@ -1318,7 +1358,6 @@ end
|
||||||
////// ICCM signals
|
////// 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 &
|
assign ic_rd_en = (ifc_fetch_req_bf & ~ifc_fetch_uncacheable_bf & ~ifc_iccm_access_bf &
|
||||||
~(((miss_state == STREAM) & ~miss_state_en) |
|
~(((miss_state == STREAM) & ~miss_state_en) |
|
||||||
((miss_state == CRIT_BYP_OK) & ~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)) )) |
|
((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 ) ;
|
( ifc_fetch_req_bf & exu_flush_final & ~ifc_fetch_uncacheable_bf & ~ifc_iccm_access_bf ) ;
|
||||||
|
|
||||||
|
|
||||||
logic ic_real_rd_wp_unused;
|
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 &
|
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) |
|
~(((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_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)));
|
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];
|
ifu_status_wr_addr[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO];
|
||||||
|
|
||||||
// status
|
// 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);
|
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] :
|
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] ;
|
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_clken;
|
||||||
logic [(pt.ICACHE_TAG_DEPTH/8)-1 : 0] way_status_clk;
|
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 );
|
assign way_status_clken[i] = (ifu_status_wr_addr_ff[pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO+3] == 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]), .* );
|
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
|
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]),
|
.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)),
|
.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]),
|
.din(way_status_new_ff[pt.ICACHE_STATUS_BITS-1:0]),
|
||||||
.dout(way_status_out[8*i+j]));
|
.dout(way_status_out[8*i+j]));
|
||||||
|
@ -1389,7 +1436,7 @@ if (pt.ICACHE_ENABLE == 1 ) begin: icache_enabled
|
||||||
|
|
||||||
always_comb begin : way_status_out_mux
|
always_comb begin : way_status_out_mux
|
||||||
way_status[pt.ICACHE_STATUS_BITS-1:0] = '0 ;
|
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
|
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];
|
way_status[pt.ICACHE_STATUS_BITS-1:0] = way_status_out[j];
|
||||||
end
|
end
|
||||||
|
@ -1399,28 +1446,28 @@ if (pt.ICACHE_ENABLE == 1 ) begin: icache_enabled
|
||||||
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] :
|
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];
|
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] ;
|
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;
|
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),
|
rvdffie #(pt.ICACHE_TAG_LO-pt.ICACHE_TAG_INDEX_LO+pt.ICACHE_NUM_WAYS+1) tag_addr_ff (.*,
|
||||||
.dout(ic_valid_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_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_clken ;
|
||||||
logic [(pt.ICACHE_TAG_DEPTH/32)-1:0] [pt.ICACHE_NUM_WAYS-1:0] tag_valid_clk ;
|
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 i=0 ; i<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 j=0; j<pt.ICACHE_NUM_WAYS; j++) begin : way_clken
|
||||||
if (pt.ICACHE_TAG_DEPTH == 32 ) begin
|
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;
|
assign tag_valid_clken[i][j] = ifu_tag_wren_ff[j] | perr_err_inv_way[j] | reset_all_tags;
|
||||||
end else begin
|
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);
|
((perr_ic_index_ff [pt.ICACHE_INDEX_HI:pt.ICACHE_TAG_INDEX_LO+5] == i ) & perr_err_inv_way[j]) | reset_all_tags);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
`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]), .* );
|
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
|
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]),
|
.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] ) |
|
.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),
|
((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),
|
.din(ic_valid_ff & ~reset_all_tags & ~perr_sel_invalidate),
|
||||||
|
@ -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])) |
|
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] ) ;
|
(~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}) |
|
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{ic_rd_hit[1]}} & {way_status[2] , 1'b0 , 1'b1}) |
|
({3{~exu_flush_final & ic_rd_hit[1]}} & {way_status[2] , 1'b0 , 1'b1}) |
|
||||||
({3{ic_rd_hit[2]}} & {1'b1 ,way_status[1] , 1'b0}) |
|
({3{~exu_flush_final & ic_rd_hit[2]}} & {1'b1 ,way_status[1] , 1'b0}) |
|
||||||
({3{ic_rd_hit[3]}} & {1'b0 ,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}) |
|
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}) |
|
({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;
|
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[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 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];
|
assign ifu_tag_wren[i] = bus_wren_last[i] | wren_reset_miss[i];
|
||||||
|
@ -1528,7 +1583,7 @@ end else begin: icache_disabled
|
||||||
|
|
||||||
end
|
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}}) ;
|
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
|
// PMU signals
|
||||||
|
@ -1536,19 +1591,21 @@ end
|
||||||
|
|
||||||
assign ifu_pmu_ic_miss_in = ic_act_miss_f ;
|
assign ifu_pmu_ic_miss_in = ic_act_miss_f ;
|
||||||
assign ifu_pmu_ic_hit_in = ic_act_hit_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_trxn_in = bus_cmd_sent ;
|
||||||
assign ifu_pmu_bus_busy_in = ifu_bus_arvalid_ff & ~ifu_bus_arready_ff & miss_pending ;
|
assign ifu_pmu_bus_busy_in = ifu_bus_arvalid_ff & ~ifu_bus_arready_ff & miss_pending ;
|
||||||
|
|
||||||
rvdff #(5) ifu_pmu_sigs_ff (.*,
|
rvdffie #(9) ifu_pmu_sigs_ff (.*,
|
||||||
.clk (active_clk),
|
.clk (free_l2clk),
|
||||||
.din ({ifu_pmu_ic_miss_in,
|
.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_ic_hit_in,
|
||||||
ifu_pmu_bus_error_in,
|
ifu_pmu_bus_error_in,
|
||||||
ifu_pmu_bus_busy_in,
|
ifu_pmu_bus_busy_in,
|
||||||
ifu_pmu_bus_trxn_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_ic_hit,
|
||||||
ifu_pmu_bus_error,
|
ifu_pmu_bus_error,
|
||||||
ifu_pmu_bus_busy,
|
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 ;
|
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,
|
.din ({ic_debug_ict_array_sel_in,
|
||||||
ic_debug_way[pt.ICACHE_NUM_WAYS-1:0]
|
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;
|
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;
|
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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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;
|
clk=0;
|
||||||
rst_l=0;
|
rst_l=0;
|
||||||
|
|
||||||
// initialize the reads and populate the istruction arrays
|
// initialize the reads and populate the instruction arrays
|
||||||
$readmemh ("left64k", compressed );
|
$readmemh ("left64k", compressed );
|
||||||
$readmemh ("right64k", expected );
|
$readmemh ("right64k", expected );
|
||||||
|
|
||||||
|
|
||||||
$dumpfile ("top.vcd");
|
$dumpfile ("top.vcd");
|
||||||
$dumpvars;
|
$dumpvars;
|
||||||
$dumpon;
|
$dumpon;
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
package el2_pkg;
|
package el2_pkg;
|
||||||
|
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic [1:0] rv_i_valid_ip;
|
logic trace_rv_i_valid_ip;
|
||||||
logic [31:0] rv_i_insn_ip;
|
logic [31:0] trace_rv_i_insn_ip;
|
||||||
logic [31:0] rv_i_address_ip;
|
logic [31:0] trace_rv_i_address_ip;
|
||||||
logic [1:0] rv_i_exception_ip;
|
logic trace_rv_i_exception_ip;
|
||||||
logic [4:0] rv_i_ecause_ip;
|
logic [4:0] trace_rv_i_ecause_ip;
|
||||||
logic [1:0] rv_i_interrupt_ip;
|
logic trace_rv_i_interrupt_ip;
|
||||||
logic [31:0] rv_i_tval_ip;
|
logic [31:0] trace_rv_i_tval_ip;
|
||||||
} el2_trace_pkt_t;
|
} el2_trace_pkt_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,36 +76,41 @@ typedef struct packed {
|
||||||
logic valid;
|
logic valid;
|
||||||
logic br_error;
|
logic br_error;
|
||||||
logic br_start_error;
|
logic br_start_error;
|
||||||
logic [31:1] prett;
|
|
||||||
logic pcall;
|
logic pcall;
|
||||||
logic pret;
|
|
||||||
logic pja;
|
logic pja;
|
||||||
logic way;
|
logic way;
|
||||||
|
logic pret;
|
||||||
|
// for power use the pret bit to clock the prett field
|
||||||
|
logic [31:1] prett;
|
||||||
} el2_predict_pkt_t;
|
} el2_predict_pkt_t;
|
||||||
|
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic legal;
|
// unlikely to change
|
||||||
logic icaf;
|
logic icaf;
|
||||||
logic icaf_f1;
|
logic icaf_second;
|
||||||
logic [1:0] icaf_type;
|
logic [1:0] icaf_type;
|
||||||
logic fence_i;
|
logic fence_i;
|
||||||
logic [3:0] i0trigger;
|
logic [3:0] i0trigger;
|
||||||
el2_inst_pkt_t pmu_i0_itype; // pmu - instruction type
|
|
||||||
logic pmu_i0_br_unpred; // pmu
|
logic pmu_i0_br_unpred; // pmu
|
||||||
logic pmu_divide;
|
logic pmu_divide;
|
||||||
|
// likely to change
|
||||||
|
logic legal;
|
||||||
logic pmu_lsu_misaligned;
|
logic pmu_lsu_misaligned;
|
||||||
|
el2_inst_pkt_t pmu_i0_itype; // pmu - instruction type
|
||||||
} el2_trap_pkt_t;
|
} el2_trap_pkt_t;
|
||||||
|
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic [4:0] i0rd;
|
// unlikely to change
|
||||||
logic i0load;
|
|
||||||
logic i0store;
|
|
||||||
logic i0div;
|
logic i0div;
|
||||||
logic i0v;
|
|
||||||
logic i0valid;
|
|
||||||
logic csrwen;
|
logic csrwen;
|
||||||
logic csrwonly;
|
logic csrwonly;
|
||||||
logic [11:0] csrwaddr;
|
logic [11:0] csrwaddr;
|
||||||
|
// likely to change
|
||||||
|
logic [4:0] i0rd;
|
||||||
|
logic i0load;
|
||||||
|
logic i0store;
|
||||||
|
logic i0v;
|
||||||
|
logic i0valid;
|
||||||
} el2_dest_pkt_t;
|
} el2_dest_pkt_t;
|
||||||
|
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
|
@ -122,6 +127,31 @@ typedef struct packed {
|
||||||
|
|
||||||
|
|
||||||
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 land;
|
||||||
logic lor;
|
logic lor;
|
||||||
logic lxor;
|
logic lxor;
|
||||||
|
@ -145,6 +175,9 @@ typedef struct packed {
|
||||||
|
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic fast_int;
|
logic fast_int;
|
||||||
|
/* verilator lint_off SYMRSVDWORD */
|
||||||
|
logic stack;
|
||||||
|
/* verilator lint_on SYMRSVDWORD */
|
||||||
logic by;
|
logic by;
|
||||||
logic half;
|
logic half;
|
||||||
logic word;
|
logic word;
|
||||||
|
@ -160,15 +193,61 @@ typedef struct packed {
|
||||||
} el2_lsu_pkt_t;
|
} el2_lsu_pkt_t;
|
||||||
|
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic exc_valid;
|
|
||||||
logic single_ecc_error;
|
|
||||||
logic inst_type; //0: Load, 1: Store
|
logic inst_type; //0: Load, 1: Store
|
||||||
|
//logic dma_valid;
|
||||||
logic exc_type; //0: MisAligned, 1: Access Fault
|
logic exc_type; //0: MisAligned, 1: Access Fault
|
||||||
logic [3:0] mscause;
|
logic [3:0] mscause;
|
||||||
logic [31:0] addr;
|
logic [31:0] addr;
|
||||||
|
logic single_ecc_error;
|
||||||
|
logic exc_valid;
|
||||||
} el2_lsu_error_pkt_t;
|
} el2_lsu_error_pkt_t;
|
||||||
|
|
||||||
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 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 alu;
|
||||||
logic rs1;
|
logic rs1;
|
||||||
logic rs2;
|
logic rs2;
|
||||||
|
@ -233,6 +312,7 @@ typedef struct packed {
|
||||||
logic clmulh;
|
logic clmulh;
|
||||||
logic clmulr;
|
logic clmulr;
|
||||||
logic grev;
|
logic grev;
|
||||||
|
logic gorc;
|
||||||
logic shfl;
|
logic shfl;
|
||||||
logic unshfl;
|
logic unshfl;
|
||||||
logic crc32_b;
|
logic crc32_b;
|
||||||
|
@ -320,6 +400,6 @@ typedef struct packed {
|
||||||
logic icache_rd_valid;
|
logic icache_rd_valid;
|
||||||
logic icache_wr_valid;
|
logic icache_wr_valid;
|
||||||
} el2_cache_debug_pkt_t;
|
} el2_cache_debug_pkt_t;
|
||||||
|
//`endif
|
||||||
|
|
||||||
endpackage // el2_pkg
|
endpackage // el2_pkg
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// 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 buf_rdata_en;
|
||||||
|
|
||||||
logic ahb_bus_addr_clk_en, buf_rdata_clk_en;
|
logic ahb_addr_clk_en, buf_rdata_clk_en;
|
||||||
logic ahb_clk, ahb_addr_clk, buf_rdata_clk;
|
logic bus_clk, ahb_addr_clk, buf_rdata_clk;
|
||||||
// Command buffer is the holding station where we convert to AXI and send to core
|
// Command buffer is the holding station where we convert to AXI and send to core
|
||||||
logic cmdbuf_wr_en, cmdbuf_rst;
|
logic cmdbuf_wr_en, cmdbuf_rst;
|
||||||
logic cmdbuf_full;
|
logic cmdbuf_full;
|
||||||
|
@ -130,8 +130,6 @@ import el2_pkg::*;
|
||||||
logic [31:0] cmdbuf_addr;
|
logic [31:0] cmdbuf_addr;
|
||||||
logic [63:0] cmdbuf_wdata;
|
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
|
// FSM to control the bus states and when to block the hready and load the command buffer
|
||||||
always_comb begin
|
always_comb begin
|
||||||
buf_nxtstate = IDLE;
|
buf_nxtstate = IDLE;
|
||||||
|
@ -163,7 +161,7 @@ import el2_pkg::*;
|
||||||
endcase
|
endcase
|
||||||
end // always_comb begin
|
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])) |
|
assign master_wstrb[7:0] = ({8{ahb_hsize_q[2:0] == 3'b0}} & (8'b1 << ahb_haddr_q[2:0])) |
|
||||||
({8{ahb_hsize_q[2:0] == 3'b1}} & (8'b11 << ahb_haddr_q[2:0])) |
|
({8{ahb_hsize_q[2:0] == 3'b1}} & (8'b11 << ahb_haddr_q[2:0])) |
|
||||||
|
@ -188,24 +186,16 @@ import el2_pkg::*;
|
||||||
(ahb_hresp_q & ~ahb_hready_q);
|
(ahb_hresp_q & ~ahb_hready_q);
|
||||||
|
|
||||||
// Buffer signals - needed for the read data and ECC error response
|
// 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_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 #(.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(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.
|
// 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_fpga #(.WIDTH(1)) hresp_ff (.din(ahb_hresp), .dout(ahb_hresp_q), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
|
||||||
rvdff #(.WIDTH(1)) hready_ff (.din(ahb_hready), .dout(ahb_hready_q), .clk(ahb_clk), .*);
|
rvdff_fpga #(.WIDTH(1)) hready_ff (.din(ahb_hready), .dout(ahb_hready_q), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
|
||||||
rvdff #(.WIDTH(2)) htrans_ff (.din(ahb_htrans_in[1:0]), .dout(ahb_htrans_q[1:0]), .clk(ahb_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 #(.WIDTH(3)) hsize_ff (.din(ahb_hsize[2:0]), .dout(ahb_hsize_q[2:0]), .clk(ahb_addr_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 #(.WIDTH(1)) hwrite_ff (.din(ahb_hwrite), .dout(ahb_hwrite_q), .clk(ahb_addr_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 #(.WIDTH(32)) haddr_ff (.din(ahb_haddr[31:0]), .dout(ahb_haddr_q[31:0]), .clk(ahb_addr_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), .*);
|
||||||
|
|
||||||
// Clock header logic
|
|
||||||
assign ahb_bus_addr_clk_en = bus_clk_en & (ahb_hready & ahb_htrans[1]);
|
|
||||||
assign buf_rdata_clk_en = bus_clk_en & buf_rdata_en;
|
|
||||||
|
|
||||||
rvclkhdr ahb_cgc (.en(bus_clk_en), .l1clk(ahb_clk), .*);
|
|
||||||
rvclkhdr ahb_addr_cgc (.en(ahb_bus_addr_clk_en), .l1clk(ahb_addr_clk), .*);
|
|
||||||
rvclkhdr buf_rdata_cgc (.en(buf_rdata_clk_en), .l1clk(buf_rdata_clk), .*);
|
|
||||||
|
|
||||||
// Address check dccm
|
// Address check dccm
|
||||||
rvrangecheck #(.CCM_SADR(pt.DCCM_SADR),
|
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_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)));
|
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), .*);
|
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 #(.WIDTH(1)) cmdbuf_writeff (.din(ahb_hwrite_q), .dout(cmdbuf_write), .en(cmdbuf_wr_en), .clk(bus_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 #(.WIDTH(2)) cmdbuf_sizeff (.din(ahb_hsize_q[1:0]), .dout(cmdbuf_size[1:0]), .en(cmdbuf_wr_en), .clk(bus_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 #(.WIDTH(8)) cmdbuf_wstrbff (.din(master_wstrb[7:0]), .dout(cmdbuf_wstrb[7:0]), .en(cmdbuf_wr_en), .clk(bus_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), .clk(bus_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), .clk(bus_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
|
// AXI Write Command Channel
|
||||||
assign axi_awvalid = cmdbuf_vld & cmdbuf_write;
|
assign axi_awvalid = cmdbuf_vld & cmdbuf_write;
|
||||||
|
@ -274,11 +264,22 @@ import el2_pkg::*;
|
||||||
assign axi_rready = 1'b1;
|
assign axi_rready = 1'b1;
|
||||||
|
|
||||||
// Clock header logic
|
// 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;
|
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
|
endproperty
|
||||||
assert_ahb_error_protocol: assert property (ahb_error_protocol) else
|
assert_ahb_error_protocol: assert property (ahb_error_protocol) else
|
||||||
$display("Bus Error with hReady isn't preceded with Bus Error without hready");
|
$display("Bus Error with hReady isn't preceded with Bus Error without hready");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -28,10 +28,12 @@ import el2_pkg::*;
|
||||||
,parameter TAG = 1) (
|
,parameter TAG = 1) (
|
||||||
|
|
||||||
input clk,
|
input clk,
|
||||||
|
input free_clk,
|
||||||
input rst_l,
|
input rst_l,
|
||||||
input scan_mode,
|
input scan_mode,
|
||||||
input bus_clk_en,
|
input bus_clk_en,
|
||||||
input clk_override,
|
input clk_override,
|
||||||
|
input dec_tlu_force_halt,
|
||||||
|
|
||||||
// AXI signals
|
// AXI signals
|
||||||
// AXI Write Channels
|
// AXI Write Channels
|
||||||
|
@ -105,9 +107,6 @@ import el2_pkg::*;
|
||||||
logic [63:0] wrbuf_data;
|
logic [63:0] wrbuf_data;
|
||||||
logic [7:0] wrbuf_byteen;
|
logic [7:0] wrbuf_byteen;
|
||||||
|
|
||||||
logic bus_write_clk_en;
|
|
||||||
logic bus_clk, bus_write_clk;
|
|
||||||
|
|
||||||
logic master_valid;
|
logic master_valid;
|
||||||
logic master_ready;
|
logic master_ready;
|
||||||
logic [TAG-1:0] master_tag;
|
logic [TAG-1:0] master_tag;
|
||||||
|
@ -169,15 +168,15 @@ import el2_pkg::*;
|
||||||
logic [31:0] last_bus_addr;
|
logic [31:0] last_bus_addr;
|
||||||
|
|
||||||
// Clocks
|
// Clocks
|
||||||
logic buf_clken, slvbuf_clken;
|
logic buf_clken;
|
||||||
logic ahbm_addr_clken;
|
|
||||||
logic ahbm_data_clken;
|
logic ahbm_data_clken;
|
||||||
|
|
||||||
logic buf_clk, slvbuf_clk;
|
logic buf_clk;
|
||||||
logic ahbm_clk;
|
logic bus_clk;
|
||||||
logic ahbm_addr_clk;
|
|
||||||
logic ahbm_data_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 to get the length from byte enable
|
||||||
function automatic logic [1:0] get_write_size;
|
function automatic logic [1:0] get_write_size;
|
||||||
input logic [7:0] byteen;
|
input logic [7:0] byteen;
|
||||||
|
@ -210,6 +209,7 @@ import el2_pkg::*;
|
||||||
logic [2:0] start_ptr;
|
logic [2:0] start_ptr;
|
||||||
logic found;
|
logic found;
|
||||||
found = '0;
|
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];
|
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
|
for (int j=0; j<8; j++) begin
|
||||||
if (~found) begin
|
if (~found) begin
|
||||||
|
@ -219,12 +219,16 @@ import el2_pkg::*;
|
||||||
end
|
end
|
||||||
endfunction // get_nextbyte_ptr
|
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
|
// Write buffer
|
||||||
assign wrbuf_en = axi_awvalid & axi_awready & master_ready;
|
assign wrbuf_en = axi_awvalid & axi_awready & master_ready;
|
||||||
assign wrbuf_data_en = axi_wvalid & axi_wready & 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_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_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent) & master_ready;
|
||||||
assign axi_wready = ~(wrbuf_data_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 axi_rdata[63:0] = slave_rdata[63:0];
|
||||||
assign slave_ready = axi_bready & axi_rready;
|
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
|
// FIFO state machine
|
||||||
always_comb begin
|
always_comb begin
|
||||||
buf_nxtstate = IDLE;
|
buf_nxtstate = IDLE;
|
||||||
|
@ -378,7 +375,7 @@ import el2_pkg::*;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
assign buf_rst = 1'b0;
|
assign buf_rst = dec_tlu_force_halt_bus;
|
||||||
assign cmd_done_rst = slave_valid_pre;
|
assign cmd_done_rst = slave_valid_pre;
|
||||||
assign buf_addr_in[31:3] = master_addr[31:3];
|
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];
|
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)));
|
(master_byteen[7:0] == 8'hf) | (master_byteen[7:0] == 8'hf0) | (master_byteen[7:0] == 8'hff)));
|
||||||
|
|
||||||
// Generate the ahb signals
|
// 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])} :
|
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
|
{1'b0, ({2{buf_aligned}} & buf_size[1:0])}; // Send the full size for aligned trxn
|
||||||
assign ahb_hburst[2:0] = 3'b0;
|
assign ahb_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_hwrite = bypass_en ? (master_opc[2:1] == 2'b01) : buf_write;
|
||||||
assign ahb_hwdata[63:0] = buf_data[63:0];
|
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[3:2] = slvbuf_write ? 2'b11 : 2'b00;
|
||||||
assign slave_opc[1:0] = {2{slvbuf_error}} & 2'b10;
|
assign slave_opc[1:0] = {2{slvbuf_error}} & 2'b10;
|
||||||
assign slave_rdata[63:0] = slvbuf_error ? {2{last_bus_addr[31:0]}} : ((buf_state == DONE) ? buf_data[63:0] : ahb_hrdata_q[63:0]);
|
assign slave_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 ;
|
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_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 #(.WIDTH(1)) wrbuf_data_vldff(.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_rst), .clk(bus_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 #(.WIDTH(TAG)) wrbuf_tagff (.din(axi_awid[TAG-1:0]), .dout(wrbuf_tag[TAG-1:0]), .en(wrbuf_en), .clk(bus_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 #(.WIDTH(3)) wrbuf_sizeff (.din(axi_awsize[2:0]), .dout(wrbuf_size[2:0]), .en(wrbuf_en), .clk(bus_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), .clk(bus_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), .clk(bus_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 #(.WIDTH(8)) wrbuf_byteenff (.din(axi_wstrb[7:0]), .dout(wrbuf_byteen[7:0]), .en(wrbuf_data_en), .clk(bus_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), .*);
|
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 #(.WIDTH(1)) buf_writeff (.din(buf_write_in), .dout(buf_write), .en(buf_wr_en), .clk(buf_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 #(.WIDTH(TAG)) buf_tagff (.din(buf_tag_in[TAG-1:0]), .dout(buf_tag[TAG-1:0]), .en(buf_wr_en), .clk(buf_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), .*);
|
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 #(.WIDTH(2)) buf_sizeff (.din(buf_size_in[1:0]), .dout(buf_size[1:0]), .en(buf_wr_en), .clk(buf_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 #(.WIDTH(1)) buf_alignedff (.din(buf_aligned_in), .dout(buf_aligned), .en(buf_wr_en), .clk(buf_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 #(.WIDTH(8)) buf_byteenff (.din(buf_byteen_in[7:0]), .dout(buf_byteen[7:0]), .en(buf_wr_en), .clk(buf_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), .*);
|
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_fpga #(.WIDTH(1)) slvbuf_writeff (.din(buf_write), .dout(slvbuf_write), .en(slvbuf_wr_en), .clk(buf_clk), .clken(buf_clken), .rawclk(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_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 #(.WIDTH(1)) slvbuf_errorff (.din(slvbuf_error_in), .dout(slvbuf_error), .en(slvbuf_error_en), .clk(ahbm_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), .*);
|
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 #(.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), .*);
|
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_fpga #(.WIDTH(1)) hready_ff (.din(ahb_hready), .dout(ahb_hready_q), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
|
||||||
rvdff #(.WIDTH(2)) htrans_ff (.din(ahb_htrans[1:0]), .dout(ahb_htrans_q[1:0]), .clk(ahbm_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 #(.WIDTH(1)) hwrite_ff (.din(ahb_hwrite), .dout(ahb_hwrite_q), .clk(ahbm_addr_clk), .*);
|
rvdff_fpga #(.WIDTH(1)) hwrite_ff (.din(ahb_hwrite), .dout(ahb_hwrite_q), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
|
||||||
rvdff #(.WIDTH(1)) hresp_ff (.din(ahb_hresp), .dout(ahb_hresp_q), .clk(ahbm_clk), .*);
|
rvdff_fpga #(.WIDTH(1)) hresp_ff (.din(ahb_hresp), .dout(ahb_hresp_q), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*);
|
||||||
rvdff #(.WIDTH(64)) hrdata_ff (.din(ahb_hrdata[63:0]), .dout(ahb_hrdata_q[63:0]), .clk(ahbm_data_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 headers
|
||||||
// clock enables for ahbm addr/data
|
// clock enables for ahbm addr/data
|
||||||
assign buf_clken = bus_clk_en & (buf_wr_en | slvbuf_wr_en | clk_override);
|
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);
|
assign ahbm_data_clken = bus_clk_en & ((buf_state != IDLE) | clk_override);
|
||||||
|
|
||||||
|
`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 buf_cgc (.en(buf_clken), .l1clk(buf_clk), .*);
|
||||||
rvclkhdr ahbm_cgc (.en(bus_clk_en), .l1clk(ahbm_clk), .*);
|
|
||||||
rvclkhdr ahbm_addr_cgc (.en(ahbm_addr_clken), .l1clk(ahbm_addr_clk), .*);
|
|
||||||
rvclkhdr ahbm_data_cgc (.en(ahbm_data_clken), .l1clk(ahbm_data_clk), .*);
|
rvclkhdr ahbm_data_cgc (.en(ahbm_data_clken), .l1clk(ahbm_data_clk), .*);
|
||||||
|
`endif
|
||||||
|
|
||||||
`ifdef ASSERT_ON
|
`ifdef RV_ASSERT_ON
|
||||||
property ahb_trxn_aligned;
|
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'h1) & (ahb_haddr[0] == 1'b0)) |
|
||||||
((ahb_hsize[2:0] == 3'h2) & (ahb_haddr[1:0] == 2'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)));
|
((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]);
|
$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;
|
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
|
endproperty
|
||||||
assert_ahb_error_protocol: assert property (ahb_error_protocol) else
|
assert_ahb_error_protocol: assert property (ahb_error_protocol) else
|
||||||
$display("Bus Error with hReady isn't preceded with Bus Error without hready");
|
$display("Bus Error with hReady isn't preceded with Bus Error without hready");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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;
|
assign dout = din;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
`ifdef CLOCKGATE
|
`ifdef RV_CLOCKGATE
|
||||||
always @(posedge tb_top.clk) begin
|
always @(posedge tb_top.clk) begin
|
||||||
#0 $strobe("CG: %0t %m din %x dout %x clk %b width %d",$time,din,dout,clk,WIDTH);
|
#0 $strobe("CG: %0t %m din %x dout %x clk %b width %d",$time,din,dout,clk,WIDTH);
|
||||||
end
|
end
|
||||||
|
@ -85,7 +85,85 @@ else begin
|
||||||
end
|
end
|
||||||
endmodule
|
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 [WIDTH-1:0] din,
|
||||||
input logic en,
|
input logic en,
|
||||||
|
@ -104,8 +182,8 @@ if (SHORT == 1) begin : genblock
|
||||||
end
|
end
|
||||||
else begin : genblock
|
else begin : genblock
|
||||||
|
|
||||||
`ifndef PHYSICAL
|
`ifndef RV_PHYSICAL
|
||||||
if (WIDTH >= 8) begin: genblock
|
if (WIDTH >= 8 || OVERRIDE==1) begin: genblock
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef RV_FPGA_OPTIMIZE
|
`ifdef RV_FPGA_OPTIMIZE
|
||||||
|
@ -115,15 +193,226 @@ else begin : genblock
|
||||||
rvdff #(WIDTH) dff (.*, .clk(l1clk));
|
rvdff #(WIDTH) dff (.*, .clk(l1clk));
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifndef PHYSICAL
|
`ifndef RV_PHYSICAL
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
$error("%m: rvdffe width must be >= 8");
|
$error("%m: rvdffe must be WIDTH >= 8");
|
||||||
`endif
|
`endif
|
||||||
end // else: !if(SHORT == 1)
|
end // else: !if(SHORT == 1)
|
||||||
|
|
||||||
endmodule // rvdffe
|
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)
|
module rvsyncss #(parameter WIDTH = 251)
|
||||||
(
|
(
|
||||||
input logic clk,
|
input logic clk,
|
||||||
|
@ -139,6 +428,23 @@ module rvsyncss #(parameter WIDTH = 251)
|
||||||
|
|
||||||
endmodule // rvsyncss
|
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
|
module rvlsadder
|
||||||
(
|
(
|
||||||
input logic [31:0] rs1,
|
input logic [31:0] rs1,
|
||||||
|
@ -468,6 +774,7 @@ module `TEC_RV_ICG
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
`ifndef RV_FPGA_OPTIMIZE
|
||||||
module rvclkhdr
|
module rvclkhdr
|
||||||
(
|
(
|
||||||
input logic en,
|
input logic en,
|
||||||
|
@ -477,11 +784,12 @@ module rvclkhdr
|
||||||
);
|
);
|
||||||
|
|
||||||
logic SE;
|
logic SE;
|
||||||
assign SE = scan_mode;
|
assign SE = 0;
|
||||||
|
|
||||||
`TEC_RV_ICG clkhdr ( .*, .EN(en), .CK(clk), .Q(l1clk));
|
`TEC_RV_ICG clkhdr ( .*, .EN(en), .CK(clk), .Q(l1clk));
|
||||||
|
|
||||||
endmodule // rvclkhdr
|
endmodule // rvclkhdr
|
||||||
|
`endif
|
||||||
|
|
||||||
module rvoclkhdr
|
module rvoclkhdr
|
||||||
(
|
(
|
||||||
|
@ -492,7 +800,7 @@ module rvoclkhdr
|
||||||
);
|
);
|
||||||
|
|
||||||
logic SE;
|
logic SE;
|
||||||
assign SE = scan_mode;
|
assign SE = 0;
|
||||||
|
|
||||||
`ifdef RV_FPGA_OPTIMIZE
|
`ifdef RV_FPGA_OPTIMIZE
|
||||||
assign l1clk = clk;
|
assign l1clk = clk;
|
||||||
|
|
|
@ -16,7 +16,17 @@
|
||||||
`define EL2_LOCAL_RAM_TEST_IO \
|
`define EL2_LOCAL_RAM_TEST_IO \
|
||||||
input logic WE, \
|
input logic WE, \
|
||||||
input logic ME, \
|
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) \
|
`define EL2_RAM(depth, width) \
|
||||||
module ram_``depth``x``width( \
|
module ram_``depth``x``width( \
|
||||||
|
@ -26,11 +36,22 @@ module ram_``depth``x``width( \
|
||||||
`EL2_LOCAL_RAM_TEST_IO \
|
`EL2_LOCAL_RAM_TEST_IO \
|
||||||
); \
|
); \
|
||||||
reg [(width-1):0] ram_core [(depth-1):0]; \
|
reg [(width-1):0] ram_core [(depth-1):0]; \
|
||||||
\
|
`ifdef GTLSIM \
|
||||||
|
integer i; \
|
||||||
|
initial begin \
|
||||||
|
for (i=0; i<depth; i=i+1) \
|
||||||
|
ram_core[i] = '0; \
|
||||||
|
end \
|
||||||
|
`endif \
|
||||||
always @(posedge CLK) begin \
|
always @(posedge CLK) begin \
|
||||||
|
`ifdef GTLSIM \
|
||||||
if (ME && WE) ram_core[ADR] <= D; \
|
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]; \
|
if (ME && ~WE) Q <= ram_core[ADR]; \
|
||||||
end \
|
end \
|
||||||
|
assign ROP = ME; \
|
||||||
\
|
\
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -42,12 +63,22 @@ module ram_be_``depth``x``width( \
|
||||||
`EL2_LOCAL_RAM_TEST_IO \
|
`EL2_LOCAL_RAM_TEST_IO \
|
||||||
); \
|
); \
|
||||||
reg [(width-1):0] ram_core [(depth-1):0]; \
|
reg [(width-1):0] ram_core [(depth-1):0]; \
|
||||||
\
|
`ifdef GTLSIM \
|
||||||
|
integer i; \
|
||||||
|
initial begin \
|
||||||
|
for (i=0; i<depth; i=i+1) \
|
||||||
|
ram_core[i] = '0; \
|
||||||
|
end \
|
||||||
|
`endif \
|
||||||
always @(posedge CLK) begin \
|
always @(posedge CLK) begin \
|
||||||
if (ME && WE) ram_core[ADR] = D & WEM | ~WEM & ram_core[ADR];\
|
`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]; \
|
if (ME && ~WE) Q <= ram_core[ADR]; \
|
||||||
end \
|
end \
|
||||||
\
|
assign ROP = ME; \
|
||||||
\
|
\
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
@ -61,7 +92,11 @@ output logic [(width-1):0] Q,
|
||||||
reg [(width-1):0] ram_core [(depth-1):0];
|
reg [(width-1):0] ram_core [(depth-1):0];
|
||||||
|
|
||||||
always @(posedge CLK) begin
|
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];
|
if (ME && ~WE) Q <= ram_core[ADR];
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -172,6 +207,7 @@ endmodule
|
||||||
`EL2_RAM_BE(256, 52)
|
`EL2_RAM_BE(256, 52)
|
||||||
`EL2_RAM_BE(128, 52)
|
`EL2_RAM_BE(128, 52)
|
||||||
`EL2_RAM_BE(64, 52)
|
`EL2_RAM_BE(64, 52)
|
||||||
|
`EL2_RAM_BE(32, 52)
|
||||||
`EL2_RAM_BE(4096, 104)
|
`EL2_RAM_BE(4096, 104)
|
||||||
`EL2_RAM_BE(2048, 104)
|
`EL2_RAM_BE(2048, 104)
|
||||||
`EL2_RAM_BE(1024, 104)
|
`EL2_RAM_BE(1024, 104)
|
||||||
|
@ -179,6 +215,7 @@ endmodule
|
||||||
`EL2_RAM_BE(256, 104)
|
`EL2_RAM_BE(256, 104)
|
||||||
`EL2_RAM_BE(128, 104)
|
`EL2_RAM_BE(128, 104)
|
||||||
`EL2_RAM_BE(64, 104)
|
`EL2_RAM_BE(64, 104)
|
||||||
|
`EL2_RAM_BE(32, 104)
|
||||||
`EL2_RAM_BE(4096, 44)
|
`EL2_RAM_BE(4096, 44)
|
||||||
`EL2_RAM_BE(2048, 44)
|
`EL2_RAM_BE(2048, 44)
|
||||||
`EL2_RAM_BE(1024, 44)
|
`EL2_RAM_BE(1024, 44)
|
||||||
|
@ -186,6 +223,7 @@ endmodule
|
||||||
`EL2_RAM_BE(256, 44)
|
`EL2_RAM_BE(256, 44)
|
||||||
`EL2_RAM_BE(128, 44)
|
`EL2_RAM_BE(128, 44)
|
||||||
`EL2_RAM_BE(64, 44)
|
`EL2_RAM_BE(64, 44)
|
||||||
|
`EL2_RAM_BE(32, 44)
|
||||||
`EL2_RAM_BE(4096, 88)
|
`EL2_RAM_BE(4096, 88)
|
||||||
`EL2_RAM_BE(2048, 88)
|
`EL2_RAM_BE(2048, 88)
|
||||||
`EL2_RAM_BE(1024, 88)
|
`EL2_RAM_BE(1024, 88)
|
||||||
|
@ -193,6 +231,8 @@ endmodule
|
||||||
`EL2_RAM_BE(256, 88)
|
`EL2_RAM_BE(256, 88)
|
||||||
`EL2_RAM_BE(128, 88)
|
`EL2_RAM_BE(128, 88)
|
||||||
`EL2_RAM_BE(64, 88)
|
`EL2_RAM_BE(64, 88)
|
||||||
|
`EL2_RAM_BE(32, 88)
|
||||||
|
`EL2_RAM(64, 39)
|
||||||
|
|
||||||
|
|
||||||
`undef EL2_RAM
|
`undef EL2_RAM
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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_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 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_rs1_d, // address rs operand
|
||||||
input logic [31:0] exu_lsu_rs2_d, // store data
|
input logic [31:0] exu_lsu_rs2_d, // store data
|
||||||
input logic [11:0] dec_lsu_offset_d, // address offset operand
|
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_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_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_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 [31:1] lsu_fir_addr, // fast interrupt address
|
||||||
output logic [1:0] lsu_fir_error, // Error during fast interrupt lookup
|
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 [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 [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_load_external_m, // PMU : Bus loads
|
||||||
output logic lsu_pmu_store_external_m, // PMU : Bus loads
|
output logic lsu_pmu_store_external_m, // PMU : Bus loads
|
||||||
output logic lsu_pmu_misaligned_m, // PMU : misaligned
|
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 [63:0] dccm_dma_rdata, // lsu data for DMA dccm read
|
||||||
output logic dccm_ready, // lsu ready for DMA access
|
output logic dccm_ready, // lsu ready for DMA access
|
||||||
|
|
||||||
input logic scan_mode, // scan
|
input logic scan_mode, // scan mode
|
||||||
input logic 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_clk,
|
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
|
input logic rst_l // reset, active low
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
logic lsu_dccm_rden_m;
|
logic lsu_dccm_rden_m;
|
||||||
logic lsu_dccm_rden_r;
|
logic lsu_dccm_rden_r;
|
||||||
logic [31:0] store_data_m;
|
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_dccm_d, addr_in_dccm_m, addr_in_dccm_r;
|
||||||
logic addr_in_pic_d, addr_in_pic_m, addr_in_pic_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 addr_external_m;
|
||||||
|
|
||||||
logic stbuf_reqvld_any;
|
logic stbuf_reqvld_any;
|
||||||
|
@ -249,7 +248,6 @@ import el2_pkg::*;
|
||||||
logic lsu_bus_buffer_pend_any;
|
logic lsu_bus_buffer_pend_any;
|
||||||
logic lsu_bus_buffer_empty_any;
|
logic lsu_bus_buffer_empty_any;
|
||||||
logic lsu_bus_buffer_full_any;
|
logic lsu_bus_buffer_full_any;
|
||||||
logic lsu_bus_idle_any;
|
|
||||||
logic lsu_busreq_m;
|
logic lsu_busreq_m;
|
||||||
logic [31:0] bus_read_data_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;
|
logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_lo, dma_dccm_wdata_ecc_hi;
|
||||||
|
|
||||||
// Clocks
|
// Clocks
|
||||||
|
logic lsu_busm_clken;
|
||||||
|
logic lsu_bus_obuf_c1_clken;
|
||||||
logic lsu_c1_m_clk, lsu_c1_r_clk;
|
logic lsu_c1_m_clk, lsu_c1_r_clk;
|
||||||
logic lsu_c2_m_clk, lsu_c2_r_clk;
|
logic lsu_c2_m_clk, lsu_c2_r_clk;
|
||||||
logic lsu_store_c1_m_clk, lsu_store_c1_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
|
// 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 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 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 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_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
|
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_m_up = dec_tlu_flush_lower_r;
|
||||||
assign flush_r = dec_tlu_i0_kill_writeb_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.
|
// 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
|
// 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
|
// Store buffer now have only non-dma dccm stores
|
||||||
// stbuf_empty not needed since it has only dccm stores
|
// stbuf_empty not needed since it has only dccm stores
|
||||||
assign lsu_idle_any = ~((lsu_pkt_m.valid & ~lsu_pkt_m.dma) |
|
assign lsu_idle_any = ~((lsu_pkt_m.valid & ~lsu_pkt_m.dma) |
|
||||||
(lsu_pkt_r.valid & ~lsu_pkt_r.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
|
// 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
|
// 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);
|
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
|
// 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;
|
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
|
// 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_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;
|
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
|
// Bus interface
|
||||||
el2_lsu_bus_intf #(.pt(pt)) bus_intf (
|
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
|
//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 #(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));
|
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 RV_ASSERT_ON
|
||||||
`ifdef ASSERT_ON
|
|
||||||
logic [1:0] store_data_bypass_sel;
|
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};
|
assign store_data_bypass_sel[1:0] = {lsu_p.store_data_bypass_d, lsu_p.store_data_bypass_m};
|
||||||
|
|
||||||
property exception_no_lsu_flush;
|
property exception_no_lsu_flush;
|
||||||
@(posedge clk) disable iff(~rst_l) lsu_lsc_ctl.lsu_error_pkt_m.exc_valid |-> ##[1:2] (flush_r );
|
@(posedge clk) disable iff(~rst_l) lsu_lsc_ctl.lsu_error_pkt_m.exc_valid |-> ##[1:2] (flush_r );
|
||||||
endproperty
|
endproperty
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -34,9 +34,9 @@ import el2_pkg::*;
|
||||||
input logic [31:0] end_addr_d, // end 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 el2_lsu_pkt_t lsu_pkt_d, // packet in d
|
||||||
input logic [31:0] dec_tlu_mrac_ff, // CSR read
|
input logic [31:0] dec_tlu_mrac_ff, // CSR read
|
||||||
input logic [3:0] rs1_region_d,
|
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 is_sideeffects_m, // is sideffects space
|
||||||
output logic addr_in_dccm_d, // address in dccm
|
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_dccm_access_error_d, // Fast interrupt dccm access error
|
||||||
output logic fir_nondccm_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 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_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);
|
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 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
|
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
|
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
|
(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
|
(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
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)(
|
)(
|
||||||
input logic 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 rst_l,
|
input logic clk_override, // Override non-functional clock gating
|
||||||
input logic scan_mode,
|
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_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_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_sideeffect_posted_disable, // Don't block the sideeffect load store to the bus
|
||||||
input logic dec_tlu_force_halt,
|
input logic dec_tlu_force_halt,
|
||||||
|
|
||||||
// various clocks needed for the bus reads and writes
|
// 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_c2_r_clk,
|
||||||
input logic lsu_bus_ibuf_c1_clk,
|
input logic lsu_bus_ibuf_c1_clk,
|
||||||
input logic lsu_bus_obuf_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_m, // load/store is unaligned at 32 bit boundary
|
||||||
input logic ldst_dual_r, // 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_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_full_any, // bus buffer is full
|
||||||
output logic lsu_bus_buffer_empty_any, // bus buffer is empty
|
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 [3:0] ld_byte_hit_buf_lo, ld_byte_hit_buf_hi, // Byte enables for forwarding data
|
||||||
output logic [31:0] ld_fwddata_buf_lo, ld_fwddata_buf_hi, // load forwarding data
|
output logic [31:0] ld_fwddata_buf_lo, ld_fwddata_buf_hi, // load forwarding data
|
||||||
|
@ -92,7 +94,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 [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 [31:0] lsu_nonblock_load_data, // Data of the non block load
|
||||||
|
|
||||||
|
|
||||||
// PMU events
|
// PMU events
|
||||||
output logic lsu_pmu_bus_trxn,
|
output logic lsu_pmu_bus_trxn,
|
||||||
output logic lsu_pmu_bus_misaligned,
|
output logic lsu_pmu_bus_misaligned,
|
||||||
|
@ -149,7 +150,6 @@ import el2_pkg::*;
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// For Ld: IDLE -> WAIT -> CMD -> RESP -> DONE_PARTIAL(?) -> DONE_WAIT(?) -> DONE -> IDLE
|
// For Ld: IDLE -> WAIT -> CMD -> RESP -> DONE_PARTIAL(?) -> DONE_WAIT(?) -> DONE -> IDLE
|
||||||
// For St: IDLE -> WAIT -> CMD -> RESP(?) -> 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;
|
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 [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_addr_offset;
|
||||||
logic [1:0] lsu_nonblock_sz;
|
logic [1:0] lsu_nonblock_sz;
|
||||||
logic lsu_nonblock_unsign, lsu_nonblock_dual;
|
logic lsu_nonblock_unsign;
|
||||||
logic lsu_nonblock_load_data_ready;
|
logic lsu_nonblock_load_data_ready;
|
||||||
|
|
||||||
logic [DEPTH-1:0] CmdPtr0Dec, CmdPtr1Dec;
|
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 [3:0] buf_numvld_any, buf_numvld_wrcmd_any, buf_numvld_cmd_any, buf_numvld_pend_any;
|
||||||
logic any_done_wait_state;
|
logic any_done_wait_state;
|
||||||
logic bus_sideeffect_pend;
|
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 bus_coalescing_disable;
|
||||||
logic mdbhd_en;
|
|
||||||
|
|
||||||
logic bus_addr_match_pending;
|
logic bus_addr_match_pending;
|
||||||
logic bus_cmd_sent, bus_cmd_ready;
|
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][DEPTH_LOG2-1:0] buf_dualtag;
|
||||||
logic [DEPTH-1:0] buf_ldfwd;
|
logic [DEPTH-1:0] buf_ldfwd;
|
||||||
logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_ldfwdtag;
|
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] buf_error;
|
||||||
logic [DEPTH-1:0][31:0] buf_data;
|
logic [DEPTH-1:0][31:0] buf_data;
|
||||||
logic [DEPTH-1:0][DEPTH-1:0] buf_age, buf_age_younger;
|
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_dual_in;
|
||||||
logic [DEPTH-1:0] buf_samedw_in;
|
logic [DEPTH-1:0] buf_samedw_in;
|
||||||
logic [DEPTH-1:0] buf_nomerge_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_sideeffect_in;
|
||||||
logic [DEPTH-1:0] buf_unsign_in;
|
logic [DEPTH-1:0] buf_unsign_in;
|
||||||
logic [DEPTH-1:0][1:0] buf_sz_in;
|
logic [DEPTH-1:0][1:0] buf_sz_in;
|
||||||
|
@ -263,7 +258,6 @@ import el2_pkg::*;
|
||||||
logic ibuf_nomerge;
|
logic ibuf_nomerge;
|
||||||
logic [DEPTH_LOG2-1:0] ibuf_tag;
|
logic [DEPTH_LOG2-1:0] ibuf_tag;
|
||||||
logic [DEPTH_LOG2-1:0] ibuf_dualtag;
|
logic [DEPTH_LOG2-1:0] ibuf_dualtag;
|
||||||
//logic ibuf_nb;
|
|
||||||
logic ibuf_sideeffect;
|
logic ibuf_sideeffect;
|
||||||
logic ibuf_unsign;
|
logic ibuf_unsign;
|
||||||
logic ibuf_write;
|
logic ibuf_write;
|
||||||
|
@ -313,6 +307,7 @@ import el2_pkg::*;
|
||||||
logic obuf_rst;
|
logic obuf_rst;
|
||||||
logic obuf_write_in;
|
logic obuf_write_in;
|
||||||
logic obuf_nosend_in;
|
logic obuf_nosend_in;
|
||||||
|
logic obuf_rdrsp_pend_en;
|
||||||
logic obuf_rdrsp_pend_in;
|
logic obuf_rdrsp_pend_in;
|
||||||
logic obuf_sideeffect_in;
|
logic obuf_sideeffect_in;
|
||||||
logic obuf_aligned_in;
|
logic obuf_aligned_in;
|
||||||
|
@ -338,7 +333,7 @@ import el2_pkg::*;
|
||||||
logic lsu_axi_rvalid_q, lsu_axi_rready_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 [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 [1:0] lsu_axi_bresp_q, lsu_axi_rresp_q;
|
||||||
logic [DEPTH_LOG2-1:0] lsu_imprecise_error_store_tag;
|
logic [pt.LSU_BUS_TAG-1:0] lsu_imprecise_error_store_tag;
|
||||||
logic [63:0] lsu_axi_rdata_q;
|
logic [63:0] lsu_axi_rdata_q;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -360,7 +355,7 @@ import el2_pkg::*;
|
||||||
// Buffer hit logic for bus load forwarding
|
// Buffer hit logic for bus load forwarding
|
||||||
assign ldst_byteen_hi_m[3:0] = ldst_byteen_ext_m[7:4];
|
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];
|
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_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;
|
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
|
end
|
||||||
|
@ -368,7 +363,7 @@ import el2_pkg::*;
|
||||||
for (genvar j=0; j<4; j++) begin
|
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_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];
|
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_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];
|
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
|
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_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];
|
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[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[15:8] |= {8{ld_byte_hitvecfn_lo[1][i]}} & buf_data[i][15:8];
|
||||||
ld_fwddata_buf_lo[23:16] |= {8{ld_byte_hitvecfn_lo[2][i]}} & buf_data[i][23:16];
|
ld_fwddata_buf_lo[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_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_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_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_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_dualtag_in[DEPTH_LOG2-1:0] = WrPtr0_r;
|
||||||
assign ibuf_sz_in[1:0] = {lsu_pkt_r.word, lsu_pkt_r.half};
|
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)]) :
|
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)]);
|
(ldst_dual_r ? store_data_hi_r[(8*i)+7:(8*i)] : store_data_lo_r[(8*i)+7:(8*i)]);
|
||||||
end
|
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;
|
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_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_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_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_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_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), .*);
|
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
|
// 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;
|
~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 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 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)) |
|
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_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))) &
|
(~(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;
|
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[0] & ~obuf_addr_in[0]) |
|
||||||
(obuf_sz_in[1] & ~(|obuf_addr_in[1: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))) |
|
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;
|
||||||
((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];
|
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 &
|
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))));
|
((obuf_valid & ~obuf_nosend) | (obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag))));
|
||||||
|
|
||||||
|
@ -518,7 +512,7 @@ import el2_pkg::*;
|
||||||
(buf_addr[CmdPtr1][2] ? {buf_byteen[CmdPtr1],4'b0} : {4'b0,buf_byteen[CmdPtr1]});
|
(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]});
|
(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]});
|
(buf_addr[CmdPtr1][2] ? {buf_data[CmdPtr1],32'b0} : {32'b0,buf_data[CmdPtr1]});
|
||||||
|
|
||||||
for (genvar i=0 ;i<8; i++) begin
|
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
|
// 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) &
|
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_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);
|
(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), .*);
|
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), .*);
|
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_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), .*);
|
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 #(.WIDTH(1)) obuf_data_done_ff (.din(obuf_data_done_in), .dout(obuf_data_done), .clk(lsu_busm_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 #(.WIDTH(1)) obuf_rdrsp_pend_ff(.din(obuf_rdrsp_pend_in), .dout(obuf_rdrsp_pend), .clk(lsu_busm_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 #(.WIDTH(pt.LSU_BUS_TAG)) obuf_rdrsp_tagff (.din(obuf_rdrsp_tag_in), .dout(obuf_rdrsp_tag), .clk(lsu_busm_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 #(.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_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 #(.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_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 #(.WIDTH(1)) obuf_mergeff (.din(obuf_merge_in), .dout(obuf_merge), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_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 #(.WIDTH(1)) obuf_writeff (.din(obuf_write_in), .dout(obuf_write), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_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 #(.WIDTH(1)) obuf_sideeffectff (.din(obuf_sideeffect_in), .dout(obuf_sideeffect), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_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 #(.WIDTH(2)) obuf_szff (.din(obuf_sz_in[1:0]), .dout(obuf_sz), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_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(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), .*);
|
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(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;
|
found_wrptr1 = '0;
|
||||||
|
|
||||||
// Find first write pointer
|
// 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
|
if (~found_wrptr0) begin
|
||||||
WrPtr0_m[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i);
|
WrPtr0_m[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i);
|
||||||
found_wrptr0 = (buf_state[i] == IDLE) & ~((ibuf_valid & (32'(ibuf_tag) == i)) |
|
found_wrptr0 = (buf_state[i] == IDLE) & ~((ibuf_valid & (ibuf_tag == i)) |
|
||||||
(lsu_busreq_r & ((32'(WrPtr0_r) == i) | (ldst_dual_r & (32'(WrPtr1_r) == i)))));
|
(lsu_busreq_r & ((WrPtr0_r == i) | (ldst_dual_r & (WrPtr1_r == i)))));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// Find second write pointer
|
// 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
|
if (~found_wrptr1) begin
|
||||||
WrPtr1_m[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i);
|
WrPtr1_m[DEPTH_LOG2-1:0] = DEPTH_LOG2'(i);
|
||||||
found_wrptr1 = (buf_state[i] == IDLE) & ~((ibuf_valid & (32'(ibuf_tag) == i)) |
|
found_wrptr1 = (buf_state[i] == IDLE) & ~((ibuf_valid & (ibuf_tag == i)) |
|
||||||
(lsu_busreq_m & (32'(WrPtr0_m) == i)) |
|
(lsu_busreq_m & (WrPtr0_m == i)) |
|
||||||
(lsu_busreq_r & ((32'(WrPtr0_r) == i) | (ldst_dual_r & (32'(WrPtr1_r) == i)))));
|
(lsu_busreq_r & ((WrPtr0_r == i) | (ldst_dual_r & (WrPtr1_r == i)))));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// Get the command ptr
|
// 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
|
// These should be one-hot
|
||||||
assign CmdPtr0Dec[i] = ~(|buf_age[i]) & (buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i];
|
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];
|
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_cmdptr0 = |CmdPtr0Dec;
|
||||||
assign found_cmdptr1 = |CmdPtr1Dec;
|
assign found_cmdptr1 = |CmdPtr1Dec;
|
||||||
|
|
||||||
assign CmdPtr0 = f_Enc8to3(8'(CmdPtr0Dec[DEPTH-1:0]));
|
assign CmdPtr0 = f_Enc8to3(8'(CmdPtr0Dec[DEPTH-1:0]));
|
||||||
assign CmdPtr1 = f_Enc8to3(8'(CmdPtr1Dec[DEPTH-1:0]));
|
assign CmdPtr1 = f_Enc8to3(8'(CmdPtr1Dec[DEPTH-1:0]));
|
||||||
assign RspPtr = f_Enc8to3(8'(RspPtrDec[DEPTH-1:0]));
|
assign RspPtr = f_Enc8to3(8'(RspPtrDec[DEPTH-1:0]));
|
||||||
|
|
||||||
// Age vector
|
// Age vector
|
||||||
for (genvar i=0; i<32'(DEPTH); i++) begin: GenAgeVec
|
for (genvar i=0; i<DEPTH; i++) begin: GenAgeVec
|
||||||
for (genvar j=0; j<32'(DEPTH); j++) begin
|
for (genvar j=0; j<DEPTH; j++) begin
|
||||||
assign buf_age_in[i][j] = (((buf_state[i] == IDLE) & buf_state_en[i]) &
|
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
|
(((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
|
(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];
|
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
|
assign buf_age_younger[i][j] = (i == j) ? 1'b0: (~buf_age[i][j] & (buf_state[j] != IDLE)); // Younger entries
|
||||||
end
|
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_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)));
|
(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_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);
|
assign buf_rsp_pickage[i][j] = buf_rspageQ[i][j] & (buf_state[j] == DONE_WAIT);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -631,7 +623,7 @@ import el2_pkg::*;
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Buffer logic
|
// 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 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]);
|
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_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_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_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_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_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};
|
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
|
always_comb begin
|
||||||
buf_nxtstate[i] = IDLE;
|
buf_nxtstate[i] = IDLE;
|
||||||
buf_state_en[i] = '0;
|
buf_state_en[i] = '0;
|
||||||
buf_cmd_state_bus_en[i] = '0;
|
|
||||||
buf_resp_state_bus_en[i] = '0;
|
buf_resp_state_bus_en[i] = '0;
|
||||||
buf_state_bus_en[i] = '0;
|
buf_state_bus_en[i] = '0;
|
||||||
buf_wr_en[i] = '0;
|
buf_wr_en[i] = '0;
|
||||||
buf_data_in[i] = '0;
|
buf_data_in[i] = '0;
|
||||||
buf_data_en[i] = '0;
|
buf_data_en[i] = '0;
|
||||||
buf_error_en[i] = '0;
|
buf_error_en[i] = '0;
|
||||||
buf_rst[i] = '0;
|
buf_rst[i] = dec_tlu_force_halt;
|
||||||
buf_ldfwd_en[i] = '0;
|
buf_ldfwd_en[i] = dec_tlu_force_halt;
|
||||||
buf_ldfwd_in[i] = '0;
|
buf_ldfwd_in[i] = '0;
|
||||||
buf_ldfwdtag_in[i] = '0;
|
buf_ldfwdtag_in[i] = '0;
|
||||||
|
|
||||||
|
@ -671,10 +661,12 @@ import el2_pkg::*;
|
||||||
buf_wr_en[i] = buf_state_en[i];
|
buf_wr_en[i] = buf_state_en[i];
|
||||||
buf_data_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_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
|
end
|
||||||
WAIT: begin
|
WAIT: begin
|
||||||
buf_nxtstate[i] = dec_tlu_force_halt ? IDLE : CMD;
|
buf_nxtstate[i] = dec_tlu_force_halt ? IDLE : CMD;
|
||||||
buf_state_en[i] = lsu_bus_clk_en | dec_tlu_force_halt;
|
buf_state_en[i] = lsu_bus_clk_en | dec_tlu_force_halt;
|
||||||
|
buf_cmd_state_bus_en[i] = '0;
|
||||||
end
|
end
|
||||||
CMD: begin
|
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;
|
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]);
|
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
|
end
|
||||||
RESP: begin
|
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_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_ldfwd[i] | any_done_wait_state |
|
||||||
(buf_dual[i] & ~buf_samedw[i] & ~buf_write[i] & buf_ldfwd[buf_dualtag[i]] &
|
(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
|
// 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))) |
|
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_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_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
|
end
|
||||||
DONE_PARTIAL: begin // Other part of dual load hasn't returned
|
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_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_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_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_state_en[i] = (buf_state_bus_en[i] & lsu_bus_clk_en) | dec_tlu_force_halt;
|
||||||
|
buf_cmd_state_bus_en[i] = '0;
|
||||||
end
|
end
|
||||||
DONE_WAIT: begin // WAIT state if there are multiple outstanding nb returns
|
DONE_WAIT: begin // WAIT state if there are multiple outstanding nb returns
|
||||||
buf_nxtstate[i] = dec_tlu_force_halt ? IDLE : DONE;
|
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_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
|
end
|
||||||
DONE: begin
|
DONE: begin
|
||||||
buf_nxtstate[i] = IDLE;
|
buf_nxtstate[i] = IDLE;
|
||||||
|
@ -724,11 +718,11 @@ import el2_pkg::*;
|
||||||
buf_state_en[i] = 1'b1;
|
buf_state_en[i] = 1'b1;
|
||||||
buf_ldfwd_in[i] = 1'b0;
|
buf_ldfwd_in[i] = 1'b0;
|
||||||
buf_ldfwd_en[i] = buf_state_en[i];
|
buf_ldfwd_en[i] = buf_state_en[i];
|
||||||
|
buf_cmd_state_bus_en[i] = '0;
|
||||||
end
|
end
|
||||||
default : begin
|
default : begin
|
||||||
buf_nxtstate[i] = IDLE;
|
buf_nxtstate[i] = IDLE;
|
||||||
buf_state_en[i] = '0;
|
buf_state_en[i] = '0;
|
||||||
buf_cmd_state_bus_en[i] = '0;
|
|
||||||
buf_resp_state_bus_en[i] = '0;
|
buf_resp_state_bus_en[i] = '0;
|
||||||
buf_state_bus_en[i] = '0;
|
buf_state_bus_en[i] = '0;
|
||||||
buf_wr_en[i] = '0;
|
buf_wr_en[i] = '0;
|
||||||
|
@ -736,6 +730,7 @@ import el2_pkg::*;
|
||||||
buf_data_en[i] = '0;
|
buf_data_en[i] = '0;
|
||||||
buf_error_en[i] = '0;
|
buf_error_en[i] = '0;
|
||||||
buf_rst[i] = '0;
|
buf_rst[i] = '0;
|
||||||
|
buf_cmd_state_bus_en[i] = '0;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
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_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(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(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_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_unsignff (.din(buf_unsign_in[i]), .dout(buf_unsign[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
||||||
rvdffs #(.WIDTH(1)) buf_writeff (.din(buf_write_in[i]), .dout(buf_write[i]), .en(buf_wr_en[i]), .clk(lsu_bus_buf_c1_clk), .*);
|
rvdffs #(.WIDTH(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
|
// buffer full logic
|
||||||
always_comb begin
|
always_comb begin
|
||||||
buf_numvld_any[3:0] = 4'(({3'b0,lsu_busreq_m} << ldst_dual_m) +
|
buf_numvld_any[3:0] = ({1'b0,lsu_busreq_m} << ldst_dual_m) +
|
||||||
({3'b0,lsu_busreq_r} << ldst_dual_r) +
|
({1'b0,lsu_busreq_r} << ldst_dual_r) +
|
||||||
{3'b0,ibuf_valid});
|
ibuf_valid;
|
||||||
buf_numvld_wrcmd_any[3:0] = 4'b0;
|
buf_numvld_wrcmd_any[3:0] = 4'b0;
|
||||||
buf_numvld_cmd_any[3:0] = 4'b0;
|
buf_numvld_cmd_any[3:0] = 4'b0;
|
||||||
buf_numvld_pend_any[3:0] = 4'b0;
|
buf_numvld_pend_any[3:0] = 4'b0;
|
||||||
any_done_wait_state = 1'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_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_wrcmd_any[3:0] += {3'b0, (buf_write[i] & (buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i])};
|
||||||
buf_numvld_cmd_any[3:0] += {3'b0, ((buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i])};
|
buf_numvld_cmd_any[3:0] += {3'b0, ((buf_state[i] == CMD) & ~buf_cmd_state_bus_en[i])};
|
||||||
|
@ -781,7 +775,7 @@ import el2_pkg::*;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign lsu_bus_buffer_pend_any = (buf_numvld_pend_any != 0);
|
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;
|
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_tag[DEPTH_LOG2-1:0] = '0;
|
||||||
lsu_nonblock_load_data_lo[31:0] = '0;
|
lsu_nonblock_load_data_lo[31:0] = '0;
|
||||||
lsu_nonblock_load_data_hi[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
|
// 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_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_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]))}};
|
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_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_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_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_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;
|
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
|
// Determine if there is a pending return to sideeffect load/store
|
||||||
always_comb begin
|
always_comb begin
|
||||||
bus_sideeffect_pend = obuf_valid & obuf_sideeffect & dec_tlu_sideeffect_posted_disable;
|
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);
|
bus_sideeffect_pend |= ((buf_state[i] == RESP) & buf_sideeffect[i] & dec_tlu_sideeffect_posted_disable);
|
||||||
end
|
end
|
||||||
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
|
// We have no ordering rules for AXI. Need to check outstanding trxns to same address for AXI
|
||||||
always_comb begin
|
always_comb begin
|
||||||
bus_addr_match_pending = '0;
|
bus_addr_match_pending = '0;
|
||||||
for (int i=0; i<32'(DEPTH); i++) begin
|
for (int i=0; i<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)))));
|
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
|
||||||
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_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_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_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_awcache[3:0] = obuf_sideeffect ? 4'b0 : 4'b1111;
|
||||||
assign lsu_axi_awregion[3:0] = obuf_addr[31:28];
|
assign lsu_axi_awregion[3:0] = obuf_addr[31:28];
|
||||||
assign lsu_axi_awlen[7:0] = '0;
|
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_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_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_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_arcache[3:0] = obuf_sideeffect ? 4'b0 : 4'b1111;
|
||||||
assign lsu_axi_arregion[3:0] = obuf_addr[31:28];
|
assign lsu_axi_arregion[3:0] = obuf_addr[31:28];
|
||||||
assign lsu_axi_arlen[7:0] = '0;
|
assign lsu_axi_arlen[7:0] = '0;
|
||||||
|
@ -886,7 +879,7 @@ import el2_pkg::*;
|
||||||
always_comb begin
|
always_comb begin
|
||||||
lsu_imprecise_error_store_any = '0;
|
lsu_imprecise_error_store_any = '0;
|
||||||
lsu_imprecise_error_store_tag = '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_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])}};
|
lsu_imprecise_error_store_tag |= DEPTH_LOG2'(i) & {DEPTH_LOG2{((buf_state[i] == DONE) & buf_error[i] & buf_write[i])}};
|
||||||
end
|
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_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];
|
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
|
// 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_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_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_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);
|
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_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 #(.WIDTH(1)) lsu_axi_awready_ff (.din(lsu_axi_awready), .dout(lsu_axi_awready_q), .clk(lsu_busm_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 #(.WIDTH(1)) lsu_axi_wvalid_ff (.din(lsu_axi_wvalid), .dout(lsu_axi_wvalid_q), .clk(lsu_busm_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 #(.WIDTH(1)) lsu_axi_wready_ff (.din(lsu_axi_wready), .dout(lsu_axi_wready_q), .clk(lsu_busm_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 #(.WIDTH(1)) lsu_axi_arvalid_ff (.din(lsu_axi_arvalid), .dout(lsu_axi_arvalid_q), .clk(lsu_busm_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 #(.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_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_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 #(.WIDTH(1)) lsu_axi_bready_ff (.din(lsu_axi_bready), .dout(lsu_axi_bready_q), .clk(lsu_busm_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 #(.WIDTH(2)) lsu_axi_bresp_ff (.din(lsu_axi_bresp[1:0]), .dout(lsu_axi_bresp_q[1:0]), .clk(lsu_busm_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 #(.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), .*);
|
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 & lsu_bus_clk_en), .*);
|
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_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 #(.WIDTH(1)) lsu_axi_rready_ff (.din(lsu_axi_rready), .dout(lsu_axi_rready_q), .clk(lsu_busm_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 #(.WIDTH(2)) lsu_axi_rresp_ff (.din(lsu_axi_rresp[1:0]), .dout(lsu_axi_rresp_q[1:0]), .clk(lsu_busm_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 #(.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(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_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), .*);
|
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_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), .*);
|
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
|
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_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]));
|
assert_ld_byte_hitvecfn_hi_onehot: assert #0 ($onehot0(ld_byte_hitvecfn_hi[i][DEPTH-1:0]));
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_CmdPtr0Dec_onehot: assert #0 ($onehot0(CmdPtr0Dec[DEPTH-1:0]));
|
for (genvar i=0; i<DEPTH; i++) begin: GenAssertAge
|
||||||
assert_CmdPtr1Dec_onehot: assert #0 ($onehot0(CmdPtr1Dec[DEPTH-1:0]));
|
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
|
`endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)(
|
)(
|
||||||
input logic 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 rst_l,
|
input logic clk_override, // Override non-functional clock gating
|
||||||
input logic scan_mode,
|
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_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_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_sideeffect_posted_disable, // disable the posted sideeffect load store to the bus
|
||||||
|
|
||||||
// various clocks needed for the bus reads and writes
|
// various clocks needed for the bus reads and writes
|
||||||
input logic lsu_c1_m_clk,
|
input logic lsu_bus_obuf_c1_clken, // obuf clock enable
|
||||||
input logic lsu_c1_r_clk,
|
input logic lsu_busm_clken, // bus clock enable
|
||||||
input logic lsu_c2_r_clk,
|
|
||||||
input logic lsu_bus_ibuf_c1_clk,
|
input logic lsu_c1_r_clk, // r pipe single pulse clock
|
||||||
input logic lsu_bus_obuf_c1_clk,
|
input logic lsu_c2_r_clk, // r pipe double pulse clock
|
||||||
input logic lsu_bus_buf_c1_clk,
|
input logic lsu_bus_ibuf_c1_clk, // ibuf single pulse clock
|
||||||
input logic lsu_free_c2_clk,
|
input logic lsu_bus_obuf_c1_clk, // obuf single pulse clock
|
||||||
input logic free_clk,
|
input logic lsu_bus_buf_c1_clk, // buf single pulse clock
|
||||||
input logic lsu_busm_clk,
|
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 dec_lsu_valid_raw_d, // Raw valid for address computation
|
||||||
input logic lsu_busreq_m, // bus request is in m
|
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_m, // lsu packet flowing down the pipe
|
||||||
input el2_lsu_pkt_t lsu_pkt_r, // 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_m, // lsu address flowing down the pipe
|
||||||
input logic [31:0] lsu_addr_r, // 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_m, // lsu address flowing down the pipe
|
||||||
input logic [31:0] end_addr_r, // lsu address flowing down the pipe
|
input logic [31:0] end_addr_r, // lsu address flowing down the pipe
|
||||||
|
|
||||||
|
@ -66,12 +67,12 @@ import el2_pkg::*;
|
||||||
input logic is_sideeffects_m, // lsu attribute is side_effects
|
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 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_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_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_full_any, // write buffer is full
|
||||||
output logic lsu_bus_buffer_empty_any, // write buffer is empty
|
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
|
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 [pt.LSU_BUS_TAG-1:0] lsu_axi_rid,
|
||||||
input logic [63:0] lsu_axi_rdata,
|
input logic [63:0] lsu_axi_rdata,
|
||||||
input logic [1:0] lsu_axi_rresp,
|
input logic [1:0] lsu_axi_rresp,
|
||||||
input logic lsu_axi_rlast,
|
|
||||||
|
|
||||||
input logic lsu_bus_clk_en
|
input logic lsu_bus_clk_en
|
||||||
|
|
||||||
|
@ -148,7 +148,6 @@ import el2_pkg::*;
|
||||||
|
|
||||||
|
|
||||||
logic lsu_bus_clk_en_q;
|
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 [3:0] ldst_byteen_m, ldst_byteen_r;
|
||||||
logic [7:0] ldst_byteen_ext_m, ldst_byteen_ext_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) |
|
assign ldst_byteen_m[3:0] = ({4{lsu_pkt_m.by}} & 4'b0001) |
|
||||||
({4{lsu_pkt_m.half}} & 4'b0011) |
|
({4{lsu_pkt_m.half}} & 4'b0011) |
|
||||||
({4{lsu_pkt_m.word}} & 4'b1111);
|
({4{lsu_pkt_m.word}} & 4'b1111);
|
||||||
assign ldst_dual_d = (lsu_addr_d[2] != end_addr_d[2]);
|
|
||||||
|
|
||||||
// Read/Write Buffer
|
// Read/Write Buffer
|
||||||
el2_lsu_bus_buffer #(.pt(pt)) bus_buffer (
|
el2_lsu_bus_buffer #(.pt(pt)) bus_buffer (
|
||||||
|
@ -263,15 +261,13 @@ import el2_pkg::*;
|
||||||
|
|
||||||
// Fifo flops
|
// 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 #(.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));
|
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
|
// Assertion to check AXI write address is aligned to size
|
||||||
property lsu_axi_awaddr_aligned;
|
property lsu_axi_awaddr_aligned;
|
||||||
|
@ -296,7 +292,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
// Assertion to check awvalid stays stable during entire bus clock
|
// Assertion to check awvalid stays stable during entire bus clock
|
||||||
property lsu_axi_awvalid_stable;
|
property lsu_axi_awvalid_stable;
|
||||||
@(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid != $past(lsu_axi_awvalid)) |-> $past(lsu_bus_clk_en);
|
@(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid != $past(lsu_axi_awvalid)) |-> ($past(lsu_bus_clk_en) | dec_tlu_force_halt);
|
||||||
endproperty
|
endproperty
|
||||||
assert_lsu_axi_awvalid_stable: assert property (lsu_axi_awvalid_stable) else
|
assert_lsu_axi_awvalid_stable: assert property (lsu_axi_awvalid_stable) else
|
||||||
$display("LSU AXI awvalid changed in middle of bus clock");
|
$display("LSU AXI awvalid changed in middle of bus clock");
|
||||||
|
@ -338,7 +334,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
// Assertion to check awvalid stays stable during entire bus clock
|
// Assertion to check awvalid stays stable during entire bus clock
|
||||||
property lsu_axi_arvalid_stable;
|
property lsu_axi_arvalid_stable;
|
||||||
@(posedge clk) disable iff(~rst_l) (lsu_axi_arvalid != $past(lsu_axi_arvalid)) |-> $past(lsu_bus_clk_en);
|
@(posedge clk) disable iff(~rst_l) (lsu_axi_arvalid != $past(lsu_axi_arvalid)) |-> ($past(lsu_bus_clk_en) | dec_tlu_force_halt);
|
||||||
endproperty
|
endproperty
|
||||||
assert_lsu_axi_arvalid_stable: assert property (lsu_axi_arvalid_stable) else
|
assert_lsu_axi_arvalid_stable: assert property (lsu_axi_arvalid_stable) else
|
||||||
$display("LSU AXI awvalid changed in middle of bus clock");
|
$display("LSU AXI awvalid changed in middle of bus clock");
|
||||||
|
|
|
@ -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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)(
|
)(
|
||||||
input logic clk, // clock
|
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_clk, // clock
|
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
|
input logic rst_l, // reset, active low
|
||||||
|
input logic dec_tlu_force_halt, // This will be high till TLU goes to debug halt
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
input logic clk_override, // chciken bit to turn off clock gating
|
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 dma_dccm_req, // dma is active
|
||||||
input logic ldst_stbuf_reqvld_r, // allocating in to the store queue
|
input logic ldst_stbuf_reqvld_r, // allocating in to the store queue
|
||||||
|
|
||||||
|
@ -53,6 +53,9 @@ import el2_pkg::*;
|
||||||
input el2_lsu_pkt_t lsu_pkt_r, // lsu packet in r
|
input el2_lsu_pkt_t lsu_pkt_r, // lsu packet in r
|
||||||
|
|
||||||
// Outputs
|
// 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_m_clk, // m pipe single pulse clock
|
||||||
output logic lsu_c1_r_clk, // r 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_bus_buf_c1_clk, // ibuf clock
|
||||||
output logic lsu_busm_clk, // bus 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_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_store_c1_m_clken, lsu_store_c1_r_clken;
|
||||||
|
|
||||||
|
|
||||||
logic lsu_stbuf_c1_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;
|
logic lsu_free_c1_clken, lsu_free_c1_clken_q, lsu_free_c2_clken;
|
||||||
|
|
||||||
|
@ -88,8 +91,7 @@ import el2_pkg::*;
|
||||||
// Clock Enable logic
|
// Clock Enable logic
|
||||||
//-------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
assign lsu_c1_d_clken = lsu_p.valid | dma_dccm_req | clk_override;
|
assign lsu_c1_m_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_r_clken = lsu_pkt_m.valid | lsu_c1_m_clken_q | 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;
|
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_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_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_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) |
|
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;
|
~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;
|
assign lsu_free_c2_clken = lsu_free_c1_clken | lsu_free_c1_clken_q | clk_override;
|
||||||
|
|
||||||
// Flops
|
// 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_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), .*);
|
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_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), .* );
|
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), .* );
|
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), .*);
|
rvoclkhdr lsu_free_cgc (.en(lsu_free_c2_clken), .l1clk(lsu_free_c2_clk), .*);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -34,28 +34,32 @@ import el2_pkg::*;
|
||||||
(
|
(
|
||||||
input logic lsu_c2_m_clk, // clocks
|
input logic lsu_c2_m_clk, // clocks
|
||||||
input logic lsu_c2_r_clk, // clocks
|
input logic lsu_c2_r_clk, // clocks
|
||||||
input logic lsu_c1_r_clk,
|
input logic lsu_c1_r_clk, // clocks
|
||||||
input logic lsu_store_c1_r_clk,
|
input logic lsu_store_c1_r_clk, // clocks
|
||||||
input logic lsu_free_c2_clk,
|
input logic lsu_free_c2_clk, // clocks
|
||||||
input logic clk,
|
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_r,// lsu packets
|
||||||
input el2_lsu_pkt_t lsu_pkt_m,// 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_d,// lsu packets
|
||||||
input logic addr_in_dccm_d, // address maps to dccm
|
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_d, // address maps to pic
|
||||||
input logic addr_in_pic_m, // 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_dccm_m, addr_in_dccm_r, // address in dccm per pipe stage
|
||||||
input logic addr_in_pic_r,
|
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_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
|
// lsu address down the pipe
|
||||||
input logic [pt.DCCM_BITS-1:0] lsu_addr_m, // starting byte address for loads
|
input logic [31:0] lsu_addr_d,
|
||||||
input logic [31:0] lsu_addr_r, // starting byte address for loads
|
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_d,
|
||||||
input logic [pt.DCCM_BITS-1:0] end_addr_m,
|
input logic [pt.DCCM_BITS-1:0] end_addr_m,
|
||||||
input logic [pt.DCCM_BITS-1:0] end_addr_r,
|
input logic [pt.DCCM_BITS-1:0] end_addr_r,
|
||||||
|
@ -98,14 +102,14 @@ 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_hi_m, // corrected dccm data
|
||||||
input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_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 [31:0] store_data_m, // Store data M-stage
|
||||||
input logic dma_dccm_wen,
|
input logic dma_dccm_wen, // Perform DMA writes only for word/dword
|
||||||
input logic dma_pic_wen,
|
input logic dma_pic_wen, // Perform PIC writes
|
||||||
input logic [2:0] dma_mem_tag_m,
|
input logic [2:0] dma_mem_tag_m, // DMA Buffer entry number M-stage
|
||||||
input logic [31:0] dma_mem_addr, // DMA address
|
input logic [31:0] dma_mem_addr, // DMA request address
|
||||||
input logic [63:0] dma_mem_wdata, // DMA write data
|
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_lo, // Shift the dma data to lower bits to make it consistent to lsu stores
|
||||||
input logic [31:0] dma_dccm_wdata_hi,
|
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_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 [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_lo, // ECC bits for the DMA wdata
|
||||||
|
|
||||||
|
@ -183,11 +187,12 @@ import el2_pkg::*;
|
||||||
logic [63:0] picm_rd_data_r;
|
logic [63:0] picm_rd_data_r;
|
||||||
logic [63:32] lsu_ld_data_r_nc, lsu_ld_data_corr_r_nc;
|
logic [63:32] lsu_ld_data_r_nc, lsu_ld_data_corr_r_nc;
|
||||||
logic [2:0] dma_mem_tag_r;
|
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_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_ecc_error = lsu_double_ecc_error_r;
|
||||||
assign dccm_dma_rtag[2:0] = dma_mem_tag_r[2:0];
|
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_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];
|
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,21 +201,22 @@ import el2_pkg::*;
|
||||||
assign dccm_rdata_corr_r[63:0] = {sec_data_hi_r[31:0],sec_data_lo_r[31:0]};
|
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_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_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
|
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] :
|
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] :
|
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
|
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_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));
|
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]}),
|
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));
|
.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));
|
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));
|
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));
|
||||||
rvdff #(32) picm_rddata_rff (.*, .din(picm_rd_data_m[31:0]), .dout(picm_rd_data_r[31:0]), .clk(lsu_c2_r_clk));
|
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));
|
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
|
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_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_ecc_error = lsu_double_ecc_error_m;
|
||||||
assign dccm_dma_rtag[2:0] = dma_mem_tag_m[2:0];
|
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_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];
|
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
|
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] :
|
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] :
|
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
|
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
|
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) |
|
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) |
|
||||||
|
@ -330,7 +336,7 @@ import el2_pkg::*;
|
||||||
end
|
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
|
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_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 #(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));
|
rvdff #(32) store_data_rff (.*, .din(store_data_m[31:0]), .dout(store_data_r[31:0]), .clk(lsu_store_c1_r_clk));
|
||||||
|
@ -356,7 +362,7 @@ import el2_pkg::*;
|
||||||
end
|
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];
|
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));
|
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));
|
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
|
end
|
||||||
|
@ -383,10 +389,6 @@ import el2_pkg::*;
|
||||||
if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable
|
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_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));
|
rvdff #(1) dccm_rden_rff (.*, .din(lsu_dccm_rden_m), .dout(lsu_dccm_rden_r), .clk(lsu_c2_r_clk));
|
||||||
end else begin: Gen_dccm_disable
|
|
||||||
assign lsu_dccm_rden_m = '0;
|
|
||||||
assign lsu_dccm_rden_r = '0;
|
|
||||||
end
|
|
||||||
|
|
||||||
// ECC correction flops since dccm write happens next cycle
|
// 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.
|
// 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.
|
||||||
|
@ -394,12 +396,21 @@ import el2_pkg::*;
|
||||||
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_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_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));
|
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_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(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));
|
||||||
|
|
||||||
`ifdef LSU_ASSERT_ON
|
end else begin: Gen_dccm_disable
|
||||||
assert_ecc_kill_lo: assert #0 (~(ld_single_ecc_error_lo_r & kill_ecc_corr_lo_r));
|
assign lsu_dccm_rden_m = '0;
|
||||||
assert_ecc_kill_hi: assert #0 (~(ld_single_ecc_error_hi_r & kill_ecc_corr_hi_r));
|
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
|
||||||
|
|
||||||
|
`ifdef RV_ASSERT_ON
|
||||||
|
|
||||||
// Load single ECC error correction implies commit/dma
|
// Load single ECC error correction implies commit/dma
|
||||||
property ld_single_ecc_error_commit;
|
property ld_single_ecc_error_commit;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
module el2_lsu_dccm_mem
|
||||||
import el2_pkg::*;
|
import el2_pkg::*;
|
||||||
#(
|
#(
|
||||||
`include "el2_param.vh"
|
`include "el2_param.vh"
|
||||||
)(
|
)(
|
||||||
input logic clk, // clock
|
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 active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
|
||||||
input logic clk_override, // clock override
|
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_wren, // write enable
|
||||||
input logic dccm_rden, // read 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_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_lo, // write data
|
||||||
input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi, // 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_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
|
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_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];
|
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)
|
// 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 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 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) ?
|
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,6 +111,7 @@ import el2_pkg::*;
|
||||||
// end clock gating section
|
// end clock gating section
|
||||||
|
|
||||||
`ifdef VERILATOR
|
`ifdef VERILATOR
|
||||||
|
|
||||||
el2_ram #(DCCM_INDEX_DEPTH,39) ram (
|
el2_ram #(DCCM_INDEX_DEPTH,39) ram (
|
||||||
// Primary ports
|
// Primary ports
|
||||||
.ME(dccm_clken[i]),
|
.ME(dccm_clken[i]),
|
||||||
|
@ -106,10 +120,13 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
`else
|
||||||
|
|
||||||
if (DCCM_INDEX_DEPTH == 32768) begin : dccm
|
if (DCCM_INDEX_DEPTH == 32768) begin : dccm
|
||||||
ram_32768x39 dccm_bank (
|
ram_32768x39 dccm_bank (
|
||||||
// Primary ports
|
// Primary ports
|
||||||
|
@ -119,6 +136,9 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
end
|
||||||
|
@ -131,6 +151,9 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
end
|
||||||
|
@ -143,6 +166,9 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
end
|
||||||
|
@ -155,6 +181,9 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
end
|
||||||
|
@ -167,6 +196,9 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
end
|
||||||
|
@ -179,6 +211,9 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
end
|
||||||
|
@ -191,6 +226,9 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
end
|
||||||
|
@ -203,6 +241,9 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
end
|
||||||
|
@ -215,15 +256,34 @@ import el2_pkg::*;
|
||||||
.ADR(addr_bank[i]),
|
.ADR(addr_bank[i]),
|
||||||
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
.D(wr_data_bank[i][pt.DCCM_FDATA_WIDTH-1:0]),
|
||||||
.Q(dccm_bank_dout[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
|
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
|
end : mem_bank
|
||||||
|
|
||||||
// Flops
|
// 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));
|
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));
|
||||||
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_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
|
`undef EL2_LOCAL_DCCM_RAM_TEST_PORTS
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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"
|
`include "el2_param.vh"
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input logic 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 lsu_c2_r_clk, // clocks
|
input logic lsu_c2_r_clk, // clock
|
||||||
input logic rst_l,
|
input logic clk_override, // Override non-functional clock gating
|
||||||
input logic scan_mode, // scan
|
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_m, // packet in m
|
||||||
input el2_lsu_pkt_t lsu_pkt_r, // packet in r
|
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_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_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_hi_r, // data from the dccm + ecc
|
||||||
input logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_lo_r,
|
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,
|
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,
|
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,
|
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,
|
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, // ld has a single ecc error
|
||||||
input logic ld_single_ecc_error_r_ff, // 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_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_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
|
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_hi_m, // corrected dccm data M-stage
|
||||||
output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_m,
|
output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_m, // corrected dccm data M-stage
|
||||||
|
|
||||||
input logic dma_dccm_wen,
|
input logic dma_dccm_wen, // Perform DMA writes only for word/dword
|
||||||
input logic [31:0] dma_dccm_wdata_lo,
|
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,
|
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_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] 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] stbuf_ecc_any, // Encoded data with ECC bits
|
||||||
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_hi_r_ff, // Encoded data with ECC bits
|
||||||
output logic [pt.DCCM_ECC_WIDTH-1:0] sec_data_ecc_lo_r_ff,
|
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_hi_r, // sec detected
|
||||||
output logic single_ecc_error_lo_r, // sec detected on lower dccm bank
|
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
|
if (pt.LOAD_TO_USE_PLUS1 == 1) begin: L2U_Plus1_1
|
||||||
logic ldst_dual_m, ldst_dual_r;
|
logic ldst_dual_m, ldst_dual_r;
|
||||||
logic is_ldst_m;
|
logic is_ldst_m;
|
||||||
logic is_ldst_hi_m, is_ldst_lo_m;
|
|
||||||
logic is_ldst_hi_r, is_ldst_lo_r;
|
logic is_ldst_hi_r, is_ldst_lo_r;
|
||||||
|
|
||||||
assign ldst_dual_r = (lsu_addr_r[2] != end_addr_r[2]);
|
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_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_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 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];
|
assign dccm_rdata_hi_any[pt.DCCM_DATA_WIDTH-1:0] = dccm_rdata_hi_r[pt.DCCM_DATA_WIDTH-1:0];
|
||||||
|
@ -163,14 +163,14 @@ import el2_pkg::*;
|
||||||
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 #(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_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(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), .*);
|
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), .*);
|
||||||
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), .*);
|
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
|
end
|
||||||
|
|
||||||
// Logic for ECC generation during write
|
// 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_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_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];
|
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 double_ecc_error_hi_any = '0;
|
||||||
assign single_ecc_error_lo_any = '0;
|
assign single_ecc_error_lo_any = '0;
|
||||||
assign double_ecc_error_lo_any = '0;
|
assign double_ecc_error_lo_any = '0;
|
||||||
|
|
||||||
assign stbuf_ecc_any[pt.DCCM_ECC_WIDTH-1:0] = '0;
|
|
||||||
end
|
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_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(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
|
endmodule // el2_lsu_ecc
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -30,7 +30,9 @@ import el2_pkg::*;
|
||||||
#(
|
#(
|
||||||
`include "el2_param.vh"
|
`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
|
// clocks per pipe
|
||||||
input logic lsu_c1_m_clk,
|
input logic lsu_c1_m_clk,
|
||||||
|
@ -39,28 +41,31 @@ import el2_pkg::*;
|
||||||
input logic lsu_c2_r_clk,
|
input logic lsu_c2_r_clk,
|
||||||
input logic lsu_store_c1_m_clk,
|
input logic lsu_store_c1_m_clk,
|
||||||
|
|
||||||
input logic [31:0] lsu_ld_data_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
|
input logic [31:0] lsu_ld_data_corr_r, // ECC corrected data R-stage
|
||||||
input logic lsu_single_ecc_error_r,
|
input logic lsu_single_ecc_error_r, // ECC single bit error R-stage
|
||||||
input logic lsu_double_ecc_error_r,
|
input logic lsu_double_ecc_error_r, // ECC double bit error R-stage
|
||||||
|
|
||||||
input logic [31:0] lsu_ld_data_m,
|
input logic [31:0] lsu_ld_data_m, // Load data M-stage
|
||||||
input logic lsu_single_ecc_error_m,
|
input logic lsu_single_ecc_error_m, // ECC single bit error M-stage
|
||||||
input logic lsu_double_ecc_error_m,
|
input logic lsu_double_ecc_error_m, // ECC double bit error M-stage
|
||||||
|
|
||||||
input logic flush_m_up,
|
input logic flush_m_up, // Flush M and D stage
|
||||||
input logic flush_r,
|
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_rs1_d, // address
|
||||||
input logic [31:0] exu_lsu_rs2_d, // store data
|
input logic [31:0] exu_lsu_rs2_d, // store data
|
||||||
|
|
||||||
input el2_lsu_pkt_t lsu_p, // lsu control packet
|
input el2_lsu_pkt_t lsu_p, // lsu control packet
|
||||||
input logic dec_lsu_valid_raw_d, // Raw valid for address computation
|
input logic dec_lsu_valid_raw_d, // Raw valid for address computation
|
||||||
input logic [11:0] dec_lsu_offset_d,
|
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] picm_mask_data_m, // PIC data M-stage
|
||||||
input logic [31:0] bus_read_data_m,
|
input logic [31:0] bus_read_data_m, // the bus return data
|
||||||
output logic [31:0] lsu_result_m,
|
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
|
output logic [31:0] lsu_result_corr_r, // This is the ECC corrected data going to RF
|
||||||
// lsu address down the pipe
|
// lsu address down the pipe
|
||||||
output logic [31:0] lsu_addr_d,
|
output logic [31:0] lsu_addr_d,
|
||||||
|
@ -73,12 +78,12 @@ import el2_pkg::*;
|
||||||
// store data down the pipe
|
// store data down the pipe
|
||||||
output logic [31:0] store_data_m,
|
output logic [31:0] store_data_m,
|
||||||
|
|
||||||
input logic [31:0] dec_tlu_mrac_ff,
|
input logic [31:0] dec_tlu_mrac_ff, // CSR for memory region control
|
||||||
output logic lsu_exc_m,
|
output logic lsu_exc_m, // Access or misaligned fault
|
||||||
output logic is_sideeffects_m,
|
output logic is_sideeffects_m, // is sideffects space
|
||||||
output logic lsu_commit_r,
|
output logic lsu_commit_r, // lsu instruction in r commits
|
||||||
output logic lsu_single_ecc_error_incr,
|
output logic lsu_single_ecc_error_incr,// LSU inc SB error counter
|
||||||
output el2_lsu_error_pkt_t lsu_error_pkt_r,
|
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 [31:1] lsu_fir_addr, // fast interrupt address
|
||||||
output logic [1:0] lsu_fir_error, // Error during fast interrupt lookup
|
output logic [1:0] lsu_fir_error, // Error during fast interrupt lookup
|
||||||
|
@ -106,10 +111,11 @@ import el2_pkg::*;
|
||||||
output el2_lsu_pkt_t lsu_pkt_m,
|
output el2_lsu_pkt_t lsu_pkt_m,
|
||||||
output el2_lsu_pkt_t lsu_pkt_r,
|
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_addr_d;
|
||||||
logic [31:0] full_end_addr_d;
|
logic [31:0] full_end_addr_d;
|
||||||
logic [31:0] lsu_rs1_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];
|
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
|
// generate the ls address
|
||||||
// need to refine this is memory is only 128KB
|
|
||||||
rvlsadder lsadder (.rs1(rs1_d[31:0]),
|
rvlsadder lsadder (.rs1(rs1_d[31:0]),
|
||||||
.offset(offset_d[11:0]),
|
.offset(offset_d[11:0]),
|
||||||
.dout(full_addr_d[31:0])
|
.dout(full_addr_d[31:0])
|
||||||
|
@ -205,7 +210,9 @@ 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));
|
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 #(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));
|
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
|
end
|
||||||
|
|
||||||
|
@ -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_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];
|
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]}) |
|
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.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]}) |
|
({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) 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) 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));
|
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
|
||||||
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_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_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), .*);
|
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_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 #(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
|
endmodule
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -36,8 +36,6 @@ import el2_pkg::*;
|
||||||
input logic clk, // core clock
|
input logic clk, // core clock
|
||||||
input logic rst_l, // reset
|
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_stbuf_c1_clk, // stbuf clock
|
||||||
input logic lsu_free_c2_clk, // free clk
|
input logic lsu_free_c2_clk, // free clk
|
||||||
|
|
||||||
|
@ -61,28 +59,29 @@ import el2_pkg::*;
|
||||||
output logic lsu_stbuf_empty_any, // stbuf is empty
|
output logic lsu_stbuf_empty_any, // stbuf is empty
|
||||||
output logic ldst_stbuf_reqvld_r, // needed for clocking
|
output logic ldst_stbuf_reqvld_r, // needed for clocking
|
||||||
|
|
||||||
input logic [pt.LSU_SB_BITS-1:0] lsu_addr_d, // lsu address
|
input logic [pt.LSU_SB_BITS-1:0] lsu_addr_d, // lsu address D-stage
|
||||||
input logic [31:0] lsu_addr_m,
|
input logic [31:0] lsu_addr_m, // lsu address M-stage
|
||||||
input logic [31:0] lsu_addr_r,
|
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 [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,
|
input logic [31:0] end_addr_m, // lsu end address M-stage - needed to check unaligned
|
||||||
input logic [31:0] end_addr_r,
|
input logic [31:0] end_addr_r, // lsu end address R-stage - needed to check unaligned
|
||||||
|
|
||||||
|
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_m, // address is in dccm
|
||||||
input logic addr_in_dccm_r, // address is in dccm
|
input logic addr_in_dccm_r, // address is in dccm
|
||||||
|
|
||||||
// Forwarding signals
|
// Forwarding signals
|
||||||
input logic lsu_cmpen_m, // needed for forwarding stbuf - load
|
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_m, // LSU packet M-stage
|
||||||
input el2_lsu_pkt_t lsu_pkt_r,
|
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_hi_m, // stbuf data
|
||||||
output logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_fwddata_lo_m,
|
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,
|
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,
|
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] WrPtr, RdPtr;
|
||||||
logic [DEPTH_LOG2-1:0] NxtWrPtr, NxtRdPtr;
|
logic [DEPTH_LOG2-1:0] NxtWrPtr, NxtRdPtr;
|
||||||
logic [DEPTH_LOG2-1:0] WrPtrPlus1, WrPtrPlus2, RdPtrPlus1;
|
logic [DEPTH_LOG2-1:0] WrPtrPlus1, WrPtrPlus2, RdPtrPlus1;
|
||||||
logic ldst_dual_d, ldst_dual_m, ldst_dual_r;
|
|
||||||
|
|
||||||
logic dual_stbuf_write_r;
|
logic dual_stbuf_write_r;
|
||||||
|
|
||||||
logic isdccmst_m, isdccmst_r;
|
logic isdccmst_m, isdccmst_r;
|
||||||
logic [3:0] stbuf_numvld_any, stbuf_specvld_any;
|
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;
|
logic [pt.LSU_SB_BITS-1:$clog2(BYTE_WIDTH)] cmpaddr_hi_m, cmpaddr_lo_m;
|
||||||
|
|
||||||
// variables to detect matching from the store queue
|
// 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;
|
assign WrPtrPlus2[DEPTH_LOG2-1:0] = WrPtr[DEPTH_LOG2-1:0] + 2'b10;
|
||||||
|
|
||||||
// ecc error on both hi/lo
|
// 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 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
|
// 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_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];
|
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
|
end: FindMatchEntry
|
||||||
|
@ -179,13 +175,14 @@ import el2_pkg::*;
|
||||||
assign store_coalesce_hi_r = |store_matchvec_hi_r[DEPTH-1:0];
|
assign store_coalesce_hi_r = |store_matchvec_hi_r[DEPTH-1:0];
|
||||||
|
|
||||||
|
|
||||||
|
if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable
|
||||||
// Allocate new in this entry if :
|
// Allocate new in this entry if :
|
||||||
// 1. wrptr, single allocate, lo did not coalesce
|
// 1. wrptr, single allocate, lo did not coalesce
|
||||||
// 2. wrptr, double allocate, lo ^ hi coalesced
|
// 2. wrptr, double allocate, lo ^ hi coalesced
|
||||||
// 3. wrptr + 1, double alloacte, niether lo or 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
|
// Also update if there is a hi or a lo coalesce to this entry
|
||||||
// Store Buffer instantiation
|
// Store Buffer instantiation
|
||||||
for (genvar i=0; i<32'(DEPTH); i++) begin: GenStBuf
|
for (genvar i=0; i<DEPTH; i++) begin: GenStBuf
|
||||||
assign stbuf_wr_en[i] = ldst_stbuf_reqvld_r & (
|
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]) & ~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 == WrPtr[DEPTH_LOG2-1:0]) & dual_stbuf_write_r & ~store_coalesce_hi_r) | // Allocate : only 1 new Write Either
|
||||||
|
@ -213,9 +210,15 @@ import el2_pkg::*;
|
||||||
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), .*);
|
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]), .*);
|
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
|
||||||
|
end else begin: Gen_dccm_disable
|
||||||
rvdff #(.WIDTH(1)) ldst_dual_mff (.din(ldst_dual_d), .dout(ldst_dual_m), .clk(lsu_c1_m_clk), .*);
|
assign stbuf_wr_en[DEPTH-1:0] = '0;
|
||||||
rvdff #(.WIDTH(1)) ldst_dual_rff (.din(ldst_dual_m), .dout(ldst_dual_r), .clk(lsu_c1_r_clk), .*);
|
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
|
||||||
|
|
||||||
// Store Buffer drain logic
|
// Store Buffer drain logic
|
||||||
assign stbuf_reqvld_flushed_any = stbuf_vld[RdPtr] & stbuf_dma_kill[RdPtr];
|
assign stbuf_reqvld_flushed_any = stbuf_vld[RdPtr] & stbuf_dma_kill[RdPtr];
|
||||||
|
@ -233,7 +236,7 @@ import el2_pkg::*;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
stbuf_numvld_any[3:0] = '0;
|
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]};
|
stbuf_numvld_any[3:0] += {3'b0, stbuf_vld[i]};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -250,24 +253,22 @@ import el2_pkg::*;
|
||||||
assign lsu_stbuf_empty_any = (stbuf_numvld_any[3:0] == 4'b0);
|
assign lsu_stbuf_empty_any = (stbuf_numvld_any[3:0] == 4'b0);
|
||||||
|
|
||||||
// Load forwarding logic from the store queue
|
// 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 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)];
|
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
|
always_comb begin: GenLdFwd
|
||||||
stbuf_fwdbyteen_hi_pre_m[BYTE_WIDTH-1:0] = '0;
|
stbuf_fwdbyteen_hi_pre_m[BYTE_WIDTH-1:0] = '0;
|
||||||
stbuf_fwdbyteen_lo_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_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;
|
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
|
// 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;
|
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_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];
|
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_hi_pre_m[31:0] = '0;
|
||||||
stbuf_fwddata_lo_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_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];
|
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_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;
|
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_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_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];
|
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)) 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), .*);
|
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);
|
assert_stbuf_overflow: assert #0 (stbuf_specvld_any[2:0] <= DEPTH);
|
||||||
property stbuf_wren_store_dccm;
|
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
|
endproperty
|
||||||
assert_stbuf_wren_store_dccm: assert property (stbuf_wren_store_dccm) else
|
assert_stbuf_wren_store_dccm: assert property (stbuf_wren_store_dccm) else
|
||||||
$display("Illegal store buffer write");
|
$display("Illegal store buffer write");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -35,21 +35,31 @@ import el2_pkg::*;
|
||||||
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][31:0] lsu_match_data;
|
||||||
logic [3:0] lsu_trigger_data_match;
|
logic [3:0] lsu_trigger_data_match;
|
||||||
logic [31:0] store_data_trigger_m;
|
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
|
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]);
|
({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]));
|
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)) &
|
((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];
|
lsu_trigger_data_match[i];
|
||||||
end
|
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
|
## Release Notes
|
||||||
|
|
||||||
* Modified MSCAUSE encoding to be consistent with current internal specification
|
* Modified MSCAUSE encoding to be consistent with current internal specification
|
||||||
* Added internal timers
|
* Added internal timers
|
||||||
|
|
||||||
|
|
||||||
# EL2 SweRV RISC-V Core<sup>TM</sup> 1.1 from Western Digital
|
# EL2 SweRV RISC-V Core<sup>TM</sup> 1.1 from Western Digital
|
||||||
|
|
||||||
## Release Notes
|
## 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
|
output logic [63:0] HRDATA
|
||||||
);
|
);
|
||||||
|
|
||||||
parameter MEM_SIZE_DW = 8192;
|
|
||||||
parameter MAILBOX_ADDR = 32'hD0580000;
|
parameter MAILBOX_ADDR = 32'hD0580000;
|
||||||
localparam MEM_SIZE = MEM_SIZE_DW*8;
|
|
||||||
|
|
||||||
logic Write;
|
logic write;
|
||||||
logic [31:0] Last_HADDR;
|
logic [31:0] laddr, addr;
|
||||||
logic [7:0] strb_lat;
|
logic [7:0] strb_lat;
|
||||||
|
logic [63:0] rdata;
|
||||||
|
|
||||||
bit [7:0] mem [0:MEM_SIZE-1];
|
bit [7:0] mem [bit[31:0]];
|
||||||
//bit [7:0] mem [int];
|
bit [7:0] wscnt;
|
||||||
//int kuku[int];
|
int dws = 0;
|
||||||
|
int iws = 0;
|
||||||
|
bit dws_rand;
|
||||||
|
bit iws_rand;
|
||||||
|
bit ok;
|
||||||
|
|
||||||
// Wires
|
// Wires
|
||||||
wire [63:0] WriteData = HWDATA;
|
wire [63:0] WriteData = HWDATA;
|
||||||
|
@ -51,23 +54,23 @@ wire [7:0] strb = HSIZE == 3'b000 ? 8'h1 << HADDR[2:0] :
|
||||||
HSIZE == 3'b001 ? 8'h3 << {HADDR[2:1],1'b0} :
|
HSIZE == 3'b001 ? 8'h3 << {HADDR[2:1],1'b0} :
|
||||||
HSIZE == 3'b010 ? 8'hf << {HADDR[2],2'b0} : 8'hff;
|
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 mailbox_write = write && laddr==MAILBOX_ADDR;
|
||||||
|
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
if ($value$plusargs("iws=%d", iws));
|
||||||
|
if ($value$plusargs("dws=%d", dws));
|
||||||
|
dws_rand = dws < 0;
|
||||||
|
iws_rand = iws < 0;
|
||||||
|
end
|
||||||
|
|
||||||
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}]};
|
|
||||||
|
|
||||||
|
|
||||||
always @ (negedge HCLK ) begin
|
always @ (negedge HCLK ) begin
|
||||||
if (Write) 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[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[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[5]) mem[{laddr[31:3],3'd5}] = HWDATA[47:40];
|
||||||
|
@ -77,25 +80,54 @@ always @ (negedge HCLK ) begin
|
||||||
if(strb_lat[1]) mem[{laddr[31:3],3'd1}] = HWDATA[15:08];
|
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];
|
if(strb_lat[0]) mem[{laddr[31:3],3'd0}] = HWDATA[07:00];
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
assign HREADYOUT = 1;
|
assign HRDATA = HREADY ? rdata : ~rdata;
|
||||||
|
assign HREADYOUT = wscnt == 0;
|
||||||
assign HRESP = 0;
|
assign HRESP = 0;
|
||||||
|
|
||||||
always @(posedge HCLK or negedge HRESETn) begin
|
always @(posedge HCLK or negedge HRESETn) begin
|
||||||
if(~HRESETn) begin
|
if(~HRESETn) begin
|
||||||
Last_HADDR <= 32'b0;
|
laddr <= 32'b0;
|
||||||
Write <= 1'b0;
|
write <= 1'b0;
|
||||||
HRDATA <= '0;
|
rdata <= '0;
|
||||||
end else begin
|
wscnt <= 0;
|
||||||
Last_HADDR <= HADDR;
|
end
|
||||||
Write <= HWRITE & |HTRANS;
|
else begin
|
||||||
|
if(HREADY & HSEL) begin
|
||||||
|
laddr <= HADDR;
|
||||||
|
write <= HWRITE & |HTRANS;
|
||||||
if(|HTRANS & ~HWRITE)
|
if(|HTRANS & ~HWRITE)
|
||||||
HRDATA <= mem_dout;
|
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;
|
strb_lat <= strb;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if(HREADY & HSEL & |HTRANS)
|
||||||
|
wscnt <= HPROT[0] ? dws[7:0] : iws[7:0];
|
||||||
|
else if(wscnt != 0)
|
||||||
|
wscnt <= wscnt-1;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -142,14 +174,11 @@ output reg [TAGW-1:0] bid
|
||||||
parameter MAILBOX_ADDR = 32'hD0580000;
|
parameter MAILBOX_ADDR = 32'hD0580000;
|
||||||
parameter MEM_SIZE_DW = 8192;
|
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;
|
bit [63:0] memdata;
|
||||||
wire [31:0] waddr, raddr;
|
|
||||||
wire [63:0] WriteData;
|
wire [63:0] WriteData;
|
||||||
wire mailbox_write;
|
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 mailbox_write = awvalid && awaddr==MAILBOX_ADDR && rst_l;
|
||||||
assign WriteData = wdata;
|
assign WriteData = wdata;
|
||||||
|
@ -169,17 +198,17 @@ always @ ( posedge aclk or negedge rst_l) begin
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ ( negedge aclk) begin
|
always @ ( negedge aclk) begin
|
||||||
if(arvalid) memdata <= {mem[raddr+7], mem[raddr+6], mem[raddr+5], mem[raddr+4],
|
if(arvalid) memdata <= {mem[araddr+7], mem[araddr+6], mem[araddr+5], mem[araddr+4],
|
||||||
mem[raddr+3], mem[raddr+2], mem[raddr+1], mem[raddr]};
|
mem[araddr+3], mem[araddr+2], mem[araddr+1], mem[araddr]};
|
||||||
if(awvalid) begin
|
if(awvalid) begin
|
||||||
if(wstrb[7]) mem[waddr+7] = wdata[63:56];
|
if(wstrb[7]) mem[awaddr+7] = wdata[63:56];
|
||||||
if(wstrb[6]) mem[waddr+6] = wdata[55:48];
|
if(wstrb[6]) mem[awaddr+6] = wdata[55:48];
|
||||||
if(wstrb[5]) mem[waddr+5] = wdata[47:40];
|
if(wstrb[5]) mem[awaddr+5] = wdata[47:40];
|
||||||
if(wstrb[4]) mem[waddr+4] = wdata[39:32];
|
if(wstrb[4]) mem[awaddr+4] = wdata[39:32];
|
||||||
if(wstrb[3]) mem[waddr+3] = wdata[31:24];
|
if(wstrb[3]) mem[awaddr+3] = wdata[31:24];
|
||||||
if(wstrb[2]) mem[waddr+2] = wdata[23:16];
|
if(wstrb[2]) mem[awaddr+2] = wdata[23:16];
|
||||||
if(wstrb[1]) mem[waddr+1] = wdata[15:08];
|
if(wstrb[1]) mem[awaddr+1] = wdata[15:08];
|
||||||
if(wstrb[0]) mem[waddr+0] = wdata[07:00];
|
if(wstrb[0]) mem[awaddr+0] = wdata[07:00];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -193,3 +222,4 @@ assign rlast = 1'b1;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
|
|
@ -1,35 +1,6 @@
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
#define ITERATIONS 1
|
#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));
|
ee_printf("Total time (secs): %d\n",time_in_secs(total_time));
|
||||||
if (time_in_secs(total_time) > 0)
|
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("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);
|
100000*default_num_contexts*results[0].iterations/time_in_secs(total_time) % 100);
|
||||||
#endif
|
#endif
|
||||||
if (time_in_secs(total_time) < 10) {
|
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)
|
void* memset(void* s, int c, size_t n)
|
||||||
{
|
{
|
||||||
asm("mv t0, a0");
|
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" )
|
OUTPUT_ARCH( "riscv" )
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
MEMORY {
|
|
||||||
EXTCODE : ORIGIN = 0, LENGTH = 0x10000
|
|
||||||
EXTDATA : ORIGIN = 0x10000, LENGTH = 0x10000
|
|
||||||
ICCM : ORIGIN = 0xee000000, LENGTH = 0x80000
|
|
||||||
DCCM : ORIGIN = 0xf0040000, LENGTH = 0x10000
|
|
||||||
}
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.text_init : {*(.text_init)} > EXTCODE
|
.text : { crt0.o (.text*) }
|
||||||
init_end = .;
|
_end = .;
|
||||||
.data.ctl : AT(0x1ffec) { LONG(ADDR(.text)); LONG(text_end); LONG(LOADADDR(.text)); LONG(0xf0040000); LONG(STACK)}>EXTDATA
|
. = 0xee000000 ;
|
||||||
.text : AT(init_end) { *(.text) *(.text.startup)} > ICCM
|
.text.init : { cmark.o (.text*) }
|
||||||
text_end = .;
|
. = 0xd0580000;
|
||||||
.data : AT(0x10000) { *(.*data) *(.rodata*) STACK = ALIGN(16) + 0x8000;} > DCCM
|
.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" )
|
OUTPUT_ARCH( "riscv" )
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.text : { *(.text*) }
|
.text : { *(.text*) }
|
||||||
_end = .;
|
_end = .;
|
||||||
. = 0x1fff8;
|
. = 0xd0580000;
|
||||||
.data.ctl : { LONG(0xf0040000); LONG(STACK) }
|
.data.io . : { *(.data.io) }
|
||||||
. = 0xf0040000;
|
. = 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
|
+libext+.v+.sv
|
||||||
//-y $SYNOPSYS_SYN_ROOT/dw/sim_ver
|
//-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_swerv_wrapper.sv
|
||||||
$RV_ROOT/design/el2_mem.sv
|
$RV_ROOT/design/el2_mem.sv
|
||||||
$RV_ROOT/design/el2_pic_ctrl.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
|
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
|
run
|
||||||
exit
|
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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
`ifdef VERILATOR
|
`ifndef VERILATOR
|
||||||
module tb_top ( input bit core_clk );
|
|
||||||
`else
|
|
||||||
module tb_top;
|
module tb_top;
|
||||||
|
`else
|
||||||
|
module tb_top ( input bit core_clk );
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`ifndef VERILATOR
|
||||||
bit core_clk;
|
bit core_clk;
|
||||||
`endif
|
`endif
|
||||||
logic rst_l;
|
logic rst_l;
|
||||||
|
@ -65,10 +68,10 @@ module tb_top;
|
||||||
|
|
||||||
logic [31:0] trace_rv_i_insn_ip;
|
logic [31:0] trace_rv_i_insn_ip;
|
||||||
logic [31:0] trace_rv_i_address_ip;
|
logic [31:0] trace_rv_i_address_ip;
|
||||||
logic [1:0] trace_rv_i_valid_ip;
|
logic trace_rv_i_valid_ip;
|
||||||
logic [1:0] trace_rv_i_exception_ip;
|
logic trace_rv_i_exception_ip;
|
||||||
logic [4:0] trace_rv_i_ecause_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 [31:0] trace_rv_i_tval_ip;
|
||||||
|
|
||||||
logic o_debug_mode_status;
|
logic o_debug_mode_status;
|
||||||
|
@ -92,15 +95,15 @@ module tb_top;
|
||||||
logic mpc_debug_run_ack;
|
logic mpc_debug_run_ack;
|
||||||
logic debug_brkpt_status;
|
logic debug_brkpt_status;
|
||||||
|
|
||||||
bit [31:0] cycleCnt;
|
int cycleCnt;
|
||||||
logic mailbox_data_val;
|
logic mailbox_data_val;
|
||||||
|
|
||||||
wire dma_hready_out;
|
wire dma_hready_out;
|
||||||
int commit_count;
|
int commit_count;
|
||||||
|
|
||||||
logic wb_valid[1:0];
|
logic wb_valid;
|
||||||
logic [4:0] wb_dest[1:0];
|
logic [4:0] wb_dest;
|
||||||
logic [31:0] wb_data[1:0];
|
logic [31:0] wb_data;
|
||||||
|
|
||||||
`ifdef RV_BUILD_AXI4
|
`ifdef RV_BUILD_AXI4
|
||||||
//-------------------------- LSU AXI signals--------------------------
|
//-------------------------- LSU AXI signals--------------------------
|
||||||
|
@ -307,6 +310,7 @@ module tb_top;
|
||||||
|
|
||||||
`endif
|
`endif
|
||||||
wire[63:0] WriteData;
|
wire[63:0] WriteData;
|
||||||
|
string abi_reg[32]; // ABI register names
|
||||||
|
|
||||||
|
|
||||||
assign mailbox_write = lmem.mailbox_write;
|
assign mailbox_write = lmem.mailbox_write;
|
||||||
|
@ -345,40 +349,75 @@ module tb_top;
|
||||||
|
|
||||||
// trace monitor
|
// trace monitor
|
||||||
always @(posedge core_clk) begin
|
always @(posedge core_clk) begin
|
||||||
wb_valid[0] <= rvtop.swerv.dec.dec_i0_wen_r;
|
wb_valid <= rvtop.swerv.dec.dec_i0_wen_r;
|
||||||
wb_dest[0] <= rvtop.swerv.dec.dec_i0_waddr_r;
|
wb_dest <= rvtop.swerv.dec.dec_i0_waddr_r;
|
||||||
wb_data[0] <= rvtop.swerv.dec.dec_i0_wdata_r;
|
wb_data <= rvtop.swerv.dec.dec_i0_wdata_r;
|
||||||
if (trace_rv_i_valid_ip !== 0) begin
|
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,
|
$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,
|
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);
|
trace_rv_i_tval_ip,trace_rv_i_interrupt_ip);
|
||||||
// Basic trace - no exception register updates
|
// Basic trace - no exception register updates
|
||||||
// #1 0 ee000000 b0201073 c 0b02 00000000
|
// #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++;
|
commit_count++;
|
||||||
$fwrite (el, "%10d : %6s 0 %h %h %s\n", cycleCnt, $sformatf("#%0d",commit_count),
|
$fwrite (el, "%10d : %8s 0 %h %h%13s ; %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],
|
trace_rv_i_address_ip, trace_rv_i_insn_ip,
|
||||||
(wb_dest[i] !=0 && wb_data[0])? $sformatf("r%0d=%h", wb_dest[i], wb_data[i]) : "");
|
(wb_dest !=0 && wb_valid)? $sformatf("%s=%h", abi_reg[wb_dest], wb_data) : " ",
|
||||||
end
|
dasm(trace_rv_i_insn_ip, trace_rv_i_address_ip, wb_dest & {5{wb_valid}}, wb_data)
|
||||||
|
);
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
initial begin
|
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
|
// tie offs
|
||||||
jtag_id[31:28] = 4'b1;
|
jtag_id[31:28] = 4'b1;
|
||||||
jtag_id[27:12] = '0;
|
jtag_id[27:12] = '0;
|
||||||
jtag_id[11:1] = 11'h45;
|
jtag_id[11:1] = 11'h45;
|
||||||
reset_vector = 32'h0;
|
reset_vector = `RV_RESET_VEC;
|
||||||
nmi_vector = 32'hee000000;
|
nmi_vector = 32'hee000000;
|
||||||
nmi_int = 0;
|
nmi_int = 0;
|
||||||
|
|
||||||
$readmemh("data.hex", lmem.mem);
|
$readmemh("program.hex", lmem.mem);
|
||||||
$readmemh("program.hex", imem.mem);
|
$readmemh("program.hex", imem.mem);
|
||||||
tp = $fopen("trace_port.csv","w");
|
tp = $fopen("trace_port.csv","w");
|
||||||
el = $fopen("exec.log","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");
|
fd = $fopen("console.log","w");
|
||||||
commit_count = 0;
|
commit_count = 0;
|
||||||
preload_dccm();
|
preload_dccm();
|
||||||
|
@ -691,6 +730,12 @@ el2_swerv_wrapper rvtop (
|
||||||
.dec_tlu_perfcnt2 (),
|
.dec_tlu_perfcnt2 (),
|
||||||
.dec_tlu_perfcnt3 (),
|
.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),
|
.soft_int ('0),
|
||||||
.core_id ('0),
|
.core_id ('0),
|
||||||
.scan_mode ( 1'b0 ), // To enable scan mode
|
.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;
|
task preload_iccm;
|
||||||
bit[31:0] data;
|
bit[31:0] data;
|
||||||
bit[31:0] addr, eaddr, saddr, faddr;
|
bit[31:0] addr, eaddr, saddr;
|
||||||
int adr;
|
|
||||||
/*
|
/*
|
||||||
addresses:
|
addresses:
|
||||||
0xffec - ICCM start address to load
|
0xfffffff0 - ICCM start address to load
|
||||||
0xfff0 - ICCM end address to load
|
0xfffffff4 - ICCM end address to load
|
||||||
0xfff4 - imem start address
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
addr = 'hffec;
|
addr = 'hffff_fff0;
|
||||||
saddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
|
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;
|
if ( (saddr < `RV_ICCM_SADR) || (saddr > `RV_ICCM_EADR)) return;
|
||||||
`ifndef RV_ICCM_ENABLE
|
`ifndef RV_ICCM_ENABLE
|
||||||
|
@ -918,54 +962,50 @@ if ( (saddr < `RV_ICCM_SADR) || (saddr > `RV_ICCM_EADR)) return;
|
||||||
$display("********************************************************");
|
$display("********************************************************");
|
||||||
$finish;
|
$finish;
|
||||||
`endif
|
`endif
|
||||||
init_iccm;
|
addr += 4;
|
||||||
addr = 'hfff0;
|
|
||||||
eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
|
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);
|
$display("ICCM pre-load from %h to %h", saddr, eaddr);
|
||||||
|
|
||||||
for(addr= saddr; addr <= eaddr; addr+=4) begin
|
for(addr= saddr; addr <= eaddr; addr+=4) begin
|
||||||
adr = faddr & 'hffff;
|
data = {imem.mem[addr+3],imem.mem[addr+2],imem.mem[addr+1],imem.mem[addr]};
|
||||||
data = {imem.mem[adr+3],imem.mem[adr+2],imem.mem[adr+1],imem.mem[adr]};
|
|
||||||
slam_iccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data});
|
slam_iccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data});
|
||||||
faddr+=4;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
|
||||||
task preload_dccm;
|
task preload_dccm;
|
||||||
bit[31:0] data;
|
bit[31:0] data;
|
||||||
bit[31:0] addr, eaddr;
|
bit[31:0] addr, saddr, eaddr;
|
||||||
int adr;
|
|
||||||
/*
|
/*
|
||||||
addresses:
|
addresses:
|
||||||
0xfff8 - DCCM start address to load
|
0xffff_fff8 - DCCM start address to load
|
||||||
0xfffc - ICCM end address to load
|
0xffff_fffc - DCCM end address to load
|
||||||
0x0 - lmem start addres to load from
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
addr = 'hfff8;
|
addr = 'hffff_fff8;
|
||||||
eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
|
saddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
|
||||||
if (eaddr != `RV_DCCM_SADR) return;
|
if (saddr < `RV_DCCM_SADR || saddr > `RV_DCCM_EADR) return;
|
||||||
`ifndef RV_DCCM_ENABLE
|
`ifndef RV_DCCM_ENABLE
|
||||||
$display("********************************************************");
|
$display("********************************************************");
|
||||||
$display("DCCM preload: there is no DCCM in SweRV, terminating !!!");
|
$display("DCCM preload: there is no DCCM in SweRV, terminating !!!");
|
||||||
$display("********************************************************");
|
$display("********************************************************");
|
||||||
$finish;
|
$finish;
|
||||||
`endif
|
`endif
|
||||||
addr = 'hfffc;
|
addr += 4;
|
||||||
eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
|
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
|
for(addr=saddr; addr <= eaddr; addr+=4) begin
|
||||||
adr = addr & 'hffff;
|
data = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]};
|
||||||
data = {lmem.mem[adr+3],lmem.mem[adr+2],lmem.mem[adr+1],lmem.mem[adr]};
|
|
||||||
slam_dccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data});
|
slam_dccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data});
|
||||||
end
|
end
|
||||||
|
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
`define ICCM_PATH `RV_TOP.mem.iccm.iccm
|
`define ICCM_PATH `RV_TOP.mem.iccm.iccm
|
||||||
`ifdef VERILATOR
|
`ifdef VERILATOR
|
||||||
`define DRAM(bk) rvtop.mem.Gen_dccm_enable.dccm.mem_bank[bk].ram.ram_core
|
`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
|
`endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
/* verilator lint_off CASEINCOMPLETE */
|
||||||
|
`include "dasm.svi"
|
||||||
|
/* verilator lint_on CASEINCOMPLETE */
|
||||||
|
|
||||||
endmodule
|
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
|
|
@ -14,6 +14,11 @@
|
||||||
# limitations under the License.
|
# 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
|
# Check for RV_ROOT
|
||||||
ifeq (,$(wildcard ${RV_ROOT}/configs/swerv.config))
|
ifeq (,$(wildcard ${RV_ROOT}/configs/swerv.config))
|
||||||
$(error env var RV_ROOT does not point to a valid dir! Exiting!)
|
$(error env var RV_ROOT does not point to a valid dir! Exiting!)
|
||||||
|
@ -29,6 +34,7 @@ IRUN = xrun
|
||||||
VCS = vcs
|
VCS = vcs
|
||||||
VLOG = qverilog
|
VLOG = qverilog
|
||||||
VERILATOR = verilator
|
VERILATOR = verilator
|
||||||
|
RIVEIRA = riviera
|
||||||
GCC_PREFIX = riscv64-unknown-elf
|
GCC_PREFIX = riscv64-unknown-elf
|
||||||
BUILD_DIR = snapshots/${snapshot}
|
BUILD_DIR = snapshots/${snapshot}
|
||||||
TBDIR = ${RV_ROOT}/testbench
|
TBDIR = ${RV_ROOT}/testbench
|
||||||
|
@ -37,24 +43,44 @@ TBDIR = ${RV_ROOT}/testbench
|
||||||
TEST = hello_world
|
TEST = hello_world
|
||||||
|
|
||||||
# Define test name
|
# Define test name
|
||||||
|
ifneq (,$(wildcard $(TBDIR)/asm/$(TEST).s))
|
||||||
TEST_DIR = ${TBDIR}/asm
|
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
|
HEX_DIR = ${TBDIR}/hex
|
||||||
|
|
||||||
|
OFILES = $(TEST).o
|
||||||
|
|
||||||
ifdef debug
|
ifdef debug
|
||||||
DEBUG_PLUS = +dumpon
|
DEBUG_PLUS = +dumpon
|
||||||
IRUN_DEBUG = -access +rc
|
IRUN_DEBUG = -access +rc
|
||||||
IRUN_DEBUG_RUN = -input ${RV_ROOT}/testbench/input.tcl
|
IRUN_DEBUG_RUN = -input ${RV_ROOT}/testbench/input.tcl
|
||||||
|
VCS_DEBUG = -debug_access
|
||||||
VERILATOR_DEBUG = --trace
|
VERILATOR_DEBUG = --trace
|
||||||
|
RIVIERA_DEBUG = +access +r
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# provide specific link file
|
# provide specific link file
|
||||||
ifeq (,$(wildcard $(TEST_DIR)/$(TEST).ld))
|
ifeq (,$(wildcard $(TEST_DIR)/$(TEST).ld))
|
||||||
LINK = $(TBDIR)/link.ld
|
LINK = $(BUILD_DIR)/link.ld
|
||||||
else
|
else
|
||||||
LINK = $(TEST_DIR)/$(TEST).ld
|
LINK = $(TEST_DIR)/$(TEST).ld
|
||||||
endif
|
endif
|
||||||
|
|
||||||
VPATH = $(TEST_DIR) $(BUILD_DIR) $(TBDIR)
|
VPATH = $(TEST_DIR) $(BUILD_DIR) $(TBDIR)
|
||||||
|
|
||||||
|
-include $(TEST_DIR)/$(TEST).mki
|
||||||
|
|
||||||
|
|
||||||
TBFILES = $(TBDIR)/tb_top.sv $(TBDIR)/ahb_sif.sv
|
TBFILES = $(TBDIR)/tb_top.sv $(TBDIR)/ahb_sif.sv
|
||||||
|
|
||||||
defines = $(BUILD_DIR)/common_defines.vh
|
defines = $(BUILD_DIR)/common_defines.vh
|
||||||
|
@ -69,27 +95,32 @@ CFLAGS += "-std=c++11"
|
||||||
# Optimization for better performance; alternative is nothing for
|
# Optimization for better performance; alternative is nothing for
|
||||||
# slower runtime (faster compiles) -O2 for faster runtime (slower
|
# slower runtime (faster compiles) -O2 for faster runtime (slower
|
||||||
# compiles), or -O for balance.
|
# compiles), or -O for balance.
|
||||||
VERILATOR_MAKE_FLAGS = OPT_FAST="-O2"
|
VERILATOR_MAKE_FLAGS = OPT_FAST="-Os"
|
||||||
|
|
||||||
# Targets
|
# Targets
|
||||||
all: clean verilator
|
all: clean verilator
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf *.log *.s *.hex *.dis *.tbl irun* vcs* simv* snapshots swerv* \
|
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.
|
# 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)
|
BUILD_PATH=${BUILD_DIR} ${RV_ROOT}/configs/swerv.config -target=$(target) $(CONF_PARAMS)
|
||||||
|
|
||||||
verilator-build: ${TBFILES} ${BUILD_DIR}/defines.h test_tb_top.cpp
|
verilator-build: ${TBFILES} ${BUILD_DIR}/defines.h test_tb_top.cpp
|
||||||
echo '`undef ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh
|
echo '`undef RV_ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh
|
||||||
$(VERILATOR) '-UASSERT_ON' --cc -CFLAGS ${CFLAGS} $(defines) \
|
$(VERILATOR) --cc -CFLAGS ${CFLAGS} $(defines) \
|
||||||
$(includes) -I${RV_ROOT}/testbench -f ${RV_ROOT}/testbench/flist \
|
$(includes) -I${RV_ROOT}/testbench -f ${RV_ROOT}/testbench/flist \
|
||||||
-Wno-WIDTH -Wno-UNOPTFLAT ${TBFILES} --top-module tb_top \
|
-Wno-WIDTH -Wno-UNOPTFLAT ${TBFILES} --top-module tb_top \
|
||||||
-exe test_tb_top.cpp --autoflush $(VERILATOR_DEBUG)
|
-exe test_tb_top.cpp --autoflush $(VERILATOR_DEBUG)
|
||||||
cp ${RV_ROOT}/testbench/test_tb_top.cpp obj_dir/
|
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
|
touch verilator-build
|
||||||
|
|
||||||
vcs-build: ${TBFILES} ${BUILD_DIR}/defines.h
|
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 \
|
-incdir ${RV_ROOT}/design/lib -incdir ${RV_ROOT}/design/include \
|
||||||
-vlog_ext +.vh+.h $(defines) -incdir $(BUILD_DIR) \
|
-vlog_ext +.vh+.h $(defines) -incdir $(BUILD_DIR) \
|
||||||
-f ${RV_ROOT}/testbench/flist -top tb_top ${TBFILES} \
|
-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
|
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
|
verilator: program.hex verilator-build
|
||||||
./obj_dir/Vtb_top
|
./obj_dir/Vtb_top
|
||||||
|
|
||||||
irun: program.hex irun-build
|
irun: program.hex irun-build
|
||||||
$(IRUN) -64bit -abvglobalfailurelimit 1 +lic_queue -licqueue \
|
$(IRUN) -64bit -abvglobalfailurelimit 1 +lic_queue -licqueue \
|
||||||
-status -xmlibdirpath . -xmlibdirname swerv.build \
|
-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
|
vcs: program.hex vcs-build
|
||||||
./simv $(DEBUG_PLUS) +vcs+lic+wait -l vcs.log
|
./simv $(DEBUG_PLUS) +vcs+lic+wait -l vcs.log
|
||||||
|
|
||||||
vlog: program.hex ${TBFILES} ${BUILD_DIR}/defines.h
|
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\
|
$(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),)
|
ifeq ($(shell which $(GCC_PREFIX)-gcc 2> /dev/null),)
|
||||||
program.hex: ${BUILD_DIR}/defines.h
|
program.hex: ${BUILD_DIR}/defines.h
|
||||||
@echo " !!! No $(GCC_PREFIX)-gcc in path, using canned hex files !!"
|
@echo " !!! No $(GCC_PREFIX)-gcc in path, using canned hex files !!"
|
||||||
cp ${HEX_DIR}/$(TEST).program.hex program.hex
|
cp ${HEX_DIR}/$(TEST).hex program.hex
|
||||||
cp ${HEX_DIR}/$(TEST).data.hex data.hex
|
|
||||||
else
|
else
|
||||||
ifneq (,$(wildcard $(TEST_DIR)/$(TEST).makefile))
|
ifneq (,$(wildcard $(TEST_DIR)/$(TEST).makefile))
|
||||||
program.hex:
|
program.hex:
|
||||||
|
@echo Building $(TEST) via $(TEST_DIR)/$(TEST).makefile
|
||||||
$(MAKE) -f $(TEST_DIR)/$(TEST).makefile
|
$(MAKE) -f $(TEST_DIR)/$(TEST).makefile
|
||||||
else
|
else
|
||||||
program.hex: $(TEST).o $(LINK)
|
program.hex: $(OFILES) $(LINK)
|
||||||
@echo Building $(TEST)
|
@echo Building $(TEST)
|
||||||
$(GCC_PREFIX)-ld -m elf32lriscv --discard-none -T$(LINK) -o $(TEST).exe $(TEST).o
|
$(GCC_PREFIX)-gcc -Wl,-m,elf32lriscv -Wl,--discard-none -T$(LINK) -o $(TEST).exe $(OFILES) -nostartfiles -nostdlib $(TEST_LIBS)
|
||||||
$(GCC_PREFIX)-objcopy -O verilog --only-section ".data*" --change-section-lma .data*-0x10000 $(TEST).exe data.hex
|
$(GCC_PREFIX)-objcopy -O verilog $(TEST).exe program.hex
|
||||||
$(GCC_PREFIX)-objcopy -O verilog --only-section ".text*" $(TEST).exe program.hex
|
|
||||||
$(GCC_PREFIX)-objdump -S $(TEST).exe > $(TEST).dis
|
$(GCC_PREFIX)-objdump -S $(TEST).exe > $(TEST).dis
|
||||||
$(GCC_PREFIX)-nm -f posix -C $(TEST).exe > $(TEST).tbl
|
|
||||||
@echo Completed building $(TEST)
|
@echo Completed building $(TEST)
|
||||||
|
|
||||||
|
|
||||||
%.o : %.s ${BUILD_DIR}/defines.h
|
%.o : %.s ${BUILD_DIR}/defines.h
|
||||||
$(GCC_PREFIX)-cpp -I${BUILD_DIR} $< > $(TEST).cpp.s
|
$(GCC_PREFIX)-cpp -I${BUILD_DIR} $< > $*.cpp.s
|
||||||
$(GCC_PREFIX)-as -march=rv32gc $(TEST).cpp.s -o $(TEST).o
|
$(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
|
%.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
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo Make sure the environment variable RV_ROOT is set.
|
@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
|
#!/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;
|
use Getopt::Long;
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,4 @@
|
||||||
#!/usr/bin/perl
|
#!/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;
|
use Getopt::Long;
|
||||||
|
|
||||||
|
|
15
tools/picmap
15
tools/picmap
|
@ -1,19 +1,4 @@
|
||||||
#!/usr/bin/perl
|
#!/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;
|
use Getopt::Long;
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,4 @@
|
||||||
#!/usr/bin/perl
|
#!/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;
|
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_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" end\n");
|
print (" end\n");
|
||||||
print (" el2_cmp_and_mux #(\n");
|
print (" cmp_and_mux #(\n");
|
||||||
print (" .ID_BITS(ID_BITS),\n");
|
print (" .ID_BITS(ID_BITS),\n");
|
||||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||||
print (" .a_id(level_intpend_id[0][2*m]),\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_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" end\n");
|
print (" end\n");
|
||||||
print (" el2_cmp_and_mux #(\n");
|
print (" cmp_and_mux #(\n");
|
||||||
print (" .ID_BITS(ID_BITS),\n");
|
print (" .ID_BITS(ID_BITS),\n");
|
||||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||||
print (" .a_id(level_intpend_id_".$l."[2*m]),\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_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" assign levelx_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
print (" assign levelx_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" end\n");
|
print (" end\n");
|
||||||
print (" el2_cmp_and_mux #(\n");
|
print (" cmp_and_mux #(\n");
|
||||||
print (" .ID_BITS(ID_BITS),\n");
|
print (" .ID_BITS(ID_BITS),\n");
|
||||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||||
print (" .a_id(levelx_intpend_id[$tmp][2*m]),\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_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" assign levelx_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
print (" assign levelx_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" end\n");
|
print (" end\n");
|
||||||
print (" el2_cmp_and_mux #(\n");
|
print (" cmp_and_mux #(\n");
|
||||||
print (" .ID_BITS(ID_BITS),\n");
|
print (" .ID_BITS(ID_BITS),\n");
|
||||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||||
print (" .a_id(levelx_intpend_id_".$l."[2*m]),\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_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" end\n");
|
print (" end\n");
|
||||||
print (" el2_cmp_and_mux #(\n");
|
print (" cmp_and_mux #(\n");
|
||||||
print (" .ID_BITS(ID_BITS),\n");
|
print (" .ID_BITS(ID_BITS),\n");
|
||||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||||
print (" .a_id(level_intpend_id[0][2*m]),\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_w_prior_en_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
print (" assign level_intpend_id_".$next_level."[m+1] = '0 ;\n");
|
||||||
print (" end\n");
|
print (" end\n");
|
||||||
print (" el2_cmp_and_mux #(\n");
|
print (" cmp_and_mux #(\n");
|
||||||
print (" .ID_BITS(ID_BITS),\n");
|
print (" .ID_BITS(ID_BITS),\n");
|
||||||
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
print (" .INTPRIORITY_BITS(INTPRIORITY_BITS)) cmp_l".$next_level." (\n");
|
||||||
print (" .a_id(level_intpend_id_".$l."[2*m]),\n");
|
print (" .a_id(level_intpend_id_".$l."[2*m]),\n");
|
||||||
|
|
Loading…
Reference in New Issue