From 2d26189faf6fa76e70202202694b0f164d75d9f4 Mon Sep 17 00:00:00 2001 From: Joseph Rahmeh Date: Tue, 17 Nov 2020 10:25:18 -0800 Subject: [PATCH] Branch 1.3 --- README.md | 62 +- configs/swerv.config | 727 ++++--- design/dbg/el2_dbg.sv | 356 +++- design/dec/csrdecode | 1 + design/dec/decode | 267 ++- design/dec/el2_dec.sv | 234 ++- design/dec/el2_dec_decode_ctl.sv | 648 ++++-- design/dec/el2_dec_gpr_ctl.sv | 12 +- design/dec/el2_dec_ib_ctl.sv | 74 +- design/dec/el2_dec_tlu_ctl.sv | 1131 ++++++----- design/dec/el2_dec_trigger.sv | 6 +- design/dmi/rvjtag_tap.v | 1 + design/el2_dma_ctrl.sv | 104 +- design/el2_mem.sv | 9 +- design/el2_pic_ctrl.sv | 95 +- design/el2_swerv.sv | 269 ++- design/el2_swerv_wrapper.sv | 561 ++--- design/exu/el2_exu.sv | 158 +- design/exu/el2_exu_alu_ctl.sv | 384 +++- design/exu/el2_exu_div_ctl.sv | 1646 ++++++++++++++- design/exu/el2_exu_mul_ctl.sv | 562 ++++- design/flist.formal | 63 + design/flist.questa | 61 + design/ifu/el2_ifu.sv | 91 +- design/ifu/el2_ifu_aln_ctl.sv | 357 ++-- design/ifu/el2_ifu_bp_ctl.sv | 360 ++-- design/ifu/el2_ifu_compress_ctl.sv | 48 +- design/ifu/el2_ifu_ic_mem.sv | 1722 +++++++--------- design/ifu/el2_ifu_iccm_mem.sv | 221 +- design/ifu/el2_ifu_ifc_ctl.sv | 32 +- design/ifu/el2_ifu_mem_ctl.sv | 462 +++-- design/ifu/el2_ifu_tb_memread.sv | 5 +- design/include/el2_def.sv | 120 +- design/lib/ahb_to_axi4.sv | 63 +- design/lib/axi4_to_ahb.sv | 108 +- design/lib/beh_lib.sv | 326 ++- design/lib/mem_lib.sv | 58 +- design/lsu/el2_lsu.sv | 45 +- design/lsu/el2_lsu_addrcheck.sv | 18 +- design/lsu/el2_lsu_bus_buffer.sv | 236 ++- design/lsu/el2_lsu_bus_intf.sv | 206 +- design/lsu/el2_lsu_clkdomain.sv | 50 +- design/lsu/el2_lsu_dccm_ctl.sv | 187 +- design/lsu/el2_lsu_dccm_mem.sv | 82 +- design/lsu/el2_lsu_ecc.sv | 61 +- design/lsu/el2_lsu_lsc_ctl.sv | 95 +- design/lsu/el2_lsu_stbuf.sv | 157 +- design/lsu/el2_lsu_trigger.sv | 24 +- docs/RISC-V_SweRV_EL2_PRM.pdf | Bin 2141611 -> 2480338 bytes release-notes.md | 31 +- testbench/SimJTAG.cc | 26 + testbench/SimJTAG.v | 89 + testbench/ahb_sif.sv | 142 +- testbench/asm/cmark.c | 238 +-- testbench/asm/cmark.ld | 1 + testbench/asm/cmark.mki | 2 + testbench/asm/cmark_dccm.mki | 1 + testbench/asm/cmark_iccm.ld | 27 +- testbench/asm/cmark_iccm.mki | 2 + testbench/asm/crt0.s | 48 + testbench/asm/hello_world.ld | 12 + testbench/asm/hello_world_dccm.ld | 10 +- testbench/asm/printf.c | 310 +++ testbench/dasm.svi | 374 ++++ testbench/flist | 2 + testbench/hex/cmark.hex | 2251 ++++++++++++++++++++ testbench/hex/cmark_dccm.hex | 2251 ++++++++++++++++++++ testbench/hex/cmark_iccm.hex | 2254 +++++++++++++++++++++ testbench/hex/hello_world.hex | 26 + testbench/hex/hello_world_dccm.hex | 28 + testbench/hex/hello_world_iccm.hex | 32 + testbench/input.tcl | 2 +- testbench/remote_bitbang.cc | 209 ++ testbench/remote_bitbang.h | 61 + testbench/tb_top.sv | 215 +- testbench/tests/Coremark/Makefile | 14 + testbench/tests/Coremark/cmark.c | 2167 ++++++++++++++++++++ testbench/tests/Coremark/printf.c | 262 +++ testbench/tests/dhry/README | 7 + testbench/tests/dhry/crt0.s | 1 + testbench/tests/dhry/dhry.h | 437 ++++ testbench/tests/dhry/dhry.mki | 2 + testbench/tests/dhry/dhry_1.c | 462 +++++ testbench/tests/dhry/dhry_2.c | 212 ++ testbench/tests/dhry/printf.c | 1 + testbench/tests/hello_world/Makefile | 11 + testbench/tests/hello_world/hello_world.s | 42 + tools/Makefile | 100 +- tools/addassign | 15 - tools/coredecode | 15 - tools/picmap | 15 - tools/smalldiv | 15 - tools/unrollforverilator | 12 +- 93 files changed, 20395 insertions(+), 4604 deletions(-) create mode 100644 design/flist.formal create mode 100644 design/flist.questa create mode 100644 testbench/SimJTAG.cc create mode 100644 testbench/SimJTAG.v create mode 120000 testbench/asm/cmark.ld create mode 100644 testbench/asm/cmark.mki create mode 120000 testbench/asm/cmark_dccm.mki create mode 100644 testbench/asm/cmark_iccm.mki create mode 100644 testbench/asm/crt0.s create mode 100644 testbench/asm/hello_world.ld create mode 100644 testbench/asm/printf.c create mode 100644 testbench/dasm.svi create mode 100755 testbench/hex/cmark.hex create mode 100755 testbench/hex/cmark_dccm.hex create mode 100755 testbench/hex/cmark_iccm.hex create mode 100755 testbench/hex/hello_world.hex create mode 100755 testbench/hex/hello_world_dccm.hex create mode 100755 testbench/hex/hello_world_iccm.hex create mode 100644 testbench/remote_bitbang.cc create mode 100644 testbench/remote_bitbang.h create mode 100644 testbench/tests/Coremark/Makefile create mode 100644 testbench/tests/Coremark/cmark.c create mode 100644 testbench/tests/Coremark/printf.c create mode 100644 testbench/tests/dhry/README create mode 120000 testbench/tests/dhry/crt0.s create mode 100644 testbench/tests/dhry/dhry.h create mode 100644 testbench/tests/dhry/dhry.mki create mode 100644 testbench/tests/dhry/dhry_1.c create mode 100644 testbench/tests/dhry/dhry_2.c create mode 120000 testbench/tests/dhry/printf.c create mode 100644 testbench/tests/hello_world/Makefile create mode 100644 testbench/tests/hello_world/hello_world.s diff --git a/README.md b/README.md index bd894b2..c381e76 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# EL2 SweRV RISC-V CoreTM 1.2 from Western Digital +# EL2 SweRV RISC-V CoreTM 1.3 from Western Digital This repository contains the SweRV EL2 CoreTM design RTL @@ -24,13 +24,14 @@ Files under the [tools](tools/) directory may be available under a different lic ├── tools # Scripts/Makefiles └── testbench # (Very) simple testbench    ├── asm # Example assembly files -    └── hex # Canned demo hex files +    ├── hex # Canned demo hex files +    └── tests # Example tests ## Dependencies -- Verilator **(4.020 or later)** must be installed on the system if running with verilator +- Verilator **(4.102 or later)** must be installed on the system if running with verilator - If adding/removing instructions, espresso must be installed (used by *tools/coredecode*) -- RISCV tool chain (based on gcc version 7.3 or higher) must be +- RISCV tool chain (based on gcc version 8.3 or higher) must be installed so that it can be used to prepare RISCV binaries to run. ## Quickstart guide @@ -57,7 +58,15 @@ This will update the **default** snapshot in $RV_ROOT/configs/snapshots/default/ Add `-snapshot=dccm64`, for example, if you wish to name your build snapshot *dccm64* and refer to it during the build. There are 4 predefined target configurations: `default`, `default_ahb`, `typical_pd` and `high_perf` that can be selected via -the `-target=name` option to swerv.config. +the `-target=name` option to swerv.config. **Note:** that the `typical_pd` target is what we base our published PPA numbers. It does not include an ICCM. + +**Building an FPGA speed optimized model:** +Use ``-fpga_optimize=1`` option to ``swerv.config`` to build a model that removes clock gating logic from flop model so that the FPGA builds can run at higher speeds. **This is now the default option for +targets other than ``typical_pd``.** + +**Building a Power optimized model (ASIC flows):** +Use ``-fpga_optimize=0`` option to ``swerv.config`` to build a model that **enables** clock gating logic into the flop model so that the ASIC flows get a better power footprint. **This is now the default option for +target``typical_pd``.** This script derives the following consistent set of include files : @@ -70,6 +79,7 @@ This script derives the following consistent set of include files : ├── perl_configs.pl # Perl %configs hash for scripting ├── pic_map_auto.h # PIC memory map based on configure size └── whisper.json # JSON file for swerv-iss + └── link.ld # default linker control file @@ -107,7 +117,7 @@ execute a short sequence of instructions that writes out "HELLO WORLD" to the bus. -The simulation produces output on the screen like: +The simulation produces output on the screen like: u ``` VerilatorTB: Start of sim @@ -130,8 +140,6 @@ The simulation generates following files: gtkwave or similar waveform viewers. You can re-execute simulation using: - ` ./obj_dir/Vtb_top ` -or `make -f $RV_ROOT/tools/Makefile verilator` @@ -143,20 +151,20 @@ The simulation run/build command has following generic form: where: ``` - 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. - predefined CPU configurations 'default' ( by default), 'default_ahb', 'typical_pd', 'high_perf' TEST - allows to run a C (.c) or assembly (.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 - run and build executable model of custom CPU configuration, remember to provide 'snapshot' argument for runs on custom configurations. - +CONF_PARAMS - allows to provide -set options to swerv.conf script to alter predefined EL2 targets parameters ``` Example: make -f $RV_ROOT/tools/Makefile verilator TEST=cmark -will simulate testbench/asm/cmark.c program with verilator +will build and simulate testbench/asm/cmark.c program with verilator If you want to compile a test only, you can run: @@ -164,35 +172,43 @@ If you want to compile a test only, you can run: make -f $RV_ROOT/tools/Makefile program.hex TEST= [TEST_DIR=/path/to/dir] -The Makefile uses `$RV_ROOT/testbench/link.ld` file by default to build test executable. +The Makefile uses `snapshot//link.ld` file, generated by swerv.conf script by default to build test executable. User can provide test specific linker file in form `.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 `.makefile`, containing building instructions -how to create `program.hex` and `data.hex` files used by simulation. The private makefile should be in the same directory -as the test source. -*(`program.hex` file is loaded to instruction bus memory slave and `data.hex` file is loaded to LSU bus memory slave and -optionally to DCCM at the beginning of simulation)*. +how to create `program.hex` file used by simulation. The private makefile should be in the same directory +as the test source. See examples in `testbench/asm` directory. + +Another way to alter test building process is to use `.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 Note: You may need to delete `program.hex` file from work directory, when run a new test. The `$RV_ROOT/testbench/asm` directory contains following tests ready to simulate: ``` -hello_world - default tes to run, prints Hello World message to screen and console.log +hello_world - default test program to run, prints Hello World message to screen and console.log hello_world_dccm - the same as above, but takes the string from preloaded DCCM. hello_world_iccm - the same as hello_world, but loads the test code to ICCM via LSU to DMA bridge and then executes - it from there. Runs on EL2 with AXI4 buses only. + it from there. Runs on EL2 with AXI4 buses only. cmark - coremark benchmark running with code and data in external memories cmark_dccm - the same as above, running data and stack from DCCM (faster) -cmark_iccm - the same as above with preloaded code to ICCM. +cmark_iccm - the same as above with preloaded code to ICCM (slower, optimized for size to fit into default ICCM). + +dhry - Run dhrystone. (Scale by 1757 to get DMIPS/MHZ) ``` The `$RV_ROOT/testbench/hex` directory contains precompiled hex files of the tests, ready for simulation in case RISCV SW tools are not installed. **Note**: The testbench has a simple synthesizable bridge that allows you to load the ICCM via load/store instructions. This is only supported for AXI4 builds. -**Building an FPGA speed optimized model:** -Use ``-set=fpga_optimize=1`` option to ``swerv.config`` to build a model that is removes clock gating logic from flop model so that the FPGA builds can run a higher speeds. ---- diff --git a/configs/swerv.config b/configs/swerv.config index 518fd58..d717517 100755 --- a/configs/swerv.config +++ b/configs/swerv.config @@ -1,24 +1,9 @@ #! /usr/bin/env 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 strict; # Do not turn this off or else use Data::Dumper; use Getopt::Long; -##use Bit::Vector; +use Bit::Vector; use lib "$ENV{RV_ROOT}/tools"; use JSON; @@ -51,19 +36,19 @@ my $defines_case = "U"; my @verilog_vars = qw (xlen config_key reset_vec tec_rv_icg numiregs nmi_vec target protection.* testbench.* dccm.* retstack core.* iccm.* btb.* bht.* icache.* pic.* regwidth memmap bus.*); # Include these macros in assembly (pattern matched) -my @asm_vars = qw (xlen reset_vec nmi_vec target dccm.* iccm.* pic.* memmap bus.* testbench.* protection.* core.*); +my @asm_vars = qw (xlen reset_vec nmi_vec target dccm.* iccm.* pic.* memmap testbench.* protection.* core.*); my @asm_overridable = qw (reset_vec nmi_vec) ; # Include these macros in PD (pattern matched) -my @pd_vars = qw (physical retstack target btb.* bht.* dccm.* iccm.* icache.* pic.* reset_vec nmi_vec build_ahb_lite datawidth bus.*); +my @pd_vars = qw (physical retstack target btb.* bht.* dccm.* iccm.* icache.* pic.* bus.* reset_vec nmi_vec build_ahb_lite datawidth ); # Dump non-derived/settable vars/values for these vars in stdout : -my @dvars = qw(retstack btb bht core dccm iccm icache pic bus protection memmap); +my @dvars = qw(retstack btb bht core dccm iccm icache pic protection memmap bus); # Prefix all macros with my $prefix = "RV_"; # No prefix if keyword has -my $no_prefix = 'RV|TOP|^tec_|regwidth|clock_period|assert_on|^datawidth|^physical|verilator|SDVT_AHB'; +my $no_prefix = 'RV|TOP|tec_rv_icg|regwidth|clock_period|^datawidth|verilator|SDVT_AHB'; my $vlog_use__wh = 1; @@ -96,7 +81,7 @@ This script can be run stand-alone by processes not running vsim User options: - -target = {default, typical_pd, high_perf, default_ahb, lsu2dma_axi} + -target = {default, default_ahb, high_perf, typical_pd} use default settings for one of the targets -set=var=value @@ -110,10 +95,18 @@ Parameters that can be set by the end user: -set=ret_stack_size = {2, 3, 4, ... 8} size of return stack - -set=btb_size = { 32, 64, 128, 256, 512 } + -set=btb_enable = {0,1} + BTB enabled + -set=btb_fullya = {0,1} + BTB Fully set-associative + -set=btb_size = { 8, 16, 32, 64, 128, 256, 512 } size of branch target buffer -set=bht_size = {32, 64, 128, 256, 512, 1024, 2048} size of branch history buffer + -set=div_bit = {1,2,3,4} + number of bits to process each cycle + -set=div_new = {0,1} + new div algorithm -set=dccm_enable = {0,1} DCCM enabled -set=dccm_num_banks = {2, 4} @@ -141,8 +134,18 @@ Parameters that can be set by the end user: default: icache_ecc==0 (parity) -set=icache_size = { 8, 16, 32, 64, 128, 256 } kB size of icache + -set=icache_2banks = {0,1} + Enable 2 banks for icache -set=icache_num_ways { 2,4} Number of ways in icache + -set=icache_bypass_enable = {0,1} + Enable Icache data bypass buffer + -set=icache_num_bypass = {1..8} + Number of entries in bypass buffer + -set=icache_num_tag_bypass = {1..8} + Number of entries in bypass buffer + -set=icache_tag_bypass_enable = {0,1} + Enable icache tag bypass buffer -set=iccm_region = { 0x0, 0x1, ... 0xf } number of 256Mb memory region containing ICCM -set=iccm_offset = hexadecimal @@ -172,8 +175,33 @@ Parameters that can be set by the end user: size of PIC -set=pic_total_int = { 1, 2, 3, ..., 255 } number of interrupt sources in PIC - -set=fpga_optimize = {1} - optimize for FPGA build by disabling clock gating in lib cells + -set=dma_buf_depth = {2,4,5} + DMA buffer depth + -set=timer_legal_en = {0,1} + Internal timers legal/enabled + -set=bitmanip_zba = {0,1} + Bit manipulation extension ZBa enabled/legal + -set=bitmanip_zbb = {0,1} + Bit manipulation extension ZBb enabled/legal + -set=bitmanip_zbc = {0,1} + Bit manipulation extension ZBc enabled/legal + -set=bitmanip_zbe = {0,1} + Bit manipulation extension ZBe enabled/legal + -set=bitmanip_zbf = {0,1} + Bit manipulation extension ZBf enabled/legal + -set=bitmanip_zbp = {0,1} + Bit manipulation extension ZBp enabled/legal + -set=bitmanip_zbr = {0,1} + Bit manipulation extension ZBr enabled/legal + -set=bitmanip_zbs = {0,1} + Bit manipulation extension ZBs enabled/legal + -fpga_optimize = { 0, 1 } + if 1, minimize clock-gating to facilitate FPGA builds + -text_in_iccm = {0, 1} + Don't add ICCM preload code in generated link.ld + + +Additionally the following may be set for bus masters and slaves using the -set=var=value option: {inst|data}_access_enable[0-7] : default 0 {inst|data}_access_addr[0-7] : default 0x00000000 @@ -184,6 +212,8 @@ Parameters that can be set by the end user: my $ret_stack_size; my $btb_size; my $bht_size; +my $btb_fullya; +my $btb_toffset_size; my $dccm_region; my $dccm_offset; my $dccm_size; @@ -207,13 +237,12 @@ my $pic_total_int; my $top_align_iccm = 0; -my $lsu2dma = 0; - my $target = "default"; my $snapshot ; my $build_path ; my $verbose; my $load_to_use_plus1; +my $btb_enable; my $dccm_enable; my $icache_2banks; my $lsu_stbuf_depth; @@ -222,9 +251,26 @@ my $lsu_num_nbload; my $dccm_num_banks; my $iccm_num_banks; my $verilator; +my $icache_bypass_enable=1; +my $icache_num_bypass=2; +my $icache_num_bypass_width; +my $icache_tag_bypass_enable=1; +my $icache_tag_num_bypass=2; +my $icache_tag_num_bypass_width; my $fast_interrupt_redirect = 1; # ON by default +my $lsu_num_nbload=4; +my $ahb = 0; +my $axi = 1; +my $text_in_iccm = 0; + +my $lsu2dma = 0; + + $ret_stack_size=8; +$btb_enable=1; +$btb_fullya=0; +$btb_toffset_size=12; $btb_size=512; $bht_size=512; $dccm_enable=1; @@ -239,7 +285,7 @@ $iccm_offset="0xe000000"; #0x380*256*1024 $iccm_size=64; $iccm_num_banks=4; $icache_enable=1; -$icache_waypack=0; +$icache_waypack=1; $icache_num_ways=2; $icache_banks_way=2; $icache_2banks=1; @@ -255,7 +301,21 @@ $pic_total_int=31; $load_to_use_plus1=0; $lsu_stbuf_depth=4; $dma_buf_depth=5; -$lsu_num_nbload=4; + +my $div_bit=4; # number of bits to process each cycle for div +my $div_new=1; # old or new div algorithm + +my $fpga_optimize = 1; + +# Default bitmanip options +my $bitmanip_zba = 0; +my $bitmanip_zbb = 1; +my $bitmanip_zbc = 0; +my $bitmanip_zbe = 0; +my $bitmanip_zbf = 0; +my $bitmanip_zbp = 0; +my $bitmanip_zbr = 0; +my $bitmanip_zbs = 1; GetOptions( "help" => \$help, @@ -264,6 +324,8 @@ GetOptions( "verbose" => \$verbose, "load_to_use_plus1" => \$load_to_use_plus1, "ret_stack_size=s" => \$ret_stack_size, + "btb_fullya" => \$btb_fullya, + "btb_enable=s" => \$btb_enable, "btb_size=s" => \$btb_size, "bht_size=s" => \$bht_size, "dccm_enable=s" => \$dccm_enable, @@ -291,6 +353,8 @@ GetOptions( "icache_size=s" => \$icache_size, "set=s@" => \@sets, "unset=s@" => \@unsets, + "fpga_optimize=s" => \$fpga_optimize, + "text_in_iccm" => \$text_in_iccm, ) || die("$helpusage"); if ($help) { @@ -303,7 +367,7 @@ if (!defined $snapshot ) { } if (!defined $ENV{BUILD_PATH}) { - $build_path = "$ENV{RV_ROOT}/configs/snapshots/$snapshot" ; + $build_path = "$ENV{PWD}/snapshots/$snapshot" ; } else { $build_path = $ENV{BUILD_PATH}; } @@ -327,6 +391,10 @@ my $pdfile = "$build_path/pd_defines.vh"; # Whisper config file path my $whisperfile = "$build_path/whisper.json"; +# +# Default linker file +my $linkerfile = "$build_path/link.ld"; + # Perl defines file path my $perlfile = "$build_path/perl_configs.pl"; @@ -344,6 +412,7 @@ elsif ($target eq "lsu2dma_axi") { } elsif ($target eq "typical_pd") { print "$self: Using target \"typical_pd\"\n"; + $fpga_optimize = 0; $ret_stack_size=2; $btb_size=32; $bht_size=128; @@ -358,6 +427,8 @@ elsif ($target eq "high_perf") { } elsif ($target eq "default_ahb") { print "$self: Using target \"default_ahb\"\n"; + $axi = 0; + $ahb = 1; } else { die "$self: ERROR! Unsupported target \"$target\". Supported are 'default', 'default_ahb', 'typical_pd', 'high_perf', 'lsu2dma_axi\n" ; @@ -374,8 +445,8 @@ our @triggers = (#{{{ }, { "reset" => ["0x23e00000", "0x00000000", "0x00000000"], - "mask" => ["0x081818c7", "0xffffffff", "0x00000000"], - "poke_mask" => ["0x081818c7", "0xffffffff", "0x00000000"] + "mask" => ["0x081810c7", "0xffffffff", "0x00000000"], + "poke_mask" => ["0x081810c7", "0xffffffff", "0x00000000"] }, { "reset" => ["0x23e00000", "0x00000000", "0x00000000"], @@ -384,8 +455,8 @@ our @triggers = (#{{{ }, { "reset" => ["0x23e00000", "0x00000000", "0x00000000"], - "mask" => ["0x081818c7", "0xffffffff", "0x00000000"], - "poke_mask" => ["0x081818c7", "0xffffffff", "0x00000000"] + "mask" => ["0x081810c7", "0xffffffff", "0x00000000"], + "poke_mask" => ["0x081810c7", "0xffffffff", "0x00000000"] }, );#}}} @@ -419,6 +490,9 @@ our %csr = (#{{{ "poke_mask" => "0x7d", "exists" => "true", }, + "mcounteren" => { + "exists" => "false", + }, "mvendorid" => { "reset" => "0x45", "mask" => "0x0", @@ -430,7 +504,7 @@ our %csr = (#{{{ "exists" => "true", }, "mimpid" => { - "reset" => "0x2", + "reset" => "0x3", "mask" => "0x0", "exists" => "true", }, @@ -620,15 +694,15 @@ our %csr = (#{{{ }, "mcgc" => { "number" => "0x7f8", - "reset" => "0x0", - "mask" => "0x000001ff", - "poke_mask" => "0x000001ff", + "reset" => "0x200", + "mask" => "0x000003ff", + "poke_mask" => "0x000003ff", "exists" => "true", }, "mfdc" => { "number" => "0x7f9", "reset" => "0x00070000", - "mask" => "0x00070fff", + "mask" => "0x00071fff", "exists" => "true", }, "mrac" => { @@ -707,15 +781,40 @@ our %csr = (#{{{ "mask" => "0xf", "exists" => "true", }, - "mscause" => { - "number" => "0x7ff", - "reset" => "0x0", - "mask" => "0x0000000f", - "exists" => "true", + "mfdht" => { + "comment" => "Force Debug Halt Threshold", + "number" => "0x7ce", + "reset" => "0x0", + "mask" => "0x0000003f", + "exists" => "true", + "shared" => "true", }, + "mfdhs" => { + "comment" => "Force Debug Halt Status", + "number" => "0x7cf", + "reset" => "0x0", + "mask" => "0x00000003", + "exists" => "true", + }, + "mscause" => { + "number" => "0x7ff", + "reset" => "0x0", + "mask" => "0x0000000f", + "exists" => "true", + }, + );#}}} +# These are the peformance counters events implemented for el2s. An +# event number from outside this list will be replaced by zero if +# written to an MHPMEVENT CSR. +my @perf_events = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, + 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 54, 55, 56, + 512, 513, 514, 515, 516); + foreach my $i (0 .. 3) { $csr{"pmpcfg$i"} = { "exists" => "false" }; } @@ -724,8 +823,6 @@ foreach my $i (0 .. 15) { $csr{"pmpaddr$i"} = { "exists" => "false" }; } - - # }}} # Main config hash, with default values # @@ -755,6 +852,9 @@ our %config = (#{{{ }, "btb" => { + "btb_enable" => "$btb_enable", # Design Parm, Overridable + "btb_fullya" => "$btb_fullya", # Design Parm, Overridable + "btb_toffset_size" => "$btb_toffset_size", # Constant "btb_size" => "$btb_size", # Design Parm, Overridable "btb_index1_hi" => "derived", "btb_index1_lo" => "2", # Constant, Do Not Override @@ -781,20 +881,30 @@ our %config = (#{{{ }, "core" => { - "lsu_stbuf_depth" => "$lsu_stbuf_depth", # Design Parm, Overridable - "dma_buf_depth" => "$dma_buf_depth", # Design Parm, Overridable - "lsu_num_nbload" => "$lsu_num_nbload", # Design Parm, Overridable + "div_bit" => "$div_bit", # Design Parm, Overridable + "div_new" => "$div_new", # Design Parm, Overridable + "lsu_stbuf_depth" => "$lsu_stbuf_depth", # Design Parm, Overridable + "dma_buf_depth" => "$dma_buf_depth", # Design Parm, Overridable + "lsu_num_nbload" => "$lsu_num_nbload", # Design Parm, Overridable "opensource" => "$opensource", # Flow Infrastructure "verilator" => "$verilator", # Flow Infrastructure - "load_to_use_plus1" => "$load_to_use_plus1", # Design Parm, Overridable + "load_to_use_plus1" => "$load_to_use_plus1", # Design Parm, Overridable "iccm_icache" => 'derived', # Used by design "iccm_only" => 'derived', # Used by design "icache_only" => 'derived', # Used by design "no_iccm_no_icache" => 'derived', # Used by design "timer_legal_en" => '1', # Design Parm, Overridable + "bitmanip_zba" => $bitmanip_zba, # Design Parm, Overridable + "bitmanip_zbb" => $bitmanip_zbb, # Design Parm, Overridable + "bitmanip_zbc" => $bitmanip_zbc, # Design Parm, Overridable + "bitmanip_zbe" => $bitmanip_zbe, # Design Parm, Overridable + "bitmanip_zbf" => $bitmanip_zbf, # Design Parm, Overridable + "bitmanip_zbp" => $bitmanip_zbp, # Design Parm, Overridable + "bitmanip_zbr" => $bitmanip_zbr, # Design Parm, Overridable + "bitmanip_zbs" => $bitmanip_zbs, # Design Parm, Overridable "fast_interrupt_redirect" => "$fast_interrupt_redirect", # Design Parm, Overridable "lsu2dma" => $lsu2dma, # used by design/TB for LSU to DMA bridge - "fpga_optimize" => "0", # Optimize fpga speed by removing clock gating + "fpga_optimize" => $fpga_optimize # Optimize fpga speed by removing clock gating }, "dccm" => { @@ -837,13 +947,19 @@ our %config = (#{{{ "iccm_bank_index_lo" => 'derived', }, "icache" => { - "icache_enable" => "$icache_enable", # Design Parm, Overridable - "icache_waypack" => "$icache_waypack", # Design Parm, Overridable - "icache_num_ways" => "$icache_num_ways", # Design Parm, Overridable - "icache_banks_way" => "2", # Design Parm, Constant - "icache_bank_width" => "8", # Design Parm, Constant - "icache_ln_sz" => "$icache_ln_sz", # Design Parm, Overridable - "icache_size" => "$icache_size", # Design Parm, Overridable + "icache_enable" => "$icache_enable", # Design Parm, Overridable + "icache_waypack" => "$icache_waypack", # Design Parm, Overridable + "icache_num_ways" => "$icache_num_ways", # Design Parm, Overridable + "icache_banks_way" => "2", # Design Parm, Constant + "icache_bank_width" => "8", # Design Parm, Constant + "icache_ln_sz" => "$icache_ln_sz", # Design Parm, Overridable + "icache_size" => "$icache_size", # Design Parm, Overridable + "icache_bypass_enable" => "$icache_bypass_enable", # Design Parm, Overridable + "icache_num_bypass" => "$icache_num_bypass", # Design Parm, Overridable + "icache_num_bypass_width" => 'derived', + "icache_tag_bypass_enable" => "$icache_tag_bypass_enable", # Design Parm, Overridable + "icache_tag_num_bypass" => "$icache_tag_num_bypass", # Design Parm, Overridable + "icache_tag_num_bypass_width" => 'derived', "icache_bank_hi" => 'derived', "icache_bank_lo" => 'derived', "icache_data_cell" => 'derived', @@ -887,7 +1003,7 @@ our %config = (#{{{ "pic_meigwctrl_offset" => '0x4000', # Testbench only: gateway control regs relative to pic_base_addr "pic_meigwclr_offset" => '0x5000', # Testbench only: gateway clear regs relative to pic_base_addr - "pic_meipl_mask" => '0xf', + "pic_meipl_mask" => '0xf', # Whisper only "pic_meip_mask" => '0x0', "pic_meie_mask" => '0x1', "pic_mpiccfg_mask" => '0x1', @@ -895,30 +1011,30 @@ our %config = (#{{{ "pic_meigwctrl_mask" => '0x3', "pic_meigwclr_mask" => '0x0', - "pic_meipl_count" => $pic_total_int, - "pic_meip_count" => 4, - "pic_meie_count" => $pic_total_int, + "pic_meipl_count" => 'derived', + "pic_meip_count" => 'derived', + "pic_meie_count" => 'derived', "pic_mpiccfg_count" => 1, - "pic_meipt_count" => $pic_total_int, - "pic_meigwctrl_count" => $pic_total_int, - "pic_meigwclr_count" => $pic_total_int + "pic_meipt_count" => 'derived', + "pic_meigwctrl_count" => 'derived', + "pic_meigwclr_count" => 'derived', }, - "testbench" => { + "testbench" => { # Testbench only "TOP" => "tb_top", "RV_TOP" => "`TOP.rvtop", "CPU_TOP" => "`RV_TOP.swerv", "clock_period" => "100", - "build_ahb_lite" => "0", - "build_axi4" => "1", + "build_ahb_lite" => "$ahb", + "build_axi4" => "$axi", "build_axi_native" => "1", "assert_on" => "", "ext_datawidth" => "64", "ext_addrwidth" => "32", "sterr_rollback" => "0", "lderr_rollback" => "1", - "SDVT_AHB" => "1", + "SDVT_AHB" => "$ahb", }, - "protection" => { # Design parms, Overridable + "protection" => { # Design parms, Overridable - static MPU "inst_access_enable0" => "0x0", "inst_access_addr0" => "0x00000000", "inst_access_mask0" => "0xffffffff", @@ -971,40 +1087,49 @@ our %config = (#{{{ "memmap" => { # Testbench only "serialio" => 'derived, overridable', # Testbench only "external_data" => 'derived, overridable', # Testbench only - "external_prog" => 'derived, overridable', # Testbench only "debug_sb_mem" => 'derived, overridable', # Testbench only "external_data_1" => 'derived, overridable', # Testbench only - "external_mem_hole" => 'derived, overridable', # Testbench only + "external_mem_hole" => 'default disabled', # Testbench only # "consoleio" => 'derived', # Part of serial io. }, "bus" => { "lsu_bus_tag" => 'derived', - "lsu_bus_id" => '1', # Design parm, Overridable, - "lsu_bus_prty" => '2', # Design parm, Overridable, - "dma_bus_tag" => '1', # Design parm, Overridable - "dma_bus_id" => '1', # Design parm, Overridable - "dma_bus_prty" => '2', # Design parm, Overridable - "sb_bus_tag" => '1', # Design parm, Overridable - "sb_bus_id" => '1', # Design parm, Overridable - "sb_bus_prty" => '2', # Design parm, Overridable + "lsu_bus_id" => '1', + "lsu_bus_prty" => '2', + "dma_bus_tag" => '1', + "dma_bus_id" => '1', + "dma_bus_prty" => '2', + "sb_bus_tag" => '1', + "sb_bus_id" => '1', + "sb_bus_prty" => '2', "ifu_bus_tag" => 'derived', - "ifu_bus_id" => '1', # Design parm, Overridable - "ifu_bus_prty" => '2', # Design parm, Overridable - "bus_prty_default" => '3', # Design parm, Overridable + "ifu_bus_id" => '1', + "ifu_bus_prty" => '2', + "bus_prty_default" => '3', }, "triggers" => \@triggers, # Whisper only "csr" => \%csr, # Whisper only + "perf_events" => \@perf_events, # Whisper only "even_odd_trigger_chains" => "true", # Whisper only ); -# These parms are used in the verilog and will be part of global parm structure +# These parms are used in the Verilog and will be part of global parm structure # need to have this be width in binary # for now autosize to the data our %verilog_parms = ( - "lsu2dma" => '1', + "lsu2dma" => '1', "timer_legal_en" => '1', + "bitmanip_zbb" => '1', + "bitmanip_zbs" => '1', + "bitmanip_zba" => '1', + "bitmanip_zbc" => '1', + "bitmanip_zbe" => '1', + "bitmanip_zbf" => '1', + "bitmanip_zbp" => '1', + "bitmanip_zbr" => '1', "fast_interrupt_redirect" => '1', + "inst_access_enable0" => '1', "inst_access_addr0" => '32', "inst_access_mask0" => '32', @@ -1062,6 +1187,12 @@ our %verilog_parms = ( "icache_beat_bits" => '4', "icache_scnd_last" => '4', "icache_beat_addr_hi" => '4', + "icache_bypass_enable" => '1', + "icache_num_bypass" => '4', + "icache_num_bypass_width" => '4', + "icache_tag_bypass_enable" => '1', + "icache_tag_num_bypass" => '4', + "icache_tag_num_bypass_width" => '4', "iccm_icache" => '1', "iccm_only" => '1', "icache_only" => '1', @@ -1072,6 +1203,9 @@ our %verilog_parms = ( "lsu_num_nbload_width" => '3', "lsu_num_nbload" => '5', "ret_stack_size" => '4', + "btb_fullya" => '1', + "btb_toffset_size" => '5', + "btb_enable" => '1', "btb_size" => '10', "btb_index1_hi" => '5', "btb_index1_lo" => '5', @@ -1082,7 +1216,7 @@ our %verilog_parms = ( "btb_addr_hi" => '5', "btb_array_depth" => '9', "btb_addr_lo" => '2', - "btb_btag_size" => '4', + "btb_btag_size" => '5', "btb_btag_fold" => '1', "btb_fold2_index_hash" => '1', "bht_size" => '12', @@ -1091,6 +1225,8 @@ our %verilog_parms = ( "bht_array_depth" => '11', "bht_ghr_size" => '4', "bht_ghr_hash_1" => '1', + "div_bit" => '3', + "div_new" => '1', "lsu_stbuf_depth" => '4', "dma_buf_depth" => '3', "load_to_use_plus1" => '1', @@ -1146,7 +1282,7 @@ our %verilog_parms = ( "lsu_bus_id" => '1', "lsu_bus_prty" => '2', "dma_bus_tag" => '4', - "dma_bus_id" => '1', + "dma_bus_id" => '5', "dma_bus_prty" => '2', "sb_bus_tag" => '4', "sb_bus_id" => '1', @@ -1157,6 +1293,12 @@ our %verilog_parms = ( "bus_prty_default" => '2', ); +# to make sure parameter math works properly add 4 to each key of %verilog_parms - was an issue in btb calculations +my $key; +foreach $key (keys %verilog_parms) { + $verilog_parms{$key} += 4; +} + # need to figure out what to do here # for now none of these can be parameters @@ -1165,15 +1307,16 @@ our %verilog_parms = ( # move deletes lower # Perform any overrides first before derived values +# map_set_unset(); gen_define("","", \%config,"",[]); - # perform final checks my $c; $c=$config{retstack}{ret_stack_size}; if (!($c >=2 && $c <=8)) { die("$helpusage\n\nFAIL: ret_stack_size == $c; ILLEGAL !!!\n\n"); } -$c=$config{btb}{btb_size}; if (!($c==32||$c==64||$c==128||$c==256||$c==512)) { die("$helpusage\n\nFAIL: btb_size == $c; ILLEGAL !!!\n\n"); } +$c=$config{btb}{btb_size}; if (!($c==8||$c==16||$c==32||$c==64||$c==128||$c==256||$c==512)) { die("$helpusage\n\nFAIL: btb_size == $c; ILLEGAL !!!\n\n"); } +$c=$config{btb}{btb_size}; if (($c==64||$c==128||$c==256||$c==512) && $config{btb}{btb_fullya}) { die("$helpusage\n\nFAIL: btb_size == $c; btb_fullya=1 ILLEGAL !!!\n\n"); } $c=$config{iccm}{iccm_region}; if (!($c>=0 && $c<16)) { die("$helpusage\n\nFAIL: iccm_region == $c ILLEGAL !!!\n\n"); } $c=$config{iccm}{iccm_offset}; if (!($c>=0 && $c<256*1024*1024 && ($c&0xfff)==0)) { die("$helpusage\n\nFAIL: iccm_offset == $c ILLEGAL !!!\n\n"); } $c=$config{iccm}{iccm_size}; if (!($c==2||$c==4||$c==8||$c==16||$c==32||$c==64||$c==128||$c==256||$c==512)) { die("$helpusage\n\nFAIL: iccm_size == $c ILLEGAL !!!\n\n"); } @@ -1182,21 +1325,33 @@ $c=$config{iccm}{iccm_enable}; if (!($c==0 || $c==1)) $c=$config{dccm}{dccm_region}; if (!($c>=0 && $c<16)) { die("$helpusage\n\nFAIL: dccm_region == $c ILLEGAL !!!\n\n"); } $c=$config{dccm}{dccm_num_banks}; if (!(($c==2 && $config{dccm}{dccm_size} != 48) || $c==4 || ($c==8 && $config{dccm}{dccm_size} != 48) || ($c==16 && $config{dccm}{dccm_size} != 4 && $config{dccm}{dccm_size} != 48))) { die("$helpusage\n\nFAIL: dccm_num_banks == $c ILLEGAL !!!\n\n"); } -$c=$config{dccm}{dccm_offset}; if (!($c>=0 && $c<256*1024*1024 && ($c&0xfff)==0)) { die("$helpusage\n\nFAIL: dccm_offset == $c ILLEGAL !!!\n\n"); } -$c=$config{dccm}{dccm_size}; if (!($c==4||$c==8||$c==16||$c==32||$c==48||$c==64||$c==128||$c==256||$c==512)) { die("$helpusage\n\nFAIL: dccm_size == $c ILLEGAL !!!\n\n"); } -$c=$config{pic}{pic_2cycle}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: pic_2cycle == $c ILLEGAL !!!\n\n"); } -$c=$config{pic}{pic_region}; if (!($c>=0 && $c<16)) { die("$helpusage\n\nFAIL: pic_region == $c ILLEGAL !!!\n\n"); } -$c=$config{pic}{pic_offset}; if (!($c>=0 && $c<256*1024*1024 && ($c&0xfff)==0)) { die("$helpusage\n\nFAIL: pic_offset == $c ILLEGAL !!!\n\n"); } -$c=$config{pic}{pic_size}; if (!($c==32 || $c==64 || $c==128 || $c==256)) { die("$helpusage\n\nFAIL: pic_size == $c ILLEGAL !!!\n\n"); } -$c=$config{pic}{pic_total_int}; if ( $c<1 || $c>255) { die("$helpusage\n\nFAIL: pic_total_int == $c ILLEGAL !!!\n\n"); } -$c=$config{icache}{icache_enable}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_enable == $c ILLEGAL !!!\n\n"); } -$c=$config{icache}{icache_waypack}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_waypack == $c ILLEGAL !!!\n\n"); } -$c=$config{icache}{icache_num_ways}; if (!($c==2 || $c==4)) { die("$helpusage\n\nFAIL: icache_num_ways == $c ILLEGAL !!!\n\n"); } -$c=$config{icache}{icache_ln_sz}; if (!($c==32 || $c==64)) { die("$helpusage\n\nFAIL: icache_ln_sz == $c ILLEGAL !!!\n\n"); } -$c=$config{icache}{icache_size}; if (!($c==8 || $c==16 || $c==32 || $c==64 || $c==128 || $c==256)) { die("$helpusage\n\nFAIL: icache_size == $c ILLEGAL !!!\n\n"); } -$c=$config{core}{lsu_stbuf_depth}; if (!($c==2 || $c==4 || $c==8)) { die("$helpusage\n\nFAIL: lsu_stbuf_depth == $c ILLEGAL !!!\n\n"); } -$c=$config{core}{dma_buf_depth}; if (!($c==2 || $c==4 || $c==5)) { die("$helpusage\n\nFAIL: dma_buf_depth == $c ILLEGAL !!!\n\n"); } -$c=$config{core}{lsu_num_nbload}; if (!($c==2 || $c==4 || $c==8)) { die("$helpusage\n\nFAIL: lsu_num_nbload == $c ILLEGAL !!!\n\n"); } +$c=$config{dccm}{dccm_offset}; if (!($c>=0 && $c<256*1024*1024 && ($c&0xfff)==0)) { die("$helpusage\n\nFAIL: dccm_offset == $c ILLEGAL !!!\n\n"); } +$c=$config{dccm}{dccm_size}; if (!($c==4||$c==8||$c==16||$c==32||$c==48||$c==64||$c==128||$c==256||$c==512)) { die("$helpusage\n\nFAIL: dccm_size == $c ILLEGAL !!!\n\n"); } +$c=$config{pic}{pic_2cycle}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: pic_2cycle == $c ILLEGAL !!!\n\n"); } +$c=$config{pic}{pic_region}; if (!($c>=0 && $c<16)) { die("$helpusage\n\nFAIL: pic_region == $c ILLEGAL !!!\n\n"); } +$c=$config{pic}{pic_offset}; if (!($c>=0 && $c<256*1024*1024 && ($c&0xfff)==0)) { die("$helpusage\n\nFAIL: pic_offset == $c ILLEGAL !!!\n\n"); } +$c=$config{pic}{pic_size}; if (!($c==32 || $c==64 || $c==128 || $c==256)) { die("$helpusage\n\nFAIL: pic_size == $c ILLEGAL !!!\n\n"); } +$c=$config{pic}{pic_total_int}; if ( $c<1 || $c>255) { die("$helpusage\n\nFAIL: pic_total_int == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_num_bypass}; if ($c<1 || $c>8) { die("$helpusage\n\nFAIL: icache_num_bypass == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_bypass_enable}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_bypass_enable == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_tag_num_bypass}; if ($c<1 || $c>8) { die("$helpusage\n\nFAIL: icache_tag_num_bypass == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_tag_bypass_enable}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_tag_bypass_enable == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_enable}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_enable == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_waypack}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_waypack == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_num_ways}; if (!($c==2 || $c==4)) { die("$helpusage\n\nFAIL: icache_num_ways == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_ln_sz}; if (!($c==32 || $c==64)) { die("$helpusage\n\nFAIL: icache_ln_sz == $c ILLEGAL !!!\n\n"); } +$c=$config{icache}{icache_size}; if (!($c==8 || $c==16 || $c==32 || $c==64 || $c==128 || $c==256)) { die("$helpusage\n\nFAIL: icache_size == $c ILLEGAL !!!\n\n"); } +$c=$config{core}{div_bit}; if (!($c==1 || $c==2 || $c==3 || $c==4 )) { die("$helpusage\n\nFAIL: div_bit == $c ILLEGAL !!!\n\n"); } +$c=$config{core}{div_new}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: div_new == $c ILLEGAL !!!\n\n"); } +$c=$config{core}{lsu_stbuf_depth}; if (!($c==2 || $c==4 || $c==8)) { die("$helpusage\n\nFAIL: lsu_stbuf_depth == $c ILLEGAL !!!\n\n"); } +$c=$config{core}{dma_buf_depth}; if (!($c==2 || $c==4 || $c==5)) { die("$helpusage\n\nFAIL: dma_buf_depth == $c ILLEGAL !!!\n\n"); } +$c=$config{core}{lsu_num_nbload}; if (!($c==2 || $c==4 || $c==8)) { die("$helpusage\n\nFAIL: lsu_num_nbload == $c ILLEGAL !!!\n\n"); } + + +# force div_bit to be 1 for old div algorithm +if ($config{core}{div_new}==0 && $config{core}{div_bit}!=1) { + die("$helpusage\n\nFAIL: div_new=0 requires div_bit=1 ILLEGAL !!!\n\n"); +} $c=$config{protection}{inst_access_addr0}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr0 lower 6b must be 0s $c !!!\n\n"); } $c=$config{protection}{inst_access_addr1}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr1 lower 6b must be 0s !!!\n\n"); } @@ -1249,17 +1404,13 @@ if ((hex($config{protection}{data_access_addr5}) & hex($config{protection}{data_ if ((hex($config{protection}{data_access_addr6}) & hex($config{protection}{data_access_mask6}))!=0) { die("$helpusage\n\nFAIL: data_access_addr6 and data_access_mask6 must be orthogonal!!!\n\n"); } if ((hex($config{protection}{data_access_addr7}) & hex($config{protection}{data_access_mask7}))!=0) { die("$helpusage\n\nFAIL: data_access_addr7 and data_access_mask7 must be orthogonal!!!\n\n"); } -if ($config{bus}{dma_bus_tag} < 1) {die "$self : ERROR! dma_bus_tag cannot be less than 1\n"} -if ($config{bus}{sb_bus_tag} < 1) {die "$self : ERROR! sb_bus_tag cannot be less than 1\n"} - -# deletes # Fill in derived configuration entries. -if ($config{icache}{icache_enable}==0 && $config{iccm}{iccm_enable}==0) { +if (($config{icache}{icache_enable}==0 || grep(/icache_enable/, @unsets)) && $config{iccm}{iccm_enable}==0) { $config{core}{no_iccm_no_icache}=1; } -elsif ($config{icache}{icache_enable}==0 && $config{iccm}{iccm_enable}==1) { +elsif (($config{icache}{icache_enable}==0 || grep(/icache_enable/, @unsets)) && $config{iccm}{iccm_enable}==1) { $config{core}{iccm_only}=1; } elsif ($config{icache}{icache_enable}==1 && $config{iccm}{iccm_enable}==0) { @@ -1269,8 +1420,16 @@ elsif ($config{icache}{icache_enable}==1 && $config{iccm}{iccm_enable}==1) { $config{core}{iccm_icache}=1; } +if (!$config{dccm}{dccm_enable}) { + $config{core}{fast_interrupt_redirect} = 0; + print "$self: Disabling fast_interrupt_redirect because DCCM not enabled\n"; +} + + + $config{btb}{btb_btag_fold} = 0; $config{btb}{btb_fold2_index_hash} = 0; +$config{btb}{btb_btag_size} = 31; if($config{btb}{btb_size}==512){ $config{btb}{btb_index1_hi} = 9; @@ -1301,8 +1460,14 @@ if($config{btb}{btb_size}==512){ $config{btb}{btb_index2_hi} = 9; $config{btb}{btb_index3_hi} = 13; $config{btb}{btb_array_depth}= 16; - $config{btb}{btb_btag_size} = 9; + $config{btb}{btb_btag_size} = 9 unless $config{btb}{btb_fullya}; $config{btb}{btb_btag_fold} = 1; +} elsif($config{btb}{btb_size}<32){ + #verif issues require these even though they are not needed + $config{btb}{btb_index1_hi} = 5; + $config{btb}{btb_index2_hi} = 8; + $config{btb}{btb_index3_hi} = 11; + $config{btb}{btb_fullya} = 1; } $config{btb}{btb_index2_lo} = $config{btb}{btb_index1_hi}+1; @@ -1349,6 +1514,10 @@ $config{bht}{bht_ghr_hash_1} = ($config{bht}{bht_ghr_size} > ($config{btb}{btb_i $config{bht}{bht_hash_string} = &ghrhash($config{btb}{btb_index1_hi}, $config{bht}{bht_ghr_size}); + + + +# PIC derived $config{pic}{pic_base_addr} = (hex($config{pic}{pic_region})<<28) + (hex($config{pic}{pic_offset})); $config{pic}{pic_base_addr} = sprintf("0x%x", $config{pic}{pic_base_addr}); @@ -1356,6 +1525,17 @@ $config{pic}{pic_base_addr} = sprintf("0x%x", $config{pic}{pic_base_addr}); $config{pic}{pic_int_words} = int($config{pic}{pic_total_int}/32 +0.9); $config{pic}{pic_bits} = 10 + log2($config{pic}{pic_size}); +$config{pic}{pic_total_int_plus1} = $config{pic}{pic_total_int} + 1; +$config{pic}{pic_meipl_count} = $config{pic}{pic_total_int}; +$config{pic}{pic_meip_count} = $config{pic}{pic_int_words}; +$config{pic}{pic_meie_count} = $config{pic}{pic_total_int}; +$config{pic}{pic_meipt_count} = $config{pic}{pic_total_int}; +$config{pic}{pic_meigwctrl_count} = $config{pic}{pic_total_int}; +$config{pic}{pic_meigwclr_count} = $config{pic}{pic_total_int}; + +$config{icache}{icache_num_bypass_width} = int(log2($config{icache}{icache_num_bypass})) + 1; +$config{icache}{icache_tag_num_bypass_width} = int(log2($config{icache}{icache_tag_num_bypass})) + 1; + $config{core}{lsu_num_nbload_width} = log2($config{core}{lsu_num_nbload}); $config{bus}{lsu_bus_tag} = log2($config{core}{lsu_num_nbload}) + 1; @@ -1488,19 +1668,6 @@ for (my $rgn = 15;$rgn >= 0; $rgn--) { } $config{memmap}{external_data} = sprintf("0x%08x", $config{memmap}{external_data}); # -# Find an unused region for external prog -for (my $rgn = 15;$rgn >= 0; $rgn--) { - if (($rgn != hex($config{iccm}{iccm_region})) && - ($rgn != hex($config{dccm}{dccm_region})) && - ($rgn != (hex($config{memmap}{serialio})>>28)) && - ($rgn != (hex($config{memmap}{external_data})>>28)) && - ($rgn != (hex($config{pic}{pic_region})))) { - $config{memmap}{external_prog} = ($rgn << 28); - $regions_used{$rgn} = 1; - last; - } -} -$config{memmap}{external_prog} = sprintf("0x%08x", $config{memmap}{external_prog}); # Unused region for second data for (my $rgn = 15;$rgn >= 0; $rgn--) { @@ -1508,15 +1675,13 @@ for (my $rgn = 15;$rgn >= 0; $rgn--) { ($rgn != hex($config{dccm}{dccm_region})) && ($rgn != (hex($config{memmap}{serialio})>>28)) && ($rgn != (hex($config{memmap}{external_data})>>28)) && - ($rgn != (hex($config{memmap}{external_prog})>>28) && - ($rgn != (hex($config{pic}{pic_region}))) - )) { + ($rgn != (hex($config{pic}{pic_region})))) { $config{memmap}{external_data_1} = ($rgn << 28); $regions_used{$rgn} = 1; last; } } -$config{memmap}{external_data_1} = sprintf("0x%08x", $config{memmap}{data_1}); +$config{memmap}{external_data_1} = sprintf("0x%08x", $config{memmap}{external_data_1}); #$config{memmap}{consoleio} = hex($config{memmap}{serialio}) + 0x100; @@ -1555,61 +1720,61 @@ if (hex($config{protection}{data_access_enable0}) > 0 || hex($config{protection}{inst_access_enable4}) > 0 || hex($config{protection}{inst_access_enable5}) > 0 || hex($config{protection}{inst_access_enable6}) > 0 || - hex($config{protection}{inst_access_enable7}) > 0) { + hex($config{protection}{inst_access_enable7}) > 0 || + $config{memmap}{external_mem_hole} eq "default disabled"){ delete($config{memmap}{external_mem_hole}) ; } else { - # Unused region to create a memory map hole - for (my $rgn = 15;$rgn >= 0; $rgn--) { - if (!defined($regions_used{$rgn})) { - $config{memmap}{external_mem_hole} = ($rgn << 28); - $regions_used{$rgn} = 1; - last; + # Unused region to create a memory map hole, if not already specified + if ($config{memmap}{external_mem_hole} eq 'derived, overridable') { + for (my $rgn = 15;$rgn >= 0; $rgn--) { + if (!defined($regions_used{$rgn})) { + $config{memmap}{external_mem_hole} = ($rgn << 28); + $regions_used{$rgn} = 1; + last; + } } - } - if ($config{memmap}{external_mem_hole} == 0) { - $config{protection}{data_access_addr0} = "0x10000000"; - $config{protection}{data_access_mask0} = "0xffffffff"; - $config{protection}{data_access_enable0} = "1"; - } elsif (($config{memmap}{external_mem_hole}>>28) == 16) { - $config{protection}{data_access_addr0} = "0x00000000"; - $config{protection}{data_access_mask0} = "0xefffffff"; - $config{protection}{data_access_enable0} = "1"; } else { - my $hreg = $config{memmap}{external_mem_hole}>>28; - $config{protection}{data_access_addr0} = sprintf("0x%x", (($hreg^8)&8)<<28); - $config{protection}{data_access_mask0} = "0x7fffffff"; - $config{protection}{data_access_addr1} = sprintf("0x%x", ($hreg&8) << 28 |(($hreg^4)&4)<<28); - $config{protection}{data_access_mask1} = "0x3fffffff"; - $config{protection}{data_access_addr2} = sprintf("0x%x", ($hreg&12) <<28 | (($hreg^2)&2) <<28); - $config{protection}{data_access_mask2} = "0x1fffffff"; - $config{protection}{data_access_addr3} = sprintf("0x%x", ($hreg&14) << 28 |(($hreg^1)&1)<<28); - $config{protection}{data_access_mask3} = "0x0fffffff"; - $config{protection}{data_access_enable0} = "1"; - $config{protection}{data_access_enable1} = "1"; - $config{protection}{data_access_enable2} = "1"; - $config{protection}{data_access_enable3} = "1"; - $config{protection}{inst_access_addr0} = sprintf("0x%x", (($hreg^8)&8)<<28); - $config{protection}{inst_access_mask0} = "0x7fffffff"; - $config{protection}{inst_access_addr1} = sprintf("0x%x", ($hreg&8) << 28 |(($hreg^4)&4)<<28); - $config{protection}{inst_access_mask1} = "0x3fffffff"; - $config{protection}{inst_access_addr2} = sprintf("0x%x", ($hreg&12) <<28 | (($hreg^2)&2) <<28); - $config{protection}{inst_access_mask2} = "0x1fffffff"; - $config{protection}{inst_access_addr3} = sprintf("0x%x", ($hreg&14) << 28 |(($hreg^1)&1)<<28); - $config{protection}{inst_access_mask3} = "0x0fffffff"; - $config{protection}{inst_access_enable0} = "1"; - $config{protection}{inst_access_enable1} = "1"; - $config{protection}{inst_access_enable2} = "1"; - $config{protection}{inst_access_enable3} = "1"; + my $rgn = hex($config{memmap}{external_mem_hole})>>28; + $config{memmap}{external_mem_hole} = ($rgn << 28); + $regions_used{$rgn} =1; } + my $hreg = $config{memmap}{external_mem_hole}>>28; + $config{protection}{data_access_addr0} = sprintf("0x%x", (($hreg^8)&8)<<28); + $config{protection}{data_access_mask0} = "0x7fffffff"; + $config{protection}{data_access_addr1} = sprintf("0x%x", ($hreg&8) << 28 |(($hreg^4)&4)<<28); + $config{protection}{data_access_mask1} = "0x3fffffff"; + $config{protection}{data_access_addr2} = sprintf("0x%x", ($hreg&12) <<28 | (($hreg^2)&2) <<28); + $config{protection}{data_access_mask2} = "0x1fffffff"; + $config{protection}{data_access_addr3} = sprintf("0x%x", ($hreg&14) << 28 |(($hreg^1)&1)<<28); + $config{protection}{data_access_mask3} = "0x0fffffff"; + $config{protection}{data_access_enable0} = "1"; + $config{protection}{data_access_enable1} = "1"; + $config{protection}{data_access_enable2} = "1"; + $config{protection}{data_access_enable3} = "1"; + $config{protection}{inst_access_addr0} = sprintf("0x%x", (($hreg^8)&8)<<28); + $config{protection}{inst_access_mask0} = "0x7fffffff"; + $config{protection}{inst_access_addr1} = sprintf("0x%x", ($hreg&8) << 28 |(($hreg^4)&4)<<28); + $config{protection}{inst_access_mask1} = "0x3fffffff"; + $config{protection}{inst_access_addr2} = sprintf("0x%x", ($hreg&12) <<28 | (($hreg^2)&2) <<28); + $config{protection}{inst_access_mask2} = "0x1fffffff"; + $config{protection}{inst_access_addr3} = sprintf("0x%x", ($hreg&14) << 28 |(($hreg^1)&1)<<28); + $config{protection}{inst_access_mask3} = "0x0fffffff"; + $config{protection}{inst_access_enable0} = "1"; + $config{protection}{inst_access_enable1} = "1"; + $config{protection}{inst_access_enable2} = "1"; + $config{protection}{inst_access_enable3} = "1"; + $config{memmap}{external_mem_hole} = sprintf("0x%08x", $config{memmap}{external_mem_hole}); } #Define 5 unused regions for used in TG +my $unrg = 0; foreach my $unr (reverse(0 .. 15)) { if (!defined($regions_used{$unr})) { - $config{memmap}{"unused_region$unr"} = sprintf("0x%08x",($unr << 28)); + $config{memmap}{"unused_region$unrg"} = sprintf("0x%08x",($unr << 28)); $regions_used{$unr} = 1; + $unrg++; } } @@ -1679,20 +1844,35 @@ if ((hex($config{iccm}{iccm_region}) == hex($config{dccm}{dccm_region})) && (hex die "$self: ERROR! ICCM and DCCM blocks collide (region $config{iccm}{iccm_region}, offset $config{dccm}{dccm_offset})!\n"; } +#printf( "axi4 %s\n",$config{"testbench"}{"build_axi4"}); +#printf( "ahb_lite %s\n",$config{"testbench"}{"build_ahb_lite"}); +#printf( "axi_native %s\n",$config{"testbench"}{"build_axi_native"}); + +if( $target eq "el2_formal_axi" ) { + $config{testbench}{build_axi_native} = 1; + $config{testbench}{build_axi4} = 1; + print( "\$config{testbench}{build_axi_native} = $config{testbench}{build_axi_native} \n" ); + print( "\$config{testbench}{build_axi4 } = $config{testbench}{build_axi4 } \n" ); +} -# all targets default to axi -if (($target eq "default_ahb") || ($config{testbench}{build_ahb_lite} == 1)) { +if (($config{testbench}{build_ahb_lite} == 1)) { delete $config{testbench}{build_axi4}; $config{testbench}{build_axi_native}=1; $verilog_parms{build_axi4} = 0; - $config{testbench}{build_ahb_lite}=1; -} else { +} +elsif (($config{testbench}{build_axi4} == 1)) { $config{testbench}{build_axi_native}=1; - $config{testbench}{build_axi4} = 1; delete $config{testbench}{build_ahb_lite}; $verilog_parms{build_ahb_lite} = 0; } +elsif (($config{testbench}{build_axi_native} == 1)) { + die("illegal to set build_axi_native w/out build_axi4"); +} + +#printf( "axi4 %s\n",$config{"testbench"}{"build_axi4"}); +#printf( "ahb_lite %s\n",$config{"testbench"}{"build_ahb_lite"}); +#printf( "axi_native %s\n",$config{"testbench"}{"build_axi_native"}); # Over-ride MFDC reset value for AXI. @@ -1701,15 +1881,14 @@ if (defined($config{"testbench"}{"build_axi_native"}) && ($config{"testbench"}{" if (! (defined($config{testbench}{build_ahb_lite}) && $config{testbench}{build_ahb_lite} ne "0")) { $config{csr}{mfdc}{reset} = "0x00070040" if exists $config{csr}{mfdc}; } + } -# AHB overrides -if (defined($config{"testbench"}{"build_ahb_lite"}) && ($config{"testbench"}{"build_ahb_lite"} ne "0")) { -} # parm processing before any values are deleted from the hash +delete $config{core}{fpga_optimize} if ($config{core}{fpga_optimize} == 0); print "$self: Writing $tdfile\n"; @@ -1728,27 +1907,55 @@ $config{config_key}="32'hdeadbeef"; # deletes if (($load_to_use_plus1==0) && !grep(/load_to_use_plus1/, @sets)) { delete $config{"core"}{"load_to_use_plus1"}; } -if (($iccm_enable==0) && !grep(/iccm_enable/, @sets)) { delete $config{"iccm"}{"iccm_enable"}; } -if (($dccm_enable==0) && !grep(/dccm_enable/, @sets)) { delete $config{"dccm"}{"dccm_enable"}; } -if (($icache_enable==0) && !grep(/icache_enable/, @sets)) { delete $config{"icache"}{"icache_enable"}; } -if (($icache_waypack==0) && !grep(/icache_waypack/, @sets)) { delete $config{"icache"}{"icache_waypack"}; } -if (($opensource==0) && !grep(/opensource/, @sets)) { delete $config{"core"}{"opensource"}; } -if (($verilator==0) && !grep(/verilator/, @sets)) { delete $config{"core"}{"verilator"}; } -if (($pic_2cycle==0) && !grep(/pic_2cycle/, @sets)) { delete $config{"pic"}{"pic_2cycle"}; } -if (($icache_ecc==0) && !grep(/icache_ecc/, @sets)) { delete $config{"icache"}{"icache_ecc"}; } -if (($icache_2banks==0) && !grep(/icache_2banks/, @sets)) { delete $config{"icache"}{"icache_2banks"}; } +if (($iccm_enable==0) && !grep(/iccm_enable/, @sets)) { delete $config{"iccm"}{"iccm_enable"}; } -# new -if ($config{"testbench"}{"build_axi4"} == 1) { +# new code to handle the -set=parm=0 value correctly for common_defines.vh +$c=$config{core}{load_to_use_plus1}; if ($c==0 && !grep(/load_to_use_plus1=1/, @sets)) { delete $config{"core"}{"load_to_use_plus1"}; } +$c=$config{core}{opensource}; if ($c==0 && !grep(/opensource=1/, @sets)) { delete $config{"core"}{"opensource"}; } +$c=$config{core}{verilator}; if ($c==0 && !grep(/verilator=1/, @sets)) { delete $config{"core"}{"verilator"}; } +$c=$config{core}{div_new}; if ($c==0 && !grep(/div_new=1/, @sets)) { delete $config{"core"}{"div_new"}; } +# not needed +#$c=$config{core}{div_bit}; if ($c==0 && !grep(/div_bit=1/, @sets)) { delete $config{"core"}{"div_bit"}; } +$c=$config{iccm}{iccm_enable}; if ($c==0 && !grep(/iccm_enable=1/, @sets)) { delete $config{"iccm"}{"iccm_enable"}; } +$c=$config{btb}{btb_enable}; if ($c==0 && !grep(/btb_enable=1/, @sets)) { delete $config{"btb"}{"btb_enable"}; } +$c=$config{dccm}{dccm_enable}; if ($c==0 && !grep(/dccm_enable=1/, @sets)) { delete $config{"dccm"}{"dccm_enable"}; } +$c=$config{icache}{icache_waypack}; if ($c==0 && !grep(/icache_waypack=1/, @sets)) { delete $config{"icache"}{"icache_waypack"}; } +$c=$config{icache}{icache_enable}; if ($c==0 && !grep(/icache_enable=1/, @sets)) { delete $config{"icache"}{"icache_enable"}; } + +$c=$config{icache}{icache_2banks}; if ($c==0 && !grep(/icache_2banks=1/, @sets)) { delete $config{"icache"}{"icache_2banks"}; } +$c=$config{pic}{pic_2cycle}; if ($c==0 && !grep(/pic_2cycle=1/, @sets)) { delete $config{"pic"}{"pic_2cycle"}; } + +$c=$config{btb}{btb_fullya}; if ($c==0 && !grep(/btb_fullya=1/, @sets)) { delete $config{"btb"}{"btb_fullya"}; } + + + +if ($target eq "default") { +} +elsif (($config{"testbench"}{"build_axi4"} == 1)) { delete $config{"testbench"}{"build_ahb_lite"}; delete $config{"testbench"}{"build_axi_native_ahb"}; } -elsif (($target eq "default_ahb") || ($config{"testbench"}{"build_ahb_lite"} == 1)) { - $config{"testbench"}{"build_ahb_lite"} = 1; +elsif (($config{"testbench"}{"build_ahb_lite"} == 1)) { delete $config{"testbench"}{"build_axi4"}; - $config{"testbench"}{"build_axi_native_ahb"} = 1; + delete $config{"testbench"}{"build_axi_native"}; + delete $config{"testbench"}{"build_axi_native_ahb"}; } +elsif (($config{"testbench"}{"build_axi_native_ahb"} == 1)) { + delete $config{"testbench"}{"build_axi4"}; + delete $config{"testbench"}{"build_axi_native_ahb"}; +} +elsif (($config{"testbench"}{"build_axi_native"} == 1)) { + die("illegal to set build_axi_native w/out build_axi4"); +} +else { + delete $config{"testbench"}{"build_ahb_lite"}; + delete $config{"testbench"}{"build_axi4"}; + delete $config{"testbench"}{"build_axi_native"}; + delete $config{"testbench"}{"build_axi_native_ahb"}; +} + + @@ -1777,10 +1984,10 @@ close FILE; my $pddata=' `include "common_defines.vh" -`undef ASSERT_ON +`undef RV_ASSERT_ON `undef TEC_RV_ICG `define TEC_RV_ICG HDBLVT16_CKGTPLT_V5_12 -`define PHYSICAL 1 +`define RV_PHYSICAL 1 '; @@ -1795,9 +2002,8 @@ print "$self: Writing $whisperfile\n"; dump_whisper_config(\%config, $whisperfile); -# change this to use config version +# PIC address map based on config `$ENV{RV_ROOT}/tools/picmap -t $config{pic}{pic_total_int} > $build_path/pic_map_auto.h`; -#`$ENV{RV_ROOT}/tools/unrollforverilator $config{pic}{pic_total_int_plus1} > $build_path/el2_pic_ctrl_verilator_unroll.sv`; # Perl vars for use by scripts print "$self: Writing $perlfile\n"; @@ -1810,6 +2016,8 @@ print FILE "1;\n"; close FILE; +# Default linker script +gen_default_linker_script(); # Done ################################################################## # @@ -1907,7 +2115,7 @@ sub gen_define {#{{{ $value = eval($value); } my $override = grep(/^$key$/, @overridable); - print_define($prefix, $key, $value, $override); + print_define($prefix, $key, $value, $override) if ($value !~ /derived/); #printf("$key = $value\n"); if ($parms and defined($parms->{$key})) { $value=decimal($value); @@ -1999,7 +2207,7 @@ sub decimal { # Collect memory protection specs (array of address pairs) in the given # resutls array. Tag is either "data" or "inst". -sub collect_mem_protection { +sub collect_mem_protection {#{{{ my ($tag, $config, $results) = @_; return unless exists $config{protection}; @@ -2061,12 +2269,12 @@ sub collect_mem_protection { push(@{$results}, [ $start, $end ]); } -} +}#}}} # Collect the memory mapped registers associated with the pic (platform # interrup controller) to include in the whisper.json file. -sub collect_mem_mapped_regs { +sub collect_mem_mapped_regs {#{{{ my ($pic, $results) = @_; my $default_mask = 0; $results->{default_mask} = $default_mask; @@ -2087,7 +2295,7 @@ sub collect_mem_mapped_regs { $item{count} = $pic->{"pic_${name}_count"}; $results->{registers}{$name} = \%item; } -} +}#}}} sub dump_whisper_config{#{{{ @@ -2116,8 +2324,9 @@ sub dump_whisper_config{#{{{ collect_mem_protection("data", $config, \@data_mem_prot); $jh{memmap}{inst} = [@inst_mem_prot] if @inst_mem_prot; $jh{memmap}{data} = [@data_mem_prot] if @data_mem_prot; - foreach my $tag (qw ( size page_size serialio )) { - $jh{memmap}{tag} = $config{memmap}{ta} if exists $config{memmap}{tag}; + $config{memmap}{consoleio} = $config{memmap}{serialio} if exists $config{memmap}{serialio}; + foreach my $tag (qw ( size page_size serialio consoleio)) { + $jh{memmap}{$tag} = $config{memmap}{$tag} if exists $config{memmap}{$tag}; } # Collect load/store-error rollback parameter. @@ -2129,7 +2338,7 @@ sub dump_whisper_config{#{{{ } # Collect dccm configs - if (exists $config{dccm} and exists $config{dccm}{dccm_enable}) { + if (exists $config{dccm} and $config{dccm}{dccm_enable}) { $jh{dccm}{region} = $config{dccm}{dccm_region}; $jh{dccm}{size} = 1024*decimal($config{dccm}{dccm_size}); # From 1k to bytes $jh{dccm}{offset} = $config{dccm}{dccm_offset}; @@ -2138,7 +2347,7 @@ sub dump_whisper_config{#{{{ } # Collect icccm configs. - if (exists $config{iccm} and exists $config{iccm}{iccm_enable}) { + if (exists $config{iccm} and $config{iccm}{iccm_enable}) { $jh{iccm}{region} = $config{iccm}{iccm_region}; $jh{iccm}{size} = 1024*decimal($config{iccm}{iccm_size}); # From 1k to bytes $jh{iccm}{offset} = $config{iccm}{iccm_offset}; @@ -2151,7 +2360,6 @@ sub dump_whisper_config{#{{{ # Collect CSRs not included in verilog. my @removed_csrs; - if (! $config{core}{timer_legal_en}) { push(@removed_csrs, $_) for qw (mitcnt0 mitbnd0 mitctl0 mitcnt1 mitbnd1 mitctl1); @@ -2167,25 +2375,26 @@ sub dump_whisper_config{#{{{ # Remove CSRs not configured into verilog. delete $jh{csr}{$_} foreach @removed_csrs; - + # Collect zb extension configs + $jh{enable_zbb} = $config{core}{bitmanip_zbb}; + $jh{enable_zbs} = $config{core}{bitmanip_zbs}; + $jh{enable_zba} = $config{core}{bitmanip_zba}; + $jh{enable_zbc} = $config{core}{bitmanip_zbc}; + $jh{enable_zbe} = $config{core}{bitmanip_zbe}; + $jh{enable_zbf} = $config{core}{bitmanip_zbf}; + $jh{enable_zbp} = $config{core}{bitmanip_zbp}; + $jh{enable_zbr} = $config{core}{bitmanip_zbr}; # Collect pic configs. if (exists $config{pic}) { my %mem_mapped; collect_mem_mapped_regs($config{pic}, \%mem_mapped); $jh{'memory_mapped_registers'} = \%mem_mapped; + } - # This is now deprecated. To be removed soon. - while (my ($k, $v) = each %{$config{pic}}) { - next if $k eq 'pic_base_addr'; # derived from region and offset - if ($k eq 'pic_size') { - $v *= 1024; # from kbytes to bytes - $v = sprintf("0x%x", $v); - } - $k =~ s/^pic_//o; - $v += 0 if $v =~ /^\d+$/o; - $jh{pic}{$k} = $v; - } + # Collect performance events. Uncomment when RTL ready. + if (exists $config{perf_events}) { + $jh{mmode_perf_events} = $config{perf_events}; } # Make atomic instructions illegal outside of DCCM. @@ -2210,7 +2419,7 @@ sub dump_whisper_config{#{{{ # Checker for iccm/dccm/pic sub-region address alignment. Address must be a multiple # of size or next higher power of 2 if size is not a power of 2. -sub check_addr_align { +sub check_addr_align {#{{{ my ($section, $addr, $size) = @_; die("Invalid $section size: $size\n") if $size <= 0; @@ -2224,23 +2433,22 @@ sub check_addr_align { $addr, $size); exit(1); } -} +}#}}} - -sub log2 { +sub log2 {#{{{ my ($n) = @_; return log($n)/log(2); -} +}#}}} -sub b2d { +sub b2d {#{{{ my ($v) = @_; $v = oct("0b" . $v); return($v); -} +}#}}} -sub d2b { +sub d2b {#{{{ my ($key,$v,$LEN) = @_; my $repeat; @@ -2255,19 +2463,19 @@ sub d2b { } return($v); -} +}#}}} -sub invalid_mask { +sub invalid_mask {#{{{ my ($m) = @_; if ($m =~ /^0x(0)*([137]?f+)$/) { return(0); } return(1); -} +}#}}} -sub b2h { +sub b2h {#{{{ my ($bin) = @_; # Make input bit string a multiple of 4 @@ -2280,10 +2488,10 @@ sub b2h { $hex .= substr("0123456789ABCDEF", $nybble, 1); } return $hex; -} +}#}}} # BHT index is a hash of the GHR and PC_HASH -sub ghrhash{ +sub ghrhash{#{{{ my($btb_index_hi,$ghr_size) = @_; $btb_size = $btb_index_hi - 1; @@ -2298,9 +2506,9 @@ sub ghrhash{ else { return "{hashin[$ghr_size+1:2]^ghr[$ghr_size-1:0]}// cf2"; } -} +}#}}} -sub dump_parms { +sub dump_parms {#{{{ my ($hash) = @_; my ($bvalue, $blen, $upper); @@ -2330,18 +2538,71 @@ sub dump_parms { my $bvalue=""; my $pcnt=0; my $delim=","; + my $msb; printf(FILE2 "parameter el2_param_t pt = '{\n"); foreach my $key (sort keys %$hash) { $upper=$key; $upper=~ tr/a-z/A-Z/; $pcnt++; if ($pcnt==$parmcnt) { undef $delim; } + if ($hash->{$key} eq "0") { $hash->{$key}="0000"; } + $msb=substr($hash->{$key},0,4); # require upper 4b to be 0 + if ($msb ne "0000") { die("parameter $upper upper 4b must be 0"); } printf(FILE2 "\t%-22s : %d\'h%-10s $delim\n",$upper,length($hash->{$key}),b2h($hash->{$key})); } printf(FILE2 "}\n"); printf(FILE2 "// parameter el2_param_t pt = %d'h%s\n",length($bcat),b2h($bcat)); +}#}}} + +sub gen_default_linker_script {#{{{ + + open (FILE, ">$linkerfile") || die "Cannot open $linkerfile for writing $!\n"; + print "$self: Writing $linkerfile\n"; + print FILE "/*\n"; + print_header(); + + my $io = "0xd0580000"; + $io = $config{memmap}{serialio} if exists $config{memmap}{serialio}; + + my $iccm = ""; my $iccm_ctl = ""; + if (exists $config{iccm} and $config{iccm}{iccm_enable} and $text_in_iccm) { + my $sa = $config{iccm}{iccm_sadr}; my $ea = $config{iccm}{iccm_eadr}; + $iccm = " . = $sa ;"; + $iccm_ctl = " . = 0xfffffff0; .iccm.ctl . : { LONG($sa); LONG($ea) }" ; + } + + my $sa = $config{memmap}{external_data}; my $dccm_ctl = ""; + if (exists $config{dccm} and $config{dccm}{dccm_enable}) { + $sa = $config{dccm}{dccm_sadr}; + $dccm_ctl = " . = 0xfffffff8; .data.ctl : { LONG($sa); LONG(STACK) }" ; + } + my $data_loc = " . = $sa ;"; + + print FILE "*/\n"; + print FILE <<"EOF"; +OUTPUT_ARCH( "riscv" ) +ENTRY(_start) + +SECTIONS +{ + . = $config{reset_vec}; + .text.init . : { *(.text.init) } + $iccm + .text . : { *(.text) } + _end = .; + . = $io; + .data.io . : { *(.data.io) } + $data_loc + .data : ALIGN(0x800) { *(.*data) *(.rodata*) STACK = ALIGN(16) + 0x8000; } + .bss : { *(.bss) } + $iccm_ctl + $dccm_ctl } +EOF + close FILE; +} #}}} + diff --git a/design/dbg/el2_dbg.sv b/design/dbg/el2_dbg.sv index 63b3eb6..09fdd12 100644 --- a/design/dbg/el2_dbg.sv +++ b/design/dbg/el2_dbg.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -108,14 +108,14 @@ import el2_pkg::*; // general inputs input logic clk, - input logic rst_l, + input logic rst_l, // This includes both top rst and debug rst input logic dbg_rst_l, input logic clk_override, input logic scan_mode ); - typedef enum logic [2:0] {IDLE=3'b000, HALTING=3'b001, HALTED=3'b010, CMD_START=3'b011, CMD_WAIT=3'b100, CMD_DONE=3'b101, RESUMING=3'b110} state_t; + typedef enum logic [3:0] {IDLE=4'h0, HALTING=4'h1, HALTED=4'h2, CORE_CMD_START=4'h3, CORE_CMD_WAIT=4'h4, SB_CMD_START=4'h5, SB_CMD_SEND=4'h6, SB_CMD_RESP=4'h7, CMD_DONE=4'h8, RESUMING=4'h9} state_t; typedef enum logic [3:0] {SBIDLE=4'h0, WAIT_RD=4'h1, WAIT_WR=4'h2, CMD_RD=4'h3, CMD_WR=4'h4, CMD_WR_ADDR=4'h5, CMD_WR_DATA=4'h6, RSP_RD=4'h7, RSP_WR=4'h8, DONE=4'h9} sb_state_t; state_t dbg_state; @@ -132,32 +132,43 @@ import el2_pkg::*; // data 0 logic [31:0] data0_din; - logic data0_reg_wren, data0_reg_wren0, data0_reg_wren1; + logic data0_reg_wren, data0_reg_wren0, data0_reg_wren1, data0_reg_wren2; // data 1 logic [31:0] data1_din; - logic data1_reg_wren, data1_reg_wren0; + logic data1_reg_wren, data1_reg_wren0, data1_reg_wren1; // abstractcs logic abstractcs_busy_wren; logic abstractcs_busy_din; logic [2:0] abstractcs_error_din; - logic abstractcs_error_sel0, abstractcs_error_sel1, abstractcs_error_sel2, abstractcs_error_sel3, abstractcs_error_sel4, abstractcs_error_sel5; - logic abstractcs_error_selor; + logic abstractcs_error_sel0, abstractcs_error_sel1, abstractcs_error_sel2, abstractcs_error_sel3, abstractcs_error_sel4, abstractcs_error_sel5, abstractcs_error_sel6; + logic dbg_sb_bus_error; + // abstractauto + logic abstractauto_reg_wren; + logic [1:0] abstractauto_reg; + // dmstatus logic dmstatus_resumeack_wren; logic dmstatus_resumeack_din; - logic dmstatus_havereset_wren; - logic dmstatus_havereset_rst; + logic dmstatus_haveresetn_wren; logic dmstatus_resumeack; logic dmstatus_unavail; logic dmstatus_running; logic dmstatus_halted; - logic dmstatus_havereset; + logic dmstatus_havereset, dmstatus_haveresetn; // dmcontrol + logic resumereq; logic dmcontrol_wren, dmcontrol_wren_Q; // command - logic command_wren; + logic execute_command_ns, execute_command; + logic command_wren, command_regno_wren; + logic command_transfer_din; + logic command_postexec_din; logic [31:0] command_din; + logic [3:0] dbg_cmd_addr_incr; + logic [31:0] dbg_cmd_curr_addr; + logic [31:0] dbg_cmd_next_addr; + // needed to send the read data back for dmi reads logic [31:0] dmi_reg_rdata_din; @@ -176,6 +187,7 @@ import el2_pkg::*; logic [2:0] sbcs_sberror_din; logic sbcs_unaligned; logic sbcs_illegal_size; + logic [19:15] sbcs_reg_int; // data logic sbdata0_reg_wren0; @@ -197,6 +209,24 @@ import el2_pkg::*; logic sbreadondata_access; logic sbdata0wr_access; + logic sb_abmem_cmd_done_in, sb_abmem_data_done_in; + logic sb_abmem_cmd_done_en, sb_abmem_data_done_en; + logic sb_abmem_cmd_done, sb_abmem_data_done; + logic [31:0] abmem_addr; + logic abmem_addr_in_dccm_region, abmem_addr_in_iccm_region, abmem_addr_in_pic_region; + logic abmem_addr_core_local; + logic abmem_addr_external; + + logic sb_cmd_pending, sb_abmem_cmd_pending; + logic sb_abmem_cmd_write; + logic [2:0] sb_abmem_cmd_size; + logic [31:0] sb_abmem_cmd_addr; + logic [31:0] sb_abmem_cmd_wdata; + + logic [2:0] sb_cmd_size; + logic [31:0] sb_cmd_addr; + logic [63:0] sb_cmd_wdata; + logic sb_bus_cmd_read, sb_bus_cmd_write_addr, sb_bus_cmd_write_data; logic sb_bus_rsp_read, sb_bus_rsp_write; logic sb_bus_rsp_error; @@ -208,6 +238,14 @@ import el2_pkg::*; logic [31:0] sbdata0_reg; logic [31:0] sbdata1_reg; + logic sb_abmem_cmd_arvalid, sb_abmem_cmd_awvalid, sb_abmem_cmd_wvalid; + logic sb_abmem_read_pend; + logic sb_cmd_awvalid, sb_cmd_wvalid, sb_cmd_arvalid; + logic sb_read_pend; + logic [31:0] sb_axi_addr; + logic [63:0] sb_axi_wrdata; + logic [2:0] sb_axi_size; + logic dbg_dm_rst_l; //clken @@ -219,10 +257,10 @@ import el2_pkg::*; // clocking // used for the abstract commands. - assign dbg_free_clken = dmi_reg_en | (dbg_state != IDLE) | dbg_state_en | dec_tlu_dbg_halted | clk_override; + assign dbg_free_clken = dmi_reg_en | execute_command | (dbg_state != IDLE) | dbg_state_en | dec_tlu_dbg_halted | dec_tlu_mpc_halted_only | dec_tlu_debug_mode | dbg_halt_req | clk_override; // used for the system bus - assign sb_free_clken = dmi_reg_en | sb_state_en | (sb_state != SBIDLE) | clk_override; + assign sb_free_clken = dmi_reg_en | execute_command | sb_state_en | (sb_state != SBIDLE) | clk_override; rvoclkhdr dbg_free_cgc (.en(dbg_free_clken), .l1clk(dbg_free_clk), .*); rvoclkhdr sb_free_cgc (.en(sb_free_clken), .l1clk(sb_free_clk), .*); @@ -231,23 +269,25 @@ import el2_pkg::*; // Reset logic assign dbg_dm_rst_l = dbg_rst_l & (dmcontrol_reg[0] | scan_mode); - assign dbg_core_rst_l = ~dmcontrol_reg[1]; + assign dbg_core_rst_l = ~dmcontrol_reg[1] | scan_mode; // system bus register // sbcs[31:29], sbcs - [22]:sbbusyerror, [21]: sbbusy, [20]:sbreadonaddr, [19:17]:sbaccess, [16]:sbautoincrement, [15]:sbreadondata, [14:12]:sberror, sbsize=32, 128=0, 64/32/16/8 are legal assign sbcs_reg[31:29] = 3'b1; assign sbcs_reg[28:23] = '0; + assign sbcs_reg[19:15] = {sbcs_reg_int[19], ~sbcs_reg_int[18], sbcs_reg_int[17:15]}; assign sbcs_reg[11:5] = 7'h20; assign sbcs_reg[4:0] = 5'b01111; - assign sbcs_wren = (dmi_reg_addr == 7'h38) & dmi_reg_en & dmi_reg_wr_en & (sb_state == SBIDLE); // & (sbcs_reg[14:12] == 3'b000); + assign sbcs_wren = (dmi_reg_addr == 7'h38) & dmi_reg_en & dmi_reg_wr_en & (sb_state == SBIDLE); assign sbcs_sbbusyerror_wren = (sbcs_wren & dmi_reg_wdata[22]) | - ((sb_state != SBIDLE) & dmi_reg_en & ((dmi_reg_addr == 7'h39) | (dmi_reg_addr == 7'h3c) | (dmi_reg_addr == 7'h3d))); + (sbcs_reg[21] & dmi_reg_en & ((dmi_reg_wr_en & (dmi_reg_addr == 7'h39)) | (dmi_reg_addr == 7'h3c) | (dmi_reg_addr == 7'h3d))); assign sbcs_sbbusyerror_din = ~(sbcs_wren & dmi_reg_wdata[22]); // Clear when writing one rvdffs #(1) sbcs_sbbusyerror_reg (.din(sbcs_sbbusyerror_din), .dout(sbcs_reg[22]), .en(sbcs_sbbusyerror_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk)); rvdffs #(1) sbcs_sbbusy_reg (.din(sbcs_sbbusy_din), .dout(sbcs_reg[21]), .en(sbcs_sbbusy_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk)); rvdffs #(1) sbcs_sbreadonaddr_reg (.din(dmi_reg_wdata[20]), .dout(sbcs_reg[20]), .en(sbcs_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk)); - rvdffs #(5) sbcs_misc_reg (.din(dmi_reg_wdata[19:15]), .dout(sbcs_reg[19:15]), .en(sbcs_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk)); + rvdffs #(5) sbcs_misc_reg (.din({dmi_reg_wdata[19],~dmi_reg_wdata[18],dmi_reg_wdata[17:15]}), + .dout(sbcs_reg_int[19:15]), .en(sbcs_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk)); rvdffs #(3) sbcs_error_reg (.din(sbcs_sberror_din[2:0]), .dout(sbcs_reg[14:12]), .en(sbcs_sberror_wren), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk)); assign sbcs_unaligned = ((sbcs_reg[19:17] == 3'b001) & sbaddress0_reg[0]) | @@ -294,8 +334,9 @@ import el2_pkg::*; // rest all the bits are zeroed out // dmactive flop is reset based on core rst_l, all other flops use dm_rst_l assign dmcontrol_wren = (dmi_reg_addr == 7'h10) & dmi_reg_en & dmi_reg_wr_en; - assign dmcontrol_reg[29] = '0; + assign dmcontrol_reg[29] = '0; assign dmcontrol_reg[27:2] = '0; + assign resumereq = dmcontrol_reg[30] & ~dmcontrol_reg[31] & dmcontrol_wren_Q; rvdffs #(4) dmcontrolff (.din({dmi_reg_wdata[31:30],dmi_reg_wdata[28],dmi_reg_wdata[1]}), .dout({dmcontrol_reg[31:30], dmcontrol_reg[28], dmcontrol_reg[1]}), .en(dmcontrol_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); rvdffs #(1) dmcontrol_dmactive_ff (.din(dmi_reg_wdata[0]), .dout(dmcontrol_reg[0]), .en(dmcontrol_wren), .rst_l(dbg_rst_l), .clk(dbg_free_clk)); rvdff #(1) dmcontrol_wrenff(.din(dmcontrol_wren), .dout(dmcontrol_wren_Q), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); @@ -303,6 +344,7 @@ import el2_pkg::*; // dmstatus register bits that are implemented // [19:18]-havereset,[17:16]-resume ack, [9:8]-halted, [3:0]-version // rest all the bits are zeroed out + //assign dmstatus_wren = (dmi_reg_addr[31:0] == 32'h11) & dmi_reg_en; assign dmstatus_reg[31:20] = '0; assign dmstatus_reg[19:18] = {2{dmstatus_havereset}}; assign dmstatus_reg[15:14] = '0; @@ -314,18 +356,18 @@ import el2_pkg::*; assign dmstatus_reg[9:8] = {2{dmstatus_halted}}; assign dmstatus_reg[3:0] = 4'h2; - assign dmstatus_resumeack_wren = ((dbg_state == RESUMING) & dec_tlu_resume_ack) | (dmstatus_resumeack & ~dmcontrol_reg[30]); + assign dmstatus_resumeack_wren = ((dbg_state == RESUMING) & dec_tlu_resume_ack) | (dmstatus_resumeack & resumereq & dmstatus_halted); assign dmstatus_resumeack_din = (dbg_state == RESUMING) & dec_tlu_resume_ack; - assign dmstatus_havereset_wren = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[1] & dmi_reg_en & dmi_reg_wr_en; - assign dmstatus_havereset_rst = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[28] & dmi_reg_en & dmi_reg_wr_en; + assign dmstatus_haveresetn_wren = (dmi_reg_addr == 7'h10) & dmi_reg_wdata[28] & dmi_reg_en & dmi_reg_wr_en & dmcontrol_reg[0]; // clear the havereset + assign dmstatus_havereset = ~dmstatus_haveresetn; assign dmstatus_unavail = dmcontrol_reg[1] | ~rst_l; assign dmstatus_running = ~(dmstatus_unavail | dmstatus_halted); - rvdffs #(1) dmstatus_resumeack_reg (.din(dmstatus_resumeack_din), .dout(dmstatus_resumeack), .en(dmstatus_resumeack_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); - rvdff #(1) dmstatus_halted_reg (.din(dec_tlu_dbg_halted & ~dec_tlu_mpc_halted_only), .dout(dmstatus_halted), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); - rvdffsc #(1) dmstatus_havereset_reg (.din(1'b1), .dout(dmstatus_havereset), .en(dmstatus_havereset_wren), .clear(dmstatus_havereset_rst), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); + rvdffs #(1) dmstatus_resumeack_reg (.din(dmstatus_resumeack_din), .dout(dmstatus_resumeack), .en(dmstatus_resumeack_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); + rvdff #(1) dmstatus_halted_reg (.din(dec_tlu_dbg_halted & ~dec_tlu_mpc_halted_only), .dout(dmstatus_halted), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); + rvdffs #(1) dmstatus_haveresetn_reg (.din(1'b1), .dout(dmstatus_haveresetn), .en(dmstatus_haveresetn_wren), .rst_l(rst_l), .clk(dbg_free_clk)); // haltsum0 register assign haltsum0_reg[31:1] = '0; @@ -337,54 +379,76 @@ import el2_pkg::*; assign abstractcs_reg[11] = '0; assign abstractcs_reg[7:4] = '0; assign abstractcs_reg[3:0] = 4'h2; // One data register - assign abstractcs_error_sel0 = abstractcs_reg[12] & dmi_reg_en & ((dmi_reg_wr_en & ( (dmi_reg_addr == 7'h16) | (dmi_reg_addr == 7'h17))) | (dmi_reg_addr == 7'h4)); - assign abstractcs_error_sel1 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h17) & ~((dmi_reg_wdata[31:24] == 8'b0) | (dmi_reg_wdata[31:24] == 8'h2)); - assign abstractcs_error_sel2 = core_dbg_cmd_done & core_dbg_cmd_fail; - assign abstractcs_error_sel3 = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h17) & ~dmstatus_reg[9]; //(dbg_state != HALTED); - assign abstractcs_error_sel4 = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en & - ((dmi_reg_wdata[22:20] != 3'b010) | ((dmi_reg_wdata[31:24] == 8'h2) && (|data1_reg[1:0]))); // Only word size is allowed - assign abstractcs_error_sel5 = (dmi_reg_addr == 7'h16) & dmi_reg_en & dmi_reg_wr_en; + assign abstractcs_error_sel0 = abstractcs_reg[12] & ~(|abstractcs_reg[10:8]) & dmi_reg_en & ((dmi_reg_wr_en & ((dmi_reg_addr == 7'h16) | (dmi_reg_addr == 7'h17)) | (dmi_reg_addr == 7'h18)) | + (dmi_reg_addr == 7'h4) | (dmi_reg_addr == 7'h5)); + assign abstractcs_error_sel1 = execute_command & ~(|abstractcs_reg[10:8]) & + ((~((command_reg[31:24] == 8'b0) | (command_reg[31:24] == 8'h2))) | // Illegal command + (((command_reg[22:20] == 3'b011) | (command_reg[22])) & (command_reg[31:24] == 8'h2)) | // Illegal abstract memory size (can't be DW or higher) + ((command_reg[22:20] != 3'b010) & ((command_reg[31:24] == 8'h0) & command_reg[17])) | // Illegal abstract reg size + ((command_reg[31:24] == 8'h0) & command_reg[18])); //postexec for abstract register access + assign abstractcs_error_sel2 = ((core_dbg_cmd_done & core_dbg_cmd_fail) | // exception from core + (execute_command & (command_reg[31:24] == 8'h0) & // unimplemented regs + (((command_reg[15:12] == 4'h1) & (command_reg[11:5] != 0)) | (command_reg[15:13] != 0)))) & ~(|abstractcs_reg[10:8]); + assign abstractcs_error_sel3 = execute_command & (dbg_state != HALTED) & ~(|abstractcs_reg[10:8]); + assign abstractcs_error_sel4 = dbg_sb_bus_error & dbg_bus_clk_en & ~(|abstractcs_reg[10:8]);// sb bus error for abstract memory command + assign abstractcs_error_sel5 = execute_command & (command_reg[31:24] == 8'h2) & ~(|abstractcs_reg[10:8]) & + (((command_reg[22:20] == 3'b001) & data1_reg[0]) | ((command_reg[22:20] == 3'b010) & (|data1_reg[1:0]))); //Unaligned address for abstract memory + assign abstractcs_error_sel6 = (dmi_reg_addr == 7'h16) & dmi_reg_en & dmi_reg_wr_en; - assign abstractcs_error_selor = abstractcs_error_sel0 | abstractcs_error_sel1 | abstractcs_error_sel2 | abstractcs_error_sel3 | abstractcs_error_sel4 | abstractcs_error_sel5; - - assign abstractcs_error_din[2:0] = ({3{abstractcs_error_sel0}} & 3'b001) | // writing command or abstractcs while a command was executing. Or accessing data0 - ({3{abstractcs_error_sel1}} & 3'b010) | // writing a non-zero command to cmd field of command - ({3{abstractcs_error_sel2}} & 3'b011) | // exception while running command - ({3{abstractcs_error_sel3}} & 3'b100) | // writing a comnand when not in the halted state - ({3{abstractcs_error_sel4}} & 3'b111) | // unaligned abstract memory command - ({3{abstractcs_error_sel5}} & ~dmi_reg_wdata[10:8] & abstractcs_reg[10:8]) | // W1C - ({3{~abstractcs_error_selor}} & abstractcs_reg[10:8]); // hold + assign abstractcs_error_din[2:0] = abstractcs_error_sel0 ? 3'b001 : // writing command or abstractcs while a command was executing. Or accessing data0 + abstractcs_error_sel1 ? 3'b010 : // writing a illegal command type to cmd field of command + abstractcs_error_sel2 ? 3'b011 : // exception while running command + abstractcs_error_sel3 ? 3'b100 : // writing a comnand when not in the halted state + abstractcs_error_sel4 ? 3'b101 : // Bus error + abstractcs_error_sel5 ? 3'b111 : // unaligned or illegal size abstract memory command + abstractcs_error_sel6 ? (~dmi_reg_wdata[10:8] & abstractcs_reg[10:8]) : //W1C + abstractcs_reg[10:8]; //hold rvdffs #(1) dmabstractcs_busy_reg (.din(abstractcs_busy_din), .dout(abstractcs_reg[12]), .en(abstractcs_busy_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); rvdff #(3) dmabstractcs_error_reg (.din(abstractcs_error_din[2:0]), .dout(abstractcs_reg[10:8]), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); + // abstract auto reg + assign abstractauto_reg_wren = dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h18) & ~abstractcs_reg[12]; + rvdffs #(2) dbg_abstractauto_reg (.*, .din(dmi_reg_wdata[1:0]), .dout(abstractauto_reg[1:0]), .en(abstractauto_reg_wren), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); // command register - implemented all the bits in this register // command[16] = 1: write, 0: read - // Size - 2, Bits Not implemented: 23 (aamvirtual), 19-autoincrement, 18-postexec, 17-transfer - assign command_wren = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en & (dbg_state == HALTED); - assign command_din[31:0] = {dmi_reg_wdata[31:24],1'b0,dmi_reg_wdata[22:20],3'b0,dmi_reg_wdata[16:0]}; - rvdffe #(32) dmcommand_reg (.*, .din(command_din[31:0]), .dout(command_reg[31:0]), .en(command_wren), .rst_l(dbg_dm_rst_l)); + assign execute_command_ns = command_wren | + (dmi_reg_en & ~abstractcs_reg[12] & (((dmi_reg_addr == 7'h4) & abstractauto_reg[0]) | ((dmi_reg_addr == 7'h5) & abstractauto_reg[1]))); + assign command_wren = (dmi_reg_addr == 7'h17) & dmi_reg_en & dmi_reg_wr_en; + assign command_regno_wren = command_wren | ((command_reg[31:24] == 8'h0) & command_reg[19] & (dbg_state == CMD_DONE) & ~(|abstractcs_reg[10:8])); // aarpostincrement + assign command_postexec_din = (dmi_reg_wdata[31:24] == 8'h0) & dmi_reg_wdata[18]; + assign command_transfer_din = (dmi_reg_wdata[31:24] == 8'h0) & dmi_reg_wdata[17]; + assign command_din[31:16] = {dmi_reg_wdata[31:24],1'b0,dmi_reg_wdata[22:19],command_postexec_din,command_transfer_din, dmi_reg_wdata[16]}; + assign command_din[15:0] = command_wren ? dmi_reg_wdata[15:0] : dbg_cmd_next_addr[15:0]; + rvdff #(1) execute_commandff (.*, .din(execute_command_ns), .dout(execute_command), .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l)); + rvdffe #(16) dmcommand_reg (.*, .din(command_din[31:16]), .dout(command_reg[31:16]), .en(command_wren), .rst_l(dbg_dm_rst_l)); + rvdffe #(16) dmcommand_regno_reg (.*, .din(command_din[15:0]), .dout(command_reg[15:0]), .en(command_regno_wren), .rst_l(dbg_dm_rst_l)); - // data0 reg - assign data0_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h4) & (dbg_state == HALTED)); - assign data0_reg_wren1 = core_dbg_cmd_done & (dbg_state == CMD_WAIT) & ~command_reg[16]; - assign data0_reg_wren = data0_reg_wren0 | data0_reg_wren1; + // data0 reg + assign data0_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h4) & (dbg_state == HALTED) & ~abstractcs_reg[12]); + assign data0_reg_wren1 = core_dbg_cmd_done & (dbg_state == CORE_CMD_WAIT) & ~command_reg[16]; + assign data0_reg_wren = data0_reg_wren0 | data0_reg_wren1 | data0_reg_wren2; - assign data0_din[31:0] = ({32{data0_reg_wren0}} & dmi_reg_wdata[31:0]) | - ({32{data0_reg_wren1}} & core_dbg_rddata[31:0]); + assign data0_din[31:0] = ({32{data0_reg_wren0}} & dmi_reg_wdata[31:0]) | + ({32{data0_reg_wren1}} & core_dbg_rddata[31:0]) | + ({32{data0_reg_wren2}} & sb_bus_rdata[31:0]); rvdffe #(32) dbg_data0_reg (.*, .din(data0_din[31:0]), .dout(data0_reg[31:0]), .en(data0_reg_wren), .rst_l(dbg_dm_rst_l)); // data 1 - assign data1_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h5) & (dbg_state == HALTED)); - assign data1_reg_wren = data1_reg_wren0; + assign data1_reg_wren0 = (dmi_reg_en & dmi_reg_wr_en & (dmi_reg_addr == 7'h5) & (dbg_state == HALTED) & ~abstractcs_reg[12]); + assign data1_reg_wren1 = (dbg_state == CMD_DONE) & (command_reg[31:24] == 8'h2) & command_reg[19] & ~(|abstractcs_reg[10:8]); // aampostincrement + assign data1_reg_wren = data1_reg_wren0 | data1_reg_wren1; - assign data1_din[31:0] = ({32{data1_reg_wren0}} & dmi_reg_wdata[31:0]); + assign data1_din[31:0] = ({32{data1_reg_wren0}} & dmi_reg_wdata[31:0]) | + ({32{data1_reg_wren1}} & dbg_cmd_next_addr[31:0]); rvdffe #(32) dbg_data1_reg (.*, .din(data1_din[31:0]), .dout(data1_reg[31:0]), .en(data1_reg_wren), .rst_l(dbg_dm_rst_l)); + rvdffs #(1) sb_abmem_cmd_doneff (.din(sb_abmem_cmd_done_in), .dout(sb_abmem_cmd_done), .en(sb_abmem_cmd_done_en), .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l), .*); + rvdffs #(1) sb_abmem_data_doneff (.din(sb_abmem_data_done_in), .dout(sb_abmem_data_done), .en(sb_abmem_data_done_en), .clk(dbg_free_clk), .rst_l(dbg_dm_rst_l), .*); // FSM to control the debug mode entry, command send/recieve, and Resume flow. always_comb begin @@ -392,45 +456,74 @@ import el2_pkg::*; dbg_state_en = 1'b0; abstractcs_busy_wren = 1'b0; abstractcs_busy_din = 1'b0; - dbg_halt_req = dmcontrol_wren_Q & dmcontrol_reg[31] & ~dmcontrol_reg[1]; // single pulse output to the core. Need to drive every time this register is written since core might be halted due to MPC + dbg_halt_req = dmcontrol_wren_Q & dmcontrol_reg[31]; // single pulse output to the core. Need to drive every time this register is written since core might be halted due to MPC dbg_resume_req = 1'b0; // single pulse output to the core + dbg_sb_bus_error = 1'b0; + data0_reg_wren2 = 1'b0; + sb_abmem_cmd_done_in = 1'b0; + sb_abmem_data_done_in = 1'b0; + sb_abmem_cmd_done_en = 1'b0; + sb_abmem_data_done_en = 1'b0; case (dbg_state) IDLE: begin dbg_nxtstate = (dmstatus_reg[9] | dec_tlu_mpc_halted_only) ? HALTED : HALTING; // initiate the halt command to the core - dbg_state_en = ((dmcontrol_reg[31] & ~dec_tlu_debug_mode) | dmstatus_reg[9] | dec_tlu_mpc_halted_only) & ~dmcontrol_reg[1]; // when the jtag writes the halt bit in the DM register, OR when the status indicates H - dbg_halt_req = dmcontrol_reg[31] & ~dmcontrol_reg[1]; // only when jtag has written the halt_req bit in the control. Removed debug mode qualification during MPC changes + dbg_state_en = dmcontrol_reg[31] | dmstatus_reg[9] | dec_tlu_mpc_halted_only; // when the jtag writes the halt bit in the DM register, OR when the status indicates H + dbg_halt_req = dmcontrol_reg[31]; // only when jtag has written the halt_req bit in the control. Removed debug mode qualification during MPC changes end HALTING : begin - dbg_nxtstate = dmcontrol_reg[1] ? IDLE : HALTED; // Goto HALTED once the core sends an ACK - dbg_state_en = dmstatus_reg[9] | dmcontrol_reg[1]; // core indicates halted + dbg_nxtstate = HALTED; // Goto HALTED once the core sends an ACK + dbg_state_en = dmstatus_reg[9] | dec_tlu_mpc_halted_only; // core indicates halted end HALTED: begin // wait for halted to go away before send to resume. Else start of new command - dbg_nxtstate = (dmstatus_reg[9] & ~dmcontrol_reg[1]) ? ((dmcontrol_reg[30] & ~dmcontrol_reg[31]) ? RESUMING : CMD_START) : + dbg_nxtstate = dmstatus_reg[9] ? (resumereq ? RESUMING : (((command_reg[31:24] == 8'h2) & abmem_addr_external) ? SB_CMD_START : CORE_CMD_START)) : (dmcontrol_reg[31] ? HALTING : IDLE); // This is MPC halted case - dbg_state_en = (dmstatus_reg[9] & dmcontrol_reg[30] & ~dmcontrol_reg[31] & dmcontrol_wren_Q) | command_wren | dmcontrol_reg[1] | ~(dmstatus_reg[9] | dec_tlu_mpc_halted_only); // need to be exclusive ??? - abstractcs_busy_wren = dbg_state_en & (dbg_nxtstate == CMD_START); // write busy when a new command was written by jtag + dbg_state_en = (dmstatus_reg[9] & resumereq) | execute_command | ~(dmstatus_reg[9] | dec_tlu_mpc_halted_only); + abstractcs_busy_wren = dbg_state_en & ((dbg_nxtstate == CORE_CMD_START) | (dbg_nxtstate == SB_CMD_START)); // write busy when a new command was written by jtag abstractcs_busy_din = 1'b1; dbg_resume_req = dbg_state_en & (dbg_nxtstate == RESUMING); // single cycle pulse to core if resuming end - CMD_START: begin - dbg_nxtstate = dmcontrol_reg[1] ? IDLE : (|abstractcs_reg[10:8]) ? CMD_DONE : CMD_WAIT; // new command sent to the core - dbg_state_en = dbg_cmd_valid | (|abstractcs_reg[10:8]) | dmcontrol_reg[1]; + CORE_CMD_START: begin + // Don't execute the command if cmderror or transfer=0 for abstract register access + dbg_nxtstate = ((|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17])) ? CMD_DONE : CORE_CMD_WAIT; // new command sent to the core + dbg_state_en = dbg_cmd_valid | (|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17]); end - CMD_WAIT: begin - dbg_nxtstate = dmcontrol_reg[1] ? IDLE : CMD_DONE; - dbg_state_en = core_dbg_cmd_done | dmcontrol_reg[1]; // go to done state for one cycle after completing current command + CORE_CMD_WAIT: begin + dbg_nxtstate = CMD_DONE; + dbg_state_en = core_dbg_cmd_done; // go to done state for one cycle after completing current command + end + SB_CMD_START: begin + dbg_nxtstate = (|abstractcs_reg[10:8]) ? CMD_DONE : SB_CMD_SEND; + dbg_state_en = (dbg_bus_clk_en & ~sb_cmd_pending) | (|abstractcs_reg[10:8]); + end + SB_CMD_SEND: begin + sb_abmem_cmd_done_in = 1'b1; + sb_abmem_data_done_in= 1'b1; + sb_abmem_cmd_done_en = (sb_bus_cmd_read | sb_bus_cmd_write_addr) & dbg_bus_clk_en; + sb_abmem_data_done_en= (sb_bus_cmd_read | sb_bus_cmd_write_data) & dbg_bus_clk_en; + dbg_nxtstate = SB_CMD_RESP; + dbg_state_en = (sb_abmem_cmd_done | sb_abmem_cmd_done_en) & (sb_abmem_data_done | sb_abmem_data_done_en) & dbg_bus_clk_en; + end + SB_CMD_RESP: begin + dbg_nxtstate = CMD_DONE; + dbg_state_en = (sb_bus_rsp_read | sb_bus_rsp_write) & dbg_bus_clk_en; + dbg_sb_bus_error = (sb_bus_rsp_read | sb_bus_rsp_write) & sb_bus_rsp_error & dbg_bus_clk_en; + data0_reg_wren2 = dbg_state_en & ~sb_abmem_cmd_write & ~dbg_sb_bus_error; end CMD_DONE: begin - dbg_nxtstate = dmcontrol_reg[1] ? IDLE : HALTED; + dbg_nxtstate = HALTED; dbg_state_en = 1'b1; abstractcs_busy_wren = dbg_state_en; // remove the busy bit from the abstracts ( bit 12 ) abstractcs_busy_din = 1'b0; + sb_abmem_cmd_done_in = 1'b0; + sb_abmem_data_done_in= 1'b0; + sb_abmem_cmd_done_en = 1'b1; + sb_abmem_data_done_en= 1'b1; end RESUMING : begin dbg_nxtstate = IDLE; - dbg_state_en = dmstatus_reg[17] | dmcontrol_reg[1]; // resume ack has been updated in the dmstatus register + dbg_state_en = dmstatus_reg[17]; // resume ack has been updated in the dmstatus register end default : begin dbg_nxtstate = IDLE; @@ -439,16 +532,23 @@ import el2_pkg::*; abstractcs_busy_din = 1'b0; dbg_halt_req = 1'b0; // single pulse output to the core dbg_resume_req = 1'b0; // single pulse output to the core + dbg_sb_bus_error = 1'b0; + data0_reg_wren2 = 1'b0; + sb_abmem_cmd_done_in = 1'b0; + sb_abmem_data_done_in = 1'b0; + sb_abmem_cmd_done_en = 1'b0; + sb_abmem_data_done_en = 1'b0; end endcase end // always_comb begin assign dmi_reg_rdata_din[31:0] = ({32{dmi_reg_addr == 7'h4}} & data0_reg[31:0]) | ({32{dmi_reg_addr == 7'h5}} & data1_reg[31:0]) | - ({32{dmi_reg_addr == 7'h10}} & dmcontrol_reg[31:0]) | + ({32{dmi_reg_addr == 7'h10}} & {2'b0,dmcontrol_reg[29],1'b0,dmcontrol_reg[27:0]}) | // Read0 to Write only bits ({32{dmi_reg_addr == 7'h11}} & dmstatus_reg[31:0]) | ({32{dmi_reg_addr == 7'h16}} & abstractcs_reg[31:0]) | ({32{dmi_reg_addr == 7'h17}} & command_reg[31:0]) | + ({32{dmi_reg_addr == 7'h18}} & {30'h0,abstractauto_reg[1:0]}) | ({32{dmi_reg_addr == 7'h40}} & haltsum0_reg[31:0]) | ({32{dmi_reg_addr == 7'h38}} & sbcs_reg[31:0]) | ({32{dmi_reg_addr == 7'h39}} & sbaddress0_reg[31:0]) | @@ -457,19 +557,34 @@ import el2_pkg::*; rvdffs #($bits(state_t)) dbg_state_reg (.din(dbg_nxtstate), .dout({dbg_state}), .en(dbg_state_en), .rst_l(dbg_dm_rst_l & rst_l), .clk(dbg_free_clk)); - // Ack will use the power on reset only otherwise there won't be any ack until dmactive is 1 - rvdffs #(32) dmi_rddata_reg (.din(dmi_reg_rdata_din[31:0]), .dout(dmi_reg_rdata[31:0]), .en(dmi_reg_en), .rst_l(dbg_dm_rst_l), .clk(dbg_free_clk)); + rvdffe #(32) dmi_rddata_reg (.din(dmi_reg_rdata_din[31:0]), .dout(dmi_reg_rdata[31:0]), .en(dmi_reg_en), .rst_l(dbg_dm_rst_l), .clk(clk), .*); + + assign abmem_addr[31:0] = data1_reg[31:0]; + assign abmem_addr_core_local = (abmem_addr_in_dccm_region | abmem_addr_in_iccm_region | abmem_addr_in_pic_region); + assign abmem_addr_external = ~abmem_addr_core_local; + + assign abmem_addr_in_dccm_region = (abmem_addr[31:28] == pt.DCCM_REGION) & pt.DCCM_ENABLE; + assign abmem_addr_in_iccm_region = (abmem_addr[31:28] == pt.ICCM_REGION) & pt.ICCM_ENABLE; + assign abmem_addr_in_pic_region = (abmem_addr[31:28] == pt.PIC_REGION); // interface for the core - assign dbg_cmd_addr[31:0] = (command_reg[31:24] == 8'h2) ? {data1_reg[31:2],2'b0} : {20'b0, command_reg[11:0]}; // Only word addresses for abstract memory - assign dbg_cmd_wrdata[31:0] = data0_reg[31:0]; - assign dbg_cmd_valid = (dbg_state == CMD_START) & ~(|abstractcs_reg[10:8]) & dma_dbg_ready; - assign dbg_cmd_write = command_reg[16]; - assign dbg_cmd_type[1:0] = (command_reg[31:24] == 8'h2) ? 2'b10 : {1'b0, (command_reg[15:12] == 4'b0)}; - assign dbg_cmd_size[1:0] = command_reg[21:20]; + assign dbg_cmd_addr[31:0] = (command_reg[31:24] == 8'h2) ? data1_reg[31:0] : {20'b0, command_reg[11:0]}; + assign dbg_cmd_wrdata[31:0] = data0_reg[31:0]; + assign dbg_cmd_valid = (dbg_state == CORE_CMD_START) & ~((|abstractcs_reg[10:8]) | ((command_reg[31:24] == 8'h0) & ~command_reg[17]) | ((command_reg[31:24] == 8'h2) & abmem_addr_external)) & dma_dbg_ready; + assign dbg_cmd_write = command_reg[16]; + assign dbg_cmd_type[1:0] = (command_reg[31:24] == 8'h2) ? 2'b10 : {1'b0, (command_reg[15:12] == 4'b0)}; + assign dbg_cmd_size[1:0] = command_reg[21:20]; + + assign dbg_cmd_addr_incr[3:0] = (command_reg[31:24] == 8'h2) ? (4'h1 << sb_abmem_cmd_size[1:0]) : 4'h1; + assign dbg_cmd_curr_addr[31:0] = (command_reg[31:24] == 8'h2) ? data1_reg[31:0] : {16'b0, command_reg[15:0]}; + assign dbg_cmd_next_addr[31:0] = dbg_cmd_curr_addr[31:0] + {28'h0,dbg_cmd_addr_incr[3:0]}; // Ask DMA to stop taking bus trxns since debug request is done - assign dbg_dma_bubble = ((dbg_state == CMD_START) & ~(|abstractcs_reg[10:8])) | (dbg_state == CMD_WAIT); + assign dbg_dma_bubble = ((dbg_state == CORE_CMD_START) & ~(|abstractcs_reg[10:8])) | (dbg_state == CORE_CMD_WAIT); + + assign sb_cmd_pending = (sb_state == CMD_RD) | (sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR) | (sb_state == CMD_WR_DATA) | (sb_state == RSP_RD) | (sb_state == RSP_WR); + assign sb_abmem_cmd_pending = (dbg_state == SB_CMD_START) | (dbg_state == SB_CMD_SEND) | (dbg_state== SB_CMD_RESP); + // system bus FSM always_comb begin @@ -483,7 +598,7 @@ import el2_pkg::*; case (sb_state) SBIDLE: begin sb_nxtstate = sbdata0wr_access ? WAIT_WR : WAIT_RD; - sb_state_en = sbdata0wr_access | sbreadondata_access | sbreadonaddr_access; + sb_state_en = (sbdata0wr_access | sbreadondata_access | sbreadonaddr_access) & ~(|sbcs_reg[14:12]) & ~sbcs_reg[22]; sbcs_sbbusy_wren = sb_state_en; // set the single read bit if it is a singlread command sbcs_sbbusy_din = 1'b1; sbcs_sberror_wren = sbcs_wren & (|dmi_reg_wdata[14:12]); // write to clear the error bits @@ -491,13 +606,13 @@ import el2_pkg::*; end WAIT_RD: begin sb_nxtstate = (sbcs_unaligned | sbcs_illegal_size) ? DONE : CMD_RD; - sb_state_en = dbg_bus_clk_en | sbcs_unaligned | sbcs_illegal_size; + sb_state_en = (dbg_bus_clk_en & ~sb_abmem_cmd_pending) | sbcs_unaligned | sbcs_illegal_size; sbcs_sberror_wren = sbcs_unaligned | sbcs_illegal_size; sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100; end WAIT_WR: begin sb_nxtstate = (sbcs_unaligned | sbcs_illegal_size) ? DONE : CMD_WR; - sb_state_en = dbg_bus_clk_en | sbcs_unaligned | sbcs_illegal_size; + sb_state_en = (dbg_bus_clk_en & ~sb_abmem_cmd_pending) | sbcs_unaligned | sbcs_illegal_size; sbcs_sberror_wren = sbcs_unaligned | sbcs_illegal_size; sbcs_sberror_din[2:0] = sbcs_unaligned ? 3'b011 : 3'b100; end @@ -534,8 +649,7 @@ import el2_pkg::*; sb_state_en = 1'b1; sbcs_sbbusy_wren = 1'b1; // reset the single read sbcs_sbbusy_din = 1'b0; - sbaddress0_reg_wren1 = sbcs_reg[16]; // auto increment was set. Update to new address after completing the current command - + sbaddress0_reg_wren1 = sbcs_reg[16] & (sbcs_reg[14:12] == 3'b0); // auto increment was set and no error. Update to new address after completing the current command end default : begin sb_nxtstate = SBIDLE; @@ -551,6 +665,29 @@ import el2_pkg::*; rvdffs #($bits(sb_state_t)) sb_state_reg (.din(sb_nxtstate), .dout({sb_state}), .en(sb_state_en), .rst_l(dbg_dm_rst_l), .clk(sb_free_clk)); + assign sb_abmem_cmd_write = command_reg[16]; + assign sb_abmem_cmd_size[2:0] = {1'b0, command_reg[21:20]}; + assign sb_abmem_cmd_addr[31:0] = abmem_addr[31:0]; + assign sb_abmem_cmd_wdata[31:0] = data0_reg[31:0]; + + assign sb_cmd_size[2:0] = sbcs_reg[19:17]; + assign sb_cmd_wdata[63:0] = {sbdata1_reg[31:0], sbdata0_reg[31:0]}; + assign sb_cmd_addr[31:0] = sbaddress0_reg[31:0]; + + assign sb_abmem_cmd_awvalid = (dbg_state == SB_CMD_SEND) & sb_abmem_cmd_write & ~sb_abmem_cmd_done; + assign sb_abmem_cmd_wvalid = (dbg_state == SB_CMD_SEND) & sb_abmem_cmd_write & ~sb_abmem_data_done; + assign sb_abmem_cmd_arvalid = (dbg_state == SB_CMD_SEND) & ~sb_abmem_cmd_write & ~sb_abmem_cmd_done & ~sb_abmem_data_done; + assign sb_abmem_read_pend = (dbg_state == SB_CMD_RESP) & ~sb_abmem_cmd_write; + + assign sb_cmd_awvalid = ((sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR)); + assign sb_cmd_wvalid = ((sb_state == CMD_WR) | (sb_state == CMD_WR_DATA)); + assign sb_cmd_arvalid = (sb_state == CMD_RD); + assign sb_read_pend = (sb_state == RSP_RD); + + assign sb_axi_size[2:0] = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid | sb_abmem_cmd_arvalid | sb_abmem_read_pend) ? sb_abmem_cmd_size[2:0] : sb_cmd_size[2:0]; + assign sb_axi_addr[31:0] = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid | sb_abmem_cmd_arvalid | sb_abmem_read_pend) ? sb_abmem_cmd_addr[31:0] : sb_cmd_addr[31:0]; + assign sb_axi_wrdata[63:0] = (sb_abmem_cmd_awvalid | sb_abmem_cmd_wvalid) ? {2{sb_abmem_cmd_wdata[31:0]}} : sb_cmd_wdata[63:0]; + // Generic bus response signals assign sb_bus_cmd_read = sb_axi_arvalid & sb_axi_arready; assign sb_bus_cmd_write_addr = sb_axi_awvalid & sb_axi_awready; @@ -561,36 +698,36 @@ import el2_pkg::*; assign sb_bus_rsp_error = (sb_bus_rsp_read & (|(sb_axi_rresp[1:0]))) | (sb_bus_rsp_write & (|(sb_axi_bresp[1:0]))); // AXI Request signals - assign sb_axi_awvalid = (sb_state == CMD_WR) | (sb_state == CMD_WR_ADDR); - assign sb_axi_awaddr[31:0] = sbaddress0_reg[31:0]; + assign sb_axi_awvalid = sb_abmem_cmd_awvalid | sb_cmd_awvalid; + assign sb_axi_awaddr[31:0] = sb_axi_addr[31:0]; assign sb_axi_awid[pt.SB_BUS_TAG-1:0] = '0; - assign sb_axi_awsize[2:0] = sbcs_reg[19:17]; - assign sb_axi_awprot[2:0] = '0; + assign sb_axi_awsize[2:0] = sb_axi_size[2:0]; + assign sb_axi_awprot[2:0] = 3'b001; assign sb_axi_awcache[3:0] = 4'b1111; - assign sb_axi_awregion[3:0] = sbaddress0_reg[31:28]; + assign sb_axi_awregion[3:0] = sb_axi_addr[31:28]; assign sb_axi_awlen[7:0] = '0; assign sb_axi_awburst[1:0] = 2'b01; assign sb_axi_awqos[3:0] = '0; assign sb_axi_awlock = '0; - assign sb_axi_wvalid = (sb_state == CMD_WR) | (sb_state == CMD_WR_DATA); - assign sb_axi_wdata[63:0] = ({64{(sbcs_reg[19:17] == 3'h0)}} & {8{sbdata0_reg[7:0]}}) | - ({64{(sbcs_reg[19:17] == 3'h1)}} & {4{sbdata0_reg[15:0]}}) | - ({64{(sbcs_reg[19:17] == 3'h2)}} & {2{sbdata0_reg[31:0]}}) | - ({64{(sbcs_reg[19:17] == 3'h3)}} & {sbdata1_reg[31:0],sbdata0_reg[31:0]}); - assign sb_axi_wstrb[7:0] = ({8{(sbcs_reg[19:17] == 3'h0)}} & (8'h1 << sbaddress0_reg[2:0])) | - ({8{(sbcs_reg[19:17] == 3'h1)}} & (8'h3 << {sbaddress0_reg[2:1],1'b0})) | - ({8{(sbcs_reg[19:17] == 3'h2)}} & (8'hf << {sbaddress0_reg[2],2'b0})) | - ({8{(sbcs_reg[19:17] == 3'h3)}} & 8'hff); + assign sb_axi_wvalid = sb_abmem_cmd_wvalid | sb_cmd_wvalid; + assign sb_axi_wdata[63:0] = ({64{(sb_axi_size[2:0] == 3'h0)}} & {8{sb_axi_wrdata[7:0]}}) | + ({64{(sb_axi_size[2:0] == 3'h1)}} & {4{sb_axi_wrdata[15:0]}}) | + ({64{(sb_axi_size[2:0] == 3'h2)}} & {2{sb_axi_wrdata[31:0]}}) | + ({64{(sb_axi_size[2:0] == 3'h3)}} & {sb_axi_wrdata[63:0]}); + assign sb_axi_wstrb[7:0] = ({8{(sb_axi_size[2:0] == 3'h0)}} & (8'h1 << sb_axi_addr[2:0])) | + ({8{(sb_axi_size[2:0] == 3'h1)}} & (8'h3 << {sb_axi_addr[2:1],1'b0})) | + ({8{(sb_axi_size[2:0] == 3'h2)}} & (8'hf << {sb_axi_addr[2],2'b0})) | + ({8{(sb_axi_size[2:0] == 3'h3)}} & 8'hff); assign sb_axi_wlast = '1; - assign sb_axi_arvalid = (sb_state == CMD_RD); - assign sb_axi_araddr[31:0] = sbaddress0_reg[31:0]; + assign sb_axi_arvalid = sb_abmem_cmd_arvalid | sb_cmd_arvalid; + assign sb_axi_araddr[31:0] = sb_axi_addr[31:0]; assign sb_axi_arid[pt.SB_BUS_TAG-1:0] = '0; - assign sb_axi_arsize[2:0] = sbcs_reg[19:17]; - assign sb_axi_arprot[2:0] = '0; + assign sb_axi_arsize[2:0] = sb_axi_size[2:0]; + assign sb_axi_arprot[2:0] = 3'b001; assign sb_axi_arcache[3:0] = 4'b0; - assign sb_axi_arregion[3:0] = sbaddress0_reg[31:28]; + assign sb_axi_arregion[3:0] = sb_axi_addr[31:28]; assign sb_axi_arlen[7:0] = '0; assign sb_axi_arburst[1:0] = 2'b01; assign sb_axi_arqos[3:0] = '0; @@ -600,14 +737,17 @@ import el2_pkg::*; assign sb_axi_bready = 1'b1; assign sb_axi_rready = 1'b1; - assign sb_bus_rdata[63:0] = ({64{sbcs_reg[19:17] == 3'h0}} & ((sb_axi_rdata[63:0] >> 8*sbaddress0_reg[2:0]) & 64'hff)) | - ({64{sbcs_reg[19:17] == 3'h1}} & ((sb_axi_rdata[63:0] >> 16*sbaddress0_reg[2:1]) & 64'hffff)) | - ({64{sbcs_reg[19:17] == 3'h2}} & ((sb_axi_rdata[63:0] >> 32*sbaddress0_reg[2]) & 64'hffff_ffff)) | - ({64{sbcs_reg[19:17] == 3'h3}} & sb_axi_rdata[63:0]); + assign sb_bus_rdata[63:0] = ({64{sb_axi_size == 3'h0}} & ((sb_axi_rdata[63:0] >> 8*sb_axi_addr[2:0]) & 64'hff)) | + ({64{sb_axi_size == 3'h1}} & ((sb_axi_rdata[63:0] >> 16*sb_axi_addr[2:1]) & 64'hffff)) | + ({64{sb_axi_size == 3'h2}} & ((sb_axi_rdata[63:0] >> 32*sb_axi_addr[2]) & 64'hffff_ffff)) | + ({64{sb_axi_size == 3'h3}} & sb_axi_rdata[63:0]); -`ifdef ASSERT_ON +`ifdef RV_ASSERT_ON // assertion. // when the resume_ack is asserted then the dec_tlu_dbg_halted should be 0 dm_check_resume_and_halted: assert property (@(posedge clk) disable iff(~rst_l) (~dec_tlu_resume_ack | ~dec_tlu_dbg_halted)); + + assert_b2b_haltreq: assert property (@(posedge clk) disable iff (~(rst_l)) (##1 dbg_halt_req |=> ~dbg_halt_req)); // One cycle delay to fix weird issue around reset + assert_halt_resume_onehot: assert #0 ($onehot0({dbg_halt_req, dbg_resume_req})); `endif endmodule diff --git a/design/dec/csrdecode b/design/dec/csrdecode index 4082ccc..b43c79b 100644 --- a/design/dec/csrdecode +++ b/design/dec/csrdecode @@ -209,6 +209,7 @@ csr[ csr_mpmc ] = { csr_mpmc } csr[ csr_mcpc ] = { csr_mcpc presync postsync } csr[ csr_meicidpl ] = { csr_meicidpl } csr[ csr_mcgc ] = { csr_mcgc } +csr[ csr_mcountinhibit] = { csr_mcountinhibit presync postsync } csr[ csr_mfdc ] = { csr_mfdc presync postsync } csr[ csr_dcsr ] = { csr_dcsr } csr[ csr_dpc ] = { csr_dpc } diff --git a/design/dec/decode b/design/dec/decode index d4435e0..b9e98c8 100644 --- a/design/dec/decode +++ b/design/dec/decode @@ -1,6 +1,146 @@ .definition +clz = [011000000000.....001.....0010011] +ctz = [011000000001.....001.....0010011] +pcnt = [011000000010.....001.....0010011] +sext_b = [011000000100.....001.....0010011] +sext_h = [011000000101.....001.....0010011] +slo = [0010000..........001.....0110011] +sro = [0010000..........101.....0110011] +sloi = [0010000..........001.....0010011] +sroi = [0010000..........101.....0010011] + +min = [0000101..........100.....0110011] +max = [0000101..........101.....0110011] +minu = [0000101..........110.....0110011] +maxu = [0000101..........111.....0110011] + +andn = [0100000..........111.....0110011] +orn = [0100000..........110.....0110011] +xnor = [0100000..........100.....0110011] +pack = [0000100..........100.....0110011] +packu = [0100100..........100.....0110011] +packh = [0000100..........111.....0110011] +rol = [0110000..........001.....0110011] +ror = [0110000..........101.....0110011] +rori = [0110000..........101.....0010011] + +sh1add = [0010000..........010.....0110011] +sh2add = [0010000..........100.....0110011] +sh3add = [0010000..........110.....0110011] + +sbset = [0010100..........001.....0110011] +sbclr = [0100100..........001.....0110011] +sbinv = [0110100..........001.....0110011] +sbext = [0100100..........101.....0110011] + +sbseti = [0010100..........001.....0010011] +sbclri = [0100100..........001.....0010011] +sbinvi = [0110100..........001.....0010011] +sbexti = [0100100..........101.....0010011] + +grev = [0110100..........101.....0110011] +#grevi = [01101............101.....0010011] +grevi0 = [011010000000.....101.....0010011] +grevi1 = [011010000001.....101.....0010011] +grevi2 = [011010000010.....101.....0010011] +grevi3 = [011010000011.....101.....0010011] +grevi4 = [011010000100.....101.....0010011] +grevi5 = [011010000101.....101.....0010011] +grevi6 = [011010000110.....101.....0010011] +grevi7 = [011010000111.....101.....0010011] +grevi8 = [011010001000.....101.....0010011] +grevi9 = [011010001001.....101.....0010011] +grevi10 = [011010001010.....101.....0010011] +grevi11 = [011010001011.....101.....0010011] +grevi12 = [011010001100.....101.....0010011] +grevi13 = [011010001101.....101.....0010011] +grevi14 = [011010001110.....101.....0010011] +grevi15 = [011010001111.....101.....0010011] +grevi16 = [011010010000.....101.....0010011] +grevi17 = [011010010001.....101.....0010011] +grevi18 = [011010010010.....101.....0010011] +grevi19 = [011010010011.....101.....0010011] +grevi20 = [011010010100.....101.....0010011] +grevi21 = [011010010101.....101.....0010011] +grevi22 = [011010010110.....101.....0010011] +grevi23 = [011010010111.....101.....0010011] +#grevi24 = [011010011000.....101.....0010011] # REV8 +rev8 = [011010011000.....101.....0010011] +grevi25 = [011010011001.....101.....0010011] +grevi26 = [011010011010.....101.....0010011] +grevi27 = [011010011011.....101.....0010011] +grevi28 = [011010011100.....101.....0010011] +grevi29 = [011010011101.....101.....0010011] +grevi30 = [011010011110.....101.....0010011] +#grevi31 = [011010011111.....101.....0010011] # REV +rev = [011010011111.....101.....0010011] + +gorc = [0010100..........101.....0110011] +#gorci = [00101............101.....0010011] +gorci0 = [001010000000.....101.....0010011] +gorci1 = [001010000001.....101.....0010011] +gorci2 = [001010000010.....101.....0010011] +gorci3 = [001010000011.....101.....0010011] +gorci4 = [001010000100.....101.....0010011] +gorci5 = [001010000101.....101.....0010011] +gorci6 = [001010000110.....101.....0010011] +#gorci7 = [001010000111.....101.....0010011] # ORC_B +orc_b = [001010000111.....101.....0010011] +gorci8 = [001010001000.....101.....0010011] +gorci9 = [001010001001.....101.....0010011] +gorci10 = [001010001010.....101.....0010011] +gorci11 = [001010001011.....101.....0010011] +gorci12 = [001010001100.....101.....0010011] +gorci13 = [001010001101.....101.....0010011] +gorci14 = [001010001110.....101.....0010011] +gorci15 = [001010001111.....101.....0010011] +#gorci16 = [001010010000.....101.....0010011] # ORC16 +orc16 = [001010010000.....101.....0010011] +gorci17 = [001010010001.....101.....0010011] +gorci18 = [001010010010.....101.....0010011] +gorci19 = [001010010011.....101.....0010011] +gorci20 = [001010010100.....101.....0010011] +gorci21 = [001010010101.....101.....0010011] +gorci22 = [001010010110.....101.....0010011] +gorci23 = [001010010111.....101.....0010011] +gorci24 = [001010011000.....101.....0010011] +gorci25 = [001010011001.....101.....0010011] +gorci26 = [001010011010.....101.....0010011] +gorci27 = [001010011011.....101.....0010011] +gorci28 = [001010011100.....101.....0010011] +gorci29 = [001010011101.....101.....0010011] +gorci30 = [001010011110.....101.....0010011] +gorci31 = [001010011111.....101.....0010011] + + +shfl = [0000100..........001.....0110011] +shfli = [00001000.........001.....0010011] + +unshfl = [0000100..........101.....0110011] +unshfli = [00001000.........101.....0010011] + +bdep = [0100100..........110.....0110011] +bext = [0000100..........110.....0110011] + +clmul = [0000101..........001.....0110011] +clmulr = [0000101..........010.....0110011] +clmulh = [0000101..........011.....0110011] + +crc32_b = [011000010000.....001.....0010011] +crc32_h = [011000010001.....001.....0010011] +crc32_w = [011000010010.....001.....0010011] +crc32c_b = [011000011000.....001.....0010011] +crc32c_h = [011000011001.....001.....0010011] +crc32c_w = [011000011010.....001.....0010011] + +bfp = [0100100..........111.....0110011] + + + + + add = [0000000..........000.....0110011] addi = [.................000.....0010011] @@ -206,20 +346,138 @@ rv32i = { rem fence fence_i + clz + ctz + pcnt + sext_b + sext_h + slo + sro + min + max + pack + packu + packh + rol + ror + zbb + sbset + sbclr + sbinv + sbext + zbs + bext + bdep + zbe + clmul + clmulh + clmulr + zbc + grev + gorc + shfl + unshfl + zbp + crc32_b + crc32_h + crc32_w + crc32c_b + crc32c_h + crc32c_w + zbr + bfp + zbf + sh1add + sh2add + sh3add + zba pm_alu } .decode +rv32i[clz] = { alu zbb rs1 rd clz } +rv32i[ctz] = { alu zbb rs1 rd ctz } +rv32i[pcnt] = { alu zbb rs1 rd pcnt } +rv32i[sext_b] = { alu zbb rs1 rd sext_b} +rv32i[sext_h] = { alu zbb rs1 rd sext_h} +rv32i[slo] = { alu zbp rs1 rs2 rd slo } +rv32i[sro] = { alu zbp rs1 rs2 rd sro } +rv32i[sloi] = { alu zbp rs1 rd shimm5 slo } +rv32i[sroi] = { alu zbp rs1 rd shimm5 sro } +rv32i[min] = { alu zbb rs1 rs2 rd sub min } +rv32i[max] = { alu zbb rs1 rs2 rd sub max } +rv32i[minu] = { alu zbb rs1 rs2 rd unsign sub min } +rv32i[maxu] = { alu zbb rs1 rs2 rd unsign sub max } +rv32i[andn] = { alu zbb zbp rs1 rs2 rd land } +rv32i[orn] = { alu zbb zbp rs1 rs2 rd lor } +rv32i[xnor] = { alu zbb zbp rs1 rs2 rd lxor } +rv32i[pack] = { alu zbb zbp rs1 rs2 rd pack } +rv32i[packu] = { alu zbb zbp rs1 rs2 rd packu } +rv32i[packh] = { alu zbb zbp rs1 rs2 rd packh } +rv32i[rol] = { alu zbb zbp rs1 rs2 rd rol } +rv32i[ror] = { alu zbb zbp rs1 rs2 rd ror } +rv32i[rori] = { alu zbb zbp rs1 rd shimm5 ror } +rv32i[sbset] = { alu zbs rs1 rs2 rd sbset } +rv32i[sbclr] = { alu zbs rs1 rs2 rd sbclr } +rv32i[sbinv] = { alu zbs rs1 rs2 rd sbinv } +rv32i[sbext] = { alu zbs rs1 rs2 rd sbext } +rv32i[sbseti] = { alu zbs rs1 rd shimm5 sbset } +rv32i[sbclri] = { alu zbs rs1 rd shimm5 sbclr } +rv32i[sbinvi] = { alu zbs rs1 rd shimm5 sbinv } +rv32i[sbexti] = { alu zbs rs1 rd shimm5 sbext } +rv32i[sh1add] = { alu zba rs1 rs2 rd sh1add} +rv32i[sh2add] = { alu zba rs1 rs2 rd sh2add} +rv32i[sh3add] = { alu zba rs1 rs2 rd sh3add} + rv32i[mul] = { mul rs1 rs2 rd low } rv32i[mulh] = { mul rs1 rs2 rd rs1_sign rs2_sign } rv32i[mulhu] = { mul rs1 rs2 rd } rv32i[mulhsu] = { mul rs1 rs2 rd rs1_sign } +rv32i[bext] = { mul zbe rs1 rs2 rd bext } +rv32i[bdep] = { mul zbe rs1 rs2 rd bdep } +rv32i[clmul] = { mul zbc rs1 rs2 rd clmul } +rv32i[clmulh] = { mul zbc rs1 rs2 rd clmulh} +rv32i[clmulr] = { mul zbc rs1 rs2 rd clmulr} -rv32i[div] = { div rs1 rs2 rd } -rv32i[divu] = { div rs1 rs2 rd unsign } -rv32i[rem] = { div rs1 rs2 rd rem} -rv32i[remu] = { div rs1 rs2 rd unsign rem} +rv32i[crc32_b] = { mul zbr rs1 rd crc32_b} +rv32i[crc32_h] = { mul zbr rs1 rd crc32_h} +rv32i[crc32_w] = { mul zbr rs1 rd crc32_w} +rv32i[crc32c_b] = { mul zbr rs1 rd crc32c_b} +rv32i[crc32c_h] = { mul zbr rs1 rd crc32c_h} +rv32i[crc32c_w] = { mul zbr rs1 rd crc32c_w} + +rv32i[bfp] = { mul zbf rs1 rs2 rd bfp } + +rv32i[grev] = { mul zbp rs1 rs2 rd grev } + +rv32i[grevi{0-23}] = { mul zbp rs1 rd shimm5 grev } +rv32i[grevi{25-30}] = { mul zbp rs1 rd shimm5 grev } + +rv32i[rev8] = { alu zbb zbp rs1 rd shimm5 grev } # grevi24 +rv32i[rev] = { alu zbb zbp rs1 rd shimm5 grev } # grevi31 + +rv32i[gorc] = { mul zbp rs1 rs2 rd gorc } + +rv32i[gorci{0-6}] = { mul zbp rs1 rd shimm5 gorc } +rv32i[gorci{8-15}] = { mul zbp rs1 rd shimm5 gorc } +rv32i[gorci{17-31}] = { mul zbp rs1 rd shimm5 gorc } + +rv32i[orc_b] = { alu zbb zbp rs1 rd shimm5 gorc } # gorci7 +rv32i[orc16] = { alu zbb zbp rs1 rd shimm5 gorc } # gorci16 + + +rv32i[shfl] = { mul zbp rs1 rs2 rd shfl } +rv32i[shfli] = { mul zbp rs1 rd shimm5 shfl } + +rv32i[unshfl] = { mul zbp rs1 rs2 rd unshfl} +rv32i[unshfli] = { mul zbp rs1 rd shimm5 unshfl} + + +rv32i[div] = { div rs1 rs2 rd } +rv32i[divu] = { div rs1 rs2 rd unsign } +rv32i[rem] = { div rs1 rs2 rd rem} +rv32i[remu] = { div rs1 rs2 rd unsign rem} rv32i[add] = { alu rs1 rs2 rd add pm_alu } rv32i[addi] = { alu rs1 imm12 rd add pm_alu } @@ -321,3 +579,4 @@ rv32i[csrwi] = { alu rd csr_write csr_imm } .end + diff --git a/design/dec/el2_dec.sv b/design/dec/el2_dec.sv index de2659a..d22997a 100644 --- a/design/dec/el2_dec.sv +++ b/design/dec/el2_dec.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -33,18 +33,20 @@ import el2_pkg::*; `include "el2_param.vh" ) ( - input logic clk, - input logic free_clk, - input logic active_clk, + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in. + input logic free_clk, // Clock always. Through two clock headers. For flops without second clock header built in. + input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in. - input logic lsu_fastint_stall_any, // needed by lsu for 2nd pass of dma with ecc correction, stall next cycle + input logic lsu_fastint_stall_any, // needed by lsu for 2nd pass of dma with ecc correction, stall next cycle -// fast interrupt - output logic dec_extint_stall, + output logic dec_extint_stall, // Stall on external interrupt - output logic dec_i0_decode_d, + output logic dec_i0_decode_d, // Valid instruction at D-stage and not blocked output logic dec_pause_state_cg, // to top for active state clock gating + output logic dec_tlu_core_empty, + input logic rst_l, // reset, active low input logic [31:1] rst_vec, // reset vector, from core pins @@ -59,44 +61,44 @@ import el2_pkg::*; output logic o_cpu_run_ack, // Run request ack output logic o_debug_mode_status, // Core to the PMU that core is in debug mode. When core is in debug mode, the PMU should refrain from sendng a halt or run request - input logic [31:4] core_id, // CORE ID - // - // external MPC halt/run interface - input logic mpc_debug_halt_req, // Async halt request - input logic mpc_debug_run_req, // Async run request - input logic mpc_reset_run_req, // Run/halt after reset - output logic mpc_debug_halt_ack, // Halt ack - output logic mpc_debug_run_ack, // Run ack - output logic debug_brkpt_status, // debug breakpoint + input logic [31:4] core_id, // CORE ID - input logic exu_pmu_i0_br_misp, // slot 0 branch misp + // external MPC halt/run interface + input logic mpc_debug_halt_req, // Async halt request + input logic mpc_debug_run_req, // Async run request + input logic mpc_reset_run_req, // Run/halt after reset + output logic mpc_debug_halt_ack, // Halt ack + output logic mpc_debug_run_ack, // Run ack + output logic debug_brkpt_status, // debug breakpoint + + input logic exu_pmu_i0_br_misp, // slot 0 branch misp input logic exu_pmu_i0_br_ataken, // slot 0 branch actual taken input logic exu_pmu_i0_pc4, // slot 0 4 byte branch - input logic lsu_nonblock_load_valid_m, // valid nonblock load at m + input logic lsu_nonblock_load_valid_m, // valid nonblock load at m input logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_m, // -> corresponding tag - input logic lsu_nonblock_load_inv_r, // invalidate request for nonblock load r + input logic lsu_nonblock_load_inv_r, // invalidate request for nonblock load r input logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_r, // -> corresponding tag - input logic lsu_nonblock_load_data_valid, // valid nonblock load data back - input logic lsu_nonblock_load_data_error, // nonblock load bus error - input logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // -> corresponding tag - input logic [31:0] lsu_nonblock_load_data, // nonblock load data + input logic lsu_nonblock_load_data_valid, // valid nonblock load data back + input logic lsu_nonblock_load_data_error, // nonblock load bus error + input logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // -> corresponding tag + input logic [31:0] lsu_nonblock_load_data, // nonblock load data - input logic lsu_pmu_bus_trxn, // D side bus transaction - input logic lsu_pmu_bus_misaligned, // D side bus misaligned - input logic lsu_pmu_bus_error, // D side bus error - input logic lsu_pmu_bus_busy, // D side bus busy - input logic lsu_pmu_misaligned_m, // D side load or store misaligned - input logic lsu_pmu_load_external_m, // D side bus load - input logic lsu_pmu_store_external_m, // D side bus store + input logic lsu_pmu_bus_trxn, // D side bus transaction + input logic lsu_pmu_bus_misaligned, // D side bus misaligned + input logic lsu_pmu_bus_error, // D side bus error + input logic lsu_pmu_bus_busy, // D side bus busy + input logic lsu_pmu_misaligned_m, // D side load or store misaligned + input logic lsu_pmu_load_external_m, // D side bus load + input logic lsu_pmu_store_external_m, // D side bus store input logic dma_pmu_dccm_read, // DMA DCCM read input logic dma_pmu_dccm_write, // DMA DCCM write input logic dma_pmu_any_read, // DMA read input logic dma_pmu_any_write, // DMA write - input logic [31:1] lsu_fir_addr, // Fast int address - input logic [1:0] lsu_fir_error, // Fast int lookup error + input logic [31:1] lsu_fir_addr, // Fast int address + input logic [1:0] lsu_fir_error, // Fast int lookup error input logic ifu_pmu_instr_aligned, // aligned instructions input logic ifu_pmu_fetch_stall, // fetch unit stalled @@ -110,28 +112,29 @@ import el2_pkg::*; input logic ifu_iccm_rd_ecc_single_err, // ICCM single bit error input logic [3:0] lsu_trigger_match_m, - input logic dbg_cmd_valid, // debugger abstract command valid - input logic dbg_cmd_write, // command is a write - input logic [1:0] dbg_cmd_type, // command type - input logic [31:0] dbg_cmd_addr, // command address - input logic [1:0] dbg_cmd_wrdata, // command write data, for fence/fence_i + input logic dbg_cmd_valid, // debugger abstract command valid + input logic dbg_cmd_write, // command is a write + input logic [1:0] dbg_cmd_type, // command type + input logic [31:0] dbg_cmd_addr, // command address + input logic [1:0] dbg_cmd_wrdata, // command write data, for fence/fence_i - input logic ifu_i0_icaf, // icache access fault - input logic [1:0] ifu_i0_icaf_type, + input logic ifu_i0_icaf, // icache access fault + input logic [1:0] ifu_i0_icaf_type, // icache access fault type - input logic ifu_i0_icaf_f1, // i0 has access fault on second fetch group - input logic ifu_i0_dbecc, // icache/iccm double-bit error + input logic ifu_i0_icaf_second, // i0 has access fault on second 2B of 4B inst + input logic ifu_i0_dbecc, // icache/iccm double-bit error - input logic lsu_idle_any, // lsu idle for halting + input logic lsu_idle_any, // lsu idle for halting - input el2_br_pkt_t i0_brp, // branch packet + input el2_br_pkt_t i0_brp, // branch packet input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index, // BP index - input logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr, // BP FGHR - input logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag, // BP tag + input logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr, // BP FGHR + input logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag, // BP tag + input logic [$clog2(pt.BTB_SIZE)-1:0] ifu_i0_fa_index, // Fully associt btb index - input el2_lsu_error_pkt_t lsu_error_pkt_r, // LSU exception/error packet - input logic lsu_single_ecc_error_incr, // LSU inc SB error counter + input el2_lsu_error_pkt_t lsu_error_pkt_r, // LSU exception/error packet + input logic lsu_single_ecc_error_incr, // LSU inc SB error counter input logic lsu_imprecise_error_load_any, // LSU imprecise load bus error input logic lsu_imprecise_error_store_any, // LSU imprecise store bus error @@ -178,7 +181,7 @@ import el2_pkg::*; input logic [70:0] ifu_ic_debug_rd_data, // diagnostic icache read data input logic ifu_ic_debug_rd_data_valid, // diagnostic icache read data valid - output el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt, // packet of DICAWICS, DICAD0/1, DICAGO info for icache diagnostics + output el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt, // packet of DICAWICS, DICAD0/1, DICAGO info for icache diagnostics // Debug start @@ -189,11 +192,11 @@ import el2_pkg::*; output logic dec_tlu_dbg_halted, // Core is halted and ready for debug command output logic dec_tlu_debug_mode, // Core is in debug mode output logic dec_tlu_resume_ack, // Resume acknowledge - output logic dec_tlu_flush_noredir_r, // Tell fetch to idle on this flush - output logic dec_tlu_mpc_halted_only, // Core is halted only due to MPC - output logic dec_tlu_flush_leak_one_r, // single step - output logic dec_tlu_flush_err_r, // iside perr/ecc rfpc - output logic [31:2] dec_tlu_meihap, // Fast ext int base + output logic dec_tlu_flush_noredir_r, // Tell fetch to idle on this flush + output logic dec_tlu_mpc_halted_only, // Core is halted only due to MPC + output logic dec_tlu_flush_leak_one_r, // single step + output logic dec_tlu_flush_err_r, // iside perr/ecc rfpc + output logic [31:2] dec_tlu_meihap, // Fast ext int base output logic dec_debug_wdata_rs1_d, // insert debug write data into rs1 at decode @@ -204,15 +207,17 @@ import el2_pkg::*; output el2_trigger_pkt_t [3:0] trigger_pkt_any, // info needed by debug trigger blocks - output logic dec_tlu_force_halt, // halt has been forced + output logic dec_tlu_force_halt, // halt has been forced // Debug end // branch info from pipe0 for errors or counter updates - input logic [1:0] exu_i0_br_hist_r, // history - input logic exu_i0_br_error_r, // error - input logic exu_i0_br_start_error_r, // start error - input logic exu_i0_br_valid_r, // valid - input logic exu_i0_br_mp_r, // mispredict - input logic exu_i0_br_middle_r, // middle of bank + input logic [1:0] exu_i0_br_hist_r, // history + input logic exu_i0_br_error_r, // error + input logic exu_i0_br_start_error_r, // start error + input logic exu_i0_br_valid_r, // valid + input logic exu_i0_br_mp_r, // mispredict + input logic exu_i0_br_middle_r, // middle of bank + + // branch info from pipe1 for errors or counter updates input logic exu_i0_br_way_r, // way hit or repl @@ -224,61 +229,65 @@ import el2_pkg::*; output logic [31:0] dec_i0_immed_d, // immediate data output logic [12:1] dec_i0_br_immed_d, // br immediate data - output el2_alu_pkt_t i0_ap, // alu packet + output el2_alu_pkt_t i0_ap, // alu packet output logic dec_i0_alu_decode_d, // schedule on D-stage alu + output logic dec_i0_branch_d, // Branch in D-stage output logic dec_i0_select_pc_d, // select pc onto rs1 for jal's output logic [31:1] dec_i0_pc_d, // pc's at decode - output logic [1:0] dec_i0_rs1_bypass_en_d, // rs1 bypass enable - output logic [1:0] dec_i0_rs2_bypass_en_d, // rs2 bypass enable + output logic [3:0] dec_i0_rs1_bypass_en_d, // rs1 bypass enable + output logic [3:0] dec_i0_rs2_bypass_en_d, // rs2 bypass enable - output logic [31:0] dec_i0_rs1_bypass_data_d, // rs1 bypass data - output logic [31:0] dec_i0_rs2_bypass_data_d, // rs2 bypass data + output logic [31:0] dec_i0_result_r, // Result R-stage - output el2_lsu_pkt_t lsu_p, // lsu packet - output el2_mul_pkt_t mul_p, // mul packet - output el2_div_pkt_t div_p, // div packet - output logic dec_div_cancel, // cancel divide operation + output el2_lsu_pkt_t lsu_p, // lsu packet + output logic dec_qual_lsu_d, // LSU instruction at D. Use to quiet LSU operands + output el2_mul_pkt_t mul_p, // mul packet + output el2_div_pkt_t div_p, // div packet + output logic dec_div_cancel, // cancel divide operation - output logic [11:0] dec_lsu_offset_d, // 12b offset for load/store addresses + output logic [11:0] dec_lsu_offset_d, // 12b offset for load/store addresses - output logic dec_csr_ren_d, // csr read enable + output logic dec_csr_ren_d, // CSR read enable + output logic [31:0] dec_csr_rddata_d, // CSR read data + output logic dec_tlu_flush_lower_r, // tlu flush due to late mp, exception, rfpc, or int + output logic dec_tlu_flush_lower_wb, + output logic [31:1] dec_tlu_flush_path_r, // tlu flush target + output logic dec_tlu_i0_kill_writeb_r, // I0 is flushed, don't writeback any results to arch state + output logic dec_tlu_fence_i_r, // flush is a fence_i rfnpc, flush icache - output logic dec_tlu_flush_lower_r, // tlu flush due to late mp, exception, rfpc, or int - output logic [31:1] dec_tlu_flush_path_r, // tlu flush target - output logic dec_tlu_i0_kill_writeb_r, // I0 is flushed, don't writeback any results to arch state - output logic dec_tlu_fence_i_r, // flush is a fence_i rfnpc, flush icache + output logic [31:1] pred_correct_npc_x, // npc if prediction is correct at e2 stage - output logic [31:1] pred_correct_npc_x, // npc if prediction is correct at e2 stage + output el2_br_tlu_pkt_t dec_tlu_br0_r_pkt, // slot 0 branch predictor update packet - output el2_br_tlu_pkt_t dec_tlu_br0_r_pkt, // slot 0 branch predictor update packet - - output logic dec_tlu_perfcnt0, // toggles when slot0 perf counter 0 has an event inc - output logic dec_tlu_perfcnt1, // toggles when slot0 perf counter 1 has an event inc - output logic dec_tlu_perfcnt2, // toggles when slot0 perf counter 2 has an event inc - output logic dec_tlu_perfcnt3, // toggles when slot0 perf counter 3 has an event inc + output logic dec_tlu_perfcnt0, // toggles when slot0 perf counter 0 has an event inc + output logic dec_tlu_perfcnt1, // toggles when slot0 perf counter 1 has an event inc + output logic dec_tlu_perfcnt2, // toggles when slot0 perf counter 2 has an event inc + output logic dec_tlu_perfcnt3, // toggles when slot0 perf counter 3 has an event inc output el2_predict_pkt_t dec_i0_predict_p_d, // prediction packet to alus output logic [pt.BHT_GHR_SIZE-1:0] i0_predict_fghr_d, // DEC predict fghr output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] i0_predict_index_d, // DEC predict index output logic [pt.BTB_BTAG_SIZE-1:0] i0_predict_btag_d, // DEC predict branch tag + output logic [$clog2(pt.BTB_SIZE)-1:0] dec_fa_error_index, // Fully associt btb error index + output logic dec_lsu_valid_raw_d, - output logic [31:0] dec_tlu_mrac_ff, // CSR for memory region control + output logic [31:0] dec_tlu_mrac_ff, // CSR for memory region control output logic [1:0] dec_data_en, // clock-gate control logic output logic [1:0] dec_ctl_en, input logic [15:0] ifu_i0_cinst, // 16b compressed instruction - output el2_trace_pkt_t rv_trace_pkt, // trace packet + output el2_trace_pkt_t trace_rv_trace_pkt, // trace packet // feature disable from mfdc - output logic dec_tlu_external_ldfwd_disable, // disable external load forwarding + output logic dec_tlu_external_ldfwd_disable, // disable external load forwarding output logic dec_tlu_sideeffect_posted_disable, // disable posted stores to side-effect address output logic dec_tlu_core_ecc_disable, // disable core ECC output logic dec_tlu_bpred_disable, // disable branch prediction @@ -291,16 +300,17 @@ import el2_pkg::*; output logic dec_tlu_lsu_clk_override, // override load/store clock domain gating output logic dec_tlu_bus_clk_override, // override bus clock domain gating output logic dec_tlu_pic_clk_override, // override PIC clock domain gating + output logic dec_tlu_picio_clk_override, // override PICIO clock domain gating output logic dec_tlu_dccm_clk_override, // override DCCM clock domain gating output logic dec_tlu_icm_clk_override, // override ICCM clock domain gating output logic dec_tlu_i0_commit_cmt, // committed i0 instruction - input logic scan_mode + input logic scan_mode // Flop scan mode control ); - logic dec_tlu_dec_clk_override; // to and from dec blocks + logic dec_tlu_dec_clk_override; // to and from dec blocks logic clk_override; logic dec_ib0_valid_d; @@ -310,26 +320,26 @@ import el2_pkg::*; logic dec_pmu_presync_stall; logic dec_pmu_postsync_stall; - logic dec_tlu_wr_pause_r; // CSR write to pause reg is at R. + logic dec_tlu_wr_pause_r; // CSR write to pause reg is at R. logic [4:0] dec_i0_rs1_d; logic [4:0] dec_i0_rs2_d; logic [31:0] dec_i0_instr_d; + logic dec_tlu_trace_disable; logic dec_tlu_pipelining_disable; logic [4:0] dec_i0_waddr_r; logic dec_i0_wen_r; logic [31:0] dec_i0_wdata_r; - logic dec_csr_wen_r; // csr write enable at wb - logic [11:0] dec_csr_wraddr_r; // write address for csryes - logic [31:0] dec_csr_wrdata_r; // csr write data at wb + logic dec_csr_wen_r; // csr write enable at wb + logic [11:0] dec_csr_wraddr_r; // write address for csryes + logic [31:0] dec_csr_wrdata_r; // csr write data at wb - logic [11:0] dec_csr_rdaddr_d; // read address for csr - logic [31:0] dec_csr_rddata_d; // csr read data at wb - logic dec_csr_legal_d; // csr indicates legal operation + logic [11:0] dec_csr_rdaddr_d; // read address for csr + logic dec_csr_legal_d; // csr indicates legal operation logic dec_csr_wen_unq_d; // valid csr with write - for csr legal logic dec_csr_any_unq_d; // valid csr - for csr legal @@ -347,7 +357,7 @@ import el2_pkg::*; logic dec_i0_icaf_d; logic dec_i0_dbecc_d; - logic dec_i0_icaf_f1_d; + logic dec_i0_icaf_second_d; logic [3:0] dec_i0_trigger_match_d; logic dec_debug_fence_d; logic dec_nonblock_load_wen; @@ -357,30 +367,29 @@ import el2_pkg::*; logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] dec_i0_bp_index; logic [pt.BHT_GHR_SIZE-1:0] dec_i0_bp_fghr; logic [pt.BTB_BTAG_SIZE-1:0] dec_i0_bp_btag; + logic [$clog2(pt.BTB_SIZE)-1:0] dec_i0_bp_fa_index; // Fully associt btb index logic [31:1] dec_tlu_i0_pc_r; logic dec_tlu_i0_kill_writeb_wb; - logic dec_tlu_flush_lower_wb; logic dec_tlu_i0_valid_r; logic dec_pause_state; - logic [1:0] dec_i0_icaf_type_d; // i0 instruction access fault type + logic [1:0] dec_i0_icaf_type_d; // i0 instruction access fault type logic dec_tlu_flush_extint; // Fast ext int started - logic [31:0] dec_i0_inst_wb1; - logic [31:1] dec_i0_pc_wb1; + logic [31:0] dec_i0_inst_wb; + logic [31:1] dec_i0_pc_wb; logic dec_tlu_i0_valid_wb1, dec_tlu_int_valid_wb1; logic [4:0] dec_tlu_exc_cause_wb1; logic [31:0] dec_tlu_mtval_wb1; logic dec_tlu_i0_exc_valid_wb1; logic [4:0] div_waddr_wb; + logic dec_div_active; - logic dec_div_active; // non-block divide is active - - + logic dec_debug_valid_d; assign clk_override = dec_tlu_dec_clk_override; @@ -419,14 +428,17 @@ import el2_pkg::*; // trace - assign rv_trace_pkt.rv_i_insn_ip = dec_i0_inst_wb1[31:0]; - assign rv_trace_pkt.rv_i_address_ip = { dec_i0_pc_wb1[31:1], 1'b0}; - assign rv_trace_pkt.rv_i_valid_ip = {dec_tlu_int_valid_wb1, // always int - dec_tlu_i0_valid_wb1 | dec_tlu_i0_exc_valid_wb1}; - assign rv_trace_pkt.rv_i_exception_ip = {dec_tlu_int_valid_wb1, dec_tlu_i0_exc_valid_wb1}; - assign rv_trace_pkt.rv_i_ecause_ip = dec_tlu_exc_cause_wb1[4:0]; // replicate across ports - assign rv_trace_pkt.rv_i_interrupt_ip = {dec_tlu_int_valid_wb1,1'b0}; - assign rv_trace_pkt.rv_i_tval_ip = dec_tlu_mtval_wb1[31:0]; // replicate across ports + assign trace_rv_trace_pkt.trace_rv_i_insn_ip = dec_i0_inst_wb[31:0]; + assign trace_rv_trace_pkt.trace_rv_i_address_ip = { dec_i0_pc_wb[31:1], 1'b0}; + + assign trace_rv_trace_pkt.trace_rv_i_valid_ip = dec_tlu_int_valid_wb1 | dec_tlu_i0_valid_wb1 | dec_tlu_i0_exc_valid_wb1; + assign trace_rv_trace_pkt.trace_rv_i_exception_ip = dec_tlu_int_valid_wb1 | dec_tlu_i0_exc_valid_wb1; + assign trace_rv_trace_pkt.trace_rv_i_ecause_ip = dec_tlu_exc_cause_wb1[4:0]; // replicate across ports + assign trace_rv_trace_pkt.trace_rv_i_interrupt_ip = dec_tlu_int_valid_wb1; + assign trace_rv_trace_pkt.trace_rv_i_tval_ip = dec_tlu_mtval_wb1[31:0]; // replicate across ports + + + // end trace diff --git a/design/dec/el2_dec_decode_ctl.sv b/design/dec/el2_dec_decode_ctl.sv index 2a30241..1878081 100644 --- a/design/dec/el2_dec_decode_ctl.sv +++ b/design/dec/el2_dec_decode_ctl.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,16 +20,18 @@ import el2_pkg::*; `include "el2_param.vh" ) ( + input logic dec_tlu_trace_disable, + input logic dec_debug_valid_d, - input logic dec_tlu_flush_extint, + input logic dec_tlu_flush_extint, // Flush external interrupt - input logic dec_tlu_force_halt, // invalidate nonblock load cam on a force halt event + input logic dec_tlu_force_halt, // invalidate nonblock load cam on a force halt event - output logic dec_extint_stall, + output logic dec_extint_stall, // Stall from external interrupt - input logic [15:0] ifu_i0_cinst, // 16b compressed instruction - output logic [31:0] dec_i0_inst_wb1, // 32b instruction at wb+1 for trace encoder - output logic [31:1] dec_i0_pc_wb1, // 31b pc at wb+1 for trace encoder + input logic [15:0] ifu_i0_cinst, // 16b compressed instruction + output logic [31:0] dec_i0_inst_wb, // 32b instruction at wb+1 for trace encoder + output logic [31:1] dec_i0_pc_wb, // 31b pc at wb+1 for trace encoder input logic lsu_nonblock_load_valid_m, // valid nonblock load at m @@ -40,8 +42,6 @@ import el2_pkg::*; input logic lsu_nonblock_load_data_error, // nonblock load bus error input logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // -> corresponding tag - input logic [31:0] lsu_nonblock_load_data, // nonblock load data - input logic [3:0] dec_i0_trigger_match_d, // i0 decode trigger matches @@ -59,17 +59,16 @@ import el2_pkg::*; input logic [1:0] dbg_cmd_wrdata, // disambiguate fence, fence_i input logic dec_i0_icaf_d, // icache access fault - input logic dec_i0_icaf_f1_d, // i0 instruction access fault at decode for f1 fetch group + input logic dec_i0_icaf_second_d, // i0 instruction access fault on second 2B of 4B inst input logic [1:0] dec_i0_icaf_type_d, // i0 instruction access fault type input logic dec_i0_dbecc_d, // icache/iccm double-bit error - input el2_br_pkt_t dec_i0_brp, // branch packet - input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] dec_i0_bp_index, // i0 branch index - input logic [pt.BHT_GHR_SIZE-1:0] dec_i0_bp_fghr, // BP FGHR + input el2_br_pkt_t dec_i0_brp, // branch packet + input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] dec_i0_bp_index, // i0 branch index + input logic [pt.BHT_GHR_SIZE-1:0] dec_i0_bp_fghr, // BP FGHR input logic [pt.BTB_BTAG_SIZE-1:0] dec_i0_bp_btag, // BP tag - - input logic [31:1] dec_i0_pc_d, // pc + input logic [$clog2(pt.BTB_SIZE)-1:0] dec_i0_bp_fa_index, // Fully associt btb index input logic lsu_idle_any, // lsu idle: if fence instr & ~lsu_idle then stall decode @@ -107,46 +106,45 @@ import el2_pkg::*; input logic [31:0] exu_i0_result_x, // from primary alu's - input logic clk, // for rvdffe's - input logic free_clk, - input logic active_clk, // clk except for halt / pause + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in. + input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in. - input logic clk_override, // test stuff - input logic rst_l, + input logic clk_override, // Override non-functional clock gating + input logic rst_l, // Flop reset - output logic dec_i0_rs1_en_d, // rs1 enable at decode - output logic dec_i0_rs2_en_d, + output logic dec_i0_rs1_en_d, // rs1 enable at decode + output logic dec_i0_rs2_en_d, // rs2 enable at decode - output logic [4:0] dec_i0_rs1_d, // rs1 logical source - output logic [4:0] dec_i0_rs2_d, + output logic [4:0] dec_i0_rs1_d, // rs1 logical source + output logic [4:0] dec_i0_rs2_d, // rs2 logical source output logic [31:0] dec_i0_immed_d, // 32b immediate data decode output logic [12:1] dec_i0_br_immed_d, // 12b branch immediate - output el2_alu_pkt_t i0_ap, // alu packets + output el2_alu_pkt_t i0_ap, // alu packets - output logic dec_i0_decode_d, // i0 decode - - output logic dec_i0_alu_decode_d, // decode to D-stage alu - - output logic [31:0] dec_i0_rs1_bypass_data_d, // i0 rs1 bypass data - output logic [31:0] dec_i0_rs2_bypass_data_d, // i0 rs2 bypass data + output logic dec_i0_decode_d, // i0 decode + output logic dec_i0_alu_decode_d, // decode to D-stage alu + output logic dec_i0_branch_d, // Branch in D-stage output logic [4:0] dec_i0_waddr_r, // i0 logical source to write to gpr's output logic dec_i0_wen_r, // i0 write enable output logic [31:0] dec_i0_wdata_r, // i0 write data - output logic dec_i0_select_pc_d, // i0 select pc for rs1 - branches + output logic dec_i0_select_pc_d, // i0 select pc for rs1 - branches - output logic [1:0] dec_i0_rs1_bypass_en_d, // i0 rs1 bypass enable - output logic [1:0] dec_i0_rs2_bypass_en_d, // i0 rs2 bypass enable + output logic [3:0] dec_i0_rs1_bypass_en_d, // i0 rs1 bypass enable + output logic [3:0] dec_i0_rs2_bypass_en_d, // i0 rs2 bypass enable + output logic [31:0] dec_i0_result_r, // Result R-stage output el2_lsu_pkt_t lsu_p, // load/store packet + output logic dec_qual_lsu_d, // LSU instruction at D. Use to quiet LSU operands output el2_mul_pkt_t mul_p, // multiply packet @@ -180,6 +178,8 @@ import el2_pkg::*; output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] i0_predict_index_d, // i0 predict index output logic [pt.BTB_BTAG_SIZE-1:0] i0_predict_btag_d, // i0_predict branch tag + output logic [$clog2(pt.BTB_SIZE)-1:0] dec_fa_error_index, // Fully associt btb error index + output logic [1:0] dec_data_en, // clock-gating logic output logic [1:0] dec_ctl_en, @@ -316,7 +316,7 @@ import el2_pkg::*; logic [3:0] i0_pipe_en; logic i0_r_ctl_en, i0_x_ctl_en, i0_wb_ctl_en; - logic i0_x_data_en, i0_r_data_en, i0_wb_data_en, i0_wb1_data_en; + logic i0_x_data_en, i0_r_data_en, i0_wb_data_en; logic debug_fence_i; logic debug_fence; @@ -362,6 +362,17 @@ import el2_pkg::*; logic flush_final_r; + logic bitmanip_zbb_legal; + logic bitmanip_zbs_legal; + logic bitmanip_zbe_legal; + logic bitmanip_zbc_legal; + logic bitmanip_zbp_legal; + logic bitmanip_zbr_legal; + logic bitmanip_zbf_legal; + logic bitmanip_zba_legal; + logic bitmanip_zbb_zbp_legal; + logic bitmanip_legal; + logic data_gate_en; logic data_gate_clk; @@ -401,7 +412,6 @@ import el2_pkg::*; logic [12:1] last_br_immed_x; - logic [24:7] div_inst; logic [31:0] i0_inst_d; logic [31:0] i0_inst_x; logic [31:0] i0_inst_r; @@ -411,39 +421,34 @@ import el2_pkg::*; logic [31:1] i0_pc_wb; logic i0_wb_en; - logic i0_wb1_en; + + logic trace_enable; + + logic debug_valid_x; el2_inst_pkt_t i0_itype; el2_reg_pkt_t i0r; + rvdffie #(8) misc1ff (.*, + .clk(free_l2clk), + .din( {leak1_i1_stall_in,leak1_i0_stall_in,dec_tlu_flush_extint,pause_state_in ,dec_tlu_wr_pause_r, tlu_wr_pause_r1,illegal_lockout_in,ps_stall_in}), + .dout({leak1_i1_stall, leak1_i0_stall, dec_extint_stall, pause_state, tlu_wr_pause_r1,tlu_wr_pause_r2,illegal_lockout, ps_stall }) + ); + rvdffie #(8) misc2ff (.*, + .clk(free_l2clk), + .din( {lsu_trigger_match_m[3:0],lsu_pmu_misaligned_m,div_active_in,exu_flush_final, dec_debug_valid_d}), + .dout({lsu_trigger_match_r[3:0],lsu_pmu_misaligned_r,div_active, flush_final_r, debug_valid_x}) + ); - // Start - Data gating {{ - - - assign data_gate_en = (dec_tlu_wr_pause_r ^ tlu_wr_pause_r1 ) | // replaces free_clk - (tlu_wr_pause_r1 ^ tlu_wr_pause_r2 ) | // replaces free_clk - (dec_tlu_flush_extint ^ dec_extint_stall ) | - (leak1_i1_stall_in ^ leak1_i1_stall ) | // replaces free_clk - (leak1_i0_stall_in ^ leak1_i0_stall ) | // replaces free_clk - (pause_state_in ^ pause_state ) | // replaces free_clk - (ps_stall_in ^ ps_stall ) | // replaces free_clk - (exu_flush_final ^ flush_final_r ) | // replaces free_clk - (illegal_lockout_in ^ illegal_lockout ); // replaces active_clk - - rvclkhdr data_gated_cgc (.*, .en(data_gate_en), .l1clk(data_gate_clk)); - - // End - Data gating }} - - - +if(pt.BTB_ENABLE==1) begin // branch prediction // in leak1_mode, ignore any predictions for i0, treat branch as if we haven't seen it before // in leak1 mode, also ignore branch errors for i0 - assign i0_brp_valid = dec_i0_brp.valid & ~leak1_mode; + assign i0_brp_valid = dec_i0_brp.valid & ~leak1_mode & ~i0_icaf_d; assign dec_i0_predict_p_d.misp = '0; assign dec_i0_predict_p_d.ataken = '0; @@ -460,7 +465,7 @@ import el2_pkg::*; // no toffset error for a pret assign i0_br_toffset_error = i0_brp_valid & dec_i0_brp.hist[1] & (dec_i0_brp.toffset[11:0] != i0_br_offset[11:0]) & ~i0_pret_raw; - assign i0_ret_error = i0_brp_valid & dec_i0_brp.ret & ~i0_pret_raw; + assign i0_ret_error = i0_brp_valid & (dec_i0_brp.ret ^ i0_pret_raw); assign i0_br_error = dec_i0_brp.br_error | i0_notbr_error | i0_br_toffset_error | i0_ret_error; assign dec_i0_predict_p_d.br_error = i0_br_error & i0_legal_decode_d & ~leak1_mode; assign dec_i0_predict_p_d.br_start_error = dec_i0_brp.br_start_error & i0_legal_decode_d & ~leak1_mode; @@ -472,7 +477,42 @@ import el2_pkg::*; assign i0_predict_fghr_d[pt.BHT_GHR_SIZE-1:0] = dec_i0_bp_fghr[pt.BHT_GHR_SIZE-1:0]; assign dec_i0_predict_p_d.way = dec_i0_brp.way; + + if(pt.BTB_FULLYA) begin + logic btb_error_found, btb_error_found_f; + logic [$clog2(pt.BTB_SIZE)-1:0] fa_error_index_ns; + + assign btb_error_found = (i0_br_error_all | btb_error_found_f) & ~dec_tlu_flush_lower_r; + assign fa_error_index_ns = (i0_br_error_all & ~btb_error_found_f) ? dec_i0_bp_fa_index : dec_fa_error_index; + + rvdff #($clog2(pt.BTB_SIZE)+1) btberrorfa_f (.*, .clk(active_clk), + .din({btb_error_found, fa_error_index_ns}), + .dout({btb_error_found_f, dec_fa_error_index})); + + + end + else + assign dec_fa_error_index = 'b0; + + // end +end // if (pt.BTB_ENABLE==1) +else begin + + always_comb begin + dec_i0_predict_p_d = '0; + dec_i0_predict_p_d.pcall = i0_pcall; // don't mark as pcall if branch error + dec_i0_predict_p_d.pja = i0_pja; + dec_i0_predict_p_d.pret = i0_pret; + dec_i0_predict_p_d.pc4 = dec_i0_pc4_d; + end + + assign i0_br_error_all = '0; + assign i0_predict_index_d = '0; + assign i0_predict_btag_d = '0; + assign i0_predict_fghr_d = '0; + assign i0_brp_valid = '0; +end // else: !if(pt.BTB_ENABLE==1) // on br error turn anything into a nop // on i0 instruction fetch access fault turn anything into a nop @@ -521,6 +561,32 @@ import el2_pkg::*; assign i0_ap.blt = i0_dp.blt; assign i0_ap.bge = i0_dp.bge; + assign i0_ap.clz = i0_dp.clz; + assign i0_ap.ctz = i0_dp.ctz; + assign i0_ap.pcnt = i0_dp.pcnt; + assign i0_ap.sext_b = i0_dp.sext_b; + assign i0_ap.sext_h = i0_dp.sext_h; + assign i0_ap.sh1add = i0_dp.sh1add; + assign i0_ap.sh2add = i0_dp.sh2add; + assign i0_ap.sh3add = i0_dp.sh3add; + assign i0_ap.zba = i0_dp.zba; + assign i0_ap.slo = i0_dp.slo; + assign i0_ap.sro = i0_dp.sro; + assign i0_ap.min = i0_dp.min; + assign i0_ap.max = i0_dp.max; + assign i0_ap.pack = i0_dp.pack; + assign i0_ap.packu = i0_dp.packu; + assign i0_ap.packh = i0_dp.packh; + assign i0_ap.rol = i0_dp.rol; + assign i0_ap.ror = i0_dp.ror; + assign i0_ap.grev = i0_dp.grev; + assign i0_ap.gorc = i0_dp.gorc; + assign i0_ap.zbb = i0_dp.zbb; + assign i0_ap.sbset = i0_dp.sbset; + assign i0_ap.sbclr = i0_dp.sbclr; + assign i0_ap.sbinv = i0_dp.sbinv; + assign i0_ap.sbext = i0_dp.sbext; + assign i0_ap.csr_write = i0_csr_write_only_d; assign i0_ap.csr_imm = i0_dp.csr_imm; assign i0_ap.jal = i0_jal; @@ -537,13 +603,18 @@ import el2_pkg::*; always_comb begin found = 0; cam_wen[NBLOAD_SIZE_MSB:0] = '0; - for (int i=0; i<32'(NBLOAD_SIZE); i++) begin + for (int i=0; i f000_1000 @@ -1324,13 +1354,13 @@ end ({32{wr_mcause_r & ~exc_or_int_valid_r}} & dec_csr_wrdata_r[31:0]) | ({32{~wr_mcause_r & ~exc_or_int_valid_r}} & mcause[31:0]) ); - rvdff #(32) mcause_ff (.*, .clk(e4e5_int_clk), .din(mcause_ns[31:0]), .dout(mcause[31:0])); + rvdffe #(32) mcause_ff (.*, .en(exc_or_int_valid_r | wr_mcause_r), .din(mcause_ns[31:0]), .dout(mcause[31:0])); // ---------------------------------------------------------------------- // MSCAUSE (RW) // [2:0] : Secondary exception Cause - `define MSCAUSE 12'h7ff + localparam MSCAUSE = 12'h7ff; - assign wr_mscause_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MSCAUSE); + assign wr_mscause_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MSCAUSE); assign ifu_mscause[3:0] = (dec_tlu_packet_r.icaf_type[1:0] == 2'b00) ? 4'b1001 : {2'b00 , dec_tlu_packet_r.icaf_type[1:0]} ; @@ -1350,9 +1380,9 @@ end // ---------------------------------------------------------------------- // MTVAL (RW) // [31:0] : Exception address if relevant - `define MTVAL 12'h343 + localparam MTVAL = 12'h343; - assign wr_mtval_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTVAL); + assign wr_mtval_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTVAL); assign mtval_capture_pc_r = exc_or_int_valid_r & (ebreak_r | (inst_acc_r & ~inst_acc_second_r) | mepc_trigger_hit_sel_pc_r) & ~take_nmi; assign mtval_capture_pc_plus2_r = exc_or_int_valid_r & (inst_acc_r & inst_acc_second_r) & ~take_nmi; assign mtval_capture_inst_r = exc_or_int_valid_r & illegal_r & ~take_nmi; @@ -1368,14 +1398,14 @@ end ({32{~take_nmi & ~wr_mtval_r & ~mtval_capture_pc_r & ~mtval_capture_inst_r & ~mtval_clear_r & ~mtval_capture_lsu_r}} & mtval[31:0]) ); - rvdff #(32) mtval_ff (.*, .clk(e4e5_int_clk), .din(mtval_ns[31:0]), .dout(mtval[31:0])); + rvdffe #(32) mtval_ff (.*, .en(tlu_flush_lower_r | wr_mtval_r), .din(mtval_ns[31:0]), .dout(mtval[31:0])); // ---------------------------------------------------------------------- // MCGC (RW) Clock gating control - // [31:9] : Reserved, reads 0x0 - // [8] : misc_clk_override + // [31:10]: Reserved, reads 0x0 + // [9] : picio_clk_override // [7] : dec_clk_override - // [6] : unused + // [6] : Unused // [5] : ifu_clk_override // [4] : lsu_clk_override // [3] : bus_clk_override @@ -1383,13 +1413,18 @@ end // [1] : dccm_clk_override // [0] : icm_clk_override // - `define MCGC 12'h7f8 - assign wr_mcgc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MCGC); + localparam MCGC = 12'h7f8; + assign wr_mcgc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCGC); - rvdffe #(9) mcgc_ff (.*, .en(wr_mcgc_r), .din(dec_csr_wrdata_r[8:0]), .dout(mcgc[8:0])); + assign mcgc_ns[9:0] = wr_mcgc_r ? {~dec_csr_wrdata_r[9], dec_csr_wrdata_r[8:0]} : mcgc_int[9:0]; + rvdffe #(10) mcgc_ff (.*, .en(wr_mcgc_r), .din(mcgc_ns[9:0]), .dout(mcgc_int[9:0])); + assign mcgc[9:0] = {~mcgc_int[9], mcgc_int[8:0]}; + + assign dec_tlu_picio_clk_override= mcgc[9]; assign dec_tlu_misc_clk_override = mcgc[8]; assign dec_tlu_dec_clk_override = mcgc[7]; + //sign dec_tlu_exu_clk_override = mcgc[6]; assign dec_tlu_ifu_clk_override = mcgc[5]; assign dec_tlu_lsu_clk_override = mcgc[4]; assign dec_tlu_bus_clk_override = mcgc[3]; @@ -1401,37 +1436,42 @@ end // MFDC (RW) Feature Disable Control // [31:19] : Reserved, reads 0x0 // [18:16] : DMA QoS Prty - // [15:12] : Reserved, reads 0x0 + // [15:13] : Reserved, reads 0x0 + // [12] : Disable trace // [11] : Disable external load forwarding // [10] : Disable dual issue // [9] : Disable pic multiple ints // [8] : Disable core ecc - // [7] : Unused, 0x0 - // [6] : Disable Sideeffect lsu posting - // [5:4] : Unused, 0x0 + // [7] : Disable secondary alu?s + // [6] : Unused, 0x0 + // [5] : Disable non-blocking loads/divides + // [4] : Disable fast divide // [3] : Disable branch prediction and return stack // [2] : Disable write buffer coalescing - // [1] : Unused, 0x0 + // [1] : Disable load misses that bypass the write buffer // [0] : Disable pipelining - Enable single instruction execution // - `define MFDC 12'h7f9 + localparam MFDC = 12'h7f9; - assign wr_mfdc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MFDC); + assign wr_mfdc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MFDC); - rvdffe #(15) mfdc_ff (.*, .en(wr_mfdc_r), .din({mfdc_ns[14:0]}), .dout(mfdc_int[14:0])); + rvdffe #(16) mfdc_ff (.*, .en(wr_mfdc_r), .din({mfdc_ns[15:0]}), .dout(mfdc_int[15:0])); -if(pt.BUILD_AXI4==1) begin : axi4 // flip poweron value of bit 6 for AXI build - assign mfdc_ns[14:0] = {~dec_csr_wrdata_r[18:16],dec_csr_wrdata_r[11:7], ~dec_csr_wrdata_r[6], dec_csr_wrdata_r[5:0]}; - assign mfdc[18:0] = {~mfdc_int[14:12], 4'b0, mfdc_int[11:7], ~mfdc_int[6], mfdc_int[5:0]}; -end -else begin - assign mfdc_ns[14:0] = {~dec_csr_wrdata_r[18:16],dec_csr_wrdata_r[11:0]}; - assign mfdc[18:0] = {~mfdc_int[14:12], 4'b0, mfdc_int[11:0]}; -end + if(pt.BUILD_AXI4==1) begin : axi4 + // flip poweron valid of bit 12 + assign mfdc_ns[15:0] = {~dec_csr_wrdata_r[18:16], dec_csr_wrdata_r[12], dec_csr_wrdata_r[11:7], ~dec_csr_wrdata_r[6], dec_csr_wrdata_r[5:0]}; + assign mfdc[18:0] = {~mfdc_int[15:13], 3'b0, mfdc_int[12], mfdc_int[11:7], ~mfdc_int[6], mfdc_int[5:0]}; + end + else begin + // flip poweron valid of bit 12 + assign mfdc_ns[15:0] = {~dec_csr_wrdata_r[18:16],dec_csr_wrdata_r[12:0]}; + assign mfdc[18:0] = {~mfdc_int[15:13], 3'b0, mfdc_int[12:0]}; + end assign dec_tlu_dma_qos_prty[2:0] = mfdc[18:16]; + assign dec_tlu_trace_disable = mfdc[12]; assign dec_tlu_external_ldfwd_disable = mfdc[11]; assign dec_tlu_core_ecc_disable = mfdc[8]; assign dec_tlu_sideeffect_posted_disable = mfdc[6]; @@ -1443,14 +1483,14 @@ end // MCPC (RW) Pause counter // [31:0] : Reads 0x0, decs in the wb register in decode_ctl - assign dec_tlu_wr_pause_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MCPC) & ~interrupt_valid_r & ~take_ext_int_start; + assign dec_tlu_wr_pause_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCPC) & ~interrupt_valid_r & ~take_ext_int_start; // ---------------------------------------------------------------------- // MRAC (RW) // [31:0] : Region Access Control Register, 16 regions, {side_effect, cachable} pairs - `define MRAC 12'h7c0 + localparam MRAC = 12'h7c0; - assign wr_mrac_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MRAC); + assign wr_mrac_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MRAC); // prevent pairs of 0x11, side_effect and cacheable assign mrac_in[31:0] = {dec_csr_wrdata_r[31], dec_csr_wrdata_r[30] & ~dec_csr_wrdata_r[31], @@ -1479,16 +1519,16 @@ end // MDEAU (WAR0) // [31:0] : Dbus Error Address Unlock register // - `define MDEAU 12'hbc0 + localparam MDEAU = 12'hbc0; - assign wr_mdeau_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MDEAU); + assign wr_mdeau_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MDEAU); // ---------------------------------------------------------------------- // MDSEAC (R) // [31:0] : Dbus Store Error Address Capture register // - `define MDSEAC 12'hfc0 + localparam MDSEAC = 12'hfc0; // only capture error bus if the MDSEAC reg is not locked assign mdseac_locked_ns = mdseac_en | (mdseac_locked_f & ~wr_mdeau_r); @@ -1502,9 +1542,9 @@ end // [0] : FW halt // [1] : Set MSTATUS[MIE] on halt - `define MPMC 12'h7c6 + localparam MPMC = 12'h7c6; - assign wr_mpmc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MPMC); + assign wr_mpmc_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MPMC); // allow the cycle of the dbg halt flush that contains the wr_mpmc_r to // set the mstatus bit potentially, use delayed version of internal dbg halt. @@ -1513,22 +1553,21 @@ end assign fw_halted_ns = (fw_halt_req | fw_halted) & ~set_mie_pmu_fw_halt; assign mpmc_b_ns[1] = wr_mpmc_r ? ~dec_csr_wrdata_r[1] : ~mpmc[1]; rvdff #(1) mpmc_ff (.*, .clk(csr_wr_clk), .din(mpmc_b_ns[1]), .dout(mpmc_b[1])); - rvdff #(1) fwh_ff (.*, .clk(free_clk), .din(fw_halted_ns), .dout(fw_halted)); assign mpmc[1] = ~mpmc_b[1]; // ---------------------------------------------------------------------- // MICECT (I-Cache error counter/threshold) // [31:27] : Icache parity error threshold // [26:0] : Icache parity error count - `define MICECT 12'h7f0 + localparam MICECT = 12'h7f0; assign csr_sat[31:27] = (dec_csr_wrdata_r[31:27] > 5'd26) ? 5'd26 : dec_csr_wrdata_r[31:27]; - assign wr_micect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MICECT); - assign micect_inc[26:0] = micect[26:0] + {26'b0, ic_perr_r_d1}; + assign wr_micect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MICECT); + assign micect_inc[26:0] = micect[26:0] + {26'b0, ic_perr_r}; assign micect_ns = wr_micect_r ? {csr_sat[31:27], dec_csr_wrdata_r[26:0]} : {micect[31:27], micect_inc[26:0]}; - rvdffe #(32) micect_ff (.*, .en(wr_micect_r | ic_perr_r_d1), .din(micect_ns[31:0]), .dout(micect[31:0])); + rvdffe #(32) micect_ff (.*, .en(wr_micect_r | ic_perr_r), .din(micect_ns[31:0]), .dout(micect[31:0])); assign mice_ce_req = |({32'hffffffff << micect[31:27]} & {5'b0, micect[26:0]}); @@ -1536,13 +1575,13 @@ end // MICCMECT (ICCM error counter/threshold) // [31:27] : ICCM parity error threshold // [26:0] : ICCM parity error count - `define MICCMECT 12'h7f1 + localparam MICCMECT = 12'h7f1; - assign wr_miccmect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MICCMECT); - assign miccmect_inc[26:0] = miccmect[26:0] + {26'b0, iccm_sbecc_r_d1 | iccm_dma_sb_error}; + assign wr_miccmect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MICCMECT); + assign miccmect_inc[26:0] = miccmect[26:0] + {26'b0, iccm_sbecc_r | iccm_dma_sb_error}; assign miccmect_ns = wr_miccmect_r ? {csr_sat[31:27], dec_csr_wrdata_r[26:0]} : {miccmect[31:27], miccmect_inc[26:0]}; - rvdffe #(32) miccmect_ff (.*, .en(wr_miccmect_r | iccm_sbecc_r_d1 | iccm_dma_sb_error), .din(miccmect_ns[31:0]), .dout(miccmect[31:0])); + rvdffe #(32) miccmect_ff (.*, .clk(free_l2clk), .en(wr_miccmect_r | iccm_sbecc_r | iccm_dma_sb_error), .din(miccmect_ns[31:0]), .dout(miccmect[31:0])); assign miccme_ce_req = |({32'hffffffff << miccmect[31:27]} & {5'b0, miccmect[26:0]}); @@ -1550,13 +1589,13 @@ end // MDCCMECT (DCCM error counter/threshold) // [31:27] : DCCM parity error threshold // [26:0] : DCCM parity error count - `define MDCCMECT 12'h7f2 + localparam MDCCMECT = 12'h7f2; - assign wr_mdccmect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MDCCMECT); + assign wr_mdccmect_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MDCCMECT); assign mdccmect_inc[26:0] = mdccmect[26:0] + {26'b0, lsu_single_ecc_error_r_d1}; assign mdccmect_ns = wr_mdccmect_r ? {csr_sat[31:27], dec_csr_wrdata_r[26:0]} : {mdccmect[31:27], mdccmect_inc[26:0]}; - rvdffe #(32) mdccmect_ff (.*, .en(wr_mdccmect_r | lsu_single_ecc_error_r_d1), .din(mdccmect_ns[31:0]), .dout(mdccmect[31:0])); + rvdffe #(32) mdccmect_ff (.*, .clk(free_l2clk), .en(wr_mdccmect_r | lsu_single_ecc_error_r_d1), .din(mdccmect_ns[31:0]), .dout(mdccmect[31:0])); assign mdccme_ce_req = |({32'hffffffff << mdccmect[31:27]} & {5'b0, mdccmect[26:0]}); @@ -1565,30 +1604,30 @@ end // MFDHT (Force Debug Halt Threshold) // [5:1] : Halt timeout threshold (power of 2) // [0] : Halt timeout enabled - `define MFDHT 12'h7ce + localparam MFDHT = 12'h7ce; - assign wr_mfdht_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MFDHT); + assign wr_mfdht_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MFDHT); assign mfdht_ns[5:0] = wr_mfdht_r ? dec_csr_wrdata_r[5:0] : mfdht[5:0]; - rvdff #(6) mfdht_ff (.*, .clk(active_clk), .din(mfdht_ns[5:0]), .dout(mfdht[5:0])); + rvdffs #(6) mfdht_ff (.*, .clk(csr_wr_clk), .en(wr_mfdht_r), .din(mfdht_ns[5:0]), .dout(mfdht[5:0])); // ---------------------------------------------------------------------- // MFDHS(RW) // [1] : LSU operation pending when debug halt threshold reached // [0] : IFU operation pending when debug halt threshold reached - `define MFDHS 12'h7cf + localparam MFDHS = 12'h7cf; - assign wr_mfdhs_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MFDHS); + assign wr_mfdhs_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MFDHS); assign mfdhs_ns[1:0] = wr_mfdhs_r ? dec_csr_wrdata_r[1:0] : ((dbg_tlu_halted & ~dbg_tlu_halted_f) ? {~lsu_idle_any_f, ~ifu_miss_state_idle_f} : mfdhs[1:0]); - rvdffs #(2) mfdhs_ff (.*, .clk(active_clk), .en(wr_mfdhs_r | dbg_tlu_halted), .din(mfdhs_ns[1:0]), .dout(mfdhs[1:0])); + rvdffs #(2) mfdhs_ff (.*, .clk(free_clk), .en(wr_mfdhs_r | dbg_tlu_halted), .din(mfdhs_ns[1:0]), .dout(mfdhs[1:0])); assign force_halt_ctr[31:0] = debug_halt_req_f ? (force_halt_ctr_f[31:0] + 32'b1) : (dbg_tlu_halted_f ? 32'b0 : force_halt_ctr_f[31:0]); - rvdffs #(32) forcehaltctr_ff (.*, .clk(active_clk), .en(mfdht[0]), .din(force_halt_ctr[31:0]), .dout(force_halt_ctr_f[31:0])); + rvdffe #(32) forcehaltctr_ff (.*, .en(mfdht[0]), .din(force_halt_ctr[31:0]), .dout(force_halt_ctr_f[31:0])); assign force_halt = mfdht[0] & |(force_halt_ctr_f[31:0] & (32'hffffffff << mfdht[5:1])); @@ -1597,9 +1636,9 @@ end // MEIVT (External Interrupt Vector Table (R/W)) // [31:10]: Base address (R/W) // [9:0] : Reserved, reads 0x0 - `define MEIVT 12'hbc8 + localparam MEIVT = 12'hbc8; - assign wr_meivt_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MEIVT); + assign wr_meivt_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEIVT); rvdffe #(22) meivt_ff (.*, .en(wr_meivt_r), .din(dec_csr_wrdata_r[31:10]), .dout(meivt[31:10])); @@ -1609,7 +1648,7 @@ end // [31:10]: Base address (R/W) // [9:2] : ClaimID (R) // [1:0] : Reserved, 0x0 - `define MEIHAP 12'hfc8 + localparam MEIHAP = 12'hfc8; assign wr_meihap_r = wr_meicpct_r; @@ -1620,9 +1659,9 @@ end // MEICURPL (R/W) // [31:4] : Reserved (read 0x0) // [3:0] : CURRPRI - Priority level of current interrupt service routine (R/W) - `define MEICURPL 12'hbcc + localparam MEICURPL = 12'hbcc; - assign wr_meicurpl_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MEICURPL); + assign wr_meicurpl_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEICURPL); assign meicurpl_ns[3:0] = wr_meicurpl_r ? dec_csr_wrdata_r[3:0] : meicurpl[3:0]; rvdff #(4) meicurpl_ff (.*, .clk(csr_wr_clk), .din(meicurpl_ns[3:0]), .dout(meicurpl[3:0])); @@ -1635,32 +1674,31 @@ end // MEICIDPL (R/W) // [31:4] : Reserved (read 0x0) // [3:0] : External Interrupt Claim ID's Priority Level Register - `define MEICIDPL 12'hbcb + localparam MEICIDPL = 12'hbcb; - assign wr_meicidpl_r = (dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MEICIDPL)) | take_ext_int_start; + assign wr_meicidpl_r = (dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEICIDPL)) | take_ext_int_start; assign meicidpl_ns[3:0] = wr_meicpct_r ? pic_pl[3:0] : (wr_meicidpl_r ? dec_csr_wrdata_r[3:0] : meicidpl[3:0]); - rvdff #(4) meicidpl_ff (.*, .clk(free_clk), .din(meicidpl_ns[3:0]), .dout(meicidpl[3:0])); // ---------------------------------------------------------------------- // MEICPCT (Capture CLAIMID in MEIHAP and PL in MEICIDPL // [31:1] : Reserved (read 0x0) // [0] : Capture (W1, Read 0) - `define MEICPCT 12'hbca + localparam MEICPCT = 12'hbca; - assign wr_meicpct_r = (dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MEICPCT)) | take_ext_int_start; + assign wr_meicpct_r = (dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEICPCT)) | take_ext_int_start; // ---------------------------------------------------------------------- // MEIPT (External Interrupt Priority Threshold) // [31:4] : Reserved (read 0x0) // [3:0] : PRITHRESH - `define MEIPT 12'hbc9 + localparam MEIPT = 12'hbc9; - assign wr_meipt_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MEIPT); + assign wr_meipt_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MEIPT); assign meipt_ns[3:0] = wr_meipt_r ? dec_csr_wrdata_r[3:0] : meipt[3:0]; - rvdff #(4) meipt_ff (.*, .clk(active_clk), .din(meipt_ns[3:0]), .dout(meipt[3:0])); + rvdff #(4) meipt_ff (.*, .clk(csr_wr_clk), .din(meipt_ns[3:0]), .dout(meipt[3:0])); // to PIC assign dec_tlu_meipt[3:0] = meipt[3:0]; @@ -1681,7 +1719,7 @@ end // [2] : step // [1:0] : prv (0x3 for this core) // - `define DCSR 12'h7b0 + localparam DCSR = 12'h7b0; // RV has clarified that 'priority 4' in the spec means top priority. // 4. single step. 3. Debugger request. 2. Ebreak. 1. Trigger. @@ -1694,7 +1732,7 @@ end ({3{ebreak_to_debug_mode_r_d1 & ~trigger_hit_for_dscr_cause_r_d1}} & 3'b001) | ({3{trigger_hit_for_dscr_cause_r_d1}} & 3'b010)); - assign wr_dcsr_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `DCSR); + assign wr_dcsr_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DCSR); @@ -1708,14 +1746,14 @@ end (wr_dcsr_r ? {dec_csr_wrdata_r[15], 3'b0, dec_csr_wrdata_r[11:10], 1'b0, dcsr[8:6], 2'b00, nmi_in_debug_mode | dcsr[3], dec_csr_wrdata_r[2]} : {dcsr[15:4], nmi_in_debug_mode, dcsr[2]}); - rvdffe #(14) dcsr_ff (.*, .en(enter_debug_halt_req_le | wr_dcsr_r | internal_dbg_halt_mode | take_nmi), .din(dcsr_ns[15:2]), .dout(dcsr[15:2])); + rvdffe #(14) dcsr_ff (.*, .clk(free_l2clk), .en(enter_debug_halt_req_le | wr_dcsr_r | internal_dbg_halt_mode | take_nmi), .din(dcsr_ns[15:2]), .dout(dcsr[15:2])); // ---------------------------------------------------------------------- // DPC (R/W) (Only accessible in debug mode) // [31:0] : Debug PC - `define DPC 12'h7b1 + localparam DPC = 12'h7b1; - assign wr_dpc_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `DPC); + assign wr_dpc_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DPC); assign dpc_capture_npc = dbg_tlu_halted & ~dbg_tlu_halted_f & ~request_debug_mode_done; assign dpc_capture_pc = request_debug_mode_r; @@ -1734,10 +1772,10 @@ end // [19:17] : Reserved // [16:3] : Index // [2:0] : Reserved - `define DICAWICS 12'h7c8 + localparam DICAWICS = 12'h7c8; assign dicawics_ns[16:0] = {dec_csr_wrdata_r[24], dec_csr_wrdata_r[21:20], dec_csr_wrdata_r[16:3]}; - assign wr_dicawics_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `DICAWICS); + assign wr_dicawics_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAWICS); rvdffe #(17) dicawics_ff (.*, .en(wr_dicawics_r), .din(dicawics_ns[16:0]), .dout(dicawics[16:0])); @@ -1753,11 +1791,11 @@ end // [6:4] : LRU // [3:1] : Reserved // [0] : Valid - `define DICAD0 12'h7c9 + localparam DICAD0 = 12'h7c9; assign dicad0_ns[31:0] = wr_dicad0_r ? dec_csr_wrdata_r[31:0] : ifu_ic_debug_rd_data[31:0]; - assign wr_dicad0_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `DICAD0); + assign wr_dicad0_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAD0); rvdffe #(32) dicad0_ff (.*, .en(wr_dicad0_r | ifu_ic_debug_rd_data_valid), .din(dicad0_ns[31:0]), .dout(dicad0[31:0])); @@ -1767,11 +1805,11 @@ end // If dicawics[array] is 0 // [63:32] : inst data // - `define DICAD0H 12'h7cc + localparam DICAD0H = 12'h7cc; assign dicad0h_ns[31:0] = wr_dicad0h_r ? dec_csr_wrdata_r[31:0] : ifu_ic_debug_rd_data[63:32]; - assign wr_dicad0h_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `DICAD0H); + assign wr_dicad0h_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAD0H); rvdffe #(32) dicad0h_ff (.*, .en(wr_dicad0h_r | ifu_ic_debug_rd_data_valid), .din(dicad0h_ns[31:0]), .dout(dicad0h[31:0])); @@ -1780,13 +1818,13 @@ if (pt.ICACHE_ECC == 1) begin // ---------------------------------------------------------------------- // DICAD1 (R/W) (Only accessible in debug mode) // [6:0] : ECC - `define DICAD1 12'h7ca + localparam DICAD1 = 12'h7ca; assign dicad1_ns[6:0] = wr_dicad1_r ? dec_csr_wrdata_r[6:0] : ifu_ic_debug_rd_data[70:64]; - assign wr_dicad1_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `DICAD1); + assign wr_dicad1_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAD1); - rvdffs #(7) dicad1_ff (.*, .clk(active_clk), .en(wr_dicad1_r | ifu_ic_debug_rd_data_valid), .din(dicad1_ns[6:0]), .dout(dicad1_raw[6:0])); + rvdffe #(.WIDTH(7), .OVERRIDE(1)) dicad1_ff (.*, .en(wr_dicad1_r | ifu_ic_debug_rd_data_valid), .din(dicad1_ns[6:0]), .dout(dicad1_raw[6:0])); assign dicad1[31:0] = {25'b0, dicad1_raw[6:0]}; @@ -1795,33 +1833,32 @@ else begin // ---------------------------------------------------------------------- // DICAD1 (R/W) (Only accessible in debug mode) // [3:0] : Parity - `define DICAD1 12'h7ca + localparam DICAD1 = 12'h7ca; assign dicad1_ns[3:0] = wr_dicad1_r ? dec_csr_wrdata_r[3:0] : ifu_ic_debug_rd_data[67:64]; - assign wr_dicad1_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `DICAD1); + assign wr_dicad1_r = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAD1); - rvdffs #(4) dicad1_ff (.*, .clk(active_clk), .en(wr_dicad1_r | ifu_ic_debug_rd_data_valid), .din(dicad1_ns[3:0]), .dout(dicad1_raw[3:0])); + rvdffs #(4) dicad1_ff (.*, .clk(free_clk), .en(wr_dicad1_r | ifu_ic_debug_rd_data_valid), .din(dicad1_ns[3:0]), .dout(dicad1_raw[3:0])); assign dicad1[31:0] = {28'b0, dicad1_raw[3:0]}; end // ---------------------------------------------------------------------- // DICAGO (R/W) (Only accessible in debug mode) // [0] : Go - `define DICAGO 12'h7cb + localparam DICAGO = 12'h7cb; if (pt.ICACHE_ECC == 1) - assign dec_tlu_ic_diag_pkt.icache_wrdata[70:0] = {dicad1[6:0], dicad0h[31:0], dicad0[31:0]}; + assign dec_tlu_ic_diag_pkt.icache_wrdata[70:0] = { dicad1[6:0], dicad0h[31:0], dicad0[31:0]}; else - assign dec_tlu_ic_diag_pkt.icache_wrdata[67:0] = {dicad1[3:0], dicad0h[31:0], dicad0[31:0]}; + assign dec_tlu_ic_diag_pkt.icache_wrdata[70:0] = {3'b0, dicad1[3:0], dicad0h[31:0], dicad0[31:0]}; assign dec_tlu_ic_diag_pkt.icache_dicawics[16:0] = dicawics[16:0]; - assign icache_rd_valid = allow_dbg_halt_csr_write & dec_csr_any_unq_d & dec_i0_decode_d & ~dec_csr_wen_unq_d & (dec_csr_rdaddr_d[11:0] == `DICAGO); - assign icache_wr_valid = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `DICAGO); + assign icache_rd_valid = allow_dbg_halt_csr_write & dec_csr_any_unq_d & dec_i0_decode_d & ~dec_csr_wen_unq_d & (dec_csr_rdaddr_d[11:0] == DICAGO); + assign icache_wr_valid = allow_dbg_halt_csr_write & dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == DICAGO); - rvdff #(2) dicgo_ff (.*, .clk(active_clk), .din({icache_rd_valid, icache_wr_valid}), .dout({icache_rd_valid_f, icache_wr_valid_f})); assign dec_tlu_ic_diag_pkt.icache_rd_valid = icache_rd_valid_f; assign dec_tlu_ic_diag_pkt.icache_wr_valid = icache_wr_valid_f; @@ -1829,9 +1866,9 @@ else // ---------------------------------------------------------------------- // MTSEL (R/W) // [1:0] : Trigger select : 00, 01, 10 are data/address triggers. 11 is inst count - `define MTSEL 12'h7a0 + localparam MTSEL = 12'h7a0; - assign wr_mtsel_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTSEL); + assign wr_mtsel_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTSEL); assign mtsel_ns[1:0] = wr_mtsel_r ? {dec_csr_wrdata_r[1:0]} : mtsel[1:0]; rvdff #(2) mtsel_ff (.*, .clk(csr_wr_clk), .din(mtsel_ns[1:0]), .dout(mtsel[1:0])); @@ -1839,7 +1876,7 @@ else // ---------------------------------------------------------------------- // MTDATA1 (R/W) // [31:0] : Trigger Data 1 - `define MTDATA1 12'h7a1 + localparam MTDATA1 = 12'h7a1; // for triggers 0, 1, 2 and 3 aka Match Control // [31:28] : type, hard coded to 0x2 @@ -1877,81 +1914,95 @@ else // don't allow clearing DMODE and action=1 assign tdata_action = (dec_csr_wrdata_r[27] & dbg_tlu_halted_f) & dec_csr_wrdata_r[12]; + // Chain bit has conditions: WARL for triggers without chains. Force to zero if dmode is 0 but next trigger dmode is 1. + assign tdata_chain = mtsel[0] ? 1'b0 : // triggers 1 and 3 chain bit is always zero + mtsel[1] ? dec_csr_wrdata_r[11] & ~(mtdata1_t3[MTDATA1_DMODE] & ~dec_csr_wrdata_r[27]) : // trigger 2 + dec_csr_wrdata_r[11] & ~(mtdata1_t1[MTDATA1_DMODE] & ~dec_csr_wrdata_r[27]); // trigger 0 + + // Kill mtdata1 write if dmode=1 but prior trigger has dmode=0/chain=1. Only applies to T1 and T3 + assign tdata_kill_write = mtsel[1] ? dec_csr_wrdata_r[27] & (~mtdata1_t2[MTDATA1_DMODE] & mtdata1_t2[MTDATA1_CHAIN]) : // trigger 3 + dec_csr_wrdata_r[27] & (~mtdata1_t0[MTDATA1_DMODE] & mtdata1_t0[MTDATA1_CHAIN]) ; // trigger 1 + + assign tdata_wrdata_r[9:0] = {dec_csr_wrdata_r[27] & dbg_tlu_halted_f, dec_csr_wrdata_r[20:19], tdata_action, - dec_csr_wrdata_r[11], + tdata_chain, dec_csr_wrdata_r[7:6], tdata_opcode, dec_csr_wrdata_r[1], tdata_load}; // If the DMODE bit is set, tdata1 can only be updated in debug_mode - assign wr_mtdata1_t0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTDATA1) & (mtsel[1:0] == 2'b0) & (~mtdata1_t0[`MTDATA1_DMODE] | dbg_tlu_halted_f); + assign wr_mtdata1_t0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA1) & (mtsel[1:0] == 2'b0) & (~mtdata1_t0[MTDATA1_DMODE] | dbg_tlu_halted_f); assign mtdata1_t0_ns[9:0] = wr_mtdata1_t0_r ? tdata_wrdata_r[9:0] : {mtdata1_t0[9], update_hit_bit_r[0] | mtdata1_t0[8], mtdata1_t0[7:0]}; - assign wr_mtdata1_t1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTDATA1) & (mtsel[1:0] == 2'b01) & (~mtdata1_t1[`MTDATA1_DMODE] | dbg_tlu_halted_f); + assign wr_mtdata1_t1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA1) & (mtsel[1:0] == 2'b01) & (~mtdata1_t1[MTDATA1_DMODE] | dbg_tlu_halted_f) & ~tdata_kill_write; assign mtdata1_t1_ns[9:0] = wr_mtdata1_t1_r ? tdata_wrdata_r[9:0] : {mtdata1_t1[9], update_hit_bit_r[1] | mtdata1_t1[8], mtdata1_t1[7:0]}; - assign wr_mtdata1_t2_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTDATA1) & (mtsel[1:0] == 2'b10) & (~mtdata1_t2[`MTDATA1_DMODE] | dbg_tlu_halted_f); + assign wr_mtdata1_t2_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA1) & (mtsel[1:0] == 2'b10) & (~mtdata1_t2[MTDATA1_DMODE] | dbg_tlu_halted_f); assign mtdata1_t2_ns[9:0] = wr_mtdata1_t2_r ? tdata_wrdata_r[9:0] : {mtdata1_t2[9], update_hit_bit_r[2] | mtdata1_t2[8], mtdata1_t2[7:0]}; - assign wr_mtdata1_t3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTDATA1) & (mtsel[1:0] == 2'b11) & (~mtdata1_t3[`MTDATA1_DMODE] | dbg_tlu_halted_f); + assign wr_mtdata1_t3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA1) & (mtsel[1:0] == 2'b11) & (~mtdata1_t3[MTDATA1_DMODE] | dbg_tlu_halted_f) & ~tdata_kill_write; assign mtdata1_t3_ns[9:0] = wr_mtdata1_t3_r ? tdata_wrdata_r[9:0] : {mtdata1_t3[9], update_hit_bit_r[3] | mtdata1_t3[8], mtdata1_t3[7:0]}; - rvdff #(10) mtdata1_t0_ff (.*, .clk(active_clk), .din(mtdata1_t0_ns[9:0]), .dout(mtdata1_t0[9:0])); - rvdff #(10) mtdata1_t1_ff (.*, .clk(active_clk), .din(mtdata1_t1_ns[9:0]), .dout(mtdata1_t1[9:0])); - rvdff #(10) mtdata1_t2_ff (.*, .clk(active_clk), .din(mtdata1_t2_ns[9:0]), .dout(mtdata1_t2[9:0])); - rvdff #(10) mtdata1_t3_ff (.*, .clk(active_clk), .din(mtdata1_t3_ns[9:0]), .dout(mtdata1_t3[9:0])); + rvdffe #(10) mtdata1_t0_ff (.*, .en(trigger_enabled[0] | wr_mtdata1_t0_r), .din(mtdata1_t0_ns[9:0]), .dout(mtdata1_t0[9:0])); + rvdffe #(10) mtdata1_t1_ff (.*, .en(trigger_enabled[1] | wr_mtdata1_t1_r), .din(mtdata1_t1_ns[9:0]), .dout(mtdata1_t1[9:0])); + rvdffe #(10) mtdata1_t2_ff (.*, .en(trigger_enabled[2] | wr_mtdata1_t2_r), .din(mtdata1_t2_ns[9:0]), .dout(mtdata1_t2[9:0])); + rvdffe #(10) mtdata1_t3_ff (.*, .en(trigger_enabled[3] | wr_mtdata1_t3_r), .din(mtdata1_t3_ns[9:0]), .dout(mtdata1_t3[9:0])); assign mtdata1_tsel_out[31:0] = ( ({32{(mtsel[1:0] == 2'b00)}} & {4'h2, mtdata1_t0[9], 6'b011111, mtdata1_t0[8:7], 6'b0, mtdata1_t0[6:5], 3'b0, mtdata1_t0[4:3], 3'b0, mtdata1_t0[2:0]}) | ({32{(mtsel[1:0] == 2'b01)}} & {4'h2, mtdata1_t1[9], 6'b011111, mtdata1_t1[8:7], 6'b0, mtdata1_t1[6:5], 3'b0, mtdata1_t1[4:3], 3'b0, mtdata1_t1[2:0]}) | ({32{(mtsel[1:0] == 2'b10)}} & {4'h2, mtdata1_t2[9], 6'b011111, mtdata1_t2[8:7], 6'b0, mtdata1_t2[6:5], 3'b0, mtdata1_t2[4:3], 3'b0, mtdata1_t2[2:0]}) | ({32{(mtsel[1:0] == 2'b11)}} & {4'h2, mtdata1_t3[9], 6'b011111, mtdata1_t3[8:7], 6'b0, mtdata1_t3[6:5], 3'b0, mtdata1_t3[4:3], 3'b0, mtdata1_t3[2:0]})); - assign trigger_pkt_any[0].select = mtdata1_t0[`MTDATA1_SEL]; - assign trigger_pkt_any[0].match = mtdata1_t0[`MTDATA1_MATCH]; - assign trigger_pkt_any[0].store = mtdata1_t0[`MTDATA1_ST]; - assign trigger_pkt_any[0].load = mtdata1_t0[`MTDATA1_LD]; - assign trigger_pkt_any[0].execute = mtdata1_t0[`MTDATA1_EXE]; - assign trigger_pkt_any[0].m = mtdata1_t0[`MTDATA1_M_ENABLED]; + assign trigger_pkt_any[0].select = mtdata1_t0[MTDATA1_SEL]; + assign trigger_pkt_any[0].match = mtdata1_t0[MTDATA1_MATCH]; + assign trigger_pkt_any[0].store = mtdata1_t0[MTDATA1_ST]; + assign trigger_pkt_any[0].load = mtdata1_t0[MTDATA1_LD]; + assign trigger_pkt_any[0].execute = mtdata1_t0[MTDATA1_EXE]; + assign trigger_pkt_any[0].m = mtdata1_t0[MTDATA1_M_ENABLED]; + + assign trigger_pkt_any[1].select = mtdata1_t1[MTDATA1_SEL]; + assign trigger_pkt_any[1].match = mtdata1_t1[MTDATA1_MATCH]; + assign trigger_pkt_any[1].store = mtdata1_t1[MTDATA1_ST]; + assign trigger_pkt_any[1].load = mtdata1_t1[MTDATA1_LD]; + assign trigger_pkt_any[1].execute = mtdata1_t1[MTDATA1_EXE]; + assign trigger_pkt_any[1].m = mtdata1_t1[MTDATA1_M_ENABLED]; + + assign trigger_pkt_any[2].select = mtdata1_t2[MTDATA1_SEL]; + assign trigger_pkt_any[2].match = mtdata1_t2[MTDATA1_MATCH]; + assign trigger_pkt_any[2].store = mtdata1_t2[MTDATA1_ST]; + assign trigger_pkt_any[2].load = mtdata1_t2[MTDATA1_LD]; + assign trigger_pkt_any[2].execute = mtdata1_t2[MTDATA1_EXE]; + assign trigger_pkt_any[2].m = mtdata1_t2[MTDATA1_M_ENABLED]; + + assign trigger_pkt_any[3].select = mtdata1_t3[MTDATA1_SEL]; + assign trigger_pkt_any[3].match = mtdata1_t3[MTDATA1_MATCH]; + assign trigger_pkt_any[3].store = mtdata1_t3[MTDATA1_ST]; + assign trigger_pkt_any[3].load = mtdata1_t3[MTDATA1_LD]; + assign trigger_pkt_any[3].execute = mtdata1_t3[MTDATA1_EXE]; + assign trigger_pkt_any[3].m = mtdata1_t3[MTDATA1_M_ENABLED]; + - assign trigger_pkt_any[1].select = mtdata1_t1[`MTDATA1_SEL]; - assign trigger_pkt_any[1].match = mtdata1_t1[`MTDATA1_MATCH]; - assign trigger_pkt_any[1].store = mtdata1_t1[`MTDATA1_ST]; - assign trigger_pkt_any[1].load = mtdata1_t1[`MTDATA1_LD]; - assign trigger_pkt_any[1].execute = mtdata1_t1[`MTDATA1_EXE]; - assign trigger_pkt_any[1].m = mtdata1_t1[`MTDATA1_M_ENABLED]; - assign trigger_pkt_any[2].select = mtdata1_t2[`MTDATA1_SEL]; - assign trigger_pkt_any[2].match = mtdata1_t2[`MTDATA1_MATCH]; - assign trigger_pkt_any[2].store = mtdata1_t2[`MTDATA1_ST]; - assign trigger_pkt_any[2].load = mtdata1_t2[`MTDATA1_LD]; - assign trigger_pkt_any[2].execute = mtdata1_t2[`MTDATA1_EXE]; - assign trigger_pkt_any[2].m = mtdata1_t2[`MTDATA1_M_ENABLED]; - assign trigger_pkt_any[3].select = mtdata1_t3[`MTDATA1_SEL]; - assign trigger_pkt_any[3].match = mtdata1_t3[`MTDATA1_MATCH]; - assign trigger_pkt_any[3].store = mtdata1_t3[`MTDATA1_ST]; - assign trigger_pkt_any[3].load = mtdata1_t3[`MTDATA1_LD]; - assign trigger_pkt_any[3].execute = mtdata1_t3[`MTDATA1_EXE]; - assign trigger_pkt_any[3].m = mtdata1_t3[`MTDATA1_M_ENABLED]; // ---------------------------------------------------------------------- // MTDATA2 (R/W) // [31:0] : Trigger Data 2 - `define MTDATA2 12'h7a2 + localparam MTDATA2 = 12'h7a2; // If the DMODE bit is set, tdata2 can only be updated in debug_mode - assign wr_mtdata2_t0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTDATA2) & (mtsel[1:0] == 2'b0) & (~mtdata1_t0[`MTDATA1_DMODE] | dbg_tlu_halted_f); - assign wr_mtdata2_t1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTDATA2) & (mtsel[1:0] == 2'b01) & (~mtdata1_t1[`MTDATA1_DMODE] | dbg_tlu_halted_f); - assign wr_mtdata2_t2_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTDATA2) & (mtsel[1:0] == 2'b10) & (~mtdata1_t2[`MTDATA1_DMODE] | dbg_tlu_halted_f); - assign wr_mtdata2_t3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MTDATA2) & (mtsel[1:0] == 2'b11) & (~mtdata1_t3[`MTDATA1_DMODE] | dbg_tlu_halted_f); + assign wr_mtdata2_t0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA2) & (mtsel[1:0] == 2'b0) & (~mtdata1_t0[MTDATA1_DMODE] | dbg_tlu_halted_f); + assign wr_mtdata2_t1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA2) & (mtsel[1:0] == 2'b01) & (~mtdata1_t1[MTDATA1_DMODE] | dbg_tlu_halted_f); + assign wr_mtdata2_t2_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA2) & (mtsel[1:0] == 2'b10) & (~mtdata1_t2[MTDATA1_DMODE] | dbg_tlu_halted_f); + assign wr_mtdata2_t3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MTDATA2) & (mtsel[1:0] == 2'b11) & (~mtdata1_t3[MTDATA1_DMODE] | dbg_tlu_halted_f); rvdffe #(32) mtdata2_t0_ff (.*, .en(wr_mtdata2_t0_r), .din(dec_csr_wrdata_r[31:0]), .dout(mtdata2_t0[31:0])); rvdffe #(32) mtdata2_t1_ff (.*, .en(wr_mtdata2_t1_r), .din(dec_csr_wrdata_r[31:0]), .dout(mtdata2_t1[31:0])); @@ -1972,65 +2023,64 @@ else //---------------------------------------------------------------------- // Performance Monitor Counters section starts //---------------------------------------------------------------------- - `define MHPME_NOEVENT 10'd0 - `define MHPME_CLK_ACTIVE 10'd1 // OOP - out of pipe - `define MHPME_ICACHE_HIT 10'd2 // OOP - `define MHPME_ICACHE_MISS 10'd3 // OOP - `define MHPME_INST_COMMIT 10'd4 - `define MHPME_INST_COMMIT_16B 10'd5 - `define MHPME_INST_COMMIT_32B 10'd6 - `define MHPME_INST_ALIGNED 10'd7 // OOP - `define MHPME_INST_DECODED 10'd8 // OOP - `define MHPME_INST_MUL 10'd9 - `define MHPME_INST_DIV 10'd10 - `define MHPME_INST_LOAD 10'd11 - `define MHPME_INST_STORE 10'd12 - `define MHPME_INST_MALOAD 10'd13 - `define MHPME_INST_MASTORE 10'd14 - `define MHPME_INST_ALU 10'd15 - `define MHPME_INST_CSRREAD 10'd16 - `define MHPME_INST_CSRRW 10'd17 - `define MHPME_INST_CSRWRITE 10'd18 - `define MHPME_INST_EBREAK 10'd19 - `define MHPME_INST_ECALL 10'd20 - `define MHPME_INST_FENCE 10'd21 - `define MHPME_INST_FENCEI 10'd22 - `define MHPME_INST_MRET 10'd23 - `define MHPME_INST_BRANCH 10'd24 - `define MHPME_BRANCH_MP 10'd25 - `define MHPME_BRANCH_TAKEN 10'd26 - `define MHPME_BRANCH_NOTP 10'd27 - `define MHPME_FETCH_STALL 10'd28 // OOP - `define MHPME_ALGNR_STALL 10'd29 // OOP - `define MHPME_DECODE_STALL 10'd30 // OOP - `define MHPME_POSTSYNC_STALL 10'd31 // OOP - `define MHPME_PRESYNC_STALL 10'd32 // OOP - `define MHPME_LSU_SB_WB_STALL 10'd34 // OOP - `define MHPME_DMA_DCCM_STALL 10'd35 // OOP - `define MHPME_DMA_ICCM_STALL 10'd36 // OOP - `define MHPME_EXC_TAKEN 10'd37 - `define MHPME_TIMER_INT_TAKEN 10'd38 - `define MHPME_EXT_INT_TAKEN 10'd39 - `define MHPME_FLUSH_LOWER 10'd40 - `define MHPME_BR_ERROR 10'd41 - `define MHPME_IBUS_TRANS 10'd42 // OOP - `define MHPME_DBUS_TRANS 10'd43 // OOP - `define MHPME_DBUS_MA_TRANS 10'd44 // OOP - `define MHPME_IBUS_ERROR 10'd45 // OOP - `define MHPME_DBUS_ERROR 10'd46 // OOP - `define MHPME_IBUS_STALL 10'd47 // OOP - `define MHPME_DBUS_STALL 10'd48 // OOP - `define MHPME_INT_DISABLED 10'd49 // OOP - `define MHPME_INT_STALLED 10'd50 // OOP - `define MHPME_INST_BITMANIP 10'd54 - `define MHPME_DBUS_LOAD 10'd55 - `define MHPME_DBUS_STORE 10'd56 + localparam MHPME_NOEVENT = 10'd0; + localparam MHPME_CLK_ACTIVE = 10'd1; // OOP - out of pipe + localparam MHPME_ICACHE_HIT = 10'd2; // OOP + localparam MHPME_ICACHE_MISS = 10'd3; // OOP + localparam MHPME_INST_COMMIT = 10'd4; + localparam MHPME_INST_COMMIT_16B = 10'd5; + localparam MHPME_INST_COMMIT_32B = 10'd6; + localparam MHPME_INST_ALIGNED = 10'd7; // OOP + localparam MHPME_INST_DECODED = 10'd8; // OOP + localparam MHPME_INST_MUL = 10'd9; + localparam MHPME_INST_DIV = 10'd10; + localparam MHPME_INST_LOAD = 10'd11; + localparam MHPME_INST_STORE = 10'd12; + localparam MHPME_INST_MALOAD = 10'd13; + localparam MHPME_INST_MASTORE = 10'd14; + localparam MHPME_INST_ALU = 10'd15; + localparam MHPME_INST_CSRREAD = 10'd16; + localparam MHPME_INST_CSRRW = 10'd17; + localparam MHPME_INST_CSRWRITE = 10'd18; + localparam MHPME_INST_EBREAK = 10'd19; + localparam MHPME_INST_ECALL = 10'd20; + localparam MHPME_INST_FENCE = 10'd21; + localparam MHPME_INST_FENCEI = 10'd22; + localparam MHPME_INST_MRET = 10'd23; + localparam MHPME_INST_BRANCH = 10'd24; + localparam MHPME_BRANCH_MP = 10'd25; + localparam MHPME_BRANCH_TAKEN = 10'd26; + localparam MHPME_BRANCH_NOTP = 10'd27; + localparam MHPME_FETCH_STALL = 10'd28; // OOP + localparam MHPME_DECODE_STALL = 10'd30; // OOP + localparam MHPME_POSTSYNC_STALL = 10'd31; // OOP + localparam MHPME_PRESYNC_STALL = 10'd32; // OOP + localparam MHPME_LSU_SB_WB_STALL = 10'd34; // OOP + localparam MHPME_DMA_DCCM_STALL = 10'd35; // OOP + localparam MHPME_DMA_ICCM_STALL = 10'd36; // OOP + localparam MHPME_EXC_TAKEN = 10'd37; + localparam MHPME_TIMER_INT_TAKEN = 10'd38; + localparam MHPME_EXT_INT_TAKEN = 10'd39; + localparam MHPME_FLUSH_LOWER = 10'd40; + localparam MHPME_BR_ERROR = 10'd41; + localparam MHPME_IBUS_TRANS = 10'd42; // OOP + localparam MHPME_DBUS_TRANS = 10'd43; // OOP + localparam MHPME_DBUS_MA_TRANS = 10'd44; // OOP + localparam MHPME_IBUS_ERROR = 10'd45; // OOP + localparam MHPME_DBUS_ERROR = 10'd46; // OOP + localparam MHPME_IBUS_STALL = 10'd47; // OOP + localparam MHPME_DBUS_STALL = 10'd48; // OOP + localparam MHPME_INT_DISABLED = 10'd49; // OOP + localparam MHPME_INT_STALLED = 10'd50; // OOP + localparam MHPME_INST_BITMANIP = 10'd54; + localparam MHPME_DBUS_LOAD = 10'd55; + localparam MHPME_DBUS_STORE = 10'd56; // Counts even during sleep state - `define MHPME_SLEEP_CYC 10'd512 // OOP - `define MHPME_DMA_READ_ALL 10'd513 // OOP - `define MHPME_DMA_WRITE_ALL 10'd514 // OOP - `define MHPME_DMA_READ_DCCM 10'd515 // OOP - `define MHPME_DMA_WRITE_DCCM 10'd516 // OOP + localparam MHPME_SLEEP_CYC = 10'd512; // OOP + localparam MHPME_DMA_READ_ALL = 10'd513; // OOP + localparam MHPME_DMA_WRITE_ALL = 10'd514; // OOP + localparam MHPME_DMA_READ_DCCM = 10'd515; // OOP + localparam MHPME_DMA_WRITE_DCCM = 10'd516; // OOP // Pack the event selects into a vector for genvar assign mhpme_vec[0][9:0] = mhpme3[9:0]; @@ -2046,79 +2096,101 @@ else for (genvar i=0 ; i < 4; i++) begin assign mhpmc_inc_r[i] = {{~mcountinhibit[i+3]}} & ( - ({1{(mhpme_vec[i][9:0] == `MHPME_CLK_ACTIVE )}} & 1'b1) | - ({1{(mhpme_vec[i][9:0] == `MHPME_ICACHE_HIT )}} & {ifu_pmu_ic_hit}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_ICACHE_MISS )}} & {ifu_pmu_ic_miss}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_COMMIT )}} & {tlu_i0_commit_cmt & ~illegal_r}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_COMMIT_16B )}} & {tlu_i0_commit_cmt & ~exu_pmu_i0_pc4 & ~illegal_r}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_COMMIT_32B )}} & {tlu_i0_commit_cmt & exu_pmu_i0_pc4 & ~illegal_r}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_ALIGNED )}} & ifu_pmu_instr_aligned) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_DECODED )}} & dec_pmu_instr_decoded) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DECODE_STALL )}} & {dec_pmu_decode_stall}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_MUL )}} & {(pmu_i0_itype_qual == MUL)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_DIV )}} & {dec_tlu_packet_r.pmu_divide & tlu_i0_commit_cmt}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_LOAD )}} & {(pmu_i0_itype_qual == LOAD)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_STORE )}} & {(pmu_i0_itype_qual == STORE)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_MALOAD )}} & {(pmu_i0_itype_qual == LOAD)} & + ({1{(mhpme_vec[i][9:0] == MHPME_CLK_ACTIVE )}} & 1'b1) | + ({1{(mhpme_vec[i][9:0] == MHPME_ICACHE_HIT )}} & {ifu_pmu_ic_hit}) | + ({1{(mhpme_vec[i][9:0] == MHPME_ICACHE_MISS )}} & {ifu_pmu_ic_miss}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_COMMIT )}} & {tlu_i0_commit_cmt & ~illegal_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_COMMIT_16B )}} & {tlu_i0_commit_cmt & ~exu_pmu_i0_pc4 & ~illegal_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_COMMIT_32B )}} & {tlu_i0_commit_cmt & exu_pmu_i0_pc4 & ~illegal_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_ALIGNED )}} & ifu_pmu_instr_aligned) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_DECODED )}} & dec_pmu_instr_decoded) | + ({1{(mhpme_vec[i][9:0] == MHPME_DECODE_STALL )}} & {dec_pmu_decode_stall}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_MUL )}} & {(pmu_i0_itype_qual == MUL)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_DIV )}} & {dec_tlu_packet_r.pmu_divide & tlu_i0_commit_cmt & ~illegal_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_LOAD )}} & {(pmu_i0_itype_qual == LOAD)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_STORE )}} & {(pmu_i0_itype_qual == STORE)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_MALOAD )}} & {(pmu_i0_itype_qual == LOAD)} & {1{dec_tlu_packet_r.pmu_lsu_misaligned}}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_MASTORE )}} & {(pmu_i0_itype_qual == STORE)} & + ({1{(mhpme_vec[i][9:0] == MHPME_INST_MASTORE )}} & {(pmu_i0_itype_qual == STORE)} & {1{dec_tlu_packet_r.pmu_lsu_misaligned}}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_ALU )}} & {(pmu_i0_itype_qual == ALU)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_CSRREAD )}} & {(pmu_i0_itype_qual == CSRREAD)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_CSRWRITE )}} & {(pmu_i0_itype_qual == CSRWRITE)})| - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_CSRRW )}} & {(pmu_i0_itype_qual == CSRRW)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_EBREAK )}} & {(pmu_i0_itype_qual == EBREAK)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_ECALL )}} & {(pmu_i0_itype_qual == ECALL)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_FENCE )}} & {(pmu_i0_itype_qual == FENCE)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_FENCEI )}} & {(pmu_i0_itype_qual == FENCEI)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_MRET )}} & {(pmu_i0_itype_qual == MRET)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_BRANCH )}} & { + ({1{(mhpme_vec[i][9:0] == MHPME_INST_ALU )}} & {(pmu_i0_itype_qual == ALU)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_CSRREAD )}} & {(pmu_i0_itype_qual == CSRREAD)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_CSRWRITE )}} & {(pmu_i0_itype_qual == CSRWRITE)})| + ({1{(mhpme_vec[i][9:0] == MHPME_INST_CSRRW )}} & {(pmu_i0_itype_qual == CSRRW)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_EBREAK )}} & {(pmu_i0_itype_qual == EBREAK)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_ECALL )}} & {(pmu_i0_itype_qual == ECALL)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_FENCE )}} & {(pmu_i0_itype_qual == FENCE)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_FENCEI )}} & {(pmu_i0_itype_qual == FENCEI)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_MRET )}} & {(pmu_i0_itype_qual == MRET)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_BRANCH )}} & { ((pmu_i0_itype_qual == CONDBR) | (pmu_i0_itype_qual == JAL))}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_BRANCH_MP )}} & {exu_pmu_i0_br_misp & tlu_i0_commit_cmt}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_BRANCH_TAKEN )}} & {exu_pmu_i0_br_ataken & tlu_i0_commit_cmt}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_BRANCH_NOTP )}} & {dec_tlu_packet_r.pmu_i0_br_unpred & tlu_i0_commit_cmt}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_FETCH_STALL )}} & { ifu_pmu_fetch_stall}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DECODE_STALL )}} & { dec_pmu_decode_stall}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_POSTSYNC_STALL )}} & {dec_pmu_postsync_stall}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_PRESYNC_STALL )}} & {dec_pmu_presync_stall}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_LSU_SB_WB_STALL )}} & { lsu_store_stall_any}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DMA_DCCM_STALL )}} & { dma_dccm_stall_any}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DMA_ICCM_STALL )}} & { dma_iccm_stall_any}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_EXC_TAKEN )}} & { (i0_exception_valid_r | i0_trigger_hit_r | lsu_exc_valid_r)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_TIMER_INT_TAKEN )}} & { take_timer_int | take_int_timer0_int | take_int_timer1_int}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_EXT_INT_TAKEN )}} & { take_ext_int}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_FLUSH_LOWER )}} & { tlu_flush_lower_r}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_BR_ERROR )}} & {(dec_tlu_br0_error_r | dec_tlu_br0_start_error_r) & rfpc_i0_r}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_IBUS_TRANS )}} & {ifu_pmu_bus_trxn}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DBUS_TRANS )}} & {lsu_pmu_bus_trxn}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DBUS_MA_TRANS )}} & {lsu_pmu_bus_misaligned}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_IBUS_ERROR )}} & {ifu_pmu_bus_error}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DBUS_ERROR )}} & {lsu_pmu_bus_error}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_IBUS_STALL )}} & {ifu_pmu_bus_busy}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DBUS_STALL )}} & {lsu_pmu_bus_busy}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INT_DISABLED )}} & {~mstatus[`MSTATUS_MIE]}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INT_STALLED )}} & {~mstatus[`MSTATUS_MIE] & |(mip[5:0] & mie[5:0])}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_INST_BITMANIP )}} & {(pmu_i0_itype_qual == BITMANIPU)}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DBUS_LOAD )}} & {tlu_i0_commit_cmt & lsu_pmu_load_external_r}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DBUS_STORE )}} & {tlu_i0_commit_cmt & lsu_pmu_store_external_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_BRANCH_MP )}} & {exu_pmu_i0_br_misp & tlu_i0_commit_cmt & ~illegal_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_BRANCH_TAKEN )}} & {exu_pmu_i0_br_ataken & tlu_i0_commit_cmt & ~illegal_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_BRANCH_NOTP )}} & {dec_tlu_packet_r.pmu_i0_br_unpred & tlu_i0_commit_cmt & ~illegal_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_FETCH_STALL )}} & { ifu_pmu_fetch_stall}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DECODE_STALL )}} & { dec_pmu_decode_stall}) | + ({1{(mhpme_vec[i][9:0] == MHPME_POSTSYNC_STALL )}} & {dec_pmu_postsync_stall}) | + ({1{(mhpme_vec[i][9:0] == MHPME_PRESYNC_STALL )}} & {dec_pmu_presync_stall}) | + ({1{(mhpme_vec[i][9:0] == MHPME_LSU_SB_WB_STALL )}} & { lsu_store_stall_any}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DMA_DCCM_STALL )}} & { dma_dccm_stall_any}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DMA_ICCM_STALL )}} & { dma_iccm_stall_any}) | + ({1{(mhpme_vec[i][9:0] == MHPME_EXC_TAKEN )}} & { (i0_exception_valid_r | i0_trigger_hit_r | lsu_exc_valid_r)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_TIMER_INT_TAKEN )}} & { take_timer_int | take_int_timer0_int | take_int_timer1_int}) | + ({1{(mhpme_vec[i][9:0] == MHPME_EXT_INT_TAKEN )}} & { take_ext_int}) | + ({1{(mhpme_vec[i][9:0] == MHPME_FLUSH_LOWER )}} & { tlu_flush_lower_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_BR_ERROR )}} & {(dec_tlu_br0_error_r | dec_tlu_br0_start_error_r) & rfpc_i0_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_IBUS_TRANS )}} & {ifu_pmu_bus_trxn}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DBUS_TRANS )}} & {lsu_pmu_bus_trxn}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DBUS_MA_TRANS )}} & {lsu_pmu_bus_misaligned}) | + ({1{(mhpme_vec[i][9:0] == MHPME_IBUS_ERROR )}} & {ifu_pmu_bus_error}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DBUS_ERROR )}} & {lsu_pmu_bus_error}) | + ({1{(mhpme_vec[i][9:0] == MHPME_IBUS_STALL )}} & {ifu_pmu_bus_busy}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DBUS_STALL )}} & {lsu_pmu_bus_busy}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INT_DISABLED )}} & {~mstatus[MSTATUS_MIE]}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INT_STALLED )}} & {~mstatus[MSTATUS_MIE] & |(mip[5:0] & mie[5:0])}) | + ({1{(mhpme_vec[i][9:0] == MHPME_INST_BITMANIP )}} & {(pmu_i0_itype_qual == BITMANIPU)}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DBUS_LOAD )}} & {tlu_i0_commit_cmt & lsu_pmu_load_external_r & ~illegal_r}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DBUS_STORE )}} & {tlu_i0_commit_cmt & lsu_pmu_store_external_r & ~illegal_r}) | // These count even during sleep - ({1{(mhpme_vec[i][9:0] == `MHPME_SLEEP_CYC )}} & {dec_tlu_pmu_fw_halted}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DMA_READ_ALL )}} & {dma_pmu_any_read}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DMA_WRITE_ALL )}} & {dma_pmu_any_write}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DMA_READ_DCCM )}} & {dma_pmu_dccm_read}) | - ({1{(mhpme_vec[i][9:0] == `MHPME_DMA_WRITE_DCCM )}} & {dma_pmu_dccm_write}) + ({1{(mhpme_vec[i][9:0] == MHPME_SLEEP_CYC )}} & {dec_tlu_pmu_fw_halted}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DMA_READ_ALL )}} & {dma_pmu_any_read}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DMA_WRITE_ALL )}} & {dma_pmu_any_write}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DMA_READ_DCCM )}} & {dma_pmu_dccm_read}) | + ({1{(mhpme_vec[i][9:0] == MHPME_DMA_WRITE_DCCM )}} & {dma_pmu_dccm_write}) ); end - rvdff #(1) pmu0inc_ff (.*, .clk(free_clk), .din(mhpmc_inc_r[0]), .dout(mhpmc_inc_r_d1[0])); - rvdff #(1) pmu1inc_ff (.*, .clk(free_clk), .din(mhpmc_inc_r[1]), .dout(mhpmc_inc_r_d1[1])); - rvdff #(1) pmu2inc_ff (.*, .clk(free_clk), .din(mhpmc_inc_r[2]), .dout(mhpmc_inc_r_d1[2])); - rvdff #(1) pmu3inc_ff (.*, .clk(free_clk), .din(mhpmc_inc_r[3]), .dout(mhpmc_inc_r_d1[3])); - rvdff #(1) perfhlt_ff (.*, .clk(free_clk), .din(perfcnt_halted), .dout(perfcnt_halted_d1)); + if(pt.FAST_INTERRUPT_REDIRECT) + rvdffie #(31) mstatus_ff (.*, .clk(free_l2clk), + .din({mdseac_locked_ns, lsu_single_ecc_error_r, lsu_exc_valid_r, lsu_i0_exc_r, + take_ext_int_start, take_ext_int_start_d1, take_ext_int_start_d2, ext_int_freeze, + mip_ns[5:0], mcyclel_cout & ~wr_mcycleh_r & mcyclel_cout_in, + minstret_enable, minstretl_cout_ns, fw_halted_ns, + meicidpl_ns[3:0], icache_rd_valid, icache_wr_valid, mhpmc_inc_r[3:0], perfcnt_halted, + mstatus_ns[1:0]}), + .dout({mdseac_locked_f, lsu_single_ecc_error_r_d1, lsu_exc_valid_r_d1, lsu_i0_exc_r_d1, + take_ext_int_start_d1, take_ext_int_start_d2, take_ext_int_start_d3, ext_int_freeze_d1, + mip[5:0], mcyclel_cout_f, minstret_enable_f, minstretl_cout_f, + fw_halted, meicidpl[3:0], icache_rd_valid_f, icache_wr_valid_f, + mhpmc_inc_r_d1[3:0], perfcnt_halted_d1, + mstatus[1:0]})); - assign perfcnt_halted = ((dec_tlu_dbg_halted & dcsr[`DCSR_STOPC]) | dec_tlu_pmu_fw_halted); - assign perfcnt_during_sleep[3:0] = {4{~(dec_tlu_dbg_halted & dcsr[`DCSR_STOPC])}} & {mhpme_vec[3][9],mhpme_vec[2][9],mhpme_vec[1][9],mhpme_vec[0][9]}; + else + rvdffie #(27) mstatus_ff (.*, .clk(free_l2clk), + .din({mdseac_locked_ns, lsu_single_ecc_error_r, lsu_exc_valid_r, lsu_i0_exc_r, + mip_ns[5:0], mcyclel_cout & ~wr_mcycleh_r & mcyclel_cout_in, + minstret_enable, minstretl_cout_ns, fw_halted_ns, + meicidpl_ns[3:0], icache_rd_valid, icache_wr_valid, mhpmc_inc_r[3:0], perfcnt_halted, + mstatus_ns[1:0]}), + .dout({mdseac_locked_f, lsu_single_ecc_error_r_d1, lsu_exc_valid_r_d1, lsu_i0_exc_r_d1, + mip[5:0], mcyclel_cout_f, minstret_enable_f, minstretl_cout_f, + fw_halted, meicidpl[3:0], icache_rd_valid_f, icache_wr_valid_f, + mhpmc_inc_r_d1[3:0], perfcnt_halted_d1, + mstatus[1:0]})); + + assign perfcnt_halted = ((dec_tlu_dbg_halted & dcsr[DCSR_STOPC]) | dec_tlu_pmu_fw_halted); + assign perfcnt_during_sleep[3:0] = {4{~(dec_tlu_dbg_halted & dcsr[DCSR_STOPC])}} & {mhpme_vec[3][9],mhpme_vec[2][9],mhpme_vec[1][9],mhpme_vec[0][9]}; assign dec_tlu_perfcnt0 = mhpmc_inc_r_d1[0] & ~(perfcnt_halted_d1 & ~perfcnt_during_sleep[0]); assign dec_tlu_perfcnt1 = mhpmc_inc_r_d1[1] & ~(perfcnt_halted_d1 & ~perfcnt_during_sleep[1]); @@ -2128,106 +2200,114 @@ else // ---------------------------------------------------------------------- // MHPMC3H(RW), MHPMC3(RW) // [63:32][31:0] : Hardware Performance Monitor Counter 3 - `define MHPMC3 12'hB03 - `define MHPMC3H 12'hB83 + localparam MHPMC3 = 12'hB03; + localparam MHPMC3H = 12'hB83; - assign mhpmc3_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPMC3); + assign mhpmc3_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC3); assign mhpmc3_wr_en1 = (~perfcnt_halted | perfcnt_during_sleep[0]) & (|(mhpmc_inc_r[0])); assign mhpmc3_wr_en = mhpmc3_wr_en0 | mhpmc3_wr_en1; - assign mhpmc3_incr[63:0] = {mhpmc3h[31:0],mhpmc3[31:0]} + {63'b0,mhpmc_inc_r[0]}; + assign mhpmc3_incr[63:0] = {mhpmc3h[31:0],mhpmc3[31:0]} + {63'b0, 1'b1}; assign mhpmc3_ns[31:0] = mhpmc3_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc3_incr[31:0]; - rvdffe #(32) mhpmc3_ff (.*, .en(mhpmc3_wr_en), .din(mhpmc3_ns[31:0]), .dout(mhpmc3[31:0])); + rvdffe #(32) mhpmc3_ff (.*, .clk(free_l2clk), .en(mhpmc3_wr_en), .din(mhpmc3_ns[31:0]), .dout(mhpmc3[31:0])); - assign mhpmc3h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPMC3H); + assign mhpmc3h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC3H); assign mhpmc3h_wr_en = mhpmc3h_wr_en0 | mhpmc3_wr_en1; assign mhpmc3h_ns[31:0] = mhpmc3h_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc3_incr[63:32]; - rvdffe #(32) mhpmc3h_ff (.*, .en(mhpmc3h_wr_en), .din(mhpmc3h_ns[31:0]), .dout(mhpmc3h[31:0])); + rvdffe #(32) mhpmc3h_ff (.*, .clk(free_l2clk), .en(mhpmc3h_wr_en), .din(mhpmc3h_ns[31:0]), .dout(mhpmc3h[31:0])); // ---------------------------------------------------------------------- // MHPMC4H(RW), MHPMC4(RW) // [63:32][31:0] : Hardware Performance Monitor Counter 4 - `define MHPMC4 12'hB04 - `define MHPMC4H 12'hB84 + localparam MHPMC4 = 12'hB04; + localparam MHPMC4H = 12'hB84; - assign mhpmc4_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPMC4); + assign mhpmc4_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC4); assign mhpmc4_wr_en1 = (~perfcnt_halted | perfcnt_during_sleep[1]) & (|(mhpmc_inc_r[1])); assign mhpmc4_wr_en = mhpmc4_wr_en0 | mhpmc4_wr_en1; - assign mhpmc4_incr[63:0] = {mhpmc4h[31:0],mhpmc4[31:0]} + {63'b0,mhpmc_inc_r[1]}; + assign mhpmc4_incr[63:0] = {mhpmc4h[31:0],mhpmc4[31:0]} + {63'b0,1'b1}; assign mhpmc4_ns[31:0] = mhpmc4_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc4_incr[31:0]; - rvdffe #(32) mhpmc4_ff (.*, .en(mhpmc4_wr_en), .din(mhpmc4_ns[31:0]), .dout(mhpmc4[31:0])); + rvdffe #(32) mhpmc4_ff (.*, .clk(free_l2clk), .en(mhpmc4_wr_en), .din(mhpmc4_ns[31:0]), .dout(mhpmc4[31:0])); - assign mhpmc4h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPMC4H); + assign mhpmc4h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC4H); assign mhpmc4h_wr_en = mhpmc4h_wr_en0 | mhpmc4_wr_en1; assign mhpmc4h_ns[31:0] = mhpmc4h_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc4_incr[63:32]; - rvdffe #(32) mhpmc4h_ff (.*, .en(mhpmc4h_wr_en), .din(mhpmc4h_ns[31:0]), .dout(mhpmc4h[31:0])); + rvdffe #(32) mhpmc4h_ff (.*, .clk(free_l2clk), .en(mhpmc4h_wr_en), .din(mhpmc4h_ns[31:0]), .dout(mhpmc4h[31:0])); // ---------------------------------------------------------------------- // MHPMC5H(RW), MHPMC5(RW) // [63:32][31:0] : Hardware Performance Monitor Counter 5 - `define MHPMC5 12'hB05 - `define MHPMC5H 12'hB85 + localparam MHPMC5 = 12'hB05; + localparam MHPMC5H = 12'hB85; - assign mhpmc5_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPMC5); + assign mhpmc5_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC5); assign mhpmc5_wr_en1 = (~perfcnt_halted | perfcnt_during_sleep[2]) & (|(mhpmc_inc_r[2])); assign mhpmc5_wr_en = mhpmc5_wr_en0 | mhpmc5_wr_en1; - assign mhpmc5_incr[63:0] = {mhpmc5h[31:0],mhpmc5[31:0]} + {63'b0,mhpmc_inc_r[2]}; + assign mhpmc5_incr[63:0] = {mhpmc5h[31:0],mhpmc5[31:0]} + {63'b0,1'b1}; assign mhpmc5_ns[31:0] = mhpmc5_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc5_incr[31:0]; - rvdffe #(32) mhpmc5_ff (.*, .en(mhpmc5_wr_en), .din(mhpmc5_ns[31:0]), .dout(mhpmc5[31:0])); + rvdffe #(32) mhpmc5_ff (.*, .clk(free_l2clk), .en(mhpmc5_wr_en), .din(mhpmc5_ns[31:0]), .dout(mhpmc5[31:0])); - assign mhpmc5h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPMC5H); + assign mhpmc5h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC5H); assign mhpmc5h_wr_en = mhpmc5h_wr_en0 | mhpmc5_wr_en1; assign mhpmc5h_ns[31:0] = mhpmc5h_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc5_incr[63:32]; - rvdffe #(32) mhpmc5h_ff (.*, .en(mhpmc5h_wr_en), .din(mhpmc5h_ns[31:0]), .dout(mhpmc5h[31:0])); + rvdffe #(32) mhpmc5h_ff (.*, .clk(free_l2clk), .en(mhpmc5h_wr_en), .din(mhpmc5h_ns[31:0]), .dout(mhpmc5h[31:0])); // ---------------------------------------------------------------------- // MHPMC6H(RW), MHPMC6(RW) // [63:32][31:0] : Hardware Performance Monitor Counter 6 - `define MHPMC6 12'hB06 - `define MHPMC6H 12'hB86 + localparam MHPMC6 = 12'hB06; + localparam MHPMC6H = 12'hB86; - assign mhpmc6_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPMC6); + assign mhpmc6_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC6); assign mhpmc6_wr_en1 = (~perfcnt_halted | perfcnt_during_sleep[3]) & (|(mhpmc_inc_r[3])); assign mhpmc6_wr_en = mhpmc6_wr_en0 | mhpmc6_wr_en1; - assign mhpmc6_incr[63:0] = {mhpmc6h[31:0],mhpmc6[31:0]} + {63'b0,mhpmc_inc_r[3]}; + assign mhpmc6_incr[63:0] = {mhpmc6h[31:0],mhpmc6[31:0]} + {63'b0,1'b1}; assign mhpmc6_ns[31:0] = mhpmc6_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc6_incr[31:0]; - rvdffe #(32) mhpmc6_ff (.*, .en(mhpmc6_wr_en), .din(mhpmc6_ns[31:0]), .dout(mhpmc6[31:0])); + rvdffe #(32) mhpmc6_ff (.*, .clk(free_l2clk), .en(mhpmc6_wr_en), .din(mhpmc6_ns[31:0]), .dout(mhpmc6[31:0])); - assign mhpmc6h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPMC6H); + assign mhpmc6h_wr_en0 = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPMC6H); assign mhpmc6h_wr_en = mhpmc6h_wr_en0 | mhpmc6_wr_en1; assign mhpmc6h_ns[31:0] = mhpmc6h_wr_en0 ? dec_csr_wrdata_r[31:0] : mhpmc6_incr[63:32]; - rvdffe #(32) mhpmc6h_ff (.*, .en(mhpmc6h_wr_en), .din(mhpmc6h_ns[31:0]), .dout(mhpmc6h[31:0])); + rvdffe #(32) mhpmc6h_ff (.*, .clk(free_l2clk), .en(mhpmc6h_wr_en), .din(mhpmc6h_ns[31:0]), .dout(mhpmc6h[31:0])); // ---------------------------------------------------------------------- // MHPME3(RW) // [9:0] : Hardware Performance Monitor Event 3 - `define MHPME3 12'h323 + localparam MHPME3 = 12'h323; - // we only have events 0-56, 512-516, HPME* are WARL so saturate otherwise - assign event_saturate_r[9:0] = ((dec_csr_wrdata_r[9:0] > 10'd516) | (|dec_csr_wrdata_r[31:10])) ? 10'd516 : dec_csr_wrdata_r[9:0]; + // we only have events 0-56 with holes, 512-516, HPME* are WARL so zero otherwise. + assign zero_event_r = ( (dec_csr_wrdata_r[9:0] > 10'd516) | + (|dec_csr_wrdata_r[31:10]) | + ((dec_csr_wrdata_r[9:0] < 10'd512) & (dec_csr_wrdata_r[9:0] > 10'd56)) | + ((dec_csr_wrdata_r[9:0] < 10'd54) & (dec_csr_wrdata_r[9:0] > 10'd50)) | + (dec_csr_wrdata_r[9:0] == 10'd29) | + (dec_csr_wrdata_r[9:0] == 10'd33) + ); - assign wr_mhpme3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPME3); - rvdffs #(10) mhpme3_ff (.*, .clk(active_clk), .en(wr_mhpme3_r), .din(event_saturate_r[9:0]), .dout(mhpme3[9:0])); + assign event_r[9:0] = zero_event_r ? '0 : dec_csr_wrdata_r[9:0]; + + assign wr_mhpme3_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPME3); + rvdffe #(10) mhpme3_ff (.*, .en(wr_mhpme3_r), .din(event_r[9:0]), .dout(mhpme3[9:0])); // ---------------------------------------------------------------------- // MHPME4(RW) // [9:0] : Hardware Performance Monitor Event 4 - `define MHPME4 12'h324 + localparam MHPME4 = 12'h324; - assign wr_mhpme4_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPME4); - rvdffs #(10) mhpme4_ff (.*, .clk(active_clk), .en(wr_mhpme4_r), .din(event_saturate_r[9:0]), .dout(mhpme4[9:0])); + assign wr_mhpme4_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPME4); + rvdffe #(10) mhpme4_ff (.*, .en(wr_mhpme4_r), .din(event_r[9:0]), .dout(mhpme4[9:0])); // ---------------------------------------------------------------------- // MHPME5(RW) // [9:0] : Hardware Performance Monitor Event 5 - `define MHPME5 12'h325 + localparam MHPME5 = 12'h325; - assign wr_mhpme5_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPME5); - rvdffs #(10) mhpme5_ff (.*, .clk(active_clk), .en(wr_mhpme5_r), .din(event_saturate_r[9:0]), .dout(mhpme5[9:0])); + assign wr_mhpme5_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPME5); + rvdffe #(10) mhpme5_ff (.*, .en(wr_mhpme5_r), .din(event_r[9:0]), .dout(mhpme5[9:0])); // ---------------------------------------------------------------------- // MHPME6(RW) // [9:0] : Hardware Performance Monitor Event 6 - `define MHPME6 12'h326 + localparam MHPME6 = 12'h326; - assign wr_mhpme6_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MHPME6); - rvdffs #(10) mhpme6_ff (.*, .clk(active_clk), .en(wr_mhpme6_r), .din(event_saturate_r[9:0]), .dout(mhpme6[9:0])); + assign wr_mhpme6_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MHPME6); + rvdffe #(10) mhpme6_ff (.*, .en(wr_mhpme6_r), .din(event_r[9:0]), .dout(mhpme6[9:0])); //---------------------------------------------------------------------- // Performance Monitor Counters section ends @@ -2244,27 +2324,37 @@ else // [1] : reserved, read 0x0 // [0] : MCYCLE disable - `define MCOUNTINHIBIT 12'h320 + localparam MCOUNTINHIBIT = 12'h320; - assign wr_mcountinhibit_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MCOUNTINHIBIT); - rvdffs #(6) mcountinhibit_ff (.*, .clk(active_clk), .en(wr_mcountinhibit_r), .din({dec_csr_wrdata_r[6:2], dec_csr_wrdata_r[0]}), .dout({mcountinhibit[6:2], mcountinhibit[0]})); + assign wr_mcountinhibit_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MCOUNTINHIBIT); + rvdffs #(6) mcountinhibit_ff (.*, .clk(csr_wr_clk), .en(wr_mcountinhibit_r), .din({dec_csr_wrdata_r[6:2], dec_csr_wrdata_r[0]}), .dout({mcountinhibit[6:2], mcountinhibit[0]})); assign mcountinhibit[1] = 1'b0; //-------------------------------------------------------------------------------- // trace //-------------------------------------------------------------------------------- + logic [4:0] dec_tlu_exc_cause_wb1_raw, dec_tlu_exc_cause_wb2; + logic dec_tlu_int_valid_wb1_raw, dec_tlu_int_valid_wb2; - rvoclkhdr trace_cgc ( .en(i0_valid_wb | exc_or_int_valid_r_d1 | interrupt_valid_r_d1 | dec_tlu_i0_valid_wb1 | - dec_tlu_i0_exc_valid_wb1 | dec_tlu_int_valid_wb1 | clk_override), .l1clk(trace_tclk), .* ); - rvdff #(8) traceff (.*, .clk(trace_tclk), - .din ({i0_valid_wb, - i0_exception_valid_r_d1 | lsu_i0_exc_r_d1 | (trigger_hit_r_d1 & ~trigger_hit_dmode_r_d1), - exc_cause_wb[4:0], - interrupt_valid_r_d1}), - .dout({dec_tlu_i0_valid_wb1, - dec_tlu_i0_exc_valid_wb1, - dec_tlu_exc_cause_wb1[4:0], - dec_tlu_int_valid_wb1})); + assign {dec_tlu_i0_valid_wb1, + dec_tlu_i0_exc_valid_wb1, + dec_tlu_exc_cause_wb1_raw[4:0], + dec_tlu_int_valid_wb1_raw} = {8{~dec_tlu_trace_disable}} & {i0_valid_wb, + i0_exception_valid_r_d1 | lsu_i0_exc_r_d1 | (trigger_hit_r_d1 & ~trigger_hit_dmode_r_d1), + exc_cause_wb[4:0], + interrupt_valid_r_d1}; + + + + // skid buffer for ints, reduces trace port count by 1 + rvdffie #(.WIDTH(6), .OVERRIDE(1)) traceskidff (.*, .clk(clk), + .din ({dec_tlu_exc_cause_wb1_raw[4:0], + dec_tlu_int_valid_wb1_raw}), + .dout({dec_tlu_exc_cause_wb2[4:0], + dec_tlu_int_valid_wb2})); + //skid for ints + assign dec_tlu_exc_cause_wb1[4:0] = dec_tlu_int_valid_wb2 ? dec_tlu_exc_cause_wb2[4:0] : dec_tlu_exc_cause_wb1_raw[4:0]; + assign dec_tlu_int_valid_wb1 = dec_tlu_int_valid_wb2; assign dec_tlu_mtval_wb1 = mtval[31:0]; @@ -2468,15 +2558,9 @@ assign csr_mitcnt1 = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[2] assign csr_mpmc = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3] &dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]); -assign csr_mcpc = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4] - &!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]); - assign csr_meicpct = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[6] &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]); -assign csr_mdeau = (!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[7] - &dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[3]); - assign csr_micect = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[3] &!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]); @@ -2625,12 +2709,12 @@ assign legal = (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9] &!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]); + assign dec_tlu_presync_d = presync & dec_csr_any_unq_d & ~dec_csr_wen_unq_d; assign dec_tlu_postsync_d = postsync & dec_csr_any_unq_d; // allow individual configuration of these features -assign conditionally_illegal = (csr_mitcnt0 | csr_mitcnt1 | csr_mitb0 | csr_mitb1 | csr_mitctl0 | csr_mitctl1) & ~pt.TIMER_LEGAL_EN; - +assign conditionally_illegal = ((csr_mitcnt0 | csr_mitcnt1 | csr_mitb0 | csr_mitb1 | csr_mitctl0 | csr_mitctl1) & !pt.TIMER_LEGAL_EN); assign valid_csr = ( legal & (~(csr_dcsr | csr_dpc | csr_dmst | csr_dicawics | csr_dicad0 | csr_dicad0h | csr_dicad1 | csr_dicago) | dbg_tlu_halted_f) & ~fast_int_meicpct & ~conditionally_illegal); @@ -2643,7 +2727,7 @@ assign dec_csr_legal_d = ( dec_csr_any_unq_d & assign dec_csr_rddata_d[31:0] = ( ({32{csr_misa}} & 32'h40001104) | ({32{csr_mvendorid}} & 32'h00000045) | ({32{csr_marchid}} & 32'h00000010) | - ({32{csr_mimpid}} & 32'h2) | + ({32{csr_mimpid}} & 32'h3) | ({32{csr_mhartid}} & {core_id[31:4], 4'b0}) | ({32{csr_mstatus}} & {19'b0, 2'b11, 3'b0, mstatus[1], 3'b0, mstatus[0], 3'b0}) | ({32{csr_mtvec}} & {mtvec[30:1], 1'b0, mtvec[0]}) | @@ -2665,7 +2749,7 @@ assign dec_csr_rddata_d[31:0] = ( ({32{csr_misa}} & 32'h40001104) | ({32{csr_meicurpl}} & {28'b0, meicurpl[3:0]}) | ({32{csr_meicidpl}} & {28'b0, meicidpl[3:0]}) | ({32{csr_meipt}} & {28'b0, meipt[3:0]}) | - ({32{csr_mcgc}} & {23'b0, mcgc[8:0]}) | + ({32{csr_mcgc}} & {22'b0, mcgc[9:0]}) | ({32{csr_mfdc}} & {13'b0, mfdc[18:0]}) | ({32{csr_dcsr}} & {16'h4000, dcsr[15:2], 2'b11}) | ({32{csr_dpc}} & {dpc[31:1], 1'b0}) | @@ -2698,6 +2782,8 @@ assign dec_csr_rddata_d[31:0] = ( ({32{csr_misa}} & 32'h40001104) | ({32{dec_timer_read_d}} & dec_timer_rddata_d[31:0]) ); + + endmodule // el2_dec_tlu_ctl module el2_dec_timer_ctl #( @@ -2705,10 +2791,10 @@ module el2_dec_timer_ctl #( ) ( input logic clk, - input logic free_clk, + input logic free_l2clk, + input logic csr_wr_clk, input logic rst_l, input logic dec_csr_wen_r_mod, // csr write enable at wb - input logic [11:0] dec_csr_rdaddr_d, // read address for csr input logic [11:0] dec_csr_wraddr_r, // write address for csr input logic [31:0] dec_csr_wrdata_r, // csr write data at wb @@ -2731,16 +2817,16 @@ module el2_dec_timer_ctl #( input logic scan_mode ); - `define MITCTL_ENABLE 0 - `define MITCTL_ENABLE_HALTED 1 - `define MITCTL_ENABLE_PAUSED 2 + localparam MITCTL_ENABLE = 0; + localparam MITCTL_ENABLE_HALTED = 1; + localparam MITCTL_ENABLE_PAUSED = 2; logic [31:0] mitcnt0_ns, mitcnt0, mitcnt1_ns, mitcnt1, mitb0, mitb1, mitb0_b, mitb1_b, mitcnt0_inc, mitcnt1_inc; logic [2:0] mitctl0_ns, mitctl0; logic [3:0] mitctl1_ns, mitctl1; logic wr_mitcnt0_r, wr_mitcnt1_r, wr_mitb0_r, wr_mitb1_r, wr_mitctl0_r, wr_mitctl1_r; logic mitcnt0_inc_ok, mitcnt1_inc_ok; - + logic mitcnt0_inc_cout, mitcnt1_inc_cout; logic mit0_match_ns; logic mit1_match_ns; logic mitctl0_0_b_ns; @@ -2757,40 +2843,51 @@ module el2_dec_timer_ctl #( // MITCNT0 (RW) // [31:0] : Internal Timer Counter 0 - `define MITCNT0 12'h7d2 + localparam MITCNT0 = 12'h7d2; - assign wr_mitcnt0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MITCNT0); + assign wr_mitcnt0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITCNT0); - assign mitcnt0_inc_ok = mitctl0[`MITCTL_ENABLE] & (~dec_pause_state | mitctl0[`MITCTL_ENABLE_PAUSED]) & (~dec_tlu_pmu_fw_halted | mitctl0[`MITCTL_ENABLE_HALTED]) & ~internal_dbg_halt_timers; + assign mitcnt0_inc_ok = mitctl0[MITCTL_ENABLE] & (~dec_pause_state | mitctl0[MITCTL_ENABLE_PAUSED]) & (~dec_tlu_pmu_fw_halted | mitctl0[MITCTL_ENABLE_HALTED]) & ~internal_dbg_halt_timers; - assign mitcnt0_inc[31:0] = mitcnt0[31:0] + {31'b0, 1'b1}; - assign mitcnt0_ns[31:0] = mit0_match_ns ? 'b0 : wr_mitcnt0_r ? dec_csr_wrdata_r[31:0] : mitcnt0_inc[31:0]; + assign {mitcnt0_inc_cout, mitcnt0_inc[7:0]} = mitcnt0[7:0] + {7'b0, 1'b1}; + assign mitcnt0_inc[31:8] = mitcnt0[31:8] + {23'b0, mitcnt0_inc_cout}; - rvdffe #(32) mitcnt0_ff (.*, .en(wr_mitcnt0_r | mitcnt0_inc_ok | mit0_match_ns), .din(mitcnt0_ns[31:0]), .dout(mitcnt0[31:0])); + assign mitcnt0_ns[31:0] = wr_mitcnt0_r ? dec_csr_wrdata_r[31:0] : mit0_match_ns ? 'b0 : mitcnt0_inc[31:0]; + + rvdffe #(24) mitcnt0_ffb (.*, .clk(free_l2clk), .en(wr_mitcnt0_r | (mitcnt0_inc_ok & mitcnt0_inc_cout) | mit0_match_ns), .din(mitcnt0_ns[31:8]), .dout(mitcnt0[31:8])); + rvdffe #(8) mitcnt0_ffa (.*, .clk(free_l2clk), .en(wr_mitcnt0_r | mitcnt0_inc_ok | mit0_match_ns), .din(mitcnt0_ns[7:0]), .dout(mitcnt0[7:0])); // ---------------------------------------------------------------------- // MITCNT1 (RW) // [31:0] : Internal Timer Counter 0 - `define MITCNT1 12'h7d5 + localparam MITCNT1 = 12'h7d5; - assign wr_mitcnt1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MITCNT1); + assign wr_mitcnt1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITCNT1); - assign mitcnt1_inc_ok = mitctl1[`MITCTL_ENABLE] & (~dec_pause_state | mitctl1[`MITCTL_ENABLE_PAUSED]) & (~dec_tlu_pmu_fw_halted | mitctl1[`MITCTL_ENABLE_HALTED]) & ~internal_dbg_halt_timers; + assign mitcnt1_inc_ok = mitctl1[MITCTL_ENABLE] & + (~dec_pause_state | mitctl1[MITCTL_ENABLE_PAUSED]) & + (~dec_tlu_pmu_fw_halted | mitctl1[MITCTL_ENABLE_HALTED]) & + ~internal_dbg_halt_timers & + (~mitctl1[3] | mit0_match_ns); // only inc MITCNT1 if not cascaded with 0, or if 0 overflows - assign mitcnt1_inc[31:0] = mitcnt1[31:0] + {31'b0, (~mitctl1[3] | mit0_match_ns)}; - assign mitcnt1_ns[31:0] = mit1_match_ns ? 'b0 : wr_mitcnt1_r ? dec_csr_wrdata_r[31:0] : mitcnt1_inc[31:0]; + assign {mitcnt1_inc_cout, mitcnt1_inc[7:0]} = mitcnt1[7:0] + {7'b0, 1'b1}; + assign mitcnt1_inc[31:8] = mitcnt1[31:8] + {23'b0, mitcnt1_inc_cout}; + + assign mitcnt1_ns[31:0] = wr_mitcnt1_r ? dec_csr_wrdata_r[31:0] : mit1_match_ns ? 'b0 : mitcnt1_inc[31:0]; + + rvdffe #(24) mitcnt1_ffb (.*, .clk(free_l2clk), .en(wr_mitcnt1_r | (mitcnt1_inc_ok & mitcnt1_inc_cout) | mit1_match_ns), .din(mitcnt1_ns[31:8]), .dout(mitcnt1[31:8])); + rvdffe #(8) mitcnt1_ffa (.*, .clk(free_l2clk), .en(wr_mitcnt1_r | mitcnt1_inc_ok | mit1_match_ns), .din(mitcnt1_ns[7:0]), .dout(mitcnt1[7:0])); - rvdffe #(32) mitcnt1_ff (.*, .en(wr_mitcnt1_r | mitcnt1_inc_ok | mit1_match_ns), .din(mitcnt1_ns[31:0]), .dout(mitcnt1[31:0])); // ---------------------------------------------------------------------- // MITB0 (RW) // [31:0] : Internal Timer Bound 0 - `define MITB0 12'h7d3 + localparam MITB0 = 12'h7d3; - assign wr_mitb0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MITB0); + assign wr_mitb0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITB0); rvdffe #(32) mitb0_ff (.*, .en(wr_mitb0_r), .din(~dec_csr_wrdata_r[31:0]), .dout(mitb0_b[31:0])); assign mitb0[31:0] = ~mitb0_b[31:0]; @@ -2799,9 +2896,9 @@ module el2_dec_timer_ctl #( // MITB1 (RW) // [31:0] : Internal Timer Bound 1 - `define MITB1 12'h7d6 + localparam MITB1 = 12'h7d6; - assign wr_mitb1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MITB1); + assign wr_mitb1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITB1); rvdffe #(32) mitb1_ff (.*, .en(wr_mitb1_r), .din(~dec_csr_wrdata_r[31:0]), .dout(mitb1_b[31:0])); assign mitb1[31:0] = ~mitb1_b[31:0]; @@ -2813,13 +2910,13 @@ module el2_dec_timer_ctl #( // [1] : Enable while HALTed // [0] : Enable (resets to 0x1) - `define MITCTL0 12'h7d4 + localparam MITCTL0 = 12'h7d4; - assign wr_mitctl0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MITCTL0); + assign wr_mitctl0_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITCTL0); assign mitctl0_ns[2:0] = wr_mitctl0_r ? {dec_csr_wrdata_r[2:0]} : {mitctl0[2:0]}; assign mitctl0_0_b_ns = ~mitctl0_ns[0]; - rvdff #(3) mitctl0_ff (.*, .clk(free_clk), .din({mitctl0_ns[2:1], mitctl0_0_b_ns}), .dout({mitctl0[2:1], mitctl0_0_b})); + rvdffs #(3) mitctl0_ff (.*, .clk(csr_wr_clk), .en(wr_mitctl0_r), .din({mitctl0_ns[2:1], mitctl0_0_b_ns}), .dout({mitctl0[2:1], mitctl0_0_b})); assign mitctl0[0] = ~mitctl0_0_b; // ---------------------------------------------------------------------- @@ -2830,13 +2927,13 @@ module el2_dec_timer_ctl #( // [1] : Enable while HALTed // [0] : Enable (resets to 0x1) - `define MITCTL1 12'h7d7 + localparam MITCTL1 = 12'h7d7; - assign wr_mitctl1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == `MITCTL1); + assign wr_mitctl1_r = dec_csr_wen_r_mod & (dec_csr_wraddr_r[11:0] == MITCTL1); assign mitctl1_ns[3:0] = wr_mitctl1_r ? {dec_csr_wrdata_r[3:0]} : {mitctl1[3:0]}; assign mitctl1_0_b_ns = ~mitctl1_ns[0]; - rvdff #(4) mitctl1_ff (.*, .clk(free_clk), .din({mitctl1_ns[3:1], mitctl1_0_b_ns}), .dout({mitctl1[3:1], mitctl1_0_b})); + rvdffs #(4) mitctl1_ff (.*, .clk(csr_wr_clk), .en(wr_mitctl1_r), .din({mitctl1_ns[3:1], mitctl1_0_b_ns}), .dout({mitctl1[3:1], mitctl1_0_b})); assign mitctl1[0] = ~mitctl1_0_b; assign dec_timer_read_d = csr_mitcnt1 | csr_mitcnt0 | csr_mitb1 | csr_mitb0 | csr_mitctl0 | csr_mitctl1; assign dec_timer_rddata_d[31:0] = ( ({32{csr_mitcnt0}} & mitcnt0[31:0]) | diff --git a/design/dec/el2_dec_trigger.sv b/design/dec/el2_dec_trigger.sv index 6a8b165..fce7298 100644 --- a/design/dec/el2_dec_trigger.sv +++ b/design/dec/el2_dec_trigger.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -29,9 +29,9 @@ import el2_pkg::*; )( input el2_trigger_pkt_t [3:0] trigger_pkt_any, // Packet from tlu. 'select':0-pc,1-Opcode 'Execute' needs to be set for dec triggers to fire. 'match'-1 do mask, 0: full match - input logic [31:1] dec_i0_pc_d, // i0 pc + input logic [31:1] dec_i0_pc_d, // i0 pc - output logic [3:0] dec_i0_trigger_match_d + output logic [3:0] dec_i0_trigger_match_d // Trigger match ); logic [3:0][31:0] dec_i0_match_data; diff --git a/design/dmi/rvjtag_tap.v b/design/dmi/rvjtag_tap.v index 2463434..2553575 100644 --- a/design/dmi/rvjtag_tap.v +++ b/design/dmi/rvjtag_tap.v @@ -173,6 +173,7 @@ always_comb begin endcase end capture_dr: begin + nsr[0] = 1'b0; case(1) dr_en[0]: nsr = {{USER_DR_LENGTH-15{1'b0}}, idle, dmi_stat, abits, version}; dr_en[1]: nsr = {{AWIDTH{1'b0}}, rd_data, rd_status}; diff --git a/design/el2_dma_ctrl.sv b/design/el2_dma_ctrl.sv index 13ff113..fcdaa42 100644 --- a/design/el2_dma_ctrl.sv +++ b/design/el2_dma_ctrl.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -64,6 +64,7 @@ module el2_dma_ctrl #( input logic [2:0] iccm_dma_rtag, // Tag of the DMA req input logic [63:0] iccm_dma_rdata, // iccm data for DMA read + output logic dma_active, // DMA is busy output logic dma_dccm_stall_any, // stall dccm pipe (bubble) so that DMA can proceed output logic dma_iccm_stall_any, // stall iccm pipe (bubble) so that DMA can proceed input logic dccm_ready, // dccm ready to accept DMA request @@ -154,6 +155,10 @@ module el2_dma_ctrl #( logic [DEPTH_PTR-1:0] RdPtr, NxtRdPtr; logic WrPtrEn, RdPtrEn, RspPtrEn; + logic [1:0] dma_dbg_sz; + logic [1:0] dma_dbg_addr; + logic [31:0] dma_dbg_mem_rddata; + logic [31:0] dma_dbg_mem_wrdata; logic dma_dbg_cmd_error; logic dma_dbg_cmd_done_q; @@ -193,6 +198,7 @@ module el2_dma_ctrl #( logic fifo_full_spec_bus; logic dbg_dma_bubble_bus; + logic stall_dma_in; logic dma_fifo_ready; logic wrbuf_en, wrbuf_data_en; @@ -225,14 +231,14 @@ module el2_dma_ctrl #( // FIFO inputs assign fifo_addr_in[31:0] = dbg_cmd_valid ? dbg_cmd_addr[31:0] : bus_cmd_addr[31:0]; - assign fifo_byteen_in[7:0] = dbg_cmd_valid ? (8'h0f << 4*dbg_cmd_addr[2]) : bus_cmd_byteen[7:0]; + assign fifo_byteen_in[7:0] = {8{~dbg_cmd_valid}} & bus_cmd_byteen[7:0]; // Byte enable is used only for bus requests assign fifo_sz_in[2:0] = dbg_cmd_valid ? {1'b0,dbg_cmd_size[1:0]} : bus_cmd_sz[2:0]; assign fifo_write_in = dbg_cmd_valid ? dbg_cmd_write : bus_cmd_write; assign fifo_posted_write_in = ~dbg_cmd_valid & bus_cmd_posted_write; assign fifo_dbg_in = dbg_cmd_valid; - for (genvar i=0 ;i<32'(DEPTH); i++) begin: GenFifo - assign fifo_cmd_en[i] = ((bus_cmd_sent & dma_bus_clk_en) | (dbg_cmd_valid & dbg_cmd_type[1])) & (DEPTH_PTR'(i) == WrPtr[DEPTH_PTR-1:0]); + for (genvar i=0 ;i> 8*dma_dbg_addr[1:0]) & 32'hff)) | + ({32{(dma_dbg_sz[1:0] == 2'h1)}} & ((dma_dbg_mem_rddata[31:0] >> 16*dma_dbg_addr[1]) & 32'hffff)) | + ({32{(dma_dbg_sz[1:0] == 2'h2)}} & dma_dbg_mem_rddata[31:0]); + assign dma_dbg_cmd_error = fifo_valid[RdPtr] & ~fifo_done[RdPtr] & fifo_dbg[RdPtr] & - ((~(dma_mem_addr_in_dccm | dma_mem_addr_in_iccm | dma_mem_addr_in_pic)) | (dma_mem_sz_int[1:0] != 2'b10)); // Only word accesses allowed + ((~(dma_mem_addr_in_dccm | dma_mem_addr_in_iccm | dma_mem_addr_in_pic)) | // Address outside of ICCM/DCCM/PIC + ((dma_mem_addr_in_iccm | dma_mem_addr_in_pic) & (dma_mem_sz_int[1:0] != 2'b10))); // Only word accesses allowed for ICCM/PIC + + assign dma_dbg_mem_wrdata[31:0] = ({32{dbg_cmd_size[1:0] == 2'h0}} & {4{dbg_cmd_wrdata[7:0]}}) | + ({32{dbg_cmd_size[1:0] == 2'h1}} & {2{dbg_cmd_wrdata[15:0]}}) | + ({32{dbg_cmd_size[1:0] == 2'h2}} & dbg_cmd_wrdata[31:0]); // Block the decode if fifo full assign dma_dccm_stall_any = dma_mem_req & (dma_mem_addr_in_dccm | dma_mem_addr_in_pic) & (dma_nack_count >= dma_nack_count_csr); assign dma_iccm_stall_any = dma_mem_req & dma_mem_addr_in_iccm & (dma_nack_count >= dma_nack_count_csr); // Used to indicate ready to debug - assign fifo_empty = ~(|(fifo_valid[DEPTH-1:0])); + assign fifo_empty = ~((|(fifo_valid[DEPTH-1:0])) | bus_cmd_sent); // Nack counter, stall the lsu pipe if 7 nacks assign dma_nack_count_csr[2:0] = dec_tlu_dma_qos_prty[2:0]; @@ -339,8 +356,8 @@ module el2_dma_ctrl #( assign dma_mem_tag[2:0] = 3'(RdPtr); assign dma_mem_addr_int[31:0] = fifo_addr[RdPtr]; assign dma_mem_sz_int[2:0] = fifo_sz[RdPtr]; - assign dma_mem_addr[31:0] = (dma_mem_write & (dma_mem_byteen[7:0] == 8'hf0)) ? {dma_mem_addr_int[31:3],1'b1,dma_mem_addr_int[1:0]} : dma_mem_addr_int[31:0]; - assign dma_mem_sz[2:0] = (dma_mem_write & ((dma_mem_byteen[7:0] == 8'h0f) | (dma_mem_byteen[7:0] == 8'hf0))) ? 3'h2 : dma_mem_sz_int[2:0]; + assign dma_mem_addr[31:0] = (dma_mem_write & ~fifo_dbg[RdPtr] & (dma_mem_byteen[7:0] == 8'hf0)) ? {dma_mem_addr_int[31:3],1'b1,dma_mem_addr_int[1:0]} : dma_mem_addr_int[31:0]; + assign dma_mem_sz[2:0] = (dma_mem_write & ~fifo_dbg[RdPtr] & ((dma_mem_byteen[7:0] == 8'h0f) | (dma_mem_byteen[7:0] == 8'hf0))) ? 3'h2 : dma_mem_sz_int[2:0]; assign dma_mem_byteen[7:0] = fifo_byteen[RdPtr]; assign dma_mem_write = fifo_write[RdPtr]; assign dma_mem_wdata[63:0] = fifo_data[RdPtr]; @@ -352,23 +369,27 @@ module el2_dma_ctrl #( assign dma_pmu_any_write = (dma_dccm_req | dma_iccm_req) & dma_mem_write; // Address check dccm - rvrangecheck #(.CCM_SADR(pt.DCCM_SADR), - .CCM_SIZE(pt.DCCM_SIZE)) addr_dccm_rangecheck ( - .addr(dma_mem_addr_int[31:0]), - .in_range(dma_mem_addr_in_dccm), - .in_region(dma_mem_addr_in_dccm_region_nc) - ); + if (pt.DCCM_ENABLE) begin: Gen_dccm_enable + rvrangecheck #(.CCM_SADR(pt.DCCM_SADR), + .CCM_SIZE(pt.DCCM_SIZE)) addr_dccm_rangecheck ( + .addr(dma_mem_addr_int[31:0]), + .in_range(dma_mem_addr_in_dccm), + .in_region(dma_mem_addr_in_dccm_region_nc) + ); + end else begin: Gen_dccm_disable + assign dma_mem_addr_in_dccm = '0; + assign dma_mem_addr_in_dccm_region_nc = '0; + end // else: !if(pt.ICCM_ENABLE) // Address check iccm - if (pt.ICCM_ENABLE) begin + if (pt.ICCM_ENABLE) begin: Gen_iccm_enable rvrangecheck #(.CCM_SADR(pt.ICCM_SADR), .CCM_SIZE(pt.ICCM_SIZE)) addr_iccm_rangecheck ( .addr(dma_mem_addr_int[31:0]), .in_range(dma_mem_addr_in_iccm), .in_region(dma_mem_addr_in_iccm_region_nc) ); - end - else begin + end else begin: Gen_iccm_disable assign dma_mem_addr_in_iccm = '0; assign dma_mem_addr_in_iccm_region_nc = '0; end // else: !if(pt.ICCM_ENABLE) @@ -382,11 +403,10 @@ module el2_dma_ctrl #( .in_region(dma_mem_addr_in_pic_region_nc) ); - // Inputs - rvdff #(1) fifo_full_bus_ff (.din(fifo_full_spec), .dout(fifo_full_spec_bus), .clk(dma_bus_clk), .*); - rvdff #(1) dbg_dma_bubble_ff (.din(dbg_dma_bubble), .dout(dbg_dma_bubble_bus), .clk(dma_bus_clk), .*); - rvdff #(1) dma_dbg_cmd_doneff (.din(dma_dbg_cmd_done), .dout(dma_dbg_cmd_done_q), .clk(free_clk), .*); + rvdff_fpga #(1) fifo_full_bus_ff (.din(fifo_full_spec), .dout(fifo_full_spec_bus), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdff_fpga #(1) dbg_dma_bubble_ff (.din(dbg_dma_bubble), .dout(dbg_dma_bubble_bus), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdff #(1) dma_dbg_cmd_doneff (.din(dma_dbg_cmd_done), .dout(dma_dbg_cmd_done_q), .clk(free_clk), .*); // Clock Gating logic assign dma_buffer_c1_clken = (bus_cmd_valid & dma_bus_clk_en) | dbg_cmd_valid | clk_override; @@ -394,7 +414,12 @@ module el2_dma_ctrl #( rvoclkhdr dma_buffer_c1cgc ( .en(dma_buffer_c1_clken), .l1clk(dma_buffer_c1_clk), .* ); rvoclkhdr dma_free_cgc (.en(dma_free_clken), .l1clk(dma_free_clk), .*); + +`ifdef RV_FPGA_OPTIMIZE + assign dma_bus_clk = 1'b0; +`else rvclkhdr dma_bus_cgc (.en(dma_bus_clk_en), .l1clk(dma_bus_clk), .*); +`endif // Write channel buffer assign wrbuf_en = dma_axi_awvalid & dma_axi_awready; @@ -403,23 +428,23 @@ module el2_dma_ctrl #( assign wrbuf_rst = wrbuf_cmd_sent & ~wrbuf_en; assign wrbuf_data_rst = wrbuf_cmd_sent & ~wrbuf_data_en; - rvdffsc #(.WIDTH(1)) wrbuf_vldff(.din(1'b1), .dout(wrbuf_vld), .en(wrbuf_en), .clear(wrbuf_rst), .clk(dma_bus_clk), .*); - rvdffsc #(.WIDTH(1)) wrbuf_data_vldff(.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_data_rst), .clk(dma_bus_clk), .*); - rvdffs #(.WIDTH(pt.DMA_BUS_TAG)) wrbuf_tagff(.din(dma_axi_awid[pt.DMA_BUS_TAG-1:0]), .dout(wrbuf_tag[pt.DMA_BUS_TAG-1:0]), .en(wrbuf_en), .clk(dma_bus_clk), .*); - rvdffs #(.WIDTH(3)) wrbuf_szff(.din(dma_axi_awsize[2:0]), .dout(wrbuf_sz[2:0]), .en(wrbuf_en), .clk(dma_bus_clk), .*); - rvdffe #(.WIDTH(32)) wrbuf_addrff(.din(dma_axi_awaddr[31:0]), .dout(wrbuf_addr[31:0]), .en(wrbuf_en & dma_bus_clk_en), .*); - rvdffe #(.WIDTH(64)) wrbuf_dataff(.din(dma_axi_wdata[63:0]), .dout(wrbuf_data[63:0]), .en(wrbuf_data_en & dma_bus_clk_en), .*); - rvdffs #(.WIDTH(8)) wrbuf_byteenff(.din(dma_axi_wstrb[7:0]), .dout(wrbuf_byteen[7:0]), .en(wrbuf_data_en), .clk(dma_bus_clk), .*); + rvdffsc_fpga #(.WIDTH(1)) wrbuf_vldff (.din(1'b1), .dout(wrbuf_vld), .en(wrbuf_en), .clear(wrbuf_rst), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdffsc_fpga #(.WIDTH(1)) wrbuf_data_vldff (.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_data_rst), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(pt.DMA_BUS_TAG)) wrbuf_tagff (.din(dma_axi_awid[pt.DMA_BUS_TAG-1:0]), .dout(wrbuf_tag[pt.DMA_BUS_TAG-1:0]), .en(wrbuf_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(3)) wrbuf_szff (.din(dma_axi_awsize[2:0]), .dout(wrbuf_sz[2:0]), .en(wrbuf_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdffe #(.WIDTH(32)) wrbuf_addrff (.din(dma_axi_awaddr[31:0]), .dout(wrbuf_addr[31:0]), .en(wrbuf_en & dma_bus_clk_en), .*); + rvdffe #(.WIDTH(64)) wrbuf_dataff (.din(dma_axi_wdata[63:0]), .dout(wrbuf_data[63:0]), .en(wrbuf_data_en & dma_bus_clk_en), .*); + rvdffs_fpga #(.WIDTH(8)) wrbuf_byteenff (.din(dma_axi_wstrb[7:0]), .dout(wrbuf_byteen[7:0]), .en(wrbuf_data_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); // Read channel buffer assign rdbuf_en = dma_axi_arvalid & dma_axi_arready; assign rdbuf_cmd_sent = bus_cmd_sent & ~bus_cmd_write; assign rdbuf_rst = rdbuf_cmd_sent & ~rdbuf_en; - rvdffsc #(.WIDTH(1)) rdbuf_vldff(.din(1'b1), .dout(rdbuf_vld), .en(rdbuf_en), .clear(rdbuf_rst), .clk(dma_bus_clk), .*); - rvdffs #(.WIDTH(pt.DMA_BUS_TAG)) rdbuf_tagff(.din(dma_axi_arid[pt.DMA_BUS_TAG-1:0]), .dout(rdbuf_tag[pt.DMA_BUS_TAG-1:0]), .en(rdbuf_en), .clk(dma_bus_clk), .*); - rvdffs #(.WIDTH(3)) rdbuf_szff(.din(dma_axi_arsize[2:0]), .dout(rdbuf_sz[2:0]), .en(rdbuf_en), .clk(dma_bus_clk), .*); - rvdffe #(.WIDTH(32)) rdbuf_addrff(.din(dma_axi_araddr[31:0]), .dout(rdbuf_addr[31:0]), .en(rdbuf_en & dma_bus_clk_en), .*); + rvdffsc_fpga #(.WIDTH(1)) rdbuf_vldff (.din(1'b1), .dout(rdbuf_vld), .en(rdbuf_en), .clear(rdbuf_rst), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(pt.DMA_BUS_TAG)) rdbuf_tagff (.din(dma_axi_arid[pt.DMA_BUS_TAG-1:0]), .dout(rdbuf_tag[pt.DMA_BUS_TAG-1:0]), .en(rdbuf_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(3)) rdbuf_szff (.din(dma_axi_arsize[2:0]), .dout(rdbuf_sz[2:0]), .en(rdbuf_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); + rvdffe #(.WIDTH(32)) rdbuf_addrff (.din(dma_axi_araddr[31:0]), .dout(rdbuf_addr[31:0]), .en(rdbuf_en & dma_bus_clk_en), .*); assign dma_axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent); assign dma_axi_wready = ~(wrbuf_data_vld & ~wrbuf_cmd_sent); @@ -442,7 +467,7 @@ module el2_dma_ctrl #( assign axi_mstr_sel = (wrbuf_vld & wrbuf_data_vld & rdbuf_vld) ? axi_mstr_priority : (wrbuf_vld & wrbuf_data_vld); assign axi_mstr_prty_in = ~axi_mstr_priority; assign axi_mstr_prty_en = bus_cmd_sent; - rvdffs #(.WIDTH(1)) mstr_prtyff(.din(axi_mstr_prty_in), .dout(axi_mstr_priority), .en(axi_mstr_prty_en), .clk(dma_bus_clk), .*); + rvdffs_fpga #(.WIDTH(1)) mstr_prtyff(.din(axi_mstr_prty_in), .dout(axi_mstr_priority), .en(axi_mstr_prty_en), .clk(dma_bus_clk), .clken(dma_bus_clk_en), .rawclk(clk), .*); assign axi_rsp_valid = fifo_valid[RspPtr] & ~fifo_dbg[RspPtr] & fifo_done_bus[RspPtr]; assign axi_rsp_rdata[63:0] = fifo_data[RspPtr]; @@ -465,7 +490,10 @@ module el2_dma_ctrl #( assign bus_rsp_valid = (dma_axi_bvalid | dma_axi_rvalid); assign bus_rsp_sent = (dma_axi_bvalid & dma_axi_bready) | (dma_axi_rvalid & dma_axi_rready); -`ifdef ASSERT_ON + assign dma_active = wrbuf_vld | rdbuf_vld | (|fifo_valid[DEPTH-1:0]); + + +`ifdef RV_ASSERT_ON for (genvar i=0; i AHB Gasket for LSU axi4_to_ahb #(.pt(pt), .TAG(pt.LSU_BUS_TAG)) lsu_axi4_to_ahb ( + + .clk(free_l2clk), + .free_clk(free_clk), + .rst_l(core_rst_l), .clk_override(dec_tlu_bus_clk_override), .bus_clk_en(lsu_bus_clk_en), + .dec_tlu_force_halt(dec_tlu_force_halt), // AXI Write Channels .axi_awvalid(lsu_axi_awvalid), @@ -983,9 +1019,12 @@ import el2_pkg::*; axi4_to_ahb #(.pt(pt), .TAG(pt.IFU_BUS_TAG)) ifu_axi4_to_ahb ( - .clk(clk), + .clk(free_l2clk), + .free_clk(free_clk), + .rst_l(core_rst_l), .clk_override(dec_tlu_bus_clk_override), .bus_clk_en(ifu_bus_clk_en), + .dec_tlu_force_halt(dec_tlu_force_halt), // AHB-Lite signals .ahb_haddr(haddr[31:0]), @@ -1040,8 +1079,12 @@ import el2_pkg::*; // AXI4 -> AHB Gasket for System Bus axi4_to_ahb #(.pt(pt), .TAG(pt.SB_BUS_TAG)) sb_axi4_to_ahb ( + .clk(free_l2clk), + .free_clk(free_clk), + .rst_l(dbg_rst_l), .clk_override(dec_tlu_bus_clk_override), .bus_clk_en(dbg_bus_clk_en), + .dec_tlu_force_halt(1'b0), // AXI Write Channels .axi_awvalid(sb_axi_awvalid), @@ -1096,6 +1139,8 @@ import el2_pkg::*; //AHB -> AXI4 Gasket for DMA ahb_to_axi4 #(.pt(pt), .TAG(pt.DMA_BUS_TAG)) dma_ahb_to_axi4 ( + .clk(free_l2clk), + .rst_l(core_rst_l), .clk_override(dec_tlu_bus_clk_override), .bus_clk_en(dma_bus_clk_en), @@ -1219,7 +1264,7 @@ import el2_pkg::*; if (pt.BUILD_AHB_LITE == 1) begin -`ifdef ASSERT_ON +`ifdef RV_ASSERT_ON property ahb_trxn_aligned; @(posedge clk) disable iff(~rst_l) (lsu_htrans[1:0] != 2'b0) |-> ((lsu_hsize[2:0] == 3'h0) | ((lsu_hsize[2:0] == 3'h1) & (lsu_haddr[0] == 1'b0)) | @@ -1244,15 +1289,19 @@ if (pt.BUILD_AHB_LITE == 1) begin // unpack packet // also need retires_p==3 - assign trace_rv_i_insn_ip[31:0] = rv_trace_pkt.rv_i_insn_ip[31:0]; - assign trace_rv_i_address_ip[31:0] = rv_trace_pkt.rv_i_address_ip[31:0]; - assign trace_rv_i_valid_ip[1:0] = rv_trace_pkt.rv_i_valid_ip[1:0]; - assign trace_rv_i_exception_ip[1:0] = rv_trace_pkt.rv_i_exception_ip[1:0]; - assign trace_rv_i_ecause_ip[4:0] = rv_trace_pkt.rv_i_ecause_ip[4:0]; - assign trace_rv_i_interrupt_ip[1:0] = rv_trace_pkt.rv_i_interrupt_ip[1:0]; - assign trace_rv_i_tval_ip[31:0] = rv_trace_pkt.rv_i_tval_ip[31:0]; + assign trace_rv_i_insn_ip[31:0] = trace_rv_trace_pkt.trace_rv_i_insn_ip[31:0]; + assign trace_rv_i_address_ip[31:0] = trace_rv_trace_pkt.trace_rv_i_address_ip[31:0]; + assign trace_rv_i_valid_ip = trace_rv_trace_pkt.trace_rv_i_valid_ip; + + assign trace_rv_i_exception_ip = trace_rv_trace_pkt.trace_rv_i_exception_ip; + + assign trace_rv_i_ecause_ip[4:0] = trace_rv_trace_pkt.trace_rv_i_ecause_ip[4:0]; + + assign trace_rv_i_interrupt_ip = trace_rv_trace_pkt.trace_rv_i_interrupt_ip; + + assign trace_rv_i_tval_ip[31:0] = trace_rv_trace_pkt.trace_rv_i_tval_ip[31:0]; diff --git a/design/el2_swerv_wrapper.sv b/design/el2_swerv_wrapper.sv index eddf515..e6de23d 100644 --- a/design/el2_swerv_wrapper.sv +++ b/design/el2_swerv_wrapper.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,22 +26,22 @@ import el2_pkg::*; `include "el2_param.vh" ) ( - input logic clk, - input logic rst_l, - input logic dbg_rst_l, - input logic [31:1] rst_vec, - input logic nmi_int, - input logic [31:1] nmi_vec, - input logic [31:1] jtag_id, + input logic clk, + input logic rst_l, + input logic dbg_rst_l, + input logic [31:1] rst_vec, + input logic nmi_int, + input logic [31:1] nmi_vec, + input logic [31:1] jtag_id, - output logic [31:0] trace_rv_i_insn_ip, - output logic [31:0] trace_rv_i_address_ip, - output logic [1:0] trace_rv_i_valid_ip, - output logic [1:0] trace_rv_i_exception_ip, - output logic [4:0] trace_rv_i_ecause_ip, - output logic [1:0] trace_rv_i_interrupt_ip, - output logic [31:0] trace_rv_i_tval_ip, + output logic [31:0] trace_rv_i_insn_ip, + output logic [31:0] trace_rv_i_address_ip, + output logic trace_rv_i_valid_ip, + output logic trace_rv_i_exception_ip, + output logic [4:0] trace_rv_i_ecause_ip, + output logic trace_rv_i_interrupt_ip, + output logic [31:0] trace_rv_i_tval_ip, // Bus signals `ifdef RV_BUILD_AXI4 @@ -49,7 +49,7 @@ import el2_pkg::*; // AXI Write Channels output logic lsu_axi_awvalid, input logic lsu_axi_awready, - output logic [pt.LSU_BUS_TAG-1:0] lsu_axi_awid, + output logic [pt.LSU_BUS_TAG-1:0] lsu_axi_awid, output logic [31:0] lsu_axi_awaddr, output logic [3:0] lsu_axi_awregion, output logic [7:0] lsu_axi_awlen, @@ -69,12 +69,12 @@ import el2_pkg::*; input logic lsu_axi_bvalid, output logic lsu_axi_bready, input logic [1:0] lsu_axi_bresp, - input logic [pt.LSU_BUS_TAG-1:0] lsu_axi_bid, + input logic [pt.LSU_BUS_TAG-1:0] lsu_axi_bid, // AXI Read Channels output logic lsu_axi_arvalid, input logic lsu_axi_arready, - output logic [pt.LSU_BUS_TAG-1:0] lsu_axi_arid, + output logic [pt.LSU_BUS_TAG-1:0] lsu_axi_arid, output logic [31:0] lsu_axi_araddr, output logic [3:0] lsu_axi_arregion, output logic [7:0] lsu_axi_arlen, @@ -87,7 +87,7 @@ import el2_pkg::*; input logic lsu_axi_rvalid, output logic lsu_axi_rready, - input logic [pt.LSU_BUS_TAG-1:0] lsu_axi_rid, + input logic [pt.LSU_BUS_TAG-1:0] lsu_axi_rid, input logic [63:0] lsu_axi_rdata, input logic [1:0] lsu_axi_rresp, input logic lsu_axi_rlast, @@ -96,7 +96,7 @@ import el2_pkg::*; // AXI Write Channels output logic ifu_axi_awvalid, input logic ifu_axi_awready, - output logic [pt.IFU_BUS_TAG-1:0] ifu_axi_awid, + output logic [pt.IFU_BUS_TAG-1:0] ifu_axi_awid, output logic [31:0] ifu_axi_awaddr, output logic [3:0] ifu_axi_awregion, output logic [7:0] ifu_axi_awlen, @@ -116,12 +116,12 @@ import el2_pkg::*; input logic ifu_axi_bvalid, output logic ifu_axi_bready, input logic [1:0] ifu_axi_bresp, - input logic [pt.IFU_BUS_TAG-1:0] ifu_axi_bid, + input logic [pt.IFU_BUS_TAG-1:0] ifu_axi_bid, // AXI Read Channels output logic ifu_axi_arvalid, input logic ifu_axi_arready, - output logic [pt.IFU_BUS_TAG-1:0] ifu_axi_arid, + output logic [pt.IFU_BUS_TAG-1:0] ifu_axi_arid, output logic [31:0] ifu_axi_araddr, output logic [3:0] ifu_axi_arregion, output logic [7:0] ifu_axi_arlen, @@ -134,7 +134,7 @@ import el2_pkg::*; input logic ifu_axi_rvalid, output logic ifu_axi_rready, - input logic [pt.IFU_BUS_TAG-1:0] ifu_axi_rid, + input logic [pt.IFU_BUS_TAG-1:0] ifu_axi_rid, input logic [63:0] ifu_axi_rdata, input logic [1:0] ifu_axi_rresp, input logic ifu_axi_rlast, @@ -143,7 +143,7 @@ import el2_pkg::*; // AXI Write Channels output logic sb_axi_awvalid, input logic sb_axi_awready, - output logic [pt.SB_BUS_TAG-1:0] sb_axi_awid, + output logic [pt.SB_BUS_TAG-1:0] sb_axi_awid, output logic [31:0] sb_axi_awaddr, output logic [3:0] sb_axi_awregion, output logic [7:0] sb_axi_awlen, @@ -163,12 +163,12 @@ import el2_pkg::*; input logic sb_axi_bvalid, output logic sb_axi_bready, input logic [1:0] sb_axi_bresp, - input logic [pt.SB_BUS_TAG-1:0] sb_axi_bid, + input logic [pt.SB_BUS_TAG-1:0] sb_axi_bid, // AXI Read Channels output logic sb_axi_arvalid, input logic sb_axi_arready, - output logic [pt.SB_BUS_TAG-1:0] sb_axi_arid, + output logic [pt.SB_BUS_TAG-1:0] sb_axi_arid, output logic [31:0] sb_axi_araddr, output logic [3:0] sb_axi_arregion, output logic [7:0] sb_axi_arlen, @@ -181,160 +181,168 @@ import el2_pkg::*; input logic sb_axi_rvalid, output logic sb_axi_rready, - input logic [pt.SB_BUS_TAG-1:0] sb_axi_rid, + input logic [pt.SB_BUS_TAG-1:0] sb_axi_rid, input logic [63:0] sb_axi_rdata, input logic [1:0] sb_axi_rresp, input logic sb_axi_rlast, //-------------------------- DMA AXI signals-------------------------- // AXI Write Channels - input logic dma_axi_awvalid, - output logic dma_axi_awready, - input logic [pt.DMA_BUS_TAG-1:0] dma_axi_awid, - input logic [31:0] dma_axi_awaddr, - input logic [2:0] dma_axi_awsize, - input logic [2:0] dma_axi_awprot, - input logic [7:0] dma_axi_awlen, - input logic [1:0] dma_axi_awburst, + input logic dma_axi_awvalid, + output logic dma_axi_awready, + input logic [pt.DMA_BUS_TAG-1:0] dma_axi_awid, + input logic [31:0] dma_axi_awaddr, + input logic [2:0] dma_axi_awsize, + input logic [2:0] dma_axi_awprot, + input logic [7:0] dma_axi_awlen, + input logic [1:0] dma_axi_awburst, - input logic dma_axi_wvalid, - output logic dma_axi_wready, - input logic [63:0] dma_axi_wdata, - input logic [7:0] dma_axi_wstrb, - input logic dma_axi_wlast, + input logic dma_axi_wvalid, + output logic dma_axi_wready, + input logic [63:0] dma_axi_wdata, + input logic [7:0] dma_axi_wstrb, + input logic dma_axi_wlast, - output logic dma_axi_bvalid, - input logic dma_axi_bready, - output logic [1:0] dma_axi_bresp, - output logic [pt.DMA_BUS_TAG-1:0] dma_axi_bid, + output logic dma_axi_bvalid, + input logic dma_axi_bready, + output logic [1:0] dma_axi_bresp, + output logic [pt.DMA_BUS_TAG-1:0] dma_axi_bid, // AXI Read Channels - input logic dma_axi_arvalid, - output logic dma_axi_arready, - input logic [pt.DMA_BUS_TAG-1:0] dma_axi_arid, - input logic [31:0] dma_axi_araddr, - input logic [2:0] dma_axi_arsize, - input logic [2:0] dma_axi_arprot, - input logic [7:0] dma_axi_arlen, - input logic [1:0] dma_axi_arburst, + input logic dma_axi_arvalid, + output logic dma_axi_arready, + input logic [pt.DMA_BUS_TAG-1:0] dma_axi_arid, + input logic [31:0] dma_axi_araddr, + input logic [2:0] dma_axi_arsize, + input logic [2:0] dma_axi_arprot, + input logic [7:0] dma_axi_arlen, + input logic [1:0] dma_axi_arburst, - output logic dma_axi_rvalid, - input logic dma_axi_rready, - output logic [pt.DMA_BUS_TAG-1:0] dma_axi_rid, - output logic [63:0] dma_axi_rdata, - output logic [1:0] dma_axi_rresp, - output logic dma_axi_rlast, + output logic dma_axi_rvalid, + input logic dma_axi_rready, + output logic [pt.DMA_BUS_TAG-1:0] dma_axi_rid, + output logic [63:0] dma_axi_rdata, + output logic [1:0] dma_axi_rresp, + output logic dma_axi_rlast, `endif `ifdef RV_BUILD_AHB_LITE //// AHB LITE BUS - output logic [31:0] haddr, - output logic [2:0] hburst, - output logic hmastlock, - output logic [3:0] hprot, - output logic [2:0] hsize, - output logic [1:0] htrans, - output logic hwrite, + output logic [31:0] haddr, + output logic [2:0] hburst, + output logic hmastlock, + output logic [3:0] hprot, + output logic [2:0] hsize, + output logic [1:0] htrans, + output logic hwrite, - input logic [63:0] hrdata, - input logic hready, - input logic hresp, + input logic [63:0] hrdata, + input logic hready, + input logic hresp, // LSU AHB Master - output logic [31:0] lsu_haddr, - output logic [2:0] lsu_hburst, - output logic lsu_hmastlock, - output logic [3:0] lsu_hprot, - output logic [2:0] lsu_hsize, - output logic [1:0] lsu_htrans, - output logic lsu_hwrite, - output logic [63:0] lsu_hwdata, + output logic [31:0] lsu_haddr, + output logic [2:0] lsu_hburst, + output logic lsu_hmastlock, + output logic [3:0] lsu_hprot, + output logic [2:0] lsu_hsize, + output logic [1:0] lsu_htrans, + output logic lsu_hwrite, + output logic [63:0] lsu_hwdata, - input logic [63:0] lsu_hrdata, - input logic lsu_hready, - input logic lsu_hresp, + input logic [63:0] lsu_hrdata, + input logic lsu_hready, + input logic lsu_hresp, // Debug Syster Bus AHB - output logic [31:0] sb_haddr, - output logic [2:0] sb_hburst, - output logic sb_hmastlock, - output logic [3:0] sb_hprot, - output logic [2:0] sb_hsize, - output logic [1:0] sb_htrans, - output logic sb_hwrite, - output logic [63:0] sb_hwdata, + output logic [31:0] sb_haddr, + output logic [2:0] sb_hburst, + output logic sb_hmastlock, + output logic [3:0] sb_hprot, + output logic [2:0] sb_hsize, + output logic [1:0] sb_htrans, + output logic sb_hwrite, + output logic [63:0] sb_hwdata, - input logic [63:0] sb_hrdata, - input logic sb_hready, - input logic sb_hresp, + input logic [63:0] sb_hrdata, + input logic sb_hready, + input logic sb_hresp, // DMA Slave - input logic dma_hsel, - input logic [31:0] dma_haddr, - input logic [2:0] dma_hburst, - input logic dma_hmastlock, - input logic [3:0] dma_hprot, - input logic [2:0] dma_hsize, - input logic [1:0] dma_htrans, - input logic dma_hwrite, - input logic [63:0] dma_hwdata, - input logic dma_hreadyin, + input logic dma_hsel, + input logic [31:0] dma_haddr, + input logic [2:0] dma_hburst, + input logic dma_hmastlock, + input logic [3:0] dma_hprot, + input logic [2:0] dma_hsize, + input logic [1:0] dma_htrans, + input logic dma_hwrite, + input logic [63:0] dma_hwdata, + input logic dma_hreadyin, - output logic [63:0] dma_hrdata, - output logic dma_hreadyout, - output logic dma_hresp, + output logic [63:0] dma_hrdata, + output logic dma_hreadyout, + output logic dma_hresp, `endif // clk ratio signals - input logic lsu_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface - input logic ifu_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface - input logic dbg_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface - input logic dma_bus_clk_en, // Clock ratio b/w cpu core clk & AHB slave interface + input logic lsu_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface + input logic ifu_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface + input logic dbg_bus_clk_en, // Clock ratio b/w cpu core clk & AHB master interface + input logic dma_bus_clk_en, // Clock ratio b/w cpu core clk & AHB slave interface + // all of these test inputs are brought to top-level; must be tied off based on usage by physical design (ie. icache or not, iccm or not, dccm or not) -// input logic ext_int, - input logic timer_int, - input logic soft_int, - input logic [pt.PIC_TOTAL_INT:1] extintsrc_req, + input el2_dccm_ext_in_pkt_t [pt.DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt, + input el2_ccm_ext_in_pkt_t [pt.ICCM_NUM_BANKS-1:0] iccm_ext_in_pkt, + input el2_ic_data_ext_in_pkt_t [pt.ICACHE_NUM_WAYS-1:0][pt.ICACHE_BANKS_WAY-1:0] ic_data_ext_in_pkt, + input el2_ic_tag_ext_in_pkt_t [pt.ICACHE_NUM_WAYS-1:0] ic_tag_ext_in_pkt, - output logic dec_tlu_perfcnt0, // toggles when slot0 perf counter 0 has an event inc - output logic dec_tlu_perfcnt1, - output logic dec_tlu_perfcnt2, - output logic dec_tlu_perfcnt3, + input logic timer_int, + input logic soft_int, + input logic [pt.PIC_TOTAL_INT:1] extintsrc_req, - input logic jtag_tck, // JTAG clk - input logic jtag_tms, // JTAG TMS - input logic jtag_tdi, // JTAG tdi - input logic jtag_trst_n, // JTAG Reset - output logic jtag_tdo, // JTAG TDO + output logic dec_tlu_perfcnt0, // toggles when slot0 perf counter 0 has an event inc + output logic dec_tlu_perfcnt1, + output logic dec_tlu_perfcnt2, + output logic dec_tlu_perfcnt3, + + // ports added by the soc team + input logic jtag_tck, // JTAG clk + input logic jtag_tms, // JTAG TMS + input logic jtag_tdi, // JTAG tdi + input logic jtag_trst_n, // JTAG Reset + output logic jtag_tdo, // JTAG TDO input logic [31:4] core_id, // external MPC halt/run interface - input logic mpc_debug_halt_req, // Async halt request - input logic mpc_debug_run_req, // Async run request - input logic mpc_reset_run_req, // Run/halt after reset - output logic mpc_debug_halt_ack, // Halt ack - output logic mpc_debug_run_ack, // Run ack - output logic debug_brkpt_status, // debug breakpoint + input logic mpc_debug_halt_req, // Async halt request + input logic mpc_debug_run_req, // Async run request + input logic mpc_reset_run_req, // Run/halt after reset + output logic mpc_debug_halt_ack, // Halt ack + output logic mpc_debug_run_ack, // Run ack + output logic debug_brkpt_status, // debug breakpoint - input logic i_cpu_halt_req, // Async halt req to CPU - output logic o_cpu_halt_ack, // core response to halt - output logic o_cpu_halt_status, // 1'b1 indicates core is halted - output logic o_debug_mode_status, // Core to the PMU that core is in debug mode. When core is in debug mode, the PMU should refrain from sendng a halt or run request - input logic i_cpu_run_req, // Async restart req to CPU - output logic o_cpu_run_ack, // Core response to run req - input logic scan_mode, // To enable scan mode - input logic mbist_mode // to enable mbist + input logic i_cpu_halt_req, // Async halt req to CPU + output logic o_cpu_halt_ack, // core response to halt + output logic o_cpu_halt_status, // 1'b1 indicates core is halted + output logic o_debug_mode_status, // Core to the PMU that core is in debug mode. When core is in debug mode, the PMU should refrain from sendng a halt or run request + input logic i_cpu_run_req, // Async restart req to CPU + output logic o_cpu_run_ack, // Core response to run req + input logic scan_mode, // To enable scan mode + input logic mbist_mode // to enable mbist ); + logic active_l2clk; + logic free_l2clk; // DCCM ports logic dccm_wren; logic dccm_rden; - logic [pt.DCCM_BITS-1:0] dccm_wr_addr_lo; - logic [pt.DCCM_BITS-1:0] dccm_wr_addr_hi; - logic [pt.DCCM_BITS-1:0] dccm_rd_addr_lo; - logic [pt.DCCM_BITS-1:0] dccm_rd_addr_hi; + logic [pt.DCCM_BITS-1:0] dccm_wr_addr_lo; + logic [pt.DCCM_BITS-1:0] dccm_wr_addr_hi; + logic [pt.DCCM_BITS-1:0] dccm_rd_addr_lo; + logic [pt.DCCM_BITS-1:0] dccm_rd_addr_hi; logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo; logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi; @@ -352,22 +360,22 @@ import el2_pkg::*; logic [pt.ICACHE_NUM_WAYS-1:0] ic_tag_valid; // Valid from the I$ tag valid outside (in flops). logic [pt.ICACHE_NUM_WAYS-1:0] ic_rd_hit; // ic_rd_hit[3:0] - logic ic_tag_perr; // Ic tag parity error + logic ic_tag_perr; // Ic tag parity error - logic [pt.ICACHE_INDEX_HI:3] ic_debug_addr; // Read/Write addresss to the Icache. - logic ic_debug_rd_en; // Icache debug rd - logic ic_debug_wr_en; // Icache debug wr - logic ic_debug_tag_array; // Debug tag array - logic [pt.ICACHE_NUM_WAYS-1:0] ic_debug_way; // Debug way. Rd or Wr. + logic [pt.ICACHE_INDEX_HI:3] ic_debug_addr; // Read/Write addresss to the Icache. + logic ic_debug_rd_en; // Icache debug rd + logic ic_debug_wr_en; // Icache debug wr + logic ic_debug_tag_array; // Debug tag array + logic [pt.ICACHE_NUM_WAYS-1:0] ic_debug_way; // Debug way. Rd or Wr. - logic [25:0] ictag_debug_rd_data;// Debug icache tag. + logic [25:0] ictag_debug_rd_data; // Debug icache tag. logic [pt.ICACHE_BANKS_WAY-1:0][70:0] ic_wr_data; logic [63:0] ic_rd_data; - logic [70:0] ic_debug_rd_data; // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC - logic [70:0] ic_debug_wr_data; // Debug wr cache. + logic [70:0] ic_debug_rd_data; // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC + logic [70:0] ic_debug_wr_data; // Debug wr cache. - logic [pt.ICACHE_BANKS_WAY-1:0] ic_eccerr; // ecc error per bank - logic [pt.ICACHE_BANKS_WAY-1:0] ic_parerr; // parity error per bank + logic [pt.ICACHE_BANKS_WAY-1:0] ic_eccerr; // ecc error per bank + logic [pt.ICACHE_BANKS_WAY-1:0] ic_parerr; // parity error per bank logic [63:0] ic_premux_data; logic ic_sel_premux_data; @@ -384,14 +392,8 @@ import el2_pkg::*; logic [63:0] iccm_rd_data; logic [77:0] iccm_rd_data_ecc; - logic core_rst_l; // Core reset including rst_l and dbg_rst_l + logic core_rst_l; // Core reset including rst_l and dbg_rst_l logic jtag_tdoEn; - logic dmi_reg_en; - logic [6:0] dmi_reg_addr; - logic dmi_reg_wr_en; - logic [31:0] dmi_reg_wdata; - logic [31:0] dmi_reg_rdata; - logic dmi_hard_reset; logic dccm_clk_override; logic icm_clk_override; @@ -402,7 +404,7 @@ import el2_pkg::*; `ifdef RV_BUILD_AXI4 //// AHB LITE BUS - logic [31:0] haddr; + logic [31:0] haddr; logic [2:0] hburst; logic hmastlock; logic [3:0] hprot; @@ -410,54 +412,55 @@ import el2_pkg::*; logic [1:0] htrans; logic hwrite; - logic [63:0] hrdata; - logic hready; - logic hresp; + logic [63:0] hrdata; + logic hready; + logic hresp; // LSU AHB Master - logic [31:0] lsu_haddr; + logic [31:0] lsu_haddr; logic [2:0] lsu_hburst; logic lsu_hmastlock; logic [3:0] lsu_hprot; logic [2:0] lsu_hsize; logic [1:0] lsu_htrans; logic lsu_hwrite; - logic [63:0] lsu_hwdata; + logic [63:0] lsu_hwdata; - logic [63:0] lsu_hrdata; - logic lsu_hready; - logic lsu_hresp; + logic [63:0] lsu_hrdata; + logic lsu_hready; + logic lsu_hresp; // Debug Syster Bus AHB - logic [31:0] sb_haddr; - logic [2:0] sb_hburst; - logic sb_hmastlock; - logic [3:0] sb_hprot; - logic [2:0] sb_hsize; - logic [1:0] sb_htrans; - logic sb_hwrite; - logic [63:0] sb_hwdata; + logic [31:0] sb_haddr; + logic [2:0] sb_hburst; + logic sb_hmastlock; + logic [3:0] sb_hprot; + logic [2:0] sb_hsize; + logic [1:0] sb_htrans; + logic sb_hwrite; + logic [63:0] sb_hwdata; - logic [63:0] sb_hrdata; - logic sb_hready; - logic sb_hresp; + logic [63:0] sb_hrdata; + logic sb_hready; + logic sb_hresp; // DMA Slave - logic dma_hsel; - logic [31:0] dma_haddr; + logic dma_hsel; + logic [31:0] dma_haddr; logic [2:0] dma_hburst; - logic dma_hmastlock; + logic dma_hmastlock; logic [3:0] dma_hprot; logic [2:0] dma_hsize; logic [1:0] dma_htrans; - logic dma_hwrite; - logic [63:0] dma_hwdata; - logic dma_hreadyin; + logic dma_hwrite; + logic [63:0] dma_hwdata; + logic dma_hreadyin; - logic [63:0] dma_hrdata; + logic [63:0] dma_hrdata; logic dma_hreadyout; logic dma_hresp; + // AHB assign hrdata[63:0] = '0; assign hready = '0; @@ -485,10 +488,11 @@ import el2_pkg::*; `endif // `ifdef RV_BUILD_AXI4 + `ifdef RV_BUILD_AHB_LITE wire lsu_axi_awvalid; - wire lsu_axi_awready; - wire [pt.LSU_BUS_TAG-1:0] lsu_axi_awid; + wire lsu_axi_awready; + wire [pt.LSU_BUS_TAG-1:0] lsu_axi_awid; wire [31:0] lsu_axi_awaddr; wire [3:0] lsu_axi_awregion; wire [7:0] lsu_axi_awlen; @@ -500,20 +504,20 @@ import el2_pkg::*; wire [3:0] lsu_axi_awqos; wire lsu_axi_wvalid; - wire lsu_axi_wready; + wire lsu_axi_wready; wire [63:0] lsu_axi_wdata; wire [7:0] lsu_axi_wstrb; wire lsu_axi_wlast; - wire lsu_axi_bvalid; + wire lsu_axi_bvalid; wire lsu_axi_bready; - wire [1:0] lsu_axi_bresp; - wire [pt.LSU_BUS_TAG-1:0] lsu_axi_bid; + wire [1:0] lsu_axi_bresp; + wire [pt.LSU_BUS_TAG-1:0] lsu_axi_bid; // AXI Read Channels wire lsu_axi_arvalid; - wire lsu_axi_arready; - wire [pt.LSU_BUS_TAG-1:0] lsu_axi_arid; + wire lsu_axi_arready; + wire [pt.LSU_BUS_TAG-1:0] lsu_axi_arid; wire [31:0] lsu_axi_araddr; wire [3:0] lsu_axi_arregion; wire [7:0] lsu_axi_arlen; @@ -524,18 +528,18 @@ import el2_pkg::*; wire [2:0] lsu_axi_arprot; wire [3:0] lsu_axi_arqos; - wire lsu_axi_rvalid; + wire lsu_axi_rvalid; wire lsu_axi_rready; - wire [pt.LSU_BUS_TAG-1:0] lsu_axi_rid; - wire [63:0] lsu_axi_rdata; - wire [1:0] lsu_axi_rresp; - wire lsu_axi_rlast; + wire [pt.LSU_BUS_TAG-1:0] lsu_axi_rid; + wire [63:0] lsu_axi_rdata; + wire [1:0] lsu_axi_rresp; + wire lsu_axi_rlast; //-------------------------- IFU AXI signals-------------------------- // AXI Write Channels wire ifu_axi_awvalid; - wire ifu_axi_awready; - wire [pt.IFU_BUS_TAG-1:0] ifu_axi_awid; + wire ifu_axi_awready; + wire [pt.IFU_BUS_TAG-1:0] ifu_axi_awid; wire [31:0] ifu_axi_awaddr; wire [3:0] ifu_axi_awregion; wire [7:0] ifu_axi_awlen; @@ -547,20 +551,20 @@ import el2_pkg::*; wire [3:0] ifu_axi_awqos; wire ifu_axi_wvalid; - wire ifu_axi_wready; + wire ifu_axi_wready; wire [63:0] ifu_axi_wdata; wire [7:0] ifu_axi_wstrb; wire ifu_axi_wlast; - wire ifu_axi_bvalid; + wire ifu_axi_bvalid; wire ifu_axi_bready; - wire [1:0] ifu_axi_bresp; - wire [pt.IFU_BUS_TAG-1:0] ifu_axi_bid; + wire [1:0] ifu_axi_bresp; + wire [pt.IFU_BUS_TAG-1:0] ifu_axi_bid; // AXI Read Channels wire ifu_axi_arvalid; - wire ifu_axi_arready; - wire [pt.IFU_BUS_TAG-1:0] ifu_axi_arid; + wire ifu_axi_arready; + wire [pt.IFU_BUS_TAG-1:0] ifu_axi_arid; wire [31:0] ifu_axi_araddr; wire [3:0] ifu_axi_arregion; wire [7:0] ifu_axi_arlen; @@ -571,18 +575,18 @@ import el2_pkg::*; wire [2:0] ifu_axi_arprot; wire [3:0] ifu_axi_arqos; - wire ifu_axi_rvalid; + wire ifu_axi_rvalid; wire ifu_axi_rready; - wire [pt.IFU_BUS_TAG-1:0] ifu_axi_rid; - wire [63:0] ifu_axi_rdata; - wire [1:0] ifu_axi_rresp; - wire ifu_axi_rlast; + wire [pt.IFU_BUS_TAG-1:0] ifu_axi_rid; + wire [63:0] ifu_axi_rdata; + wire [1:0] ifu_axi_rresp; + wire ifu_axi_rlast; //-------------------------- SB AXI signals-------------------------- // AXI Write Channels wire sb_axi_awvalid; - wire sb_axi_awready; - wire [pt.SB_BUS_TAG-1:0] sb_axi_awid; + wire sb_axi_awready; + wire [pt.SB_BUS_TAG-1:0] sb_axi_awid; wire [31:0] sb_axi_awaddr; wire [3:0] sb_axi_awregion; wire [7:0] sb_axi_awlen; @@ -594,20 +598,20 @@ import el2_pkg::*; wire [3:0] sb_axi_awqos; wire sb_axi_wvalid; - wire sb_axi_wready; + wire sb_axi_wready; wire [63:0] sb_axi_wdata; wire [7:0] sb_axi_wstrb; wire sb_axi_wlast; - wire sb_axi_bvalid; + wire sb_axi_bvalid; wire sb_axi_bready; - wire [1:0] sb_axi_bresp; - wire [pt.SB_BUS_TAG-1:0] sb_axi_bid; + wire [1:0] sb_axi_bresp; + wire [pt.SB_BUS_TAG-1:0] sb_axi_bid; // AXI Read Channels wire sb_axi_arvalid; - wire sb_axi_arready; - wire [pt.SB_BUS_TAG-1:0] sb_axi_arid; + wire sb_axi_arready; + wire [pt.SB_BUS_TAG-1:0] sb_axi_arid; wire [31:0] sb_axi_araddr; wire [3:0] sb_axi_arregion; wire [7:0] sb_axi_arlen; @@ -618,49 +622,49 @@ import el2_pkg::*; wire [2:0] sb_axi_arprot; wire [3:0] sb_axi_arqos; - wire sb_axi_rvalid; + wire sb_axi_rvalid; wire sb_axi_rready; - wire [pt.SB_BUS_TAG-1:0] sb_axi_rid; - wire [63:0] sb_axi_rdata; - wire [1:0] sb_axi_rresp; - wire sb_axi_rlast; + wire [pt.SB_BUS_TAG-1:0] sb_axi_rid; + wire [63:0] sb_axi_rdata; + wire [1:0] sb_axi_rresp; + wire sb_axi_rlast; //-------------------------- DMA AXI signals-------------------------- // AXI Write Channels - wire dma_axi_awvalid; + wire dma_axi_awvalid; wire dma_axi_awready; - wire [pt.DMA_BUS_TAG-1:0] dma_axi_awid; - wire [31:0] dma_axi_awaddr; - wire [2:0] dma_axi_awsize; - wire [2:0] dma_axi_awprot; - wire [7:0] dma_axi_awlen; - wire [1:0] dma_axi_awburst; + wire [pt.DMA_BUS_TAG-1:0] dma_axi_awid; + wire [31:0] dma_axi_awaddr; + wire [2:0] dma_axi_awsize; + wire [2:0] dma_axi_awprot; + wire [7:0] dma_axi_awlen; + wire [1:0] dma_axi_awburst; - wire dma_axi_wvalid; + wire dma_axi_wvalid; wire dma_axi_wready; - wire [63:0] dma_axi_wdata; - wire [7:0] dma_axi_wstrb; - wire dma_axi_wlast; + wire [63:0] dma_axi_wdata; + wire [7:0] dma_axi_wstrb; + wire dma_axi_wlast; wire dma_axi_bvalid; - wire dma_axi_bready; + wire dma_axi_bready; wire [1:0] dma_axi_bresp; - wire [pt.DMA_BUS_TAG-1:0] dma_axi_bid; + wire [pt.DMA_BUS_TAG-1:0] dma_axi_bid; // AXI Read Channels - wire dma_axi_arvalid; + wire dma_axi_arvalid; wire dma_axi_arready; - wire [pt.DMA_BUS_TAG-1:0] dma_axi_arid; - wire [31:0] dma_axi_araddr; - wire [2:0] dma_axi_arsize; - wire [2:0] dma_axi_arprot; - wire [7:0] dma_axi_arlen; - wire [1:0] dma_axi_arburst; + wire [pt.DMA_BUS_TAG-1:0] dma_axi_arid; + wire [31:0] dma_axi_araddr; + wire [2:0] dma_axi_arsize; + wire [2:0] dma_axi_arprot; + wire [7:0] dma_axi_arlen; + wire [1:0] dma_axi_arburst; wire dma_axi_rvalid; - wire dma_axi_rready; - wire [pt.DMA_BUS_TAG-1:0] dma_axi_rid; + wire dma_axi_rready; + wire [pt.DMA_BUS_TAG-1:0] dma_axi_rid; wire [63:0] dma_axi_rdata; wire [1:0] dma_axi_rresp; wire dma_axi_rlast; @@ -674,40 +678,53 @@ import el2_pkg::*; `endif // `ifdef RV_BUILD_AHB_LITE + logic dmi_reg_en; + logic [6:0] dmi_reg_addr; + logic dmi_reg_wr_en; + logic [31:0] dmi_reg_wdata; + logic [31:0] dmi_reg_rdata; + // Instantiate the el2_swerv core el2_swerv #(.pt(pt)) swerv ( - .* - ); + .clk(clk), + .* + ); // Instantiate the mem - el2_mem #(.pt(pt)) mem( - .rst_l(core_rst_l), - .* - ); + el2_mem #(.pt(pt)) mem ( + .clk(active_l2clk), + .rst_l(core_rst_l), + .* + ); - // Instantiate the JTAG/DMI + + // JTAG/DMI instance dmi_wrapper dmi_wrapper ( - // JTAG signals - .trst_n(jtag_trst_n), // JTAG reset - .tck (jtag_tck), // JTAG clock - .tms (jtag_tms), // Test mode select - .tdi (jtag_tdi), // Test Data Input - .tdo (jtag_tdo), // Test Data Output - .tdoEnable (), // Test Data Output enable - - // Processor Signals - .core_rst_n (dbg_rst_l), // Primary reset active low - .core_clk (clk), // Core clock - .jtag_id (jtag_id), // 32 bit JTAG ID - .rd_data (dmi_reg_rdata), // 32 bit Read data from Processor - .reg_wr_data (dmi_reg_wdata), // 32 bit Write data to Processor - .reg_wr_addr (dmi_reg_addr), // 32 bit Write address to Processor - .reg_en (dmi_reg_en), // 1 bit Write interface bit to Processor - .reg_wr_en (dmi_reg_wr_en), // 1 bit Write enable to Processor - .dmi_hard_reset (dmi_hard_reset) //a hard reset of the DTM, causing the DTM to forget about any outstanding DMI transactions -); - + // JTAG signals + .trst_n (jtag_trst_n), // JTAG reset + .tck (jtag_tck), // JTAG clock + .tms (jtag_tms), // Test mode select + .tdi (jtag_tdi), // Test Data Input + .tdo (jtag_tdo), // Test Data Output + .tdoEnable (), + // Processor Signals + .core_rst_n (dbg_rst_l), // Debug reset, active low + .core_clk (clk), // Core clock + .jtag_id (jtag_id), // JTAG ID + .rd_data (dmi_reg_rdata), // Read data from Processor + .reg_wr_data (dmi_reg_wdata), // Write data to Processor + .reg_wr_addr (dmi_reg_addr), // Write address to Processor + .reg_en (dmi_reg_en), // Write interface bit to Processor + .reg_wr_en (dmi_reg_wr_en), // Write enable to Processor + .dmi_hard_reset () + ); +`ifdef RV_ASSERT_ON +// to avoid internal assertions failure at time 0 +initial begin + $assertoff(0, swerv); + @ (negedge clk) $asserton(0, swerv); +end +`endif endmodule - diff --git a/design/exu/el2_exu.sv b/design/exu/el2_exu.sv index fc5f547..5f7319b 100644 --- a/design/exu/el2_exu.sv +++ b/design/exu/el2_exu.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -36,21 +36,25 @@ import el2_pkg::*; input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] i0_predict_index_d, // DEC predict index input logic [pt.BTB_BTAG_SIZE-1:0] i0_predict_btag_d, // DEC predict branch tag + input logic [31:0] lsu_result_m, // Load result M-stage + input logic [31:0] lsu_nonblock_load_data, // nonblock load data input logic dec_i0_rs1_en_d, // Qualify GPR RS1 data input logic dec_i0_rs2_en_d, // Qualify GPR RS2 data input logic [31:0] gpr_i0_rs1_d, // DEC data gpr input logic [31:0] gpr_i0_rs2_d, // DEC data gpr input logic [31:0] dec_i0_immed_d, // DEC data immediate - input logic [31:0] dec_i0_rs1_bypass_data_d, // DEC bypass data - input logic [31:0] dec_i0_rs2_bypass_data_d, // DEC bypass data + input logic [31:0] dec_i0_result_r, // DEC result in R-stage input logic [12:1] dec_i0_br_immed_d, // Branch immediate input logic dec_i0_alu_decode_d, // Valid to X-stage ALU + input logic dec_i0_branch_d, // Branch in D-stage input logic dec_i0_select_pc_d, // PC select to RS1 input logic [31:1] dec_i0_pc_d, // Instruction PC - input logic [1:0] dec_i0_rs1_bypass_en_d, // DEC bypass select 1 - X-stage, 0 - dec bypass data - input logic [1:0] dec_i0_rs2_bypass_en_d, // DEC bypass select 1 - X-stage, 0 - dec bypass data - input logic dec_csr_ren_d, // Clear I0 RS1 primary + input logic [3:0] dec_i0_rs1_bypass_en_d, // DEC bypass select 1 - X-stage, 0 - dec bypass data + input logic [3:0] dec_i0_rs2_bypass_en_d, // DEC bypass select 1 - X-stage, 0 - dec bypass data + input logic dec_csr_ren_d, // CSR read select + input logic [31:0] dec_csr_rddata_d, // CSR read data + input logic dec_qual_lsu_d, // LSU instruction at D. Use to quiet LSU operands input el2_mul_pkt_t mul_p, // DEC {valid, operand signs, low, operand bypass} input el2_div_pkt_t div_p, // DEC {valid, unsigned, rem} input logic dec_div_cancel, // Cancel the divide operation @@ -105,18 +109,16 @@ import el2_pkg::*; - logic data_gate_en; logic [31:0] i0_rs1_bypass_data_d; logic [31:0] i0_rs2_bypass_data_d; logic i0_rs1_bypass_en_d; logic i0_rs2_bypass_en_d; logic [31:0] i0_rs1_d, i0_rs2_d; - logic [31:0] muldiv_rs1_d, muldiv_rs2_d; + logic [31:0] muldiv_rs1_d; logic [31:1] pred_correct_npc_r; logic i0_pred_correct_upper_r; - logic [31:0] csr_rs1_in_d; logic [31:1] i0_flush_path_upper_r; - logic x_data_en, r_data_en; + logic x_data_en, x_data_en_q1, x_data_en_q2, r_data_en, r_data_en_q2; logic x_ctl_en, r_ctl_en; logic [pt.BHT_GHR_SIZE-1:0] ghr_d_ns, ghr_d; @@ -130,7 +132,6 @@ import el2_pkg::*; el2_predict_pkt_t final_predict_mp; el2_predict_pkt_t i0_predict_newp_d; - logic flush_lower_ff; logic flush_in_d; logic [31:0] alu_result_x; @@ -148,6 +149,7 @@ import el2_pkg::*; logic [31:1] i0_flush_path_x; el2_predict_pkt_t i0_predict_p_x; logic i0_pred_correct_upper_x; + logic i0_branch_x; localparam PREDPIPESIZE = pt.BTB_ADDR_HI-pt.BTB_ADDR_LO+1+pt.BHT_GHR_SIZE+pt.BTB_BTAG_SIZE; logic [PREDPIPESIZE-1:0] predpipe_d, predpipe_x, predpipe_r, final_predpipe_mp; @@ -155,84 +157,73 @@ import el2_pkg::*; - rvdffe #(31) i_flush_path_x_ff (.*, .en ( x_data_en ), .din( i0_flush_path_d[31:1] ), .dout( i0_flush_path_x[31:1] ) ); - rvdffe #(32) i_csr_rs1_x_ff (.*, .en ( x_data_en ), .din( csr_rs1_in_d[31:0] ), .dout( exu_csr_rs1_x[31:0] ) ); - rvdffe #($bits(el2_predict_pkt_t)) i_predictpacket_x_ff (.*, .en ( x_data_en ), .din( i0_predict_p_d ), .dout( i0_predict_p_x ) ); - rvdffe #(PREDPIPESIZE) i_predpipe_x_ff (.*, .en ( x_data_en ), .din( predpipe_d ), .dout( predpipe_x ) ); - rvdffe #(PREDPIPESIZE) i_predpipe_r_ff (.*, .en ( r_data_en ), .din( predpipe_x ), .dout( predpipe_r ) ); + rvdffpcie #(31) i_flush_path_x_ff (.*, .clk(clk), .en ( x_data_en ), .din ( i0_flush_path_d[31:1] ), .dout( i0_flush_path_x[31:1] ) ); + rvdffe #(32) i_csr_rs1_x_ff (.*, .clk(clk), .en ( x_data_en_q1 ), .din ( i0_rs1_d[31:0] ), .dout( exu_csr_rs1_x[31:0] ) ); + rvdffppe #($bits(el2_predict_pkt_t)) i_predictpacket_x_ff (.*, .clk(clk), .en ( x_data_en ), .din ( i0_predict_p_d ), .dout( i0_predict_p_x ) ); + rvdffe #(PREDPIPESIZE) i_predpipe_x_ff (.*, .clk(clk), .en ( x_data_en_q2 ), .din ( predpipe_d ), .dout( predpipe_x ) ); + rvdffe #(PREDPIPESIZE) i_predpipe_r_ff (.*, .clk(clk), .en ( r_data_en_q2 ), .din ( predpipe_x ), .dout( predpipe_r ) ); - rvdffe #(4+pt.BHT_GHR_SIZE) i_x_ff (.*, .en ( x_ctl_en ), .din ({i0_valid_d,i0_taken_d,i0_flush_upper_d,i0_pred_correct_upper_d,ghr_x_ns[pt.BHT_GHR_SIZE-1:0]} ), - .dout({i0_valid_x,i0_taken_x,i0_flush_upper_x,i0_pred_correct_upper_x,ghr_x[pt.BHT_GHR_SIZE-1:0]} ) ); + rvdffe #(4+pt.BHT_GHR_SIZE) i_x_ff (.*, .clk(clk), .en ( x_ctl_en ), .din ({i0_valid_d,i0_taken_d,i0_flush_upper_d,i0_pred_correct_upper_d,ghr_x_ns[pt.BHT_GHR_SIZE-1:0]} ), + .dout({i0_valid_x,i0_taken_x,i0_flush_upper_x,i0_pred_correct_upper_x,ghr_x[pt.BHT_GHR_SIZE-1:0]} ) ); - rvdffe #($bits(el2_predict_pkt_t)+7) i_r_ff0 (.*, .en ( r_ctl_en ), .din ({i0_predict_p_x ,pred_correct_npc_x[6:1],i0_pred_correct_upper_x}), - .dout({i0_pp_r ,pred_correct_npc_r[6:1],i0_pred_correct_upper_r}) ); + rvdffppe #($bits(el2_predict_pkt_t)+1) i_r_ff0 (.*, .clk(clk), .en ( r_ctl_en ), .din ({i0_pred_correct_upper_x, i0_predict_p_x}), + .dout({i0_pred_correct_upper_r, i0_pp_r }) ); - rvdffe #(56) i_r_ff1 (.*, .en ( r_data_en ), .din ({i0_flush_path_x[31:1] ,pred_correct_npc_x[31:7]}), - .dout({i0_flush_path_upper_r[31:1],pred_correct_npc_r[31:7]}) ); + rvdffpcie #(31) i_flush_r_ff (.*, .clk(clk), .en ( r_data_en ), .din ( i0_flush_path_x[31:1] ), .dout( i0_flush_path_upper_r[31:1]) ); + rvdffpcie #(31) i_npc_r_ff (.*, .clk(clk), .en ( r_data_en ), .din ( pred_correct_npc_x[31:1] ), .dout( pred_correct_npc_r[31:1] ) ); - if (pt.BHT_SIZE==32 || pt.BHT_SIZE==64) - begin - rvdffs #(pt.BHT_GHR_SIZE+2) i_data_gate_ff (.*, .en( data_gate_en ), .din ({ghr_d_ns[pt.BHT_GHR_SIZE-1:0],mul_p.valid,dec_tlu_flush_lower_r}), - .dout({ghr_d[pt.BHT_GHR_SIZE-1:0] ,mul_valid_x,flush_lower_ff} ) ); - end - else - begin - rvdffe #(pt.BHT_GHR_SIZE+2) i_data_gate_ff (.*, .en( data_gate_en ), .din ({ghr_d_ns[pt.BHT_GHR_SIZE-1:0],mul_p.valid,dec_tlu_flush_lower_r}), - .dout({ghr_d[pt.BHT_GHR_SIZE-1:0] ,mul_valid_x,flush_lower_ff} ) ); - end + rvdffie #(pt.BHT_GHR_SIZE+2,1) i_misc_ff (.*, .clk(clk), .din ({ghr_d_ns[pt.BHT_GHR_SIZE-1:0], mul_p.valid, dec_i0_branch_d}), + .dout({ghr_d[pt.BHT_GHR_SIZE-1:0] , mul_valid_x, i0_branch_x}) ); - assign data_gate_en = ( ghr_d_ns[pt.BHT_GHR_SIZE-1:0] != ghr_d[pt.BHT_GHR_SIZE-1:0]) | - ( mul_p.valid != mul_valid_x ) | - ( dec_tlu_flush_lower_r != flush_lower_ff ); - assign predpipe_d[PREDPIPESIZE-1:0] = {i0_predict_fghr_d, i0_predict_index_d, i0_predict_btag_d}; - assign i0_rs1_bypass_en_d = dec_i0_rs1_bypass_en_d[0] | dec_i0_rs1_bypass_en_d[1]; - assign i0_rs2_bypass_en_d = dec_i0_rs2_bypass_en_d[0] | dec_i0_rs2_bypass_en_d[1]; + assign i0_rs1_bypass_en_d = dec_i0_rs1_bypass_en_d[0] | dec_i0_rs1_bypass_en_d[1] | dec_i0_rs1_bypass_en_d[2] | dec_i0_rs1_bypass_en_d[3]; + assign i0_rs2_bypass_en_d = dec_i0_rs2_bypass_en_d[0] | dec_i0_rs2_bypass_en_d[1] | dec_i0_rs2_bypass_en_d[2] | dec_i0_rs2_bypass_en_d[3]; - assign i0_rs1_bypass_data_d[31:0]=({32{dec_i0_rs1_bypass_en_d[0]}} & dec_i0_rs1_bypass_data_d[31:0]) | - ({32{dec_i0_rs1_bypass_en_d[1]}} & exu_i0_result_x[31:0] ); + assign i0_rs1_bypass_data_d[31:0]=({32{dec_i0_rs1_bypass_en_d[0]}} & dec_i0_result_r[31:0] ) | + ({32{dec_i0_rs1_bypass_en_d[1]}} & lsu_result_m[31:0] ) | + ({32{dec_i0_rs1_bypass_en_d[2]}} & exu_i0_result_x[31:0] ) | + ({32{dec_i0_rs1_bypass_en_d[3]}} & lsu_nonblock_load_data[31:0]); - assign i0_rs2_bypass_data_d[31:0]=({32{dec_i0_rs2_bypass_en_d[0]}} & dec_i0_rs2_bypass_data_d[31:0]) | - ({32{dec_i0_rs2_bypass_en_d[1]}} & exu_i0_result_x[31:0] ); + assign i0_rs2_bypass_data_d[31:0]=({32{dec_i0_rs2_bypass_en_d[0]}} & dec_i0_result_r[31:0] ) | + ({32{dec_i0_rs2_bypass_en_d[1]}} & lsu_result_m[31:0] ) | + ({32{dec_i0_rs2_bypass_en_d[2]}} & exu_i0_result_x[31:0] ) | + ({32{dec_i0_rs2_bypass_en_d[3]}} & lsu_nonblock_load_data[31:0]); - assign i0_rs1_d[31:0] = ({32{ i0_rs1_bypass_en_d }} & i0_rs1_bypass_data_d[31:0]) | - ({32{~i0_rs1_bypass_en_d & dec_i0_select_pc_d }} & {dec_i0_pc_d[31:1],1'b0} ) | // for jal's - ({32{~i0_rs1_bypass_en_d & dec_debug_wdata_rs1_d }} & dbg_cmd_wrdata[31:0] ) | - ({32{~i0_rs1_bypass_en_d & ~dec_debug_wdata_rs1_d & dec_i0_rs1_en_d}} & gpr_i0_rs1_d[31:0] ); + assign i0_rs1_d[31:0] = ({32{ i0_rs1_bypass_en_d }} & i0_rs1_bypass_data_d[31:0]) | + ({32{~i0_rs1_bypass_en_d & dec_i0_select_pc_d }} & {dec_i0_pc_d[31:1],1'b0} ) | // for jal's + ({32{~i0_rs1_bypass_en_d & dec_debug_wdata_rs1_d }} & dbg_cmd_wrdata[31:0] ) | + ({32{~i0_rs1_bypass_en_d & ~dec_debug_wdata_rs1_d & dec_i0_rs1_en_d}} & gpr_i0_rs1_d[31:0] ); - assign i0_rs2_d[31:0] = ({32{~i0_rs2_bypass_en_d & dec_i0_rs2_en_d}} & gpr_i0_rs2_d[31:0] ) | - ({32{~i0_rs2_bypass_en_d }} & dec_i0_immed_d[31:0] ) | - ({32{ i0_rs2_bypass_en_d }} & i0_rs2_bypass_data_d[31:0]); + assign i0_rs2_d[31:0] = ({32{~i0_rs2_bypass_en_d & dec_i0_rs2_en_d}} & gpr_i0_rs2_d[31:0] ) | + ({32{~i0_rs2_bypass_en_d }} & dec_i0_immed_d[31:0] ) | + ({32{ i0_rs2_bypass_en_d }} & i0_rs2_bypass_data_d[31:0]); - assign exu_lsu_rs1_d[31:0] = ({32{~i0_rs1_bypass_en_d & ~dec_extint_stall & dec_i0_rs1_en_d}} & gpr_i0_rs1_d[31:0] ) | - ({32{ i0_rs1_bypass_en_d & ~dec_extint_stall }} & i0_rs1_bypass_data_d[31:0]) | - ({32{ dec_extint_stall }} & {dec_tlu_meihap[31:2],2'b0}); + assign exu_lsu_rs1_d[31:0] = ({32{~i0_rs1_bypass_en_d & ~dec_extint_stall & dec_i0_rs1_en_d & dec_qual_lsu_d}} & gpr_i0_rs1_d[31:0] ) | + ({32{ i0_rs1_bypass_en_d & ~dec_extint_stall & dec_qual_lsu_d}} & i0_rs1_bypass_data_d[31:0]) | + ({32{ dec_extint_stall & dec_qual_lsu_d}} & {dec_tlu_meihap[31:2],2'b0}); - assign exu_lsu_rs2_d[31:0] = ({32{~i0_rs2_bypass_en_d & ~dec_extint_stall & dec_i0_rs2_en_d}} & gpr_i0_rs2_d[31:0] ) | - ({32{ i0_rs2_bypass_en_d & ~dec_extint_stall }} & i0_rs2_bypass_data_d[31:0]); + assign exu_lsu_rs2_d[31:0] = ({32{~i0_rs2_bypass_en_d & ~dec_extint_stall & dec_i0_rs2_en_d & dec_qual_lsu_d}} & gpr_i0_rs2_d[31:0] ) | + ({32{ i0_rs2_bypass_en_d & ~dec_extint_stall & dec_qual_lsu_d}} & i0_rs2_bypass_data_d[31:0]); - assign muldiv_rs1_d[31:0] = ({32{~i0_rs1_bypass_en_d & dec_i0_rs1_en_d}} & gpr_i0_rs1_d[31:0] ) | - ({32{ i0_rs1_bypass_en_d }} & i0_rs1_bypass_data_d[31:0]); + assign muldiv_rs1_d[31:0] = ({32{~i0_rs1_bypass_en_d & dec_i0_rs1_en_d}} & gpr_i0_rs1_d[31:0] ) | + ({32{ i0_rs1_bypass_en_d }} & i0_rs1_bypass_data_d[31:0]); - assign muldiv_rs2_d[31:0] = ({32{~i0_rs2_bypass_en_d & dec_i0_rs2_en_d}} & gpr_i0_rs2_d[31:0] ) | - ({32{~i0_rs2_bypass_en_d }} & dec_i0_immed_d[31:0] ) | - ({32{ i0_rs2_bypass_en_d }} & i0_rs2_bypass_data_d[31:0]); - - - assign csr_rs1_in_d[31:0] = ( dec_csr_ren_d ) ? i0_rs1_d[31:0] : exu_csr_rs1_x[31:0]; assign x_data_en = dec_data_en[1]; + assign x_data_en_q1 = dec_data_en[1] & dec_csr_ren_d; + assign x_data_en_q2 = dec_data_en[1] & dec_i0_branch_d; assign r_data_en = dec_data_en[0]; + assign r_data_en_q2 = dec_data_en[0] & i0_branch_x; assign x_ctl_en = dec_ctl_en[1]; assign r_ctl_en = dec_ctl_en[0]; @@ -240,7 +231,7 @@ import el2_pkg::*; el2_exu_alu_ctl #(.pt(pt)) i_alu (.*, - .enable ( x_ctl_en ), // I + .enable ( x_data_en ), // I .pp_in ( i0_predict_newp_d ), // I .valid_in ( dec_i0_alu_decode_d ), // I .flush_upper_x ( i0_flush_upper_x ), // I @@ -251,6 +242,7 @@ import el2_pkg::*; .brimm_in ( dec_i0_br_immed_d[12:1] ), // I .ap ( i0_ap ), // I .csr_ren_in ( dec_csr_ren_d ), // I + .csr_rddata_in ( dec_csr_rddata_d[31:0] ), // I .result_ff ( alu_result_x[31:0] ), // O .flush_upper_out ( i0_flush_upper_d ), // O .flush_final_out ( exu_flush_final ), // O @@ -262,10 +254,10 @@ import el2_pkg::*; el2_exu_mul_ctl #(.pt(pt)) i_mul (.*, - .mul_p ( mul_p ), // I - .rs1_in ( muldiv_rs1_d[31:0] ), // I - .rs2_in ( muldiv_rs2_d[31:0] ), // I - .result_x ( mul_result_x[31:0] )); // O + .mul_p ( mul_p & {$bits(el2_mul_pkt_t){mul_p.valid}} ), // I + .rs1_in ( muldiv_rs1_d[31:0] & {32{mul_p.valid}} ), // I + .rs2_in ( i0_rs2_d[31:0] & {32{mul_p.valid}} ), // I + .result_x ( mul_result_x[31:0] )); // O @@ -273,7 +265,7 @@ import el2_pkg::*; .cancel ( dec_div_cancel ), // I .dp ( div_p ), // I .dividend ( muldiv_rs1_d[31:0] ), // I - .divisor ( muldiv_rs2_d[31:0] ), // I + .divisor ( i0_rs2_d[31:0] ), // I .finish_dly ( exu_div_wren ), // O .out ( exu_div_result[31:0] )); // O @@ -298,7 +290,7 @@ import el2_pkg::*; assign i0_valid_d = i0_predict_p_d.valid & dec_i0_alu_decode_d & ~dec_tlu_flush_lower_r; assign i0_taken_d = (i0_predict_p_d.ataken & dec_i0_alu_decode_d); - +if(pt.BTB_ENABLE==1) begin // maintain GHR at D assign ghr_d_ns[pt.BHT_GHR_SIZE-1:0] = ({pt.BHT_GHR_SIZE{~dec_tlu_flush_lower_r & i0_valid_d}} & {ghr_d[pt.BHT_GHR_SIZE-2:0], i0_taken_d}) | @@ -314,7 +306,7 @@ import el2_pkg::*; assign exu_i0_br_valid_r = i0_pp_r.valid; assign exu_i0_br_mp_r = i0_pp_r.misp; assign exu_i0_br_way_r = i0_pp_r.way; - assign exu_i0_br_hist_r[1:0] = i0_pp_r.hist[1:0]; + assign exu_i0_br_hist_r[1:0] = {2{i0_pp_r.valid}} & i0_pp_r.hist[1:0]; assign exu_i0_br_error_r = i0_pp_r.br_error; assign exu_i0_br_middle_r = i0_pp_r.pc4 ^ i0_pp_r.boffset; assign exu_i0_br_start_error_r = i0_pp_r.br_start_error; @@ -330,6 +322,7 @@ import el2_pkg::*; assign after_flush_eghr[pt.BHT_GHR_SIZE-1:0] = (i0_flush_upper_x & ~dec_tlu_flush_lower_r) ? ghr_d[pt.BHT_GHR_SIZE-1:0] : ghr_x[pt.BHT_GHR_SIZE-1:0]; + assign exu_mp_pkt.valid = final_predict_mp.valid; assign exu_mp_pkt.way = final_predict_mp.way; assign exu_mp_pkt.misp = final_predict_mp.misp; assign exu_mp_pkt.pcall = final_predict_mp.pcall; @@ -347,11 +340,30 @@ import el2_pkg::*; exu_mp_btag[pt.BTB_BTAG_SIZE-1:0]} = final_predpipe_mp[PREDPIPESIZE-pt.BHT_GHR_SIZE-1:0]; assign exu_mp_eghr[pt.BHT_GHR_SIZE-1:0] = final_predpipe_mp[PREDPIPESIZE-1:pt.BTB_ADDR_HI-pt.BTB_ADDR_LO+pt.BTB_BTAG_SIZE+1]; // mp ghr for bht write +end // if (pt.BTB_ENABLE==1) +else begin + assign ghr_d_ns = '0; + assign ghr_x_ns = '0; + assign exu_mp_pkt = '0; + assign exu_mp_eghr = '0; + assign exu_mp_fghr = '0; + assign exu_mp_index = '0; + assign exu_mp_btag = '0; + assign exu_i0_br_hist_r = '0; + assign exu_i0_br_error_r = '0; + assign exu_i0_br_start_error_r = '0; + assign exu_i0_br_index_r = '0; + assign exu_i0_br_valid_r = '0; + assign exu_i0_br_mp_r = '0; + assign exu_i0_br_middle_r = '0; + assign exu_i0_br_fghr_r = '0; + assign exu_i0_br_way_r = '0; +end // else: !if(pt.BTB_ENABLE==1) - assign exu_flush_path_final[31:1] = (dec_tlu_flush_lower_r) ? dec_tlu_flush_path_r[31:1] : i0_flush_path_d[31:1]; + assign exu_flush_path_final[31:1] = ( {31{ dec_tlu_flush_lower_r }} & dec_tlu_flush_path_r[31:1] ) | + ( {31{~dec_tlu_flush_lower_r & i0_flush_upper_d}} & i0_flush_path_d[31:1] ); - assign exu_npc_r[31:1] = (i0_pred_correct_upper_r) ? pred_correct_npc_r[31:1] : - i0_flush_path_upper_r[31:1]; + assign exu_npc_r[31:1] = (i0_pred_correct_upper_r) ? pred_correct_npc_r[31:1] : i0_flush_path_upper_r[31:1]; endmodule // el2_exu diff --git a/design/exu/el2_exu_alu_ctl.sv b/design/exu/el2_exu_alu_ctl.sv index ed195dc..95c784c 100644 --- a/design/exu/el2_exu_alu_ctl.sv +++ b/design/exu/el2_exu_alu_ctl.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -29,7 +29,8 @@ import el2_pkg::*; input logic enable, // Clock enable input logic valid_in, // Valid input el2_alu_pkt_t ap, // predecodes - input logic csr_ren_in, // extra decode + input logic csr_ren_in, // CSR select + input logic [31:0] csr_rddata_in, // CSR data input logic signed [31:0] a_in, // A operand input logic [31:0] b_in, // B operand input logic [31:1] pc_in, // for pc=pc+2,4 calculations @@ -47,13 +48,10 @@ import el2_pkg::*; ); + logic [31:0] zba_a_in; logic [31:0] aout; logic cout,ov,neg; logic [31:0] lout; - logic [5:0] shift_amount; - logic [31:0] shift_mask; - logic [62:0] shift_extend; - logic [62:0] shift_long; logic [31:0] sout; logic sel_shift; logic sel_adder; @@ -72,10 +70,148 @@ import el2_pkg::*; + // *** Start - BitManip *** + + // Zbb + logic ap_clz; + logic ap_ctz; + logic ap_pcnt; + logic ap_sext_b; + logic ap_sext_h; + logic ap_min; + logic ap_max; + logic ap_pack; + logic ap_packu; + logic ap_packh; + logic ap_rol; + logic ap_ror; + logic ap_rev; + logic ap_rev8; + logic ap_orc_b; + logic ap_orc16; + logic ap_zbb; + + // Zbs + logic ap_sbset; + logic ap_sbclr; + logic ap_sbinv; + logic ap_sbext; + + // Zbr + logic ap_slo; + logic ap_sro; + + // Zba + logic ap_sh1add; + logic ap_sh2add; + logic ap_sh3add; + logic ap_zba; - rvdffe #(31) i_pc_ff (.*, .en(enable), .din(pc_in[31:1]), .dout(pc_ff[31:1])); // any PC is run through here - doesn't have to be alu - rvdffe #(32) i_result_ff (.*, .en(enable), .din(result[31:0]), .dout(result_ff[31:0])); + + if (pt.BITMANIP_ZBB == 1) + begin + assign ap_clz = ap.clz; + assign ap_ctz = ap.ctz; + assign ap_pcnt = ap.pcnt; + assign ap_sext_b = ap.sext_b; + assign ap_sext_h = ap.sext_h; + assign ap_min = ap.min; + assign ap_max = ap.max; + end + else + begin + assign ap_clz = 1'b0; + assign ap_ctz = 1'b0; + assign ap_pcnt = 1'b0; + assign ap_sext_b = 1'b0; + assign ap_sext_h = 1'b0; + assign ap_min = 1'b0; + assign ap_max = 1'b0; + end + + + if ( (pt.BITMANIP_ZBB == 1) | (pt.BITMANIP_ZBP == 1) ) + begin + assign ap_pack = ap.pack; + assign ap_packu = ap.packu; + assign ap_packh = ap.packh; + assign ap_rol = ap.rol; + assign ap_ror = ap.ror; + assign ap_rev = ap.grev & (b_in[4:0] == 5'b11111); + assign ap_rev8 = ap.grev & (b_in[4:0] == 5'b11000); + assign ap_orc_b = ap.gorc & (b_in[4:0] == 5'b00111); + assign ap_orc16 = ap.gorc & (b_in[4:0] == 5'b10000); + assign ap_zbb = ap.zbb; + end + else + begin + assign ap_pack = 1'b0; + assign ap_packu = 1'b0; + assign ap_packh = 1'b0; + assign ap_rol = 1'b0; + assign ap_ror = 1'b0; + assign ap_rev = 1'b0; + assign ap_rev8 = 1'b0; + assign ap_orc_b = 1'b0; + assign ap_orc16 = 1'b0; + assign ap_zbb = 1'b0; + end + + + if (pt.BITMANIP_ZBS == 1) + begin + assign ap_sbset = ap.sbset; + assign ap_sbclr = ap.sbclr; + assign ap_sbinv = ap.sbinv; + assign ap_sbext = ap.sbext; + end + else + begin + assign ap_sbset = 1'b0; + assign ap_sbclr = 1'b0; + assign ap_sbinv = 1'b0; + assign ap_sbext = 1'b0; + end + + + if (pt.BITMANIP_ZBP == 1) + begin + assign ap_slo = ap.slo; + assign ap_sro = ap.sro; + end + else + begin + assign ap_slo = 1'b0; + assign ap_sro = 1'b0; + end + + + if (pt.BITMANIP_ZBA == 1) + begin + assign ap_sh1add = ap.sh1add; + assign ap_sh2add = ap.sh2add; + assign ap_sh3add = ap.sh3add; + assign ap_zba = ap.zba; + end + else + begin + assign ap_sh1add = 1'b0; + assign ap_sh2add = 1'b0; + assign ap_sh3add = 1'b0; + assign ap_zba = 1'b0; + end + + + + + // *** End - BitManip *** + + + + + rvdffpcie #(31) i_pc_ff (.*, .clk(clk), .en(enable), .din(pc_in[31:1]), .dout(pc_ff[31:1])); // any PC is run through here - doesn't have to be alu + rvdffe #(32) i_result_ff (.*, .clk(clk), .en(enable & valid_in), .din(result[31:0]), .dout(result_ff[31:0])); @@ -106,11 +242,17 @@ import el2_pkg::*; // jalr => rs1=rs1, rs2=sext(offset20:1]); rd=pc+[2,4] + + assign zba_a_in[31:0] = ( {32{ ap_sh1add}} & {a_in[30:0],1'b0} ) | + ( {32{ ap_sh2add}} & {a_in[29:0],2'b0} ) | + ( {32{ ap_sh3add}} & {a_in[28:0],3'b0} ) | + ( {32{~ap_zba }} & a_in[31:0] ); + logic [31:0] bm; assign bm[31:0] = ( ap.sub ) ? ~b_in[31:0] : b_in[31:0]; - assign {cout, aout[31:0]} = {1'b0, a_in[31:0]} + {1'b0, bm[31:0]} + {32'b0, ap.sub}; + assign {cout, aout[31:0]} = {1'b0, zba_a_in[31:0]} + {1'b0, bm[31:0]} + {32'b0, ap.sub}; assign ov = (~a_in[31] & ~bm[31] & aout[31]) | ( a_in[31] & bm[31] & ~aout[31] ); @@ -118,7 +260,6 @@ import el2_pkg::*; assign lt = (~ap.unsign & (neg ^ ov)) | ( ap.unsign & ~cout); - assign eq = (a_in[31:0] == b_in[31:0]); assign ne = ~eq; assign neg = aout[31]; @@ -126,39 +267,227 @@ import el2_pkg::*; - assign lout[31:0] = ( {32{csr_ren_in}} & b_in[31:0] ) | - ( {32{ap.land }} & a_in[31:0] & b_in[31:0] ) | - ( {32{ap.lor }} & (a_in[31:0] | b_in[31:0]) ) | - ( {32{ap.lxor }} & (a_in[31:0] ^ b_in[31:0]) ); + assign lout[31:0] = ( {32{csr_ren_in }} & csr_rddata_in[31:0] ) | + ( {32{ap.land & ~ap_zbb}} & a_in[31:0] & b_in[31:0] ) | + ( {32{ap.lor & ~ap_zbb}} & (a_in[31:0] | b_in[31:0]) ) | + ( {32{ap.lxor & ~ap_zbb}} & (a_in[31:0] ^ b_in[31:0]) ) | + ( {32{ap.land & ap_zbb}} & a_in[31:0] & ~b_in[31:0] ) | + ( {32{ap.lor & ap_zbb}} & (a_in[31:0] | ~b_in[31:0]) ) | + ( {32{ap.lxor & ap_zbb}} & (a_in[31:0] ^ ~b_in[31:0]) ); + // * * * * * * * * * * * * * * * * * * BitManip : SLO,SRO * * * * * * * * * * * * * * * * * * + // * * * * * * * * * * * * * * * * * * BitManip : ROL,ROR * * * * * * * * * * * * * * * * * * + // * * * * * * * * * * * * * * * * * * BitManip : ZBEXT * * * * * * * * * * * * * * * * * * + + logic [5:0] shift_amount; + logic [31:0] shift_mask; + logic [62:0] shift_extend; + logic [62:0] shift_long; + assign shift_amount[5:0] = ( { 6{ap.sll}} & (6'd32 - {1'b0,b_in[4:0]}) ) | // [5] unused ( { 6{ap.srl}} & {1'b0,b_in[4:0]} ) | - ( { 6{ap.sra}} & {1'b0,b_in[4:0]} ); + ( { 6{ap.sra}} & {1'b0,b_in[4:0]} ) | + ( { 6{ap_rol}} & (6'd32 - {1'b0,b_in[4:0]}) ) | + ( { 6{ap_ror}} & {1'b0,b_in[4:0]} ) | + ( { 6{ap_slo}} & (6'd32 - {1'b0,b_in[4:0]}) ) | + ( { 6{ap_sro}} & {1'b0,b_in[4:0]} ) | + ( { 6{ap_sbext}} & {1'b0,b_in[4:0]} ); - assign shift_mask[31:0] = ( 32'hffffffff << ({5{ap.sll}} & b_in[4:0]) ); + assign shift_mask[31:0] = ( 32'hffffffff << ({5{ap.sll | ap_slo}} & b_in[4:0]) ); assign shift_extend[31:0] = a_in[31:0]; assign shift_extend[62:32] = ( {31{ap.sra}} & {31{a_in[31]}} ) | - ( {31{ap.sll}} & a_in[30:0] ); + ( {31{ap.sll}} & a_in[30:0] ) | + ( {31{ap_rol}} & a_in[30:0] ) | + ( {31{ap_ror}} & a_in[30:0] ) | + ( {31{ap_slo}} & a_in[30:0] ) | + ( {31{ap_sro}} & {31{ 1'b1 }} ); assign shift_long[62:0] = ( shift_extend[62:0] >> shift_amount[4:0] ); // 62-32 unused - assign sout[31:0] = ( shift_long[31:0] & shift_mask[31:0] ); + assign sout[31:0] = ( shift_long[31:0] & shift_mask[31:0] ) | ( {32{ap_slo}} & ~shift_mask[31:0] ); + + + + + // * * * * * * * * * * * * * * * * * * BitManip : CLZ,CTZ * * * * * * * * * * * * * * * * * * + + logic bitmanip_clz_ctz_sel; + logic [31:0] bitmanip_a_reverse_ff; + logic [31:0] bitmanip_lzd_in; + logic [5:0] bitmanip_dw_lzd_enc; + logic [5:0] bitmanip_clz_ctz_result; + + assign bitmanip_clz_ctz_sel = ap_clz | ap_ctz; + + assign bitmanip_a_reverse_ff[31:0] = {a_in[0], a_in[1], a_in[2], a_in[3], a_in[4], a_in[5], a_in[6], a_in[7], + a_in[8], a_in[9], a_in[10], a_in[11], a_in[12], a_in[13], a_in[14], a_in[15], + a_in[16], a_in[17], a_in[18], a_in[19], a_in[20], a_in[21], a_in[22], a_in[23], + a_in[24], a_in[25], a_in[26], a_in[27], a_in[28], a_in[29], a_in[30], a_in[31]}; + + assign bitmanip_lzd_in[31:0] = ( {32{ap_clz}} & a_in[31:0] ) | + ( {32{ap_ctz}} & bitmanip_a_reverse_ff[31:0]); + + logic [31:0] bitmanip_lzd_os; + integer i; + logic found; + + always_comb + begin + bitmanip_lzd_os[31:0] = bitmanip_lzd_in[31:0]; + bitmanip_dw_lzd_enc[5:0]= 6'b0; + found = 1'b0; + + for (int i=0; i<32 && found==0; i++) begin + if (bitmanip_lzd_os[31] == 1'b0) begin + bitmanip_dw_lzd_enc[5:0]= bitmanip_dw_lzd_enc[5:0] + 6'b00_0001; + bitmanip_lzd_os[31:0] = bitmanip_lzd_os[31:0] << 1; + end + else + found=1'b1; + end + end + + + + assign bitmanip_clz_ctz_result[5:0] = {6{bitmanip_clz_ctz_sel}} & {bitmanip_dw_lzd_enc[5],( {5{~bitmanip_dw_lzd_enc[5]}} & bitmanip_dw_lzd_enc[4:0] )}; + + + + + // * * * * * * * * * * * * * * * * * * BitManip : PCNT * * * * * * * * * * * * * * * * * * + + logic [5:0] bitmanip_pcnt; + logic [5:0] bitmanip_pcnt_result; + + + integer bitmanip_pcnt_i; + + always_comb + begin + bitmanip_pcnt[5:0] = 6'b0; + + for (bitmanip_pcnt_i=0; bitmanip_pcnt_i<32; bitmanip_pcnt_i++) + begin + bitmanip_pcnt[5:0] = bitmanip_pcnt[5:0] + {5'b0,a_in[bitmanip_pcnt_i]}; + end // FOR bitmanip_pcnt_i + end // ALWAYS_COMB + + + assign bitmanip_pcnt_result[5:0] = {6{ap_pcnt}} & bitmanip_pcnt[5:0]; + + + + + // * * * * * * * * * * * * * * * * * * BitManip : SEXT_B,SEXT_H * * * * * * * * * * * * * * * * * + + logic [31:0] bitmanip_sext_result; + + assign bitmanip_sext_result[31:0] = ( {32{ap_sext_b}} & { {24{a_in[7]}} ,a_in[7:0] } ) | + ( {32{ap_sext_h}} & { {16{a_in[15]}},a_in[15:0] } ); + + + + + // * * * * * * * * * * * * * * * * * * BitManip : MIN,MAX,MINU,MAXU * * * * * * * * * * * * * * * + + logic bitmanip_minmax_sel; + logic [31:0] bitmanip_minmax_result; + + assign bitmanip_minmax_sel = ap_min | ap_max; + + + logic bitmanip_minmax_sel_a; + + assign bitmanip_minmax_sel_a = ge ^ ap_min; + + assign bitmanip_minmax_result[31:0] = ({32{bitmanip_minmax_sel & bitmanip_minmax_sel_a}} & a_in[31:0]) | + ({32{bitmanip_minmax_sel & ~bitmanip_minmax_sel_a}} & b_in[31:0]); + + + + // * * * * * * * * * * * * * * * * * * BitManip : PACK, PACKU, PACKH * * * * * * * * * * * * * * * + + logic [31:0] bitmanip_pack_result; + logic [31:0] bitmanip_packu_result; + logic [31:0] bitmanip_packh_result; + + assign bitmanip_pack_result[31:0] = {32{ap_pack}} & {b_in[15:0], a_in[15:0]}; + assign bitmanip_packu_result[31:0] = {32{ap_packu}} & {b_in[31:16],a_in[31:16]}; + assign bitmanip_packh_result[31:0] = {32{ap_packh}} & {16'b0,b_in[7:0],a_in[7:0]}; + + + + // * * * * * * * * * * * * * * * * * * BitManip : REV, REV8, ORC_B * * * * * * * * * * * * * * * * + + logic [31:0] bitmanip_rev_result; + logic [31:0] bitmanip_rev8_result; + logic [31:0] bitmanip_orc_b_result; + logic [31:0] bitmanip_orc16_result; + + assign bitmanip_rev_result[31:0] = {32{ap_rev}} & + {a_in[00],a_in[01],a_in[02],a_in[03],a_in[04],a_in[05],a_in[06],a_in[07], + a_in[08],a_in[09],a_in[10],a_in[11],a_in[12],a_in[13],a_in[14],a_in[15], + a_in[16],a_in[17],a_in[18],a_in[19],a_in[20],a_in[21],a_in[22],a_in[23], + a_in[24],a_in[25],a_in[26],a_in[27],a_in[28],a_in[29],a_in[30],a_in[31]}; + + assign bitmanip_rev8_result[31:0] = {32{ap_rev8}} & {a_in[7:0],a_in[15:8],a_in[23:16],a_in[31:24]}; + + +// uint32_t gorc32(uint32_t rs1, uint32_t rs2) +// { +// uint32_t x = rs1; +// int shamt = rs2 & 31; ORC.B ORC16 +// if (shamt & 1) x |= ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1); 1 0 +// if (shamt & 2) x |= ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2); 1 0 +// if (shamt & 4) x |= ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4); 1 0 +// if (shamt & 8) x |= ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8); 0 0 +// if (shamt & 16) x |= ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16); 0 1 +// return x; +// } + + +// BEFORE 31 , 30 , 29 , 28 , 27 , 26, 25, 24 +// shamt[0] b = a31|a30,a31|a30,a29|a28,a29|a28, a27|a26,a27|a26,a25|a24,a25|a24 +// shamt[1] c = b31|b29,b30|b28,b31|b29,b30|b28, b27|b25,b26|b24,b27|b25,b26|b24 +// shamt[2] d = c31|c27,c30|c26,c29|c25,c28|c24, c31|c27,c30|c26,c29|c25,c28|c24 +// +// Expand d31 = c31 | c27; +// = b31 | b29 | b27 | b25; +// = a31|a30 | a29|a28 | a27|a26 | a25|a24 + + assign bitmanip_orc_b_result[31:0] = {32{ap_orc_b}} & { {8{| a_in[31:24]}}, {8{| a_in[23:16]}}, {8{| a_in[15:8]}}, {8{| a_in[7:0]}} }; + + assign bitmanip_orc16_result[31:0] = {32{ap_orc16}} & { {a_in[31:16] | a_in[15:0]}, {a_in[31:16] | a_in[15:0]} }; + + + + // * * * * * * * * * * * * * * * * * * BitManip : ZBSET, ZBCLR, ZBINV * * * * * * * * * * * * * * + + logic [31:0] bitmanip_sb_1hot; + logic [31:0] bitmanip_sb_data; + + assign bitmanip_sb_1hot[31:0] = ( 32'h00000001 << b_in[4:0] ); + + assign bitmanip_sb_data[31:0] = ( {32{ap_sbset}} & ( a_in[31:0] | bitmanip_sb_1hot[31:0]) ) | + ( {32{ap_sbclr}} & ( a_in[31:0] & ~bitmanip_sb_1hot[31:0]) ) | + ( {32{ap_sbinv}} & ( a_in[31:0] ^ bitmanip_sb_1hot[31:0]) ); - assign sel_shift = ap.sll | ap.srl | ap.sra; - assign sel_adder = (ap.add | ap.sub) & ~ap.slt; + + assign sel_shift = ap.sll | ap.srl | ap.sra | ap_slo | ap_sro | ap_rol | ap_ror; + assign sel_adder = (ap.add | ap.sub | ap_zba) & ~ap.slt & ~ap_min & ~ap_max; assign sel_pc = ap.jal | pp_in.pcall | pp_in.pja | pp_in.pret; assign csr_write_data[31:0]= (ap.csr_imm) ? b_in[31:0] : a_in[31:0]; @@ -171,7 +500,20 @@ import el2_pkg::*; ({32{sel_adder}} & aout[31:0] ) | ({32{sel_pc}} & {pcout[31:1],1'b0} ) | ({32{ap.csr_write}} & csr_write_data[31:0] ) | - {31'b0, slt_one} ; + {31'b0, slt_one} | + ({32{ap_sbext}} & {31'b0, sout[0]} ) | + {26'b0, bitmanip_clz_ctz_result[5:0]} | + {26'b0, bitmanip_pcnt_result[5:0]} | + bitmanip_sext_result[31:0] | + bitmanip_minmax_result[31:0] | + bitmanip_pack_result[31:0] | + bitmanip_packu_result[31:0] | + bitmanip_packh_result[31:0] | + bitmanip_rev_result[31:0] | + bitmanip_rev8_result[31:0] | + bitmanip_orc_b_result[31:0] | + bitmanip_orc16_result[31:0] | + bitmanip_sb_data[31:0]; diff --git a/design/exu/el2_exu_div_ctl.sv b/design/exu/el2_exu_div_ctl.sv index 1beef7d..43d1021 100644 --- a/design/exu/el2_exu_div_ctl.sv +++ b/design/exu/el2_exu_div_ctl.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -36,10 +36,127 @@ import el2_pkg::*; ); + logic [31:0] out_raw; + + assign out[31:0] = {32{finish_dly}} & out_raw[31:0]; // Qualification added to quiet result bus while divide is iterating + + + + if (pt.DIV_NEW == 0) + begin + el2_exu_div_existing_1bit_cheapshortq i_existing_1bit_div_cheapshortq ( + .clk ( clk ), // I + .rst_l ( rst_l ), // I + .scan_mode ( scan_mode ), // I + .cancel ( cancel ), // I + .valid_in ( dp.valid ), // I + .signed_in (~dp.unsign ), // I + .rem_in ( dp.rem ), // I + .dividend_in ( dividend[31:0] ), // I + .divisor_in ( divisor[31:0] ), // I + .valid_out ( finish_dly ), // O + .data_out ( out_raw[31:0] )); // O + end + + + if ( (pt.DIV_NEW == 1) & (pt.DIV_BIT == 1) ) + begin + el2_exu_div_new_1bit_fullshortq i_new_1bit_div_fullshortq ( + .clk ( clk ), // I + .rst_l ( rst_l ), // I + .scan_mode ( scan_mode ), // I + .cancel ( cancel ), // I + .valid_in ( dp.valid ), // I + .signed_in (~dp.unsign ), // I + .rem_in ( dp.rem ), // I + .dividend_in ( dividend[31:0] ), // I + .divisor_in ( divisor[31:0] ), // I + .valid_out ( finish_dly ), // O + .data_out ( out_raw[31:0] )); // O + end + + + if ( (pt.DIV_NEW == 1) & (pt.DIV_BIT == 2) ) + begin + el2_exu_div_new_2bit_fullshortq i_new_2bit_div_fullshortq ( + .clk ( clk ), // I + .rst_l ( rst_l ), // I + .scan_mode ( scan_mode ), // I + .cancel ( cancel ), // I + .valid_in ( dp.valid ), // I + .signed_in (~dp.unsign ), // I + .rem_in ( dp.rem ), // I + .dividend_in ( dividend[31:0] ), // I + .divisor_in ( divisor[31:0] ), // I + .valid_out ( finish_dly ), // O + .data_out ( out_raw[31:0] )); // O + end + + + if ( (pt.DIV_NEW == 1) & (pt.DIV_BIT == 3) ) + begin + el2_exu_div_new_3bit_fullshortq i_new_3bit_div_fullshortq ( + .clk ( clk ), // I + .rst_l ( rst_l ), // I + .scan_mode ( scan_mode ), // I + .cancel ( cancel ), // I + .valid_in ( dp.valid ), // I + .signed_in (~dp.unsign ), // I + .rem_in ( dp.rem ), // I + .dividend_in ( dividend[31:0] ), // I + .divisor_in ( divisor[31:0] ), // I + .valid_out ( finish_dly ), // O + .data_out ( out_raw[31:0] )); // O + end + + + if ( (pt.DIV_NEW == 1) & (pt.DIV_BIT == 4) ) + begin + el2_exu_div_new_4bit_fullshortq i_new_4bit_div_fullshortq ( + .clk ( clk ), // I + .rst_l ( rst_l ), // I + .scan_mode ( scan_mode ), // I + .cancel ( cancel ), // I + .valid_in ( dp.valid ), // I + .signed_in (~dp.unsign ), // I + .rem_in ( dp.rem ), // I + .dividend_in ( dividend[31:0] ), // I + .divisor_in ( divisor[31:0] ), // I + .valid_out ( finish_dly ), // O + .data_out ( out_raw[31:0] )); // O + end + + + +endmodule // el2_exu_div_ctl + + + + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +module el2_exu_div_existing_1bit_cheapshortq + ( + input logic clk, // Top level clock + input logic rst_l, // Reset + input logic scan_mode, // Scan mode + + input logic cancel, // Flush pipeline + input logic valid_in, + input logic signed_in, + input logic rem_in, + input logic [31:0] dividend_in, + input logic [31:0] divisor_in, + + output logic valid_out, + output logic [31:0] data_out + ); + + logic div_clken; - logic exu_div_clk; logic run_in, run_state; - logic [5:0] count_in, count; + logic [5:0] count_in, count; logic [32:0] m_ff; logic qff_enable; logic aff_enable; @@ -58,7 +175,7 @@ import el2_pkg::*; logic rem_ff; logic add; logic [32:0] a_eff; - logic [55:0] a_eff_shift; + logic [64:0] a_eff_shift; logic rem_correct; logic valid_ff_x; logic valid_x; @@ -66,22 +183,52 @@ import el2_pkg::*; logic finish_ff; logic smallnum_case, smallnum_case_ff; - logic [3:0] smallnum, smallnum_ff; + logic [3:0] smallnum, smallnum_ff; logic m_already_comp; + logic [4:0] a_cls; + logic [4:0] b_cls; + logic [5:0] shortq_shift; + logic [5:0] shortq_shift_ff; + logic [5:0] shortq; + logic shortq_enable; + logic shortq_enable_ff; + logic [32:0] short_dividend; + logic [3:0] shortq_raw; + logic [3:0] shortq_shift_xx; - rvoclkhdr exu_div_cgc (.*, .en(div_clken), .l1clk(exu_div_clk)); - rvdff #(1) e1val_ff (.*, .clk(exu_div_clk), .din(dp.valid & ~cancel), .dout(valid_ff_x)); - rvdff #(1) i_finish_ff (.*, .clk(exu_div_clk), .din(finish & ~cancel), .dout(finish_ff)); - rvdff #(1) runff (.*, .clk(exu_div_clk), .din(run_in), .dout(run_state)); - rvdff #(6) countff (.*, .clk(exu_div_clk), .din(count_in[5:0]), .dout(count[5:0])); - rvdffs #(4) miscf (.*, .clk(exu_div_clk), .din({dividend[31],divisor[31],sign_eff,dp.rem}), .dout({dividend_neg_ff,divisor_neg_ff,sign_ff,rem_ff}), .en(dp.valid)); - rvdff #(5) smallnumff (.*, .clk(exu_div_clk), .din({smallnum_case,smallnum[3:0]}), .dout({smallnum_case_ff,smallnum_ff[3:0]})); - rvdffe #(33) mff (.*, .en(dp.valid), .din({ ~dp.unsign & divisor[31], divisor[31:0]}), .dout(m_ff[32:0])); - rvdffe #(33) qff (.*, .en(qff_enable), .din(q_in[32:0]), .dout(q_ff[32:0])); - rvdffe #(33) aff (.*, .en(aff_enable), .din(a_in[32:0]), .dout(a_ff[32:0])); + rvdffe #(23) i_misc_ff (.*, .clk(clk), .en(div_clken), .din ({valid_in & ~cancel, + finish & ~cancel, + run_in, + count_in[5:0], + (valid_in & dividend_in[31]) | (~valid_in & dividend_neg_ff), + (valid_in & divisor_in[31] ) | (~valid_in & divisor_neg_ff ), + (valid_in & sign_eff ) | (~valid_in & sign_ff ), + (valid_in & rem_in ) | (~valid_in & rem_ff ), + smallnum_case, + smallnum[3:0], + shortq_enable, + shortq_shift[3:0]}), + + .dout({valid_ff_x, + finish_ff, + run_state, + count[5:0], + dividend_neg_ff, + divisor_neg_ff, + sign_ff, + rem_ff, + smallnum_case_ff, + smallnum_ff[3:0], + shortq_enable_ff, + shortq_shift_xx[3:0]})); + + + rvdffe #(33) mff (.*, .clk(clk), .en(valid_in), .din({signed_in & divisor_in[31], divisor_in[31:0]}), .dout(m_ff[32:0])); + rvdffe #(33) qff (.*, .clk(clk), .en(qff_enable), .din(q_in[32:0]), .dout(q_ff[32:0])); + rvdffe #(33) aff (.*, .clk(clk), .en(aff_enable), .din(a_in[32:0]), .dout(a_ff[32:0])); rvtwoscomp #(32) i_dividend_comp (.din(q_ff[31:0]), .dout(dividend_comp[31:0])); rvtwoscomp #(32) i_q_ff_comp (.din(q_ff[31:0]), .dout(q_ff_comp[31:0])); @@ -95,8 +242,8 @@ import el2_pkg::*; // small number divides - any 4b / 4b is done in 1 cycle (divisor != 0) // to generate espresso equations: - // 1) smalldiv > smalldiv.e - // 2) espresso -Dso -oeqntott smalldiv.e | addassign > smalldiv + // 1. smalldiv > smalldiv.e + // 2. espresso -Dso -oeqntott smalldiv.e | addassign > smalldiv // smallnum case does not cover divide by 0 assign smallnum_case = ((q_ff[31:4] == 28'b0) & (m_ff[31:4] == 28'b0) & (m_ff[31:0] != 32'b0) & ~rem_ff & valid_x) | @@ -153,47 +300,38 @@ import el2_pkg::*; // END - short circuit logic for small numbers }} -// *** Start Short Q *** {{ - - logic [2:0] a_cls; - logic [2:0] b_cls; - logic [3:0] shortq_shift; - logic [4:0] shortq_shift_ff; - logic shortq_enable; - logic shortq_enable_ff; - logic [32:0] short_dividend; + // *** Start Short Q *** {{ assign short_dividend[31:0] = q_ff[31:0]; assign short_dividend[32] = sign_ff & q_ff[31]; -// A B -// 210 210 SH -// --- --- -- -// 1xx 000 0 -// 1xx 001 8 -// 1xx 01x 16 -// 1xx 1xx 24 -// 01x 000 8 -// 01x 001 16 -// 01x 01x 24 -// 01x 1xx 32 -// 001 000 16 -// 001 001 24 -// 001 01x 32 -// 001 1xx 32 -// 000 000 24 -// 000 001 32 -// 000 01x 32 -// 000 1xx 32 - - logic [3:0] shortq_raw; - logic [3:0] shortq_shift_xx; + // A B + // 210 210 SH + // --- --- -- + // 1xx 000 0 + // 1xx 001 8 + // 1xx 01x 16 + // 1xx 1xx 24 + // 01x 000 8 + // 01x 001 16 + // 01x 01x 24 + // 01x 1xx 32 + // 001 000 16 + // 001 001 24 + // 001 01x 32 + // 001 1xx 32 + // 000 000 24 + // 000 001 32 + // 000 01x 32 + // 000 1xx 32 + assign a_cls[4:3] = 2'b0; assign a_cls[2] = (~short_dividend[32] & (short_dividend[31:24] != {8{1'b0}})) | ( short_dividend[32] & (short_dividend[31:23] != {9{1'b1}})); assign a_cls[1] = (~short_dividend[32] & (short_dividend[23:16] != {8{1'b0}})) | ( short_dividend[32] & (short_dividend[22:15] != {8{1'b1}})); assign a_cls[0] = (~short_dividend[32] & (short_dividend[15:08] != {8{1'b0}})) | ( short_dividend[32] & (short_dividend[14:07] != {8{1'b1}})); + assign b_cls[4:3] = 2'b0; assign b_cls[2] = (~m_ff[32] & ( m_ff[31:24] != {8{1'b0}})) | ( m_ff[32] & ( m_ff[31:24] != {8{1'b1}})); assign b_cls[1] = (~m_ff[32] & ( m_ff[23:16] != {8{1'b0}})) | ( m_ff[32] & ( m_ff[23:16] != {8{1'b1}})); assign b_cls[0] = (~m_ff[32] & ( m_ff[15:08] != {8{1'b0}})) | ( m_ff[32] & ( m_ff[15:08] != {8{1'b1}})); @@ -222,54 +360,40 @@ import el2_pkg::*; assign shortq_shift[3:0] = ({4{shortq_enable}} & shortq_raw[3:0]); - rvdff #(5) i_shortq_ff (.*, .clk(exu_div_clk), .din({shortq_enable,shortq_shift[3:0]}), .dout({shortq_enable_ff,shortq_shift_xx[3:0]})); + assign shortq[5:0] = 6'b0; + assign shortq_shift[5:4] = 2'b0; + assign shortq_shift_ff[5] = 1'b0; assign shortq_shift_ff[4:0] = ({5{shortq_shift_xx[3]}} & 5'b1_1111) | // 31 ({5{shortq_shift_xx[2]}} & 5'b1_1000) | // 24 ({5{shortq_shift_xx[1]}} & 5'b1_0000) | // 16 ({5{shortq_shift_xx[0]}} & 5'b0_1000); // 8 -`ifdef ASSERT_ON - - logic div_assert_fail; - - assign div_assert_fail = (shortq_shift_xx[3] & shortq_shift_xx[2]) | - (shortq_shift_xx[3] & shortq_shift_xx[1]) | - (shortq_shift_xx[3] & shortq_shift_xx[0]) | - (shortq_shift_xx[2] & shortq_shift_xx[1]) | - (shortq_shift_xx[2] & shortq_shift_xx[0]) | - (shortq_shift_xx[1] & shortq_shift_xx[0]); - - assert_exu_div_shortq_shift_error: assert #0 (~div_assert_fail) else $display("ERROR: SHORTQ_SHIFT_XX with multiple shifts ON!"); - -`endif - - -// *** End Short *** }} + // *** End Short *** }} - assign div_clken = dp.valid | run_state | finish | finish_ff; + assign div_clken = valid_in | run_state | finish | finish_ff; - assign run_in = (dp.valid | run_state) & ~finish & ~cancel; + assign run_in = (valid_in | run_state) & ~finish & ~cancel; assign count_in[5:0] = {6{run_state & ~finish & ~cancel & ~shortq_enable}} & (count[5:0] + {1'b0,shortq_shift_ff[4:0]} + 6'd1); assign finish = (smallnum_case | ((~rem_ff) ? (count[5:0] == 6'd32) : (count[5:0] == 6'd33))); - assign finish_dly = finish_ff & ~cancel; + assign valid_out = finish_ff & ~cancel; - assign sign_eff = ~dp.unsign & (divisor[31:0] != 32'b0); + assign sign_eff = signed_in & (divisor_in[31:0] != 32'b0); - assign q_in[32:0] = ({33{~run_state }} & {1'b0,dividend[31:0]}) | + assign q_in[32:0] = ({33{~run_state }} & {1'b0,dividend_in[31:0]}) | ({33{ run_state & (valid_ff_x | shortq_enable_ff)}} & ({dividend_eff[31:0], ~a_in[32]} << shortq_shift_ff[4:0])) | ({33{ run_state & ~(valid_ff_x | shortq_enable_ff)}} & {q_ff[31:0], ~a_in[32]}); - assign qff_enable = dp.valid | (run_state & ~shortq_enable); + assign qff_enable = valid_in | (run_state & ~shortq_enable); @@ -279,17 +403,17 @@ import el2_pkg::*; assign m_eff[32:0] = ( add ) ? m_ff[32:0] : ~m_ff[32:0]; - assign a_eff_shift[55:0] = {24'b0, dividend_eff[31:0]} << shortq_shift_ff[4:0]; + assign a_eff_shift[64:0] = {33'b0, dividend_eff[31:0]} << shortq_shift_ff[4:0]; - assign a_eff[32:0] = ({33{ rem_correct }} & a_ff[32:0] ) | - ({33{~rem_correct & ~shortq_enable_ff}} & {a_ff[31:0], q_ff[32]} ) | - ({33{~rem_correct & shortq_enable_ff}} & {9'b0,a_eff_shift[55:32]}); + assign a_eff[32:0] = ({33{ rem_correct }} & a_ff[32:0] ) | + ({33{~rem_correct & ~shortq_enable_ff}} & {a_ff[31:0], q_ff[32]} ) | + ({33{~rem_correct & shortq_enable_ff}} & a_eff_shift[64:32] ); assign a_shift[32:0] = {33{run_state}} & a_eff[32:0]; assign a_in[32:0] = {33{run_state}} & (a_shift[32:0] + m_eff[32:0] + {32'b0,~add}); - assign aff_enable = dp.valid | (run_state & ~shortq_enable & (count[5:0]!=6'd33)) | rem_correct; + assign aff_enable = valid_in | (run_state & ~shortq_enable & (count[5:0]!=6'd33)) | rem_correct; assign m_already_comp = (divisor_neg_ff & sign_ff); @@ -305,9 +429,1373 @@ import el2_pkg::*; assign a_ff_eff[31:0] = (sign_ff & dividend_neg_ff) ? a_ff_comp[31:0] : a_ff[31:0]; - assign out[31:0] = ({32{ smallnum_case_ff }} & {28'b0, smallnum_ff[3:0]}) | + assign data_out[31:0] = ({32{ smallnum_case_ff }} & {28'b0, smallnum_ff[3:0]}) | ({32{ rem_ff}} & a_ff_eff[31:0] ) | ({32{~smallnum_case_ff & ~rem_ff}} & q_ff_eff[31:0] ); -endmodule // el2_exu_div_ctl + + +endmodule // el2_exu_div_existing_1bit_cheapshortq + + + + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +module el2_exu_div_new_1bit_fullshortq + ( + input logic clk, // Top level clock + input logic rst_l, // Reset + input logic scan_mode, // Scan mode + + input logic cancel, // Flush pipeline + input logic valid_in, + input logic signed_in, + input logic rem_in, + input logic [31:0] dividend_in, + input logic [31:0] divisor_in, + + output logic valid_out, + output logic [31:0] data_out + ); + + + logic valid_ff_in, valid_ff; + logic finish_raw, finish, finish_ff; + logic running_state; + logic misc_enable; + logic [2:0] control_in, control_ff; + logic dividend_sign_ff, divisor_sign_ff, rem_ff; + logic count_enable; + logic [6:0] count_in, count_ff; + + logic smallnum_case; + logic [3:0] smallnum; + + logic a_enable, a_shift; + logic [31:0] a_in, a_ff; + + logic b_enable, b_twos_comp; + logic [32:0] b_in, b_ff; + + logic [31:0] q_in, q_ff; + + logic rq_enable, r_sign_sel, r_restore_sel, r_adder_sel; + logic [31:0] r_in, r_ff; + + logic twos_comp_q_sel, twos_comp_b_sel; + logic [31:0] twos_comp_in, twos_comp_out; + + logic quotient_set; + logic [32:0] adder_out; + + logic [63:0] ar_shifted; + logic [5:0] shortq; + logic [4:0] shortq_shift; + logic [4:0] shortq_shift_ff; + logic shortq_enable; + logic shortq_enable_ff; + logic [32:0] shortq_dividend; + + logic by_zero_case; + logic by_zero_case_ff; + + + + rvdffe #(19) i_misc_ff (.*, .clk(clk), .en(misc_enable), .din ({valid_ff_in, control_in[2:0], by_zero_case, shortq_enable, shortq_shift[4:0], finish, count_in[6:0]}), + .dout({valid_ff, control_ff[2:0], by_zero_case_ff, shortq_enable_ff, shortq_shift_ff[4:0], finish_ff, count_ff[6:0]})); + + rvdffe #(32) i_a_ff (.*, .clk(clk), .en(a_enable), .din(a_in[31:0]), .dout(a_ff[31:0])); + rvdffe #(33) i_b_ff (.*, .clk(clk), .en(b_enable), .din(b_in[32:0]), .dout(b_ff[32:0])); + rvdffe #(32) i_r_ff (.*, .clk(clk), .en(rq_enable), .din(r_in[31:0]), .dout(r_ff[31:0])); + rvdffe #(32) i_q_ff (.*, .clk(clk), .en(rq_enable), .din(q_in[31:0]), .dout(q_ff[31:0])); + + + + + assign valid_ff_in = valid_in & ~cancel; + + assign control_in[2] = (~valid_in & control_ff[2]) | (valid_in & signed_in & dividend_in[31]); + assign control_in[1] = (~valid_in & control_ff[1]) | (valid_in & signed_in & divisor_in[31]); + assign control_in[0] = (~valid_in & control_ff[0]) | (valid_in & rem_in); + + assign dividend_sign_ff = control_ff[2]; + assign divisor_sign_ff = control_ff[1]; + assign rem_ff = control_ff[0]; + + + assign by_zero_case = valid_ff & (b_ff[31:0] == 32'b0); + + assign misc_enable = valid_in | valid_ff | cancel | running_state | finish_ff; + assign running_state = (| count_ff[6:0]) | shortq_enable_ff; + assign finish_raw = smallnum_case | + by_zero_case | + (count_ff[6:0] == 7'd32); + + + assign finish = finish_raw & ~cancel; + assign count_enable = (valid_ff | running_state) & ~finish & ~finish_ff & ~cancel & ~shortq_enable; + assign count_in[6:0] = {7{count_enable}} & (count_ff[6:0] + {6'b0,1'b1} + {2'b0,shortq_shift_ff[4:0]}); + + + assign a_enable = valid_in | running_state; + assign a_shift = running_state & ~shortq_enable_ff; + + assign ar_shifted[63:0] = { {32{dividend_sign_ff}} , a_ff[31:0]} << shortq_shift_ff[4:0]; + + assign a_in[31:0] = ( {32{~a_shift & ~shortq_enable_ff}} & dividend_in[31:0] ) | + ( {32{ a_shift }} & {a_ff[30:0],1'b0} ) | + ( {32{ shortq_enable_ff}} & ar_shifted[31:0] ); + + + + assign b_enable = valid_in | b_twos_comp; + assign b_twos_comp = valid_ff & ~(dividend_sign_ff ^ divisor_sign_ff); + + assign b_in[32:0] = ( {33{~b_twos_comp}} & { (signed_in & divisor_in[31]),divisor_in[31:0] } ) | + ( {33{ b_twos_comp}} & {~divisor_sign_ff,twos_comp_out[31:0] } ); + + + assign rq_enable = valid_in | valid_ff | running_state; + assign r_sign_sel = valid_ff & dividend_sign_ff & ~by_zero_case; + assign r_restore_sel = running_state & ~quotient_set & ~shortq_enable_ff; + assign r_adder_sel = running_state & quotient_set & ~shortq_enable_ff; + + + assign r_in[31:0] = ( {32{r_sign_sel }} & 32'hffffffff ) | + ( {32{r_restore_sel }} & {r_ff[30:0] ,a_ff[31]} ) | + ( {32{r_adder_sel }} & adder_out[31:0] ) | + ( {32{shortq_enable_ff}} & ar_shifted[63:32] ) | + ( {32{by_zero_case }} & a_ff[31:0] ); + + + assign q_in[31:0] = ( {32{~valid_ff }} & {q_ff[30:0], quotient_set} ) | + ( {32{ smallnum_case }} & {28'b0 , smallnum[3:0]} ) | + ( {32{ by_zero_case }} & {32{1'b1}} ); + + + + assign adder_out[32:0] = {r_ff[31:0],a_ff[31]} + {b_ff[32:0] }; + + + assign quotient_set = (~adder_out[32] ^ dividend_sign_ff) | ( (a_ff[30:0] == 31'b0) & (adder_out[32:0] == 33'b0) ); + + + + assign twos_comp_b_sel = valid_ff & ~(dividend_sign_ff ^ divisor_sign_ff); + assign twos_comp_q_sel = ~valid_ff & ~rem_ff & (dividend_sign_ff ^ divisor_sign_ff) & ~by_zero_case_ff; + + assign twos_comp_in[31:0] = ( {32{twos_comp_q_sel}} & q_ff[31:0] ) | + ( {32{twos_comp_b_sel}} & b_ff[31:0] ); + + rvtwoscomp #(32) i_twos_comp (.din(twos_comp_in[31:0]), .dout(twos_comp_out[31:0])); + + + + assign valid_out = finish_ff & ~cancel; + + assign data_out[31:0] = ( {32{~rem_ff & ~twos_comp_q_sel}} & q_ff[31:0] ) | + ( {32{ rem_ff }} & r_ff[31:0] ) | + ( {32{ twos_comp_q_sel}} & twos_comp_out[31:0] ); + + + + + // *** *** *** START : SMALLNUM {{ + + assign smallnum_case = ( (a_ff[31:4] == 28'b0) & (b_ff[31:4] == 28'b0) & ~by_zero_case & ~rem_ff & valid_ff & ~cancel) | + ( (a_ff[31:0] == 32'b0) & ~by_zero_case & ~rem_ff & valid_ff & ~cancel); + + assign smallnum[3] = ( a_ff[3] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ); + + assign smallnum[2] = ( a_ff[3] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[2] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & ~b_ff[2] ); + + assign smallnum[1] = ( a_ff[2] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[1] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & ~b_ff[3] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & ~a_ff[2] & ~b_ff[3] & ~b_ff[2] & b_ff[1] & b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[1] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[2] ); + + assign smallnum[0] = ( a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & a_ff[0] & ~b_ff[3] & b_ff[1] & b_ff[0]) | + ( a_ff[2] & ~b_ff[3] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[1] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[0] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + (~a_ff[3] & a_ff[2] & ~a_ff[1] & ~b_ff[3] & ~b_ff[2] & b_ff[1] & b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & ~b_ff[2] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & ~a_ff[2] & ~b_ff[3] & b_ff[2] & b_ff[1] ) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[2] & ~b_ff[1] ) | + (~a_ff[3] & a_ff[2] & a_ff[0] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & ~a_ff[1] & ~b_ff[3] & b_ff[2] & b_ff[0]) | + ( ~a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & a_ff[1] & ~b_ff[2] & ~b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & b_ff[2] ) | + ( a_ff[3] & a_ff[2] & b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[1] & b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[0] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[1] & ~b_ff[3] & b_ff[2] & b_ff[1] & b_ff[0]) | + ( a_ff[3] & a_ff[2] & a_ff[1] & b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & a_ff[2] & a_ff[1] & b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & a_ff[0] & b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[1] ) | + ( a_ff[3] & a_ff[1] & a_ff[0] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & a_ff[1] & a_ff[0] & b_ff[3] ); + + // *** *** *** END : SMALLNUM }} + + + + + // *** *** *** Start : Short Q {{ + + assign shortq_dividend[32:0] = {dividend_sign_ff,a_ff[31:0]}; + + + logic [5:0] dw_a_enc; + logic [5:0] dw_b_enc; + logic [6:0] dw_shortq_raw; + + + + el2_exu_div_cls i_a_cls ( + .operand ( shortq_dividend[32:0] ), + .cls ( dw_a_enc[4:0] )); + + el2_exu_div_cls i_b_cls ( + .operand ( b_ff[32:0] ), + .cls ( dw_b_enc[4:0] )); + + assign dw_a_enc[5] = 1'b0; + assign dw_b_enc[5] = 1'b0; + + + + assign dw_shortq_raw[6:0] = {1'b0,dw_b_enc[5:0]} - {1'b0,dw_a_enc[5:0]} + 7'd1; + assign shortq[5:0] = dw_shortq_raw[6] ? 6'd0 : dw_shortq_raw[5:0]; + + assign shortq_enable = valid_ff & ~shortq[5] & ~(shortq[4:1] == 4'b1111) & ~cancel; + + assign shortq_shift[4:0] = ~shortq_enable ? 5'd0 : (5'b11111 - shortq[4:0]); + + + // *** *** *** End : Short Q }} + + + + + +endmodule // el2_exu_div_new_1bit_fullshortq + + + + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +module el2_exu_div_new_2bit_fullshortq + ( + input logic clk, // Top level clock + input logic rst_l, // Reset + input logic scan_mode, // Scan mode + + input logic cancel, // Flush pipeline + input logic valid_in, + input logic signed_in, + input logic rem_in, + input logic [31:0] dividend_in, + input logic [31:0] divisor_in, + + output logic valid_out, + output logic [31:0] data_out + ); + + + logic valid_ff_in, valid_ff; + logic finish_raw, finish, finish_ff; + logic running_state; + logic misc_enable; + logic [2:0] control_in, control_ff; + logic dividend_sign_ff, divisor_sign_ff, rem_ff; + logic count_enable; + logic [6:0] count_in, count_ff; + + logic smallnum_case; + logic [3:0] smallnum; + + logic a_enable, a_shift; + logic [31:0] a_in, a_ff; + + logic b_enable, b_twos_comp; + logic [32:0] b_in; + logic [34:0] b_ff; + + logic [31:0] q_in, q_ff; + + logic rq_enable, r_sign_sel, r_restore_sel, r_adder1_sel, r_adder2_sel, r_adder3_sel; + logic [31:0] r_in, r_ff; + + logic twos_comp_q_sel, twos_comp_b_sel; + logic [31:0] twos_comp_in, twos_comp_out; + + logic [3:1] quotient_raw; + logic [1:0] quotient_new; + logic [32:0] adder1_out; + logic [33:0] adder2_out; + logic [34:0] adder3_out; + + logic [63:0] ar_shifted; + logic [5:0] shortq; + logic [4:0] shortq_shift; + logic [4:1] shortq_shift_ff; + logic shortq_enable; + logic shortq_enable_ff; + logic [32:0] shortq_dividend; + + logic by_zero_case; + logic by_zero_case_ff; + + + + rvdffe #(18) i_misc_ff (.*, .clk(clk), .en(misc_enable), .din ({valid_ff_in, control_in[2:0], by_zero_case, shortq_enable, shortq_shift[4:1], finish, count_in[6:0]}), + .dout({valid_ff, control_ff[2:0], by_zero_case_ff, shortq_enable_ff, shortq_shift_ff[4:1], finish_ff, count_ff[6:0]})); + + rvdffe #(32) i_a_ff (.*, .clk(clk), .en(a_enable), .din(a_in[31:0]), .dout(a_ff[31:0])); + rvdffe #(33) i_b_ff (.*, .clk(clk), .en(b_enable), .din(b_in[32:0]), .dout(b_ff[32:0])); + rvdffe #(32) i_r_ff (.*, .clk(clk), .en(rq_enable), .din(r_in[31:0]), .dout(r_ff[31:0])); + rvdffe #(32) i_q_ff (.*, .clk(clk), .en(rq_enable), .din(q_in[31:0]), .dout(q_ff[31:0])); + + + + + assign valid_ff_in = valid_in & ~cancel; + + assign control_in[2] = (~valid_in & control_ff[2]) | (valid_in & signed_in & dividend_in[31]); + assign control_in[1] = (~valid_in & control_ff[1]) | (valid_in & signed_in & divisor_in[31]); + assign control_in[0] = (~valid_in & control_ff[0]) | (valid_in & rem_in); + + assign dividend_sign_ff = control_ff[2]; + assign divisor_sign_ff = control_ff[1]; + assign rem_ff = control_ff[0]; + + + assign by_zero_case = valid_ff & (b_ff[31:0] == 32'b0); + + assign misc_enable = valid_in | valid_ff | cancel | running_state | finish_ff; + assign running_state = (| count_ff[6:0]) | shortq_enable_ff; + assign finish_raw = smallnum_case | + by_zero_case | + (count_ff[6:0] == 7'd32); + + + assign finish = finish_raw & ~cancel; + assign count_enable = (valid_ff | running_state) & ~finish & ~finish_ff & ~cancel & ~shortq_enable; + assign count_in[6:0] = {7{count_enable}} & (count_ff[6:0] + {5'b0,2'b10} + {2'b0,shortq_shift_ff[4:1],1'b0}); + + + assign a_enable = valid_in | running_state; + assign a_shift = running_state & ~shortq_enable_ff; + + assign ar_shifted[63:0] = { {32{dividend_sign_ff}} , a_ff[31:0]} << {shortq_shift_ff[4:1],1'b0}; + + assign a_in[31:0] = ( {32{~a_shift & ~shortq_enable_ff}} & dividend_in[31:0] ) | + ( {32{ a_shift }} & {a_ff[29:0],2'b0} ) | + ( {32{ shortq_enable_ff}} & ar_shifted[31:0] ); + + + + assign b_enable = valid_in | b_twos_comp; + assign b_twos_comp = valid_ff & ~(dividend_sign_ff ^ divisor_sign_ff); + + assign b_in[32:0] = ( {33{~b_twos_comp}} & { (signed_in & divisor_in[31]),divisor_in[31:0] } ) | + ( {33{ b_twos_comp}} & {~divisor_sign_ff,twos_comp_out[31:0] } ); + + + assign rq_enable = valid_in | valid_ff | running_state; + assign r_sign_sel = valid_ff & dividend_sign_ff & ~by_zero_case; + assign r_restore_sel = running_state & (quotient_new[1:0] == 2'b00) & ~shortq_enable_ff; + assign r_adder1_sel = running_state & (quotient_new[1:0] == 2'b01) & ~shortq_enable_ff; + assign r_adder2_sel = running_state & (quotient_new[1:0] == 2'b10) & ~shortq_enable_ff; + assign r_adder3_sel = running_state & (quotient_new[1:0] == 2'b11) & ~shortq_enable_ff; + + + assign r_in[31:0] = ( {32{r_sign_sel }} & 32'hffffffff ) | + ( {32{r_restore_sel }} & {r_ff[29:0] ,a_ff[31:30]} ) | + ( {32{r_adder1_sel }} & adder1_out[31:0] ) | + ( {32{r_adder2_sel }} & adder2_out[31:0] ) | + ( {32{r_adder3_sel }} & adder3_out[31:0] ) | + ( {32{shortq_enable_ff}} & ar_shifted[63:32] ) | + ( {32{by_zero_case }} & a_ff[31:0] ); + + + assign q_in[31:0] = ( {32{~valid_ff }} & {q_ff[29:0], quotient_new[1:0]} ) | + ( {32{ smallnum_case }} & {28'b0 , smallnum[3:0]} ) | + ( {32{ by_zero_case }} & {32{1'b1}} ); + + + assign b_ff[34:33] = {b_ff[32],b_ff[32]}; + + + assign adder1_out[32:0] = { r_ff[30:0],a_ff[31:30]} + b_ff[32:0]; + assign adder2_out[33:0] = { r_ff[31:0],a_ff[31:30]} + {b_ff[32:0],1'b0}; + assign adder3_out[34:0] = {r_ff[31],r_ff[31:0],a_ff[31:30]} + {b_ff[33:0],1'b0} + b_ff[34:0]; + + + assign quotient_raw[1] = (~adder1_out[32] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder1_out[32:0] == 33'b0) ); + assign quotient_raw[2] = (~adder2_out[33] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder2_out[33:0] == 34'b0) ); + assign quotient_raw[3] = (~adder3_out[34] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder3_out[34:0] == 35'b0) ); + + assign quotient_new[1] = quotient_raw[3] | quotient_raw[2]; + assign quotient_new[0] = quotient_raw[3] |(~quotient_raw[2] & quotient_raw[1]); + + + assign twos_comp_b_sel = valid_ff & ~(dividend_sign_ff ^ divisor_sign_ff); + assign twos_comp_q_sel = ~valid_ff & ~rem_ff & (dividend_sign_ff ^ divisor_sign_ff) & ~by_zero_case_ff; + + assign twos_comp_in[31:0] = ( {32{twos_comp_q_sel}} & q_ff[31:0] ) | + ( {32{twos_comp_b_sel}} & b_ff[31:0] ); + + rvtwoscomp #(32) i_twos_comp (.din(twos_comp_in[31:0]), .dout(twos_comp_out[31:0])); + + + + assign valid_out = finish_ff & ~cancel; + + assign data_out[31:0] = ( {32{~rem_ff & ~twos_comp_q_sel}} & q_ff[31:0] ) | + ( {32{ rem_ff }} & r_ff[31:0] ) | + ( {32{ twos_comp_q_sel}} & twos_comp_out[31:0] ); + + + + + // *** *** *** START : SMALLNUM {{ + + assign smallnum_case = ( (a_ff[31:4] == 28'b0) & (b_ff[31:4] == 28'b0) & ~by_zero_case & ~rem_ff & valid_ff & ~cancel) | + ( (a_ff[31:0] == 32'b0) & ~by_zero_case & ~rem_ff & valid_ff & ~cancel); + + assign smallnum[3] = ( a_ff[3] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ); + + assign smallnum[2] = ( a_ff[3] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[2] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & ~b_ff[2] ); + + assign smallnum[1] = ( a_ff[2] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[1] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & ~b_ff[3] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & ~a_ff[2] & ~b_ff[3] & ~b_ff[2] & b_ff[1] & b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[1] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[2] ); + + assign smallnum[0] = ( a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & a_ff[0] & ~b_ff[3] & b_ff[1] & b_ff[0]) | + ( a_ff[2] & ~b_ff[3] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[1] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[0] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + (~a_ff[3] & a_ff[2] & ~a_ff[1] & ~b_ff[3] & ~b_ff[2] & b_ff[1] & b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & ~b_ff[2] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & ~a_ff[2] & ~b_ff[3] & b_ff[2] & b_ff[1] ) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[2] & ~b_ff[1] ) | + (~a_ff[3] & a_ff[2] & a_ff[0] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & ~a_ff[1] & ~b_ff[3] & b_ff[2] & b_ff[0]) | + ( ~a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & a_ff[1] & ~b_ff[2] & ~b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & b_ff[2] ) | + ( a_ff[3] & a_ff[2] & b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[1] & b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[0] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[1] & ~b_ff[3] & b_ff[2] & b_ff[1] & b_ff[0]) | + ( a_ff[3] & a_ff[2] & a_ff[1] & b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & a_ff[2] & a_ff[1] & b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & a_ff[0] & b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[1] ) | + ( a_ff[3] & a_ff[1] & a_ff[0] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & a_ff[1] & a_ff[0] & b_ff[3] ); + + // *** *** *** END : SMALLNUM }} + + + + + // *** *** *** Start : Short Q {{ + + assign shortq_dividend[32:0] = {dividend_sign_ff,a_ff[31:0]}; + + + logic [5:0] dw_a_enc; + logic [5:0] dw_b_enc; + logic [6:0] dw_shortq_raw; + + + + el2_exu_div_cls i_a_cls ( + .operand ( shortq_dividend[32:0] ), + .cls ( dw_a_enc[4:0] )); + + el2_exu_div_cls i_b_cls ( + .operand ( b_ff[32:0] ), + .cls ( dw_b_enc[4:0] )); + + assign dw_a_enc[5] = 1'b0; + assign dw_b_enc[5] = 1'b0; + + + + assign dw_shortq_raw[6:0] = {1'b0,dw_b_enc[5:0]} - {1'b0,dw_a_enc[5:0]} + 7'd1; + assign shortq[5:0] = dw_shortq_raw[6] ? 6'd0 : dw_shortq_raw[5:0]; + + assign shortq_enable = valid_ff & ~shortq[5] & ~(shortq[4:1] == 4'b1111) & ~cancel; + + assign shortq_shift[4:0] = ~shortq_enable ? 5'd0 : (5'b11111 - shortq[4:0]); // [0] is unused + + + // *** *** *** End : Short Q }} + + + + + +endmodule // el2_exu_div_new_2bit_fullshortq + + + + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +module el2_exu_div_new_3bit_fullshortq + ( + input logic clk, // Top level clock + input logic rst_l, // Reset + input logic scan_mode, // Scan mode + + input logic cancel, // Flush pipeline + input logic valid_in, + input logic signed_in, + input logic rem_in, + input logic [31:0] dividend_in, + input logic [31:0] divisor_in, + + output logic valid_out, + output logic [31:0] data_out + ); + + + logic valid_ff_in, valid_ff; + logic finish_raw, finish, finish_ff; + logic running_state; + logic misc_enable; + logic [2:0] control_in, control_ff; + logic dividend_sign_ff, divisor_sign_ff, rem_ff; + logic count_enable; + logic [6:0] count_in, count_ff; + + logic smallnum_case; + logic [3:0] smallnum; + + logic a_enable, a_shift; + logic [32:0] a_in, a_ff; + + logic b_enable, b_twos_comp; + logic [32:0] b_in; + logic [36:0] b_ff; + + logic [31:0] q_in, q_ff; + + logic rq_enable; + logic r_sign_sel; + logic r_restore_sel; + logic r_adder1_sel, r_adder2_sel, r_adder3_sel, r_adder4_sel, r_adder5_sel, r_adder6_sel, r_adder7_sel; + logic [32:0] r_in, r_ff; + + logic twos_comp_q_sel, twos_comp_b_sel; + logic [31:0] twos_comp_in, twos_comp_out; + + logic [7:1] quotient_raw; + logic [2:0] quotient_new; + logic [33:0] adder1_out; + logic [34:0] adder2_out; + logic [35:0] adder3_out; + logic [36:0] adder4_out; + logic [36:0] adder5_out; + logic [36:0] adder6_out; + logic [36:0] adder7_out; + + logic [65:0] ar_shifted; + logic [5:0] shortq; + logic [4:0] shortq_shift; + logic [4:0] shortq_decode; + logic [4:0] shortq_shift_ff; + logic shortq_enable; + logic shortq_enable_ff; + logic [32:0] shortq_dividend; + + logic by_zero_case; + logic by_zero_case_ff; + + + + rvdffe #(19) i_misc_ff (.*, .clk(clk), .en(misc_enable), .din ({valid_ff_in, control_in[2:0], by_zero_case, shortq_enable, shortq_shift[4:0], finish, count_in[6:0]}), + .dout({valid_ff, control_ff[2:0], by_zero_case_ff, shortq_enable_ff, shortq_shift_ff[4:0], finish_ff, count_ff[6:0]})); + + rvdffe #(33) i_a_ff (.*, .clk(clk), .en(a_enable), .din(a_in[32:0]), .dout(a_ff[32:0])); + rvdffe #(33) i_b_ff (.*, .clk(clk), .en(b_enable), .din(b_in[32:0]), .dout(b_ff[32:0])); + rvdffe #(33) i_r_ff (.*, .clk(clk), .en(rq_enable), .din(r_in[32:0]), .dout(r_ff[32:0])); + rvdffe #(32) i_q_ff (.*, .clk(clk), .en(rq_enable), .din(q_in[31:0]), .dout(q_ff[31:0])); + + + + + assign valid_ff_in = valid_in & ~cancel; + + assign control_in[2] = (~valid_in & control_ff[2]) | (valid_in & signed_in & dividend_in[31]); + assign control_in[1] = (~valid_in & control_ff[1]) | (valid_in & signed_in & divisor_in[31]); + assign control_in[0] = (~valid_in & control_ff[0]) | (valid_in & rem_in); + + assign dividend_sign_ff = control_ff[2]; + assign divisor_sign_ff = control_ff[1]; + assign rem_ff = control_ff[0]; + + + assign by_zero_case = valid_ff & (b_ff[31:0] == 32'b0); + + assign misc_enable = valid_in | valid_ff | cancel | running_state | finish_ff; + assign running_state = (| count_ff[6:0]) | shortq_enable_ff; + assign finish_raw = smallnum_case | + by_zero_case | + (count_ff[6:0] == 7'd33); + + + assign finish = finish_raw & ~cancel; + assign count_enable = (valid_ff | running_state) & ~finish & ~finish_ff & ~cancel & ~shortq_enable; + assign count_in[6:0] = {7{count_enable}} & (count_ff[6:0] + {5'b0,2'b11} + {2'b0,shortq_shift_ff[4:0]}); + + + assign a_enable = valid_in | running_state; + assign a_shift = running_state & ~shortq_enable_ff; + + assign ar_shifted[65:0] = { {33{dividend_sign_ff}} , a_ff[32:0]} << {shortq_shift_ff[4:0]}; + + assign a_in[32:0] = ( {33{~a_shift & ~shortq_enable_ff}} & {signed_in & dividend_in[31],dividend_in[31:0]} ) | + ( {33{ a_shift }} & {a_ff[29:0],3'b0} ) | + ( {33{ shortq_enable_ff}} & ar_shifted[32:0] ); + + + + assign b_enable = valid_in | b_twos_comp; + assign b_twos_comp = valid_ff & ~(dividend_sign_ff ^ divisor_sign_ff); + + assign b_in[32:0] = ( {33{~b_twos_comp}} & { (signed_in & divisor_in[31]),divisor_in[31:0] } ) | + ( {33{ b_twos_comp}} & {~divisor_sign_ff,twos_comp_out[31:0] } ); + + + assign rq_enable = valid_in | valid_ff | running_state; + assign r_sign_sel = valid_ff & dividend_sign_ff & ~by_zero_case; + assign r_restore_sel = running_state & (quotient_new[2:0] == 3'b000) & ~shortq_enable_ff; + assign r_adder1_sel = running_state & (quotient_new[2:0] == 3'b001) & ~shortq_enable_ff; + assign r_adder2_sel = running_state & (quotient_new[2:0] == 3'b010) & ~shortq_enable_ff; + assign r_adder3_sel = running_state & (quotient_new[2:0] == 3'b011) & ~shortq_enable_ff; + assign r_adder4_sel = running_state & (quotient_new[2:0] == 3'b100) & ~shortq_enable_ff; + assign r_adder5_sel = running_state & (quotient_new[2:0] == 3'b101) & ~shortq_enable_ff; + assign r_adder6_sel = running_state & (quotient_new[2:0] == 3'b110) & ~shortq_enable_ff; + assign r_adder7_sel = running_state & (quotient_new[2:0] == 3'b111) & ~shortq_enable_ff; + + + assign r_in[32:0] = ( {33{r_sign_sel }} & {33{1'b1}} ) | + ( {33{r_restore_sel }} & {r_ff[29:0] ,a_ff[32:30]} ) | + ( {33{r_adder1_sel }} & adder1_out[32:0] ) | + ( {33{r_adder2_sel }} & adder2_out[32:0] ) | + ( {33{r_adder3_sel }} & adder3_out[32:0] ) | + ( {33{r_adder4_sel }} & adder4_out[32:0] ) | + ( {33{r_adder5_sel }} & adder5_out[32:0] ) | + ( {33{r_adder6_sel }} & adder6_out[32:0] ) | + ( {33{r_adder7_sel }} & adder7_out[32:0] ) | + ( {33{shortq_enable_ff}} & ar_shifted[65:33] ) | + ( {33{by_zero_case }} & {1'b0,a_ff[31:0]} ); + + + assign q_in[31:0] = ( {32{~valid_ff }} & {q_ff[28:0], quotient_new[2:0]} ) | + ( {32{ smallnum_case}} & {28'b0 , smallnum[3:0]} ) | + ( {32{ by_zero_case }} & {32{1'b1}} ); + + + assign b_ff[36:33] = {b_ff[32],b_ff[32],b_ff[32],b_ff[32]}; + + + assign adder1_out[33:0] = { r_ff[30:0],a_ff[32:30]} + b_ff[33:0]; + assign adder2_out[34:0] = { r_ff[31:0],a_ff[32:30]} + {b_ff[33:0],1'b0}; + assign adder3_out[35:0] = { r_ff[32:0],a_ff[32:30]} + {b_ff[34:0],1'b0} + b_ff[35:0]; + assign adder4_out[36:0] = {r_ff[32],r_ff[32:0],a_ff[32:30]} + {b_ff[34:0],2'b0}; + assign adder5_out[36:0] = {r_ff[32],r_ff[32:0],a_ff[32:30]} + {b_ff[34:0],2'b0} + b_ff[36:0]; + assign adder6_out[36:0] = {r_ff[32],r_ff[32:0],a_ff[32:30]} + {b_ff[34:0],2'b0} + {b_ff[35:0],1'b0}; + assign adder7_out[36:0] = {r_ff[32],r_ff[32:0],a_ff[32:30]} + {b_ff[34:0],2'b0} + {b_ff[35:0],1'b0} + b_ff[36:0]; + + assign quotient_raw[1] = (~adder1_out[33] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder1_out[33:0] == 34'b0) ); + assign quotient_raw[2] = (~adder2_out[34] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder2_out[34:0] == 35'b0) ); + assign quotient_raw[3] = (~adder3_out[35] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder3_out[35:0] == 36'b0) ); + assign quotient_raw[4] = (~adder4_out[36] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder4_out[36:0] == 37'b0) ); + assign quotient_raw[5] = (~adder5_out[36] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder5_out[36:0] == 37'b0) ); + assign quotient_raw[6] = (~adder6_out[36] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder6_out[36:0] == 37'b0) ); + assign quotient_raw[7] = (~adder7_out[36] ^ dividend_sign_ff) | ( (a_ff[29:0] == 30'b0) & (adder7_out[36:0] == 37'b0) ); + + assign quotient_new[2] = quotient_raw[7] | quotient_raw[6] | quotient_raw[5] | quotient_raw[4]; + assign quotient_new[1] = quotient_raw[7] | quotient_raw[6] | (~quotient_raw[4] & quotient_raw[3]) | (~quotient_raw[3] & quotient_raw[2]); + assign quotient_new[0] = quotient_raw[7] | (~quotient_raw[6] & quotient_raw[5]) | (~quotient_raw[4] & quotient_raw[3]) | (~quotient_raw[2] & quotient_raw[1]); + + + assign twos_comp_b_sel = valid_ff & ~(dividend_sign_ff ^ divisor_sign_ff); + assign twos_comp_q_sel = ~valid_ff & ~rem_ff & (dividend_sign_ff ^ divisor_sign_ff) & ~by_zero_case_ff; + + assign twos_comp_in[31:0] = ( {32{twos_comp_q_sel}} & q_ff[31:0] ) | + ( {32{twos_comp_b_sel}} & b_ff[31:0] ); + + rvtwoscomp #(32) i_twos_comp (.din(twos_comp_in[31:0]), .dout(twos_comp_out[31:0])); + + + + assign valid_out = finish_ff & ~cancel; + + assign data_out[31:0] = ( {32{~rem_ff & ~twos_comp_q_sel}} & q_ff[31:0] ) | + ( {32{ rem_ff }} & r_ff[31:0] ) | + ( {32{ twos_comp_q_sel}} & twos_comp_out[31:0] ); + + + + + // *** *** *** START : SMALLNUM {{ + + assign smallnum_case = ( (a_ff[31:4] == 28'b0) & (b_ff[31:4] == 28'b0) & ~by_zero_case & ~rem_ff & valid_ff & ~cancel) | + ( (a_ff[31:0] == 32'b0) & ~by_zero_case & ~rem_ff & valid_ff & ~cancel); + + assign smallnum[3] = ( a_ff[3] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ); + + assign smallnum[2] = ( a_ff[3] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[2] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & ~b_ff[2] ); + + assign smallnum[1] = ( a_ff[2] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[1] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & ~b_ff[3] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & ~a_ff[2] & ~b_ff[3] & ~b_ff[2] & b_ff[1] & b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[1] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[2] ); + + assign smallnum[0] = ( a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & a_ff[0] & ~b_ff[3] & b_ff[1] & b_ff[0]) | + ( a_ff[2] & ~b_ff[3] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[1] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[0] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + (~a_ff[3] & a_ff[2] & ~a_ff[1] & ~b_ff[3] & ~b_ff[2] & b_ff[1] & b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & ~b_ff[2] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & ~a_ff[2] & ~b_ff[3] & b_ff[2] & b_ff[1] ) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[2] & ~b_ff[1] ) | + (~a_ff[3] & a_ff[2] & a_ff[0] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & ~a_ff[1] & ~b_ff[3] & b_ff[2] & b_ff[0]) | + ( ~a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & a_ff[1] & ~b_ff[2] & ~b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & b_ff[2] ) | + ( a_ff[3] & a_ff[2] & b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[1] & b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[0] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[1] & ~b_ff[3] & b_ff[2] & b_ff[1] & b_ff[0]) | + ( a_ff[3] & a_ff[2] & a_ff[1] & b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & a_ff[2] & a_ff[1] & b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & a_ff[0] & b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[1] ) | + ( a_ff[3] & a_ff[1] & a_ff[0] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & a_ff[1] & a_ff[0] & b_ff[3] ); + + // *** *** *** END : SMALLNUM }} + + + + + // *** *** *** Start : Short Q {{ + + assign shortq_dividend[32:0] = {dividend_sign_ff,a_ff[31:0]}; + + + logic [5:0] dw_a_enc; + logic [5:0] dw_b_enc; + logic [6:0] dw_shortq_raw; + + + + el2_exu_div_cls i_a_cls ( + .operand ( shortq_dividend[32:0] ), + .cls ( dw_a_enc[4:0] )); + + el2_exu_div_cls i_b_cls ( + .operand ( b_ff[32:0] ), + .cls ( dw_b_enc[4:0] )); + + assign dw_a_enc[5] = 1'b0; + assign dw_b_enc[5] = 1'b0; + + + + assign dw_shortq_raw[6:0] = {1'b0,dw_b_enc[5:0]} - {1'b0,dw_a_enc[5:0]} + 7'd1; + assign shortq[5:0] = dw_shortq_raw[6] ? 6'd0 : dw_shortq_raw[5:0]; + + assign shortq_enable = valid_ff & ~shortq[5] & ~(shortq[4:2] == 3'b111) & ~cancel; + + assign shortq_decode[4:0] = ( {5{shortq[4:0] == 5'd31}} & 5'd00) | + ( {5{shortq[4:0] == 5'd30}} & 5'd00) | + ( {5{shortq[4:0] == 5'd29}} & 5'd00) | + ( {5{shortq[4:0] == 5'd28}} & 5'd00) | + ( {5{shortq[4:0] == 5'd27}} & 5'd03) | + ( {5{shortq[4:0] == 5'd26}} & 5'd06) | + ( {5{shortq[4:0] == 5'd25}} & 5'd06) | + ( {5{shortq[4:0] == 5'd24}} & 5'd06) | + ( {5{shortq[4:0] == 5'd23}} & 5'd09) | + ( {5{shortq[4:0] == 5'd22}} & 5'd09) | + ( {5{shortq[4:0] == 5'd21}} & 5'd09) | + ( {5{shortq[4:0] == 5'd20}} & 5'd12) | + ( {5{shortq[4:0] == 5'd19}} & 5'd12) | + ( {5{shortq[4:0] == 5'd18}} & 5'd12) | + ( {5{shortq[4:0] == 5'd17}} & 5'd15) | + ( {5{shortq[4:0] == 5'd16}} & 5'd15) | + ( {5{shortq[4:0] == 5'd15}} & 5'd15) | + ( {5{shortq[4:0] == 5'd14}} & 5'd18) | + ( {5{shortq[4:0] == 5'd13}} & 5'd18) | + ( {5{shortq[4:0] == 5'd12}} & 5'd18) | + ( {5{shortq[4:0] == 5'd11}} & 5'd21) | + ( {5{shortq[4:0] == 5'd10}} & 5'd21) | + ( {5{shortq[4:0] == 5'd09}} & 5'd21) | + ( {5{shortq[4:0] == 5'd08}} & 5'd24) | + ( {5{shortq[4:0] == 5'd07}} & 5'd24) | + ( {5{shortq[4:0] == 5'd06}} & 5'd24) | + ( {5{shortq[4:0] == 5'd05}} & 5'd27) | + ( {5{shortq[4:0] == 5'd04}} & 5'd27) | + ( {5{shortq[4:0] == 5'd03}} & 5'd27) | + ( {5{shortq[4:0] == 5'd02}} & 5'd27) | + ( {5{shortq[4:0] == 5'd01}} & 5'd27) | + ( {5{shortq[4:0] == 5'd00}} & 5'd27); + + + assign shortq_shift[4:0] = ~shortq_enable ? 5'd0 : shortq_decode[4:0]; + + + // *** *** *** End : Short Q }} + + + + + +endmodule // el2_exu_div_new_3bit_fullshortq + + + + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +module el2_exu_div_new_4bit_fullshortq + ( + input logic clk, // Top level clock + input logic rst_l, // Reset + input logic scan_mode, // Scan mode + + input logic cancel, // Flush pipeline + input logic valid_in, + input logic signed_in, + input logic rem_in, + input logic [31:0] dividend_in, + input logic [31:0] divisor_in, + + output logic valid_out, + output logic [31:0] data_out + ); + + + logic valid_ff_in, valid_ff; + logic finish_raw, finish, finish_ff; + logic running_state; + logic misc_enable; + logic [2:0] control_in, control_ff; + logic dividend_sign_ff, divisor_sign_ff, rem_ff; + logic count_enable; + logic [6:0] count_in, count_ff; + + logic smallnum_case; + logic [3:0] smallnum; + + logic a_enable, a_shift; + logic [31:0] a_in, a_ff; + + logic b_enable, b_twos_comp; + logic [32:0] b_in; + logic [37:0] b_ff; + + logic [31:0] q_in, q_ff; + + logic rq_enable; + logic r_sign_sel; + logic r_restore_sel; + logic r_adder01_sel, r_adder02_sel, r_adder03_sel; + logic r_adder04_sel, r_adder05_sel, r_adder06_sel, r_adder07_sel; + logic r_adder08_sel, r_adder09_sel, r_adder10_sel, r_adder11_sel; + logic r_adder12_sel, r_adder13_sel, r_adder14_sel, r_adder15_sel; + logic [32:0] r_in, r_ff; + + logic twos_comp_q_sel, twos_comp_b_sel; + logic [31:0] twos_comp_in, twos_comp_out; + + logic [15:1] quotient_raw; + logic [3:0] quotient_new; + logic [34:0] adder01_out; + logic [35:0] adder02_out; + logic [36:0] adder03_out; + logic [37:0] adder04_out; + logic [37:0] adder05_out; + logic [37:0] adder06_out; + logic [37:0] adder07_out; + logic [37:0] adder08_out; + logic [37:0] adder09_out; + logic [37:0] adder10_out; + logic [37:0] adder11_out; + logic [37:0] adder12_out; + logic [37:0] adder13_out; + logic [37:0] adder14_out; + logic [37:0] adder15_out; + + logic [64:0] ar_shifted; + logic [5:0] shortq; + logic [4:0] shortq_shift; + logic [4:0] shortq_decode; + logic [4:0] shortq_shift_ff; + logic shortq_enable; + logic shortq_enable_ff; + logic [32:0] shortq_dividend; + + logic by_zero_case; + logic by_zero_case_ff; + + + + rvdffe #(19) i_misc_ff (.*, .clk(clk), .en(misc_enable), .din ({valid_ff_in, control_in[2:0], by_zero_case, shortq_enable, shortq_shift[4:0], finish, count_in[6:0]}), + .dout({valid_ff, control_ff[2:0], by_zero_case_ff, shortq_enable_ff, shortq_shift_ff[4:0], finish_ff, count_ff[6:0]})); + + rvdffe #(32) i_a_ff (.*, .clk(clk), .en(a_enable), .din(a_in[31:0]), .dout(a_ff[31:0])); + rvdffe #(33) i_b_ff (.*, .clk(clk), .en(b_enable), .din(b_in[32:0]), .dout(b_ff[32:0])); + rvdffe #(33) i_r_ff (.*, .clk(clk), .en(rq_enable), .din(r_in[32:0]), .dout(r_ff[32:0])); + rvdffe #(32) i_q_ff (.*, .clk(clk), .en(rq_enable), .din(q_in[31:0]), .dout(q_ff[31:0])); + + + + + assign valid_ff_in = valid_in & ~cancel; + + assign control_in[2] = (~valid_in & control_ff[2]) | (valid_in & signed_in & dividend_in[31]); + assign control_in[1] = (~valid_in & control_ff[1]) | (valid_in & signed_in & divisor_in[31]); + assign control_in[0] = (~valid_in & control_ff[0]) | (valid_in & rem_in); + + assign dividend_sign_ff = control_ff[2]; + assign divisor_sign_ff = control_ff[1]; + assign rem_ff = control_ff[0]; + + + assign by_zero_case = valid_ff & (b_ff[31:0] == 32'b0); + + assign misc_enable = valid_in | valid_ff | cancel | running_state | finish_ff; + assign running_state = (| count_ff[6:0]) | shortq_enable_ff; + assign finish_raw = smallnum_case | + by_zero_case | + (count_ff[6:0] == 7'd32); + + + assign finish = finish_raw & ~cancel; + assign count_enable = (valid_ff | running_state) & ~finish & ~finish_ff & ~cancel & ~shortq_enable; + assign count_in[6:0] = {7{count_enable}} & (count_ff[6:0] + 7'd4 + {2'b0,shortq_shift_ff[4:0]}); + + + assign a_enable = valid_in | running_state; + assign a_shift = running_state & ~shortq_enable_ff; + + assign ar_shifted[64:0] = { {33{dividend_sign_ff}} , a_ff[31:0]} << {shortq_shift_ff[4:0]}; + + assign a_in[31:0] = ( {32{~a_shift & ~shortq_enable_ff}} & dividend_in[31:0] ) | + ( {32{ a_shift }} & {a_ff[27:0],4'b0} ) | + ( {32{ shortq_enable_ff}} & ar_shifted[31:0] ); + + + + assign b_enable = valid_in | b_twos_comp; + assign b_twos_comp = valid_ff & ~(dividend_sign_ff ^ divisor_sign_ff); + + assign b_in[32:0] = ( {33{~b_twos_comp}} & { (signed_in & divisor_in[31]),divisor_in[31:0] } ) | + ( {33{ b_twos_comp}} & {~divisor_sign_ff,twos_comp_out[31:0] } ); + + + assign rq_enable = valid_in | valid_ff | running_state; + assign r_sign_sel = valid_ff & dividend_sign_ff & ~by_zero_case; + assign r_restore_sel = running_state & (quotient_new[3:0] == 4'd00) & ~shortq_enable_ff; + assign r_adder01_sel = running_state & (quotient_new[3:0] == 4'd01) & ~shortq_enable_ff; + assign r_adder02_sel = running_state & (quotient_new[3:0] == 4'd02) & ~shortq_enable_ff; + assign r_adder03_sel = running_state & (quotient_new[3:0] == 4'd03) & ~shortq_enable_ff; + assign r_adder04_sel = running_state & (quotient_new[3:0] == 4'd04) & ~shortq_enable_ff; + assign r_adder05_sel = running_state & (quotient_new[3:0] == 4'd05) & ~shortq_enable_ff; + assign r_adder06_sel = running_state & (quotient_new[3:0] == 4'd06) & ~shortq_enable_ff; + assign r_adder07_sel = running_state & (quotient_new[3:0] == 4'd07) & ~shortq_enable_ff; + assign r_adder08_sel = running_state & (quotient_new[3:0] == 4'd08) & ~shortq_enable_ff; + assign r_adder09_sel = running_state & (quotient_new[3:0] == 4'd09) & ~shortq_enable_ff; + assign r_adder10_sel = running_state & (quotient_new[3:0] == 4'd10) & ~shortq_enable_ff; + assign r_adder11_sel = running_state & (quotient_new[3:0] == 4'd11) & ~shortq_enable_ff; + assign r_adder12_sel = running_state & (quotient_new[3:0] == 4'd12) & ~shortq_enable_ff; + assign r_adder13_sel = running_state & (quotient_new[3:0] == 4'd13) & ~shortq_enable_ff; + assign r_adder14_sel = running_state & (quotient_new[3:0] == 4'd14) & ~shortq_enable_ff; + assign r_adder15_sel = running_state & (quotient_new[3:0] == 4'd15) & ~shortq_enable_ff; + + assign r_in[32:0] = ( {33{r_sign_sel }} & {33{1'b1}} ) | + ( {33{r_restore_sel }} & {r_ff[28:0],a_ff[31:28]} ) | + ( {33{r_adder01_sel }} & adder01_out[32:0] ) | + ( {33{r_adder02_sel }} & adder02_out[32:0] ) | + ( {33{r_adder03_sel }} & adder03_out[32:0] ) | + ( {33{r_adder04_sel }} & adder04_out[32:0] ) | + ( {33{r_adder05_sel }} & adder05_out[32:0] ) | + ( {33{r_adder06_sel }} & adder06_out[32:0] ) | + ( {33{r_adder07_sel }} & adder07_out[32:0] ) | + ( {33{r_adder08_sel }} & adder08_out[32:0] ) | + ( {33{r_adder09_sel }} & adder09_out[32:0] ) | + ( {33{r_adder10_sel }} & adder10_out[32:0] ) | + ( {33{r_adder11_sel }} & adder11_out[32:0] ) | + ( {33{r_adder12_sel }} & adder12_out[32:0] ) | + ( {33{r_adder13_sel }} & adder13_out[32:0] ) | + ( {33{r_adder14_sel }} & adder14_out[32:0] ) | + ( {33{r_adder15_sel }} & adder15_out[32:0] ) | + ( {33{shortq_enable_ff}} & ar_shifted[64:32] ) | + ( {33{by_zero_case }} & {1'b0,a_ff[31:0]} ); + + + assign q_in[31:0] = ( {32{~valid_ff }} & {q_ff[27:0], quotient_new[3:0]} ) | + ( {32{ smallnum_case}} & {28'b0 , smallnum[3:0]} ) | + ( {32{ by_zero_case }} & {32{1'b1}} ); + + + assign b_ff[37:33] = {b_ff[32],b_ff[32],b_ff[32],b_ff[32],b_ff[32]}; + + + assign adder01_out[34:0] = { r_ff[30:0],a_ff[31:28]} + b_ff[34:0]; + assign adder02_out[35:0] = { r_ff[31:0],a_ff[31:28]} + {b_ff[34:0],1'b0}; + assign adder03_out[36:0] = { r_ff[32:0],a_ff[31:28]} + {b_ff[35:0],1'b0} + b_ff[36:0]; + assign adder04_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[35:0],2'b0}; + assign adder05_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[35:0],2'b0} + b_ff[37:0]; + assign adder06_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[35:0],2'b0} + {b_ff[36:0],1'b0}; + assign adder07_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[35:0],2'b0} + {b_ff[36:0],1'b0} + b_ff[37:0]; + assign adder08_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[34:0],3'b0}; + assign adder09_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[34:0],3'b0} + b_ff[37:0]; + assign adder10_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[34:0],3'b0} + {b_ff[36:0],1'b0}; + assign adder11_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[34:0],3'b0} + {b_ff[36:0],1'b0} + b_ff[37:0]; + assign adder12_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[34:0],3'b0} + {b_ff[35:0],2'b0}; + assign adder13_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[34:0],3'b0} + {b_ff[35:0],2'b0} + b_ff[37:0]; + assign adder14_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[34:0],3'b0} + {b_ff[35:0],2'b0} + {b_ff[36:0],1'b0}; + assign adder15_out[37:0] = {r_ff[32],r_ff[32:0],a_ff[31:28]} + {b_ff[34:0],3'b0} + {b_ff[35:0],2'b0} + {b_ff[36:0],1'b0} + b_ff[37:0]; + + assign quotient_raw[01] = (~adder01_out[34] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder01_out[34:0] == 35'b0) ); + assign quotient_raw[02] = (~adder02_out[35] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder02_out[35:0] == 36'b0) ); + assign quotient_raw[03] = (~adder03_out[36] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder03_out[36:0] == 37'b0) ); + assign quotient_raw[04] = (~adder04_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder04_out[37:0] == 38'b0) ); + assign quotient_raw[05] = (~adder05_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder05_out[37:0] == 38'b0) ); + assign quotient_raw[06] = (~adder06_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder06_out[37:0] == 38'b0) ); + assign quotient_raw[07] = (~adder07_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder07_out[37:0] == 38'b0) ); + assign quotient_raw[08] = (~adder08_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder08_out[37:0] == 38'b0) ); + assign quotient_raw[09] = (~adder09_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder09_out[37:0] == 38'b0) ); + assign quotient_raw[10] = (~adder10_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder10_out[37:0] == 38'b0) ); + assign quotient_raw[11] = (~adder11_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder11_out[37:0] == 38'b0) ); + assign quotient_raw[12] = (~adder12_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder12_out[37:0] == 38'b0) ); + assign quotient_raw[13] = (~adder13_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder13_out[37:0] == 38'b0) ); + assign quotient_raw[14] = (~adder14_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder14_out[37:0] == 38'b0) ); + assign quotient_raw[15] = (~adder15_out[37] ^ dividend_sign_ff) | ( (a_ff[27:0] == 28'b0) & (adder15_out[37:0] == 38'b0) ); + + + assign quotient_new[0] = ( quotient_raw[15:01] == 15'b000_0000_0000_0001 ) | // 1 + ( quotient_raw[15:03] == 13'b000_0000_0000_01 ) | // 3 + ( quotient_raw[15:05] == 11'b000_0000_0001 ) | // 5 + ( quotient_raw[15:07] == 9'b000_0000_01 ) | // 7 + ( quotient_raw[15:09] == 7'b000_0001 ) | // 9 + ( quotient_raw[15:11] == 5'b000_01 ) | // 11 + ( quotient_raw[15:13] == 3'b001 ) | // 13 + ( quotient_raw[ 15] == 1'b1 ); // 15 + + assign quotient_new[1] = ( quotient_raw[15:02] == 14'b000_0000_0000_001 ) | // 2 + ( quotient_raw[15:03] == 13'b000_0000_0000_01 ) | // 3 + ( quotient_raw[15:06] == 10'b000_0000_001 ) | // 6 + ( quotient_raw[15:07] == 9'b000_0000_01 ) | // 7 + ( quotient_raw[15:10] == 6'b000_001 ) | // 10 + ( quotient_raw[15:11] == 5'b000_01 ) | // 11 + ( quotient_raw[15:14] == 2'b01 ) | // 14 + ( quotient_raw[ 15] == 1'b1 ); // 15 + + assign quotient_new[2] = ( quotient_raw[15:04] == 12'b000_0000_0000_1 ) | // 4 + ( quotient_raw[15:05] == 11'b000_0000_0001 ) | // 5 + ( quotient_raw[15:06] == 10'b000_0000_001 ) | // 6 + ( quotient_raw[15:07] == 9'b000_0000_01 ) | // 7 + ( quotient_raw[15:12] == 4'b000_1 ) | // 12 + ( quotient_raw[15:13] == 3'b001 ) | // 13 + ( quotient_raw[15:14] == 2'b01 ) | // 14 + ( quotient_raw[ 15] == 1'b1 ); // 15 + + assign quotient_new[3] = ( quotient_raw[15:08] == 8'b000_0000_1 ) | // 8 + ( quotient_raw[15:09] == 7'b000_0001 ) | // 9 + ( quotient_raw[15:10] == 6'b000_001 ) | // 10 + ( quotient_raw[15:11] == 5'b000_01 ) | // 11 + ( quotient_raw[15:12] == 4'b000_1 ) | // 12 + ( quotient_raw[15:13] == 3'b001 ) | // 13 + ( quotient_raw[15:14] == 2'b01 ) | // 14 + ( quotient_raw[ 15] == 1'b1 ); // 15 + + + assign twos_comp_b_sel = valid_ff & ~(dividend_sign_ff ^ divisor_sign_ff); + assign twos_comp_q_sel = ~valid_ff & ~rem_ff & (dividend_sign_ff ^ divisor_sign_ff) & ~by_zero_case_ff; + + assign twos_comp_in[31:0] = ( {32{twos_comp_q_sel}} & q_ff[31:0] ) | + ( {32{twos_comp_b_sel}} & b_ff[31:0] ); + + rvtwoscomp #(32) i_twos_comp (.din(twos_comp_in[31:0]), .dout(twos_comp_out[31:0])); + + + + assign valid_out = finish_ff & ~cancel; + + assign data_out[31:0] = ( {32{~rem_ff & ~twos_comp_q_sel}} & q_ff[31:0] ) | + ( {32{ rem_ff }} & r_ff[31:0] ) | + ( {32{ twos_comp_q_sel}} & twos_comp_out[31:0] ); + + + + + // *** *** *** START : SMALLNUM {{ + + assign smallnum_case = ( (a_ff[31:4] == 28'b0) & (b_ff[31:4] == 28'b0) & ~by_zero_case & ~rem_ff & valid_ff & ~cancel) | + ( (a_ff[31:0] == 32'b0) & ~by_zero_case & ~rem_ff & valid_ff & ~cancel); + + assign smallnum[3] = ( a_ff[3] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ); + + assign smallnum[2] = ( a_ff[3] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[2] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & ~b_ff[2] ); + + assign smallnum[1] = ( a_ff[2] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[1] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & ~b_ff[3] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & ~a_ff[2] & ~b_ff[3] & ~b_ff[2] & b_ff[1] & b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & a_ff[2] & ~b_ff[3] & b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[1] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[2] ); + + assign smallnum[0] = ( a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & a_ff[0] & ~b_ff[3] & b_ff[1] & b_ff[0]) | + ( a_ff[2] & ~b_ff[3] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[1] & ~b_ff[3] & ~b_ff[2] & ~b_ff[0]) | + ( a_ff[0] & ~b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + (~a_ff[3] & a_ff[2] & ~a_ff[1] & ~b_ff[3] & ~b_ff[2] & b_ff[1] & b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & ~b_ff[2] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & ~a_ff[2] & ~b_ff[3] & b_ff[2] & b_ff[1] ) | + (~a_ff[3] & a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[2] & ~b_ff[1] ) | + (~a_ff[3] & a_ff[2] & a_ff[0] & ~b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & ~a_ff[1] & ~b_ff[3] & b_ff[2] & b_ff[0]) | + ( ~a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & ~b_ff[1] & ~b_ff[0]) | + ( a_ff[3] & a_ff[1] & ~b_ff[2] & ~b_ff[0]) | + (~a_ff[3] & a_ff[2] & a_ff[1] & a_ff[0] & ~b_ff[3] & b_ff[2] ) | + ( a_ff[3] & a_ff[2] & b_ff[3] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[1] & b_ff[3] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[0] & ~b_ff[2] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[1] & ~b_ff[3] & b_ff[2] & b_ff[1] & b_ff[0]) | + ( a_ff[3] & a_ff[2] & a_ff[1] & b_ff[3] & ~b_ff[0]) | + ( a_ff[3] & a_ff[2] & a_ff[1] & b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & a_ff[2] & a_ff[0] & b_ff[3] & ~b_ff[1] ) | + ( a_ff[3] & ~a_ff[2] & a_ff[1] & ~b_ff[3] & b_ff[1] ) | + ( a_ff[3] & a_ff[1] & a_ff[0] & ~b_ff[2] ) | + ( a_ff[3] & a_ff[2] & a_ff[1] & a_ff[0] & b_ff[3] ); + + // *** *** *** END : SMALLNUM }} + + + + + // *** *** *** Start : Short Q {{ + + assign shortq_dividend[32:0] = {dividend_sign_ff,a_ff[31:0]}; + + + logic [5:0] dw_a_enc; + logic [5:0] dw_b_enc; + logic [6:0] dw_shortq_raw; + + + + el2_exu_div_cls i_a_cls ( + .operand ( shortq_dividend[32:0] ), + .cls ( dw_a_enc[4:0] )); + + el2_exu_div_cls i_b_cls ( + .operand ( b_ff[32:0] ), + .cls ( dw_b_enc[4:0] )); + + assign dw_a_enc[5] = 1'b0; + assign dw_b_enc[5] = 1'b0; + + + assign dw_shortq_raw[6:0] = {1'b0,dw_b_enc[5:0]} - {1'b0,dw_a_enc[5:0]} + 7'd1; + assign shortq[5:0] = dw_shortq_raw[6] ? 6'd0 : dw_shortq_raw[5:0]; + + assign shortq_enable = valid_ff & ~shortq[5] & ~(shortq[4:2] == 3'b111) & ~cancel; + + assign shortq_decode[4:0] = ( {5{shortq[4:0] == 5'd31}} & 5'd00) | + ( {5{shortq[4:0] == 5'd30}} & 5'd00) | + ( {5{shortq[4:0] == 5'd29}} & 5'd00) | + ( {5{shortq[4:0] == 5'd28}} & 5'd00) | + ( {5{shortq[4:0] == 5'd27}} & 5'd04) | + ( {5{shortq[4:0] == 5'd26}} & 5'd04) | + ( {5{shortq[4:0] == 5'd25}} & 5'd04) | + ( {5{shortq[4:0] == 5'd24}} & 5'd04) | + ( {5{shortq[4:0] == 5'd23}} & 5'd08) | + ( {5{shortq[4:0] == 5'd22}} & 5'd08) | + ( {5{shortq[4:0] == 5'd21}} & 5'd08) | + ( {5{shortq[4:0] == 5'd20}} & 5'd08) | + ( {5{shortq[4:0] == 5'd19}} & 5'd12) | + ( {5{shortq[4:0] == 5'd18}} & 5'd12) | + ( {5{shortq[4:0] == 5'd17}} & 5'd12) | + ( {5{shortq[4:0] == 5'd16}} & 5'd12) | + ( {5{shortq[4:0] == 5'd15}} & 5'd16) | + ( {5{shortq[4:0] == 5'd14}} & 5'd16) | + ( {5{shortq[4:0] == 5'd13}} & 5'd16) | + ( {5{shortq[4:0] == 5'd12}} & 5'd16) | + ( {5{shortq[4:0] == 5'd11}} & 5'd20) | + ( {5{shortq[4:0] == 5'd10}} & 5'd20) | + ( {5{shortq[4:0] == 5'd09}} & 5'd20) | + ( {5{shortq[4:0] == 5'd08}} & 5'd20) | + ( {5{shortq[4:0] == 5'd07}} & 5'd24) | + ( {5{shortq[4:0] == 5'd06}} & 5'd24) | + ( {5{shortq[4:0] == 5'd05}} & 5'd24) | + ( {5{shortq[4:0] == 5'd04}} & 5'd24) | + ( {5{shortq[4:0] == 5'd03}} & 5'd28) | + ( {5{shortq[4:0] == 5'd02}} & 5'd28) | + ( {5{shortq[4:0] == 5'd01}} & 5'd28) | + ( {5{shortq[4:0] == 5'd00}} & 5'd28); + + + assign shortq_shift[4:0] = ~shortq_enable ? 5'd0 : shortq_decode[4:0]; + + + // *** *** *** End : Short Q }} + + + + + +endmodule // el2_exu_div_new_4bit_fullshortq + + + + + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +module el2_exu_div_cls + ( + input logic [32:0] operand, + + output logic [4:0] cls // Count leading sign bits - "n" format ignoring [32] + ); + + + logic [4:0] cls_zeros; + logic [4:0] cls_ones; + + +assign cls_zeros[4:0] = ({5{operand[31] == { 1'b1} }} & 5'd00) | + ({5{operand[31:30] == {{ 1{1'b0}},1'b1} }} & 5'd01) | + ({5{operand[31:29] == {{ 2{1'b0}},1'b1} }} & 5'd02) | + ({5{operand[31:28] == {{ 3{1'b0}},1'b1} }} & 5'd03) | + ({5{operand[31:27] == {{ 4{1'b0}},1'b1} }} & 5'd04) | + ({5{operand[31:26] == {{ 5{1'b0}},1'b1} }} & 5'd05) | + ({5{operand[31:25] == {{ 6{1'b0}},1'b1} }} & 5'd06) | + ({5{operand[31:24] == {{ 7{1'b0}},1'b1} }} & 5'd07) | + ({5{operand[31:23] == {{ 8{1'b0}},1'b1} }} & 5'd08) | + ({5{operand[31:22] == {{ 9{1'b0}},1'b1} }} & 5'd09) | + ({5{operand[31:21] == {{10{1'b0}},1'b1} }} & 5'd10) | + ({5{operand[31:20] == {{11{1'b0}},1'b1} }} & 5'd11) | + ({5{operand[31:19] == {{12{1'b0}},1'b1} }} & 5'd12) | + ({5{operand[31:18] == {{13{1'b0}},1'b1} }} & 5'd13) | + ({5{operand[31:17] == {{14{1'b0}},1'b1} }} & 5'd14) | + ({5{operand[31:16] == {{15{1'b0}},1'b1} }} & 5'd15) | + ({5{operand[31:15] == {{16{1'b0}},1'b1} }} & 5'd16) | + ({5{operand[31:14] == {{17{1'b0}},1'b1} }} & 5'd17) | + ({5{operand[31:13] == {{18{1'b0}},1'b1} }} & 5'd18) | + ({5{operand[31:12] == {{19{1'b0}},1'b1} }} & 5'd19) | + ({5{operand[31:11] == {{20{1'b0}},1'b1} }} & 5'd20) | + ({5{operand[31:10] == {{21{1'b0}},1'b1} }} & 5'd21) | + ({5{operand[31:09] == {{22{1'b0}},1'b1} }} & 5'd22) | + ({5{operand[31:08] == {{23{1'b0}},1'b1} }} & 5'd23) | + ({5{operand[31:07] == {{24{1'b0}},1'b1} }} & 5'd24) | + ({5{operand[31:06] == {{25{1'b0}},1'b1} }} & 5'd25) | + ({5{operand[31:05] == {{26{1'b0}},1'b1} }} & 5'd26) | + ({5{operand[31:04] == {{27{1'b0}},1'b1} }} & 5'd27) | + ({5{operand[31:03] == {{28{1'b0}},1'b1} }} & 5'd28) | + ({5{operand[31:02] == {{29{1'b0}},1'b1} }} & 5'd29) | + ({5{operand[31:01] == {{30{1'b0}},1'b1} }} & 5'd30) | + ({5{operand[31:00] == {{31{1'b0}},1'b1} }} & 5'd31) | + ({5{operand[31:00] == {{32{1'b0}} } }} & 5'd00); // Don't care case as it will be handled as special case + + +assign cls_ones[4:0] = ({5{operand[31:30] == {{ 1{1'b1}},1'b0} }} & 5'd00) | + ({5{operand[31:29] == {{ 2{1'b1}},1'b0} }} & 5'd01) | + ({5{operand[31:28] == {{ 3{1'b1}},1'b0} }} & 5'd02) | + ({5{operand[31:27] == {{ 4{1'b1}},1'b0} }} & 5'd03) | + ({5{operand[31:26] == {{ 5{1'b1}},1'b0} }} & 5'd04) | + ({5{operand[31:25] == {{ 6{1'b1}},1'b0} }} & 5'd05) | + ({5{operand[31:24] == {{ 7{1'b1}},1'b0} }} & 5'd06) | + ({5{operand[31:23] == {{ 8{1'b1}},1'b0} }} & 5'd07) | + ({5{operand[31:22] == {{ 9{1'b1}},1'b0} }} & 5'd08) | + ({5{operand[31:21] == {{10{1'b1}},1'b0} }} & 5'd09) | + ({5{operand[31:20] == {{11{1'b1}},1'b0} }} & 5'd10) | + ({5{operand[31:19] == {{12{1'b1}},1'b0} }} & 5'd11) | + ({5{operand[31:18] == {{13{1'b1}},1'b0} }} & 5'd12) | + ({5{operand[31:17] == {{14{1'b1}},1'b0} }} & 5'd13) | + ({5{operand[31:16] == {{15{1'b1}},1'b0} }} & 5'd14) | + ({5{operand[31:15] == {{16{1'b1}},1'b0} }} & 5'd15) | + ({5{operand[31:14] == {{17{1'b1}},1'b0} }} & 5'd16) | + ({5{operand[31:13] == {{18{1'b1}},1'b0} }} & 5'd17) | + ({5{operand[31:12] == {{19{1'b1}},1'b0} }} & 5'd18) | + ({5{operand[31:11] == {{20{1'b1}},1'b0} }} & 5'd19) | + ({5{operand[31:10] == {{21{1'b1}},1'b0} }} & 5'd20) | + ({5{operand[31:09] == {{22{1'b1}},1'b0} }} & 5'd21) | + ({5{operand[31:08] == {{23{1'b1}},1'b0} }} & 5'd22) | + ({5{operand[31:07] == {{24{1'b1}},1'b0} }} & 5'd23) | + ({5{operand[31:06] == {{25{1'b1}},1'b0} }} & 5'd24) | + ({5{operand[31:05] == {{26{1'b1}},1'b0} }} & 5'd25) | + ({5{operand[31:04] == {{27{1'b1}},1'b0} }} & 5'd26) | + ({5{operand[31:03] == {{28{1'b1}},1'b0} }} & 5'd27) | + ({5{operand[31:02] == {{29{1'b1}},1'b0} }} & 5'd28) | + ({5{operand[31:01] == {{30{1'b1}},1'b0} }} & 5'd29) | + ({5{operand[31:00] == {{31{1'b1}},1'b0} }} & 5'd30) | + ({5{operand[31:00] == {{32{1'b1}} } }} & 5'd31); + + +assign cls[4:0] = operand[32] ? cls_ones[4:0] : cls_zeros[4:0]; + +endmodule // el2_exu_div_cls diff --git a/design/exu/el2_exu_mul_ctl.sv b/design/exu/el2_exu_mul_ctl.sv index b9b68ba..9b6dae7 100644 --- a/design/exu/el2_exu_mul_ctl.sv +++ b/design/exu/el2_exu_mul_ctl.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ import el2_pkg::*; logic mul_x_enable; + logic bit_x_enable; logic signed [32:0] rs1_ext_in; logic signed [32:0] rs2_ext_in; logic [65:0] prod_x; @@ -42,8 +43,116 @@ import el2_pkg::*; + // *** Start - BitManip *** + + logic bitmanip_sel_d; + logic bitmanip_sel_x; + logic [31:0] bitmanip_d; + logic [31:0] bitmanip_x; + + + + // ZBE + logic ap_bext; + logic ap_bdep; + + // ZBC + logic ap_clmul; + logic ap_clmulh; + logic ap_clmulr; + + // ZBP + logic ap_grev; + logic ap_gorc; + logic ap_shfl; + logic ap_unshfl; + + // ZBR + logic ap_crc32_b; + logic ap_crc32_h; + logic ap_crc32_w; + logic ap_crc32c_b; + logic ap_crc32c_h; + logic ap_crc32c_w; + + // ZBF + logic ap_bfp; + + + if (pt.BITMANIP_ZBE == 1) + begin + assign ap_bext = mul_p.bext; + assign ap_bdep = mul_p.bdep; + end + else + begin + assign ap_bext = 1'b0; + assign ap_bdep = 1'b0; + end + + if (pt.BITMANIP_ZBC == 1) + begin + assign ap_clmul = mul_p.clmul; + assign ap_clmulh = mul_p.clmulh; + assign ap_clmulr = mul_p.clmulr; + end + else + begin + assign ap_clmul = 1'b0; + assign ap_clmulh = 1'b0; + assign ap_clmulr = 1'b0; + end + + if (pt.BITMANIP_ZBP == 1) + begin + assign ap_grev = mul_p.grev; + assign ap_gorc = mul_p.gorc; + assign ap_shfl = mul_p.shfl; + assign ap_unshfl = mul_p.unshfl; + end + else + begin + assign ap_grev = 1'b0; + assign ap_gorc = 1'b0; + assign ap_shfl = 1'b0; + assign ap_unshfl = 1'b0; + end + + if (pt.BITMANIP_ZBR == 1) + begin + assign ap_crc32_b = mul_p.crc32_b; + assign ap_crc32_h = mul_p.crc32_h; + assign ap_crc32_w = mul_p.crc32_w; + assign ap_crc32c_b = mul_p.crc32c_b; + assign ap_crc32c_h = mul_p.crc32c_h; + assign ap_crc32c_w = mul_p.crc32c_w; + end + else + begin + assign ap_crc32_b = 1'b0; + assign ap_crc32_h = 1'b0; + assign ap_crc32_w = 1'b0; + assign ap_crc32c_b = 1'b0; + assign ap_crc32c_h = 1'b0; + assign ap_crc32c_w = 1'b0; + end + + if (pt.BITMANIP_ZBF == 1) + begin + assign ap_bfp = mul_p.bfp; + end + else + begin + assign ap_bfp = 1'b0; + end + + + // *** End - BitManip *** + + assign mul_x_enable = mul_p.valid; + assign bit_x_enable = mul_p.valid; assign rs1_ext_in[32] = mul_p.rs1_sign & rs1_in[31]; assign rs2_ext_in[32] = mul_p.rs2_sign & rs2_in[31]; @@ -59,17 +168,460 @@ import el2_pkg::*; logic signed [32:0] rs1_x; logic signed [32:0] rs2_x; - rvdffe #(34) i_a_x_ff (.*, .din({mul_p.low,rs1_ext_in[32:0]}), .dout({low_x,rs1_x[32:0]}), .en(mul_x_enable)); - rvdffe #(33) i_b_x_ff (.*, .din( rs2_ext_in[32:0] ), .dout( rs2_x[32:0] ), .en(mul_x_enable)); + rvdffe #(34) i_a_x_ff (.*, .clk(clk), .din({mul_p.low,rs1_ext_in[32:0]}), .dout({low_x,rs1_x[32:0]}), .en(mul_x_enable)); + rvdffe #(33) i_b_x_ff (.*, .clk(clk), .din( rs2_ext_in[32:0] ), .dout( rs2_x[32:0] ), .en(mul_x_enable)); assign prod_x[65:0] = rs1_x * rs2_x; - assign result_x[31:0] = ( {32{~low_x}} & prod_x[63:32] ) | - ( {32{ low_x}} & prod_x[31:0] ); + // * * * * * * * * * * * * * * * * * * BitManip : BEXT, BDEP * * * * * * * * * * * * * * * * * * + // *** BEXT == "gather" *** + + logic [31:0] bext_d; + logic bext_test_bit_d; + integer bext_i, bext_j; + + + always_comb + begin + + bext_j = 0; + bext_test_bit_d = 1'b0; + bext_d[31:0] = 32'b0; + + for (bext_i=0; bext_i<32; bext_i++) + begin + bext_test_bit_d = rs2_in[bext_i]; + if (bext_test_bit_d) + begin + bext_d[bext_j] = rs1_in[bext_i]; + bext_j = bext_j + 1; + end // IF bext_test_bit + end // FOR bext_i + end // ALWAYS_COMB + + + + // *** BDEP == "scatter" *** + + logic [31:0] bdep_d; + logic bdep_test_bit_d; + integer bdep_i, bdep_j; + + + always_comb + begin + + bdep_j = 0; + bdep_test_bit_d = 1'b0; + bdep_d[31:0] = 32'b0; + + for (bdep_i=0; bdep_i<32; bdep_i++) + begin + bdep_test_bit_d = rs2_in[bdep_i]; + if (bdep_test_bit_d) + begin + bdep_d[bdep_i] = rs1_in[bdep_j]; + bdep_j = bdep_j + 1; + end // IF bdep_test_bit + end // FOR bdep_i + end // ALWAYS_COMB + + + + + // * * * * * * * * * * * * * * * * * * BitManip : CLMUL, CLMULH, CLMULR * * * * * * * * * * * * * + + logic [62:0] clmul_raw_d; + + + assign clmul_raw_d[62:0] = ( {63{rs2_in[00]}} & {31'b0,rs1_in[31:0] } ) ^ + ( {63{rs2_in[01]}} & {30'b0,rs1_in[31:0], 1'b0} ) ^ + ( {63{rs2_in[02]}} & {29'b0,rs1_in[31:0], 2'b0} ) ^ + ( {63{rs2_in[03]}} & {28'b0,rs1_in[31:0], 3'b0} ) ^ + ( {63{rs2_in[04]}} & {27'b0,rs1_in[31:0], 4'b0} ) ^ + ( {63{rs2_in[05]}} & {26'b0,rs1_in[31:0], 5'b0} ) ^ + ( {63{rs2_in[06]}} & {25'b0,rs1_in[31:0], 6'b0} ) ^ + ( {63{rs2_in[07]}} & {24'b0,rs1_in[31:0], 7'b0} ) ^ + ( {63{rs2_in[08]}} & {23'b0,rs1_in[31:0], 8'b0} ) ^ + ( {63{rs2_in[09]}} & {22'b0,rs1_in[31:0], 9'b0} ) ^ + ( {63{rs2_in[10]}} & {21'b0,rs1_in[31:0],10'b0} ) ^ + ( {63{rs2_in[11]}} & {20'b0,rs1_in[31:0],11'b0} ) ^ + ( {63{rs2_in[12]}} & {19'b0,rs1_in[31:0],12'b0} ) ^ + ( {63{rs2_in[13]}} & {18'b0,rs1_in[31:0],13'b0} ) ^ + ( {63{rs2_in[14]}} & {17'b0,rs1_in[31:0],14'b0} ) ^ + ( {63{rs2_in[15]}} & {16'b0,rs1_in[31:0],15'b0} ) ^ + ( {63{rs2_in[16]}} & {15'b0,rs1_in[31:0],16'b0} ) ^ + ( {63{rs2_in[17]}} & {14'b0,rs1_in[31:0],17'b0} ) ^ + ( {63{rs2_in[18]}} & {13'b0,rs1_in[31:0],18'b0} ) ^ + ( {63{rs2_in[19]}} & {12'b0,rs1_in[31:0],19'b0} ) ^ + ( {63{rs2_in[20]}} & {11'b0,rs1_in[31:0],20'b0} ) ^ + ( {63{rs2_in[21]}} & {10'b0,rs1_in[31:0],21'b0} ) ^ + ( {63{rs2_in[22]}} & { 9'b0,rs1_in[31:0],22'b0} ) ^ + ( {63{rs2_in[23]}} & { 8'b0,rs1_in[31:0],23'b0} ) ^ + ( {63{rs2_in[24]}} & { 7'b0,rs1_in[31:0],24'b0} ) ^ + ( {63{rs2_in[25]}} & { 6'b0,rs1_in[31:0],25'b0} ) ^ + ( {63{rs2_in[26]}} & { 5'b0,rs1_in[31:0],26'b0} ) ^ + ( {63{rs2_in[27]}} & { 4'b0,rs1_in[31:0],27'b0} ) ^ + ( {63{rs2_in[28]}} & { 3'b0,rs1_in[31:0],28'b0} ) ^ + ( {63{rs2_in[29]}} & { 2'b0,rs1_in[31:0],29'b0} ) ^ + ( {63{rs2_in[30]}} & { 1'b0,rs1_in[31:0],30'b0} ) ^ + ( {63{rs2_in[31]}} & { rs1_in[31:0],31'b0} ); + + + + + // * * * * * * * * * * * * * * * * * * BitManip : GREV * * * * * * * * * * * * * * * * * * + + // uint32_t grev32(uint32_t rs1, uint32_t rs2) + // { + // uint32_t x = rs1; + // int shamt = rs2 & 31; + // + // if (shamt & 1) x = ( (x & 0x55555555) << 1) | ( (x & 0xAAAAAAAA) >> 1); + // if (shamt & 2) x = ( (x & 0x33333333) << 2) | ( (x & 0xCCCCCCCC) >> 2); + // if (shamt & 4) x = ( (x & 0x0F0F0F0F) << 4) | ( (x & 0xF0F0F0F0) >> 4); + // if (shamt & 8) x = ( (x & 0x00FF00FF) << 8) | ( (x & 0xFF00FF00) >> 8); + // if (shamt & 16) x = ( (x & 0x0000FFFF) << 16) | ( (x & 0xFFFF0000) >> 16); + // + // return x; + // } + + + logic [31:0] grev1_d; + logic [31:0] grev2_d; + logic [31:0] grev4_d; + logic [31:0] grev8_d; + logic [31:0] grev_d; + + + assign grev1_d[31:0] = (rs2_in[0]) ? {rs1_in[30],rs1_in[31],rs1_in[28],rs1_in[29],rs1_in[26],rs1_in[27],rs1_in[24],rs1_in[25], + rs1_in[22],rs1_in[23],rs1_in[20],rs1_in[21],rs1_in[18],rs1_in[19],rs1_in[16],rs1_in[17], + rs1_in[14],rs1_in[15],rs1_in[12],rs1_in[13],rs1_in[10],rs1_in[11],rs1_in[08],rs1_in[09], + rs1_in[06],rs1_in[07],rs1_in[04],rs1_in[05],rs1_in[02],rs1_in[03],rs1_in[00],rs1_in[01]} : rs1_in[31:0]; + + assign grev2_d[31:0] = (rs2_in[1]) ? {grev1_d[29:28],grev1_d[31:30],grev1_d[25:24],grev1_d[27:26], + grev1_d[21:20],grev1_d[23:22],grev1_d[17:16],grev1_d[19:18], + grev1_d[13:12],grev1_d[15:14],grev1_d[09:08],grev1_d[11:10], + grev1_d[05:04],grev1_d[07:06],grev1_d[01:00],grev1_d[03:02]} : grev1_d[31:0]; + + assign grev4_d[31:0] = (rs2_in[2]) ? {grev2_d[27:24],grev2_d[31:28],grev2_d[19:16],grev2_d[23:20], + grev2_d[11:08],grev2_d[15:12],grev2_d[03:00],grev2_d[07:04]} : grev2_d[31:0]; + + assign grev8_d[31:0] = (rs2_in[3]) ? {grev4_d[23:16],grev4_d[31:24],grev4_d[07:00],grev4_d[15:08]} : grev4_d[31:0]; + + assign grev_d[31:0] = (rs2_in[4]) ? {grev8_d[15:00],grev8_d[31:16]} : grev8_d[31:0]; + + + + + // * * * * * * * * * * * * * * * * * * BitManip : GORC * * * * * * * * * * * * * * * * * * + + // uint32_t gorc32(uint32_t rs1, uint32_t rs2) + // { + // uint32_t x = rs1; + // int shamt = rs2 & 31; + // + // if (shamt & 1) x |= ( (x & 0x55555555) << 1) | ( (x & 0xAAAAAAAA) >> 1); + // if (shamt & 2) x |= ( (x & 0x33333333) << 2) | ( (x & 0xCCCCCCCC) >> 2); + // if (shamt & 4) x |= ( (x & 0x0F0F0F0F) << 4) | ( (x & 0xF0F0F0F0) >> 4); + // if (shamt & 8) x |= ( (x & 0x00FF00FF) << 8) | ( (x & 0xFF00FF00) >> 8); + // if (shamt & 16) x |= ( (x & 0x0000FFFF) << 16) | ( (x & 0xFFFF0000) >> 16); + // + // return x; + // } + + + logic [31:0] gorc1_d; + logic [31:0] gorc2_d; + logic [31:0] gorc4_d; + logic [31:0] gorc8_d; + logic [31:0] gorc_d; + + + assign gorc1_d[31:0] = ( {32{rs2_in[0]}} & {rs1_in[30],rs1_in[31],rs1_in[28],rs1_in[29],rs1_in[26],rs1_in[27],rs1_in[24],rs1_in[25], + rs1_in[22],rs1_in[23],rs1_in[20],rs1_in[21],rs1_in[18],rs1_in[19],rs1_in[16],rs1_in[17], + rs1_in[14],rs1_in[15],rs1_in[12],rs1_in[13],rs1_in[10],rs1_in[11],rs1_in[08],rs1_in[09], + rs1_in[06],rs1_in[07],rs1_in[04],rs1_in[05],rs1_in[02],rs1_in[03],rs1_in[00],rs1_in[01]} ) | rs1_in[31:0]; + + assign gorc2_d[31:0] = ( {32{rs2_in[1]}} & {gorc1_d[29:28],gorc1_d[31:30],gorc1_d[25:24],gorc1_d[27:26], + gorc1_d[21:20],gorc1_d[23:22],gorc1_d[17:16],gorc1_d[19:18], + gorc1_d[13:12],gorc1_d[15:14],gorc1_d[09:08],gorc1_d[11:10], + gorc1_d[05:04],gorc1_d[07:06],gorc1_d[01:00],gorc1_d[03:02]} ) | gorc1_d[31:0]; + + assign gorc4_d[31:0] = ( {32{rs2_in[2]}} & {gorc2_d[27:24],gorc2_d[31:28],gorc2_d[19:16],gorc2_d[23:20], + gorc2_d[11:08],gorc2_d[15:12],gorc2_d[03:00],gorc2_d[07:04]} ) | gorc2_d[31:0]; + + assign gorc8_d[31:0] = ( {32{rs2_in[3]}} & {gorc4_d[23:16],gorc4_d[31:24],gorc4_d[07:00],gorc4_d[15:08]} ) | gorc4_d[31:0]; + + assign gorc_d[31:0] = ( {32{rs2_in[4]}} & {gorc8_d[15:00],gorc8_d[31:16]} ) | gorc8_d[31:0]; + + + + + // * * * * * * * * * * * * * * * * * * BitManip : SHFL, UNSHLF * * * * * * * * * * * * * * * * * * + + // uint32_t shuffle32_stage (uint32_t src, uint32_t maskL, uint32_t maskR, int N) + // { + // uint32_t x = src & ~(maskL | maskR); + // x |= ((src << N) & maskL) | ((src >> N) & maskR); + // return x; + // } + // + // + // + // uint32_t shfl32(uint32_t rs1, uint32_t rs2) + // { + // uint32_t x = rs1; + // int shamt = rs2 & 15 + // + // if (shamt & 8) x = shuffle32_stage(x, 0x00ff0000, 0x0000ff00, 8); + // if (shamt & 4) x = shuffle32_stage(x, 0x0f000f00, 0x00f000f0, 4); + // if (shamt & 2) x = shuffle32_stage(x, 0x30303030, 0xc0c0c0c0, 2); + // if (shamt & 1) x = shuffle32_stage(x, 0x44444444, 0x22222222, 1); + // + // return x; + // } + + + logic [31:0] shfl8_d; + logic [31:0] shfl4_d; + logic [31:0] shfl2_d; + logic [31:0] shfl_d; + + + + assign shfl8_d[31:0] = (rs2_in[3]) ? {rs1_in[31:24],rs1_in[15:08],rs1_in[23:16],rs1_in[07:00]} : rs1_in[31:0]; + + assign shfl4_d[31:0] = (rs2_in[2]) ? {shfl8_d[31:28],shfl8_d[23:20],shfl8_d[27:24],shfl8_d[19:16], + shfl8_d[15:12],shfl8_d[07:04],shfl8_d[11:08],shfl8_d[03:00]} : shfl8_d[31:0]; + + assign shfl2_d[31:0] = (rs2_in[1]) ? {shfl4_d[31:30],shfl4_d[27:26],shfl4_d[29:28],shfl4_d[25:24], + shfl4_d[23:22],shfl4_d[19:18],shfl4_d[21:20],shfl4_d[17:16], + shfl4_d[15:14],shfl4_d[11:10],shfl4_d[13:12],shfl4_d[09:08], + shfl4_d[07:06],shfl4_d[03:02],shfl4_d[05:04],shfl4_d[01:00]} : shfl4_d[31:0]; + + assign shfl_d[31:0] = (rs2_in[0]) ? {shfl2_d[31],shfl2_d[29],shfl2_d[30],shfl2_d[28],shfl2_d[27],shfl2_d[25],shfl2_d[26],shfl2_d[24], + shfl2_d[23],shfl2_d[21],shfl2_d[22],shfl2_d[20],shfl2_d[19],shfl2_d[17],shfl2_d[18],shfl2_d[16], + shfl2_d[15],shfl2_d[13],shfl2_d[14],shfl2_d[12],shfl2_d[11],shfl2_d[09],shfl2_d[10],shfl2_d[08], + shfl2_d[07],shfl2_d[05],shfl2_d[06],shfl2_d[04],shfl2_d[03],shfl2_d[01],shfl2_d[02],shfl2_d[00]} : shfl2_d[31:0]; + + + + + // uint32_t unshfl32(uint32_t rs1, uint32_t rs2) + // { + // uint32_t x = rs1; + // int shamt = rs2 & 15 + // + // if (shamt & 1) x = shuffle32_stage(x, 0x44444444, 0x22222222, 1); + // if (shamt & 2) x = shuffle32_stage(x, 0x30303030, 0xc0c0c0c0, 2); + // if (shamt & 4) x = shuffle32_stage(x, 0x0f000f00, 0x00f000f0, 4); + // if (shamt & 8) x = shuffle32_stage(x, 0x00ff0000, 0x0000ff00, 8); + // + // return x; + // } + + + logic [31:0] unshfl1_d; + logic [31:0] unshfl2_d; + logic [31:0] unshfl4_d; + logic [31:0] unshfl_d; + + + assign unshfl1_d[31:0] = (rs2_in[0]) ? {rs1_in[31],rs1_in[29],rs1_in[30],rs1_in[28],rs1_in[27],rs1_in[25],rs1_in[26],rs1_in[24], + rs1_in[23],rs1_in[21],rs1_in[22],rs1_in[20],rs1_in[19],rs1_in[17],rs1_in[18],rs1_in[16], + rs1_in[15],rs1_in[13],rs1_in[14],rs1_in[12],rs1_in[11],rs1_in[09],rs1_in[10],rs1_in[08], + rs1_in[07],rs1_in[05],rs1_in[06],rs1_in[04],rs1_in[03],rs1_in[01],rs1_in[02],rs1_in[00]} : rs1_in[31:0]; + + assign unshfl2_d[31:0] = (rs2_in[1]) ? {unshfl1_d[31:30],unshfl1_d[27:26],unshfl1_d[29:28],unshfl1_d[25:24], + unshfl1_d[23:22],unshfl1_d[19:18],unshfl1_d[21:20],unshfl1_d[17:16], + unshfl1_d[15:14],unshfl1_d[11:10],unshfl1_d[13:12],unshfl1_d[09:08], + unshfl1_d[07:06],unshfl1_d[03:02],unshfl1_d[05:04],unshfl1_d[01:00]} : unshfl1_d[31:0]; + + assign unshfl4_d[31:0] = (rs2_in[2]) ? {unshfl2_d[31:28],unshfl2_d[23:20],unshfl2_d[27:24],unshfl2_d[19:16], + unshfl2_d[15:12],unshfl2_d[07:04],unshfl2_d[11:08],unshfl2_d[03:00]} : unshfl2_d[31:0]; + + assign unshfl_d[31:0] = (rs2_in[3]) ? {unshfl4_d[31:24],unshfl4_d[15:08],unshfl4_d[23:16],unshfl4_d[07:00]} : unshfl4_d[31:0]; + + + + + // * * * * * * * * * * * * * * * * * * BitManip : CRC32, CRC32c * * * * * * * * * * * * * * * * * + + // *** computed from https: //crccalc.com *** + // + // "a" is 8'h61 = 8'b0110_0001 (8'h61 ^ 8'hff = 8'h9e) + // + // Input must first be XORed with 32'hffff_ffff + // + // + // CRC32 + // + // Input Output Input Output + // ----- -------- -------- -------- + // "a" e8b7be43 ffffff9e 174841bc + // "aa" 078a19d7 ffff9e9e f875e628 + // "aaaa" ad98e545 9e9e9e9e 5267a1ba + // + // + // + // CRC32c + // + // Input Output Input Output + // ----- -------- -------- -------- + // "a" c1d04330 ffffff9e 3e2fbccf + // "aa" f1f2dac2 ffff9e9e 0e0d253d + // "aaaa" 6a52eeb0 9e9e9e9e 95ad114f + + + logic crc32_all; + logic [31:0] crc32_poly_rev; + logic [31:0] crc32c_poly_rev; + integer crc32_bi, crc32_hi, crc32_wi, crc32c_bi, crc32c_hi, crc32c_wi; + logic [31:0] crc32_bd, crc32_hd, crc32_wd, crc32c_bd, crc32c_hd, crc32c_wd; + + + assign crc32_all = ap_crc32_b | ap_crc32_h | ap_crc32_w | ap_crc32c_b | ap_crc32c_h | ap_crc32c_w; + + assign crc32_poly_rev[31:0] = 32'hEDB88320; // bit reverse of 32'h04C11DB7 + assign crc32c_poly_rev[31:0] = 32'h82F63B78; // bit reverse of 32'h1EDC6F41 + + + always_comb + begin + crc32_bd[31:0] = rs1_in[31:0]; + + for (crc32_bi=0; crc32_bi<8; crc32_bi++) + begin + crc32_bd[31:0] = (crc32_bd[31:0] >> 1) ^ (crc32_poly_rev[31:0] & {32{crc32_bd[0]}}); + end // FOR crc32_bi + end // ALWAYS_COMB + + + always_comb + begin + crc32_hd[31:0] = rs1_in[31:0]; + + for (crc32_hi=0; crc32_hi<16; crc32_hi++) + begin + crc32_hd[31:0] = (crc32_hd[31:0] >> 1) ^ (crc32_poly_rev[31:0] & {32{crc32_hd[0]}}); + end // FOR crc32_hi + end // ALWAYS_COMB + + + always_comb + begin + crc32_wd[31:0] = rs1_in[31:0]; + + for (crc32_wi=0; crc32_wi<32; crc32_wi++) + begin + crc32_wd[31:0] = (crc32_wd[31:0] >> 1) ^ (crc32_poly_rev[31:0] & {32{crc32_wd[0]}}); + end // FOR crc32_wi + end // ALWAYS_COMB + + + + + always_comb + begin + crc32c_bd[31:0] = rs1_in[31:0]; + + for (crc32c_bi=0; crc32c_bi<8; crc32c_bi++) + begin + crc32c_bd[31:0] = (crc32c_bd[31:0] >> 1) ^ (crc32c_poly_rev[31:0] & {32{crc32c_bd[0]}}); + end // FOR crc32c_bi + end // ALWAYS_COMB + + + always_comb + begin + crc32c_hd[31:0] = rs1_in[31:0]; + + for (crc32c_hi=0; crc32c_hi<16; crc32c_hi++) + begin + crc32c_hd[31:0] = (crc32c_hd[31:0] >> 1) ^ (crc32c_poly_rev[31:0] & {32{crc32c_hd[0]}}); + end // FOR crc32c_hi + end // ALWAYS_COMB + + + always_comb + begin + crc32c_wd[31:0] = rs1_in[31:0]; + + for (crc32c_wi=0; crc32c_wi<32; crc32c_wi++) + begin + crc32c_wd[31:0] = (crc32c_wd[31:0] >> 1) ^ (crc32c_poly_rev[31:0] & {32{crc32c_wd[0]}}); + end // FOR crc32c_wi + end // ALWAYS_COMB + + + + + + // * * * * * * * * * * * * * * * * * * BitManip : BFP * * * * * * * * * * * * * * * * * * + + logic [4:0] bfp_len; + logic [4:0] bfp_off; + logic [31:0] bfp_len_mask_; + logic [15:0] bfp_preshift_data; + logic [63:0] bfp_shift_data; + logic [63:0] bfp_shift_mask; + logic [31:0] bfp_result_d; + + + assign bfp_len[3:0] = rs2_in[27:24]; + assign bfp_len[4] = (bfp_len[3:0] == 4'b0); // If LEN field is zero, then LEN=16 + assign bfp_off[4:0] = rs2_in[20:16]; + + assign bfp_len_mask_[31:0] = 32'hffff_ffff << bfp_len[4:0]; + assign bfp_preshift_data[15:0]= rs2_in[15:0] & ~bfp_len_mask_[15:0]; + + assign bfp_shift_data[63:0] = {16'b0,bfp_preshift_data[15:0], 16'b0,bfp_preshift_data[15:0]} << bfp_off[4:0]; + assign bfp_shift_mask[63:0] = {bfp_len_mask_[31:0], bfp_len_mask_[31:0]} << bfp_off[4:0]; + + assign bfp_result_d[31:0] = bfp_shift_data[63:32] | (rs1_in[31:0] & bfp_shift_mask[63:32]); + + + + + + // * * * * * * * * * * * * * * * * * * BitManip : Common logic * * * * * * * * * * * * * * * * * * + + + assign bitmanip_sel_d = ap_bext | ap_bdep | ap_clmul | ap_clmulh | ap_clmulr | ap_grev | ap_gorc | ap_shfl | ap_unshfl | crc32_all | ap_bfp; + + assign bitmanip_d[31:0] = ( {32{ap_bext}} & bext_d[31:0] ) | + ( {32{ap_bdep}} & bdep_d[31:0] ) | + ( {32{ap_clmul}} & clmul_raw_d[31:0] ) | + ( {32{ap_clmulh}} & {1'b0,clmul_raw_d[62:32]} ) | + ( {32{ap_clmulr}} & clmul_raw_d[62:31] ) | + ( {32{ap_grev}} & grev_d[31:0] ) | + ( {32{ap_gorc}} & gorc_d[31:0] ) | + ( {32{ap_shfl}} & shfl_d[31:0] ) | + ( {32{ap_unshfl}} & unshfl_d[31:0] ) | + ( {32{ap_crc32_b}} & crc32_bd[31:0] ) | + ( {32{ap_crc32_h}} & crc32_hd[31:0] ) | + ( {32{ap_crc32_w}} & crc32_wd[31:0] ) | + ( {32{ap_crc32c_b}} & crc32c_bd[31:0] ) | + ( {32{ap_crc32c_h}} & crc32c_hd[31:0] ) | + ( {32{ap_crc32c_w}} & crc32c_wd[31:0] ) | + ( {32{ap_bfp}} & bfp_result_d[31:0] ); + + + + rvdffe #(33) i_bitmanip_ff (.*, .clk(clk), .din({bitmanip_sel_d,bitmanip_d[31:0]}), .dout({bitmanip_sel_x,bitmanip_x[31:0]}), .en(bit_x_enable)); + + + + + assign result_x[31:0] = ( {32{~bitmanip_sel_x & ~low_x}} & prod_x[63:32] ) | + ( {32{~bitmanip_sel_x & low_x}} & prod_x[31:0] ) | + bitmanip_x[31:0]; + endmodule // el2_exu_mul_ctl diff --git a/design/flist.formal b/design/flist.formal new file mode 100644 index 0000000..0039512 --- /dev/null +++ b/design/flist.formal @@ -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 diff --git a/design/flist.questa b/design/flist.questa new file mode 100644 index 0000000..4f461c7 --- /dev/null +++ b/design/flist.questa @@ -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 diff --git a/design/ifu/el2_ifu.sv b/design/ifu/el2_ifu.sv index 35588b1..837a9c2 100644 --- a/design/ifu/el2_ifu.sv +++ b/design/ifu/el2_ifu.sv @@ -1,6 +1,6 @@ //******************************************************************************** // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,12 +25,12 @@ import el2_pkg::*; `include "el2_param.vh" ) ( - input logic free_clk, - input logic active_clk, - input logic clk, - input logic rst_l, + input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in. + input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in. + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic rst_l, // reset, active low - input logic dec_i0_decode_d, + input logic dec_i0_decode_d, // Valid instruction at D and not blocked input logic exu_flush_final, // flush, includes upper and lower input logic dec_tlu_i0_commit_cmt , // committed i0 @@ -87,7 +87,6 @@ import el2_pkg::*; input logic [63:0] ifu_axi_rdata, input logic [1:0] ifu_axi_rresp, - input logic ifu_bus_clk_en, input logic dma_iccm_req, @@ -160,24 +159,24 @@ import el2_pkg::*; output logic ifu_pmu_bus_trxn, // iside bus transactions - output logic ifu_i0_icaf, // Instructio 0 access fault. From Aligner to Decode + output logic ifu_i0_icaf, // Instruction 0 access fault. From Aligner to Decode output logic [1:0] ifu_i0_icaf_type, // Instruction 0 access fault type - output logic ifu_i0_valid, // Instructio 0 valid. From Aligner to Decode - output logic ifu_i0_icaf_f1, // Instruction 0 has access fault on second fetch group + output logic ifu_i0_valid, // Instruction 0 valid. From Aligner to Decode + output logic ifu_i0_icaf_second, // Instruction 0 has access fault on second 2B of 4B inst output logic ifu_i0_dbecc, // Instruction 0 has double bit ecc error output logic iccm_dma_sb_error, // Single Bit ECC error from a DMA access - output logic[31:0] ifu_i0_instr, // Instructio 0 . From Aligner to Decode - output logic[31:1] ifu_i0_pc, // Instructio 0 pc. From Aligner to Decode - output logic ifu_i0_pc4, // Instructio 0 is 4 byte. From Aligner to Decode + output logic[31:0] ifu_i0_instr, // Instruction 0 . From Aligner to Decode + output logic[31:1] ifu_i0_pc, // Instruction 0 pc. From Aligner to Decode + output logic ifu_i0_pc4, // Instruction 0 is 4 byte. From Aligner to Decode output logic ifu_miss_state_idle, // There is no outstanding miss. Cache miss state is idle. - - output el2_br_pkt_t i0_brp, // Instructio 0 branch packet. From Aligner to Decode + output el2_br_pkt_t i0_brp, // Instruction 0 branch packet. From Aligner to Decode output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index, // BP index output logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr, // BP FGHR output logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag, // BP tag + output logic [$clog2(pt.BTB_SIZE)-1:0] ifu_i0_fa_index, // Fully associt btb index input el2_predict_pkt_t exu_mp_pkt, // mispredict packet input logic [pt.BHT_GHR_SIZE-1:0] exu_mp_eghr, // execute ghr @@ -188,16 +187,18 @@ import el2_pkg::*; input el2_br_tlu_pkt_t dec_tlu_br0_r_pkt, // slot0 update/error pkt input logic [pt.BHT_GHR_SIZE-1:0] exu_i0_br_fghr_r, // fghr to bp input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] exu_i0_br_index_r, // bp index + input logic [$clog2(pt.BTB_SIZE)-1:0] dec_fa_error_index, // Fully associt btb error index input dec_tlu_flush_lower_wb, output logic [15:0] ifu_i0_cinst, + /// Icache debug input el2_cache_debug_pkt_t dec_tlu_ic_diag_pkt , output logic ifu_ic_debug_rd_data_valid, - output logic iccm_buf_correct_ecc, - output logic iccm_correction_state, + output logic iccm_buf_correct_ecc, + output logic iccm_correction_state, input logic scan_mode ); @@ -220,22 +221,16 @@ import el2_pkg::*; logic ic_write_stall; logic ic_dma_active; logic ifc_dma_access_ok; - logic ic_access_fault_f; + logic [1:0] ic_access_fault_f; logic [1:0] ic_access_fault_type_f; logic ifu_ic_mb_empty; - logic ic_hit_f; - // fetch control - el2_ifu_ifc_ctl #(.pt(pt)) ifc (.* - ); - - logic [1:0] ifu_bp_way_f; // way indication; right justified - logic ifu_bp_hit_taken_f; // kill next fetch; taken target found + logic [1:0] ifu_bp_way_f; // way indication; right justified + logic ifu_bp_hit_taken_f; // kill next fetch; taken target found logic [31:1] ifu_bp_btb_target_f; // predicted target PC logic ifu_bp_inst_mask_f; // tell ic which valids to kill because of a taken branch; right justified - logic [1:0] ifu_bp_hist1_f; // history counters for all 4 potential branches; right justified logic [1:0] ifu_bp_hist0_f; // history counters for all 4 potential branches; right justified logic [11:0] ifu_bp_poffset_f; // predicted target @@ -243,9 +238,28 @@ import el2_pkg::*; logic [1:0] ifu_bp_pc4_f; // pc4 indication; right justified logic [1:0] ifu_bp_valid_f; // branch valid, right justified logic [pt.BHT_GHR_SIZE-1:0] ifu_bp_fghr_f; + logic [1:0] [$clog2(pt.BTB_SIZE)-1:0] ifu_bp_fa_index_f; + + + // fetch control + el2_ifu_ifc_ctl #(.pt(pt)) ifc (.* + ); // branch predictor - el2_ifu_bp_ctl #(.pt(pt)) bp (.*); + if (pt.BTB_ENABLE==1) begin : bpred + el2_ifu_bp_ctl #(.pt(pt)) bp (.*); + end + else begin : bpred + assign ifu_bp_hit_taken_f = '0; + // verif wires + logic btb_wr_en_way0, btb_wr_en_way1,dec_tlu_error_wb; + logic [16+pt.BTB_BTAG_SIZE:0] btb_wr_data; + assign btb_wr_en_way0 = '0; + assign btb_wr_en_way1 = '0; + assign btb_wr_data = '0; + assign dec_tlu_error_wb ='0; + assign ifu_bp_inst_mask_f = 1'b1; + end logic [1:0] ic_fetch_val_f; @@ -253,7 +267,7 @@ import el2_pkg::*; logic [31:0] ifu_fetch_data_f; logic ifc_fetch_req_f; logic ifc_fetch_req_f_raw; - logic iccm_rd_ecc_double_err; // This fetch has an iccm double error. + logic [1:0] iccm_rd_ecc_double_err; // This fetch has an iccm double error. logic ifu_async_error_start; @@ -269,7 +283,10 @@ import el2_pkg::*; logic ifc_region_acc_fault_bf; // Access fault. in ICCM region but offset is outside defined ICCM. // aligner - el2_ifu_aln_ctl #(.pt(pt)) aln (.*); + + el2_ifu_aln_ctl #(.pt(pt)) aln ( + .* + ); // icache @@ -316,29 +333,29 @@ import el2_pkg::*; logic exu_flush_final_d1; assign mppc_ns[31:1] = `EXU.i0_flush_upper_x ? `EXU.exu_i0_pc_x : `EXU.dec_i0_pc_d; assign mppc_ns[0] = 1'b0; - rvdff #(33) mdseal_ff (.*, .din({mppc_ns[31:0], exu_flush_final}), .dout({mppc[31:0], exu_flush_final_d1})); + rvdff #(33) junk_ff (.*, .clk(active_clk), .din({mppc_ns[31:0], exu_flush_final}), .dout({mppc[31:0], exu_flush_final_d1})); logic tmp_bnk; - assign tmp_bnk = bp.btb_sel_f[1]; + assign tmp_bnk = bpred.bp.btb_sel_f[1]; always @(negedge clk) begin if(`DEC.tlu.mcyclel[31:0] == 32'h0000_0010) begin - $display("BTB_CONFIG: %d",pt.BTB_ARRAY_DEPTH*4); + $display("BTB_CONFIG: %d",pt.BTB_SIZE); `ifndef BP_NOGSHARE - $display("BHT_CONFIG: %d gshare: 1",pt.BHT_ARRAY_DEPTH*4); + $display("BHT_CONFIG: %d gshare: 1",pt.BHT_SIZE); `else - $display("BHT_CONFIG: %d gshare: 0",pt.BHT_ARRAY_DEPTH*4); + $display("BHT_CONFIG: %d gshare: 0",pt.BHT_SIZE); `endif $display("RS_CONFIG: %d", pt.RET_STACK_SIZE); end if(exu_flush_final_d1 & ~(dec_tlu_br0_r_pkt.br_error | dec_tlu_br0_r_pkt.br_start_error) & (exu_mp_pkt.misp | exu_mp_pkt.ataken)) - $display("%7d BTB_MP : index: %0h bank: %0h call: %b ret: %b ataken: %b hist: %h valid: %b tag: %h targ: %h eghr: %b pred: %b ghr_index: %h brpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha, exu_mp_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO], 1'b0, exu_mp_call, exu_mp_ret, exu_mp_ataken, exu_mp_hist[1:0], exu_mp_valid, exu_mp_btag[pt.BTB_BTAG_SIZE-1:0], {exu_flush_path_final[31:1], 1'b0}, exu_mp_eghr[pt.BHT_GHR_SIZE-1:0], exu_mp_valid, bp.bht_wr_addr0, mppc[31:0], exu_mp_pkt.way); + $display("%7d BTB_MP : index: %0h bank: %0h call: %b ret: %b ataken: %b hist: %h valid: %b tag: %h targ: %h eghr: %b pred: %b ghr_index: %h brpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha, exu_mp_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO], 1'b0, exu_mp_call, exu_mp_ret, exu_mp_ataken, exu_mp_hist[1:0], exu_mp_valid, exu_mp_btag[pt.BTB_BTAG_SIZE-1:0], {exu_flush_path_final[31:1], 1'b0}, exu_mp_eghr[pt.BHT_GHR_SIZE-1:0], exu_mp_valid, bpred.bp.bht_wr_addr0, mppc[31:0], exu_mp_pkt.way); for(int i = 0; i < 8; i++) begin if(ifu_bp_valid_f[i] & ifc_fetch_req_f) - $display("%7d BTB_HIT : index: %0h bank: %0h call: %b ret: %b taken: %b strength: %b tag: %h targ: %0h ghr: %4b ghr_index: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,btb_rd_addr_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO],bp.btb_sel_f[1], bp.btb_rd_call_f, bp.btb_rd_ret_f, ifu_bp_hist1_f[tmp_bnk], ifu_bp_hist0_f[tmp_bnk], bp.fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0], {ifu_bp_btb_target_f[31:1], 1'b0}, bp.fghr[pt.BHT_GHR_SIZE-1:0], bp.bht_rd_addr_f, ifu_bp_way_f[tmp_bnk]); + $display("%7d BTB_HIT : index: %0h bank: %0h call: %b ret: %b taken: %b strength: %b tag: %h targ: %0h ghr: %4b ghr_index: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,btb_rd_addr_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO],bpred.bp.btb_sel_f[1], bpred.bp.btb_rd_call_f, bpred.bp.btb_rd_ret_f, ifu_bp_hist1_f[tmp_bnk], ifu_bp_hist0_f[tmp_bnk], bpred.bp.fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0], {ifu_bp_btb_target_f[31:1], 1'b0}, bpred.bp.fghr[pt.BHT_GHR_SIZE-1:0], bpred.bp.bht_rd_addr_f, ifu_bp_way_f[tmp_bnk]); end if(dec_tlu_br0_r_pkt.valid & ~(dec_tlu_br0_r_pkt.br_error | dec_tlu_br0_r_pkt.br_start_error)) - $display("%7d BTB_UPD0: ghr_index: %0h bank: %0h hist: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,bp.br0_hashed_wb[pt.BHT_ADDR_HI:pt.BHT_ADDR_LO],{dec_tlu_br0_r_pkt.middle}, dec_tlu_br0_r_pkt.hist, dec_tlu_br0_r_pkt.way); + $display("%7d BTB_UPD0: ghr_index: %0h bank: %0h hist: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,bpred.bp.br0_hashed_wb[pt.BHT_ADDR_HI:pt.BHT_ADDR_LO],{dec_tlu_br0_r_pkt.middle}, dec_tlu_br0_r_pkt.hist, dec_tlu_br0_r_pkt.way); if(dec_tlu_br0_r_pkt.br_error | dec_tlu_br0_r_pkt.br_start_error) $display("%7d BTB_ERR0: index: %0h bank: %0h start: %b rfpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,exu_i0_br_index_r[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO],1'b0, dec_tlu_br0_r_pkt.br_start_error, {exu_flush_path_final[31:1], 1'b0}, dec_tlu_br0_r_pkt.way); diff --git a/design/ifu/el2_ifu_aln_ctl.sv b/design/ifu/el2_ifu_aln_ctl.sv index 55e17db..9deda1b 100644 --- a/design/ifu/el2_ifu_aln_ctl.sv +++ b/design/ifu/el2_ifu_aln_ctl.sv @@ -1,6 +1,6 @@ //******************************************************************************** // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,31 +25,21 @@ import el2_pkg::*; ) ( - input logic scan_mode, - input logic rst_l, - input logic clk, - input logic active_clk, + input logic scan_mode, // Flop scan mode control + input logic rst_l, // reset, active low + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in. input logic ifu_async_error_start, // ecc/parity related errors with current fetch - not sent down the pipe - input logic iccm_rd_ecc_double_err, // This fetch has a double ICCM ecc error. + input logic [1:0] iccm_rd_ecc_double_err, // This fetch has a double ICCM ecc error. - input logic ic_access_fault_f, // Instruction access fault for the current fetch. + input logic [1:0] ic_access_fault_f, // Instruction access fault for the current fetch. input logic [1:0] ic_access_fault_type_f, // Instruction access fault types - input logic [pt.BHT_GHR_SIZE-1:0] ifu_bp_fghr_f, // fetch GHR - input logic [31:1] ifu_bp_btb_target_f, // predicted RET target - input logic [11:0] ifu_bp_poffset_f, // predicted target offset - - input logic [1:0] ifu_bp_hist0_f, // history counters for all 4 potential branches, bit 1, right justified - input logic [1:0] ifu_bp_hist1_f, // history counters for all 4 potential branches, bit 1, right justified - input logic [1:0] ifu_bp_pc4_f, // pc4 indication, right justified - input logic [1:0] ifu_bp_way_f, // way indication, right justified - input logic [1:0] ifu_bp_valid_f, // branch valid, right justified - input logic [1:0] ifu_bp_ret_f, // predicted ret indication, right justified input logic exu_flush_final, // Flush from the pipeline. - input logic dec_i0_decode_d, + input logic dec_i0_decode_d, // Valid instruction at D-stage and not blocked input logic [31:0] ifu_fetch_data_f, // fetch data in memory format - not right justified @@ -61,7 +51,7 @@ import el2_pkg::*; output logic ifu_i0_valid, // Instruction 0 is valid output logic ifu_i0_icaf, // Instruction 0 has access fault output logic [1:0] ifu_i0_icaf_type, // Instruction 0 access fault type - output logic ifu_i0_icaf_f1, // Instruction 0 has access fault on second fetch group + output logic ifu_i0_icaf_second, // Instruction 0 has access fault on second 2B of 4B inst output logic ifu_i0_dbecc, // Instruction 0 has double bit ecc error output logic [31:0] ifu_i0_instr, // Instruction 0 @@ -70,10 +60,28 @@ import el2_pkg::*; output logic ifu_fb_consume1, // Consumed one buffer. To fetch control fetch for buffer mass balance output logic ifu_fb_consume2, // Consumed two buffers.To fetch control fetch for buffer mass balance + + + input logic [pt.BHT_GHR_SIZE-1:0] ifu_bp_fghr_f, // fetch GHR + input logic [31:1] ifu_bp_btb_target_f, // predicted RET target + input logic [11:0] ifu_bp_poffset_f, // predicted target offset + input logic [1:0] [$clog2(pt.BTB_SIZE)-1:0] ifu_bp_fa_index_f, // predicted branch index (fully associative option) + + input logic [1:0] ifu_bp_hist0_f, // history counters for all 4 potential branches, bit 1, right justified + input logic [1:0] ifu_bp_hist1_f, // history counters for all 4 potential branches, bit 1, right justified + input logic [1:0] ifu_bp_pc4_f, // pc4 indication, right justified + input logic [1:0] ifu_bp_way_f, // way indication, right justified + input logic [1:0] ifu_bp_valid_f, // branch valid, right justified + input logic [1:0] ifu_bp_ret_f, // predicted ret indication, right justified + + output el2_br_pkt_t i0_brp, // Branch packet for I0. output logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] ifu_i0_bp_index, // BP index output logic [pt.BHT_GHR_SIZE-1:0] ifu_i0_bp_fghr, // BP FGHR output logic [pt.BTB_BTAG_SIZE-1:0] ifu_i0_bp_btag, // BP tag + + output logic [$clog2(pt.BTB_SIZE)-1:0] ifu_i0_fa_index, // Fully associt btb index + output logic ifu_pmu_instr_aligned, // number of inst aligned this cycle output logic [15:0] ifu_i0_cinst // 16b compress inst for i0 @@ -90,11 +98,6 @@ import el2_pkg::*; logic [1:0] f0val_in, f0val; logic [1:0] sf1val, sf0val; - logic [31:1] f2pc_in, f2pc; - logic [31:1] f1pc_in, f1pc; - logic [31:1] f0pc_in, f0pc; - logic [31:1] sf1pc; - logic [31:0] aligndata; logic first4B, first2B; @@ -105,8 +108,6 @@ import el2_pkg::*; logic f2_valid, sf1_valid, sf0_valid; logic [31:0] ifirst; - logic [31:1] f0pc_plus1; - logic [31:1] f1pc_plus1; logic [1:0] alignval; logic [31:1] firstpc, secondpc; @@ -119,6 +120,8 @@ import el2_pkg::*; logic [1:0] f1hist0; logic [1:0] f0hist0; + logic [1:0][$clog2(pt.BTB_SIZE)-1:0] f0index, f1index, alignindex; + logic [1:0] f1ictype; logic [1:0] f0ictype; @@ -146,10 +149,10 @@ import el2_pkg::*; logic [31:1] f1prett; logic [31:1] f0prett; - logic f1dbecc; - logic f0dbecc; - logic f1icaf; - logic f0icaf; + logic [1:0] f1dbecc; + logic [1:0] f0dbecc; + logic [1:0] f1icaf; + logic [1:0] f0icaf; logic [1:0] aligndbecc; logic [1:0] alignicaf; @@ -159,10 +162,6 @@ import el2_pkg::*; logic first_legal; - logic f2_wr_en; - logic f0_shift_wr_en; - logic f1_shift_wr_en; - logic [1:0] wrptr, wrptr_in; logic [1:0] rdptr, rdptr_in; logic [2:0] qwen; @@ -185,16 +184,17 @@ import el2_pkg::*; logic [2:0] qren; logic consume_fb1, consume_fb0; - logic [1:1] icaf_eff; + logic [1:0] icaf_eff; - localparam BRDATA_SIZE = 12; - localparam BRDATA_WIDTH = 6; + localparam BRDATA_SIZE = pt.BTB_ENABLE ? 16+($clog2(pt.BTB_SIZE)*2*pt.BTB_FULLYA) : 2; + localparam BRDATA_WIDTH = pt.BTB_ENABLE ? 8+($clog2(pt.BTB_SIZE)*pt.BTB_FULLYA) : 1; logic [BRDATA_SIZE-1:0] brdata_in, brdata2, brdata1, brdata0; logic [BRDATA_SIZE-1:0] brdata1eff, brdata0eff; logic [BRDATA_SIZE-1:0] brdata1final, brdata0final; - localparam MHI = 46+pt.BHT_GHR_SIZE; - localparam MSIZE = 47+pt.BHT_GHR_SIZE; + localparam MHI = 1+(pt.BTB_ENABLE * (43+pt.BHT_GHR_SIZE)); + localparam MSIZE = 2+(pt.BTB_ENABLE * (43+pt.BHT_GHR_SIZE)); + logic [MHI:0] misc_data_in, misc2, misc1, misc0; logic [MHI:0] misc1eff, misc0eff; @@ -204,40 +204,45 @@ import el2_pkg::*; assign error_stall_in = (error_stall | ifu_async_error_start) & ~exu_flush_final; - rvdff #(1) error_stallff (.*, .clk(active_clk), .din(error_stall_in), .dout(error_stall)); + rvdff #(.WIDTH(7)) bundle1ff (.*, + .clk(active_clk), + .din ({wrptr_in[1:0],rdptr_in[1:0],q2off_in,q1off_in,q0off_in}), + .dout({wrptr[1:0], rdptr[1:0], q2off, q1off, q0off}) + ); - rvdff #(2) wrpff (.*, .clk(active_clk), .din(wrptr_in[1:0]), .dout(wrptr[1:0])); - rvdff #(2) rdpff (.*, .clk(active_clk), .din(rdptr_in[1:0]), .dout(rdptr[1:0])); + rvdffie #(.WIDTH(7),.OVERRIDE(1)) bundle2ff (.*, + .din ({error_stall_in,f2val_in[1:0],f1val_in[1:0],f0val_in[1:0]}), + .dout({error_stall, f2val[1:0], f1val[1:0], f0val[1:0] }) + ); - rvdff #(2) f2valff (.*, .clk(active_clk), .din(f2val_in[1:0]), .dout(f2val[1:0])); - rvdff #(2) f1valff (.*, .clk(active_clk), .din(f1val_in[1:0]), .dout(f1val[1:0])); - rvdff #(2) f0valff (.*, .clk(active_clk), .din(f0val_in[1:0]), .dout(f0val[1:0])); +if(pt.BTB_ENABLE==1) begin + rvdffe #(BRDATA_SIZE) brdata2ff (.*, .clk(clk), .en(qwen[2]), .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata2[BRDATA_SIZE-1:0])); + rvdffe #(BRDATA_SIZE) brdata1ff (.*, .clk(clk), .en(qwen[1]), .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata1[BRDATA_SIZE-1:0])); + rvdffe #(BRDATA_SIZE) brdata0ff (.*, .clk(clk), .en(qwen[0]), .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata0[BRDATA_SIZE-1:0])); + rvdffe #(MSIZE) misc2ff (.*, .clk(clk), .en(qwen[2]), .din(misc_data_in[MHI:0]), .dout(misc2[MHI:0])); + rvdffe #(MSIZE) misc1ff (.*, .clk(clk), .en(qwen[1]), .din(misc_data_in[MHI:0]), .dout(misc1[MHI:0])); + rvdffe #(MSIZE) misc0ff (.*, .clk(clk), .en(qwen[0]), .din(misc_data_in[MHI:0]), .dout(misc0[MHI:0])); +end +else begin - rvdff #(1) q2offsetff (.*, .clk(active_clk), .din(q2off_in), .dout(q2off)); - rvdff #(1) q1offsetff (.*, .clk(active_clk), .din(q1off_in), .dout(q1off)); - rvdff #(1) q0offsetff (.*, .clk(active_clk), .din(q0off_in), .dout(q0off)); - rvdffe #(31) f2pcff (.*, .en(f2_wr_en), .din(f2pc_in[31:1]), .dout(f2pc[31:1])); - rvdffe #(31) f1pcff (.*, .en(f1_shift_wr_en), .din(f1pc_in[31:1]), .dout(f1pc[31:1])); - rvdffe #(31) f0pcff (.*, .en(f0_shift_wr_en), .din(f0pc_in[31:1]), .dout(f0pc[31:1])); - rvdffe #(BRDATA_SIZE) brdata2ff (.*, .en(qwen[2]), .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata2[BRDATA_SIZE-1:0])); - rvdffe #(BRDATA_SIZE) brdata1ff (.*, .en(qwen[1]), .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata1[BRDATA_SIZE-1:0])); - rvdffe #(BRDATA_SIZE) brdata0ff (.*, .en(qwen[0]), .din(brdata_in[BRDATA_SIZE-1:0]), .dout(brdata0[BRDATA_SIZE-1:0])); - rvdffe #(MSIZE) misc2ff (.*, .en(qwen[2]), .din(misc_data_in[MHI:0]), .dout(misc2[MHI:0])); - rvdffe #(MSIZE) misc1ff (.*, .en(qwen[1]), .din(misc_data_in[MHI:0]), .dout(misc1[MHI:0])); - rvdffe #(MSIZE) misc0ff (.*, .en(qwen[0]), .din(misc_data_in[MHI:0]), .dout(misc0[MHI:0])); + rvdffie #((MSIZE*3)+(BRDATA_SIZE*3)) miscff (.*, + .din({qwen[2] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc2[MHI:0], brdata2[BRDATA_SIZE-1:0]}, + qwen[1] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc1[MHI:0], brdata1[BRDATA_SIZE-1:0]}, + qwen[0] ? {misc_data_in[MHI:0], brdata_in[BRDATA_SIZE-1:0]} : {misc0[MHI:0], brdata0[BRDATA_SIZE-1:0]}}), + .dout({misc2[MHI:0],misc1[MHI:0],misc0[MHI:0], + brdata2[BRDATA_SIZE-1:0], brdata1[BRDATA_SIZE-1:0], brdata0[BRDATA_SIZE-1:0]}) + ); +end - rvdffe #(32) q2ff (.*, .en(qwen[2]), .din(ifu_fetch_data_f[31:0]), .dout(q2[31:0])); - rvdffe #(32) q1ff (.*, .en(qwen[1]), .din(ifu_fetch_data_f[31:0]), .dout(q1[31:0])); - rvdffe #(32) q0ff (.*, .en(qwen[0]), .din(ifu_fetch_data_f[31:0]), .dout(q0[31:0])); + logic [31:1] q2pc, q1pc, q0pc; + rvdffe #(31) q2pcff (.*, .clk(clk), .en(qwen[2]), .din(ifu_fetch_pc[31:1]), .dout(q2pc[31:1])); + rvdffe #(31) q1pcff (.*, .clk(clk), .en(qwen[1]), .din(ifu_fetch_pc[31:1]), .dout(q1pc[31:1])); + rvdffe #(31) q0pcff (.*, .clk(clk), .en(qwen[0]), .din(ifu_fetch_pc[31:1]), .dout(q0pc[31:1])); - - - - assign f2_wr_en = fetch_to_f2; - assign f1_shift_wr_en = fetch_to_f1 | shift_f2_f1 | f1_shift_2B; - assign f0_shift_wr_en = fetch_to_f0 | shift_f2_f0 | shift_f1_f0 | shift_2B | shift_4B; - + rvdffe #(32) q2ff (.*, .clk(clk), .en(qwen[2]), .din(ifu_fetch_data_f[31:0]), .dout(q2[31:0])); + rvdffe #(32) q1ff (.*, .clk(clk), .en(qwen[1]), .din(ifu_fetch_data_f[31:0]), .dout(q1[31:0])); + rvdffe #(32) q0ff (.*, .clk(clk), .en(qwen[0]), .din(ifu_fetch_data_f[31:0]), .dout(q0[31:0])); // new queue control logic @@ -297,40 +302,64 @@ import el2_pkg::*; // misc data that is associated with each fetch buffer - assign misc_data_in[MHI:0] = { iccm_rd_ecc_double_err, - ic_access_fault_f, - ic_access_fault_type_f[1:0], - ifu_bp_btb_target_f[31:1], - ifu_bp_poffset_f[11:0], - ifu_bp_fghr_f[pt.BHT_GHR_SIZE-1:0] - }; + if(pt.BTB_ENABLE==1) + assign misc_data_in[MHI:0] = { + + ic_access_fault_type_f[1:0], + ifu_bp_btb_target_f[31:1], + ifu_bp_poffset_f[11:0], + ifu_bp_fghr_f[pt.BHT_GHR_SIZE-1:0] + }; + else + assign misc_data_in[MHI:0] = { + ic_access_fault_type_f[1:0] + }; assign {misc1eff[MHI:0],misc0eff[MHI:0]} = (({MSIZE*2{qren[0]}} & {misc1[MHI:0],misc0[MHI:0]}) | ({MSIZE*2{qren[1]}} & {misc2[MHI:0],misc1[MHI:0]}) | ({MSIZE*2{qren[2]}} & {misc0[MHI:0],misc2[MHI:0]})); - assign { f1dbecc, - f1icaf, + if(pt.BTB_ENABLE==1) begin + assign { f1ictype[1:0], f1prett[31:1], f1poffset[11:0], f1fghr[pt.BHT_GHR_SIZE-1:0] } = misc1eff[MHI:0]; - assign { f0dbecc, - f0icaf, + assign { f0ictype[1:0], f0prett[31:1], f0poffset[11:0], f0fghr[pt.BHT_GHR_SIZE-1:0] } = misc0eff[MHI:0]; + if(pt.BTB_FULLYA) begin + assign brdata_in[BRDATA_SIZE-1:0] = { + ifu_bp_fa_index_f[1], iccm_rd_ecc_double_err[1],ic_access_fault_f[1],ifu_bp_hist1_f[1],ifu_bp_hist0_f[1],ifu_bp_pc4_f[1],ifu_bp_way_f[1],ifu_bp_valid_f[1],ifu_bp_ret_f[1], + ifu_bp_fa_index_f[0], iccm_rd_ecc_double_err[0],ic_access_fault_f[0],ifu_bp_hist1_f[0],ifu_bp_hist0_f[0],ifu_bp_pc4_f[0],ifu_bp_way_f[0],ifu_bp_valid_f[0],ifu_bp_ret_f[0] + }; + assign {f0index[1],f0dbecc[1],f0icaf[1],f0hist1[1],f0hist0[1],f0pc4[1],f0way[1],f0brend[1],f0ret[1], + f0index[0],f0dbecc[0],f0icaf[0],f0hist1[0],f0hist0[0],f0pc4[0],f0way[0],f0brend[0],f0ret[0]} = brdata0final[BRDATA_SIZE-1:0]; + + assign {f1index[1],f1dbecc[1],f1icaf[1],f1hist1[1],f1hist0[1],f1pc4[1],f1way[1],f1brend[1],f1ret[1], + f1index[0],f1dbecc[0],f1icaf[0],f1hist1[0],f1hist0[0],f1pc4[0],f1way[0],f1brend[0],f1ret[0]} = brdata1final[BRDATA_SIZE-1:0]; + + end + else begin + assign brdata_in[BRDATA_SIZE-1:0] = { + iccm_rd_ecc_double_err[1],ic_access_fault_f[1],ifu_bp_hist1_f[1],ifu_bp_hist0_f[1],ifu_bp_pc4_f[1],ifu_bp_way_f[1],ifu_bp_valid_f[1],ifu_bp_ret_f[1], + iccm_rd_ecc_double_err[0],ic_access_fault_f[0],ifu_bp_hist1_f[0],ifu_bp_hist0_f[0],ifu_bp_pc4_f[0],ifu_bp_way_f[0],ifu_bp_valid_f[0],ifu_bp_ret_f[0] + }; + assign {f0dbecc[1],f0icaf[1],f0hist1[1],f0hist0[1],f0pc4[1],f0way[1],f0brend[1],f0ret[1], + f0dbecc[0],f0icaf[0],f0hist1[0],f0hist0[0],f0pc4[0],f0way[0],f0brend[0],f0ret[0]} = brdata0final[BRDATA_SIZE-1:0]; + + assign {f1dbecc[1],f1icaf[1],f1hist1[1],f1hist0[1],f1pc4[1],f1way[1],f1brend[1],f1ret[1], + f1dbecc[0],f1icaf[0],f1hist1[0],f1hist0[0],f1pc4[0],f1way[0],f1brend[0],f1ret[0]} = brdata1final[BRDATA_SIZE-1:0]; + + end - assign brdata_in[BRDATA_SIZE-1:0] = { - ifu_bp_hist1_f[1],ifu_bp_hist0_f[1],ifu_bp_pc4_f[1],ifu_bp_way_f[1],ifu_bp_valid_f[1],ifu_bp_ret_f[1], - ifu_bp_hist1_f[0],ifu_bp_hist0_f[0],ifu_bp_pc4_f[0],ifu_bp_way_f[0],ifu_bp_valid_f[0],ifu_bp_ret_f[0] - }; @@ -344,11 +373,37 @@ import el2_pkg::*; assign brdata1final[BRDATA_SIZE-1:0] = (({BRDATA_SIZE{q1sel[0]}} & { brdata1eff[2*BRDATA_WIDTH-1:0]}) | ({BRDATA_SIZE{q1sel[1]}} & {{BRDATA_WIDTH{1'b0}},brdata1eff[BRDATA_SIZE-1:BRDATA_WIDTH]})); - assign {f0hist1[1],f0hist0[1],f0pc4[1],f0way[1],f0brend[1],f0ret[1], - f0hist1[0],f0hist0[0],f0pc4[0],f0way[0],f0brend[0],f0ret[0]} = brdata0final[BRDATA_SIZE-1:0]; + end // if (pt.BTB_ENABLE==1) + else begin + assign { + f1ictype[1:0] + } = misc1eff[MHI:0]; - assign {f1hist1[1],f1hist0[1],f1pc4[1],f1way[1],f1brend[1],f1ret[1], - f1hist1[0],f1hist0[0],f1pc4[0],f1way[0],f1brend[0],f1ret[0]} = brdata1final[BRDATA_SIZE-1:0]; + assign { + f0ictype[1:0] + } = misc0eff[MHI:0]; + + assign brdata_in[BRDATA_SIZE-1:0] = { + iccm_rd_ecc_double_err[1],ic_access_fault_f[1], + iccm_rd_ecc_double_err[0],ic_access_fault_f[0] + }; + assign {f0dbecc[1],f0icaf[1], + f0dbecc[0],f0icaf[0]} = brdata0final[BRDATA_SIZE-1:0]; + + assign {f1dbecc[1],f1icaf[1], + f1dbecc[0],f1icaf[0]} = brdata1final[BRDATA_SIZE-1:0]; + + assign {brdata1eff[BRDATA_SIZE-1:0],brdata0eff[BRDATA_SIZE-1:0]} = (({BRDATA_SIZE*2{qren[0]}} & {brdata1[BRDATA_SIZE-1:0],brdata0[BRDATA_SIZE-1:0]}) | + ({BRDATA_SIZE*2{qren[1]}} & {brdata2[BRDATA_SIZE-1:0],brdata1[BRDATA_SIZE-1:0]}) | + ({BRDATA_SIZE*2{qren[2]}} & {brdata0[BRDATA_SIZE-1:0],brdata2[BRDATA_SIZE-1:0]})); + + assign brdata0final[BRDATA_SIZE-1:0] = (({BRDATA_SIZE{q0sel[0]}} & { brdata0eff[2*BRDATA_WIDTH-1:0]}) | + ({BRDATA_SIZE{q0sel[1]}} & {{BRDATA_WIDTH{1'b0}},brdata0eff[BRDATA_SIZE-1:BRDATA_WIDTH]})); + + assign brdata1final[BRDATA_SIZE-1:0] = (({BRDATA_SIZE{q1sel[0]}} & { brdata1eff[2*BRDATA_WIDTH-1:0]}) | + ({BRDATA_SIZE{q1sel[1]}} & {{BRDATA_WIDTH{1'b0}},brdata1eff[BRDATA_SIZE-1:BRDATA_WIDTH]})); + + end // else: !if(pt.BTB_ENABLE==1) // possible states of { sf0_valid, sf1_valid, f2_valid } @@ -391,28 +446,6 @@ import el2_pkg::*; ( sf0_valid & sf1_valid & ~f2_valid & ifvalid); - - assign f0pc_plus1[31:1] = f0pc[31:1] + 31'd1; - assign f1pc_plus1[31:1] = f1pc[31:1] + 31'd1; - - assign f2pc_in[31:1] = ifu_fetch_pc[31:1]; - - - assign sf1pc[31:1] = ({31{ f1_shift_2B}} & f1pc_plus1[31:1]) | - ({31{~f1_shift_2B}} & f1pc[31:1] ); - - assign f1pc_in[31:1] = ({31{ fetch_to_f1 }} & ifu_fetch_pc[31:1]) | - ({31{ shift_f2_f1}} & f2pc[31:1] ) | - ({31{~fetch_to_f1 & ~shift_f2_f1}} & sf1pc[31:1] ); - - - assign f0pc_in[31:1] = ({31{ fetch_to_f0 }} & ifu_fetch_pc[31:1]) | - ({31{ shift_f2_f0 }} & f2pc[31:1] ) | - ({31{ shift_f1_f0}} & sf1pc[31:1] ) | - ({31{~fetch_to_f0 & ~shift_f2_f0 & ~shift_f1_f0}} & f0pc_plus1[31:1] ); - - - assign f2val_in[1:0] = ({2{ fetch_to_f2 & ~exu_flush_final}} & ifu_fetch_val[1:0]) | ({2{~fetch_to_f2 & ~shift_f2_f1 & ~shift_f2_f0 & ~exu_flush_final}} & f2val[1:0] ); @@ -434,11 +467,6 @@ import el2_pkg::*; ({2{ shift_f1_f0 & ~exu_flush_final}} & sf1val[1:0] ) | ({2{~fetch_to_f0 & ~shift_f2_f0 & ~shift_f1_f0 & ~exu_flush_final}} & sf0val[1:0] ); - - - - - assign {q1eff[31:0],q0eff[31:0]} = (({64{qren[0]}} & {q1[31:0],q0[31:0]}) | ({64{qren[1]}} & {q2[31:0],q1[31:0]}) | ({64{qren[2]}} & {q0[31:0],q2[31:0]})); @@ -448,6 +476,16 @@ import el2_pkg::*; assign q1final[15:0] = ({16{q1sel[0]}} & q1eff[15:0] ) | ({16{q1sel[1]}} & q1eff[31:16]); + logic [31:1] q0pceff, q0pcfinal; + logic [31:1] q1pceff; + + assign {q1pceff[31:1],q0pceff[31:1]} = (({62{qren[0]}} & {q1pc[31:1],q0pc[31:1]}) | + ({62{qren[1]}} & {q2pc[31:1],q1pc[31:1]}) | + ({62{qren[2]}} & {q0pc[31:1],q2pc[31:1]})); + + + assign q0pcfinal[31:1] = ({31{q0sel[0]}} & ( q0pceff[31:1])) | + ({31{q0sel[1]}} & ( q0pceff[31:1] + 31'd1)); assign aligndata[31:0] = ({32{ f0val[1] }} & {q0final[31:0]}) | ({32{~f0val[1] & f0val[0]}} & {q1final[15:0],q0final[15:0]}); @@ -455,19 +493,26 @@ import el2_pkg::*; assign alignval[1:0] = ({ 2{ f0val[1] }} & {2'b11}) | ({ 2{~f0val[1] & f0val[0]}} & {f1val[0],1'b1}); - assign alignicaf[1:0] = ({ 2{ f0val[1] }} & {{2{f0icaf}}}) | - ({ 2{~f0val[1] & f0val[0]}} & {f1icaf,f0icaf}); + assign alignicaf[1:0] = ({ 2{ f0val[1] }} & f0icaf[1:0] ) | + ({ 2{~f0val[1] & f0val[0]}} & {f1icaf[0],f0icaf[0]}); - assign aligndbecc[1:0] = ({ 2{ f0val[1] }} & {{2{f0dbecc}}}) | - ({ 2{~f0val[1] & f0val[0]}} & {f1dbecc,f0dbecc}); + assign aligndbecc[1:0] = ({ 2{ f0val[1] }} & f0dbecc[1:0] ) | + ({ 2{~f0val[1] & f0val[0]}} & {f1dbecc[0],f0dbecc[0]}); + + if (pt.BTB_ENABLE==1) begin // for branch prediction + assign alignbrend[1:0] = ({ 2{ f0val[1] }} & f0brend[1:0] ) | ({ 2{~f0val[1] & f0val[0]}} & {f1brend[0],f0brend[0]}); assign alignpc4[1:0] = ({ 2{ f0val[1] }} & f0pc4[1:0] ) | ({ 2{~f0val[1] & f0val[0]}} & {f1pc4[0],f0pc4[0]}); + if(pt.BTB_FULLYA) begin + assign alignindex[0] = f0index[0]; + assign alignindex[1] = f0val[1] ? f0index[1] : f1index[0]; + end assign alignret[1:0] = ({ 2{ f0val[1] }} & f0ret[1:0] ) | ({ 2{~f0val[1] & f0val[0]}} & {f1ret[0],f0ret[0]}); @@ -481,20 +526,23 @@ import el2_pkg::*; assign alignhist0[1:0] = ({ 2{ f0val[1] }} & f0hist0[1:0] ) | ({ 2{~f0val[1] & f0val[0]}} & {f1hist0[0],f0hist0[0]}); + assign secondpc[31:1] = ({31{ f0val[1] }} & (q0pceff[31:1] + 31'd1)) | + // you need the base pc for 2nd one only (4B max, 2B for the 1st and 2B for the 2nd) + ({31{~f0val[1] & f0val[0]}} & q1pceff[31:1] ); + + + assign firstpc[31:1] = q0pcfinal[31:1]; + end // if (pt.BTB_ENABLE==1) + assign alignfromf1[1] = ~f0val[1] & f0val[0]; - assign secondpc[31:1] = ({31{ f0val[1] }} & f0pc_plus1[31:1]) | - ({31{~f0val[1] & f0val[0]}} & f1pc[31:1] ); + assign ifu_i0_pc[31:1] = q0pcfinal[31:1]; - assign ifu_i0_pc[31:1] = f0pc[31:1]; - - assign firstpc[31:1] = f0pc[31:1]; assign ifu_i0_pc4 = first4B; - assign ifu_i0_cinst[15:0] = aligndata[15:0]; assign first4B = (aligndata[1:0] == 2'b11); @@ -510,9 +558,9 @@ import el2_pkg::*; assign ifu_i0_icaf_type[1:0] = (first4B & ~f0val[1] & f0val[0] & ~alignicaf[0] & ~aligndbecc[0]) ? f1ictype[1:0] : f0ictype[1:0]; - assign icaf_eff[1] = alignicaf[1] | aligndbecc[1]; + assign icaf_eff[1:0] = alignicaf[1:0] | aligndbecc[1:0]; - assign ifu_i0_icaf_f1 = first4B & icaf_eff[1] & alignfromf1[1]; + assign ifu_i0_icaf_second = first4B & ~icaf_eff[0] & icaf_eff[1]; assign ifu_i0_dbecc = (first4B & (|aligndbecc[1:0])) | (first2B & aligndbecc[0] ); @@ -521,23 +569,38 @@ import el2_pkg::*; assign ifirst[31:0] = aligndata[31:0]; - assign ifu_i0_instr[31:0] = ({32{first4B}} & ifirst[31:0]) | - ({32{first2B}} & uncompress0[31:0]); + assign ifu_i0_instr[31:0] = ({32{first4B & alignval[1]}} & ifirst[31:0]) | + ({32{first2B & alignval[0]}} & uncompress0[31:0]); +if(pt.BTB_ENABLE==1) begin // if you detect br does not start on instruction boundary - el2_btb_addr_hash #(.pt(pt)) firsthash (.pc(firstpc [pt.BTB_INDEX3_HI:pt.BTB_INDEX1_LO]), .hash(firstpc_hash [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO])); - el2_btb_addr_hash #(.pt(pt)) secondhash(.pc(secondpc[pt.BTB_INDEX3_HI:pt.BTB_INDEX1_LO]), .hash(secondpc_hash[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO])); + el2_btb_addr_hash #(.pt(pt)) firsthash (.pc(firstpc [pt.BTB_INDEX3_HI:pt.BTB_INDEX1_LO]), + .hash(firstpc_hash [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO])); + el2_btb_addr_hash #(.pt(pt)) secondhash(.pc(secondpc[pt.BTB_INDEX3_HI:pt.BTB_INDEX1_LO]), + .hash(secondpc_hash[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO])); + + if(pt.BTB_FULLYA) begin + assign firstbrtag_hash = firstpc; + assign secondbrtag_hash = secondpc; + end + else begin + if(pt.BTB_BTAG_FOLD) begin : btbfold + el2_btb_tag_hash_fold #(.pt(pt)) first_brhash (.pc(firstpc [pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), + .hash(firstbrtag_hash [pt.BTB_BTAG_SIZE-1:0])); + el2_btb_tag_hash_fold #(.pt(pt)) second_brhash(.pc(secondpc[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), + .hash(secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0])); + end + else begin + el2_btb_tag_hash #(.pt(pt)) first_brhash (.pc(firstpc [pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), + .hash(firstbrtag_hash [pt.BTB_BTAG_SIZE-1:0])); + el2_btb_tag_hash #(.pt(pt)) second_brhash(.pc(secondpc[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), + .hash(secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0])); + end + end // else: !if(pt.BTB_FULLYA) + -if(pt.BTB_BTAG_FOLD) begin : btbfold - el2_btb_tag_hash_fold #(.pt(pt)) first_brhash (.pc(firstpc [pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), .hash(firstbrtag_hash [pt.BTB_BTAG_SIZE-1:0])); - el2_btb_tag_hash_fold #(.pt(pt)) second_brhash(.pc(secondpc[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), .hash(secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0])); -end -else begin - el2_btb_tag_hash #(.pt(pt)) first_brhash (.pc(firstpc [pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), .hash(firstbrtag_hash [pt.BTB_BTAG_SIZE-1:0])); - el2_btb_tag_hash #(.pt(pt)) second_brhash(.pc(secondpc[pt.BTB_ADDR_HI+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE+pt.BTB_BTAG_SIZE:pt.BTB_ADDR_HI+1]), .hash(secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0])); -end // start_indexing - you want pc to be based on where the end of branch is prediction // normal indexing pc based that's incorrect now for pc4 cases it's pc4 + 2 @@ -578,7 +641,12 @@ end i0_brp.br_error = (i0_brp.valid & i0_brp_pc4 & first2B) | (i0_brp.valid & ~i0_brp_pc4 & first4B); - end + if(pt.BTB_FULLYA) + ifu_i0_fa_index = (first2B | alignbrend[0]) ? alignindex[0] : alignindex[1]; + else + ifu_i0_fa_index = '0; + + end assign ifu_i0_bp_index[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] = (first2B | alignbrend[0]) ? firstpc_hash[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] : @@ -589,11 +657,18 @@ end assign ifu_i0_bp_btag[pt.BTB_BTAG_SIZE-1:0] = (first2B | alignbrend[0]) ? firstbrtag_hash[pt.BTB_BTAG_SIZE-1:0] : secondbrtag_hash[pt.BTB_BTAG_SIZE-1:0]; - +end +else begin + assign i0_brp = '0; + assign ifu_i0_bp_index = '0; + assign ifu_i0_bp_fghr = '0; + assign ifu_i0_bp_btag = '0; +end // else: !if(pt.BTB_ENABLE==1) // decompress - el2_ifu_compress_ctl compress0 (.din(aligndata[15:0]), .dout(uncompress0[31:0])); + // quiet inputs for 4B inst + el2_ifu_compress_ctl compress0 (.din((first2B) ? aligndata[15:0] : '0), .dout(uncompress0[31:0])); @@ -604,8 +679,6 @@ end // compute how many bytes are being shifted from f0 - // assign shift_0B = ~i0_shift; - assign shift_2B = i0_shift & first2B; assign shift_4B = i0_shift & first4B; diff --git a/design/ifu/el2_ifu_bp_ctl.sv b/design/ifu/el2_ifu_bp_ctl.sv index ad1c501..6c2f6e5 100644 --- a/design/ifu/el2_ifu_bp_ctl.sv +++ b/design/ifu/el2_ifu_bp_ctl.sv @@ -1,6 +1,6 @@ //******************************************************************************** // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -32,7 +32,6 @@ import el2_pkg::*; ( input logic clk, - input logic active_clk, input logic rst_l, input logic ic_hit_f, // Icache hit, enables F address capture @@ -44,6 +43,8 @@ import el2_pkg::*; input logic [pt.BHT_GHR_SIZE-1:0] exu_i0_br_fghr_r, // fghr to bp input logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] exu_i0_br_index_r, // bp index + input logic [$clog2(pt.BTB_SIZE)-1:0] dec_fa_error_index, // Fully associative btb error index + input logic dec_tlu_flush_lower_wb, // used to move EX4 RS to EX1 and F input logic dec_tlu_flush_leak_one_wb, // don't hit for leak one fetches @@ -72,10 +73,21 @@ import el2_pkg::*; output logic [1:0] ifu_bp_valid_f, // branch valid, right justified output logic [11:0] ifu_bp_poffset_f, // predicted target + output logic [1:0] [$clog2(pt.BTB_SIZE)-1:0] ifu_bp_fa_index_f, // predicted branch index (fully associative option) + input logic scan_mode ); - localparam TAG_START=16+pt.BTB_BTAG_SIZE; + + localparam BTB_DWIDTH = pt.BTB_TOFFSET_SIZE+pt.BTB_BTAG_SIZE+5; + localparam BTB_DWIDTH_TOP = int'(pt.BTB_TOFFSET_SIZE)+int'(pt.BTB_BTAG_SIZE)+4; + localparam BTB_FA_INDEX = $clog2(pt.BTB_SIZE)-1; + localparam FA_CMP_LOWER = $clog2(pt.ICACHE_LN_SZ); + localparam FA_TAG_END_UPPER= 5+int'(pt.BTB_TOFFSET_SIZE)+int'(FA_CMP_LOWER)-1; // must cast to int or vcs build fails + localparam FA_TAG_START_LOWER = 3+int'(pt.BTB_TOFFSET_SIZE)+int'(FA_CMP_LOWER); + localparam FA_TAG_END_LOWER = 5+int'(pt.BTB_TOFFSET_SIZE); + + localparam TAG_START=BTB_DWIDTH-1; localparam PC4=4; localparam BOFF=3; localparam CALL=2; @@ -84,10 +96,11 @@ import el2_pkg::*; localparam LRU_SIZE=pt.BTB_ARRAY_DEPTH; localparam NUM_BHT_LOOP = (pt.BHT_ARRAY_DEPTH > 16 ) ? 16 : pt.BHT_ARRAY_DEPTH; - localparam NUM_BHT_LOOP_INNER_HI = (pt.BHT_ARRAY_DEPTH > 16 ) ? pt.BHT_ADDR_LO+3 : pt.BHT_ADDR_HI; - localparam NUM_BHT_LOOP_OUTER_LO = (pt.BHT_ARRAY_DEPTH > 16 ) ? pt.BHT_ADDR_LO+4 : pt.BHT_ADDR_LO; + localparam NUM_BHT_LOOP_INNER_HI = (pt.BHT_ARRAY_DEPTH > 16 ) ?pt.BHT_ADDR_LO+3 : pt.BHT_ADDR_HI; + localparam NUM_BHT_LOOP_OUTER_LO = (pt.BHT_ARRAY_DEPTH > 16 ) ?pt.BHT_ADDR_LO+4 : pt.BHT_ADDR_LO; localparam BHT_NO_ADDR_MATCH = ( pt.BHT_ARRAY_DEPTH <= 16 ); + logic exu_mp_valid_write; logic exu_mp_ataken; logic exu_mp_valid; // conditional branch mispredict @@ -120,13 +133,12 @@ import el2_pkg::*; logic rs_push, rs_pop, rs_hold; logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] btb_rd_addr_p1_f, btb_wr_addr, btb_rd_addr_f; logic [pt.BTB_BTAG_SIZE-1:0] btb_wr_tag, fetch_rd_tag_f, fetch_rd_tag_p1_f; - logic [16+pt.BTB_BTAG_SIZE:0] btb_wr_data; + logic [BTB_DWIDTH-1:0] btb_wr_data; logic btb_wr_en_way0, btb_wr_en_way1; logic dec_tlu_error_wb, btb_valid, dec_tlu_br0_middle_wb; logic [pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] btb_error_addr_wb; - logic branch_error_collision_f, fetch_mp_collision_f, branch_error_collision_p1_f, fetch_mp_collision_p1_f; logic branch_error_bank_conflict_f; @@ -142,17 +154,17 @@ import el2_pkg::*; logic leak_one_f, leak_one_f_d1; - logic [LRU_SIZE-1:0][16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way0_out ; + logic [LRU_SIZE-1:0][BTB_DWIDTH-1:0] btb_bank0_rd_data_way0_out ; - logic [LRU_SIZE-1:0][16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way1_out ; + logic [LRU_SIZE-1:0][BTB_DWIDTH-1:0] btb_bank0_rd_data_way1_out ; - logic [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way0_f ; - logic [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way1_f ; + logic [BTB_DWIDTH-1:0] btb_bank0_rd_data_way0_f ; + logic [BTB_DWIDTH-1:0] btb_bank0_rd_data_way1_f ; - logic [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way0_p1_f ; - logic [16+pt.BTB_BTAG_SIZE:0] btb_bank0_rd_data_way1_p1_f ; + logic [BTB_DWIDTH-1:0] btb_bank0_rd_data_way0_p1_f ; + logic [BTB_DWIDTH-1:0] btb_bank0_rd_data_way1_p1_f ; - logic [16+pt.BTB_BTAG_SIZE:0] btb_vbank0_rd_data_f, btb_vbank1_rd_data_f; + logic [BTB_DWIDTH-1:0] btb_vbank0_rd_data_f, btb_vbank1_rd_data_f; logic final_h; logic btb_fg_crossing_f; @@ -167,10 +179,10 @@ import el2_pkg::*; logic [31:2] fetch_addr_p1_f; - logic exu_mp_way, exu_mp_way_f, dec_tlu_br0_way_wb, dec_tlu_way_wb, dec_tlu_way_wb_f; - logic [16+pt.BTB_BTAG_SIZE:0] btb_bank0e_rd_data_f, btb_bank0e_rd_data_p1_f; + logic exu_mp_way, exu_mp_way_f, dec_tlu_br0_way_wb, dec_tlu_way_wb; + logic [BTB_DWIDTH-1:0] btb_bank0e_rd_data_f, btb_bank0e_rd_data_p1_f; - logic [16+pt.BTB_BTAG_SIZE:0] btb_bank0o_rd_data_f; + logic [BTB_DWIDTH-1:0] btb_bank0o_rd_data_f; logic [1:0] tag_match_way0_expanded_f, tag_match_way1_expanded_f; @@ -178,7 +190,7 @@ import el2_pkg::*; logic [1:0] bht_bank0_rd_data_f; logic [1:0] bht_bank1_rd_data_f; logic [1:0] bht_bank0_rd_data_p1_f; -logic exu_flush_final_d1; + genvar j, i; assign exu_mp_valid = exu_mp_pkt.misp & ~leak_one_f; // conditional branch mispredict assign exu_mp_boffset = exu_mp_pkt.boffset; // branch offset @@ -229,6 +241,12 @@ logic exu_flush_final_d1; assign branch_error_bank_conflict_f = branch_error_collision_f & dec_tlu_error_wb; assign branch_error_bank_conflict_p1_f = branch_error_collision_p1_f & dec_tlu_error_wb; + // set on leak one, hold until next flush without leak one + assign leak_one_f = (dec_tlu_flush_leak_one_wb & dec_tlu_flush_lower_wb) | (leak_one_f_d1 & ~dec_tlu_flush_lower_wb); + +logic exu_flush_final_d1; + + if(!pt.BTB_FULLYA) begin assign fetch_mp_collision_f = ( (exu_mp_btag[pt.BTB_BTAG_SIZE-1:0] == fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]) & exu_mp_valid & ifc_fetch_req_f & (exu_mp_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] == btb_rd_addr_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]) @@ -237,26 +255,18 @@ logic exu_flush_final_d1; exu_mp_valid & ifc_fetch_req_f & (exu_mp_addr[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO] == btb_rd_addr_p1_f[pt.BTB_ADDR_HI:pt.BTB_ADDR_LO]) ); - // set on leak one, hold until next flush without leak one - assign leak_one_f = (dec_tlu_flush_leak_one_wb & dec_tlu_flush_lower_wb) | (leak_one_f_d1 & ~dec_tlu_flush_lower_wb); - - - rvdff #(4) coll_ff (.*, .clk(active_clk), - .din({exu_flush_final, exu_mp_way, dec_tlu_way_wb, leak_one_f}), - .dout({exu_flush_final_d1, exu_mp_way_f, dec_tlu_way_wb_f, leak_one_f_d1})); - // 2 -way SA, figure out the way hit and mux accordingly assign tag_match_way0_f = btb_bank0_rd_data_way0_f[BV] & (btb_bank0_rd_data_way0_f[TAG_START:17] == fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]) & - ~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & ifc_fetch_req_f & ~leak_one_f; + ~(dec_tlu_way_wb & branch_error_bank_conflict_f) & ifc_fetch_req_f & ~leak_one_f; assign tag_match_way1_f = btb_bank0_rd_data_way1_f[BV] & (btb_bank0_rd_data_way1_f[TAG_START:17] == fetch_rd_tag_f[pt.BTB_BTAG_SIZE-1:0]) & - ~(dec_tlu_way_wb_f & branch_error_bank_conflict_f) & ifc_fetch_req_f & ~leak_one_f; + ~(dec_tlu_way_wb & branch_error_bank_conflict_f) & ifc_fetch_req_f & ~leak_one_f; assign tag_match_way0_p1_f = btb_bank0_rd_data_way0_p1_f[BV] & (btb_bank0_rd_data_way0_p1_f[TAG_START:17] == fetch_rd_tag_p1_f[pt.BTB_BTAG_SIZE-1:0]) & - ~(dec_tlu_way_wb_f & branch_error_bank_conflict_p1_f) & ifc_fetch_req_f & ~leak_one_f; + ~(dec_tlu_way_wb & branch_error_bank_conflict_p1_f) & ifc_fetch_req_f & ~leak_one_f; assign tag_match_way1_p1_f = btb_bank0_rd_data_way1_p1_f[BV] & (btb_bank0_rd_data_way1_p1_f[TAG_START:17] == fetch_rd_tag_p1_f[pt.BTB_BTAG_SIZE-1:0]) & - ~(dec_tlu_way_wb_f & branch_error_bank_conflict_p1_f) & ifc_fetch_req_f & ~leak_one_f; + ~(dec_tlu_way_wb & branch_error_bank_conflict_p1_f) & ifc_fetch_req_f & ~leak_one_f; // Both ways could hit, use the offset bit to reorder @@ -276,21 +286,22 @@ logic exu_flush_final_d1; assign wayhit_f[1:0] = tag_match_way0_expanded_f[1:0] | tag_match_way1_expanded_f[1:0]; assign wayhit_p1_f[1:0] = tag_match_way0_expanded_p1_f[1:0] | tag_match_way1_expanded_p1_f[1:0]; - assign btb_bank0o_rd_data_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_f[1]}} & btb_bank0_rd_data_way0_f[16+pt.BTB_BTAG_SIZE:0]) | - ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_f[1]}} & btb_bank0_rd_data_way1_f[16+pt.BTB_BTAG_SIZE:0]) ); - assign btb_bank0e_rd_data_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_f[0]}} & btb_bank0_rd_data_way0_f[16+pt.BTB_BTAG_SIZE:0]) | - ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_f[0]}} & btb_bank0_rd_data_way1_f[16+pt.BTB_BTAG_SIZE:0]) ); + assign btb_bank0o_rd_data_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_f[1]}} & btb_bank0_rd_data_way0_f[BTB_DWIDTH-1:0]) | + ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_f[1]}} & btb_bank0_rd_data_way1_f[BTB_DWIDTH-1:0]) ); + assign btb_bank0e_rd_data_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_f[0]}} & btb_bank0_rd_data_way0_f[BTB_DWIDTH-1:0]) | + ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_f[0]}} & btb_bank0_rd_data_way1_f[BTB_DWIDTH-1:0]) ); - assign btb_bank0e_rd_data_p1_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_p1_f[0]}} & btb_bank0_rd_data_way0_p1_f[16+pt.BTB_BTAG_SIZE:0]) | - ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_p1_f[0]}} & btb_bank0_rd_data_way1_p1_f[16+pt.BTB_BTAG_SIZE:0]) ); + assign btb_bank0e_rd_data_p1_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{tag_match_way0_expanded_p1_f[0]}} & btb_bank0_rd_data_way0_p1_f[BTB_DWIDTH-1:0]) | + ({17+pt.BTB_BTAG_SIZE{tag_match_way1_expanded_p1_f[0]}} & btb_bank0_rd_data_way1_p1_f[BTB_DWIDTH-1:0]) ); // virtual bank order - assign btb_vbank0_rd_data_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{fetch_start_f[0]}} & btb_bank0e_rd_data_f[16+pt.BTB_BTAG_SIZE:0]) | - ({17+pt.BTB_BTAG_SIZE{fetch_start_f[1]}} & btb_bank0o_rd_data_f[16+pt.BTB_BTAG_SIZE:0]) ); - assign btb_vbank1_rd_data_f[16+pt.BTB_BTAG_SIZE:0] = ( ({17+pt.BTB_BTAG_SIZE{fetch_start_f[0]}} & btb_bank0o_rd_data_f[16+pt.BTB_BTAG_SIZE:0]) | - ({17+pt.BTB_BTAG_SIZE{fetch_start_f[1]}} & btb_bank0e_rd_data_p1_f[16+pt.BTB_BTAG_SIZE:0]) ); + assign btb_vbank0_rd_data_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{fetch_start_f[0]}} & btb_bank0e_rd_data_f[BTB_DWIDTH-1:0]) | + ({17+pt.BTB_BTAG_SIZE{fetch_start_f[1]}} & btb_bank0o_rd_data_f[BTB_DWIDTH-1:0]) ); + assign btb_vbank1_rd_data_f[BTB_DWIDTH-1:0] = ( ({17+pt.BTB_BTAG_SIZE{fetch_start_f[0]}} & btb_bank0o_rd_data_f[BTB_DWIDTH-1:0]) | + ({17+pt.BTB_BTAG_SIZE{fetch_start_f[1]}} & btb_bank0e_rd_data_p1_f[BTB_DWIDTH-1:0]) ); + assign way_raw[1:0] = tag_match_vway1_expanded_f[1:0] | (~vwayhit_f[1:0] & btb_vlru_rd_f[1:0]); // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- @@ -306,8 +317,12 @@ logic exu_flush_final_d1; assign mp_wrlru_b0[LRU_SIZE-1:0] = mp_wrindex_dec[LRU_SIZE-1:0] & {LRU_SIZE{exu_mp_valid}}; - genvar j, i; + assign btb_lru_b0_hold[LRU_SIZE-1:0] = ~mp_wrlru_b0[LRU_SIZE-1:0] & ~fetch_wrlru_b0[LRU_SIZE-1:0]; + + // Forward the mp lru information to the fetch, avoids multiple way hits later + assign use_mp_way = fetch_mp_collision_f; + assign use_mp_way_p1 = fetch_mp_collision_p1_f; assign lru_update_valid_f = (vwayhit_f[0] | vwayhit_f[1]) & ifc_fetch_req_f & ~leak_one_f; @@ -317,18 +332,13 @@ logic exu_flush_final_d1; assign fetch_wrlru_p1_b0[LRU_SIZE-1:0] = fetch_wrindex_p1_dec[LRU_SIZE-1:0] & {LRU_SIZE{lru_update_valid_f}}; - assign btb_lru_b0_hold[LRU_SIZE-1:0] = ~mp_wrlru_b0[LRU_SIZE-1:0] & ~fetch_wrlru_b0[LRU_SIZE-1:0]; - - // Forward the mp lru information to the fetch, avoids multiple way hits later - assign use_mp_way = fetch_mp_collision_f; - assign use_mp_way_p1 = fetch_mp_collision_p1_f; - - assign btb_lru_b0_ns[LRU_SIZE-1:0] = ( (btb_lru_b0_hold[LRU_SIZE-1:0] & btb_lru_b0_f[LRU_SIZE-1:0]) | (mp_wrlru_b0[LRU_SIZE-1:0] & {LRU_SIZE{~exu_mp_way}}) | (fetch_wrlru_b0[LRU_SIZE-1:0] & {LRU_SIZE{tag_match_way0_f}}) | (fetch_wrlru_p1_b0[LRU_SIZE-1:0] & {LRU_SIZE{tag_match_way0_p1_f}}) ); + + assign btb_lru_rd_f = use_mp_way ? exu_mp_way_f : |(fetch_wrindex_dec[LRU_SIZE-1:0] & btb_lru_b0_f[LRU_SIZE-1:0]); assign btb_lru_rd_p1_f = use_mp_way_p1 ? exu_mp_way_f : |(fetch_wrindex_p1_dec[LRU_SIZE-1:0] & btb_lru_b0_f[LRU_SIZE-1:0]); @@ -340,12 +350,12 @@ logic exu_flush_final_d1; assign tag_match_vway1_expanded_f[1:0] = ( ({2{fetch_start_f[0]}} & {tag_match_way1_expanded_f[1:0]}) | ({2{fetch_start_f[1]}} & {tag_match_way1_expanded_p1_f[0], tag_match_way1_expanded_f[1]}) ); - assign way_raw[1:0] = tag_match_vway1_expanded_f[1:0] | (~vwayhit_f[1:0] & btb_vlru_rd_f[1:0]); rvdffe #(LRU_SIZE) btb_lru_ff (.*, .en(ifc_fetch_req_f | exu_mp_valid), .din(btb_lru_b0_ns[(LRU_SIZE)-1:0]), .dout(btb_lru_b0_f[(LRU_SIZE)-1:0])); + end // if (!pt.BTB_FULLYA) // Detect end of cache line and mask as needed logic eoc_near; logic eoc_mask; @@ -353,8 +363,6 @@ logic exu_flush_final_d1; assign eoc_mask = ~eoc_near| (|(~ifc_fetch_addr_f[2:1])); - assign vwayhit_f[1:0] = ( ({2{fetch_start_f[0]}} & {wayhit_f[1:0]}) | - ({2{fetch_start_f[1]}} & {wayhit_p1_f[0], wayhit_f[1]})) & {eoc_mask, 1'b1}; // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- @@ -456,7 +464,10 @@ logic exu_flush_final_d1; ({pt.BHT_GHR_SIZE{~exu_flush_final_d1 & ifc_fetch_req_f & ic_hit_f & ~leak_one_f_d1}} & merged_ghr[pt.BHT_GHR_SIZE-1:0]) | ({pt.BHT_GHR_SIZE{~exu_flush_final_d1 & ~(ifc_fetch_req_f & ic_hit_f & ~leak_one_f_d1)}} & fghr[pt.BHT_GHR_SIZE-1:0])); - rvdff #(pt.BHT_GHR_SIZE) fetchghr (.*, .clk(active_clk), .din(fghr_ns[pt.BHT_GHR_SIZE-1:0]), .dout(fghr[pt.BHT_GHR_SIZE-1:0])); + rvdffie #(.WIDTH(pt.BHT_GHR_SIZE+3),.OVERRIDE(1)) fetchghr (.*, + .din ({exu_flush_final, exu_mp_way, leak_one_f, fghr_ns[pt.BHT_GHR_SIZE-1:0]}), + .dout({exu_flush_final_d1, exu_mp_way_f, leak_one_f_d1, fghr[pt.BHT_GHR_SIZE-1:0]})); + assign ifu_bp_fghr_f[pt.BHT_GHR_SIZE-1:0] = fghr[pt.BHT_GHR_SIZE-1:0]; @@ -502,7 +513,8 @@ assign use_fa_plus = (~bht_dir_f[0] & ~fetch_start_f[0] & ~btb_rd_pc4_f); assign bp_total_branch_offset_f = bloc_f[1] ^ btb_rd_pc4_f; logic [31:2] adder_pc_in_f, ifc_fetch_adder_prior; - rvdffe #(30) faddrf_ff (.*, .en(ifc_fetch_req_f & ~ifu_bp_hit_taken_f & ic_hit_f), .din(ifc_fetch_addr_f[31:2]), .dout(ifc_fetch_adder_prior[31:2])); + rvdfflie #(.WIDTH(30), .LEFT(19)) faddrf_ff (.*, .en(ifc_fetch_req_f & ~ifu_bp_hit_taken_f & ic_hit_f), .din(ifc_fetch_addr_f[31:2]), .dout(ifc_fetch_adder_prior[31:2])); + assign ifu_bp_poffset_f[11:0] = btb_rd_tgt_f[11:0]; @@ -514,8 +526,9 @@ assign use_fa_plus = (~bht_dir_f[0] & ~fetch_start_f[0] & ~btb_rd_pc4_f); .offset(btb_rd_tgt_f[11:0]), .dout(bp_btb_target_adder_f[31:1]) ); - // mux in the return stack address here for a predicted return assuming the RS is valid - assign ifu_bp_btb_target_f[31:1] = (btb_rd_ret_f & ~btb_rd_call_f & rets_out[0][0]) ? rets_out[0][31:1] : bp_btb_target_adder_f[31:1]; + // mux in the return stack address here for a predicted return assuming the RS is valid, quite if no prediction + assign ifu_bp_btb_target_f[31:1] = (({31{btb_rd_ret_f & ~btb_rd_call_f & rets_out[0][0] & ifu_bp_hit_taken_f}} & rets_out[0][31:1]) | + ({31{~(btb_rd_ret_f & ~btb_rd_call_f & rets_out[0][0]) & ifu_bp_hit_taken_f}} & bp_btb_target_adder_f[31:1]) ); // ---------------------------------------------------------------------- @@ -539,7 +552,7 @@ assign use_fa_plus = (~bht_dir_f[0] & ~fetch_start_f[0] & ~btb_rd_pc4_f); assign rsenable[0] = ~rs_hold; - for (i=0; i<32'(pt.RET_STACK_SIZE); i++) begin : retstack + for (i=0; i tag[pt.BTB_BTAG_SIZE-1:0], toffset[11:0], pc4, boffset, call, ret, valid + if(!pt.BTB_FULLYA) begin - for (j=0 ; j<32'(LRU_SIZE) ; j++) begin : BTB_FLOPS - // Way 0 - rvdffe #(17+pt.BTB_BTAG_SIZE) btb_bank0_way0 (.*, + for (j=0 ; j> (16*iccm_rd_addr_lo_q[1]))}); diff --git a/design/ifu/el2_ifu_ifc_ctl.sv b/design/ifu/el2_ifu_ifc_ctl.sv index 33c1401..3ab758e 100644 --- a/design/ifu/el2_ifu_ifc_ctl.sv +++ b/design/ifu/el2_ifu_ifc_ctl.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,9 +26,8 @@ import el2_pkg::*; `include "el2_param.vh" ) ( - input logic clk, - input logic free_clk, - input logic active_clk, + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in. input logic rst_l, // reset enable, from core pin input logic scan_mode, // scan @@ -76,7 +75,7 @@ import el2_pkg::*; logic fb_full_f_ns, fb_full_f; logic fb_right, fb_right2, fb_left, wfm, idle; - logic sel_last_addr_bf, sel_btb_addr_bf, sel_next_addr_bf; + logic sel_last_addr_bf, sel_next_addr_bf; logic miss_f, miss_a; logic flush_fb, dma_iccm_stall_any_f; logic mb_empty_mod, goto_idle, leave_idle; @@ -95,13 +94,15 @@ import el2_pkg::*; logic dma_stall; assign dma_stall = ic_dma_active | dma_iccm_stall_any_f; - rvdff #(2) ran_ff (.*, .clk(free_clk), .din({dma_iccm_stall_any, miss_f}), .dout({dma_iccm_stall_any_f, miss_a})); + // Fetch address mux // - flush // - Miss *or* flush during WFM (icache miss buffer is blocking) // - Sequential +if(pt.BTB_ENABLE==1) begin + logic sel_btb_addr_bf; assign sel_last_addr_bf = ~exu_flush_final & (~ifc_fetch_req_f | ~ic_hit_f); assign sel_btb_addr_bf = ~exu_flush_final & ifc_fetch_req_f & ifu_bp_hit_taken_f & ic_hit_f; @@ -114,6 +115,17 @@ import el2_pkg::*; ({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path +end // if (pt.BTB_ENABLE=1) + else begin + assign sel_last_addr_bf = ~exu_flush_final & (~ifc_fetch_req_f | ~ic_hit_f); + assign sel_next_addr_bf = ~exu_flush_final & ifc_fetch_req_f & ic_hit_f; + + + assign fetch_addr_bf[31:1] = ( ({31{exu_flush_final}} & exu_flush_path_final[31:1]) | // FLUSH path + ({31{sel_last_addr_bf}} & ifc_fetch_addr_f[31:1]) | // MISS path + ({31{sel_next_addr_bf}} & {fetch_addr_next[31:1]})); // SEQ path + +end assign fetch_addr_next[31:1] = {({ifc_fetch_addr_f[31:2]} + 31'b1), fetch_addr_next_1 }; assign line_wrap = (fetch_addr_next[pt.ICACHE_TAG_INDEX_LO] ^ ifc_fetch_addr_f[pt.ICACHE_TAG_INDEX_LO]); @@ -186,8 +198,9 @@ import el2_pkg::*; assign idle = state == IDLE ; assign wfm = state == WFM ; - rvdff #(2) fsm_ff (.*, .clk(active_clk), .din({next_state[1:0]}), .dout({state[1:0]})); - rvdff #(5) fbwrite_ff (.*, .clk(active_clk), .din({fb_full_f_ns, fb_write_ns[3:0]}), .dout({fb_full_f, fb_write_f[3:0]})); + rvdffie #(10) fbwrite_ff (.*, .clk(free_l2clk), + .din( {dma_iccm_stall_any, miss_f, ifc_fetch_req_bf, next_state[1:0], fb_full_f_ns, fb_write_ns[3:0]}), + .dout({dma_iccm_stall_any_f, miss_a, ifc_fetch_req_f, state[1:0], fb_full_f, fb_write_f[3:0]})); assign ifu_pmu_fetch_stall = wfm | (ifc_fetch_req_bf_raw & @@ -195,11 +208,10 @@ import el2_pkg::*; dma_stall)); - rvdff #(1) req_ff (.*, .clk(active_clk), .din(ifc_fetch_req_bf), .dout(ifc_fetch_req_f)); assign ifc_fetch_addr_bf[31:1] = fetch_addr_bf[31:1]; - rvdffe #(31) faddrf1_ff (.*, .en(fetch_bf_en), .din(fetch_addr_bf[31:1]), .dout(ifc_fetch_addr_f[31:1])); + rvdffpcie #(31) faddrf1_ff (.*, .en(fetch_bf_en), .din(fetch_addr_bf[31:1]), .dout(ifc_fetch_addr_f[31:1])); if (pt.ICCM_ENABLE) begin diff --git a/design/ifu/el2_ifu_mem_ctl.sv b/design/ifu/el2_ifu_mem_ctl.sv index 7781068..3ca8222 100644 --- a/design/ifu/el2_ifu_mem_ctl.sv +++ b/design/ifu/el2_ifu_mem_ctl.sv @@ -1,6 +1,6 @@ - //******************************************************************************** +//******************************************************************************** // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,18 +27,18 @@ import el2_pkg::*; `include "el2_param.vh" ) ( - input logic clk, - input logic free_clk, // free clock always except during pause - input logic active_clk, // Active always except during pause - input logic rst_l, + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in. + input logic free_l2clk, // Clock always. Through one clock header. For flops with second header built in. + input logic rst_l, // reset, active low input logic exu_flush_final, // Flush from the pipeline., includes flush lower input logic dec_tlu_flush_lower_wb, // Flush lower from the pipeline. input logic dec_tlu_flush_err_wb, // Flush from the pipeline due to perr. - input logic dec_tlu_i0_commit_cmt, // committed i0 instruction - input logic dec_tlu_force_halt, // force halt. + input logic dec_tlu_i0_commit_cmt, // committed i0 instruction + input logic dec_tlu_force_halt, // force halt. - input logic [31:1] ifc_fetch_addr_bf, // Fetch Address byte aligned always. F1 stage. + input logic [31:1] ifc_fetch_addr_bf, // Fetch Address byte aligned always. F1 stage. input logic ifc_fetch_uncacheable_bf, // The fetch request is uncacheable space. F1 stage input logic ifc_fetch_req_bf, // Fetch request. Comes with the address. F1 stage input logic ifc_fetch_req_bf_raw, // Fetch request without some qualifications. Used for clock-gating. F1 stage @@ -46,7 +46,7 @@ import el2_pkg::*; input logic ifc_region_acc_fault_bf, // Access fault. in ICCM region but offset is outside defined ICCM. input logic ifc_dma_access_ok, // It is OK to give dma access to the ICCM. (ICCM is not busy this cycle). input logic dec_tlu_fence_i_wb, // Fence.i instruction is committing. Clear all Icache valids. - input logic ifu_bp_hit_taken_f, // Branch is predicted taken. Kill the fetch next cycle. + input logic ifu_bp_hit_taken_f, // Branch is predicted taken. Kill the fetch next cycle. input logic ifu_bp_inst_mask_f, // tell ic which valids to kill because of a taken branch, right justified @@ -160,10 +160,10 @@ import el2_pkg::*; input logic [1:0] ifu_fetch_val, // IFU control signals output logic ic_hit_f, // Hit in Icache(if Icache access) or ICCM access( ICCM always has ic_hit_f) - output logic ic_access_fault_f, // Access fault (bus error or ICCM access in region but out of offset range). + output logic [1:0] ic_access_fault_f, // Access fault (bus error or ICCM access in region but out of offset range). output logic [1:0] ic_access_fault_type_f, // Access fault types output logic iccm_rd_ecc_single_err, // This fetch has a single ICCM ecc error. - output logic iccm_rd_ecc_double_err, // This fetch has a double ICCM ecc error. + output logic [1:0] iccm_rd_ecc_double_err, // This fetch has a double ICCM ecc error. output logic ic_error_start, // This has any I$ errors ( data/tag/ecc/parity ) output logic ifu_async_error_start, // Or of the sb iccm, and all the icache errors sent to aligner to stop @@ -184,7 +184,6 @@ import el2_pkg::*; input logic scan_mode ); - // Create different defines for ICACHE and ICCM enable combinations localparam NUM_OF_BEATS = 8 ; @@ -219,6 +218,7 @@ import el2_pkg::*; logic ifu_wr_data_comb_err ; logic ifu_byp_data_err_new; + logic [1:0] ifu_byp_data_err_f; logic ifu_wr_cumulative_err_data; logic ifu_wr_cumulative_err; logic ifu_wr_data_comb_err_ff; @@ -229,7 +229,7 @@ import el2_pkg::*; logic ifc_iccm_access_f ; logic ifc_region_acc_fault_f; logic ifc_region_acc_fault_final_f; - logic ifc_bus_acc_fault_f; + logic [1:0] ifc_bus_acc_fault_f; logic ic_act_miss_f; logic ic_miss_under_miss_f; logic ic_ignore_2nd_miss_f; @@ -312,14 +312,12 @@ import el2_pkg::*; logic ifu_pmu_bus_busy_in; logic ic_debug_ict_array_sel_in; logic ic_debug_ict_array_sel_ff; - logic debug_data_clk; logic debug_data_clken; logic last_data_recieved_in ; logic last_data_recieved_ff ; logic ifu_bus_rvalid ; logic ifu_bus_rvalid_ff ; - logic ifu_bus_rvalid_unq ; logic ifu_bus_rvalid_unq_ff ; logic ifu_bus_arready_unq ; logic ifu_bus_arready_unq_ff ; @@ -335,28 +333,28 @@ import el2_pkg::*; logic [63:0] ifu_bus_rsp_rdata; logic [1:0] ifu_bus_rsp_opc; - logic [pt.ICACHE_NUM_BEATS-1:0] write_fill_data; - logic [pt.ICACHE_NUM_BEATS-1:0] wr_data_c1_clk; - logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_valid_in; - logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_valid; - logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_error_in; - logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_error; - logic [pt.ICACHE_BEAT_ADDR_HI:1] byp_fetch_index; - logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_0; - logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_1; - logic [pt.ICACHE_BEAT_ADDR_HI:3] byp_fetch_index_inc; - logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_inc_0; - logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_inc_1; - logic miss_buff_hit_unq_f ; - logic stream_hit_f ; - logic stream_miss_f ; - logic stream_eol_f ; - logic crit_byp_hit_f ; - logic [pt.IFU_BUS_TAG-1:0] other_tag ; - logic [(2*pt.ICACHE_NUM_BEATS)-1:0] [31:0] ic_miss_buff_data; - logic [63:0] ic_miss_buff_half; - logic scnd_miss_req, scnd_miss_req_q, scnd_miss_req_ff2; - logic scnd_miss_req_in; + logic [pt.ICACHE_NUM_BEATS-1:0] write_fill_data; + logic [pt.ICACHE_NUM_BEATS-1:0] wr_data_c1_clk; + logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_valid_in; + logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_valid; + logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_error_in; + logic [pt.ICACHE_NUM_BEATS-1:0] ic_miss_buff_data_error; + logic [pt.ICACHE_BEAT_ADDR_HI:1] byp_fetch_index; + logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_0; + logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_1; + logic [pt.ICACHE_BEAT_ADDR_HI:3] byp_fetch_index_inc; + logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_inc_0; + logic [pt.ICACHE_BEAT_ADDR_HI:2] byp_fetch_index_inc_1; + logic miss_buff_hit_unq_f ; + logic stream_hit_f ; + logic stream_miss_f ; + logic stream_eol_f ; + logic crit_byp_hit_f ; + logic [pt.IFU_BUS_TAG-1:0] other_tag ; + logic [(2*pt.ICACHE_NUM_BEATS)-1:0] [31:0] ic_miss_buff_data; + logic [63:0] ic_miss_buff_half; + logic scnd_miss_req, scnd_miss_req_q; + logic scnd_miss_req_in; logic [pt.ICCM_BITS-1:2] iccm_ecc_corr_index_ff; @@ -435,6 +433,7 @@ import el2_pkg::*; logic ic_crit_wd_rdy; // Critical fetch is ready to be bypassed. logic ifu_bp_hit_taken_q_f; + logic ifu_bus_rvalid_unq; logic bus_cmd_beat_en; @@ -443,11 +442,16 @@ import el2_pkg::*; assign fetch_bf_f_c1_clken = ifc_fetch_req_bf_raw | ifc_fetch_req_f | miss_pending | exu_flush_final | scnd_miss_req; - assign debug_c1_clken = ic_debug_rd_en | ic_debug_wr_en ; + assign debug_c1_clken = ic_debug_rd_en | ic_debug_wr_en ; // C1 - 1 clock pulse for data +`ifdef RV_FPGA_OPTIMIZE + assign fetch_bf_f_c1_clk = 1'b0; + assign debug_c1_clk = 1'b0; +`else + rvclkhdr fetch_bf_f_c1_cgc ( .en(fetch_bf_f_c1_clken), .l1clk(fetch_bf_f_c1_clk), .* ); + rvclkhdr debug_c1_cgc ( .en(debug_c1_clken), .l1clk(debug_c1_clk), .* ); +`endif - rvclkhdr fetch_bf_f_c1_cgc ( .en(fetch_bf_f_c1_clken), .l1clk(fetch_bf_f_c1_clk), .* ); - rvclkhdr debug_c1_cgc ( .en(debug_c1_clken), .l1clk(debug_c1_clk), .* ); // ------ end clock gating section ------------------------ @@ -529,7 +533,7 @@ import el2_pkg::*; end endcase end - rvdffs #(($bits(miss_state_t))) miss_state_ff (.clk(free_clk), .din(miss_nxtstate), .dout({miss_state}), .en(miss_state_en), .*); + rvdffs #(($bits(miss_state_t))) miss_state_ff (.clk(active_clk), .din(miss_nxtstate), .dout({miss_state}), .en(miss_state_en), .*); logic sel_hold_imb ; @@ -554,14 +558,14 @@ import el2_pkg::*; assign sel_hold_imb_scnd =((miss_state == SCND_MISS) | ic_miss_under_miss_f) & ~flush_final_f ; assign way_status_mb_scnd_in[pt.ICACHE_STATUS_BITS-1:0] = (miss_state == SCND_MISS) ? way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0] : {way_status[pt.ICACHE_STATUS_BITS-1:0]} ; - assign tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0] = (miss_state == SCND_MISS) ? tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0] : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags}}); + assign tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0] = (miss_state == SCND_MISS) ? tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0] : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags & ~exu_flush_final}}); assign uncacheable_miss_scnd_in = sel_hold_imb_scnd ? uncacheable_miss_scnd_ff : ifc_fetch_uncacheable_bf ; - rvdff #(1) unc_miss_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .din (uncacheable_miss_scnd_in), .dout(uncacheable_miss_scnd_ff)); - rvdff #(31) imb_f_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({imb_scnd_in[31:1]}), .dout({imb_scnd_ff[31:1]})); - rvdff #(pt.ICACHE_STATUS_BITS) mb_rep_wayf2_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({way_status_mb_scnd_in[pt.ICACHE_STATUS_BITS-1:0]}), .dout({way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0]})); - rvdff #(pt.ICACHE_NUM_WAYS) mb_tagv_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0]}), .dout({tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0]})); + rvdff_fpga #(1) unc_miss_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din (uncacheable_miss_scnd_in), .dout(uncacheable_miss_scnd_ff)); + rvdffpcie #(31) imb_f_scnd_ff (.*, .en(fetch_bf_f_c1_clken), .din ({imb_scnd_in[31:1]}), .dout({imb_scnd_ff[31:1]})); + rvdff_fpga #(pt.ICACHE_STATUS_BITS) mb_rep_wayf2_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din ({way_status_mb_scnd_in[pt.ICACHE_STATUS_BITS-1:0]}), .dout({way_status_mb_scnd_ff[pt.ICACHE_STATUS_BITS-1:0]})); + rvdff_fpga #(pt.ICACHE_NUM_WAYS) mb_tagv_scnd_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din ({tagv_mb_scnd_in[pt.ICACHE_NUM_WAYS-1:0]}), .dout({tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0]})); @@ -597,45 +601,40 @@ import el2_pkg::*; miss_pending ? way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0] : {way_status[pt.ICACHE_STATUS_BITS-1:0]} ; assign tagv_mb_in[pt.ICACHE_NUM_WAYS-1:0] = scnd_miss_req ? (tagv_mb_scnd_ff[pt.ICACHE_NUM_WAYS-1:0] | ({pt.ICACHE_NUM_WAYS {scnd_miss_index_match}} & replace_way_mb_any[pt.ICACHE_NUM_WAYS-1:0])) : - miss_pending ? tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0] : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags}}) ; + miss_pending ? tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0] : ({ic_tag_valid[pt.ICACHE_NUM_WAYS-1:0]} & {pt.ICACHE_NUM_WAYS{~reset_all_tags & ~exu_flush_final}}) ; assign reset_ic_in = miss_pending & ~scnd_miss_req_q & (reset_all_tags | reset_ic_ff) ; - rvdff #(1) reset_ic_f (.*, .clk(free_clk), .din (reset_ic_in), .dout(reset_ic_ff)); - rvdff #(1) uncache_ff (.*, .clk(active_clk), .din (ifc_fetch_uncacheable_bf), .dout(fetch_uncacheable_ff)); - - rvdff #(31) ifu_fetch_addr_f_ff (.*, - .clk (fetch_bf_f_c1_clk), - .din ({ifc_fetch_addr_bf[31:1]}), - .dout({ifu_fetch_addr_int_f[31:1]})); + rvdffpcie #(31) ifu_fetch_addr_f_ff (.*, .en(fetch_bf_f_c1_clken), .din ({ifc_fetch_addr_bf[31:1]}), .dout({ifu_fetch_addr_int_f[31:1]})); assign vaddr_f[pt.ICACHE_BEAT_ADDR_HI:1] = ifu_fetch_addr_int_f[pt.ICACHE_BEAT_ADDR_HI:1] ; - rvdff #(1) unc_miss_ff (.*, .clk(fetch_bf_f_c1_clk), .din (uncacheable_miss_in), .dout(uncacheable_miss_ff)); - rvdff #(31) imb_f_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({imb_in[31:1]}), .dout({imb_ff[31:1]})); + rvdffpcie #(31) imb_f_ff (.*, .en(fetch_bf_f_c1_clken), .din (imb_in[31:1]), .dout(imb_ff[31:1])); + rvdff_fpga #(1) unc_miss_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din ( uncacheable_miss_in), .dout( uncacheable_miss_ff)); assign miss_addr_in[31:pt.ICACHE_BEAT_ADDR_HI+1] = (~miss_pending ) ? imb_ff[31:pt.ICACHE_BEAT_ADDR_HI+1] : ( scnd_miss_req_q ) ? imb_scnd_ff[31:pt.ICACHE_BEAT_ADDR_HI+1] : miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1] ; - rvdff #(31-pt.ICACHE_BEAT_ADDR_HI) miss_f_ff (.*, .clk(busclk_reset), .din ({miss_addr_in[31:pt.ICACHE_BEAT_ADDR_HI+1]}), .dout({miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1]})); + + rvdfflie #(.WIDTH(31-pt.ICACHE_BEAT_ADDR_HI),.LEFT(31-pt.ICACHE_BEAT_ADDR_HI-8)) miss_f_ff (.*, .en(bus_ifu_bus_clk_en | ic_act_miss_f | dec_tlu_force_halt), .din ({miss_addr_in[31:pt.ICACHE_BEAT_ADDR_HI+1]}), .dout({miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1]})); - rvdff #(pt.ICACHE_STATUS_BITS) mb_rep_wayf2_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({way_status_mb_in[pt.ICACHE_STATUS_BITS-1:0]}), .dout({way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0]})); - rvdff #(pt.ICACHE_NUM_WAYS) mb_tagv_ff (.*, .clk(fetch_bf_f_c1_clk), .din ({tagv_mb_in[pt.ICACHE_NUM_WAYS-1:0]}), .dout({tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0]})); + + rvdff_fpga #(pt.ICACHE_STATUS_BITS) mb_rep_wayf2_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din ({way_status_mb_in[pt.ICACHE_STATUS_BITS-1:0]}), .dout({way_status_mb_ff[pt.ICACHE_STATUS_BITS-1:0]})); + rvdff_fpga #(pt.ICACHE_NUM_WAYS) mb_tagv_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din ({tagv_mb_in[pt.ICACHE_NUM_WAYS-1:0]}), .dout({tagv_mb_ff[pt.ICACHE_NUM_WAYS-1:0]})); assign ifc_fetch_req_qual_bf = ifc_fetch_req_bf & ~((miss_state == CRIT_WRD_RDY) & flush_final_f) & ~stream_miss_f ;// & ~exu_flush_final ; - rvdff #(1) fetch_req_f_ff (.*, .clk(active_clk), .din(ifc_fetch_req_qual_bf), .dout(ifc_fetch_req_f_raw)); assign ifc_fetch_req_f = ifc_fetch_req_f_raw & ~exu_flush_final ; - rvdff #(1) ifu_iccm_acc_ff (.*, .clk(fetch_bf_f_c1_clk), .din(ifc_iccm_access_bf), .dout(ifc_iccm_access_f)); - rvdff #(1) ifu_iccm_reg_acc_ff (.*, .clk(fetch_bf_f_c1_clk), .din(ifc_region_acc_fault_final_bf), .dout(ifc_region_acc_fault_final_f)); - rvdff #(1) rgn_acc_ff (.*, .clk(fetch_bf_f_c1_clk), .din(ifc_region_acc_fault_bf), .dout(ifc_region_acc_fault_f)); + rvdff_fpga #(1) ifu_iccm_acc_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din(ifc_iccm_access_bf), .dout(ifc_iccm_access_f)); + rvdff_fpga #(1) ifu_iccm_reg_acc_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din(ifc_region_acc_fault_final_bf), .dout(ifc_region_acc_fault_final_f)); + rvdff_fpga #(1) rgn_acc_ff (.*, .clk(fetch_bf_f_c1_clk), .clken(fetch_bf_f_c1_clken), .rawclk(clk), .din(ifc_region_acc_fault_bf), .dout(ifc_region_acc_fault_f)); assign ifu_ic_req_addr_f[31:3] = {miss_addr[31:pt.ICACHE_BEAT_ADDR_HI+1] , ic_req_addr_bits_hi_3[pt.ICACHE_BEAT_ADDR_HI:3] }; @@ -654,7 +653,6 @@ import el2_pkg::*; assign ic_rw_addr[31:1] = ifu_ic_rw_int_addr[31:1] ; - rvdff #(1) sel_mb_ff (.*, .clk(free_clk), .din (sel_mb_addr), .dout(sel_mb_addr_ff)); if (pt.ICACHE_ECC == 1) begin: icache_ecc_1 logic [6:0] ic_wr_ecc; @@ -669,7 +667,7 @@ if (pt.ICACHE_ECC == 1) begin: icache_ecc_1 .din (ic_miss_buff_half[63:0]), .ecc_out(ic_miss_buff_ecc[6:0])); - for (genvar i=0; i < 32'(pt.ICACHE_BANKS_WAY) ; i++) begin : ic_wr_data_loop + for (genvar i=0; i < pt.ICACHE_BANKS_WAY ; i++) begin : ic_wr_data_loop assign ic_wr_data[i][70:0] = ic_wr_16bytes_data[((71*i)+70): (71*i)]; end @@ -682,13 +680,15 @@ if (pt.ICACHE_ECC == 1) begin: icache_ecc_1 assign ifu_ic_debug_rd_data_in[70:0] = ic_debug_ict_array_sel_ff ? {2'b0,ictag_debug_rd_data[25:21],32'b0,ictag_debug_rd_data[20:0],{7-pt.ICACHE_STATUS_BITS{1'b0}}, way_status[pt.ICACHE_STATUS_BITS-1:0],3'b0,ic_debug_tag_val_rd_out} : ic_debug_rd_data[70:0]; - rvdff #(71) ifu_debug_data_ff (.*, .clk (debug_data_clk), - .din ({ - ifu_ic_debug_rd_data_in[70:0] - }), - .dout({ - ifu_ic_debug_rd_data[70:0] - })); + rvdffe #(71) ifu_debug_data_ff (.*, + .en (debug_data_clken), + .din ({ + ifu_ic_debug_rd_data_in[70:0] + }), + .dout({ + ifu_ic_debug_rd_data[70:0] + }) + ); assign ic_wr_16bytes_data[141:0] = ifu_bus_rid_ff[0] ? {ic_wr_ecc[6:0] , ifu_bus_rdata_ff[63:0] , ic_miss_buff_ecc[6:0] , ic_miss_buff_half[63:0] } : {ic_miss_buff_ecc[6:0] , ic_miss_buff_half[63:0] , ic_wr_ecc[6:0] , ifu_bus_rdata_ff[63:0] } ; @@ -709,7 +709,7 @@ else begin : icache_parity_1 for (genvar i=0; i < pt.ICACHE_BANKS_WAY ; i++) begin : ic_wr_data_loop - assign ic_wr_data[i][67:0] = ic_wr_16bytes_data[((68*i)+67): (68*i)]; + assign ic_wr_data[i][70:0] = {3'b0, ic_wr_16bytes_data[((68*i)+67): (68*i)]}; end @@ -722,13 +722,15 @@ else begin : icache_parity_1 assign ifu_ic_debug_rd_data_in[70:0] = ic_debug_ict_array_sel_ff ? {6'b0,ictag_debug_rd_data[21],32'b0,ictag_debug_rd_data[20:0],{7-pt.ICACHE_STATUS_BITS{1'b0}},way_status[pt.ICACHE_STATUS_BITS-1:0],3'b0,ic_debug_tag_val_rd_out} : ic_debug_rd_data[70:0] ; - rvdff #(71) ifu_debug_data_ff (.*, .clk (debug_data_clk), - .din ({ - ifu_ic_debug_rd_data_in[70:0] - }), - .dout({ - ifu_ic_debug_rd_data[70:0] - })); + rvdffe #(71) ifu_debug_data_ff (.*, + .en (debug_data_clken), + .din ({ + ifu_ic_debug_rd_data_in[70:0] + }), + .dout({ + ifu_ic_debug_rd_data[70:0] + }) + ); assign ic_wr_16bytes_data[135:0] = ifu_bus_rid_ff[0] ? {ic_wr_parity[3:0] , ifu_bus_rdata_ff[63:0] , ic_miss_buff_parity[3:0] , ic_miss_buff_half[63:0] } : {ic_miss_buff_parity[3:0] , ic_miss_buff_half[63:0] , ic_wr_parity[3:0] , ifu_bus_rdata_ff[63:0] } ; @@ -740,11 +742,9 @@ end assign ifu_wr_cumulative_err = (ifu_wr_data_comb_err | ifu_wr_data_comb_err_ff) & ~reset_beat_cnt; assign ifu_wr_cumulative_err_data = ifu_wr_data_comb_err | ifu_wr_data_comb_err_ff ; - rvdff #(1) cumul_err_ff (.*, .clk(free_clk), .din (ifu_wr_cumulative_err), .dout(ifu_wr_data_comb_err_ff)); - - assign sel_byp_data = (ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK)) & ~ifu_byp_data_err_new; - assign sel_ic_data = ~(ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK)) & ~fetch_req_iccm_f ; + assign sel_byp_data = (ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK)); + assign sel_ic_data = ~(ic_crit_wd_rdy | (miss_state == STREAM) | (miss_state == CRIT_BYP_OK) | (miss_state == MISS_WAIT)) & ~fetch_req_iccm_f & ~ifc_region_acc_fault_final_f; if (pt.ICCM_ICACHE==1) begin: iccm_icache assign sel_iccm_data = fetch_req_iccm_f ; @@ -779,14 +779,14 @@ if (pt.NO_ICCM_NO_ICACHE == 1 ) begin: no_iccm_no_icache end - assign ifc_bus_acc_fault_f = ic_byp_hit_f & ifu_byp_data_err_new ; + assign ifc_bus_acc_fault_f[1:0] = {2{ic_byp_hit_f}} & ifu_byp_data_err_f[1:0] ; assign ic_data_f[31:0] = ic_final_data[31:0]; -rvdff #(1) flush_final_ff (.*, .clk(free_clk), .din({exu_flush_final}), .dout({flush_final_f})); + assign fetch_req_f_qual = ic_hit_f & ~exu_flush_final; -assign ic_access_fault_f = (ifc_region_acc_fault_final_f | ifc_bus_acc_fault_f) & ~exu_flush_final; -assign ic_access_fault_type_f[1:0] = iccm_rd_ecc_double_err ? 2'b01 : +assign ic_access_fault_f[1:0] = ({2{ifc_region_acc_fault_final_f}} | ifc_bus_acc_fault_f[1:0]) & {2{~exu_flush_final}}; +assign ic_access_fault_type_f[1:0] = |iccm_rd_ecc_double_err ? 2'b01 : ifc_region_acc_fault_f ? 2'b10 : ifc_region_acc_fault_memory_f ? 2'b11 : 2'b00 ; @@ -802,28 +802,33 @@ assign two_byte_instr = (ic_data_f[1:0] != 2'b11 ) ; logic [63:0] ic_miss_buff_data_in; assign ic_miss_buff_data_in[63:0] = ifu_bus_rsp_rdata[63:0]; - for (genvar i=0; i<32'(pt.ICACHE_NUM_BEATS); i++) begin : wr_flop - assign write_fill_data[i] = bus_ifu_wr_en & ( (pt.IFU_BUS_TAG)'(i) == ifu_bus_rsp_tag[pt.IFU_BUS_TAG-1:0]); - rvclkhdr data_c1_cgc ( .en(write_fill_data[i]), .l1clk(wr_data_c1_clk[i]), .* ); - rvdff #(32) byp_data_0_ff (.*, - .clk (wr_data_c1_clk[i]), - .din (ic_miss_buff_data_in[31:0]), - .dout(ic_miss_buff_data[i*2][31:0])); + for (genvar i=0; i (~$past(ahb_hready) & $past(ahb_hresp)); + @(posedge bus_clk) (ahb_hready & ahb_hresp) |-> (~$past(ahb_hready) & $past(ahb_hresp)); endproperty assert_ahb_error_protocol: assert property (ahb_error_protocol) else $display("Bus Error with hReady isn't preceded with Bus Error without hready"); diff --git a/design/lib/axi4_to_ahb.sv b/design/lib/axi4_to_ahb.sv index 481ad88..672f0b1 100644 --- a/design/lib/axi4_to_ahb.sv +++ b/design/lib/axi4_to_ahb.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,10 +28,12 @@ import el2_pkg::*; ,parameter TAG = 1) ( input clk, + input free_clk, input rst_l, input scan_mode, input bus_clk_en, input clk_override, + input dec_tlu_force_halt, // AXI signals // AXI Write Channels @@ -105,9 +107,6 @@ import el2_pkg::*; logic [63:0] wrbuf_data; logic [7:0] wrbuf_byteen; - logic bus_write_clk_en; - logic bus_clk, bus_write_clk; - logic master_valid; logic master_ready; logic [TAG-1:0] master_tag; @@ -169,15 +168,15 @@ import el2_pkg::*; logic [31:0] last_bus_addr; // Clocks - logic buf_clken, slvbuf_clken; - logic ahbm_addr_clken; + logic buf_clken; logic ahbm_data_clken; - logic buf_clk, slvbuf_clk; - logic ahbm_clk; - logic ahbm_addr_clk; + logic buf_clk; + logic bus_clk; logic ahbm_data_clk; + logic dec_tlu_force_halt_bus, dec_tlu_force_halt_bus_ns, dec_tlu_force_halt_bus_q; + // Function to get the length from byte enable function automatic logic [1:0] get_write_size; input logic [7:0] byteen; @@ -210,6 +209,7 @@ import el2_pkg::*; logic [2:0] start_ptr; logic found; found = '0; + //get_nxtbyte_ptr[2:0] = current_byte_ptr[2:0]; start_ptr[2:0] = get_next ? (current_byte_ptr[2:0] + 3'b1) : current_byte_ptr[2:0]; for (int j=0; j<8; j++) begin if (~found) begin @@ -219,12 +219,16 @@ import el2_pkg::*; end endfunction // get_nextbyte_ptr + // Create bus synchronized version of force halt + assign dec_tlu_force_halt_bus = dec_tlu_force_halt | dec_tlu_force_halt_bus_q; + assign dec_tlu_force_halt_bus_ns = ~bus_clk_en & dec_tlu_force_halt_bus; + rvdff #(.WIDTH(1)) force_halt_busff(.din(dec_tlu_force_halt_bus_ns), .dout(dec_tlu_force_halt_bus_q), .clk(free_clk), .*); // Write buffer assign wrbuf_en = axi_awvalid & axi_awready & master_ready; assign wrbuf_data_en = axi_wvalid & axi_wready & master_ready; assign wrbuf_cmd_sent = master_valid & master_ready & (master_opc[2:1] == 2'b01); - assign wrbuf_rst = wrbuf_cmd_sent & ~wrbuf_en; + assign wrbuf_rst = (wrbuf_cmd_sent & ~wrbuf_en) | dec_tlu_force_halt_bus; assign axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent) & master_ready; assign axi_wready = ~(wrbuf_data_vld & ~wrbuf_cmd_sent) & master_ready; @@ -251,13 +255,6 @@ import el2_pkg::*; assign axi_rdata[63:0] = slave_rdata[63:0]; assign slave_ready = axi_bready & axi_rready; - // Clock header logic - assign bus_write_clk_en = bus_clk_en & ((axi_awvalid & axi_awready) | (axi_wvalid & axi_wready)); - - rvclkhdr bus_cgc (.en(bus_clk_en), .l1clk(bus_clk), .*); - rvclkhdr bus_write_cgc (.en(bus_write_clk_en), .l1clk(bus_write_clk), .*); - - // FIFO state machine always_comb begin buf_nxtstate = IDLE; @@ -378,7 +375,7 @@ import el2_pkg::*; endcase end - assign buf_rst = 1'b0; + assign buf_rst = dec_tlu_force_halt_bus; assign cmd_done_rst = slave_valid_pre; assign buf_addr_in[31:3] = master_addr[31:3]; assign buf_addr_in[2:0] = (buf_aligned_in & (master_opc[2:1] == 2'b01)) ? get_write_addr(master_byteen[7:0]) : master_addr[2:0]; @@ -393,7 +390,8 @@ import el2_pkg::*; (master_byteen[7:0] == 8'hf) | (master_byteen[7:0] == 8'hf0) | (master_byteen[7:0] == 8'hff))); // Generate the ahb signals - assign ahb_haddr[31:0] = bypass_en ? {master_addr[31:3],buf_cmd_byte_ptr[2:0]} : {buf_addr[31:3],buf_cmd_byte_ptr[2:0]}; + assign ahb_haddr[31:3] = bypass_en ? master_addr[31:3] : buf_addr[31:3]; + assign ahb_haddr[2:0] = {3{(ahb_htrans == 2'b10)}} & buf_cmd_byte_ptr[2:0]; // Trxn should be aligned during IDLE assign ahb_hsize[2:0] = bypass_en ? {1'b0, ({2{buf_aligned_in}} & buf_size_in[1:0])} : {1'b0, ({2{buf_aligned}} & buf_size[1:0])}; // Send the full size for aligned trxn assign ahb_hburst[2:0] = 3'b0; @@ -402,7 +400,7 @@ import el2_pkg::*; assign ahb_hwrite = bypass_en ? (master_opc[2:1] == 2'b01) : buf_write; assign ahb_hwdata[63:0] = buf_data[63:0]; - assign slave_valid = slave_valid_pre; + assign slave_valid = slave_valid_pre;// & (~slvbuf_posted_write | slvbuf_error); assign slave_opc[3:2] = slvbuf_write ? 2'b11 : 2'b00; assign slave_opc[1:0] = {2{slvbuf_error}} & 2'b10; assign slave_rdata[63:0] = slvbuf_error ? {2{last_bus_addr[31:0]}} : ((buf_state == DONE) ? buf_data[63:0] : ahb_hrdata_q[63:0]); @@ -411,53 +409,57 @@ import el2_pkg::*; assign last_addr_en = (ahb_htrans[1:0] != 2'b0) & ahb_hready & ahb_hwrite ; - rvdffsc #(.WIDTH(1)) wrbuf_vldff (.din(1'b1), .dout(wrbuf_vld), .en(wrbuf_en), .clear(wrbuf_rst), .clk(bus_clk), .*); - rvdffsc #(.WIDTH(1)) wrbuf_data_vldff(.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_rst), .clk(bus_clk), .*); - rvdffs #(.WIDTH(TAG)) wrbuf_tagff (.din(axi_awid[TAG-1:0]), .dout(wrbuf_tag[TAG-1:0]), .en(wrbuf_en), .clk(bus_clk), .*); - rvdffs #(.WIDTH(3)) wrbuf_sizeff (.din(axi_awsize[2:0]), .dout(wrbuf_size[2:0]), .en(wrbuf_en), .clk(bus_clk), .*); - rvdffe #(.WIDTH(32)) wrbuf_addrff (.din(axi_awaddr[31:0]), .dout(wrbuf_addr[31:0]), .en(wrbuf_en), .clk(bus_clk), .*); - rvdffe #(.WIDTH(64)) wrbuf_dataff (.din(axi_wdata[63:0]), .dout(wrbuf_data[63:0]), .en(wrbuf_data_en), .clk(bus_clk), .*); - rvdffs #(.WIDTH(8)) wrbuf_byteenff (.din(axi_wstrb[7:0]), .dout(wrbuf_byteen[7:0]), .en(wrbuf_data_en), .clk(bus_clk), .*); + rvdffsc_fpga #(.WIDTH(1)) wrbuf_vldff (.din(1'b1), .dout(wrbuf_vld), .en(wrbuf_en), .clear(wrbuf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdffsc_fpga #(.WIDTH(1)) wrbuf_data_vldff(.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(TAG)) wrbuf_tagff (.din(axi_awid[TAG-1:0]), .dout(wrbuf_tag[TAG-1:0]), .en(wrbuf_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(3)) wrbuf_sizeff (.din(axi_awsize[2:0]), .dout(wrbuf_size[2:0]), .en(wrbuf_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdffe #(.WIDTH(32)) wrbuf_addrff (.din(axi_awaddr[31:0]), .dout(wrbuf_addr[31:0]), .en(wrbuf_en & bus_clk_en), .clk(clk), .*); + rvdffe #(.WIDTH(64)) wrbuf_dataff (.din(axi_wdata[63:0]), .dout(wrbuf_data[63:0]), .en(wrbuf_data_en & bus_clk_en), .clk(clk), .*); + rvdffs_fpga #(.WIDTH(8)) wrbuf_byteenff (.din(axi_wstrb[7:0]), .dout(wrbuf_byteen[7:0]), .en(wrbuf_data_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); - rvdffs #(.WIDTH(32)) last_bus_addrff (.din(ahb_haddr[31:0]), .dout(last_bus_addr[31:0]), .en(last_addr_en), .clk(ahbm_clk), .*); + rvdffs_fpga #(.WIDTH(32)) last_bus_addrff (.din(ahb_haddr[31:0]), .dout(last_bus_addr[31:0]), .en(last_addr_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); - rvdffsc #(.WIDTH($bits(state_t))) buf_state_ff (.din(buf_nxtstate), .dout({buf_state}), .en(buf_state_en), .clear(buf_rst), .clk(ahbm_clk), .*); - rvdffs #(.WIDTH(1)) buf_writeff (.din(buf_write_in), .dout(buf_write), .en(buf_wr_en), .clk(buf_clk), .*); - rvdffs #(.WIDTH(TAG)) buf_tagff (.din(buf_tag_in[TAG-1:0]), .dout(buf_tag[TAG-1:0]), .en(buf_wr_en), .clk(buf_clk), .*); - rvdffe #(.WIDTH(32)) buf_addrff (.din(buf_addr_in[31:0]), .dout(buf_addr[31:0]), .en(buf_wr_en & bus_clk_en), .*); - rvdffs #(.WIDTH(2)) buf_sizeff (.din(buf_size_in[1:0]), .dout(buf_size[1:0]), .en(buf_wr_en), .clk(buf_clk), .*); - rvdffs #(.WIDTH(1)) buf_alignedff (.din(buf_aligned_in), .dout(buf_aligned), .en(buf_wr_en), .clk(buf_clk), .*); - rvdffs #(.WIDTH(8)) buf_byteenff (.din(buf_byteen_in[7:0]), .dout(buf_byteen[7:0]), .en(buf_wr_en), .clk(buf_clk), .*); - rvdffe #(.WIDTH(64)) buf_dataff (.din(buf_data_in[63:0]), .dout(buf_data[63:0]), .en(buf_data_wr_en & bus_clk_en), .*); + rvdffsc_fpga #(.WIDTH($bits(state_t))) buf_state_ff (.din(buf_nxtstate), .dout({buf_state}), .en(buf_state_en), .clear(buf_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(1)) buf_writeff (.din(buf_write_in), .dout(buf_write), .en(buf_wr_en), .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(TAG)) buf_tagff (.din(buf_tag_in[TAG-1:0]), .dout(buf_tag[TAG-1:0]), .en(buf_wr_en), .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); + rvdffe #(.WIDTH(32)) buf_addrff (.din(buf_addr_in[31:0]), .dout(buf_addr[31:0]), .en(buf_wr_en & bus_clk_en), .clk(clk), .*); + rvdffs_fpga #(.WIDTH(2)) buf_sizeff (.din(buf_size_in[1:0]), .dout(buf_size[1:0]), .en(buf_wr_en), .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(1)) buf_alignedff (.din(buf_aligned_in), .dout(buf_aligned), .en(buf_wr_en), .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(8)) buf_byteenff (.din(buf_byteen_in[7:0]), .dout(buf_byteen[7:0]), .en(buf_wr_en), .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); + rvdffe #(.WIDTH(64)) buf_dataff (.din(buf_data_in[63:0]), .dout(buf_data[63:0]), .en(buf_data_wr_en & bus_clk_en), .clk(clk), .*); - rvdffs #(.WIDTH(1)) slvbuf_writeff (.din(buf_write), .dout(slvbuf_write), .en(slvbuf_wr_en), .clk(buf_clk), .*); - rvdffs #(.WIDTH(TAG)) slvbuf_tagff (.din(buf_tag[TAG-1:0]), .dout(slvbuf_tag[TAG-1:0]), .en(slvbuf_wr_en), .clk(buf_clk), .*); - rvdffs #(.WIDTH(1)) slvbuf_errorff (.din(slvbuf_error_in), .dout(slvbuf_error), .en(slvbuf_error_en), .clk(ahbm_clk), .*); + rvdffs_fpga #(.WIDTH(1)) slvbuf_writeff (.din(buf_write), .dout(slvbuf_write), .en(slvbuf_wr_en), .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(TAG)) slvbuf_tagff (.din(buf_tag[TAG-1:0]), .dout(slvbuf_tag[TAG-1:0]), .en(slvbuf_wr_en), .clk(buf_clk), .clken(buf_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(1)) slvbuf_errorff (.din(slvbuf_error_in), .dout(slvbuf_error), .en(slvbuf_error_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); - rvdffsc #(.WIDTH(1)) buf_cmd_doneff (.din(1'b1), .en(cmd_done), .dout(cmd_doneQ), .clear(cmd_done_rst), .clk(ahbm_clk), .*); - rvdffs #(.WIDTH(3)) buf_cmd_byte_ptrff (.din(buf_cmd_byte_ptr[2:0]), .dout(buf_cmd_byte_ptrQ[2:0]), .en(buf_cmd_byte_ptr_en), .clk(ahbm_clk), .*); + rvdffsc_fpga #(.WIDTH(1)) buf_cmd_doneff (.din(1'b1), .dout(cmd_doneQ), .en(cmd_done), .clear(cmd_done_rst), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(3)) buf_cmd_byte_ptrff (.din(buf_cmd_byte_ptr[2:0]), .dout(buf_cmd_byte_ptrQ[2:0]), .en(buf_cmd_byte_ptr_en), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); - rvdff #(.WIDTH(1)) hready_ff (.din(ahb_hready), .dout(ahb_hready_q), .clk(ahbm_clk), .*); - rvdff #(.WIDTH(2)) htrans_ff (.din(ahb_htrans[1:0]), .dout(ahb_htrans_q[1:0]), .clk(ahbm_clk), .*); - rvdff #(.WIDTH(1)) hwrite_ff (.din(ahb_hwrite), .dout(ahb_hwrite_q), .clk(ahbm_addr_clk), .*); - rvdff #(.WIDTH(1)) hresp_ff (.din(ahb_hresp), .dout(ahb_hresp_q), .clk(ahbm_clk), .*); - rvdff #(.WIDTH(64)) hrdata_ff (.din(ahb_hrdata[63:0]), .dout(ahb_hrdata_q[63:0]), .clk(ahbm_data_clk), .*); + rvdff_fpga #(.WIDTH(1)) hready_ff (.din(ahb_hready), .dout(ahb_hready_q), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdff_fpga #(.WIDTH(2)) htrans_ff (.din(ahb_htrans[1:0]), .dout(ahb_htrans_q[1:0]), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdff_fpga #(.WIDTH(1)) hwrite_ff (.din(ahb_hwrite), .dout(ahb_hwrite_q), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdff_fpga #(.WIDTH(1)) hresp_ff (.din(ahb_hresp), .dout(ahb_hresp_q), .clk(bus_clk), .clken(bus_clk_en), .rawclk(clk), .*); + rvdff_fpga #(.WIDTH(64)) hrdata_ff (.din(ahb_hrdata[63:0]), .dout(ahb_hrdata_q[63:0]), .clk(ahbm_data_clk), .clken(ahbm_data_clken), .rawclk(clk), .*); // Clock headers // clock enables for ahbm addr/data assign buf_clken = bus_clk_en & (buf_wr_en | slvbuf_wr_en | clk_override); - assign ahbm_addr_clken = bus_clk_en & ((ahb_hready & ahb_htrans[1]) | clk_override); assign ahbm_data_clken = bus_clk_en & ((buf_state != IDLE) | clk_override); - rvclkhdr buf_cgc (.en(buf_clken), .l1clk(buf_clk), .*); - rvclkhdr ahbm_cgc (.en(bus_clk_en), .l1clk(ahbm_clk), .*); - rvclkhdr ahbm_addr_cgc (.en(ahbm_addr_clken), .l1clk(ahbm_addr_clk), .*); +`ifdef RV_FPGA_OPTIMIZE + assign bus_clk = 1'b0; + assign buf_clk = 1'b0; + assign ahbm_data_clk = 1'b0; +`else + rvclkhdr bus_cgc (.en(bus_clk_en), .l1clk(bus_clk), .*); + rvclkhdr buf_cgc (.en(buf_clken), .l1clk(buf_clk), .*); rvclkhdr ahbm_data_cgc (.en(ahbm_data_clken), .l1clk(ahbm_data_clk), .*); +`endif -`ifdef ASSERT_ON +`ifdef RV_ASSERT_ON property ahb_trxn_aligned; - @(posedge ahbm_clk) ahb_htrans[1] |-> ((ahb_hsize[2:0] == 3'h0) | + @(posedge bus_clk) ahb_htrans[1] |-> ((ahb_hsize[2:0] == 3'h0) | ((ahb_hsize[2:0] == 3'h1) & (ahb_haddr[0] == 1'b0)) | ((ahb_hsize[2:0] == 3'h2) & (ahb_haddr[1:0] == 2'b0)) | ((ahb_hsize[2:0] == 3'h3) & (ahb_haddr[2:0] == 3'b0))); @@ -466,7 +468,7 @@ import el2_pkg::*; $display("Assertion ahb_trxn_aligned failed: ahb_htrans=2'h%h, ahb_hsize=3'h%h, ahb_haddr=32'h%h",ahb_htrans[1:0], ahb_hsize[2:0], ahb_haddr[31:0]); property ahb_error_protocol; - @(posedge ahbm_clk) (ahb_hready & ahb_hresp) |-> (~$past(ahb_hready) & $past(ahb_hresp)); + @(posedge bus_clk) (ahb_hready & ahb_hresp) |-> (~$past(ahb_hready) & $past(ahb_hresp)); endproperty assert_ahb_error_protocol: assert property (ahb_error_protocol) else $display("Bus Error with hReady isn't preceded with Bus Error without hready"); diff --git a/design/lib/beh_lib.sv b/design/lib/beh_lib.sv index 96612b0..a36e86f 100644 --- a/design/lib/beh_lib.sv +++ b/design/lib/beh_lib.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ if (SHORT == 1) begin assign dout = din; end else begin -`ifdef CLOCKGATE +`ifdef RV_CLOCKGATE always @(posedge tb_top.clk) begin #0 $strobe("CG: %0t %m din %x dout %x clk %b width %d",$time,din,dout,clk,WIDTH); end @@ -85,7 +85,85 @@ else begin end endmodule -module rvdffe #( parameter WIDTH=1, SHORT=0 ) +// _fpga versions +module rvdff_fpga #( parameter WIDTH=1, SHORT=0 ) + ( + input logic [WIDTH-1:0] din, + input logic clk, + input logic clken, + input logic rawclk, + input logic rst_l, + + output logic [WIDTH-1:0] dout + ); + +if (SHORT == 1) begin + assign dout = din; +end +else begin + `ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dffs (.clk(rawclk), .en(clken), .*); +`else + rvdff #(WIDTH) dff (.*); +`endif +end +endmodule + +// rvdff with 2:1 input mux to flop din iff sel==1 +module rvdffs_fpga #( parameter WIDTH=1, SHORT=0 ) + ( + input logic [WIDTH-1:0] din, + input logic en, + input logic clk, + input logic clken, + input logic rawclk, + input logic rst_l, + + output logic [WIDTH-1:0] dout + ); + +if (SHORT == 1) begin : genblock + assign dout = din; +end +else begin : genblock +`ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dffs (.clk(rawclk), .en(clken & en), .*); +`else + rvdffs #(WIDTH) dffs (.*); +`endif +end + +endmodule + +// rvdff with en and clear +module rvdffsc_fpga #( parameter WIDTH=1, SHORT=0 ) + ( + input logic [WIDTH-1:0] din, + input logic en, + input logic clear, + input logic clk, + input logic clken, + input logic rawclk, + input logic rst_l, + + output logic [WIDTH-1:0] dout + ); + + logic [WIDTH-1:0] din_new; +if (SHORT == 1) begin + assign dout = din; +end +else begin +`ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dffs (.clk(rawclk), .din(din[WIDTH-1:0] & {WIDTH{~clear}}),.en((en | clear) & clken), .*); +`else + rvdffsc #(WIDTH) dffsc (.*); +`endif +end +endmodule + + +module rvdffe #( parameter WIDTH=1, SHORT=0, OVERRIDE=0 ) ( input logic [WIDTH-1:0] din, input logic en, @@ -104,8 +182,8 @@ if (SHORT == 1) begin : genblock end else begin : genblock -`ifndef PHYSICAL - if (WIDTH >= 8) begin: genblock +`ifndef RV_PHYSICAL + if (WIDTH >= 8 || OVERRIDE==1) begin: genblock `endif `ifdef RV_FPGA_OPTIMIZE @@ -115,15 +193,226 @@ else begin : genblock rvdff #(WIDTH) dff (.*, .clk(l1clk)); `endif -`ifndef PHYSICAL +`ifndef RV_PHYSICAL end else - $error("%m: rvdffe width must be >= 8"); + $error("%m: rvdffe must be WIDTH >= 8"); `endif end // else: !if(SHORT == 1) endmodule // rvdffe + +module rvdffpcie #( parameter WIDTH=31 ) + ( + input logic [WIDTH-1:0] din, + input logic clk, + input logic rst_l, + input logic en, + input logic scan_mode, + output logic [WIDTH-1:0] dout + ); + + + +`ifndef RV_PHYSICAL + if (WIDTH == 31) begin: genblock +`endif + +`ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dff ( .* ); +`else + + rvdfflie #(.WIDTH(WIDTH), .LEFT(19)) dff (.*); + +`endif + +`ifndef RV_PHYSICAL + end + else + $error("%m: rvdffpcie width must be 31"); +`endif +endmodule + +// format: { LEFT, EXTRA } +// LEFT # of bits will be done with rvdffie, all else EXTRA with rvdffe +module rvdfflie #( parameter WIDTH=16, LEFT=8 ) + ( + input logic [WIDTH-1:0] din, + input logic clk, + input logic rst_l, + input logic en, + input logic scan_mode, + output logic [WIDTH-1:0] dout + ); + + localparam EXTRA = WIDTH-LEFT; + + + + + + + + localparam LMSB = WIDTH-1; + localparam LLSB = LMSB-LEFT+1; + localparam XMSB = LLSB-1; + localparam XLSB = LLSB-EXTRA; + + +`ifndef RV_PHYSICAL + if (WIDTH >= 16 && LEFT >= 8 && EXTRA >= 8) begin: genblock +`endif + +`ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dff ( .* ); +`else + + rvdffiee #(LEFT) dff_left (.*, .din(din[LMSB:LLSB]), .dout(dout[LMSB:LLSB])); + + + rvdffe #(EXTRA) dff_extra (.*, .din(din[XMSB:XLSB]), .dout(dout[XMSB:XLSB])); + + + + +`endif + +`ifndef RV_PHYSICAL + end + else + $error("%m: rvdfflie musb be WIDTH >= 16 && LEFT >= 8 && EXTRA >= 8"); +`endif +endmodule + + + + +// special power flop for predict packet +// format: { LEFT, RIGHT==31 } +// LEFT # of bits will be done with rvdffe; RIGHT is enabled by LEFT[LSB] & en +module rvdffppe #( parameter WIDTH=32 ) + ( + input logic [WIDTH-1:0] din, + input logic clk, + input logic rst_l, + input logic en, + input logic scan_mode, + output logic [WIDTH-1:0] dout + ); + + localparam RIGHT = 31; + localparam LEFT = WIDTH - RIGHT; + + localparam LMSB = WIDTH-1; + localparam LLSB = LMSB-LEFT+1; + localparam RMSB = LLSB-1; + localparam RLSB = LLSB-RIGHT; + + +`ifndef RV_PHYSICAL + if (WIDTH>=32 && LEFT>=8 && RIGHT>=8) begin: genblock +`endif + +`ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dff ( .* ); +`else + rvdffe #(LEFT) dff_left (.*, .din(din[LMSB:LLSB]), .dout(dout[LMSB:LLSB])); + + rvdffe #(RIGHT) dff_right (.*, .din(din[RMSB:RLSB]), .dout(dout[RMSB:RLSB]), .en(en & din[LLSB])); // qualify with pret + + +`endif + +`ifndef RV_PHYSICAL + end + else + $error("%m: must be WIDTH>=32 && LEFT>=8 && RIGHT>=8"); +`endif +endmodule + + + + +module rvdffie #( parameter WIDTH=1, OVERRIDE=0 ) + ( + input logic [WIDTH-1:0] din, + + input logic clk, + input logic rst_l, + input logic scan_mode, + output logic [WIDTH-1:0] dout + ); + + logic l1clk; + logic en; + + + + + + + + +`ifndef RV_PHYSICAL + if (WIDTH >= 8 || OVERRIDE==1) begin: genblock +`endif + + assign en = |(din ^ dout); + +`ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dff ( .* ); +`else + rvclkhdr clkhdr ( .* ); + rvdff #(WIDTH) dff (.*, .clk(l1clk)); +`endif + +`ifndef RV_PHYSICAL + end + else + $error("%m: rvdffie must be WIDTH >= 8"); +`endif + + +endmodule + +// ie flop but it has an .en input +module rvdffiee #( parameter WIDTH=1, OVERRIDE=0 ) + ( + input logic [WIDTH-1:0] din, + + input logic clk, + input logic rst_l, + input logic scan_mode, + input logic en, + output logic [WIDTH-1:0] dout + ); + + logic l1clk; + logic final_en; + +`ifndef RV_PHYSICAL + if (WIDTH >= 8 || OVERRIDE==1) begin: genblock +`endif + + assign final_en = (|(din ^ dout)) & en; + +`ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dff ( .*, .en(final_en) ); +`else + rvdffe #(WIDTH) dff (.*, .en(final_en)); +`endif + +`ifndef RV_PHYSICAL + end + else + $error("%m: rvdffie width must be >= 8"); +`endif + +endmodule + + + module rvsyncss #(parameter WIDTH = 251) ( input logic clk, @@ -139,6 +428,23 @@ module rvsyncss #(parameter WIDTH = 251) endmodule // rvsyncss +module rvsyncss_fpga #(parameter WIDTH = 251) + ( + input logic gw_clk, + input logic rawclk, + input logic clken, + input logic rst_l, + input logic [WIDTH-1:0] din, + output logic [WIDTH-1:0] dout + ); + + logic [WIDTH-1:0] din_ff1; + + rvdff_fpga #(WIDTH) sync_ff1 (.*, .clk(gw_clk), .rawclk(rawclk), .clken(clken), .din (din[WIDTH-1:0]), .dout(din_ff1[WIDTH-1:0])); + rvdff_fpga #(WIDTH) sync_ff2 (.*, .clk(gw_clk), .rawclk(rawclk), .clken(clken), .din (din_ff1[WIDTH-1:0]), .dout(dout[WIDTH-1:0])); + +endmodule // rvsyncss + module rvlsadder ( input logic [31:0] rs1, @@ -468,6 +774,7 @@ module `TEC_RV_ICG endmodule +`ifndef RV_FPGA_OPTIMIZE module rvclkhdr ( input logic en, @@ -477,11 +784,12 @@ module rvclkhdr ); logic SE; - assign SE = scan_mode; + assign SE = 0; `TEC_RV_ICG clkhdr ( .*, .EN(en), .CK(clk), .Q(l1clk)); endmodule // rvclkhdr +`endif module rvoclkhdr ( @@ -492,7 +800,7 @@ module rvoclkhdr ); logic SE; - assign SE = scan_mode; + assign SE = 0; `ifdef RV_FPGA_OPTIMIZE assign l1clk = clk; diff --git a/design/lib/mem_lib.sv b/design/lib/mem_lib.sv index 00702ea..325f80e 100644 --- a/design/lib/mem_lib.sv +++ b/design/lib/mem_lib.sv @@ -16,7 +16,17 @@ `define EL2_LOCAL_RAM_TEST_IO \ input logic WE, \ input logic ME, \ -input logic CLK +input logic CLK, \ +input logic TEST1, \ +input logic RME, \ +input logic [3:0] RM, \ +input logic LS, \ +input logic DS, \ +input logic SD, \ +input logic TEST_RNM, \ +input logic BC1, \ +input logic BC2, \ +output logic ROP `define EL2_RAM(depth, width) \ module ram_``depth``x``width( \ @@ -26,11 +36,22 @@ module ram_``depth``x``width( \ `EL2_LOCAL_RAM_TEST_IO \ ); \ reg [(width-1):0] ram_core [(depth-1):0]; \ - \ -always @(posedge CLK) begin \ +`ifdef GTLSIM \ +integer i; \ +initial begin \ + for (i=0; i> {dma_mem_addr[2:0], 3'b000}; // Shift the dma data to lower bits to make it consistent to lsu stores @@ -299,16 +300,19 @@ import el2_pkg::*; assign flush_m_up = dec_tlu_flush_lower_r; assign flush_r = dec_tlu_i0_kill_writeb_r; + // lsu idle // lsu halt idle. This is used for entering the halt mode. Also, DMA accesses are allowed during fence. // Indicates non-idle if there is a instruction valid in d-r or read/write buffers are non-empty since they can come with error // Store buffer now have only non-dma dccm stores // stbuf_empty not needed since it has only dccm stores assign lsu_idle_any = ~((lsu_pkt_m.valid & ~lsu_pkt_m.dma) | (lsu_pkt_r.valid & ~lsu_pkt_r.dma)) & - lsu_bus_buffer_empty_any & lsu_bus_idle_any; + lsu_bus_buffer_empty_any; + + assign lsu_active = (lsu_pkt_m.valid | lsu_pkt_r.valid | ld_single_ecc_error_r_ff) | ~lsu_bus_buffer_empty_any; // This includes DMA. Used for gating top clock // Instantiate the store buffer - assign store_stbuf_reqvld_r = lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_dccm_r & ~flush_r & ~lsu_pkt_r.dma; + assign store_stbuf_reqvld_r = lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_dccm_r & ~flush_r & (~lsu_pkt_r.dma | ((lsu_pkt_r.by | lsu_pkt_r.half) & ~lsu_double_ecc_error_r)); // Disable Forwarding for now assign lsu_cmpen_m = lsu_pkt_m.valid & (lsu_pkt_m.load | lsu_pkt_m.store) & (addr_in_dccm_m | addr_in_pic_m); @@ -316,6 +320,11 @@ import el2_pkg::*; // Bus signals assign lsu_busreq_m = lsu_pkt_m.valid & ((lsu_pkt_m.load | lsu_pkt_m.store) & addr_external_m) & ~flush_m_up & ~lsu_exc_m & ~lsu_pkt_m.fast_int; + // Dual signals + assign ldst_dual_d = (lsu_addr_d[2] != end_addr_d[2]); + assign ldst_dual_m = (lsu_addr_m[2] != end_addr_m[2]); + assign ldst_dual_r = (lsu_addr_r[2] != end_addr_r[2]); + // PMU signals assign lsu_pmu_misaligned_m = lsu_pkt_m.valid & ((lsu_pkt_m.half & lsu_addr_m[0]) | (lsu_pkt_m.word & (|lsu_addr_m[1:0]))); assign lsu_pmu_load_external_m = lsu_pkt_m.valid & lsu_pkt_m.load & addr_external_m; @@ -358,18 +367,24 @@ import el2_pkg::*; // Bus interface el2_lsu_bus_intf #(.pt(pt)) bus_intf ( + .lsu_addr_m(lsu_addr_m[31:0] & {32{addr_external_m & lsu_pkt_m.valid}}), + .lsu_addr_r(lsu_addr_r[31:0] & {32{lsu_busreq_r}}), + + .end_addr_m(end_addr_m[31:0] & {32{addr_external_m & lsu_pkt_m.valid}}), + .end_addr_r(end_addr_r[31:0] & {32{lsu_busreq_r}}), + + .store_data_r(store_data_r[31:0] & {32{lsu_busreq_r}}), .* ); //Flops rvdff #(3) dma_mem_tag_mff (.*, .din(dma_mem_tag_d[2:0]), .dout(dma_mem_tag_m[2:0]), .clk(lsu_c1_m_clk)); - rvdff #(2) lsu_raw_fwd_r_ff (.*, .din({lsu_raw_fwd_hi_m, lsu_raw_fwd_lo_m}), .dout({lsu_raw_fwd_hi_r, lsu_raw_fwd_lo_r}), .clk(lsu_c2_r_clk)); - -`ifdef ASSERT_ON +`ifdef RV_ASSERT_ON logic [1:0] store_data_bypass_sel; assign store_data_bypass_sel[1:0] = {lsu_p.store_data_bypass_d, lsu_p.store_data_bypass_m}; + property exception_no_lsu_flush; @(posedge clk) disable iff(~rst_l) lsu_lsc_ctl.lsu_error_pkt_m.exc_valid |-> ##[1:2] (flush_r ); endproperty diff --git a/design/lsu/el2_lsu_addrcheck.sv b/design/lsu/el2_lsu_addrcheck.sv index e63db2b..2abe8e1 100644 --- a/design/lsu/el2_lsu_addrcheck.sv +++ b/design/lsu/el2_lsu_addrcheck.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,16 +27,16 @@ import el2_pkg::*; #( `include "el2_param.vh" )( - input logic lsu_c2_m_clk, // clock - input logic rst_l, // reset + input logic lsu_c2_m_clk, // clock + input logic rst_l, // reset input logic [31:0] start_addr_d, // start address for lsu input logic [31:0] end_addr_d, // end address for lsu input el2_lsu_pkt_t lsu_pkt_d, // packet in d - input logic [31:0] dec_tlu_mrac_ff, // CSR read - input logic [3:0] rs1_region_d, + input logic [31:0] dec_tlu_mrac_ff, // CSR read + input logic [3:0] rs1_region_d, // address rs operand [31:28] - input logic [31:0] rs1_d, + input logic [31:0] rs1_d, // address rs operand output logic is_sideeffects_m, // is sideffects space output logic addr_in_dccm_d, // address in dccm @@ -50,7 +50,7 @@ import el2_pkg::*; output logic fir_dccm_access_error_d, // Fast interrupt dccm access error output logic fir_nondccm_access_error_d,// Fast interrupt dccm access error - input logic scan_mode + input logic scan_mode // Scan mode ); @@ -116,7 +116,7 @@ import el2_pkg::*; ); assign start_addr_dccm_or_pic = start_addr_in_dccm_region_d | start_addr_in_pic_region_d; - assign base_reg_dccm_or_pic = (rs1_region_d[3:0] == pt.DCCM_REGION) | (rs1_region_d[3:0] == pt.PIC_REGION); + assign base_reg_dccm_or_pic = ((rs1_region_d[3:0] == pt.DCCM_REGION) & pt.DCCM_ENABLE) | (rs1_region_d[3:0] == pt.PIC_REGION); assign addr_in_dccm_d = (start_addr_in_dccm_d & end_addr_in_dccm_d); assign addr_in_pic_d = (start_addr_in_pic_d & end_addr_in_pic_d); @@ -154,7 +154,7 @@ import el2_pkg::*; assign regpred_access_fault_d = (start_addr_dccm_or_pic ^ base_reg_dccm_or_pic); // 5. Region predication access fault: Base Address in DCCM/PIC and Final address in non-DCCM/non-PIC region or vice versa assign picm_access_fault_d = (addr_in_pic_d & ((start_addr_d[1:0] != 2'b0) | ~lsu_pkt_d.word)); // 6. Ld/St access to picm are not word aligned or word size - if (pt.DCCM_REGION == pt.PIC_REGION) begin + if (pt.DCCM_ENABLE & (pt.DCCM_REGION == pt.PIC_REGION)) begin assign unmapped_access_fault_d = ((start_addr_in_dccm_region_d & ~(start_addr_in_dccm_d | start_addr_in_pic_d)) | // 0. Addr in dccm/pic region but not in dccm/pic offset (end_addr_in_dccm_region_d & ~(end_addr_in_dccm_d | end_addr_in_pic_d)) | // 0. Addr in dccm/pic region but not in dccm/pic offset (start_addr_in_dccm_d & end_addr_in_pic_d) | // 0. DCCM -> PIC cross when DCCM/PIC in same region diff --git a/design/lsu/el2_lsu_bus_buffer.sv b/design/lsu/el2_lsu_bus_buffer.sv index 33f6379..8e85278 100644 --- a/design/lsu/el2_lsu_bus_buffer.sv +++ b/design/lsu/el2_lsu_bus_buffer.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,15 +28,18 @@ import el2_pkg::*; #( `include "el2_param.vh" )( - input logic clk, - input logic rst_l, - input logic scan_mode, + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic clk_override, // Override non-functional clock gating + input logic rst_l, // reset, active low + input logic scan_mode, // scan mode input logic dec_tlu_external_ldfwd_disable, // disable load to load forwarding for externals input logic dec_tlu_wb_coalescing_disable, // disable write buffer coalescing input logic dec_tlu_sideeffect_posted_disable, // Don't block the sideeffect load store to the bus input logic dec_tlu_force_halt, // various clocks needed for the bus reads and writes + input logic lsu_bus_obuf_c1_clken, + input logic lsu_busm_clken, input logic lsu_c2_r_clk, input logic lsu_bus_ibuf_c1_clk, input logic lsu_bus_obuf_c1_clk, @@ -68,12 +71,11 @@ import el2_pkg::*; input logic ldst_dual_m, // load/store is unaligned at 32 bit boundary input logic ldst_dual_r, // load/store is unaligned at 32 bit boundary - input logic [7:0] ldst_byteen_ext_m, + input logic [7:0] ldst_byteen_ext_m, // HI and LO signals output logic lsu_bus_buffer_pend_any, // bus buffer has a pending bus entry output logic lsu_bus_buffer_full_any, // bus buffer is full output logic lsu_bus_buffer_empty_any, // bus buffer is empty - output logic lsu_bus_idle_any, // No pending responses from the bus output logic [3:0] ld_byte_hit_buf_lo, ld_byte_hit_buf_hi, // Byte enables for forwarding data output logic [31:0] ld_fwddata_buf_lo, ld_fwddata_buf_hi, // load forwarding data @@ -87,11 +89,10 @@ import el2_pkg::*; output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_tag_m, // the tag of the external non block load output logic lsu_nonblock_load_inv_r, // invalidate signal for the cam entry for non block loads output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_inv_tag_r, // tag of the enrty which needs to be invalidated - output logic lsu_nonblock_load_data_valid, // the non block is valid - sending information back to the cam - output logic lsu_nonblock_load_data_error, // non block load has an error - output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // the tag of the non block load sending the data/error - output logic [31:0] lsu_nonblock_load_data, // Data of the non block load - + output logic lsu_nonblock_load_data_valid, // the non block is valid - sending information back to the cam + output logic lsu_nonblock_load_data_error, // non block load has an error + output logic [pt.LSU_NUM_NBLOAD_WIDTH-1:0] lsu_nonblock_load_data_tag, // the tag of the non block load sending the data/error + output logic [31:0] lsu_nonblock_load_data, // Data of the non block load // PMU events output logic lsu_pmu_bus_trxn, @@ -149,7 +150,6 @@ import el2_pkg::*; ); - // For Ld: IDLE -> WAIT -> CMD -> RESP -> DONE_PARTIAL(?) -> DONE_WAIT(?) -> DONE -> IDLE // For St: IDLE -> WAIT -> CMD -> RESP(?) -> IDLE typedef enum logic [2:0] {IDLE=3'b000, WAIT=3'b001, CMD=3'b010, RESP=3'b011, DONE_PARTIAL=3'b100, DONE_WAIT=3'b101, DONE=3'b110} state_t; @@ -178,7 +178,7 @@ import el2_pkg::*; logic [31:0] lsu_nonblock_load_data_hi, lsu_nonblock_load_data_lo, lsu_nonblock_data_unalgn; logic [1:0] lsu_nonblock_addr_offset; logic [1:0] lsu_nonblock_sz; - logic lsu_nonblock_unsign, lsu_nonblock_dual; + logic lsu_nonblock_unsign; logic lsu_nonblock_load_data_ready; logic [DEPTH-1:0] CmdPtr0Dec, CmdPtr1Dec; @@ -191,10 +191,7 @@ import el2_pkg::*; logic [3:0] buf_numvld_any, buf_numvld_wrcmd_any, buf_numvld_cmd_any, buf_numvld_pend_any; logic any_done_wait_state; logic bus_sideeffect_pend; - logic [7:0] bus_pend_trxn, bus_pend_trxnQ, bus_pend_trxn_ns; - logic lsu_bus_cntr_overflow; logic bus_coalescing_disable; - logic mdbhd_en; logic bus_addr_match_pending; logic bus_cmd_sent, bus_cmd_ready; @@ -219,7 +216,6 @@ import el2_pkg::*; logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_dualtag; logic [DEPTH-1:0] buf_ldfwd; logic [DEPTH-1:0][DEPTH_LOG2-1:0] buf_ldfwdtag; - //logic [DEPTH-1:0] buf_nb; logic [DEPTH-1:0] buf_error; logic [DEPTH-1:0][31:0] buf_data; logic [DEPTH-1:0][DEPTH-1:0] buf_age, buf_age_younger; @@ -234,7 +230,6 @@ import el2_pkg::*; logic [DEPTH-1:0] buf_dual_in; logic [DEPTH-1:0] buf_samedw_in; logic [DEPTH-1:0] buf_nomerge_in; - //logic [DEPTH-1:0] buf_nb_in; logic [DEPTH-1:0] buf_sideeffect_in; logic [DEPTH-1:0] buf_unsign_in; logic [DEPTH-1:0][1:0] buf_sz_in; @@ -263,7 +258,6 @@ import el2_pkg::*; logic ibuf_nomerge; logic [DEPTH_LOG2-1:0] ibuf_tag; logic [DEPTH_LOG2-1:0] ibuf_dualtag; - //logic ibuf_nb; logic ibuf_sideeffect; logic ibuf_unsign; logic ibuf_write; @@ -313,6 +307,7 @@ import el2_pkg::*; logic obuf_rst; logic obuf_write_in; logic obuf_nosend_in; + logic obuf_rdrsp_pend_en; logic obuf_rdrsp_pend_in; logic obuf_sideeffect_in; logic obuf_aligned_in; @@ -331,15 +326,15 @@ import el2_pkg::*; logic [7:0] obuf_byteen0_in, obuf_byteen1_in; logic [63:0] obuf_data0_in, obuf_data1_in; - logic lsu_axi_awvalid_q, lsu_axi_awready_q; - logic lsu_axi_wvalid_q, lsu_axi_wready_q; - logic lsu_axi_arvalid_q, lsu_axi_arready_q; - logic lsu_axi_bvalid_q, lsu_axi_bready_q; - logic lsu_axi_rvalid_q, lsu_axi_rready_q; - logic [pt.LSU_BUS_TAG-1:0] lsu_axi_bid_q, lsu_axi_rid_q; - logic [1:0] lsu_axi_bresp_q, lsu_axi_rresp_q; - logic [DEPTH_LOG2-1:0] lsu_imprecise_error_store_tag; - logic [63:0] lsu_axi_rdata_q; + logic lsu_axi_awvalid_q, lsu_axi_awready_q; + logic lsu_axi_wvalid_q, lsu_axi_wready_q; + logic lsu_axi_arvalid_q, lsu_axi_arready_q; + logic lsu_axi_bvalid_q, lsu_axi_bready_q; + logic lsu_axi_rvalid_q, lsu_axi_rready_q; + logic [pt.LSU_BUS_TAG-1:0] lsu_axi_bid_q, lsu_axi_rid_q; + logic [1:0] lsu_axi_bresp_q, lsu_axi_rresp_q; + logic [pt.LSU_BUS_TAG-1:0] lsu_imprecise_error_store_tag; + logic [63:0] lsu_axi_rdata_q; //------------------------------------------------------------------------------ // Load forwarding logic start @@ -360,7 +355,7 @@ import el2_pkg::*; // Buffer hit logic for bus load forwarding assign ldst_byteen_hi_m[3:0] = ldst_byteen_ext_m[7:4]; assign ldst_byteen_lo_m[3:0] = ldst_byteen_ext_m[3:0]; - for (genvar i=0; i<32'(DEPTH); i++) begin + for (genvar i=0; i 4'b0) & (obuf_wr_timer < TIMER_LOG2'(TIMER_MAX))) ? (obuf_wr_timer + 1'b1) : obuf_wr_timer); + assign obuf_wr_timer_in = obuf_wr_en ? 3'b0: (((buf_numvld_cmd_any > 4'b0) & (obuf_wr_timer < TIMER_MAX)) ? (obuf_wr_timer + 1'b1) : obuf_wr_timer); assign obuf_force_wr_en = lsu_busreq_m & ~lsu_busreq_r & ~ibuf_valid & (buf_numvld_cmd_any[3:0] == 4'b1) & (lsu_addr_m[31:2] != buf_addr[CmdPtr0][31:2]); // Entry in m can't merge with entry going to obuf and there is no entry in between assign ibuf_buf_byp = ibuf_byp & (buf_numvld_pend_any[3:0] == 4'b0) & (~lsu_pkt_r.store | no_dword_merge_r); assign obuf_wr_en = ((ibuf_buf_byp & lsu_commit_r & ~(is_sideeffects_r & bus_sideeffect_pend)) | ((buf_state[CmdPtr0] == CMD) & found_cmdptr0 & ~buf_cmd_state_bus_en[CmdPtr0] & ~(buf_sideeffect[CmdPtr0] & bus_sideeffect_pend) & (~(buf_dual[CmdPtr0] & buf_samedw[CmdPtr0] & ~buf_write[CmdPtr0]) | found_cmdptr1 | buf_nomerge[CmdPtr0] | obuf_force_wr_en))) & - (bus_cmd_ready | ~obuf_valid | obuf_nosend) & ~obuf_wr_wait & ~lsu_bus_cntr_overflow & ~bus_addr_match_pending & lsu_bus_clk_en; + (bus_cmd_ready | ~obuf_valid | obuf_nosend) & ~obuf_wr_wait & ~bus_addr_match_pending & lsu_bus_clk_en; assign obuf_rst = ((bus_cmd_sent | (obuf_valid & obuf_nosend)) & ~obuf_wr_en & lsu_bus_clk_en) | dec_tlu_force_halt; @@ -505,10 +499,10 @@ import el2_pkg::*; (obuf_sz_in[0] & ~obuf_addr_in[0]) | (obuf_sz_in[1] & ~(|obuf_addr_in[1:0]))); - assign obuf_rdrsp_pend_in = (~(obuf_wr_en & ~obuf_nosend_in) & obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag))) | - ((bus_cmd_sent & ~obuf_write) & ~dec_tlu_force_halt) ; + assign obuf_rdrsp_pend_in = ((~(obuf_wr_en & ~obuf_nosend_in) & obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag))) | (bus_cmd_sent & ~obuf_write)) & ~dec_tlu_force_halt; + assign obuf_rdrsp_pend_en = lsu_bus_clk_en | dec_tlu_force_halt; assign obuf_rdrsp_tag_in[pt.LSU_BUS_TAG-1:0] = (bus_cmd_sent & ~obuf_write) ? obuf_tag0[pt.LSU_BUS_TAG-1:0] : obuf_rdrsp_tag[pt.LSU_BUS_TAG-1:0]; - // No ld to ld fwd for aligned & atomic64 + // No ld to ld fwd for aligned assign obuf_nosend_in = (obuf_addr_in[31:3] == obuf_addr[31:3]) & obuf_aligned_in & ~obuf_sideeffect & ~obuf_write & ~obuf_write_in & ~dec_tlu_external_ldfwd_disable & ((obuf_valid & ~obuf_nosend) | (obuf_rdrsp_pend & ~(bus_rsp_read & (bus_rsp_read_tag == obuf_rdrsp_tag)))); @@ -516,9 +510,9 @@ import el2_pkg::*; (buf_addr[CmdPtr0][2] ? {buf_byteen[CmdPtr0],4'b0} : {4'b0,buf_byteen[CmdPtr0]}); assign obuf_byteen1_in[7:0] = ibuf_buf_byp ? (end_addr_r[2] ? {ldst_byteen_hi_r[3:0],4'b0} : {4'b0,ldst_byteen_hi_r[3:0]}) : (buf_addr[CmdPtr1][2] ? {buf_byteen[CmdPtr1],4'b0} : {4'b0,buf_byteen[CmdPtr1]}); - assign obuf_data0_in[63:0] = ibuf_buf_byp ? (lsu_addr_r[2] ? {store_data_lo_r[31:0],32'b0} : {32'b0,store_data_lo_r[31:0]}) : + assign obuf_data0_in[63:0] = ibuf_buf_byp ? (lsu_addr_r[2] ? {store_data_lo_r[31:0],32'b0} : {32'b0,store_data_lo_r[31:0]}) : (buf_addr[CmdPtr0][2] ? {buf_data[CmdPtr0],32'b0} : {32'b0,buf_data[CmdPtr0]}); - assign obuf_data1_in[63:0] = ibuf_buf_byp ? (lsu_addr_r[2] ? {store_data_hi_r[31:0],32'b0} :{32'b0,store_data_hi_r[31:0]}) : + assign obuf_data1_in[63:0] = ibuf_buf_byp ? (end_addr_r[2] ? {store_data_hi_r[31:0],32'b0} :{32'b0,store_data_hi_r[31:0]}) : (buf_addr[CmdPtr1][2] ? {buf_data[CmdPtr1],32'b0} : {32'b0,buf_data[CmdPtr1]}); for (genvar i=0 ;i<8; i++) begin @@ -529,28 +523,27 @@ import el2_pkg::*; // No store obuf merging for AXI since all stores are sent non-posted. Can't track the second id right now assign obuf_merge_en = ((CmdPtr0 != CmdPtr1) & found_cmdptr0 & found_cmdptr1 & (buf_state[CmdPtr0] == CMD) & (buf_state[CmdPtr1] == CMD) & ~buf_cmd_state_bus_en[CmdPtr0] & ~buf_sideeffect[CmdPtr0] & - ((buf_write[CmdPtr0] & buf_write[CmdPtr1] & (buf_addr[CmdPtr0][31:3] == buf_addr[CmdPtr1][31:3]) & ~bus_coalescing_disable & ~pt.BUILD_AXI_NATIVE) | - (~buf_write[CmdPtr0] & buf_dual[CmdPtr0] & ~buf_dualhi[CmdPtr0] & buf_samedw[CmdPtr0]))) | // CmdPtr0/CmdPtr1 are for same load which is within a DW + (~buf_write[CmdPtr0] & buf_dual[CmdPtr0] & ~buf_dualhi[CmdPtr0] & buf_samedw[CmdPtr0])) | // CmdPtr0/CmdPtr1 are for same load which is within a DW (ibuf_buf_byp & ldst_samedw_r & ldst_dual_r); - rvdff #(.WIDTH(1)) obuf_wren_ff (.din(obuf_wr_en), .dout(obuf_wr_enQ), .clk(lsu_busm_clk), .*); - rvdffsc #(.WIDTH(1)) obuf_valid_ff (.din(1'b1), .dout(obuf_valid), .en(obuf_wr_en), .clear(obuf_rst), .clk(lsu_free_c2_clk), .*); - rvdffs #(.WIDTH(1)) obuf_nosend_ff (.din(obuf_nosend_in), .dout(obuf_nosend), .en(obuf_wr_en), .clk(lsu_free_c2_clk), .*); - rvdff #(.WIDTH(1)) obuf_cmd_done_ff (.din(obuf_cmd_done_in), .dout(obuf_cmd_done), .clk(lsu_busm_clk), .*); - rvdff #(.WIDTH(1)) obuf_data_done_ff (.din(obuf_data_done_in), .dout(obuf_data_done), .clk(lsu_busm_clk), .*); - rvdff #(.WIDTH(1)) obuf_rdrsp_pend_ff(.din(obuf_rdrsp_pend_in), .dout(obuf_rdrsp_pend), .clk(lsu_busm_clk), .*); - rvdff #(.WIDTH(pt.LSU_BUS_TAG)) obuf_rdrsp_tagff (.din(obuf_rdrsp_tag_in), .dout(obuf_rdrsp_tag), .clk(lsu_busm_clk), .*); - rvdffs #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag0ff (.din(obuf_tag0_in), .dout(obuf_tag0), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); - rvdffs #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag1ff (.din(obuf_tag1_in), .dout(obuf_tag1), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); - rvdffs #(.WIDTH(1)) obuf_mergeff (.din(obuf_merge_in), .dout(obuf_merge), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); - rvdffs #(.WIDTH(1)) obuf_writeff (.din(obuf_write_in), .dout(obuf_write), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); - rvdffs #(.WIDTH(1)) obuf_sideeffectff (.din(obuf_sideeffect_in), .dout(obuf_sideeffect), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); - rvdffs #(.WIDTH(2)) obuf_szff (.din(obuf_sz_in[1:0]), .dout(obuf_sz), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); - rvdffe #(.WIDTH(32)) obuf_addrff (.din(obuf_addr_in[31:0]), .dout(obuf_addr), .en(obuf_wr_en), .*); - rvdffs #(.WIDTH(8)) obuf_byteenff (.din(obuf_byteen_in[7:0]), .dout(obuf_byteen), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .*); - rvdffe #(.WIDTH(64)) obuf_dataff (.din(obuf_data_in[63:0]), .dout(obuf_data), .en(obuf_wr_en), .*); - rvdff #(.WIDTH(TIMER_LOG2)) obuf_timerff (.din(obuf_wr_timer_in), .dout(obuf_wr_timer), .clk(lsu_busm_clk), .*); + rvdff_fpga #(.WIDTH(1)) obuf_wren_ff (.din(obuf_wr_en), .dout(obuf_wr_enQ), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); + rvdffsc #(.WIDTH(1)) obuf_valid_ff (.din(1'b1), .dout(obuf_valid), .en(obuf_wr_en), .clear(obuf_rst), .clk(lsu_free_c2_clk), .*); + rvdffs #(.WIDTH(1)) obuf_nosend_ff (.din(obuf_nosend_in), .dout(obuf_nosend), .en(obuf_wr_en), .clk(lsu_free_c2_clk), .*); + rvdffs #(.WIDTH(1)) obuf_rdrsp_pend_ff(.din(obuf_rdrsp_pend_in), .dout(obuf_rdrsp_pend), .en(obuf_rdrsp_pend_en), .clk(lsu_free_c2_clk), .*); + rvdff_fpga #(.WIDTH(1)) obuf_cmd_done_ff (.din(obuf_cmd_done_in), .dout(obuf_cmd_done), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); + rvdff_fpga #(.WIDTH(1)) obuf_data_done_ff (.din(obuf_data_done_in), .dout(obuf_data_done), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); + rvdff_fpga #(.WIDTH(pt.LSU_BUS_TAG)) obuf_rdrsp_tagff (.din(obuf_rdrsp_tag_in), .dout(obuf_rdrsp_tag), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag0ff (.din(obuf_tag0_in), .dout(obuf_tag0), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(pt.LSU_BUS_TAG)) obuf_tag1ff (.din(obuf_tag1_in), .dout(obuf_tag1), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(1)) obuf_mergeff (.din(obuf_merge_in), .dout(obuf_merge), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(1)) obuf_writeff (.din(obuf_write_in), .dout(obuf_write), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(1)) obuf_sideeffectff (.din(obuf_sideeffect_in), .dout(obuf_sideeffect), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(2)) obuf_szff (.din(obuf_sz_in[1:0]), .dout(obuf_sz), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); + rvdffs_fpga #(.WIDTH(8)) obuf_byteenff (.din(obuf_byteen_in[7:0]), .dout(obuf_byteen), .en(obuf_wr_en), .clk(lsu_bus_obuf_c1_clk), .clken(lsu_bus_obuf_c1_clken), .rawclk(clk), .*); + rvdffe #(.WIDTH(32)) obuf_addrff (.din(obuf_addr_in[31:0]), .dout(obuf_addr), .en(obuf_wr_en), .*); + rvdffe #(.WIDTH(64)) obuf_dataff (.din(obuf_data_in[63:0]), .dout(obuf_data), .en(obuf_wr_en), .*); + rvdff_fpga #(.WIDTH(TIMER_LOG2)) obuf_timerff (.din(obuf_wr_timer_in), .dout(obuf_wr_timer), .clk(lsu_busm_clk), .clken(lsu_busm_clken), .rawclk(clk), .*); //------------------------------------------------------------------------------ @@ -565,27 +558,27 @@ import el2_pkg::*; found_wrptr1 = '0; // Find first write pointer - for (int i=0; i<32'(DEPTH); i++) begin + for (int i=0; i= (DEPTH-1)) : (buf_numvld_any[3:0] == 4'(DEPTH)); + assign lsu_bus_buffer_full_any = (ldst_dual_d & dec_lsu_valid_raw_d) ? (buf_numvld_any[3:0] >= (DEPTH-1)) : (buf_numvld_any[3:0] == DEPTH); assign lsu_bus_buffer_empty_any = ~(|buf_state[DEPTH-1:0]) & ~ibuf_valid & ~obuf_valid; @@ -797,9 +791,9 @@ import el2_pkg::*; lsu_nonblock_load_data_tag[DEPTH_LOG2-1:0] = '0; lsu_nonblock_load_data_lo[31:0] = '0; lsu_nonblock_load_data_hi[31:0] = '0; - for (int i=0; i<32'(DEPTH); i++) begin + for (int i=0; i> 8*lsu_nonblock_addr_offset[1:0]); assign lsu_nonblock_load_data_valid = lsu_nonblock_load_data_ready & ~lsu_nonblock_load_data_error; @@ -823,7 +816,7 @@ import el2_pkg::*; // Determine if there is a pending return to sideeffect load/store always_comb begin bus_sideeffect_pend = obuf_valid & obuf_sideeffect & dec_tlu_sideeffect_posted_disable; - for (int i=0; i<32'(DEPTH); i++) begin + for (int i=0; i ((lsu_axi_awsize[2:0] == 3'h0) | - ((lsu_axi_awsize[2:0] == 3'h1) & (lsu_axi_awaddr[0] == 1'b0)) | - ((lsu_axi_awsize[2:0] == 3'h2) & (lsu_axi_awaddr[1:0] == 2'b0)) | - ((lsu_axi_awsize[2:0] == 3'h3) & (lsu_axi_awaddr[2:0] == 3'b0))); - endproperty - assert_lsu_axi_awaddr_aligned: assert property (lsu_axi_awaddr_aligned) else - $display("Assertion lsu_axi_awaddr_aligned failed: lsu_axi_awvalid=1'b%b, lsu_axi_awsize=3'h%h, lsu_axi_awaddr=32'h%h",lsu_axi_awvalid, lsu_axi_awsize[2:0], lsu_axi_awaddr[31:0]); - // Assertion to check awvalid stays stable during entire bus clock + // Assertion to check AXI write address is aligned to size + property lsu_axi_awaddr_aligned; + @(posedge lsu_busm_clk) disable iff(~rst_l) lsu_axi_awvalid |-> ((lsu_axi_awsize[2:0] == 3'h0) | + ((lsu_axi_awsize[2:0] == 3'h1) & (lsu_axi_awaddr[0] == 1'b0)) | + ((lsu_axi_awsize[2:0] == 3'h2) & (lsu_axi_awaddr[1:0] == 2'b0)) | + ((lsu_axi_awsize[2:0] == 3'h3) & (lsu_axi_awaddr[2:0] == 3'b0))); + endproperty + assert_lsu_axi_awaddr_aligned: assert property (lsu_axi_awaddr_aligned) else + $display("Assertion lsu_axi_awaddr_aligned failed: lsu_axi_awvalid=1'b%b, lsu_axi_awsize=3'h%h, lsu_axi_awaddr=32'h%h",lsu_axi_awvalid, lsu_axi_awsize[2:0], lsu_axi_awaddr[31:0]); + // Assertion to check awvalid stays stable during entire bus clock - // Assertion to check AXI read address is aligned to size - property lsu_axi_araddr_aligned; - @(posedge lsu_busm_clk) disable iff(~rst_l) lsu_axi_arvalid |-> ((lsu_axi_arsize[2:0] == 3'h0) | - ((lsu_axi_arsize[2:0] == 3'h1) & (lsu_axi_araddr[0] == 1'b0)) | - ((lsu_axi_arsize[2:0] == 3'h2) & (lsu_axi_araddr[1:0] == 2'b0)) | - ((lsu_axi_arsize[2:0] == 3'h3) & (lsu_axi_araddr[2:0] == 3'b0))); - endproperty - assert_lsu_axi_araddr_aligned: assert property (lsu_axi_araddr_aligned) else - $display("Assertion lsu_axi_araddr_aligned failed: lsu_axi_awvalid=1'b%b, lsu_axi_awsize=3'h%h, lsu_axi_araddr=32'h%h",lsu_axi_awvalid, lsu_axi_awsize[2:0], lsu_axi_araddr[31:0]); + // Assertion to check AXI read address is aligned to size + property lsu_axi_araddr_aligned; + @(posedge lsu_busm_clk) disable iff(~rst_l) lsu_axi_arvalid |-> ((lsu_axi_arsize[2:0] == 3'h0) | + ((lsu_axi_arsize[2:0] == 3'h1) & (lsu_axi_araddr[0] == 1'b0)) | + ((lsu_axi_arsize[2:0] == 3'h2) & (lsu_axi_araddr[1:0] == 2'b0)) | + ((lsu_axi_arsize[2:0] == 3'h3) & (lsu_axi_araddr[2:0] == 3'b0))); + endproperty + assert_lsu_axi_araddr_aligned: assert property (lsu_axi_araddr_aligned) else + $display("Assertion lsu_axi_araddr_aligned failed: lsu_axi_awvalid=1'b%b, lsu_axi_awsize=3'h%h, lsu_axi_araddr=32'h%h",lsu_axi_awvalid, lsu_axi_awsize[2:0], lsu_axi_araddr[31:0]); - // Assertion to check awvalid stays stable during entire bus clock - property lsu_axi_awvalid_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid != $past(lsu_axi_awvalid)) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_awvalid_stable: assert property (lsu_axi_awvalid_stable) else - $display("LSU AXI awvalid changed in middle of bus clock"); + // Assertion to check awvalid stays stable during entire bus clock + property lsu_axi_awvalid_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid != $past(lsu_axi_awvalid)) |-> ($past(lsu_bus_clk_en) | dec_tlu_force_halt); + endproperty + assert_lsu_axi_awvalid_stable: assert property (lsu_axi_awvalid_stable) else + $display("LSU AXI awvalid changed in middle of bus clock"); - // Assertion to check awid stays stable during entire bus clock - property lsu_axi_awid_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid & (lsu_axi_awid[pt.LSU_BUS_TAG-1:0] != $past(lsu_axi_awid[pt.LSU_BUS_TAG-1:0]))) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_awid_stable: assert property (lsu_axi_awid_stable) else - $display("LSU AXI awid changed in middle of bus clock"); + // Assertion to check awid stays stable during entire bus clock + property lsu_axi_awid_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid & (lsu_axi_awid[pt.LSU_BUS_TAG-1:0] != $past(lsu_axi_awid[pt.LSU_BUS_TAG-1:0]))) |-> $past(lsu_bus_clk_en); + endproperty + assert_lsu_axi_awid_stable: assert property (lsu_axi_awid_stable) else + $display("LSU AXI awid changed in middle of bus clock"); - // Assertion to check awaddr stays stable during entire bus clock - property lsu_axi_awaddr_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid & (lsu_axi_awaddr[31:0] != $past(lsu_axi_awaddr[31:0]))) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_awaddr_stable: assert property (lsu_axi_awaddr_stable) else - $display("LSU AXI awaddr changed in middle of bus clock"); + // Assertion to check awaddr stays stable during entire bus clock + property lsu_axi_awaddr_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid & (lsu_axi_awaddr[31:0] != $past(lsu_axi_awaddr[31:0]))) |-> $past(lsu_bus_clk_en); + endproperty + assert_lsu_axi_awaddr_stable: assert property (lsu_axi_awaddr_stable) else + $display("LSU AXI awaddr changed in middle of bus clock"); - // Assertion to check awsize stays stable during entire bus clock - property lsu_axi_awsize_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid & (lsu_axi_awsize[2:0] != $past(lsu_axi_awsize[2:0]))) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_awsize_stable: assert property (lsu_axi_awsize_stable) else - $display("LSU AXI awsize changed in middle of bus clock"); + // Assertion to check awsize stays stable during entire bus clock + property lsu_axi_awsize_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid & (lsu_axi_awsize[2:0] != $past(lsu_axi_awsize[2:0]))) |-> $past(lsu_bus_clk_en); + endproperty + assert_lsu_axi_awsize_stable: assert property (lsu_axi_awsize_stable) else + $display("LSU AXI awsize changed in middle of bus clock"); - // Assertion to check wstrb stays stable during entire bus clock - property lsu_axi_wstrb_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_wvalid & (lsu_axi_wstrb[7:0] != $past(lsu_axi_wstrb[7:0]))) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_wstrb_stable: assert property (lsu_axi_wstrb_stable) else - $display("LSU AXI wstrb changed in middle of bus clock"); + // Assertion to check wstrb stays stable during entire bus clock + property lsu_axi_wstrb_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_wvalid & (lsu_axi_wstrb[7:0] != $past(lsu_axi_wstrb[7:0]))) |-> $past(lsu_bus_clk_en); + endproperty + assert_lsu_axi_wstrb_stable: assert property (lsu_axi_wstrb_stable) else + $display("LSU AXI wstrb changed in middle of bus clock"); - // Assertion to check wdata stays stable during entire bus clock - property lsu_axi_wdata_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_wvalid & (lsu_axi_wdata[63:0] != $past(lsu_axi_wdata[63:0]))) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_wdata_stable: assert property (lsu_axi_wdata_stable) else - $display("LSU AXI wdata changed in middle of bus clock"); + // Assertion to check wdata stays stable during entire bus clock + property lsu_axi_wdata_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_wvalid & (lsu_axi_wdata[63:0] != $past(lsu_axi_wdata[63:0]))) |-> $past(lsu_bus_clk_en); + endproperty + assert_lsu_axi_wdata_stable: assert property (lsu_axi_wdata_stable) else + $display("LSU AXI wdata changed in middle of bus clock"); - // Assertion to check awvalid stays stable during entire bus clock - property lsu_axi_arvalid_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_arvalid != $past(lsu_axi_arvalid)) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_arvalid_stable: assert property (lsu_axi_arvalid_stable) else - $display("LSU AXI awvalid changed in middle of bus clock"); + // Assertion to check awvalid stays stable during entire bus clock + property lsu_axi_arvalid_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_arvalid != $past(lsu_axi_arvalid)) |-> ($past(lsu_bus_clk_en) | dec_tlu_force_halt); + endproperty + assert_lsu_axi_arvalid_stable: assert property (lsu_axi_arvalid_stable) else + $display("LSU AXI awvalid changed in middle of bus clock"); - // Assertion to check awid stays stable during entire bus clock - property lsu_axi_arid_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_arvalid & (lsu_axi_arid[pt.LSU_BUS_TAG-1:0] != $past(lsu_axi_arid[pt.LSU_BUS_TAG-1:0]))) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_arid_stable: assert property (lsu_axi_arid_stable) else - $display("LSU AXI awid changed in middle of bus clock"); + // Assertion to check awid stays stable during entire bus clock + property lsu_axi_arid_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_arvalid & (lsu_axi_arid[pt.LSU_BUS_TAG-1:0] != $past(lsu_axi_arid[pt.LSU_BUS_TAG-1:0]))) |-> $past(lsu_bus_clk_en); + endproperty + assert_lsu_axi_arid_stable: assert property (lsu_axi_arid_stable) else + $display("LSU AXI awid changed in middle of bus clock"); - // Assertion to check awaddr stays stable during entire bus clock - property lsu_axi_araddr_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_arvalid & (lsu_axi_araddr[31:0] != $past(lsu_axi_araddr[31:0]))) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_araddr_stable: assert property (lsu_axi_araddr_stable) else - $display("LSU AXI awaddr changed in middle of bus clock"); + // Assertion to check awaddr stays stable during entire bus clock + property lsu_axi_araddr_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_arvalid & (lsu_axi_araddr[31:0] != $past(lsu_axi_araddr[31:0]))) |-> $past(lsu_bus_clk_en); + endproperty + assert_lsu_axi_araddr_stable: assert property (lsu_axi_araddr_stable) else + $display("LSU AXI awaddr changed in middle of bus clock"); - // Assertion to check awsize stays stable during entire bus clock - property lsu_axi_arsize_stable; - @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid & (lsu_axi_arsize[2:0] != $past(lsu_axi_arsize[2:0]))) |-> $past(lsu_bus_clk_en); - endproperty - assert_lsu_axi_arsize_stable: assert property (lsu_axi_arsize_stable) else - $display("LSU AXI awsize changed in middle of bus clock"); + // Assertion to check awsize stays stable during entire bus clock + property lsu_axi_arsize_stable; + @(posedge clk) disable iff(~rst_l) (lsu_axi_awvalid & (lsu_axi_arsize[2:0] != $past(lsu_axi_arsize[2:0]))) |-> $past(lsu_bus_clk_en); + endproperty + assert_lsu_axi_arsize_stable: assert property (lsu_axi_arsize_stable) else + $display("LSU AXI awsize changed in middle of bus clock"); `endif diff --git a/design/lsu/el2_lsu_clkdomain.sv b/design/lsu/el2_lsu_clkdomain.sv index bc27f5c..e5b4abf 100644 --- a/design/lsu/el2_lsu_clkdomain.sv +++ b/design/lsu/el2_lsu_clkdomain.sv @@ -1,4 +1,4 @@ -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,13 +28,13 @@ import el2_pkg::*; #( `include "el2_param.vh" )( - input logic clk, // clock - input logic free_clk, // clock - input logic rst_l, // reset + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in. + input logic rst_l, // reset, active low + input logic dec_tlu_force_halt, // This will be high till TLU goes to debug halt // Inputs input logic clk_override, // chciken bit to turn off clock gating - input logic addr_in_dccm_m, // address in dccm input logic dma_dccm_req, // dma is active input logic ldst_stbuf_reqvld_r, // allocating in to the store queue @@ -47,12 +47,15 @@ import el2_pkg::*; input logic lsu_bus_clk_en, // bus clock enable - input el2_lsu_pkt_t lsu_p, // lsu packet in decode - input el2_lsu_pkt_t lsu_pkt_d, // lsu packet in d - input el2_lsu_pkt_t lsu_pkt_m, // lsu packet in m - input el2_lsu_pkt_t lsu_pkt_r, // lsu packet in r + input el2_lsu_pkt_t lsu_p, // lsu packet in decode + input el2_lsu_pkt_t lsu_pkt_d, // lsu packet in d + input el2_lsu_pkt_t lsu_pkt_m, // lsu packet in m + input el2_lsu_pkt_t lsu_pkt_r, // lsu packet in r // Outputs + output logic lsu_bus_obuf_c1_clken, // obuf clock enable + output logic lsu_busm_clken, // bus clock enable + output logic lsu_c1_m_clk, // m pipe single pulse clock output logic lsu_c1_r_clk, // r pipe single pulse clock @@ -68,19 +71,19 @@ import el2_pkg::*; output logic lsu_bus_buf_c1_clk, // ibuf clock output logic lsu_busm_clk, // bus clock - output logic lsu_free_c2_clk, + output logic lsu_free_c2_clk, // free double pulse clock - input logic scan_mode + input logic scan_mode // Scan mode ); - logic lsu_c1_d_clken, lsu_c1_m_clken, lsu_c1_r_clken; + logic lsu_c1_m_clken, lsu_c1_r_clken; logic lsu_c2_m_clken, lsu_c2_r_clken; - logic lsu_c1_d_clken_q, lsu_c1_m_clken_q, lsu_c1_r_clken_q; + logic lsu_c1_m_clken_q, lsu_c1_r_clken_q; logic lsu_store_c1_m_clken, lsu_store_c1_r_clken; logic lsu_stbuf_c1_clken; - logic lsu_bus_ibuf_c1_clken, lsu_bus_obuf_c1_clken, lsu_bus_buf_c1_clken; + logic lsu_bus_ibuf_c1_clken, lsu_bus_buf_c1_clken; logic lsu_free_c1_clken, lsu_free_c1_clken_q, lsu_free_c2_clken; @@ -88,8 +91,7 @@ import el2_pkg::*; // Clock Enable logic //------------------------------------------------------------------------------------------- - assign lsu_c1_d_clken = lsu_p.valid | dma_dccm_req | clk_override; - assign lsu_c1_m_clken = lsu_pkt_d.valid | lsu_c1_d_clken_q | clk_override; + assign lsu_c1_m_clken = lsu_p.valid | dma_dccm_req | clk_override; assign lsu_c1_r_clken = lsu_pkt_m.valid | lsu_c1_m_clken_q | clk_override; assign lsu_c2_m_clken = lsu_c1_m_clken | lsu_c1_m_clken_q | clk_override; @@ -101,16 +103,15 @@ import el2_pkg::*; assign lsu_stbuf_c1_clken = ldst_stbuf_reqvld_r | stbuf_reqvld_any | stbuf_reqvld_flushed_any | clk_override; assign lsu_bus_ibuf_c1_clken = lsu_busreq_r | clk_override; assign lsu_bus_obuf_c1_clken = (lsu_bus_buffer_pend_any | lsu_busreq_r | clk_override) & lsu_bus_clk_en; - assign lsu_bus_buf_c1_clken = ~lsu_bus_buffer_empty_any | lsu_busreq_r | clk_override; + assign lsu_bus_buf_c1_clken = ~lsu_bus_buffer_empty_any | lsu_busreq_r | dec_tlu_force_halt | clk_override; assign lsu_free_c1_clken = (lsu_p.valid | lsu_pkt_d.valid | lsu_pkt_m.valid | lsu_pkt_r.valid) | ~lsu_bus_buffer_empty_any | ~lsu_stbuf_empty_any | clk_override; assign lsu_free_c2_clken = lsu_free_c1_clken | lsu_free_c1_clken_q | clk_override; // Flops - rvdff #(1) lsu_free_c1_clkenff (.din(lsu_free_c1_clken), .dout(lsu_free_c1_clken_q), .clk(free_clk), .*); + rvdff #(1) lsu_free_c1_clkenff (.din(lsu_free_c1_clken), .dout(lsu_free_c1_clken_q), .clk(active_clk), .*); - rvdff #(1) lsu_c1_d_clkenff (.din(lsu_c1_d_clken), .dout(lsu_c1_d_clken_q), .clk(lsu_free_c2_clk), .*); rvdff #(1) lsu_c1_m_clkenff (.din(lsu_c1_m_clken), .dout(lsu_c1_m_clken_q), .clk(lsu_free_c2_clk), .*); rvdff #(1) lsu_c1_r_clkenff (.din(lsu_c1_r_clken), .dout(lsu_c1_r_clken_q), .clk(lsu_free_c2_clk), .*); @@ -126,10 +127,17 @@ import el2_pkg::*; rvoclkhdr lsu_stbuf_c1_cgc ( .en(lsu_stbuf_c1_clken), .l1clk(lsu_stbuf_c1_clk), .* ); rvoclkhdr lsu_bus_ibuf_c1_cgc ( .en(lsu_bus_ibuf_c1_clken), .l1clk(lsu_bus_ibuf_c1_clk), .* ); - rvclkhdr lsu_bus_obuf_c1_cgc ( .en(lsu_bus_obuf_c1_clken), .l1clk(lsu_bus_obuf_c1_clk), .* ); rvoclkhdr lsu_bus_buf_c1_cgc ( .en(lsu_bus_buf_c1_clken), .l1clk(lsu_bus_buf_c1_clk), .* ); - rvclkhdr lsu_busm_cgc (.en(lsu_bus_clk_en), .l1clk(lsu_busm_clk), .*); + assign lsu_busm_clken = (~lsu_bus_buffer_empty_any | lsu_busreq_r | clk_override) & lsu_bus_clk_en; + +`ifdef RV_FPGA_OPTIMIZE + assign lsu_busm_clk = 1'b0; + assign lsu_bus_obuf_c1_clk = 1'b0; +`else + rvclkhdr lsu_bus_obuf_c1_cgc ( .en(lsu_bus_obuf_c1_clken), .l1clk(lsu_bus_obuf_c1_clk), .* ); + rvclkhdr lsu_busm_cgc (.en(lsu_busm_clken), .l1clk(lsu_busm_clk), .*); +`endif rvoclkhdr lsu_free_cgc (.en(lsu_free_c2_clken), .l1clk(lsu_free_c2_clk), .*); diff --git a/design/lsu/el2_lsu_dccm_ctl.sv b/design/lsu/el2_lsu_dccm_ctl.sv index 1d44f69..31ea651 100644 --- a/design/lsu/el2_lsu_dccm_ctl.sv +++ b/design/lsu/el2_lsu_dccm_ctl.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -32,37 +32,41 @@ import el2_pkg::*; `include "el2_param.vh" ) ( - input logic lsu_c2_m_clk, // clocks - input logic lsu_c2_r_clk, // clocks - input logic lsu_c1_r_clk, - input logic lsu_store_c1_r_clk, - input logic lsu_free_c2_clk, - input logic clk, + input logic lsu_c2_m_clk, // clocks + input logic lsu_c2_r_clk, // clocks + input logic lsu_c1_r_clk, // clocks + input logic lsu_store_c1_r_clk, // clocks + input logic lsu_free_c2_clk, // clocks + input logic clk_override, // Override non-functional clock gating + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. - input logic rst_l, + input logic rst_l, // reset, active low - input el2_lsu_pkt_t lsu_pkt_r, // lsu packets - input el2_lsu_pkt_t lsu_pkt_m, // lsu packets - input el2_lsu_pkt_t lsu_pkt_d, + input el2_lsu_pkt_t lsu_pkt_r,// lsu packets + input el2_lsu_pkt_t lsu_pkt_m,// lsu packets + input el2_lsu_pkt_t lsu_pkt_d,// lsu packets input logic addr_in_dccm_d, // address maps to dccm input logic addr_in_pic_d, // address maps to pic input logic addr_in_pic_m, // address maps to pic - input logic addr_in_dccm_m, addr_in_dccm_r, - input logic addr_in_pic_r, + input logic addr_in_dccm_m, addr_in_dccm_r, // address in dccm per pipe stage + input logic addr_in_pic_r, // address in pic per pipe stage input logic lsu_raw_fwd_lo_r, lsu_raw_fwd_hi_r, - input logic lsu_commit_r, + input logic lsu_commit_r, // lsu instruction in r commits + input logic ldst_dual_m, ldst_dual_r,// load/store is unaligned at 32 bit boundary per pipe stage - input logic [31:0] lsu_addr_d, // starting byte address for loads - input logic [pt.DCCM_BITS-1:0] lsu_addr_m, // starting byte address for loads - input logic [31:0] lsu_addr_r, // starting byte address for loads + // lsu address down the pipe + input logic [31:0] lsu_addr_d, + input logic [pt.DCCM_BITS-1:0] lsu_addr_m, + input logic [31:0] lsu_addr_r, + // lsu address down the pipe - needed to check unaligned input logic [pt.DCCM_BITS-1:0] end_addr_d, input logic [pt.DCCM_BITS-1:0] end_addr_m, input logic [pt.DCCM_BITS-1:0] end_addr_r, - input logic stbuf_reqvld_any, // write enable - input logic [pt.LSU_SB_BITS-1:0] stbuf_addr_any, // stbuf address (aligned) + input logic stbuf_reqvld_any, // write enable + input logic [pt.LSU_SB_BITS-1:0] stbuf_addr_any, // stbuf address (aligned) input logic [pt.DCCM_DATA_WIDTH-1:0] stbuf_data_any, // the read out from stbuf input logic [pt.DCCM_ECC_WIDTH-1:0] stbuf_ecc_any, // the encoded data with ECC bits @@ -71,8 +75,8 @@ import el2_pkg::*; input logic [pt.DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_hi_m, // stbuf fowarding to load input logic [pt.DCCM_BYTE_WIDTH-1:0] stbuf_fwdbyteen_lo_m, // stbuf fowarding to load - output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_r, // data from the dccm - output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_r, // data from the dccm + output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_r, // data from the dccm + output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_r, // data from the dccm output logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_hi_r, // data from the dccm + ecc output logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_lo_r, output logic [pt.DCCM_DATA_WIDTH-1:0] lsu_ld_data_r, // right justified, ie load byte will have data at 7:0 @@ -88,8 +92,8 @@ import el2_pkg::*; input logic [pt.DCCM_ECC_WIDTH-1:0] sec_data_ecc_hi_r_ff, // the encoded data with ECC bits input logic [pt.DCCM_ECC_WIDTH-1:0] sec_data_ecc_lo_r_ff, // the encoded data with ECC bits - output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_m, // data from the dccm - output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_m, // data from the dccm + output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_m, // data from the dccm + output logic [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_m, // data from the dccm output logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_hi_m, // data from the dccm + ecc output logic [pt.DCCM_ECC_WIDTH-1:0] dccm_data_ecc_lo_m, output logic [pt.DCCM_DATA_WIDTH-1:0] lsu_ld_data_m, // right justified, ie load byte will have data at 7:0 @@ -98,58 +102,58 @@ import el2_pkg::*; input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_m, // corrected dccm data input logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_m, // corrected dccm data - input logic [31:0] store_data_m, - input logic dma_dccm_wen, - input logic dma_pic_wen, - input logic [2:0] dma_mem_tag_m, - input logic [31:0] dma_mem_addr, // DMA address - input logic [63:0] dma_mem_wdata, // DMA write data - input logic [31:0] dma_dccm_wdata_lo, - input logic [31:0] dma_dccm_wdata_hi, - input logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_hi, // ECC bits for the DMA wdata - input logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_lo, // ECC bits for the DMA wdata + input logic [31:0] store_data_m, // Store data M-stage + input logic dma_dccm_wen, // Perform DMA writes only for word/dword + input logic dma_pic_wen, // Perform PIC writes + input logic [2:0] dma_mem_tag_m, // DMA Buffer entry number M-stage + input logic [31:0] dma_mem_addr, // DMA request address + input logic [63:0] dma_mem_wdata, // DMA write data + input logic [31:0] dma_dccm_wdata_lo, // Shift the dma data to lower bits to make it consistent to lsu stores + input logic [31:0] dma_dccm_wdata_hi, // Shift the dma data to lower bits to make it consistent to lsu stores + input logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_hi, // ECC bits for the DMA wdata + input logic [pt.DCCM_ECC_WIDTH-1:0] dma_dccm_wdata_ecc_lo, // ECC bits for the DMA wdata output logic [pt.DCCM_DATA_WIDTH-1:0] store_data_hi_r, output logic [pt.DCCM_DATA_WIDTH-1:0] store_data_lo_r, - output logic [pt.DCCM_DATA_WIDTH-1:0] store_datafn_hi_r, // data from the dccm - output logic [pt.DCCM_DATA_WIDTH-1:0] store_datafn_lo_r, // data from the dccm + output logic [pt.DCCM_DATA_WIDTH-1:0] store_datafn_hi_r, // data from the dccm + output logic [pt.DCCM_DATA_WIDTH-1:0] store_datafn_lo_r, // data from the dccm output logic [31:0] store_data_r, // raw store data to be sent to bus output logic ld_single_ecc_error_r, output logic ld_single_ecc_error_r_ff, output logic [31:0] picm_mask_data_m, // pic data to stbuf - output logic lsu_stbuf_commit_any, // stbuf wins the dccm port or is to pic + output logic lsu_stbuf_commit_any, // stbuf wins the dccm port or is to pic output logic lsu_dccm_rden_m, // dccm read output logic lsu_dccm_rden_r, // dccm read - output logic dccm_dma_rvalid, // dccm serviving the dma load - output logic dccm_dma_ecc_error, // DMA load had ecc error - output logic [2:0] dccm_dma_rtag, // DMA return tag - output logic [63:0] dccm_dma_rdata, // dccm data to dma request + output logic dccm_dma_rvalid, // dccm serviving the dma load + output logic dccm_dma_ecc_error, // DMA load had ecc error + output logic [2:0] dccm_dma_rtag, // DMA return tag + output logic [63:0] dccm_dma_rdata, // dccm data to dma request // DCCM ports - output logic dccm_wren, // dccm interface -- write - output logic dccm_rden, // dccm interface -- write - output logic [pt.DCCM_BITS-1:0] dccm_wr_addr_lo, // dccm interface -- wr addr for lo bank - output logic [pt.DCCM_BITS-1:0] dccm_wr_addr_hi, // dccm interface -- wr addr for hi bank - output logic [pt.DCCM_BITS-1:0] dccm_rd_addr_lo, // dccm interface -- read address for lo bank - output logic [pt.DCCM_BITS-1:0] dccm_rd_addr_hi, // dccm interface -- read address for hi bank - output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo, // dccm write data for lo bank - output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi, // dccm write data for hi bank + output logic dccm_wren, // dccm interface -- write + output logic dccm_rden, // dccm interface -- write + output logic [pt.DCCM_BITS-1:0] dccm_wr_addr_lo, // dccm interface -- wr addr for lo bank + output logic [pt.DCCM_BITS-1:0] dccm_wr_addr_hi, // dccm interface -- wr addr for hi bank + output logic [pt.DCCM_BITS-1:0] dccm_rd_addr_lo, // dccm interface -- read address for lo bank + output logic [pt.DCCM_BITS-1:0] dccm_rd_addr_hi, // dccm interface -- read address for hi bank + output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo, // dccm write data for lo bank + output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi, // dccm write data for hi bank - input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // dccm read data back from the dccm - input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // dccm read data back from the dccm + input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // dccm read data back from the dccm + input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // dccm read data back from the dccm // PIC ports - output logic picm_wren, // write to pic - output logic picm_rden, // read to pick - output logic picm_mken, // write to pic need a mask - output logic [31:0] picm_rdaddr, // address for pic read access - output logic [31:0] picm_wraddr, // address for pic write access - output logic [31:0] picm_wr_data, // write data - input logic [31:0] picm_rd_data, // read data + output logic picm_wren, // write to pic + output logic picm_rden, // read to pick + output logic picm_mken, // write to pic need a mask + output logic [31:0] picm_rdaddr, // address for pic read access + output logic [31:0] picm_wraddr, // address for pic write access + output logic [31:0] picm_wr_data, // write data + input logic [31:0] picm_rd_data, // read data - input logic scan_mode // scan mode + input logic scan_mode // scan mode ); @@ -183,11 +187,12 @@ import el2_pkg::*; logic [63:0] picm_rd_data_r; logic [63:32] lsu_ld_data_r_nc, lsu_ld_data_corr_r_nc; logic [2:0] dma_mem_tag_r; + logic stbuf_fwddata_en; assign dccm_dma_rvalid = lsu_pkt_r.valid & lsu_pkt_r.load & lsu_pkt_r.dma; assign dccm_dma_ecc_error = lsu_double_ecc_error_r; assign dccm_dma_rtag[2:0] = dma_mem_tag_r[2:0]; - assign dccm_dma_rdata[63:0] = lsu_rdata_corr_r; + assign dccm_dma_rdata[63:0] = ldst_dual_r ? lsu_rdata_corr_r[63:0] : {2{lsu_rdata_corr_r[31:0]}}; assign {lsu_ld_data_r_nc[63:32], lsu_ld_data_r[31:0]} = lsu_rdata_r[63:0] >> 8*lsu_addr_r[1:0]; assign {lsu_ld_data_corr_r_nc[63:32], lsu_ld_data_corr_r[31:0]} = lsu_rdata_corr_r[63:0] >> 8*lsu_addr_r[1:0]; @@ -196,22 +201,23 @@ import el2_pkg::*; assign dccm_rdata_corr_r[63:0] = {sec_data_hi_r[31:0],sec_data_lo_r[31:0]}; assign stbuf_fwddata_r[63:0] = {stbuf_fwddata_hi_r[31:0], stbuf_fwddata_lo_r[31:0]}; assign stbuf_fwdbyteen_r[7:0] = {stbuf_fwdbyteen_hi_r[3:0], stbuf_fwdbyteen_lo_r[3:0]}; + assign stbuf_fwddata_en = (|stbuf_fwdbyteen_hi_m[3:0]) | (|stbuf_fwdbyteen_lo_m[3:0]) | clk_override; for (genvar i=0; i<8; i++) begin: GenDMAData assign lsu_rdata_corr_r[(8*i)+7:8*i] = stbuf_fwdbyteen_r[i] ? stbuf_fwddata_r[(8*i)+7:8*i] : - (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] : dccm_rdata_corr_r[(8*i)+7:8*i]); + (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] : ({8{addr_in_dccm_r}} & dccm_rdata_corr_r[(8*i)+7:8*i])); assign lsu_rdata_r[(8*i)+7:8*i] = stbuf_fwdbyteen_r[i] ? stbuf_fwddata_r[(8*i)+7:8*i] : - (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] : dccm_rdata_r[(8*i)+7:8*i]); + (addr_in_pic_r ? picm_rd_data_r[(8*i)+7:8*i] : ({8{addr_in_dccm_r}} & dccm_rdata_r[(8*i)+7:8*i])); end - rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_hi_r_ff (.*, .din(dccm_rdata_hi_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(dccm_rdata_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_dccm_rden_m)); - rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_lo_r_ff (.*, .din(dccm_rdata_lo_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(dccm_rdata_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_dccm_rden_m)); + rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_hi_r_ff (.*, .din(dccm_rdata_hi_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(dccm_rdata_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en((lsu_dccm_rden_m & ldst_dual_m) | clk_override)); + rvdffe #(pt.DCCM_DATA_WIDTH) dccm_rdata_lo_r_ff (.*, .din(dccm_rdata_lo_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(dccm_rdata_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_dccm_rden_m | clk_override)); rvdffe #(2*pt.DCCM_ECC_WIDTH) dccm_data_ecc_r_ff (.*, .din({dccm_data_ecc_hi_m[pt.DCCM_ECC_WIDTH-1:0], dccm_data_ecc_lo_m[pt.DCCM_ECC_WIDTH-1:0]}), - .dout({dccm_data_ecc_hi_r[pt.DCCM_ECC_WIDTH-1:0], dccm_data_ecc_lo_r[pt.DCCM_ECC_WIDTH-1:0]}), .en(lsu_dccm_rden_m)); - rvdff #(8) stbuf_fwdbyteen_ff (.*, .din({stbuf_fwdbyteen_hi_m[3:0], stbuf_fwdbyteen_lo_m[3:0]}), .dout({stbuf_fwdbyteen_hi_r[3:0], stbuf_fwdbyteen_lo_r[3:0]}), .clk(lsu_c2_r_clk)); - rvdff #(64) stbuf_fwddata_ff (.*, .din({stbuf_fwddata_hi_m[31:0], stbuf_fwddata_lo_m[31:0]}), .dout({stbuf_fwddata_hi_r[31:0], stbuf_fwddata_lo_r[31:0]}), .clk(lsu_c2_r_clk)); - rvdff #(32) picm_rddata_rff (.*, .din(picm_rd_data_m[31:0]), .dout(picm_rd_data_r[31:0]), .clk(lsu_c2_r_clk)); - rvdff #(3) dma_mem_tag_rff (.*, .din(dma_mem_tag_m[2:0]), .dout(dma_mem_tag_r[2:0]), .clk(lsu_c1_r_clk)); + .dout({dccm_data_ecc_hi_r[pt.DCCM_ECC_WIDTH-1:0], dccm_data_ecc_lo_r[pt.DCCM_ECC_WIDTH-1:0]}), .en(lsu_dccm_rden_m | clk_override)); + rvdff #(8) stbuf_fwdbyteen_ff (.*, .din({stbuf_fwdbyteen_hi_m[3:0], stbuf_fwdbyteen_lo_m[3:0]}), .dout({stbuf_fwdbyteen_hi_r[3:0], stbuf_fwdbyteen_lo_r[3:0]}), .clk(lsu_c2_r_clk)); + rvdffe #(64) stbuf_fwddata_ff (.*, .din({stbuf_fwddata_hi_m[31:0], stbuf_fwddata_lo_m[31:0]}), .dout({stbuf_fwddata_hi_r[31:0], stbuf_fwddata_lo_r[31:0]}), .en(stbuf_fwddata_en)); + rvdffe #(32) picm_rddata_rff (.*, .din(picm_rd_data_m[31:0]), .dout(picm_rd_data_r[31:0]), .en(addr_in_pic_m | clk_override)); + rvdff #(3) dma_mem_tag_rff (.*, .din(dma_mem_tag_m[2:0]), .dout(dma_mem_tag_r[2:0]), .clk(lsu_c1_r_clk)); end else begin: L2U_Plus1_0 @@ -225,7 +231,7 @@ import el2_pkg::*; assign dccm_dma_rvalid = lsu_pkt_m.valid & lsu_pkt_m.load & lsu_pkt_m.dma; assign dccm_dma_ecc_error = lsu_double_ecc_error_m; assign dccm_dma_rtag[2:0] = dma_mem_tag_m[2:0]; - assign dccm_dma_rdata[63:0] = lsu_rdata_corr_m; + assign dccm_dma_rdata[63:0] = ldst_dual_m ? lsu_rdata_corr_m[63:0] : {2{lsu_rdata_corr_m[31:0]}}; assign {lsu_ld_data_m_nc[63:32], lsu_ld_data_m[31:0]} = lsu_rdata_m[63:0] >> 8*lsu_addr_m[1:0]; assign {lsu_ld_data_corr_m_nc[63:32], lsu_ld_data_corr_m[31:0]} = lsu_rdata_corr_m[63:0] >> 8*lsu_addr_m[1:0]; @@ -236,13 +242,13 @@ import el2_pkg::*; for (genvar i=0; i<8; i++) begin: GenLoop assign lsu_rdata_corr_m[(8*i)+7:8*i] = stbuf_fwdbyteen_m[i] ? stbuf_fwddata_m[(8*i)+7:8*i] : - (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : dccm_rdata_corr_m[(8*i)+7:8*i]); + (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : ({8{addr_in_dccm_m}} & dccm_rdata_corr_m[(8*i)+7:8*i])); assign lsu_rdata_m[(8*i)+7:8*i] = stbuf_fwdbyteen_m[i] ? stbuf_fwddata_m[(8*i)+7:8*i] : - (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : dccm_rdata_m[(8*i)+7:8*i]); + (addr_in_pic_m ? picm_rd_data_m[(8*i)+7:8*i] : ({8{addr_in_dccm_m}} & dccm_rdata_m[(8*i)+7:8*i])); end - rvdff #(32) lsu_ld_data_corr_rff(.*, .din(lsu_ld_data_corr_m[31:0]), .dout(lsu_ld_data_corr_r[31:0]), .clk(lsu_c2_r_clk)); + rvdffe #(32) lsu_ld_data_corr_rff(.*, .din(lsu_ld_data_corr_m[31:0]), .dout(lsu_ld_data_corr_r[31:0]), .en((lsu_pkt_m.valid & lsu_pkt_m.load & (addr_in_pic_m | addr_in_dccm_m)) | clk_override)); end assign kill_ecc_corr_lo_r = (((lsu_addr_d[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2]) | (end_addr_d[pt.DCCM_BITS-1:2] == lsu_addr_r[pt.DCCM_BITS-1:2])) & lsu_pkt_d.valid & lsu_pkt_d.store & lsu_pkt_d.dma & addr_in_dccm_d) | @@ -289,7 +295,7 @@ import el2_pkg::*; {stbuf_ecc_any[pt.DCCM_ECC_WIDTH-1:0],stbuf_data_any[pt.DCCM_DATA_WIDTH-1:0]}); // DCCM outputs - assign store_byteen_m[3:0] = {4{lsu_pkt_m.store}} & + assign store_byteen_m[3:0] = {4{lsu_pkt_m.store}} & (({4{lsu_pkt_m.by}} & 4'b0001) | ({4{lsu_pkt_m.half}} & 4'b0011) | ({4{lsu_pkt_m.word}} & 4'b1111)); @@ -330,7 +336,7 @@ import el2_pkg::*; end rvdff #(1) dccm_wren_ff (.*, .din(lsu_stbuf_commit_any), .dout(dccm_wren_Q), .clk(lsu_free_c2_clk)); // ECC load errors writing to dccm shouldn't fwd to stores in pipe - rvdffe #(32) dccm_wrdata_ff (.*, .din(stbuf_data_any[31:0]), .dout(dccm_wr_data_Q[31:0]), .en(lsu_stbuf_commit_any), .clk(clk)); + rvdffe #(32) dccm_wrdata_ff (.*, .din(stbuf_data_any[31:0]), .dout(dccm_wr_data_Q[31:0]), .en(lsu_stbuf_commit_any | clk_override), .clk(clk)); rvdff #(1) dccm_wrbyp_dm_loff (.*, .din(dccm_wr_bypass_d_m_lo), .dout(dccm_wr_bypass_d_m_lo_Q), .clk(lsu_free_c2_clk)); rvdff #(1) dccm_wrbyp_dm_hiff (.*, .din(dccm_wr_bypass_d_m_hi), .dout(dccm_wr_bypass_d_m_hi_Q), .clk(lsu_free_c2_clk)); rvdff #(32) store_data_rff (.*, .din(store_data_m[31:0]), .dout(store_data_r[31:0]), .clk(lsu_store_c1_r_clk)); @@ -356,8 +362,8 @@ import el2_pkg::*; end assign store_data_r[31:0] = 32'({store_data_hi_r[31:0],store_data_lo_r[31:0]} >> 8*lsu_addr_r[1:0]) & store_data_mask[31:0]; - rvdff #(pt.DCCM_DATA_WIDTH) store_data_hi_rff (.*, .din(store_data_hi_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .clk(lsu_store_c1_r_clk)); - rvdff #(pt.DCCM_DATA_WIDTH) store_data_lo_rff (.*, .din(store_data_lo_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .clk(lsu_store_c1_r_clk)); + rvdffe #(pt.DCCM_DATA_WIDTH) store_data_hi_rff (.*, .din(store_data_hi_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en((ldst_dual_m & lsu_pkt_m.valid & lsu_pkt_m.store) | clk_override), .clk(clk)); + rvdff #(pt.DCCM_DATA_WIDTH) store_data_lo_rff (.*, .din(store_data_lo_r_in[pt.DCCM_DATA_WIDTH-1:0]), .dout(store_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .clk(lsu_store_c1_r_clk)); end @@ -383,23 +389,28 @@ import el2_pkg::*; if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable rvdff #(1) dccm_rden_mff (.*, .din(lsu_dccm_rden_d), .dout(lsu_dccm_rden_m), .clk(lsu_c2_m_clk)); rvdff #(1) dccm_rden_rff (.*, .din(lsu_dccm_rden_m), .dout(lsu_dccm_rden_r), .clk(lsu_c2_r_clk)); + + // ECC correction flops since dccm write happens next cycle + // We are writing to dccm in r+1 for ecc correction since fast_int needs to be blocked in decode - 1. We can probably write in r for plus0 configuration since we know ecc error in M. + // In that case these (_ff) flops are needed only in plus1 configuration + rvdff #(1) ld_double_ecc_error_rff (.*, .din(lsu_double_ecc_error_r), .dout(lsu_double_ecc_error_r_ff), .clk(lsu_free_c2_clk)); + rvdff #(1) ld_single_ecc_error_hi_rff (.*, .din(ld_single_ecc_error_hi_r_ns), .dout(ld_single_ecc_error_hi_r_ff), .clk(lsu_free_c2_clk)); + rvdff #(1) ld_single_ecc_error_lo_rff (.*, .din(ld_single_ecc_error_lo_r_ns), .dout(ld_single_ecc_error_lo_r_ff), .clk(lsu_free_c2_clk)); + rvdffe #(pt.DCCM_BITS) ld_sec_addr_hi_rff (.*, .din(end_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk)); + rvdffe #(pt.DCCM_BITS) ld_sec_addr_lo_rff (.*, .din(lsu_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk)); + end else begin: Gen_dccm_disable assign lsu_dccm_rden_m = '0; assign lsu_dccm_rden_r = '0; + + assign lsu_double_ecc_error_r_ff = 1'b0; + assign ld_single_ecc_error_hi_r_ff = 1'b0; + assign ld_single_ecc_error_lo_r_ff = 1'b0; + assign ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0] = '0; + assign ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0] = '0; end - // ECC correction flops since dccm write happens next cycle - // We are writing to dccm in r+1 for ecc correction since fast_int needs to be blocked in decode - 1. We can probably write in r for plus0 configuration since we know ecc error in M. - // In that case these (_ff) flops are needed only in plus1 configuration - rvdff #(1) ld_double_ecc_error_rff (.*, .din(lsu_double_ecc_error_r), .dout(lsu_double_ecc_error_r_ff), .clk(lsu_free_c2_clk)); - rvdff #(1) ld_single_ecc_error_hi_rff (.*, .din(ld_single_ecc_error_hi_r_ns), .dout(ld_single_ecc_error_hi_r_ff), .clk(lsu_free_c2_clk)); - rvdff #(1) ld_single_ecc_error_lo_rff (.*, .din(ld_single_ecc_error_lo_r_ns), .dout(ld_single_ecc_error_lo_r_ff), .clk(lsu_free_c2_clk)); - rvdffe #(pt.DCCM_BITS) ld_sec_addr_hi_rff (.*, .din(end_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_hi_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r), .clk(clk)); - rvdffe #(pt.DCCM_BITS) ld_sec_addr_lo_rff (.*, .din(lsu_addr_r[pt.DCCM_BITS-1:0]), .dout(ld_sec_addr_lo_r_ff[pt.DCCM_BITS-1:0]), .en(ld_single_ecc_error_r), .clk(clk)); - -`ifdef LSU_ASSERT_ON - assert_ecc_kill_lo: assert #0 (~(ld_single_ecc_error_lo_r & kill_ecc_corr_lo_r)); - assert_ecc_kill_hi: assert #0 (~(ld_single_ecc_error_hi_r & kill_ecc_corr_hi_r)); +`ifdef RV_ASSERT_ON // Load single ECC error correction implies commit/dma property ld_single_ecc_error_commit; diff --git a/design/lsu/el2_lsu_dccm_mem.sv b/design/lsu/el2_lsu_dccm_mem.sv index 3f8a963..5892dba 100644 --- a/design/lsu/el2_lsu_dccm_mem.sv +++ b/design/lsu/el2_lsu_dccm_mem.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,14 +27,27 @@ // //******************************************************************************** +`define EL2_LOCAL_DCCM_RAM_TEST_PORTS .TEST1(dccm_ext_in_pkt[i].TEST1), \ + .RME(dccm_ext_in_pkt[i].RME), \ + .RM(dccm_ext_in_pkt[i].RM), \ + .LS(dccm_ext_in_pkt[i].LS), \ + .DS(dccm_ext_in_pkt[i].DS), \ + .SD(dccm_ext_in_pkt[i].SD), \ + .TEST_RNM(dccm_ext_in_pkt[i].TEST_RNM), \ + .BC1(dccm_ext_in_pkt[i].BC1), \ + .BC2(dccm_ext_in_pkt[i].BC2), \ + + + module el2_lsu_dccm_mem import el2_pkg::*; #( `include "el2_param.vh" )( - input logic clk, // clock - input logic rst_l, - input logic clk_override, // clock override + input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. + input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in. + input logic rst_l, // reset, active low + input logic clk_override, // Override non-functional clock gating input logic dccm_wren, // write enable input logic dccm_rden, // read enable @@ -44,6 +57,7 @@ import el2_pkg::*; input logic [pt.DCCM_BITS-1:0] dccm_rd_addr_hi, // read address for the upper bank in case of a misaligned access input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo, // write data input logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi, // write data + input el2_dccm_ext_in_pkt_t [pt.DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt, // the dccm packet from the soc output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // read data from the lo bank output logic [pt.DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // read data from the hi bank @@ -78,10 +92,9 @@ import el2_pkg::*; assign dccm_rd_data_lo[pt.DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_lo_q[pt.DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]][pt.DCCM_FDATA_WIDTH-1:0]; assign dccm_rd_data_hi[pt.DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:pt.DCCM_BANK_BITS]][pt.DCCM_FDATA_WIDTH-1:0]; - // Generate even/odd address // 8 Banks, 16KB each (2048 x 72) - for (genvar i=0; i<32'(pt.DCCM_NUM_BANKS); i++) begin: mem_bank + for (genvar i=0; i (lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_dccm_r & ~lsu_pkt_r.dma); + @(posedge clk) disable iff(~rst_l) (|stbuf_wr_en[DEPTH-1:0]) |-> (lsu_pkt_r.valid & lsu_pkt_r.store & addr_in_dccm_r); endproperty assert_stbuf_wren_store_dccm: assert property (stbuf_wren_store_dccm) else $display("Illegal store buffer write"); diff --git a/design/lsu/el2_lsu_trigger.sv b/design/lsu/el2_lsu_trigger.sv index ab506f3..40a5dfd 100644 --- a/design/lsu/el2_lsu_trigger.sv +++ b/design/lsu/el2_lsu_trigger.sv @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 Western Digital Corporation or it's affiliates. +// Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,29 +27,39 @@ import el2_pkg::*; #( `include "el2_param.vh" )( - input el2_trigger_pkt_t [3:0] trigger_pkt_any, // trigger packet from dec + input el2_trigger_pkt_t [3:0] trigger_pkt_any, // trigger packet from dec input el2_lsu_pkt_t lsu_pkt_m, // lsu packet input logic [31:0] lsu_addr_m, // address input logic [31:0] store_data_m, // store data - output logic [3:0] lsu_trigger_match_m // match result + output logic [3:0] lsu_trigger_match_m // match result ); + logic trigger_enable; logic [3:0][31:0] lsu_match_data; logic [3:0] lsu_trigger_data_match; logic [31:0] store_data_trigger_m; + logic [31:0] ldst_addr_trigger_m; - assign store_data_trigger_m[31:0] = {({16{lsu_pkt_m.word}} & store_data_m[31:16]),({8{(lsu_pkt_m.half | lsu_pkt_m.word)}} & store_data_m[15:8]), store_data_m[7:0]}; + // Generate the trigger enable (This is for power) + always_comb begin + trigger_enable = 1'b0; + for (int i=0; i<4; i++) begin + trigger_enable |= trigger_pkt_any[i].m; + end + end + + assign store_data_trigger_m[31:0] = {({16{lsu_pkt_m.word}} & store_data_m[31:16]),({8{(lsu_pkt_m.half | lsu_pkt_m.word)}} & store_data_m[15:8]), store_data_m[7:0]} & {32{trigger_enable}}; + assign ldst_addr_trigger_m[31:0] = lsu_addr_m[31:0] & {32{trigger_enable}}; for (genvar i=0; i<4; i++) begin - assign lsu_match_data[i][31:0] = ({32{~trigger_pkt_any[i].select}} & lsu_addr_m[31:0]) | + assign lsu_match_data[i][31:0] = ({32{~trigger_pkt_any[i].select}} & ldst_addr_trigger_m[31:0]) | ({32{trigger_pkt_any[i].select & trigger_pkt_any[i].store}} & store_data_trigger_m[31:0]); - rvmaskandmatch trigger_match (.mask(trigger_pkt_any[i].tdata2[31:0]), .data(lsu_match_data[i][31:0]), .masken(trigger_pkt_any[i].match), .match(lsu_trigger_data_match[i])); - assign lsu_trigger_match_m[i] = lsu_pkt_m.valid & ~lsu_pkt_m.dma & + assign lsu_trigger_match_m[i] = lsu_pkt_m.valid & ~lsu_pkt_m.dma & trigger_enable & ((trigger_pkt_any[i].store & lsu_pkt_m.store) | (trigger_pkt_any[i].load & lsu_pkt_m.load & ~trigger_pkt_any[i].select)) & lsu_trigger_data_match[i]; end diff --git a/docs/RISC-V_SweRV_EL2_PRM.pdf b/docs/RISC-V_SweRV_EL2_PRM.pdf index 891bca5f5dcb7f8a9766a2a8a55f32762dd0c878..ddfa84d8907eaee92f1e768e0e118ae9d806eb62 100755 GIT binary patch delta 1426705 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%0Alj_4O!hBrGb+gWCzc1C!gch(7zhl9P9 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