diff --git a/.gitignore b/.gitignore index 38d466cd8..6e9920603 100644 --- a/.gitignore +++ b/.gitignore @@ -111,4 +111,5 @@ sim/imperas.log sim/results-error/ sim/test1.rep sim/vsim.log -tests/coverage/*.S +tests/coverage/*.elf +*.elf.memfile \ No newline at end of file diff --git a/Install b/Install deleted file mode 100644 index 47a91dddd..000000000 --- a/Install +++ /dev/null @@ -1,333 +0,0 @@ -Complete Wally Installation guide -Formally RISC-V System on Chip Design Appendix D - -Sections: -1. RISC-V Tool Installation (Sys Admin) -2. Core-v-wally Repo Installation -3. Build and Run Regression Tests - -Section 1 tool install should be done once by a system admin with root access. The specific details may need to be -adjusted as some tools may already be present on the system. This guide assumes all compiled from source tools are -installed at base diretory $RISCV. - -* Tool-chain Installation (Sys Admin) - -** TL;DR Open Source Tool-chain Installation - - The installing details are involved, but can be skipped using the following script. wally-tool-chain-install.sh installs the open source tools to RISCV=/opt/riscv by default. Change by supplying an alternate path as an argument, (ie. wally-tool-chain-install.sh /mnt/disk1/riscv). - This install script does NOT install buildroot or commercial EDA tools; Questa, Design Compiler, or Innovus. - It must be run as root or with sudo. - This script is tested for Ubuntu, 20.04 and 22.04 - - wally-tool-chain-install.sh - - The step by step instructions include Red Hat 8 / Fedora. - -** Detailed Tool-chain Instal Guide - Section 2.1 described Wally platform requirements and Section 2.2 describes how a user gets started using Wally on a Linux server. This appendix describes how the system administrator installs RISC-V tools. Superuser privileges are necessary for many of the tools. Setting up all of the tools can be time-consuming and fussy, so this appendix also describes a fallback flow with Docker and Podman. - -*** Open Source Software Installation - -Compiling, assembling, and simulating RISC-V programs requires downloading and installing the following free tools: - -1. The GCC cross-compiler -2. A RISC-V simulator such as Spike, Sail, and/or QEMU -3. Spike is easy to use but doesn’t support peripherals to boot Linux -4. QEMU is faster and can boot Linux -5. Sail is presently the official golden reference for RISC-V and is used by the riscof verification suite, but runs slowly and is painful to instal - -This setup needs to be done once by the administrator - -Note: The following directions assume you have an account called cad to install shared software and files. You can substitute a different user for cad if you prefer. - -Note: Installing software in Linux is unreasonably touchy and varies with the flavor and version of your Linux distribution. Don’t be surprised if the installation directions have changed since the book was written or don’t work on your machine; you may need some ingenuity to adjust them. Browse the openhwgroup/core-v-wally repo and look at the README.md for the latest build instructions. - -*** Create the $RISCV Directory - -First, set up a directory for riscv software in some place such as /opt/riscv. We will call this shared directory $RISCV. - -$ export RISCV=/opt/riscv -$ sudo mkdir $RISCV -$ sudo chown cad $RISCV -$ sudo su cad (or root, if you don’t have a cad account) -$ export RISCV=/opt/riscv -$ chmod 755 $RISCV -$ umask 0002 -$ cd $RISCV - -*** Update Tools - -Ubuntu users may need to install and update various tools. - -$ sudo apt update -$ sudo apt upgrade -$ sudo apt install git gawk make texinfo bison flex build-essential python libz-dev libexpat-dev autoconf device-tree-compiler ninja-build libglib2.56-dev libpixman-1-dev build-essential ncurses-base ncurses-bin libncurses5-dev dialog - -*** Install RISC-V GCC Cross-Compiler - -To install GCC from source can take hours to compile. This configuration enables multilib to target many flavors of RISC-V. This book is tested with GCC 12.2 (tagged 2022.09.21), but will likely work with newer versions as well. - -$ git clone https://github.com/riscv/riscv-gnu-toolchain -$ cd riscv-gnu-toolchain -$ git checkout 2022.09.21 -$ ./configure --prefix=$RISCV --enable-multilib --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;" -$ make --jobs - -Note: make --jobs will reduce compile time by compiling in parallel. However, adding this option could dramatically increase the memory utilization of your local machine. - -*** Install elf2hex - -We also need the elf2hex utility to convert executable files into hexadecimal files for Verilog simulation. Install with: - -$ cd $RISCV -$ export PATH=$RISCV/riscv-gnu-toolchain/bin:$PATH -$ git clone https://github.com/sifive/elf2hex.git -$ cd elf2hex -$ autoreconf -i -$ ./configure --target=riscv64-unknown-elf --prefix=$RISCV -$ make -$ make install - -Note: The exe2hex utility that comes with Spike doesn’t work for our purposes because it doesn’t handle programs that start at 0x80000000. The SiFive version above is touchy to install. For example, if Python version 2.x is in your path, it won’t install correctly. Also, be sure riscv64-unknown-elf-objcopy shows up in your path in $RISCV/riscv-gnu-toolchain/bin at the time of compilation, or elf2hex won’t work properly. - -*** Install RISC-V Spike Simulator - -Spike also takes a while to install and compile, but this can be done concurrently with the GCC installation. After the build, we need to change two Makefiles to support atomic instructions . - -$ cd $RISCV -$ git clone https://github.com/riscv-software-src/riscv-isa-sim -$ mkdir riscv-isa-sim/build -$ cd riscv-isa-sim/build -$ ../configure --prefix=$RISCV --enable-commitlog -$ make --jobs -$ make install -$ cd ../arch_test_target/spike/device -$ sed -i 's/--isa=rv32ic/--isa=rv32iac/' rv32i_m/privilege/Makefile.include -$ sed -i 's/--isa=rv64ic/--isa=rv64iac/' rv64i_m/privilege/Makefile.include - -*** Install Sail Simulator - -Sail is the new golden reference model for RISC-V. Sail is written in OCaml, which is an object-oriented extension of ML, which in turn is a functional programming language suited to formal verification. OCaml is installed with the opam OCcaml package manager. Sail has so many dependencies that it can be difficult to install. - -On Ubuntu, apt-get makes opam installation fairly simple. - -$ sudo apt-get install opam build-essential libgmp-dev z3 pkg-config zlib1g-dev - -If you are on RedHat/Rocky Linux 8, installation is much more difficult because packages are not available in the default package manager and some need to be built from source. - -$ sudo bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)" - When prompted, put it in /usr/bin -$ sudo yum groupinstall 'Development Tools' -$ sudo yum -y install gmp-devel -$ sudo yum -y install zlib-devel -$ git clone https://github.com/Z3Prover/z3.git -$ cd z3 -$ python scripts/mk_make.py -$ cd build -$ make -$ sudo make install -$ cd ../.. -$ sudo pip3 install chardet==3.0.4 -$ sudo pip3 install urllib3==1.22 - -Once you have installed the packages on either Ubuntu or RedHat, use opam to install the OCaml compiler and Sail. Run as the cad user because you will be installing Sail in $RISCV. - -$ sudo su cad -$ opam init -y --disable-sandboxing -$ opam switch create ocaml-base-compiler.4.06.1 -$ opam install sail -y - -Now you can clone and compile Sail-RISCV. This will take a while. - -$ eval $(opam config env) -$ cd $RISCV -$ git clone https://github.com/riscv/sail-riscv.git -$ cd sail-riscv -$ make -$ ARCH=RV32 make -$ ARCH=RV64 make -$ exit -$ sudo su -$ export RISCV=/opt/riscv -$ ln -s $RISCV/sail-riscv/c_emulator/riscv_sim_RV64 /usr/bin/riscv_sim_RV64 -$ ln -s $RISCV/sail-riscv/c_emulator/riscv_sim_RV32 /usr/bin/riscv_sim_RV32 -$ exit - -*** Install riscof - -riscof is a Python library used as the RISC-V compatibility framework test an implementation such as Wally or Spike against the Sail golden reference. It will be used to compile the riscv-arch-test suite. - -It is most convenient if the sysadmin installs riscof into the server’s Python libraries: - -$ sudo pip3 install testresources -$ sudo pip3 install riscof --ignore-installed PyYAML - -However, riscof can also be installed and run locally by individual users. - -*** Install Verilator - -Verilator is a free Verilog simulator with a good Lint tool used to catch errors in the SystemVerilog code. It is needed to run regression. -$ sudo apt install verilator - -*** Install QEMU Simulator - -QEMU is another simulator used when booting Linux in Chapter 17. You can optionally install it using the following commands. - - -The QEMU patch changes the VirtIO driver to match the Wally peripherals, and also adds print statements to log the state of the CSRs (see Section 2.5XREF). - - -$ cd $RISCV -$ git clone --recurse-submodules https://github.com/qemu/qemu -$ cd qemu -$ git checkout v6.2.0 # last version tested; newer versions might be ok -$ ./configure --target-list=riscv64-softmmu --prefix=$RISCV -$ make --jobs -$ make install - -*** Cross-Compile Buildroot Linux - -Building Linux is only necessary for exploring the boot process in Chapter 17. Building and generating a trace is a time-consuming operation that could be skipped for now; you can return to this section later if you are interested in the Linux details. - -Buildroot depends on configuration files in riscv-wally, so the cad user must install Wally first according to the instructions in Section 2.2.2. However, don’t source ~/wally-riscv/setup.sh because it will set LD_LIBRARY_PATH in a way to cause make to fail on buildroot. - -To configure and build Buildroot: - -$ cd $RISCV -$ export WALLY=~/riscv-wally # make sure you haven’t sourced ~/riscv-wally/setup.sh by now -$ git clone https://github.com/buildroot/buildroot.git -$ cd buildroot -$ git checkout 2021.05 # last tested working version -$ cp -r $WALLY/linux/buildroot-config-src/wally ./board -$ cp ./board/wally/main.config .config -$ make --jobs - -To generate disassembly files and the device tree, run another make script. Note that you can expect some warnings about phandle references while running dtc on wally-virt.dtb. - -$ source ~/riscv-wally/setup.sh -$ cd $WALLY/linux/buildroot-scripts -$ make all - -Note: When the make tasks complete, you’ll find source code in $RISCV/buildroot/output/build and the executables in $RISCV/buildroot/output/images. - -*** Download Synthesis Libraries - -For logic synthesis, we need a synthesis tool (see Section 3.XREF) and a cell library. Clone the OSU 12-track cell library for the Skywater 130 nm process: - -$ cd $RISCV -$ mkdir cad -$ mkdir cad/lib -$ cd cad/lib -$ git clone https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t12 - -** Installing EDA Tools - -Electronic Design Automation (EDA) tools are vital to implementations of System on Chip architectures as well as validating different designs. Open-source and commercial tools exist for multiple strategies and although the one can spend a lifetime using combinations of different tools, only a small subset of tools is utilized for this text. The tools are chosen because of their ease in access as well as their repeatability for accomplishing many of the tasks utilized to design Wally. It is anticipated that additional tools may be documented later after this is text is published to improve use and access. - -Siemens Quest is the primary tool utilized for simulating and validating Wally. For logic synthesis, you will need Synopsys Design Compiler. Questa and Design Compiler are commercial tools that require an educational or commercial license. - -Note: Some EDA tools utilize LM_LICENSE_FILE for their environmental variable to point to their license server. Some operating systems may also utilize MGLS_LICENSE_FILE instead, therefore, it is important to read the user manual on the preferred environmental variable required to point to a user’s license file. Although there are different mechanisms to allow licenses to work, many companies commonly utilize the FlexLM (i.e., Flex-enabled) license server manager that runs off a node locked license. - -Although most EDA tools are Linux-friendly, they tend to have issues when not installed on recommended OS flavors. Both Red Hat Enterprise Linux and SUSE Linux products typically tend to be recommended for installing commercial-based EDA tools and are recommended for utilizing complex simulation and architecture exploration. Questa can also be installed on Microsoft Windows as well as Mac OS with a Virtual Machine such as Parallels. - -Siemens Questa - -Siemens Questa simulates behavioral, RTL and gate-level HDL. To install Siemens Questa first go to a web browser and navigate to -https://eda.sw.siemens.com/en-US/ic/questa/simulation/advanced-simulator/. Click Sign In and log in with your credentials and the product can easily be downloaded and installed. Some Windows-based installations also require gcc libraries that are typically provided as a compressed zip download through Siemens. - -Synopsys Design Compiler (DC) - -Many commercial synthesis and place and route tools require a common installer. These installers are provided by the EDA vendor and Synopsys has one called Synopsys Installer. To use Synopsys Installer, you will need to acquire a license through Synopsys that is typically Called Synopsys Common Licensing (SCL). Both the Synopsys Installer, license key file, and Design Compiler can all be downloaded through Synopsys Solvnet. First open a web browser, log into Synsopsy Solvnet, and download the installer and Design Compiler installation files. Then, install the Installer - -$ firefox & -Navigate to https://solvnet.synopsys.com -Log in with your institution’s username and password -Click on Downloads, then scroll down to Synopsys Installer -Select the latest version (currently 5.4). Click Download Here, agree, -Click on SynopsysInstaller_v5.4.run -Return to downloads and also get Design Compiler (synthesis) latest version, and any others you want. - Click on all parts and the .spf file, then click Download Files near the top -move the SynopsysIntaller into /cad/synopsys/Installer_5.4 with 755 permission for cad, -move other files into /cad/synopsys/downloads and work as user cad from here on -$ cd /cad/synopsys/installer_5.4 -$ ./SynopsysInstaller_v5.4.run -Accept default installation directory -$ ./installer -Enter source path as /cad/synopsys/downloads, and installation path as /cad/synopsys -When prompted, enter your site ID -Follow prompts - -Installer can be utilized in graphical or text-based modes. It is far easier to use the text-based installation tool. To install DC, navigate to the location where your downloaded DC files are and type installer. You should be prompted with questions related to where you wish to have your files installed. - -The Synopsys Installer automatically installs all downloaded product files into a single top-level target directory. You do not need to specify the installation directory for each product. For example, if you specify /import/programs/synopsys as the target directory, your installation directory structure might look like this after installation: - -/import/programs/synopsys/syn/S-2021.06-SP1 - -Note: Although most parts of Wally, including the software used in this chapter and Questa simulation, will work on most modern Linux platforms, as of 2022, the Synopsys CAD tools for SoC design are only supported on RedHat Enterprise Linux 7.4 or 8 or SUSE Linux Enterprise Server (SLES) 12 or 15. Moreover, the RISC-V formal specification (sail-riscv) does not build gracefully on RHEL7. - -The Verilog simulation has been tested with Siemens Questa/ModelSim. This package is available to universities worldwide as part of the Design Verification Bundle through the Siemens Academic Partner Program members for $990/year. - -If you want to implement your own version of the chip, your tool and license complexity rises significantly. Logic synthesis uses Synopsys Design Compiler. Placement and routing uses Cadence Innovus. Both Synopsys and Cadence offer their tools at a steep discount to their university program members, but the cost is still several thousand dollars per year. Most research universities with integrated circuit design programs have Siemens, Synopsys, and Cadence licenses. You also need a process design kit (PDK) for a specific integrated circuit technology and its libraries. The open-source Google Skywater 130 nm PDK is sufficient to synthesize the core but lacks memories. Google presently funds some fabrication runs for universities. IMEC and Muse Semiconductor offers full access to multiproject wafer fabrication on the TSMC 28 nm process including logic, I/O, and memory libraries; this involves three non-disclosure agreements. Fabrication costs on the order of $10,000 for a batch of 1 mm2 chips. - -Startups can expect to spend more than $1 million on CAD tools to get a chip to market. Commercial CAD tools are not realistically available to individuals without a university or company connection. - -* Core-v-wally Repo Installation -** TL;DR Repo Install -cd -git clone --recurse-submodules https://github.com/davidharrishmc/riscv-wally -cd riscv-wally -source ./setup.sh # may require some modification for your system. Always run once after opening a new terminal. - -** Detailed Repo Install Guide - -1. cd - Return to home directory. The home directory is sufficent a location for students. - However more advanced users may choose to clone wally into another directory. - -2. git clone --recurse-submodules https://github.com/davidharrishmc/riscv-wally - Clone the wally repository and all dependent submodules into subdirectory riscv-wally. - -3. cd riscv-wally - Change directory to the wally repos riscv-wally. - -4. source ./setup.sh - setup.sh is s configuration script which creates several environment variables. - WALLY: Absolute directory path to this repo clone. - MGLS_LICENSE_FILE: Siemens license server for questa sim (modelsim). If your computer - is already configured for questa remove variable. - SNPSLMD_LICENSE_FILE: Synopsys license server. If remove if already setup. - PATH: PATH is extended to include the installation directories for Siemens questa and - Synopsys design compiler. Remove if already setup. - Adds riscv-gnu-toolchain and spike to PATH. Adjust if installed in another location. - Or remove if already in the PATH variable. - Adds path to wally repo specific tools. (Must include.) - Adds path to verilator. Remove if already in path. - RISCV: This is the location of the riscv tool chain and other wally requirements. - See the Sys Admin section for details. - - If using ubuntu 22.04 setup.sh can be reduced to - - echo "Executing Wally setup.sh" - - # Path to Wally repository - #!/bin/bash - - WALLY=$(dirname ${BASH_SOURCE[0]:-$0}) - export WALLY=$(cd "$WALLY" && pwd) - echo \$WALLY set to ${WALLY} - - # Path to RISC-V Tools - export RISCV=/opt/riscv # change this if you installed the tools in a different location - - # utility functions in Wally repository - export PATH=$PATH:$RISCV/bin - export PATH=$WALLY/bin:$PATH - -* Build and Run Regression Tests - Ensure the system tools are installed. - - cd - make - cd sim - ./regression-wally #(depends on having Questa installed) - diff --git a/README.md b/README.md index f7abf0ba1..a03625217 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,15 @@ Wally is described in an upcoming textbook, *RISC-V System-on-Chip Design*, by H New users may wish to do the following setup to access the server via a GUI and use a text editor. + Git started with Git configuration and authentication: B.1 (replace with your name and email) + $ git config --global user.name "Ben Bitdiddle" + $ git config --global user.email "ben_bitdiddle@wally.edu" + $ git config --global pull.rebase false Optional: Download and install x2go - A.1.1 Optional: Download and install VSCode - A.4.2 Optional: Make sure you can log into your server via x2go and via a terminal Terminal on Mac, cmd on Windows, xterm on Linux See A.1 about ssh -Y login from a terminal - Git started with Git configuration and authentication: B.1 - $ git config --global user.name ″Ben Bitdiddle″ - $ git config --global user.email ″ben_bitdiddle@wally.edu″ - $ git config --global pull.rebase false Then clone the repo, source setup, make the tests and run regression @@ -30,20 +30,20 @@ Then clone the repo, source setup, make the tests and run regression On the Linux computer where you will be working, log in +Clone your fork of the repo and run the setup script. + + $ cd + $ git clone --recurse-submodules https://github.com//cvw + $ git remote add upstream https://github.com/openhwgroup/cvw + $ cd cvw + $ source ./setup.sh + Add the following lines to your .bashrc or .bash_profile to run the setup script each time you log in. if [ -f ~/cvw/setup.sh ]; then source ~/cvw/setup.sh fi -Clone your fork of the repo, run the setup script, and build the tests: - - $ cd - $ git clone --recurse-submodules https://github.com//cvw - $ cd cvw - $ source ./setup.sh - $ make - Edit setup.sh and change the following lines to point to the path and license server for your Siemens Questa and Synopsys Design Compiler installation and license server. If you only have Questa, you can still simulate but cannot run logic synthesis. export MGLS_LICENSE_FILE=1717@solidworks.eng.hmc.edu # Change this to your Siemens license server @@ -51,253 +51,27 @@ Edit setup.sh and change the following lines to point to the path and license se export QUESTAPATH=/cad/mentor/questa_sim-2021.2_1/questasim/bin # Change this for your path to Questa export SNPSPATH=/cad/synopsys/SYN/bin # Change this for your path to Design Compiler -Run a regression simulation with Questa to prove everything is installed. +If the tools are not yet installed on your server, follow the Toolchain Installation instructions in the section below. +Build the tests and run a regression simulation with Questa to prove everything is installed. Building tests will take a while. + + $ make $ cd sim $ ./regression-wally (depends on having Questa installed) # Toolchain Installation (Sys Admin) -This section describes the open source toolchain installation. These steps should only be done once by the system admin. +This section describes the open source toolchain installation. The +current version of the toolchain has been tested on Ubuntu and Red +Hat/Rocky 8 Linux. Ubuntu works more smoothly and is recommended +unless you have a compelling need for RedHat. -## TL;DR Open Source Tool-chain Installation - -The full instalation details are involved can be be skipped using the following script, wally-tool-chain-install.sh. -The script installs the open source tools to /opt/riscv by default. This can be changed by supply the path as the first argument. This script does not install buildroot (see the Detailed Tool-chain Install Guide in the following section) and does not install commercial EDA tools; Siemens Questa, Synopsys Design Compiler, or Cadence Innovus (see section Installing IDA Tools). It must be run as root or with sudo. This script is tested for Ubuntu, 20.04 and 22.04. Fedora and Red Hat can be installed in the Detailed Tool-chain Install Guide. - - $ sudo wally-tool-chain-install.sh - -## Detailed Toolchain Install Guide - -This section describes how to install the tools needed for CORE-V-Wally. Superuser privileges are necessary for many of the tools. Setting up all of the tools can be time-consuming and fussy, so Appendix D also describes an option with a Docker container. - -### Open Source Software Installation - -Compiling, assembling, and simulating RISC-V programs requires downloading and installing the following free tools: - -1. The GCC cross-compiler -2. A RISC-V simulator such as Spike, Sail, and/or QEMU -3. Spike is easy to use but doesn’t support peripherals to boot Linux -4. QEMU is faster and can boot Linux -5. Sail is presently the official golden reference for RISC-V and is used by the riscof verification suite, but runs slowly and is painful to instal - -This setup needs to be done once by the administrator - -Note: The following directions assume you have an account called cad to install shared software and files. You can substitute a different user for cad if you prefer. - -Note: Installing software in Linux is unreasonably touchy and varies with the flavor and version of your Linux distribution. Don’t be surprised if the installation directions have changed since the book was written or don’t work on your machine; you may need some ingenuity to adjust them. Browse the openhwgroup/core-v-wally repo and look at the README.md for the latest build instructions. - -### Create the $RISCV Directory - -First, set up a directory for riscv software in some place such as /opt/riscv. We will call this shared directory $RISCV. - - $ export RISCV=/opt/riscv - $ sudo mkdir $RISCV - $ sudo chown cad $RISCV - $ sudo su cad (or root, if you don’t have a cad account) - $ export RISCV=/opt/riscv - $ chmod 755 $RISCV - $ umask 0002 - $ cd $RISCV - -### Update Tools - -Ubuntu users may need to install and update various tools. Beware when cutting and pasting that some lines are long! - - $ sudo apt update - $ sudo apt upgrade - $ sudo apt install git gawk make texinfo bison flex build-essential python3 zlib1g-dev libexpat-dev autoconf device-tree-compiler ninja-build libglib2.0-dev libpixman-1-dev build-essential ncurses-base ncurses-bin libncurses5-dev dialog - -### Install RISC-V GCC Cross-Compiler - -To install GCC from source can take hours to compile. This configuration enables multilib to target many flavors of RISC-V. This book is tested with GCC 12.2 (tagged 2023.01.31), but will likely work with newer versions as well. - - $ git clone https://github.com/riscv/riscv-gnu-toolchain - $ cd riscv-gnu-toolchain - $ git checkout 2023.01.31 - $ ./configure --prefix=$RISCV --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;" - $ make --jobs - -Note: make --jobs will reduce compile time by compiling in parallel. However, adding this option could dramatically increase the memory utilization of your local machine. - -### Install elf2hex - -We also need the elf2hex utility to convert executable files into hexadecimal files for Verilog simulation. Install with: - - $ cd $RISCV - $ export PATH=$RISCV/bin:$PATH - $ git clone https://github.com/sifive/elf2hex.git - $ cd elf2hex - $ autoreconf -i - $ ./configure --target=riscv64-unknown-elf --prefix=$RISCV - $ make - $ make install - -Note: The exe2hex utility that comes with Spike doesn’t work for our purposes because it doesn’t handle programs that start at 0x80000000. The SiFive version above is touchy to install. For example, if Python version 2.x is in your path, it won’t install correctly. Also, be sure riscv64-unknown-elf-objcopy shows up in your path in $RISCV/riscv-gnu-toolchain/bin at the time of compilation, or elf2hex won’t work properly. - -### Install RISC-V Spike Simulator - -Spike also takes a while to install and compile, but this can be done concurrently with the GCC installation. After the build, we need to change two Makefiles to support atomic instructions . - - $ cd $RISCV - $ git clone https://github.com/riscv-software-src/riscv-isa-sim - $ mkdir riscv-isa-sim/build - $ cd riscv-isa-sim/build - $ ../configure --prefix=$RISCV - $ make --jobs - $ make install - $ cd ../arch_test_target/spike/device - $ sed -i 's/--isa=rv32ic/--isa=rv32iac/' rv32i_m/privilege/Makefile.include - $ sed -i 's/--isa=rv64ic/--isa=rv64iac/' rv64i_m/privilege/Makefile.include - -### Install Sail Simulator - -Sail is the new golden reference model for RISC-V. Sail is written in OCaml, which is an object-oriented extension of ML, which in turn is a functional programming language suited to formal verification. OCaml is installed with the opam OCcaml package manager. Sail has so many dependencies that it can be difficult to install. - -On Ubuntu, apt-get makes opam installation fairly simple. - -$ sudo apt-get install opam build-essential libgmp-dev z3 pkg-config zlib1g-dev - -If you are on RedHat/Rocky Linux 8, installation is much more difficult because packages are not available in the default package manager and some need to be built from source. - - $ sudo bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)" - When prompted, put it in /usr/bin - $ sudo yum groupinstall 'Development Tools' - $ sudo yum -y install gmp-devel - $ sudo yum -y install zlib-devel - $ git clone https://github.com/Z3Prover/z3.git - $ cd z3 - $ python scripts/mk_make.py - $ cd build - $ make - $ sudo make install - $ cd ../.. - $ sudo pip3 install chardet==3.0.4 - $ sudo pip3 install urllib3==1.22 - -Once you have installed the packages on either Ubuntu or RedHat, use opam to install the OCaml compiler and Sail. Run as the cad user because you will be installing Sail in $RISCV. - - $ sudo su cad - $ opam init -y --disable-sandboxing - $ opam switch create ocaml-base-compiler.4.06.1 - $ opam install sail -y - -Now you can clone and compile Sail-RISCV. This will take a while. - - $ eval $(opam config env) - $ cd $RISCV - $ git clone https://github.com/riscv/sail-riscv.git - $ cd sail-riscv - $ make - $ ARCH=RV32 make - $ ARCH=RV64 make - $ exit - $ sudo su - $ export RISCV=/opt/riscv - $ ln -sf $RISCV/sail-riscv/c_emulator/riscv_sim_RV64 /usr/bin/riscv_sim_RV64 - $ ln -sf $RISCV/sail-riscv/c_emulator/riscv_sim_RV32 /usr/bin/riscv_sim_RV32 - $ exit - -### Install riscof - -riscof is a Python library used as the RISC-V compatibility framework test an implementation such as Wally or Spike against the Sail golden reference. It will be used to compile the riscv-arch-test suite. - -It is most convenient if the sysadmin installs riscof into the server’s Python libraries: - - $ sudo pip3 install testresources - $ sudo pip3 install riscof --ignore-installed PyYAML - -However, riscof can also be installed and run locally by individual users. - -### Other Python libraries - -While a sysadmin is installing Python libraries, it's worth doing some more that will be needed by visualization scripts. - - $ sudo pip3 install matplotlib scipy sklearn adjustText lief - -### Install Verilator - -Verilator is a free Verilog simulator with a good Lint tool used to catch errors in the SystemVerilog code. It is needed to run regression. -$ sudo apt install verilator - -### Install QEMU Simulator - -QEMU is another simulator used when booting Linux in Chapter 17. You can optionally install it using the following commands. - - -The QEMU patch changes the VirtIO driver to match the Wally peripherals, and also adds print statements to log the state of the CSRs (see Section 2.5XREF). - - - $ cd $RISCV - $ git clone --recurse-submodules https://github.com/qemu/qemu - $ cd qemu - $ git checkout v6.2.0 # last version tested; newer versions might be ok - $ ./configure --target-list=riscv64-softmmu --prefix=$RISCV - $ make --jobs - $ make install - -### Cross-Compile Buildroot Linux - -Building Linux is only necessary for exploring the boot process in Chapter 17. Building and generating a trace is a time-consuming operation that could be skipped for now; you can return to this section later if you are interested in the Linux details. - -Buildroot depends on configuration files in riscv-wally, so the cad user must install Wally first according to the instructions in Section 2.2.2. However, don’t source ~/wally-riscv/setup.sh because it will set LD_LIBRARY_PATH in a way to cause make to fail on buildroot. - -To configure and build Buildroot: - - $ cd $RISCV - $ export WALLY=~/riscv-wally # make sure you haven’t sourced ~/riscv-wally/setup.sh by now - $ git clone https://github.com/buildroot/buildroot.git - $ cd buildroot - $ git checkout 2021.05 # last tested working version - $ cp -r $WALLY/linux/buildroot-config-src/wally ./board - $ cp ./board/wally/main.config .config - $ make --jobs - -To generate disassembly files and the device tree, run another make script. Note that you can expect some warnings about phandle references while running dtc on wally-virt.dtb. - -$ source ~/riscv-wally/setup.sh -$ cd $WALLY/linux/buildroot-scripts -$ make all - -Note: When the make tasks complete, you’ll find source code in $RISCV/buildroot/output/build and the executables in $RISCV/buildroot/output/images. - -### Generate load images for linux boot - -The Questa linux boot uses preloaded bootram and ram memory. We use QEMU to generate these preloaded memory files. Files output in $RISCV/linux-testvectors - - cd cvw/linux/testvector-generation - ./genInitMem.sh - -This may require changing file permissions to the linux-testvectors directory. - -### Generate QEMU linux trace - -The linux testbench can instruction by instruction compare Wally's committed instructions against QEMU. To do this QEMU outputs a log file consisting of all instructions executed. Interrupts are handled by forcing the testbench to generate an interrupt at the same cycle as in QEMU. Generating this trace will take more than 24 hours. - - cd cvw/linux/testvector-generation - ./genTrace.sh - -### Download Synthesis Libraries - -For logic synthesis, we need a synthesis tool (see Section 3.XREF) and a cell library. Clone the OSU 12-track cell library for the Skywater 130 nm process: - - $ cd $RISCV - $ mkdir cad - $ mkdir cad/lib - $ cd cad/lib - $ git clone https://foss-eda-tools.googlesource.com/skywater-pdk/libs/sky130_osu_sc_t12 - -### Install github cli - -The github cli allows users to directly issue pull requests from their fork back to openhwgroup/cvw using the command line. - - $ type -p curl >/dev/null || sudo apt install curl -y - $ curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ - && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ - && sudo apt update \ - && sudo apt install gh -y +Ubuntu users can install the tools by running + $ sudo $WALLY/bin/wally-tool-chain-install.sh +See wally-tool-chain-install.sh for a detailed description of each component, +or to issue the commands one at a time to install on the command line. ## Installing EDA Tools Electronic Design Automation (EDA) tools are vital to implementations of System on Chip architectures as well as validating different designs. Open-source and commercial tools exist for multiple strategies and although the one can spend a lifetime using combinations of different tools, only a small subset of tools is utilized for this text. The tools are chosen because of their ease in access as well as their repeatability for accomplishing many of the tasks utilized to design Wally. It is anticipated that additional tools may be documented later after this is text is published to improve use and access. diff --git a/bin/wally-tool-chain-install.sh b/bin/wally-tool-chain-install.sh index 138104c75..ef98aed76 100755 --- a/bin/wally-tool-chain-install.sh +++ b/bin/wally-tool-chain-install.sh @@ -5,6 +5,7 @@ ## Written: Ross Thompson ross1728@gmail.com ## Created: 18 January 2023 ## Modified: 22 January 2023 +## Modified: 23 March 2023 ## ## Purpose: Open source tool chain installation script ## @@ -26,22 +27,27 @@ ## and limitations under the License. ################################################################################################ +# Use /opt/riscv for installation - may require running script with sudo export RISCV="${1:-/opt/riscv}" export PATH=$PATH:$RISCV/bin set -e # break on error -NUM_THREADS=1 # for low memory machines > 16GiB -#NUM_THREADS=8 # for >= 32GiB +# Modify accordingly for your machine +# Increasing NUM_THREADS will speed up parallel compilation of the tools +#NUM_THREADS=2 # for low memory machines > 16GiB +NUM_THREADS=8 # for >= 32GiB #NUM_THREADS=16 # for >= 64GiB sudo mkdir -p $RISCV -# UPDATE / UPGRADE -apt update +# Update and Upgrade tools (see https://itsfoss.com/apt-update-vs-upgrade/) +apt update -y +apt upgrade -y +apt install -y git gawk make texinfo bison flex build-essential python3 libz-dev libexpat-dev autoconf device-tree-compiler ninja-build libpixman-1-dev ncurses-base ncurses-bin libncurses5-dev dialog curl wget ftp libgmp-dev libglib2.0-dev python3-pip pkg-config opam z3 zlib1g-dev verilator -# INSTALL -apt install -y git gawk make texinfo bison flex build-essential python3 libz-dev libexpat-dev autoconf device-tree-compiler ninja-build libpixman-1-dev build-essential ncurses-base ncurses-bin libncurses5-dev dialog curl wget ftp libgmp-dev +# Other python libraries used through the book. +pip3 install matplotlib scipy scikit-learn adjustText lief # needed for Ubuntu 22.04, gcc cross compiler expects python not python2 or python3. if ! command -v python &> /dev/null @@ -50,7 +56,15 @@ then ln -sf /usr/bin/python3 /usr/bin/python fi -# gcc cross-compiler +# gcc cross-compiler (https://github.com/riscv-collab/riscv-gnu-toolchain) +# To install GCC from source can take hours to compile. +#This configuration enables multilib to target many flavors of RISC-V. +# This book is tested with GCC 12.2 (tagged 2023.01.31), but will likely work with newer versions as well. +# Note that GCC12.2 has binutils 2.39, which has a known performance bug that causes +# objdump to run 100x slower than in previous versions, causing riscof to make versy slowly. +# However GCC12.x is needed for bit manipulation instructions. There is an open issue to fix this: +# https://github.com/riscv-collab/riscv-gnu-toolchain/issues/1188 + cd $RISCV git clone https://github.com/riscv/riscv-gnu-toolchain cd riscv-gnu-toolchain @@ -59,9 +73,14 @@ git checkout 2023.01.31 make -j ${NUM_THREADS} make install -# elf2hex +# elf2hex (https://github.com/sifive/elf2hex) +#The elf2hex utility to converts executable files into hexadecimal files for Verilog simulation. +# Note: The exe2hex utility that comes with Spike doesn’t work for our purposes because it doesn’t +# handle programs that start at 0x80000000. The SiFive version above is touchy to install. +# For example, if Python version 2.x is in your path, it won’t install correctly. +# Also, be sure riscv64-unknown-elf-objcopy shows up in your path in $RISCV/riscv-gnu-toolchain/bin +# at the time of compilation, or elf2hex won’t work properly. cd $RISCV -#export PATH=$RISCV/riscv-gnu-toolchain/bin:$PATH export PATH=$RISCV/bin:$PATH git clone https://github.com/sifive/elf2hex.git cd elf2hex @@ -70,13 +89,8 @@ autoreconf -i make make install -# Update Python3.6 for QEMU -apt-get -y update -apt-get -y install python3-pip -apt-get -y install pkg-config -apt-get -y install libglib2.0-dev -# QEMU +# QEMU (https://www.qemu.org/docs/master/system/target-riscv.html) cd $RISCV git clone --recurse-submodules https://github.com/qemu/qemu cd qemu @@ -84,7 +98,9 @@ cd qemu make -j ${NUM_THREADS} make install -# Spike +# Spike (https://github.com/riscv-software-src/riscv-isa-sim) +# Spike also takes a while to install and compile, but this can be done concurrently +#with the GCC installation. After the build, we need to change two Makefiles to support atomic instructions. cd $RISCV git clone https://github.com/riscv-software-src/riscv-isa-sim mkdir -p riscv-isa-sim/build @@ -96,18 +112,25 @@ cd ../arch_test_target/spike/device sed -i 's/--isa=rv32ic/--isa=rv32iac/' rv32i_m/privilege/Makefile.include sed -i 's/--isa=rv64ic/--isa=rv64iac/' rv64i_m/privilege/Makefile.include -# SAIL -cd $RISCV -apt-get install -y opam build-essential libgmp-dev z3 pkg-config zlib1g-dev -git clone https://github.com/Z3Prover/z3.git -cd z3 -python scripts/mk_make.py -cd build -make -j ${NUM_THREADS} -make install -cd ../.. -pip3 install chardet==3.0.4 -pip3 install urllib3==1.22 +# Sail (https://github.com/riscv/sail-riscv) +# Sail is the new golden reference model for RISC-V. Sail is written in OCaml, which +# is an object-oriented extension of ML, which in turn is a functional programming +# language suited to formal verification. OCaml is installed with the opam OCcaml +# package manager. Sail has so many dependencies that it can be difficult to install. +# This script works for Ubuntu. + +# Do these commands only for RedHat / Rocky 8 to build from source. +#cd $RISCV +#git clone https://github.com/Z3Prover/z3.git +#cd z3 +#python scripts/mk_make.py +#cd build +#make -j ${NUM_THREADS} +#make install +#cd ../.. +#pip3 install chardet==3.0.4 +#pip3 install urllib3==1.22 + opam init -y --disable-sandboxing opam switch create ocaml-base-compiler.4.06.1 opam install sail -y @@ -127,13 +150,3 @@ ln -sf $RISCV/sail-riscv/c_emulator/riscv_sim_RV32 /usr/bin/riscv_sim_RV32 pip3 install testresources pip3 install riscof --ignore-installed PyYAML -# Verilator -apt install -y verilator - -# install github cli (gh) -type -p curl >/dev/null || sudo apt install curl -y -curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ -&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ -&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ -&& sudo apt update \ -&& sudo apt install gh -y diff --git a/config/rv32gc/wally-config.vh b/config/rv32gc/wally-config.vh index 359e2d83e..d9d770f82 100644 --- a/config/rv32gc/wally-config.vh +++ b/config/rv32gc/wally-config.vh @@ -145,10 +145,10 @@ `define DIVCOPIES 32'h4 // bit manipulation -`define ZBA_SUPPORTED 0 -`define ZBB_SUPPORTED 0 -`define ZBC_SUPPORTED 0 -`define ZBS_SUPPORTED 0 +`define ZBA_SUPPORTED 1 +`define ZBB_SUPPORTED 1 +`define ZBC_SUPPORTED 1 +`define ZBS_SUPPORTED 1 // Memory synthesis configuration `define USE_SRAM 0 diff --git a/config/rv64gc/wally-config.vh b/config/rv64gc/wally-config.vh index b5038be58..4ef3bf517 100644 --- a/config/rv64gc/wally-config.vh +++ b/config/rv64gc/wally-config.vh @@ -148,10 +148,10 @@ `define DIVCOPIES 32'h4 // bit manipulation -`define ZBA_SUPPORTED 0 -`define ZBB_SUPPORTED 0 -`define ZBC_SUPPORTED 0 -`define ZBS_SUPPORTED 0 +`define ZBA_SUPPORTED 1 +`define ZBB_SUPPORTED 1 +`define ZBC_SUPPORTED 1 +`define ZBS_SUPPORTED 1 // Memory synthesis configuration `define USE_SRAM 0 diff --git a/sim/Makefile b/sim/Makefile index 1c31e1f24..bf6255b33 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -1,3 +1,20 @@ + +all: riscoftests memfiles + # *** Build old tests/imperas-riscv-tests for now; + # Delete this part when the privileged tests transition over to tests/wally-riscv-arch-test + # DH: 2/27/22 temporarily commented out imperas-riscv-tests because license expired + #make -C ../tests/imperas-riscv-tests --jobs + #make -C ../tests/imperas-riscv-tests XLEN=64 --jobs + # Only compile Imperas tests if they are installed locally. + # They are usually a symlink to $RISCV/imperas-riscv-tests and only + # get compiled there manually during installation + #make -C ../addins/imperas-riscv-tests + #make -C ../addins/imperas-riscv-tests XLEN=64 + #cd ../addins/imperas-riscv-tests; elf2hex.sh + #cd ../addins/imperas-riscv-tests; extractFunctionRadix.sh work/*/*/*.elf.objdump + # Link Linux test vectors + #cd ../tests/linux-testgen/linux-testvectors/;./tvLinker.sh + coverage: #make -C ../tests/coverage --jobs #iter-elf.bash --cover --search ../tests/coverage @@ -21,22 +38,6 @@ coverage: # vcover report -recursive cov/cov.ucdb > cov/rv64gc_recursive.rpt vcover report -details -threshH 100 -html cov/cov.ucdb -all: riscoftests memfiles - # *** Build old tests/imperas-riscv-tests for now; - # Delete this part when the privileged tests transition over to tests/wally-riscv-arch-test - # DH: 2/27/22 temporarily commented out imperas-riscv-tests because license expired - #make -C ../tests/imperas-riscv-tests --jobs - #make -C ../tests/imperas-riscv-tests XLEN=64 --jobs - # Only compile Imperas tests if they are installed locally. - # They are usually a symlink to $RISCV/imperas-riscv-tests and only - # get compiled there manually during installation - #make -C ../addins/imperas-riscv-tests - #make -C ../addins/imperas-riscv-tests XLEN=64 - #cd ../addins/imperas-riscv-tests; elf2hex.sh - #cd ../addins/imperas-riscv-tests; extractFunctionRadix.sh work/*/*/*.elf.objdump - # Link Linux test vectors - #cd ../tests/linux-testgen/linux-testvectors/;./tvLinker.sh - allclean: clean all clean: diff --git a/sim/coverage-exclusions-rv64gc.do b/sim/coverage-exclusions-rv64gc.do index 8f79b7d5d..9905c897b 100644 --- a/sim/coverage-exclusions-rv64gc.do +++ b/sim/coverage-exclusions-rv64gc.do @@ -24,11 +24,22 @@ #// and limitations under the License. #//////////////////////////////////////////////////////////////////////////////////////////////// +# LZA (i<64) statement confuses coverage tool +# This is ugly to exlcude the whole file - is there a better option +coverage exclude -srcfile lzc.sv + + +###################### +# Toggle exclusions +# Not used because toggle coverage isn't measured +###################### + # Exclude DivBusyE from all design units because rv64gc uses the fdivsqrt unit for integer division -coverage exclude -togglenode DivBusyE -du * +#coverage exclude -togglenode DivBusyE -du * # Exclude QuotM and RemM from MDU because rv64gc uses the fdivsqrt rather tha div unit for integer division -coverage exclude -togglenode /dut/core/mdu/mdu/QuotM -coverage exclude -togglenode /dut/core/mdu/mdu/RemM +#coverage exclude -togglenode /dut/core/mdu/mdu/QuotM +#coverage exclude -togglenode /dut/core/mdu/mdu/RemM # StallFCause is hardwired to 0 -coverage exclude -togglenode /dut/core/hzu/StallFCause +#coverage exclude -togglenode /dut/core/hzu/StallFCause + diff --git a/sim/regression-wally b/sim/regression-wally index 683f30a93..7a509c890 100755 --- a/sim/regression-wally +++ b/sim/regression-wally @@ -79,7 +79,7 @@ for test in tests64i: configs.append(tc) tests32gcimperas = ["imperas32i", "imperas32f", "imperas32m", "imperas32c"] # unused -tests32gc = ["arch32f", "arch32d", "arch32i", "arch32priv", "arch32c", "arch32m", "arch32zi", "wally32a", "wally32priv", "wally32periph"] +tests32gc = ["arch32f", "arch32d", "arch32i", "arch32priv", "arch32c", "arch32m", "arch32zi", "arch32zba", "arch32zbb", "arch32zbc", "arch32zbs", "wally32a", "wally32priv", "wally32periph"] for test in tests32gc: tc = TestCase( name=test, @@ -126,12 +126,18 @@ for test in ahbTests: grepstr="All tests ran without failures") configs.append(tc) -#tests64gc = ["arch64i", "arch64c", "arch64m"] -tests64gc = ["arch64f", "arch64d", "arch64i", "arch64priv", "arch64c", "arch64m", "arch64zi", "wally64a", "wally64periph", "wally64priv"] +tests64gc = ["arch64f", "arch64d", "arch64i", "arch64zba", "arch64zbb", "arch64zbc", "arch64zbs", + "arch64priv", "arch64c", "arch64m", "arch64zi", "wally64a", "wally64periph", "wally64priv"] if (coverage): # delete all but 64gc tests when running coverage configs = [] - tests64gc = ["arch64f", "arch64d", "arch64i", "arch64priv", "arch64c", "arch64m", "arch64zi", "wally64a", "wally64periph", "wally64priv", "imperas64f", "imperas64d", "imperas64c", "imperas64i"] -# tests64gc.append(["imperas64f", "imperas64d", "imperas64c", "imperas64i"]) + tests64gc = ["coverage64gc", "arch64i", "arch64priv", "arch64c", "arch64m", + "arch64zi", "wally64a", "wally64periph", "wally64priv", + "arch64zba", "arch64zbb", "arch64zbc", "arch64zbs", + "imperas64f", "imperas64d", "imperas64c", "imperas64i"] +# tests64gc = ["coverage64gc", "arch64f", "arch64d", "arch64i", "arch64priv", "arch64c", "arch64m", +# "arch64zi", "wally64a", "wally64periph", "wally64priv", +# "arch64zba", "arch64zbb", "arch64zbc", "arch64zbs", +# "imperas64f", "imperas64d", "imperas64c", "imperas64i"] coverStr = '-coverage' else: coverStr = '' @@ -156,7 +162,7 @@ def run_test_case(config): """Run the given test case, and return 0 if the test suceeds and 1 if it fails""" logname = "logs/"+config.variant+"_"+config.name+".log" cmd = config.cmd.format(logname) - print(cmd) +# print(cmd) os.chdir(regressionDir) os.system(cmd) if search_log_for_text(config.grepstr, logname): diff --git a/src/cache/cache.sv b/src/cache/cache.sv index 5d4fca7d5..da7f83276 100644 --- a/src/cache/cache.sv +++ b/src/cache/cache.sv @@ -98,9 +98,9 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE logic CacheEn; logic [CACHEWORDSPERLINE-1:0] MemPAdrDecoded; logic [LINELEN/8-1:0] LineByteMask, DemuxedByteMask, FetchBufferByteSel; - logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr; + logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr; - genvar index; + genvar index; ///////////////////////////////////////////////////////////////////////////////////////////// // Read Path @@ -154,9 +154,9 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE // Bus address for fetch, writeback, or flush writeback mux3 #(`PA_BITS) CacheBusAdrMux(.d0({PAdr[`PA_BITS-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), - .d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), - .d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}), - .s({SelFlush, SelWriteback}), .y(CacheBusAdr)); + .d1({Tag, PAdr[SETTOP-1:OFFSETLEN], {OFFSETLEN{1'b0}}}), + .d2({Tag, FlushAdr, {OFFSETLEN{1'b0}}}), + .s({SelFlush, SelWriteback}), .y(CacheBusAdr)); ///////////////////////////////////////////////////////////////////////////////////////////// // Write Path @@ -198,11 +198,11 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE ///////////////////////////////////////////////////////////////////////////////////////////// cachefsm #(READ_ONLY_CACHE) cachefsm(.clk, .reset, .CacheBusRW, .CacheBusAck, - .FlushStage, .CacheRW, .CacheAtomic, .Stall, - .CacheHit, .LineDirty, .CacheStall, .CacheCommitted, - .CacheMiss, .CacheAccess, .SelAdr, - .ClearValid, .ClearDirty, .SetDirty, .SetValid, .SelWriteback, .SelFlush, - .FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst, - .FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer, + .FlushStage, .CacheRW, .CacheAtomic, .Stall, + .CacheHit, .LineDirty, .CacheStall, .CacheCommitted, + .CacheMiss, .CacheAccess, .SelAdr, + .ClearValid, .ClearDirty, .SetDirty, .SetValid, .SelWriteback, .SelFlush, + .FlushAdrCntEn, .FlushWayCntEn, .FlushCntRst, + .FlushAdrFlag, .FlushWayFlag, .FlushCache, .SelFetchBuffer, .InvalidateCache, .CacheEn, .LRUWriteEn); endmodule diff --git a/src/cache/cachefsm.sv b/src/cache/cachefsm.sv index 1edb0b65a..c51257be7 100644 --- a/src/cache/cachefsm.sv +++ b/src/cache/cachefsm.sv @@ -47,7 +47,7 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( output logic [1:0] CacheBusRW, // [1] Read (cache line fetch) or [0] write bus (cache line writeback) // performance counter outputs output logic CacheMiss, // Cache miss - output logic CacheAccess, // Cache access + output logic CacheAccess, // Cache access // cache internals input logic CacheHit, // Exactly 1 way hits @@ -69,21 +69,21 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( output logic CacheEn // Enable the cache memory arrays. Disable hold read data constant ); - logic resetDelay; - logic AMO, StoreAMO; - logic AnyUpdateHit, AnyHit; - logic AnyMiss; - logic FlushFlag; + logic resetDelay; + logic AMO, StoreAMO; + logic AnyUpdateHit, AnyHit; + logic AnyMiss; + logic FlushFlag; typedef enum logic [3:0]{STATE_READY, // hit states - // miss states - STATE_FETCH, - STATE_WRITEBACK, - STATE_WRITE_LINE, - STATE_READ_HOLD, // required for back to back reads. structural hazard on writting SRAM - // flush cache - STATE_FLUSH, - STATE_FLUSH_WRITEBACK} statetype; + // miss states + STATE_FETCH, + STATE_WRITEBACK, + STATE_WRITE_LINE, + STATE_READ_HOLD, // required for back to back reads. structural hazard on writting SRAM + // flush cache + STATE_FLUSH, + STATE_FLUSH_WRITEBACK} statetype; statetype CurrState, NextState; @@ -111,26 +111,26 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( always_comb begin NextState = STATE_READY; case (CurrState) - STATE_READY: if(InvalidateCache) NextState = STATE_READY; - else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; - else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; - else if(AnyMiss & LineDirty) NextState = STATE_WRITEBACK; - else NextState = STATE_READY; - STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; - else NextState = STATE_FETCH; - STATE_WRITE_LINE: NextState = STATE_READ_HOLD; - STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; - else NextState = STATE_READY; - STATE_WRITEBACK: if(CacheBusAck) NextState = STATE_FETCH; - else NextState = STATE_WRITEBACK; + STATE_READY: if(InvalidateCache) NextState = STATE_READY; + else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; + else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; + else if(AnyMiss & LineDirty) NextState = STATE_WRITEBACK; + else NextState = STATE_READY; + STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; + else NextState = STATE_FETCH; + STATE_WRITE_LINE: NextState = STATE_READ_HOLD; + STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; + else NextState = STATE_READY; + STATE_WRITEBACK: if(CacheBusAck) NextState = STATE_FETCH; + else NextState = STATE_WRITEBACK; // eviction needs a delay as the bus fsm does not correctly handle sending the write command at the same time as getting back the bus ack. - STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK; - else if (FlushFlag) NextState = STATE_READ_HOLD; - else NextState = STATE_FLUSH; - STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH; - else if(CacheBusAck) NextState = STATE_READ_HOLD; - else NextState = STATE_FLUSH_WRITEBACK; - default: NextState = STATE_READY; + STATE_FLUSH: if(LineDirty) NextState = STATE_FLUSH_WRITEBACK; + else if (FlushFlag) NextState = STATE_READ_HOLD; + else NextState = STATE_FLUSH; + STATE_FLUSH_WRITEBACK: if(CacheBusAck & ~FlushFlag) NextState = STATE_FLUSH; + else if(CacheBusAck) NextState = STATE_READ_HOLD; + else NextState = STATE_FLUSH_WRITEBACK; + default: NextState = STATE_READY; endcase end @@ -156,14 +156,14 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) ( (CurrState == STATE_READY & AnyMiss & LineDirty); assign SelFlush = (CurrState == STATE_READY & FlushCache) | - (CurrState == STATE_FLUSH) | - (CurrState == STATE_FLUSH_WRITEBACK); + (CurrState == STATE_FLUSH) | + (CurrState == STATE_FLUSH_WRITEBACK); assign FlushAdrCntEn = (CurrState == STATE_FLUSH_WRITEBACK & FlushWayFlag & CacheBusAck) | - (CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty); + (CurrState == STATE_FLUSH & FlushWayFlag & ~LineDirty); assign FlushWayCntEn = (CurrState == STATE_FLUSH & ~LineDirty) | - (CurrState == STATE_FLUSH_WRITEBACK & CacheBusAck); + (CurrState == STATE_FLUSH_WRITEBACK & CacheBusAck); assign FlushCntRst = (CurrState == STATE_FLUSH & FlushFlag & ~LineDirty) | - (CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck); + (CurrState == STATE_FLUSH_WRITEBACK & FlushFlag & CacheBusAck); // Bus interface controls assign CacheBusRW[1] = (CurrState == STATE_READY & AnyMiss & ~LineDirty) | (CurrState == STATE_FETCH & ~CacheBusAck) | diff --git a/src/cache/cacheway.sv b/src/cache/cacheway.sv index da40ab705..d7cc0792d 100644 --- a/src/cache/cacheway.sv +++ b/src/cache/cacheway.sv @@ -30,7 +30,7 @@ `include "wally-config.vh" module cacheway #(parameter NUMLINES=512, LINELEN = 256, TAGLEN = 26, - OFFSETLEN = 5, INDEXLEN = 9, READ_ONLY_CACHE = 0) ( + OFFSETLEN = 5, INDEXLEN = 9, READ_ONLY_CACHE = 0) ( input logic clk, input logic reset, input logic FlushStage, // Pipeline flush of second stage (prevent writes and bus operations) @@ -86,8 +86,6 @@ module cacheway #(parameter NUMLINES=512, LINELEN = 256, TAGLEN = 26, assign SelNonHit = FlushWayEn | SetValid | SelWriteback; mux2 #(1) seltagmux(VictimWay, FlushWay, SelFlush, SelTag); - //assign SelTag = VictimWay | FlushWay; - //assign SelData = HitWay | FlushWayEn | VictimWayEn; mux2 #(1) selectedwaymux(HitWay, SelTag, SelNonHit , SelData); @@ -95,10 +93,6 @@ module cacheway #(parameter NUMLINES=512, LINELEN = 256, TAGLEN = 26, // Write Enable demux ///////////////////////////////////////////////////////////////////////////////////////////// - // RT: Can we merge these two muxes? This is also shared in cacheLRU. - //mux3 #(1) selectwaymux(HitWay, VictimWay, FlushWay, {SelFlush, SetValid}, SelData); - //mux3 #(1) selecteddatamux(HitWay, VictimWay, FlushWay, {SelFlush, SelNonHit}, SelData); - assign SetValidWay = SetValid & SelData; assign ClearValidWay = ClearValid & SelData; assign SetDirtyWay = SetDirty & SelData; @@ -117,8 +111,6 @@ module cacheway #(parameter NUMLINES=512, LINELEN = 256, TAGLEN = 26, .addr(CacheSet), .dout(ReadTag), .bwe('1), .din(PAdr[`PA_BITS-1:OFFSETLEN+INDEXLEN]), .we(SetValidEN)); - - // AND portion of distributed tag multiplexer assign TagWay = SelTag ? ReadTag : '0; // AND part of AOMux assign DirtyWay = SelTag & Dirty & ValidWay; @@ -152,8 +144,8 @@ module cacheway #(parameter NUMLINES=512, LINELEN = 256, TAGLEN = 26, always_ff @(posedge clk) begin // Valid bit array, if (reset) ValidBits <= #1 '0; if(CacheEn) begin - ValidWay <= #1 ValidBits[CacheSet]; - if(InvalidateCache) ValidBits <= #1 '0; + ValidWay <= #1 ValidBits[CacheSet]; + if(InvalidateCache) ValidBits <= #1 '0; else if (SetValidEN | (ClearValidWay & ~FlushStage)) ValidBits[CacheSet] <= #1 SetValidWay; end end diff --git a/src/cache/subcachelineread.sv b/src/cache/subcachelineread.sv index 490618070..58d022a71 100644 --- a/src/cache/subcachelineread.sv +++ b/src/cache/subcachelineread.sv @@ -33,8 +33,8 @@ module subcachelineread #(parameter LINELEN, WORDLEN, parameter MUXINTERVAL )( // The number of bits between mux. Set to 16 for I$ to support compressed. Set to `LLEN for D$ input logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1 : 0] PAdr, // Physical address - input logic [LINELEN-1:0] ReadDataLine,// Read data of the whole cacheline - output logic [WORDLEN-1:0] ReadDataWord // read data of selected word. + input logic [LINELEN-1:0] ReadDataLine,// Read data of the whole cacheline + output logic [WORDLEN-1:0] ReadDataWord // read data of selected word. ); localparam WORDSPERLINE = LINELEN/MUXINTERVAL; @@ -50,7 +50,7 @@ module subcachelineread #(parameter LINELEN, WORDLEN, genvar index; for (index = 0; index < WORDSPERLINE; index++) begin:readdatalinesetsmux - assign ReadDataLineSets[index] = ReadDataLinePad[(index*MUXINTERVAL)+WORDLEN-1 : (index*MUXINTERVAL)]; + assign ReadDataLineSets[index] = ReadDataLinePad[(index*MUXINTERVAL)+WORDLEN-1 : (index*MUXINTERVAL)]; end // variable input mux diff --git a/src/ebu/ahbcacheinterface.sv b/src/ebu/ahbcacheinterface.sv index 7278f4f93..b30a15096 100644 --- a/src/ebu/ahbcacheinterface.sv +++ b/src/ebu/ahbcacheinterface.sv @@ -35,7 +35,7 @@ module ahbcacheinterface #( parameter LINELEN, // Number of bits in cacheline parameter LLENPOVERAHBW // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation) )( - input logic HCLK, HRESETn, + input logic HCLK, HRESETn, // bus interface controls input logic HREADY, // AHB peripheral ready output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ @@ -56,7 +56,7 @@ module ahbcacheinterface #( input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch output logic CacheBusAck, // Handshack to $ indicating bus transaction completed output logic [LINELEN-1:0] FetchBuffer, // Register to hold beats of cache line as the arrive from bus - output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase + output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr // uncached interface @@ -76,10 +76,10 @@ module ahbcacheinterface #( logic [`PA_BITS-1:0] LocalHADDR; // Address after selecting between cached and uncached operation logic [AHBWLOGBWPL-1:0] BeatCountDelayed; // Beat within the cache line in the second (Data) cache stage logic CaptureEn; // Enable updating the Fetch buffer with valid data from HRDATA - logic [`AHBW/8-1:0] BusByteMaskM; // Byte enables within a word. For cache request all 1s + logic [`AHBW/8-1:0] BusByteMaskM; // Byte enables within a word. For cache request all 1s logic [`AHBW-1:0] PreHWDATA; // AHB Address phase write data - genvar index; + genvar index; // fetch buffer is made of BEATSPERLINE flip-flops for (index = 0; index < BEATSPERLINE; index++) begin:fetchbuffer @@ -100,7 +100,7 @@ module ahbcacheinterface #( logic [`AHBW-1:0] AHBWordSets [(LLENPOVERAHBW)-1:0]; genvar index; for (index = 0; index < LLENPOVERAHBW; index++) begin:readdatalinesetsmux - assign AHBWordSets[index] = CacheReadDataWordM[(index*`AHBW)+`AHBW-1: (index*`AHBW)]; + assign AHBWordSets[index] = CacheReadDataWordM[(index*`AHBW)+`AHBW-1: (index*`AHBW)]; end assign CacheReadDataWordAHB = AHBWordSets[BeatCount[$clog2(LLENPOVERAHBW)-1:0]]; end else assign CacheReadDataWordAHB = CacheReadDataWordM[`AHBW-1:0]; @@ -118,5 +118,5 @@ module ahbcacheinterface #( buscachefsm #(BeatCountThreshold, AHBWLOGBWPL) AHBBuscachefsm( .HCLK, .HRESETn, .Flush, .BusRW, .Stall, .BusCommitted, .BusStall, .CaptureEn, .SelBusBeat, .CacheBusRW, .CacheBusAck, .BeatCount, .BeatCountDelayed, - .HREADY, .HTRANS, .HWRITE, .HBURST); + .HREADY, .HTRANS, .HWRITE, .HBURST); endmodule diff --git a/src/ebu/ahbinterface.sv b/src/ebu/ahbinterface.sv index ff50f54f5..579791032 100644 --- a/src/ebu/ahbinterface.sv +++ b/src/ebu/ahbinterface.sv @@ -32,29 +32,28 @@ module ahbinterface #( parameter LSU = 0 // 1: LSU bus width is `XLEN, 0: IFU bus width is 32 bits )( - input logic HCLK, HRESETn, + input logic HCLK, HRESETn, // bus interface - input logic HREADY, // AHB peripheral ready - output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ - output logic HWRITE, // AHB 0: Read operation 1: Write operation - input logic [`XLEN-1:0] HRDATA, // AHB read data - output logic [`XLEN-1:0] HWDATA, // AHB write data - output logic [`XLEN/8-1:0] HWSTRB, // AHB byte mask + input logic HREADY, // AHB peripheral ready + output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ + output logic HWRITE, // AHB 0: Read operation 1: Write operation + input logic [`XLEN-1:0] HRDATA, // AHB read data + output logic [`XLEN-1:0] HWDATA, // AHB write data + output logic [`XLEN/8-1:0] HWSTRB, // AHB byte mask // lsu/ifu interface - input logic Stall, // Core pipeline is stalled - input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting - input logic [1:0] BusRW, // Memory operation read/write control: 10: read, 01: write - input logic [`XLEN/8-1:0] ByteMask, // Bytes enables within a word - input logic [`XLEN-1:0] WriteData, // IEU write data for a store - output logic BusStall, // Bus is busy with an in flight memory operation - output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt + input logic Stall, // Core pipeline is stalled + input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting + input logic [1:0] BusRW, // Memory operation read/write control: 10: read, 01: write + input logic [`XLEN/8-1:0] ByteMask, // Bytes enables within a word + input logic [`XLEN-1:0] WriteData, // IEU write data for a store + output logic BusStall, // Bus is busy with an in flight memory operation + output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt output logic [(LSU ? `XLEN : 32)-1:0] FetchBuffer // Register to hold HRDATA after arriving from the bus ); - logic CaptureEn; - - localparam LEN = (LSU ? `XLEN : 32); // 32 bits for IFU, XLEN for LSU + logic CaptureEn; + localparam LEN = (LSU ? `XLEN : 32); // 32 bits for IFU, XLEN for LSU flopen #(LEN) fb(.clk(HCLK), .en(CaptureEn), .d(HRDATA[LEN-1:0]), .q(FetchBuffer)); @@ -70,4 +69,5 @@ module ahbinterface #( busfsm busfsm(.HCLK, .HRESETn, .Flush, .BusRW, .BusCommitted, .Stall, .BusStall, .CaptureEn, .HREADY, .HTRANS, .HWRITE); + endmodule diff --git a/src/ebu/buscachefsm.sv b/src/ebu/buscachefsm.sv index 2f3e99228..c619c9135 100644 --- a/src/ebu/buscachefsm.sv +++ b/src/ebu/buscachefsm.sv @@ -35,33 +35,33 @@ module buscachefsm #( parameter BeatCountThreshold, // Largest beat index parameter AHBWLOGBWPL // Log2 of BEATSPERLINE )( - input logic HCLK, - input logic HRESETn, + input logic HCLK, + input logic HRESETn, // IEU interface - input logic Stall, // Core pipeline is stalled - input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting - input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write - output logic BusStall, // Bus is busy with an in flight memory operation - output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt - - // ahb cache interface locals. - output logic CaptureEn, // Enable updating the Fetch buffer with valid data from HRDATA - - // cache interface - input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch - output logic CacheBusAck, // Handshack to $ indicating bus transaction completed + input logic Stall, // Core pipeline is stalled + input logic Flush, // Pipeline stage flush. Prevents bus transaction from starting + input logic [1:0] BusRW, // Uncached memory operation read/write control: 10: read, 01: write + output logic BusStall, // Bus is busy with an in flight memory operation + output logic BusCommitted, // Bus is busy with an in flight memory operation and it is not safe to take an interrupt + + // ahb cache interface locals. + output logic CaptureEn, // Enable updating the Fetch buffer with valid data from HRDATA + + // cache interface + input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch + output logic CacheBusAck, // Handshack to $ indicating bus transaction completed // lsu interface output logic [AHBWLOGBWPL-1:0] BeatCount, // Beat position within the cache line in the Address Phase output logic [AHBWLOGBWPL-1:0] BeatCountDelayed, // Beat within the cache line in the second (Data) cache stage - output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr + output logic SelBusBeat, // Tells the cache to select the word from ReadData or WriteData from BeatCount rather than PAdr // BUS interface - input logic HREADY, // AHB peripheral ready - output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ - output logic HWRITE, // AHB 0: Read operation 1: Write operation - output logic [2:0] HBURST // AHB burst length + input logic HREADY, // AHB peripheral ready + output logic [1:0] HTRANS, // AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ + output logic HWRITE, // AHB 0: Read operation 1: Write operation + output logic [2:0] HBURST // AHB burst length ); typedef enum logic [2:0] {ADR_PHASE, DATA_PHASE, MEM3, CACHE_FETCH, CACHE_WRITEBACK} busstatetype; @@ -70,26 +70,26 @@ module buscachefsm #( busstatetype CurrState, NextState; logic [AHBWLOGBWPL-1:0] NextBeatCount; - logic FinalBeatCount; - logic [2:0] LocalBurstType; - logic BeatCntEn; - logic BeatCntReset; - logic CacheAccess; + logic FinalBeatCount; + logic [2:0] LocalBurstType; + logic BeatCntEn; + logic BeatCntReset; + logic CacheAccess; always_ff @(posedge HCLK) if (~HRESETn | Flush) CurrState <= #1 ADR_PHASE; else CurrState <= #1 NextState; always_comb begin - case(CurrState) - ADR_PHASE: if (HREADY & |BusRW) NextState = DATA_PHASE; - else if (HREADY & CacheBusRW[0]) NextState = CACHE_WRITEBACK; - else if (HREADY & CacheBusRW[1]) NextState = CACHE_FETCH; - else NextState = ADR_PHASE; - DATA_PHASE: if(HREADY) NextState = MEM3; - else NextState = DATA_PHASE; - MEM3: if(Stall) NextState = MEM3; - else NextState = ADR_PHASE; + case(CurrState) + ADR_PHASE: if (HREADY & |BusRW) NextState = DATA_PHASE; + else if (HREADY & CacheBusRW[0]) NextState = CACHE_WRITEBACK; + else if (HREADY & CacheBusRW[1]) NextState = CACHE_FETCH; + else NextState = ADR_PHASE; + DATA_PHASE: if(HREADY) NextState = MEM3; + else NextState = DATA_PHASE; + MEM3: if(Stall) NextState = MEM3; + else NextState = ADR_PHASE; CACHE_FETCH: if(HREADY & FinalBeatCount & CacheBusRW[0]) NextState = CACHE_WRITEBACK; else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH; else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE; @@ -98,8 +98,8 @@ module buscachefsm #( else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH; else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE; else NextState = CACHE_WRITEBACK; - default: NextState = ADR_PHASE; - endcase + default: NextState = ADR_PHASE; + endcase end // IEU, LSU, and IFU controls @@ -117,8 +117,8 @@ module buscachefsm #( assign CacheAccess = CurrState == CACHE_FETCH | CurrState == CACHE_WRITEBACK; assign BusStall = (CurrState == ADR_PHASE & ((|BusRW) | (|CacheBusRW))) | - //(CurrState == DATA_PHASE & ~BusRW[0]) | // *** replace the next line with this. Fails uart test but i think it's a test problem not a hardware problem. - (CurrState == DATA_PHASE) | + //(CurrState == DATA_PHASE & ~BusRW[0]) | // *** replace the next line with this. Fails uart test but i think it's a test problem not a hardware problem. + (CurrState == DATA_PHASE) | (CurrState == CACHE_FETCH & ~HREADY) | (CurrState == CACHE_WRITEBACK & ~HREADY); assign BusCommitted = CurrState != ADR_PHASE; @@ -144,7 +144,7 @@ module buscachefsm #( // communication to cache assign CacheBusAck = (CacheAccess & HREADY & FinalBeatCount); assign SelBusBeat = (CurrState == ADR_PHASE & (BusRW[0] | CacheBusRW[0])) | - (CurrState == DATA_PHASE & BusRW[0]) | + (CurrState == DATA_PHASE & BusRW[0]) | (CurrState == CACHE_WRITEBACK) | (CurrState == CACHE_FETCH); diff --git a/src/ebu/busfsm.sv b/src/ebu/busfsm.sv index 019708a3d..de1dd7583 100644 --- a/src/ebu/busfsm.sv +++ b/src/ebu/busfsm.sv @@ -57,20 +57,20 @@ module busfsm ( else CurrState <= #1 NextState; always_comb begin - case(CurrState) - ADR_PHASE: if(HREADY & |BusRW) NextState = DATA_PHASE; - else NextState = ADR_PHASE; - DATA_PHASE: if(HREADY) NextState = MEM3; - else NextState = DATA_PHASE; - MEM3: if(Stall) NextState = MEM3; - else NextState = ADR_PHASE; - default: NextState = ADR_PHASE; - endcase + case(CurrState) + ADR_PHASE: if(HREADY & |BusRW) NextState = DATA_PHASE; + else NextState = ADR_PHASE; + DATA_PHASE: if(HREADY) NextState = MEM3; + else NextState = DATA_PHASE; + MEM3: if(Stall) NextState = MEM3; + else NextState = ADR_PHASE; + default: NextState = ADR_PHASE; + endcase end assign BusStall = (CurrState == ADR_PHASE & |BusRW) | -// (CurrState == DATA_PHASE & ~BusRW[0]); // possible optimization here. fails uart test, but i'm not sure the failure is valid. - (CurrState == DATA_PHASE); +// (CurrState == DATA_PHASE & ~BusRW[0]); // possible optimization here. fails uart test, but i'm not sure the failure is valid. + (CurrState == DATA_PHASE); assign BusCommitted = CurrState != ADR_PHASE; diff --git a/src/ebu/controllerinputstage.sv b/src/ebu/controllerinputstage.sv index 681f12bc9..7a6c76bb9 100644 --- a/src/ebu/controllerinputstage.sv +++ b/src/ebu/controllerinputstage.sv @@ -36,26 +36,26 @@ module controllerinputstage #( parameter SAVE_ENABLED = 1 // 1: Save manager inputs if Save = 1, 0: Don't save inputs )( - input logic HCLK, - input logic HRESETn, - input logic Save, // Two or more managers requesting (HTRANS != 00) at the same time. Save the non-granted manager inputs - input logic Restore, // Restore a saved manager inputs when it is finally granted - input logic Disable, // Supress HREADY to the non-granted manager - output logic Request, // This manager is making a request + input logic HCLK, + input logic HRESETn, + input logic Save, // Two or more managers requesting (HTRANS != 00) at the same time. Save the non-granted manager inputs + input logic Restore, // Restore a saved manager inputs when it is finally granted + input logic Disable, // Supress HREADY to the non-granted manager + output logic Request, // This manager is making a request // controller input - input logic [1:0] HTRANSIn, // Manager input. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ - input logic HWRITEIn, // Manager input. AHB 0: Read operation 1: Write operation - input logic [2:0] HSIZEIn, // Manager input. AHB transaction width - input logic [2:0] HBURSTIn, // Manager input. AHB burst length + input logic [1:0] HTRANSIn, // Manager input. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ + input logic HWRITEIn, // Manager input. AHB 0: Read operation 1: Write operation + input logic [2:0] HSIZEIn, // Manager input. AHB transaction width + input logic [2:0] HBURSTIn, // Manager input. AHB burst length input logic [`PA_BITS-1:0] HADDRIn, // Manager input. AHB address - output logic HREADYOut, // Indicate to manager the peripherial is not busy and another manager does not have priority + output logic HREADYOut, // Indicate to manager the peripherial is not busy and another manager does not have priority // controller output - output logic [1:0] HTRANSOut, // Aribrated manager transaction. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ - output logic HWRITEOut, // Aribrated manager transaction. AHB 0: Read operation 1: Write operation - output logic [2:0] HSIZEOut, // Aribrated manager transaction. AHB transaction width - output logic [2:0] HBURSTOut, // Aribrated manager transaction. AHB burst length + output logic [1:0] HTRANSOut, // Aribrated manager transaction. AHB transaction type, 00: IDLE, 10 NON_SEQ, 11 SEQ + output logic HWRITEOut, // Aribrated manager transaction. AHB 0: Read operation 1: Write operation + output logic [2:0] HSIZEOut, // Aribrated manager transaction. AHB transaction width + output logic [2:0] HBURSTOut, // Aribrated manager transaction. AHB burst length output logic [`PA_BITS-1:0] HADDROut, // Aribrated manager transaction. AHB address - input logic HREADYIn // Peripherial ready + input logic HREADYIn // Peripherial ready ); logic HWRITESave; diff --git a/src/ebu/ebu.sv b/src/ebu/ebu.sv index d4e87de2a..b045c6aaa 100644 --- a/src/ebu/ebu.sv +++ b/src/ebu/ebu.sv @@ -52,27 +52,26 @@ module ebu ( output logic LSUHREADY, // AHB peripheral. Never gated as LSU always has priority // AHB-Lite external signals - output logic HCLK, HRESETn, - input logic HREADY, // AHB peripheral ready - input logic HRESP, // AHB peripheral response. 0: OK 1: Error - output logic [`PA_BITS-1:0] HADDR, // AHB address to peripheral after arbitration - output logic [`AHBW-1:0] HWDATA, // AHB Write data after arbitration - output logic [`XLEN/8-1:0] HWSTRB, // AHB byte write enables after arbitration - output logic HWRITE, // AHB transaction direction after arbitration - output logic [2:0] HSIZE, // AHB transaction size after arbitration - output logic [2:0] HBURST, // AHB burst length after arbitration - output logic [3:0] HPROT, // AHB protection. Wally does not use - output logic [1:0] HTRANS, // AHB transaction request after arbitration - output logic HMASTLOCK // AHB master lock. Wally does not use + output logic HCLK, HRESETn, + input logic HREADY, // AHB peripheral ready + input logic HRESP, // AHB peripheral response. 0: OK 1: Error + output logic [`PA_BITS-1:0] HADDR, // AHB address to peripheral after arbitration + output logic [`AHBW-1:0] HWDATA, // AHB Write data after arbitration + output logic [`XLEN/8-1:0] HWSTRB, // AHB byte write enables after arbitration + output logic HWRITE, // AHB transaction direction after arbitration + output logic [2:0] HSIZE, // AHB transaction size after arbitration + output logic [2:0] HBURST, // AHB burst length after arbitration + output logic [3:0] HPROT, // AHB protection. Wally does not use + output logic [1:0] HTRANS, // AHB transaction request after arbitration + output logic HMASTLOCK // AHB master lock. Wally does not use ); - logic LSUDisable; - logic LSUSelect; + logic LSUSelect; logic IFUSave; - logic IFURestore; - logic IFUDisable; - logic IFUSelect; + logic IFURestore; + logic IFUDisable; + logic IFUSelect; logic [`PA_BITS-1:0] IFUHADDROut; logic [1:0] IFUHTRANSOut; @@ -87,10 +86,8 @@ module ebu ( logic LSUHWRITEOut; logic IFUReq; - logic LSUReq; + logic LSUReq; - - assign HCLK = clk; assign HRESETn = ~reset; @@ -129,7 +126,7 @@ module ebu ( // HRDATA is sent to all controllers at the core level. ebufsmarb ebufsmarb(.HCLK, .HRESETn, .HBURST, .HREADY, .LSUReq, .IFUReq, .IFUSave, - .IFURestore, .IFUDisable, .IFUSelect, .LSUDisable, .LSUSelect); + .IFURestore, .IFUDisable, .IFUSelect, .LSUDisable, .LSUSelect); endmodule diff --git a/src/ebu/ebufsmarb.sv b/src/ebu/ebufsmarb.sv index bd5cfb892..ec1a3d674 100644 --- a/src/ebu/ebufsmarb.sv +++ b/src/ebu/ebufsmarb.sv @@ -31,34 +31,33 @@ `include "wally-config.vh" module ebufsmarb ( - input logic HCLK, - input logic HRESETn, + input logic HCLK, + input logic HRESETn, input logic [2:0] HBURST, // AHB burst length - input logic HREADY, + input logic HREADY, - input logic LSUReq, - input logic IFUReq, + input logic LSUReq, + input logic IFUReq, + output logic IFUSave, + output logic IFURestore, + output logic IFUDisable, + output logic IFUSelect, + output logic LSUDisable, + output logic LSUSelect); - output logic IFUSave, - output logic IFURestore, - output logic IFUDisable, - output logic IFUSelect, - output logic LSUDisable, - output logic LSUSelect); - - typedef enum logic [1:0] {IDLE, ARBITRATE} statetype; + typedef enum logic [1:0] {IDLE, ARBITRATE} statetype; statetype CurrState, NextState; - logic both; // Both the LSU and IFU request at the same time - logic IFUReqD; // 1 cycle delayed IFU request. Part of arbitration - logic FinalBeat, FinalBeatD; // Indicates the last beat of a burst - logic BeatCntEn; - logic [4-1:0] NextBeatCount, BeatCount; // Position within a burst transfer - logic CntReset; - logic [3:0] Threshold; // Number of beats derived from HBURST + logic both; // Both the LSU and IFU request at the same time + logic IFUReqD; // 1 cycle delayed IFU request. Part of arbitration + logic FinalBeat, FinalBeatD; // Indicates the last beat of a burst + logic BeatCntEn; + logic [3:0] BeatCount; // Position within a burst transfer + logic BeatCntReset; + logic [3:0] Threshold; // Number of beats derived from HBURST //////////////////////////////////////////////////////////////////////////////////////////////////// // Aribtration scheme @@ -70,8 +69,8 @@ module ebufsmarb ( flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextState, IDLE, CurrState); always_comb case (CurrState) - IDLE: if (both) NextState = ARBITRATE; - else NextState = IDLE; + IDLE: if (both) NextState = ARBITRATE; + else NextState = IDLE; ARBITRATE: if (HREADY & FinalBeatD & ~(LSUReq & IFUReq)) NextState = IDLE; else NextState = ARBITRATE; default: NextState = IDLE; @@ -91,31 +90,33 @@ module ebufsmarb ( // This is necessary because the pipeline is stalled for the entire duration of both transactions, // and the LSU memory request will stil be active. flopr #(1) ifureqreg(HCLK, ~HRESETn, IFUReq, IFUReqD); - assign LSUDisable = CurrState == ARBITRATE ? 1'b0 : (IFUReqD & ~(HREADY & FinalBeatD)); - assign LSUSelect = NextState == ARBITRATE ? 1'b1: LSUReq; + assign LSUDisable = (CurrState == ARBITRATE) ? 1'b0 : (IFUReqD & ~(HREADY & FinalBeatD)); + assign LSUSelect = (NextState == ARBITRATE) ? 1'b1: LSUReq; //////////////////////////////////////////////////////////////////////////////////////////////////// // Burst mode logic //////////////////////////////////////////////////////////////////////////////////////////////////// - flopenr #(4) BeatCountReg(HCLK, ~HRESETn | CntReset | FinalBeat, BeatCntEn, NextBeatCount, BeatCount); - assign NextBeatCount = BeatCount + 1'b1; - - assign CntReset = NextState == IDLE; + assign BeatCntReset = NextState == IDLE; assign FinalBeat = (BeatCount == Threshold); // Detect when we are waiting on the final access. - assign BeatCntEn = (NextState == ARBITRATE & HREADY); - + // Counting the beats in the EBU is only necessary when both the LSU and IFU request concurrently. + // LSU has priority. HREADY serves double duty during a burst transaction. It indicates when the + // beat completes and when the transaction finishes. However there is nothing external to + // differentiate them. The EBU counts the HREADY beats so it knows when to switch to the IFU's + // request. + assign BeatCntEn = (NextState == ARBITRATE) & HREADY; + counter #(4) BeatCounter(HCLK, ~HRESETn | BeatCntReset | FinalBeat, BeatCntEn, BeatCount); + // Used to store data from data phase of AHB. - flopenr #(1) FinalBeatReg(HCLK, ~HRESETn | CntReset, BeatCntEn, FinalBeat, FinalBeatD); + flopenr #(1) FinalBeatReg(HCLK, ~HRESETn | BeatCntReset, BeatCntEn, FinalBeat, FinalBeatD); - // unlike the bus fsm in lsu/ifu, we need to derive the number of beats from HBURST. - always_comb begin - case(HBURST) - 0: Threshold = 4'b0000; - 3: Threshold = 4'b0011; // INCR4 - 5: Threshold = 4'b0111; // INCR8 - 7: Threshold = 4'b1111; // INCR16 - default: Threshold = 4'b0000; // INCR without end. - endcase - end + // unlike the bus fsm in lsu/ifu, we need to derive the number of beats from HBURST, Threshold = num beats - 1. + // HBURST[2:1] Beats threshold + // 00 1 0 + // 01 4 3 + // 10 8 7 + // 11 16 15 + always_comb + if (HBURST[2:1] == 2'b00) Threshold = 4'b0000; + else Threshold = (2 << HBURST[2:1]) - 1; endmodule diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index e787d10b4..be10e8007 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -31,53 +31,53 @@ module fctrl ( input logic clk, input logic reset, // input control signals - input logic StallE, StallM, StallW, // stall signals - input logic FlushE, FlushM, FlushW, // flush signals - input logic IntDivE, // is inteteger division - input logic [2:0] FRM_REGW, // rounding mode from CSR - input logic [1:0] STATUS_FS, // is FPU enabled? - input logic FDivBusyE, // is the divider busy - // intruction - input logic [31:0] InstrD, // the full instruction - input logic [6:0] Funct7D, // bits 31:25 of instruction - may contain percision - input logic [6:0] OpD, // bits 6:0 of instruction - input logic [4:0] Rs2D, // bits 24:20 of instruction - input logic [2:0] Funct3D, Funct3E, // bits 14:12 of instruction - may contain rounding mode - // input mux selections - output logic XEnD, YEnD, ZEnD, // enable inputs - output logic XEnE, YEnE, ZEnE, // enable inputs - // opperation mux selections - output logic FCvtIntE, FCvtIntW, // convert to integer opperation - output logic [2:0] FrmM, // FP rounding mode - output logic [`FMTBITS-1:0] FmtE, FmtM, // FP format - output logic [2:0] OpCtrlE, OpCtrlM, // Select which opperation to do in each component - output logic FpLoadStoreM, // FP load or store instruction - output logic [1:0] PostProcSelE, PostProcSelM, // select result in the post processing unit - output logic [1:0] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage + input logic StallE, StallM, StallW, // stall signals + input logic FlushE, FlushM, FlushW, // flush signals + input logic IntDivE, // is inteteger division + input logic [2:0] FRM_REGW, // rounding mode from CSR + input logic [1:0] STATUS_FS, // is FPU enabled? + input logic FDivBusyE, // is the divider busy + // intruction + input logic [31:0] InstrD, // the full instruction + input logic [6:0] Funct7D, // bits 31:25 of instruction - may contain percision + input logic [6:0] OpD, // bits 6:0 of instruction + input logic [4:0] Rs2D, // bits 24:20 of instruction + input logic [2:0] Funct3D, Funct3E, // bits 14:12 of instruction - may contain rounding mode + // input mux selections + output logic XEnD, YEnD, ZEnD, // enable inputs + output logic XEnE, YEnE, ZEnE, // enable inputs + // opperation mux selections + output logic FCvtIntE, FCvtIntW, // convert to integer opperation + output logic [2:0] FrmM, // FP rounding mode + output logic [`FMTBITS-1:0] FmtE, FmtM, // FP format + output logic [2:0] OpCtrlE, OpCtrlM, // Select which opperation to do in each component + output logic FpLoadStoreM, // FP load or store instruction + output logic [1:0] PostProcSelE, PostProcSelM, // select result in the post processing unit + output logic [1:0] FResSelE, FResSelM, FResSelW, // Select one of the results that finish in the memory stage // register control signals - output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable - output logic FWriteIntE, FWriteIntM, // Write to integer register - output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input - output logic [4:0] Adr1E, Adr2E, Adr3E, // adresses of each input + output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable + output logic FWriteIntE, FWriteIntM, // Write to integer register + output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input + output logic [4:0] Adr1E, Adr2E, Adr3E, // adresses of each input // other control signals output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction - output logic FDivStartE, IDivStartE // Start division or squareroot + output logic FDivStartE, IDivStartE // Start division or squareroot ); `define FCTRLW 12 - logic [`FCTRLW-1:0] ControlsD; // control signals - logic FRegWriteD; // FP register write enable - logic FDivStartD; // start division/sqrt - logic FWriteIntD; // integer register write enable - logic [2:0] OpCtrlD; // Select which opperation to do in each component - logic [1:0] PostProcSelD; // select result in the post processing unit - logic [1:0] FResSelD; // Select one of the results that finish in the memory stage - logic [2:0] FrmD, FrmE; // FP rounding mode - logic [`FMTBITS-1:0] FmtD; // FP format - logic [1:0] Fmt; // format - before possible reduction - logic SupportedFmt; // is the format supported - logic FCvtIntD, FCvtIntM; // convert to integer opperation + logic [`FCTRLW-1:0] ControlsD; // control signals + logic FRegWriteD; // FP register write enable + logic FDivStartD; // start division/sqrt + logic FWriteIntD; // integer register write enable + logic [2:0] OpCtrlD; // Select which opperation to do in each component + logic [1:0] PostProcSelD; // select result in the post processing unit + logic [1:0] FResSelD; // Select one of the results that finish in the memory stage + logic [2:0] FrmD, FrmE; // FP rounding mode + logic [`FMTBITS-1:0] FmtD; // FP format + logic [1:0] Fmt; // format - before possible reduction + logic SupportedFmt; // is the format supported + logic FCvtIntD, FCvtIntM; // convert to integer opperation // FPU Instruction Decoder assign Fmt = Funct7D[1:0]; @@ -123,7 +123,7 @@ module fctrl ( 7'b00001??: ControlsD = `FCTRLW'b1_0_01_10_111_0_0_0; // fsub 7'b00010??: ControlsD = `FCTRLW'b1_0_01_10_100_0_0_0; // fmul 7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_xx0_1_0_0; // fdiv - 7'b01011??: ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0_0; // fsqrt + 7'b01011??: if (Rs2D == 5'b0000) ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0_0; // fsqrt 7'b00100??: case(Funct3D) 3'b000: ControlsD = `FCTRLW'b1_0_00_xx_000_0_0_0; // fsgnj 3'b001: ControlsD = `FCTRLW'b1_0_00_xx_001_0_0_0; // fsgnjn @@ -141,7 +141,8 @@ module fctrl ( 3'b000: ControlsD = `FCTRLW'b0_1_00_xx_011_0_0_0; // fle default: ControlsD = `FCTRLW'b0_0_00_xx_000__0_1_0; // non-implemented instruction endcase - 7'b11100??: if (Funct3D == 3'b001) ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass + 7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000) + ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass else if (Funct3D[1:0] == 2'b00) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.w to int reg else if (Funct3D[1:0] == 2'b01) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.d to int reg else ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction diff --git a/src/fpu/fcvt.sv b/src/fpu/fcvt.sv index 2f121a75a..32ca7542f 100644 --- a/src/fpu/fcvt.sv +++ b/src/fpu/fcvt.sv @@ -30,20 +30,20 @@ `include "wally-config.vh" module fcvt ( - input logic Xs, // input's sign - input logic [`NE-1:0] Xe, // input's exponent - input logic [`NF:0] Xm, // input's fraction - input logic [`XLEN-1:0] Int, // integer input - from IEU - input logic [2:0] OpCtrl, // choose which opperation (look below for values) - input logic ToInt, // is fp->int (since it's writting to the integer register) - input logic XZero, // is the input zero - input logic [`FMTBITS-1:0] Fmt, // the input's precision (11=quad 01=double 00=single 10=half) - output logic [`NE:0] Ce, // the calculated expoent - output logic [`LOGCVTLEN-1:0] ShiftAmt, // how much to shift by + input logic Xs, // input's sign + input logic [`NE-1:0] Xe, // input's exponent + input logic [`NF:0] Xm, // input's fraction + input logic [`XLEN-1:0] Int, // integer input - from IEU + input logic [2:0] OpCtrl, // choose which opperation (look below for values) + input logic ToInt, // is fp->int (since it's writting to the integer register) + input logic XZero, // is the input zero + input logic [`FMTBITS-1:0] Fmt, // the input's precision (11=quad 01=double 00=single 10=half) + output logic [`NE:0] Ce, // the calculated expoent + output logic [`LOGCVTLEN-1:0] ShiftAmt, // how much to shift by output logic ResSubnormUf,// does the result underflow or is subnormal - output logic Cs, // the result's sign - output logic IntZero, // is the integer zero? - output logic [`CVTLEN-1:0] LzcIn // input to the Leading Zero Counter (priority encoder) + output logic Cs, // the result's sign + output logic IntZero, // is the integer zero? + output logic [`CVTLEN-1:0] LzcIn // input to the Leading Zero Counter (priority encoder) ); // OpCtrls: @@ -60,7 +60,7 @@ module fcvt ( logic [`XLEN-1:0] PosInt; // the positive integer input logic [`XLEN-1:0] TrimInt; // integer trimmed to the correct size logic [`NE-2:0] NewBias; // the bias of the final result - logic [`NE-1:0] OldExp; // the old exponent + logic [`NE-1:0] OldExp; // the old exponent logic Signed; // is the opperation with a signed integer? logic Int64; // is the integer 64 bits? logic IntToFp; // is the opperation an int->fp conversion? diff --git a/src/fpu/fdivsqrt/fdivsqrt.sv b/src/fpu/fdivsqrt/fdivsqrt.sv index c69618f43..92f64cbdc 100644 --- a/src/fpu/fdivsqrt/fdivsqrt.sv +++ b/src/fpu/fdivsqrt/fdivsqrt.sv @@ -29,49 +29,49 @@ `include "wally-config.vh" module fdivsqrt( - input logic clk, - input logic reset, + input logic clk, + input logic reset, input logic [`FMTBITS-1:0] FmtE, - input logic XsE, - input logic [`NF:0] XmE, YmE, - input logic [`NE-1:0] XeE, YeE, - input logic XInfE, YInfE, - input logic XZeroE, YZeroE, - input logic XNaNE, YNaNE, - input logic FDivStartE, IDivStartE, - input logic StallM, - input logic FlushE, - input logic SqrtE, SqrtM, - input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // these are the src outputs before the mux choosing between them and PCE to put in srcA/B - input logic [2:0] Funct3E, Funct3M, - input logic IntDivE, W64E, - output logic DivStickyM, - output logic FDivBusyE, IFDivStartE, FDivDoneE, - output logic [`NE+1:0] QeM, - output logic [`DIVb:0] QmM, - output logic [`XLEN-1:0] FIntDivResultM + input logic XsE, + input logic [`NF:0] XmE, YmE, + input logic [`NE-1:0] XeE, YeE, + input logic XInfE, YInfE, + input logic XZeroE, YZeroE, + input logic XNaNE, YNaNE, + input logic FDivStartE, IDivStartE, + input logic StallM, + input logic FlushE, + input logic SqrtE, SqrtM, + input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // these are the src outputs before the mux choosing between them and PCE to put in srcA/B + input logic [2:0] Funct3E, Funct3M, + input logic IntDivE, W64E, + output logic DivStickyM, + output logic FDivBusyE, IFDivStartE, FDivDoneE, + output logic [`NE+1:0] QeM, + output logic [`DIVb:0] QmM, + output logic [`XLEN-1:0] FIntDivResultM ); // Floating-point division and square root module, with optional integer division and remainder // Computes X/Y, sqrt(X), A/B, or A%B - logic [`DIVb+3:0] WS, WC; // Partial remainder components - logic [`DIVb+3:0] X; // Iterator Initial Value (from dividend) - logic [`DIVb-1:0] DPreproc, D; // Iterator Divisor - logic [`DIVb:0] FirstU, FirstUM; // Intermediate result values - logic [`DIVb+1:0] FirstC; // Step tracker - logic Firstun; // Quotient selection - logic WZeroE; // Early termination flag - logic SpecialCaseM; // Divide by zero, square root of negative, etc. - logic DivStartE; // Enable signal for flops during stall - - // Integer div/rem signals - logic BZeroM; // Denominator is zero - logic IntDivM; // Integer operation - logic [`DIVBLEN:0] nE, nM, mM; // Shift amounts - logic NegQuotM, ALTBM, AsM, W64M; // Special handling for postprocessor - logic [`XLEN-1:0] AM; // Original Numerator for postprocessor - logic ISpecialCaseE; // Integer div/remainder special cases + logic [`DIVb+3:0] WS, WC; // Partial remainder components + logic [`DIVb+3:0] X; // Iterator Initial Value (from dividend) + logic [`DIVb-1:0] DPreproc, D; // Iterator Divisor + logic [`DIVb:0] FirstU, FirstUM; // Intermediate result values + logic [`DIVb+1:0] FirstC; // Step tracker + logic Firstun; // Quotient selection + logic WZeroE; // Early termination flag + logic SpecialCaseM; // Divide by zero, square root of negative, etc. + logic DivStartE; // Enable signal for flops during stall + + // Integer div/rem signals + logic BZeroM; // Denominator is zero + logic IntDivM; // Integer operation + logic [`DIVBLEN:0] nE, nM, mM; // Shift amounts + logic NegQuotM, ALTBM, AsM, W64M; // Special handling for postprocessor + logic [`XLEN-1:0] AM; // Original Numerator for postprocessor + logic ISpecialCaseE; // Integer div/remainder special cases fdivsqrtpreproc fdivsqrtpreproc( // Preprocessor .clk, .IFDivStartE, .Xm(XmE), .Ym(YmE), .Xe(XeE), .Ye(YeE), @@ -100,4 +100,4 @@ module fdivsqrt( // Int-specific .nM, .mM, .ALTBM, .AsM, .BZeroM, .NegQuotM, .W64M, .RemOpM(Funct3M[1]), .AM, .FIntDivResultM); -endmodule \ No newline at end of file +endmodule diff --git a/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv b/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv index b5b2ba335..482fed842 100644 --- a/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtexpcalc.sv @@ -69,6 +69,6 @@ module fdivsqrtexpcalc( assign SExp = {SXExp[`NE+1], SXExp[`NE+1:1]} + {2'b0, Bias}; // correct exponent for subnormal input's normalization shifts - assign DExp = ({2'b0, Xe} - {{(`NE+1-`DIVBLEN){1'b0}}, ell} - {2'b0, Ye} + {{(`NE+1-`DIVBLEN){1'b0}}, m} + {3'b0, Bias}) & {`NE+2{~XZero}}; // *** why Xzero? Is this a hack for postprocessor? + assign DExp = ({2'b0, Xe} - {{(`NE+1-`DIVBLEN){1'b0}}, ell} - {2'b0, Ye} + {{(`NE+1-`DIVBLEN){1'b0}}, m} + {3'b0, Bias}); assign Qe = Sqrt ? SExp : DExp; endmodule diff --git a/src/fpu/fdivsqrt/fdivsqrtpostproc.sv b/src/fpu/fdivsqrt/fdivsqrtpostproc.sv index b09e9f385..7b92f8c83 100644 --- a/src/fpu/fdivsqrt/fdivsqrtpostproc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtpostproc.sv @@ -37,7 +37,7 @@ module fdivsqrtpostproc( input logic [`DIVb+1:0] FirstC, input logic SqrtE, input logic Firstun, SqrtM, SpecialCaseM, NegQuotM, - input logic [`XLEN-1:0] AM, + input logic [`XLEN-1:0] AM, input logic RemOpM, ALTBM, BZeroM, AsM, W64M, input logic [`DIVBLEN:0] nM, mM, output logic [`DIVb:0] QmM, @@ -46,11 +46,11 @@ module fdivsqrtpostproc( output logic [`XLEN-1:0] FIntDivResultM ); - logic [`DIVb+3:0] W, Sum, DM; - logic [`DIVb:0] PreQmM; - logic NegStickyM; - logic weq0E, WZeroM; - logic [`XLEN-1:0] IntDivResultM; + logic [`DIVb+3:0] W, Sum, DM; + logic [`DIVb:0] PreQmM; + logic NegStickyM; + logic weq0E, WZeroM; + logic [`XLEN-1:0] IntDivResultM; ////////////////////////// // Execute Stage: Detect early termination for an exact result @@ -134,4 +134,4 @@ module fdivsqrtpostproc( end else assign FIntDivResultM = IntDivResultM[`XLEN-1:0]; end -endmodule \ No newline at end of file +endmodule diff --git a/src/fpu/fdivsqrt/fdivsqrtpreproc.sv b/src/fpu/fdivsqrt/fdivsqrtpreproc.sv index c5485c26f..9a69085fd 100644 --- a/src/fpu/fdivsqrt/fdivsqrtpreproc.sv +++ b/src/fpu/fdivsqrt/fdivsqrtpreproc.sv @@ -29,35 +29,35 @@ `include "wally-config.vh" module fdivsqrtpreproc ( - input logic clk, - input logic IFDivStartE, - input logic [`NF:0] Xm, Ym, - input logic [`NE-1:0] Xe, Ye, + input logic clk, + input logic IFDivStartE, + input logic [`NF:0] Xm, Ym, + input logic [`NE-1:0] Xe, Ye, input logic [`FMTBITS-1:0] Fmt, - input logic Sqrt, - input logic XZeroE, - input logic [2:0] Funct3E, - output logic [`NE+1:0] QeM, - output logic [`DIVb+3:0] X, - output logic [`DIVb-1:0] DPreproc, + input logic Sqrt, + input logic XZeroE, + input logic [2:0] Funct3E, + output logic [`NE+1:0] QeM, + output logic [`DIVb+3:0] X, + output logic [`DIVb-1:0] DPreproc, // Int-specific - input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B - input logic IntDivE, W64E, - output logic ISpecialCaseE, - output logic [`DIVBLEN:0] nE, nM, mM, - output logic NegQuotM, ALTBM, IntDivM, W64M, - output logic AsM, BZeroM, - output logic [`XLEN-1:0] AM + input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B + input logic IntDivE, W64E, + output logic ISpecialCaseE, + output logic [`DIVBLEN:0] nE, nM, mM, + output logic NegQuotM, ALTBM, IntDivM, W64M, + output logic AsM, BZeroM, + output logic [`XLEN-1:0] AM ); - logic [`DIVb-1:0] XPreproc; - logic [`DIVb:0] PreSqrtX; - logic [`DIVb+3:0] DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed - logic [`NE+1:0] QeE; // Quotient Exponent (FP only) - logic [`DIVb-1:0] IFNormLenX, IFNormLenD; // Correctly-sized inputs for iterator - logic [`DIVBLEN:0] mE, ell; // Leading zeros of inputs - logic NumerZeroE; // Numerator is zero (X or A) - logic AZeroE, BZeroE; // A or B is Zero for integer division + logic [`DIVb-1:0] XPreproc; + logic [`DIVb:0] PreSqrtX; + logic [`DIVb+3:0] DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed + logic [`NE+1:0] QeE; // Quotient Exponent (FP only) + logic [`DIVb-1:0] IFNormLenX, IFNormLenD; // Correctly-sized inputs for iterator + logic [`DIVBLEN:0] mE, ell; // Leading zeros of inputs + logic NumerZeroE; // Numerator is zero (X or A) + logic AZeroE, BZeroE; // A or B is Zero for integer division if (`IDIV_ON_FPU) begin:intpreproc // Int Supported logic signedDiv, NegQuotE; diff --git a/src/fpu/fdivsqrt/fdivsqrtqsel2.sv b/src/fpu/fdivsqrt/fdivsqrtqsel2.sv index f18b31f1b..fd0a2a469 100644 --- a/src/fpu/fdivsqrt/fdivsqrtqsel2.sv +++ b/src/fpu/fdivsqrt/fdivsqrtqsel2.sv @@ -45,11 +45,11 @@ module fdivsqrtqsel2 ( assign g = ps & pc; assign magnitude = ~((ps[2]^pc[2]) & (ps[1]^pc[1]) & - (ps[0]^pc[0])); + (ps[0]^pc[0])); assign sign = (ps[3]^pc[3])^ (ps[2] & pc[2] | ((ps[2]^pc[2]) & - (ps[1]&pc[1] | ((ps[1]^pc[1]) & - (ps[0]&pc[0]))))); + (ps[1]&pc[1] | ((ps[1]^pc[1]) & + (ps[0]&pc[0]))))); // Produce digit = +1, 0, or -1 assign up = magnitude & ~sign; diff --git a/src/fpu/fdivsqrt/fdivsqrtqsel4.sv b/src/fpu/fdivsqrt/fdivsqrtqsel4.sv index 3a8a110f0..7a0db24d8 100644 --- a/src/fpu/fdivsqrt/fdivsqrtqsel4.sv +++ b/src/fpu/fdivsqrt/fdivsqrtqsel4.sv @@ -32,21 +32,21 @@ module fdivsqrtqsel4 ( input logic [2:0] Dmsbs, input logic [4:0] Smsbs, input logic [7:0] WSmsbs, WCmsbs, - input logic Sqrt, j1, + input logic Sqrt, j1, output logic [3:0] udigit ); - logic [6:0] Wmsbs; - logic [7:0] PreWmsbs; - logic [2:0] A; + logic [6:0] Wmsbs; + logic [7:0] PreWmsbs; + logic [2:0] A; - assign PreWmsbs = WCmsbs + WSmsbs; - assign Wmsbs = PreWmsbs[7:1]; - // D = 0001.xxx... - // Dmsbs = | | + assign PreWmsbs = WCmsbs + WSmsbs; + assign Wmsbs = PreWmsbs[7:1]; + // D = 0001.xxx... + // Dmsbs = | | // W = xxxx.xxx... - // Wmsbs = | | + // Wmsbs = | | - logic [3:0] USel4[1023:0]; + logic [3:0] USel4[1023:0]; // Prepopulate selection table; this is constant at compile time always_comb begin @@ -109,5 +109,5 @@ module fdivsqrtqsel4 ( end else A = Dmsbs; // Select quotient digit from lookup table based on A and W - assign udigit = USel4[{A,Wmsbs}]; + assign udigit = USel4[{A,Wmsbs}]; endmodule diff --git a/src/fpu/fdivsqrt/fdivsqrtqsel4cmp.sv b/src/fpu/fdivsqrt/fdivsqrtqsel4cmp.sv index 882458106..e508a6d7c 100644 --- a/src/fpu/fdivsqrt/fdivsqrtqsel4cmp.sv +++ b/src/fpu/fdivsqrt/fdivsqrtqsel4cmp.sv @@ -32,19 +32,19 @@ module fdivsqrtqsel4cmp ( input logic [2:0] Dmsbs, input logic [4:0] Smsbs, input logic [7:0] WSmsbs, WCmsbs, - input logic SqrtE, j1, + input logic SqrtE, j1, output logic [3:0] udigit ); - logic [6:0] Wmsbs; - logic [7:0] PreWmsbs; - logic [2:0] A; + logic [6:0] Wmsbs; + logic [7:0] PreWmsbs; + logic [2:0] A; - assign PreWmsbs = WCmsbs + WSmsbs; - assign Wmsbs = PreWmsbs[7:1]; - // D = 0001.xxx... - // Dmsbs = | | + assign PreWmsbs = WCmsbs + WSmsbs; + assign Wmsbs = PreWmsbs[7:1]; + // D = 0001.xxx... + // Dmsbs = | | // W = xxxx.xxx... - // Wmsbs = | | + // Wmsbs = | | logic [6:0] mk2, mk1, mk0, mkm1; logic [6:0] mks2[7:0], mks1[7:0]; @@ -87,5 +87,5 @@ module fdivsqrtqsel4cmp ( else if ($signed(Wmsbs) >= $signed(mk1)) udigit = 4'b0100; // choose 1 else if ($signed(Wmsbs) >= $signed(mk0)) udigit = 4'b0000; // choose 0 else if ($signed(Wmsbs) >= $signed(mkm1)) udigit = 4'b0010; // choose -1 - else udigit = 4'b0001; // choose -2 + else udigit = 4'b0001; // choose -2 endmodule diff --git a/src/fpu/fdivsqrt/fdivsqrtstage2.sv b/src/fpu/fdivsqrt/fdivsqrtstage2.sv index 63ab6c059..53c1711cb 100644 --- a/src/fpu/fdivsqrt/fdivsqrtstage2.sv +++ b/src/fpu/fdivsqrt/fdivsqrtstage2.sv @@ -31,32 +31,32 @@ /* verilator lint_off UNOPTFLAT */ module fdivsqrtstage2 ( input logic [`DIVb-1:0] D, - input logic [`DIVb+3:0] DBar, - input logic [`DIVb:0] U, UM, - input logic [`DIVb+3:0] WS, WC, + input logic [`DIVb+3:0] DBar, + input logic [`DIVb:0] U, UM, + input logic [`DIVb+3:0] WS, WC, input logic [`DIVb+1:0] C, - input logic SqrtE, - output logic un, + input logic SqrtE, + output logic un, output logic [`DIVb+1:0] CNext, - output logic [`DIVb:0] UNext, UMNext, - output logic [`DIVb+3:0] WSNext, WCNext + output logic [`DIVb:0] UNext, UMNext, + output logic [`DIVb+3:0] WSNext, WCNext ); /* verilator lint_on UNOPTFLAT */ - logic [`DIVb+3:0] Dsel; - logic up, uz; - logic [`DIVb+3:0] F; - logic [`DIVb+3:0] AddIn; - logic [`DIVb+3:0] WSA, WCA; + logic [`DIVb+3:0] Dsel; + logic up, uz; + logic [`DIVb+3:0] F; + logic [`DIVb+3:0] AddIn; + logic [`DIVb+3:0] WSA, WCA; // Qmient Selection logic // Given partial remainder, select digit of +1, 0, or -1 (up, uz, un) // q encoding: - // 1000 = +2 - // 0100 = +1 - // 0000 = 0 - // 0010 = -1 - // 0001 = -2 + // 1000 = +2 + // 0100 = +1 + // 0000 = 0 + // 0010 = -1 + // 0001 = -2 fdivsqrtqsel2 qsel2(WS[`DIVb+3:`DIVb], WC[`DIVb+3:`DIVb], up, uz, un); // Sqrt F generation. Extend C, U, UM to Q4.k diff --git a/src/fpu/fdivsqrt/fdivsqrtstage4.sv b/src/fpu/fdivsqrt/fdivsqrtstage4.sv index 007dd18bb..ee92d263b 100644 --- a/src/fpu/fdivsqrt/fdivsqrtstage4.sv +++ b/src/fpu/fdivsqrt/fdivsqrtstage4.sv @@ -30,34 +30,34 @@ module fdivsqrtstage4 ( input logic [`DIVb-1:0] D, - input logic [`DIVb+3:0] DBar, D2, DBar2, - input logic [`DIVb:0] U, UM, - input logic [`DIVb+3:0] WS, WC, + input logic [`DIVb+3:0] DBar, D2, DBar2, + input logic [`DIVb:0] U,UM, + input logic [`DIVb+3:0] WS, WC, input logic [`DIVb+1:0] C, - input logic SqrtE, j1, + input logic SqrtE, j1, output logic [`DIVb+1:0] CNext, - output logic un, - output logic [`DIVb:0] UNext, UMNext, - output logic [`DIVb+3:0] WSNext, WCNext + output logic un, + output logic [`DIVb:0] UNext, UMNext, + output logic [`DIVb+3:0] WSNext, WCNext ); - logic [`DIVb+3:0] Dsel; - logic [3:0] udigit; - logic [`DIVb+3:0] F; - logic [`DIVb+3:0] AddIn; - logic [4:0] Smsbs; - logic [2:0] Dmsbs; - logic [7:0] WCmsbs, WSmsbs; - logic CarryIn; - logic [`DIVb+3:0] WSA, WCA; + logic [`DIVb+3:0] Dsel; + logic [3:0] udigit; + logic [`DIVb+3:0] F; + logic [`DIVb+3:0] AddIn; + logic [4:0] Smsbs; + logic [2:0] Dmsbs; + logic [7:0] WCmsbs, WSmsbs; + logic CarryIn; + logic [`DIVb+3:0] WSA, WCA; // Digit Selection logic // u encoding: - // 1000 = +2 - // 0100 = +1 - // 0000 = 0 - // 0010 = -1 - // 0001 = -2 + // 1000 = +2 + // 0100 = +1 + // 0000 = 0 + // 0010 = -1 + // 0001 = -2 assign Smsbs = U[`DIVb:`DIVb-4]; assign Dmsbs = D[`DIVb-1:`DIVb-3]; assign WCmsbs = WC[`DIVb+3:`DIVb-4]; diff --git a/src/fpu/fma/fmalza.sv b/src/fpu/fma/fmalza.sv index 640e4ed80..59fb3fc3e 100644 --- a/src/fpu/fma/fmalza.sv +++ b/src/fpu/fma/fmalza.sv @@ -32,12 +32,12 @@ module fmalza #(WIDTH) ( input logic [WIDTH-1:0] A, // addend input logic [2*`NF+1:0] Pm, // product - input logic Cin, // carry in + input logic Cin, // carry in input logic sub, // subtraction output logic [$clog2(WIDTH+1)-1:0] SCnt // normalization shift count for the positive result ); - logic [WIDTH:0] F; // most significant bit of F indicates leading digit + logic [WIDTH:0] F; // most significant bit of F indicates leading digit logic [WIDTH-1:0] B; // zero-extended product with same size as aligned A logic [WIDTH-1:0] P, G, K; // propagate, generate, kill for each column logic [WIDTH-1:0] Pp1, Gm1, Km1; // propagate shifted right by 1, generate/kill shifted left 1 diff --git a/src/fpu/fpu.sv b/src/fpu/fpu.sv index 8ff36fbfc..32bdfc1ca 100755 --- a/src/fpu/fpu.sv +++ b/src/fpu/fpu.sv @@ -29,40 +29,40 @@ `include "wally-config.vh" module fpu ( - input logic clk, - input logic reset, + input logic clk, + input logic reset, // Hazards - input logic StallE, StallM, StallW, // stall signals (from HZU) - input logic FlushE, FlushM, FlushW, // flush signals (from HZU) - output logic FPUStallD, // Stall the decode stage (To HZU) - output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU) - // CSRs - input logic [1:0] STATUS_FS, // Is floating-point enabled? (From privileged unit) - input logic [2:0] FRM_REGW, // Rounding mode (from CSR) - // Decode stage - input logic [31:0] InstrD, // instruction (from IFU) - // Execute stage - input logic [2:0] Funct3E, // Funct fields of instruction specify type of operations - input logic IntDivE, W64E, // Integer division on FPU - input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Integer input for convert, move, and int div (from IEU) - input logic [4:0] RdE, // which FP register to write to (from IEU) - output logic FWriteIntE, // integer register write enable (to IEU) - output logic FCvtIntE, // Convert to int (to IEU) - // Memory stage - input logic [2:0] Funct3M, // Funct fields of instruction specify type of operations - input logic [4:0] RdM, // which FP register to write to (from IEU) - output logic FRegWriteM, // FP register write enable (to privileged unit) - output logic FpLoadStoreM, // Fp load instruction? (to LSU) - output logic [`FLEN-1:0] FWriteDataM, // Data to be written to memory (to LSU) - output logic [`XLEN-1:0] FIntResM, // data to be written to integer register (to IEU) - output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction (to IFU) - output logic [4:0] SetFflagsM, // FPU flags (to privileged unit) - // Writeback stage - input logic [4:0] RdW, // which FP register to write to (from IEU) - input logic [`FLEN-1:0] ReadDataW, // Read data (from LSU) - output logic [`XLEN-1:0] FCvtIntResW, // convert result to to be written to integer register (to IEU) - output logic FCvtIntW, // select FCvtIntRes (to IEU) - output logic [`XLEN-1:0] FIntDivResultW // Result from integer division (to IEU) + input logic StallE, StallM, StallW, // stall signals (from HZU) + input logic FlushE, FlushM, FlushW, // flush signals (from HZU) + output logic FPUStallD, // Stall the decode stage (To HZU) + output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU) + // CSRs + input logic [1:0] STATUS_FS, // Is floating-point enabled? (From privileged unit) + input logic [2:0] FRM_REGW, // Rounding mode (from CSR) + // Decode stage + input logic [31:0] InstrD, // instruction (from IFU) + // Execute stage + input logic [2:0] Funct3E, // Funct fields of instruction specify type of operations + input logic IntDivE, W64E, // Integer division on FPU + input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Integer input for convert, move, and int div (from IEU) + input logic [4:0] RdE, // which FP register to write to (from IEU) + output logic FWriteIntE, // integer register write enable (to IEU) + output logic FCvtIntE, // Convert to int (to IEU) + // Memory stage + input logic [2:0] Funct3M, // Funct fields of instruction specify type of operations + input logic [4:0] RdM, // which FP register to write to (from IEU) + output logic FRegWriteM, // FP register write enable (to privileged unit) + output logic FpLoadStoreM, // Fp load instruction? (to LSU) + output logic [`FLEN-1:0] FWriteDataM, // Data to be written to memory (to LSU) + output logic [`XLEN-1:0] FIntResM, // data to be written to integer register (to IEU) + output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction (to IFU) + output logic [4:0] SetFflagsM, // FPU flags (to privileged unit) + // Writeback stage + input logic [4:0] RdW, // which FP register to write to (from IEU) + input logic [`FLEN-1:0] ReadDataW, // Read data (from LSU) + output logic [`XLEN-1:0] FCvtIntResW, // convert result to to be written to integer register (to IEU) + output logic FCvtIntW, // select FCvtIntRes (to IEU) + output logic [`XLEN-1:0] FIntDivResultW // Result from integer division (to IEU) ); // RISC-V FPU specifics: @@ -70,97 +70,97 @@ module fpu ( // - RISC-V detects underflow after rounding // control signals - logic FRegWriteW; // FP register write enable - logic [2:0] FrmM; // FP rounding mode - logic [`FMTBITS-1:0] FmtE, FmtM; // FP precision 0-single 1-double - logic FDivStartE, IDivStartE; // Start division or squareroot - logic FWriteIntM; // Write to integer register - logic [1:0] ForwardXE, ForwardYE, ForwardZE; // forwarding mux control signals - logic [2:0] OpCtrlE, OpCtrlM; // Select which opperation to do in each component - logic [1:0] FResSelE, FResSelM, FResSelW; // Select one of the results that finish in the memory stage - logic [1:0] PostProcSelE, PostProcSelM; // select result in the post processing unit - logic [4:0] Adr1D, Adr2D, Adr3D; // register adresses of each input - logic [4:0] Adr1E, Adr2E, Adr3E; // register adresses of each input - logic XEnD, YEnD, ZEnD; // X, Y, Z inputs used for current operation - logic XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation - logic FRegWriteE; // Write floating-point register + logic FRegWriteW; // FP register write enable + logic [2:0] FrmM; // FP rounding mode + logic [`FMTBITS-1:0] FmtE, FmtM; // FP precision 0-single 1-double + logic FDivStartE, IDivStartE; // Start division or squareroot + logic FWriteIntM; // Write to integer register + logic [1:0] ForwardXE, ForwardYE, ForwardZE; // forwarding mux control signals + logic [2:0] OpCtrlE, OpCtrlM; // Select which opperation to do in each component + logic [1:0] FResSelE, FResSelM, FResSelW; // Select one of the results that finish in the memory stage + logic [1:0] PostProcSelE, PostProcSelM; // select result in the post processing unit + logic [4:0] Adr1D, Adr2D, Adr3D; // register adresses of each input + logic [4:0] Adr1E, Adr2E, Adr3E; // register adresses of each input + logic XEnD, YEnD, ZEnD; // X, Y, Z inputs used for current operation + logic XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation + logic FRegWriteE; // Write floating-point register // regfile signals - logic [`FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage - logic [`FLEN-1:0] FRD1E, FRD2E, FRD3E; // Read Data from FP register - execute stage - logic [`FLEN-1:0] XE; // Input 1 to the various units (after forwarding) - logic [`XLEN-1:0] IntSrcXE; // Input 1 to the various units (after forwarding) - logic [`FLEN-1:0] PreYE, YE; // Input 2 to the various units (after forwarding) - logic [`FLEN-1:0] PreZE, ZE; // Input 3 to the various units (after forwarding) + logic [`FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage + logic [`FLEN-1:0] FRD1E, FRD2E, FRD3E; // Read Data from FP register - execute stage + logic [`FLEN-1:0] XE; // Input 1 to the various units (after forwarding) + logic [`XLEN-1:0] IntSrcXE; // Input 1 to the various units (after forwarding) + logic [`FLEN-1:0] PreYE, YE; // Input 2 to the various units (after forwarding) + logic [`FLEN-1:0] PreZE, ZE; // Input 3 to the various units (after forwarding) // unpacking signals - logic XsE, YsE, ZsE; // input's sign - execute stage - logic XsM, YsM; // input's sign - memory stage - logic [`NE-1:0] XeE, YeE, ZeE; // input's exponent - execute stage - logic [`NE-1:0] ZeM; // input's exponent - memory stage - logic [`NF:0] XmE, YmE, ZmE; // input's significand - execute stage - logic [`NF:0] XmM, YmM, ZmM; // input's significand - memory stage - logic XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute stage - logic XNaNM, YNaNM, ZNaNM; // is the input a NaN - memory stage - logic XSNaNE, YSNaNE, ZSNaNE; // is the input a signaling NaN - execute stage - logic XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage - logic XSubnormE; // is the input subnormal - logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage - logic XZeroM, YZeroM; // is the input zero - memory stage - logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage - logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage - logic XExpMaxE; // is the exponent all ones (max value) - logic [`FLEN-1:0] XPostBoxE; // X after fixing bad NaN box. Needed for 1-input operations + logic XsE, YsE, ZsE; // input's sign - execute stage + logic XsM, YsM; // input's sign - memory stage + logic [`NE-1:0] XeE, YeE, ZeE; // input's exponent - execute stage + logic [`NE-1:0] ZeM; // input's exponent - memory stage + logic [`NF:0] XmE, YmE, ZmE; // input's significand - execute stage + logic [`NF:0] XmM, YmM, ZmM; // input's significand - memory stage + logic XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute stage + logic XNaNM, YNaNM, ZNaNM; // is the input a NaN - memory stage + logic XSNaNE, YSNaNE, ZSNaNE; // is the input a signaling NaN - execute stage + logic XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage + logic XSubnormE; // is the input subnormal + logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage + logic XZeroM, YZeroM; // is the input zero - memory stage + logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage + logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage + logic XExpMaxE; // is the exponent all ones (max value) + logic [`FLEN-1:0] XPostBoxE; // X after fixing bad NaN box. Needed for 1-input operations // Fma Signals - logic FmaAddSubE; // Multiply by 1.0 when adding or subtracting - logic [1:0] FmaZSelE; // Select Z = Y when adding or subtracting, 0 when multiplying - logic [3*`NF+3:0] SmE, SmM; // Sum significand - logic FmaAStickyE, FmaAStickyM; // FMA addend sticky bit output - logic [`NE+1:0] SeE,SeM; // Sum exponent - logic InvAE, InvAM; // Invert addend - logic AsE, AsM; // Addend sign - logic PsE, PsM; // Product sign - logic SsE, SsM; // Sum sign - logic [$clog2(3*`NF+5)-1:0] SCntE, SCntM; // LZA sum leading zero count + logic FmaAddSubE; // Multiply by 1.0 when adding or subtracting + logic [1:0] FmaZSelE; // Select Z = Y when adding or subtracting, 0 when multiplying + logic [3*`NF+3:0] SmE, SmM; // Sum significand + logic FmaAStickyE, FmaAStickyM; // FMA addend sticky bit output + logic [`NE+1:0] SeE,SeM; // Sum exponent + logic InvAE, InvAM; // Invert addend + logic AsE, AsM; // Addend sign + logic PsE, PsM; // Product sign + logic SsE, SsM; // Sum sign + logic [$clog2(3*`NF+5)-1:0] SCntE, SCntM; // LZA sum leading zero count // Cvt Signals - logic [`NE:0] CeE, CeM; // convert intermediate expoent - logic [`LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by - logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is subnormal - logic CsE, CsM; // convert result sign - logic IntZeroE, IntZeroM; // is the integer zero? - logic [`CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder) - logic [`XLEN-1:0] FCvtIntResM; // fcvt integer result (for IEU) + logic [`NE:0] CeE, CeM; // convert intermediate expoent + logic [`LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by + logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is subnormal + logic CsE, CsM; // convert result sign + logic IntZeroE, IntZeroM; // is the integer zero? + logic [`CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder) + logic [`XLEN-1:0] FCvtIntResM; // fcvt integer result (for IEU) // divide signals - logic [`DIVb:0] QmM; // fdivsqrt signifcand - logic [`NE+1:0] QeM; // fdivsqrt exponent - logic DivStickyM; // fdivsqrt sticky bit - logic FDivDoneE, IFDivStartE; // fdivsqrt control signals - logic [`XLEN-1:0] FIntDivResultM; // fdivsqrt integer division result (for IEU) + logic [`DIVb:0] QmM; // fdivsqrt signifcand + logic [`NE+1:0] QeM; // fdivsqrt exponent + logic DivStickyM; // fdivsqrt sticky bit + logic FDivDoneE, IFDivStartE; // fdivsqrt control signals + logic [`XLEN-1:0] FIntDivResultM; // fdivsqrt integer division result (for IEU) // result and flag signals - logic [`XLEN-1:0] ClassResE; // classify result - logic [`FLEN-1:0] CmpFpResE; // compare result to FPU (min/max) - logic [`XLEN-1:0] CmpIntResE; // compare result to IEU (eq/lt/le) - logic CmpNVE; // compare invalid flag (Not Valid) - logic [`FLEN-1:0] SgnResE; // sign injection result - logic [`XLEN-1:0] FIntResE; // FPU to IEU E-stage result (classify, compare, move) - logic [`FLEN-1:0] PostProcResM; // Postprocessor output - logic [4:0] PostProcFlgM; // Postprocessor flags - logic PreNVE, PreNVM; // selected flag that is ready in the memory stage - logic [`FLEN-1:0] FpResM, FpResW; // FPU preliminary result - logic [`FLEN-1:0] PreFpResE, PreFpResM; // selected result that is ready in the memory stage - logic [`FLEN-1:0] FResultW; // final FP result being written to the FP register + logic [`XLEN-1:0] ClassResE; // classify result + logic [`FLEN-1:0] CmpFpResE; // compare result to FPU (min/max) + logic [`XLEN-1:0] CmpIntResE; // compare result to IEU (eq/lt/le) + logic CmpNVE; // compare invalid flag (Not Valid) + logic [`FLEN-1:0] SgnResE; // sign injection result + logic [`XLEN-1:0] FIntResE; // FPU to IEU E-stage result (classify, compare, move) + logic [`FLEN-1:0] PostProcResM; // Postprocessor output + logic [4:0] PostProcFlgM; // Postprocessor flags + logic PreNVE, PreNVM; // selected flag that is ready in the memory stage + logic [`FLEN-1:0] FpResM, FpResW; // FPU preliminary result + logic [`FLEN-1:0] PreFpResE, PreFpResM; // selected result that is ready in the memory stage + logic [`FLEN-1:0] FResultW; // final FP result being written to the FP register // other signals - logic [`FLEN-1:0] AlignedSrcAE; // align SrcA from IEU to the floating point format for fmv - logic [`FLEN-1:0] BoxedZeroE; // Zero value for Z for multiplication, with NaN boxing if needed - logic [`FLEN-1:0] BoxedOneE; // One value for Z for multiplication, with NaN boxing if needed - logic StallUnpackedM; // Stall unpacker outputs during multicycle fdivsqrt - logic [`FLEN-1:0] SgnExtXE; // Sign-extended X input for move to integer - logic mvsgn; // sign bit for extending move + logic [`FLEN-1:0] AlignedSrcAE; // align SrcA from IEU to the floating point format for fmv + logic [`FLEN-1:0] BoxedZeroE; // Zero value for Z for multiplication, with NaN boxing if needed + logic [`FLEN-1:0] BoxedOneE; // One value for Z for multiplication, with NaN boxing if needed + logic StallUnpackedM; // Stall unpacker outputs during multicycle fdivsqrt + logic [`FLEN-1:0] SgnExtXE; // Sign-extended X input for move to integer + logic mvsgn; // sign bit for extending move ////////////////////////////////////////////////////////////////////////////////////////// // Decode Stage: fctrl decoder, read register file @@ -180,7 +180,7 @@ module fpu ( fregfile fregfile (.clk, .reset, .we4(FRegWriteW), .a1(InstrD[19:15]), .a2(InstrD[24:20]), .a3(InstrD[31:27]), .a4(RdW), .wd4(FResultW), - .rd1(FRD1D), .rd2(FRD2D), .rd3(FRD3D)); + .rd1(FRD1D), .rd2(FRD2D), .rd3(FRD3D)); // D/E pipeline registers flopenrc #(`FLEN) DEReg1(clk, reset, FlushE, ~StallE, FRD1D, FRD1E); diff --git a/src/fpu/fregfile.sv b/src/fpu/fregfile.sv index 1a5a2eecf..69961a847 100644 --- a/src/fpu/fregfile.sv +++ b/src/fpu/fregfile.sv @@ -29,8 +29,8 @@ `include "wally-config.vh" module fregfile ( - input logic clk, reset, - input logic we4, // write enable + input logic clk, reset, + input logic we4, // write enable input logic [4:0] a1, a2, a3, a4, // adresses input logic [`FLEN-1:0] wd4, // write data output logic [`FLEN-1:0] rd1, rd2, rd3 // read data @@ -46,7 +46,7 @@ module fregfile ( always_ff @(negedge clk) // or posedge reset) if (reset) for(i=0; i<32; i++) rf[i] <= 0; - else if (we4) rf[a4] <= wd4; + else if (we4) rf[a4] <= wd4; assign #2 rd1 = rf[a1]; assign #2 rd2 = rf[a2]; diff --git a/src/fpu/fsgninj.sv b/src/fpu/fsgninj.sv index 0db7dc2f3..9ce938709 100755 --- a/src/fpu/fsgninj.sv +++ b/src/fpu/fsgninj.sv @@ -29,43 +29,43 @@ `include "wally-config.vh" module fsgninj ( - input logic Xs, Ys, // X and Y sign bits - input logic [`FLEN-1:0] X, // X - input logic [`FMTBITS-1:0] Fmt, // format - input logic [1:0] OpCtrl, // operation control - output logic [`FLEN-1:0] SgnRes // result + input logic Xs, Ys, // X and Y sign bits + input logic [`FLEN-1:0] X, // X + input logic [`FMTBITS-1:0] Fmt, // format + input logic [1:0] OpCtrl, // operation control + output logic [`FLEN-1:0] SgnRes // result ); - logic ResSgn; // result sign + logic ResSgn; // result sign - // OpCtrl: - // 00 - fsgnj - directly copy over sign value of Y - // 01 - fsgnjn - negate sign value of Y - // 10 - fsgnjx - XOR sign values of X and Y - - // calculate the result's sign - assign ResSgn = (OpCtrl[1] ? Xs : OpCtrl[0]) ^ Ys; - - // format final result based on precision - // - uses NaN-blocking format - // - if there are any unsused bits the most significant bits are filled with 1s - + // OpCtrl: + // 00 - fsgnj - directly copy over sign value of Y + // 01 - fsgnjn - negate sign value of Y + // 10 - fsgnjx - XOR sign values of X and Y + + // calculate the result's sign + assign ResSgn = (OpCtrl[1] ? Xs : OpCtrl[0]) ^ Ys; + + // format final result based on precision + // - uses NaN-blocking format + // - if there are any unsused bits the most significant bits are filled with 1s + if (`FPSIZES == 1) - assign SgnRes = {ResSgn, X[`FLEN-2:0]}; + assign SgnRes = {ResSgn, X[`FLEN-2:0]}; else if (`FPSIZES == 2) - assign SgnRes = {~Fmt|ResSgn, X[`FLEN-2:`LEN1], Fmt ? X[`LEN1-1] : ResSgn, X[`LEN1-2:0]}; + assign SgnRes = {~Fmt|ResSgn, X[`FLEN-2:`LEN1], Fmt ? X[`LEN1-1] : ResSgn, X[`LEN1-2:0]}; else if (`FPSIZES == 3) begin - logic [2:0] SgnBits; + logic [2:0] SgnBits; always_comb case (Fmt) `FMT: SgnBits = {ResSgn, X[`LEN1-1], X[`LEN2-1]}; - `FMT1: SgnBits = {1'b1, ResSgn, X[`LEN2-1]}; + `FMT1: SgnBits = {1'b1, ResSgn, X[`LEN2-1]}; `FMT2: SgnBits = {2'b11, ResSgn}; default: SgnBits = {3{1'bx}}; endcase - assign SgnRes = {SgnBits[2], X[`FLEN-2:`LEN1], SgnBits[1], X[`LEN1-2:`LEN2], SgnBits[0], X[`LEN2-2:0]}; - end else if (`FPSIZES == 4) begin - logic [3:0] SgnBits; + assign SgnRes = {SgnBits[2], X[`FLEN-2:`LEN1], SgnBits[1], X[`LEN1-2:`LEN2], SgnBits[0], X[`LEN2-2:0]}; + end else if (`FPSIZES == 4) begin + logic [3:0] SgnBits; always_comb case (Fmt) `Q_FMT: SgnBits = {ResSgn, X[`D_LEN-1], X[`S_LEN-1], X[`H_LEN-1]}; @@ -73,7 +73,7 @@ module fsgninj ( `S_FMT: SgnBits = {2'b11, ResSgn, X[`H_LEN-1]}; `H_FMT: SgnBits = {3'b111, ResSgn}; endcase - assign SgnRes = {SgnBits[3], X[`Q_LEN-2:`D_LEN], SgnBits[2], X[`D_LEN-2:`S_LEN], SgnBits[1], X[`S_LEN-2:`H_LEN], SgnBits[0], X[`H_LEN-2:0]}; - end + assign SgnRes = {SgnBits[3], X[`Q_LEN-2:`D_LEN], SgnBits[2], X[`D_LEN-2:`S_LEN], SgnBits[1], X[`S_LEN-2:`H_LEN], SgnBits[0], X[`H_LEN-2:0]}; + end endmodule diff --git a/src/generic/arrs.sv b/src/generic/arrs.sv index 0bb30c96a..5a9cf21f0 100644 --- a/src/generic/arrs.sv +++ b/src/generic/arrs.sv @@ -30,13 +30,13 @@ `include "wally-config.vh" module arrs( - input logic clk, - input logic areset, + input logic clk, + input logic areset, output logic reset ); - logic metaStable; - logic resetB; + logic metaStable; + logic resetB; always_ff @(posedge clk , posedge areset) begin if (areset) begin diff --git a/src/generic/clockgater.sv b/src/generic/clockgater.sv index 55f02cff5..c09f98f2c 100644 --- a/src/generic/clockgater.sv +++ b/src/generic/clockgater.sv @@ -27,9 +27,9 @@ `include "wally-config.vh" module clockgater ( - input logic E, - input logic SE, - input logic CLK, + input logic E, + input logic SE, + input logic CLK, output logic ECLK ); @@ -39,10 +39,10 @@ module clockgater ( // VERY IMPORTANT. // This part functionally models a clock gater, but does not necessarily meet the timing constrains a real standard cell would. // Do not use this in synthesis! - logic enable_q; + logic enable_q; always_latch begin if(~CLK) begin - enable_q <= E | SE; + enable_q <= E | SE; end end assign ECLK = enable_q & CLK; diff --git a/src/generic/lzc.sv b/src/generic/lzc.sv index ecfd6796a..9b7c841b2 100644 --- a/src/generic/lzc.sv +++ b/src/generic/lzc.sv @@ -32,7 +32,7 @@ module lzc #(parameter WIDTH = 1) ( always_comb begin i = 0; - while (~num[WIDTH-1-i] & (i < WIDTH)) i = i+1; // search for leading one + while ((i < WIDTH) & ~num[WIDTH-1-i]) i = i+1; // search for leading one ZeroCnt = i[$clog2(WIDTH+1)-1:0]; end endmodule diff --git a/src/generic/mem/ram1p1rwbe.sv b/src/generic/mem/ram1p1rwbe.sv index f3c98873e..8905cc551 100644 --- a/src/generic/mem/ram1p1rwbe.sv +++ b/src/generic/mem/ram1p1rwbe.sv @@ -49,39 +49,39 @@ module ram1p1rwbe #(parameter DEPTH=64, WIDTH=44) ( // *************************************************************************** // TRUE SRAM macro // *************************************************************************** - if ((`USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray + if ((`USE_SRAM == 1) & (WIDTH == 128) & (DEPTH == 64)) begin // Cache data subarray genvar index; - // 64 x 128-bit SRAM - logic [WIDTH-1:0] BitWriteMask; - for (index=0; index < WIDTH; index++) - assign BitWriteMask[index] = bwe[index/8]; + // 64 x 128-bit SRAM + logic [WIDTH-1:0] BitWriteMask; + for (index=0; index < WIDTH; index++) + assign BitWriteMask[index] = bwe[index/8]; ram1p1rwbe_64x128 sram1A (.CLK(clk), .CEB(~ce), .WEB(~we), - .A(addr), .D(din), - .BWEB(~BitWriteMask), .Q(dout)); + .A(addr), .D(din), + .BWEB(~BitWriteMask), .Q(dout)); end else if ((`USE_SRAM == 1) & (WIDTH == 44) & (DEPTH == 64)) begin // RV64 cache tag - genvar index; - // 64 x 44-bit SRAM - logic [WIDTH-1:0] BitWriteMask; - for (index=0; index < WIDTH; index++) - assign BitWriteMask[index] = bwe[index/8]; - ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we), - .A(addr), .D(din), - .BWEB(~BitWriteMask), .Q(dout)); + genvar index; + // 64 x 44-bit SRAM + logic [WIDTH-1:0] BitWriteMask; + for (index=0; index < WIDTH; index++) + assign BitWriteMask[index] = bwe[index/8]; + ram1p1rwbe_64x44 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we), + .A(addr), .D(din), + .BWEB(~BitWriteMask), .Q(dout)); end else if ((`USE_SRAM == 1) & (WIDTH == 22) & (DEPTH == 64)) begin // RV32 cache tag - genvar index; - // 64 x 22-bit SRAM - logic [WIDTH-1:0] BitWriteMask; - for (index=0; index < WIDTH; index++) - assign BitWriteMask[index] = bwe[index/8]; - ram1p1rwbe_64x22 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we), - .A(addr), .D(din), - .BWEB(~BitWriteMask), .Q(dout)); + genvar index; + // 64 x 22-bit SRAM + logic [WIDTH-1:0] BitWriteMask; + for (index=0; index < WIDTH; index++) + assign BitWriteMask[index] = bwe[index/8]; + ram1p1rwbe_64x22 sram1B (.CLK(clk), .CEB(~ce), .WEB(~we), + .A(addr), .D(din), + .BWEB(~BitWriteMask), .Q(dout)); - // *************************************************************************** - // READ first SRAM model - // *************************************************************************** + // *************************************************************************** + // READ first SRAM model + // *************************************************************************** end else begin: ram integer i; @@ -91,19 +91,18 @@ module ram1p1rwbe #(parameter DEPTH=64, WIDTH=44) ( assign dout = RAM[addrd]; /* // Read - always_ff @(posedge clk) - if(ce) dout <= #1 mem[addr]; */ - + always_ff @(posedge clk) + if(ce) dout <= #1 mem[addr]; */ // Write divided into part for bytes and part for extra msbs - // Questa sim version 2022.3_2 does not allow multiple drivers for RAM when using always_ff. - // Therefore these always blocks use the older always @(posedge clk) + // Questa sim version 2022.3_2 does not allow multiple drivers for RAM when using always_ff. + // Therefore these always blocks use the older always @(posedge clk) if(WIDTH >= 8) always @(posedge clk) if (ce & we) for(i = 0; i < WIDTH/8; i++) if(bwe[i]) RAM[addr][i*8 +: 8] <= #1 din[i*8 +: 8]; - + if (WIDTH%8 != 0) // handle msbs if width not a multiple of 8 always @(posedge clk) if (ce & we & bwe[WIDTH/8]) diff --git a/src/generic/mem/ram1p1rwbe_64x128.sv b/src/generic/mem/ram1p1rwbe_64x128.sv index 84a3e74f9..55b1d75b0 100755 --- a/src/generic/mem/ram1p1rwbe_64x128.sv +++ b/src/generic/mem/ram1p1rwbe_64x128.sv @@ -26,7 +26,7 @@ module ram1p1rwbe_64x128( input logic CLK, - input logic CEB, + input logic CEB, input logic WEB, input logic [5:0] A, input logic [127:0] D, diff --git a/src/generic/mem/ram1p1rwbe_64x22.sv b/src/generic/mem/ram1p1rwbe_64x22.sv index 8e0f56306..5e7a4c5cf 100755 --- a/src/generic/mem/ram1p1rwbe_64x22.sv +++ b/src/generic/mem/ram1p1rwbe_64x22.sv @@ -26,7 +26,7 @@ module ram1p1rwbe_64x22( input logic CLK, - input logic CEB, + input logic CEB, input logic WEB, input logic [5:0] A, input logic [21:0] D, diff --git a/src/generic/mem/ram1p1rwbe_64x44.sv b/src/generic/mem/ram1p1rwbe_64x44.sv index 89730a42b..a2c2c81fa 100644 --- a/src/generic/mem/ram1p1rwbe_64x44.sv +++ b/src/generic/mem/ram1p1rwbe_64x44.sv @@ -26,7 +26,7 @@ module ram1p1rwbe_64x44( input logic CLK, - input logic CEB, + input logic CEB, input logic WEB, input logic [5:0] A, input logic [43:0] D, diff --git a/src/generic/mem/ram2p1r1wbe.sv b/src/generic/mem/ram2p1r1wbe.sv index cefd5ab9f..4c72095b6 100644 --- a/src/generic/mem/ram2p1r1wbe.sv +++ b/src/generic/mem/ram2p1r1wbe.sv @@ -44,96 +44,94 @@ module ram2p1r1wbe #(parameter DEPTH=1024, WIDTH=68) ( output logic [WIDTH-1:0] rd1 ); - logic [WIDTH-1:0] mem[DEPTH-1:0]; - localparam SRAMWIDTH = 32; - localparam SRAMNUMSETS = SRAMWIDTH/WIDTH; + logic [WIDTH-1:0] mem[DEPTH-1:0]; + localparam SRAMWIDTH = 32; + localparam SRAMNUMSETS = SRAMWIDTH/WIDTH; // *************************************************************************** // TRUE Smem macro // *************************************************************************** - if ((`USE_SRAM == 1) & (WIDTH == 68) & (DEPTH == 1024)) begin - - ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk), - .CEBA(~ce1), .CEBB(~ce2), - .WEBA('0), .WEBB(~we2), - .AA(ra1), .AB(wa2), - .DA('0), - .DB(wd2), - .BWEBA('0), .BWEBB('1), - .QA(rd1), - .QB()); + if ((`USE_SRAM == 1) & (WIDTH == 68) & (DEPTH == 1024)) begin + + ram2p1r1wbe_1024x68 memory1(.CLKA(clk), .CLKB(clk), + .CEBA(~ce1), .CEBB(~ce2), + .WEBA('0), .WEBB(~we2), + .AA(ra1), .AB(wa2), + .DA('0), + .DB(wd2), + .BWEBA('0), .BWEBB('1), + .QA(rd1), + .QB()); - end else if ((`USE_SRAM == 1) & (WIDTH == 36) & (DEPTH == 1024)) begin - - ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk), - .CEBA(~ce1), .CEBB(~ce2), - .WEBA('0), .WEBB(~we2), - .AA(ra1), .AB(wa2), - .DA('0), - .DB(wd2), - .BWEBA('0), .BWEBB('1), - .QA(rd1), - .QB()); + end else if ((`USE_SRAM == 1) & (WIDTH == 36) & (DEPTH == 1024)) begin + + ram2p1r1wbe_1024x36 memory1(.CLKA(clk), .CLKB(clk), + .CEBA(~ce1), .CEBB(~ce2), + .WEBA('0), .WEBB(~we2), + .AA(ra1), .AB(wa2), + .DA('0), + .DB(wd2), + .BWEBA('0), .BWEBB('1), + .QA(rd1), + .QB()); - end else if ((`USE_SRAM == 1) & (WIDTH == 2) & (DEPTH == 1024)) begin + end else if ((`USE_SRAM == 1) & (WIDTH == 2) & (DEPTH == 1024)) begin - logic [SRAMWIDTH-1:0] SRAMReadData; - logic [SRAMWIDTH-1:0] SRAMWriteData; - logic [SRAMWIDTH-1:0] RD1Sets[SRAMNUMSETS-1:0]; - logic [SRAMNUMSETS-1:0] SRAMBitMaskPre; - logic [SRAMWIDTH-1:0] SRAMBitMask; - logic [$clog2(DEPTH)-1:0] RA1Q; - - - onehotdecoder #($clog2(SRAMNUMSETS)) oh1(wa2[$clog2(SRAMNUMSETS)-1:0], SRAMBitMaskPre); - genvar index; - for (index = 0; index < SRAMNUMSETS; index++) begin:readdatalinesetsmux - assign RD1Sets[index] = SRAMReadData[(index*WIDTH)+WIDTH-1 : (index*WIDTH)]; - assign SRAMWriteData[index*2+1:index*2] = wd2; - assign SRAMBitMask[index*2+1:index*2] = {2{SRAMBitMaskPre[index]}}; - end - flopen #($clog2(DEPTH)) mem_reg1 (clk, ce1, ra1, RA1Q); - assign rd1 = RD1Sets[RA1Q[$clog2(SRAMWIDTH)-1:0]]; - ram2p1r1wbe_64x32 memory2(.CLKA(clk), .CLKB(clk), - .CEBA(~ce1), .CEBB(~ce2), - .WEBA('0), .WEBB(~we2), - .AA(ra1[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]), - .AB(wa2[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]), - .DA('0), - .DB(SRAMWriteData), - .BWEBA('0), .BWEBB(SRAMBitMask), - .QA(SRAMReadData), - .QB()); + logic [SRAMWIDTH-1:0] SRAMReadData; + logic [SRAMWIDTH-1:0] SRAMWriteData; + logic [SRAMWIDTH-1:0] RD1Sets[SRAMNUMSETS-1:0]; + logic [SRAMNUMSETS-1:0] SRAMBitMaskPre; + logic [SRAMWIDTH-1:0] SRAMBitMask; + logic [$clog2(DEPTH)-1:0] RA1Q; + + onehotdecoder #($clog2(SRAMNUMSETS)) oh1(wa2[$clog2(SRAMNUMSETS)-1:0], SRAMBitMaskPre); + genvar index; + for (index = 0; index < SRAMNUMSETS; index++) begin:readdatalinesetsmux + assign RD1Sets[index] = SRAMReadData[(index*WIDTH)+WIDTH-1 : (index*WIDTH)]; + assign SRAMWriteData[index*2+1:index*2] = wd2; + assign SRAMBitMask[index*2+1:index*2] = {2{SRAMBitMaskPre[index]}}; + end + flopen #($clog2(DEPTH)) mem_reg1 (clk, ce1, ra1, RA1Q); + assign rd1 = RD1Sets[RA1Q[$clog2(SRAMWIDTH)-1:0]]; + ram2p1r1wbe_64x32 memory2(.CLKA(clk), .CLKB(clk), + .CEBA(~ce1), .CEBB(~ce2), + .WEBA('0), .WEBB(~we2), + .AA(ra1[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]), + .AB(wa2[$clog2(DEPTH)-1:$clog2(SRAMNUMSETS)]), + .DA('0), + .DB(SRAMWriteData), + .BWEBA('0), .BWEBB(SRAMBitMask), + .QA(SRAMReadData), + .QB()); - end else begin - - // *************************************************************************** - // READ first SRAM model - // *************************************************************************** - integer i; - + end else begin + + // *************************************************************************** + // READ first SRAM model + // *************************************************************************** + integer i; + // Read logic [$clog2(DEPTH)-1:0] ra1d; flopen #($clog2(DEPTH)) adrreg(clk, ce1, ra1, ra1d); assign rd1 = mem[ra1d]; -/* // Read - always_ff @(posedge clk) - if(ce1) rd1 <= #1 mem[ra1]; */ - - // Write divided into part for bytes and part for extra msbs - if(WIDTH >= 8) - always @(posedge clk) - if (ce2 & we2) - for(i = 0; i < WIDTH/8; i++) - if(bwe2[i]) mem[wa2][i*8 +: 8] <= #1 wd2[i*8 +: 8]; - - if (WIDTH%8 != 0) // handle msbs if width not a multiple of 8 - always @(posedge clk) - if (ce2 & we2 & bwe2[WIDTH/8]) - mem[wa2][WIDTH-1:WIDTH-WIDTH%8] <= #1 wd2[WIDTH-1:WIDTH-WIDTH%8]; - + /* // Read + always_ff @(posedge clk) + if(ce1) rd1 <= #1 mem[ra1]; */ + + // Write divided into part for bytes and part for extra msbs + if(WIDTH >= 8) + always @(posedge clk) + if (ce2 & we2) + for(i = 0; i < WIDTH/8; i++) + if(bwe2[i]) mem[wa2][i*8 +: 8] <= #1 wd2[i*8 +: 8]; + + if (WIDTH%8 != 0) // handle msbs if width not a multiple of 8 + always @(posedge clk) + if (ce2 & we2 & bwe2[WIDTH/8]) + mem[wa2][WIDTH-1:WIDTH-WIDTH%8] <= #1 wd2[WIDTH-1:WIDTH-WIDTH%8]; end - + endmodule diff --git a/src/generic/mem/ram2p1r1wbe_1024x36.sv b/src/generic/mem/ram2p1r1wbe_1024x36.sv index b6b501f27..302277ed0 100755 --- a/src/generic/mem/ram2p1r1wbe_1024x36.sv +++ b/src/generic/mem/ram2p1r1wbe_1024x36.sv @@ -27,8 +27,8 @@ module ram2p1r1wbe_1024x36( input logic CLKA, input logic CLKB, - input logic CEBA, - input logic CEBB, + input logic CEBA, + input logic CEBB, input logic WEBA, input logic WEBB, input logic [9:0] AA, @@ -43,12 +43,12 @@ module ram2p1r1wbe_1024x36( // replace "generic1024x36RAM" with "TSDN..1024X36.." module from your memory vendor //generic1024x36RAM sramIP (.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, - // .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); + // .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); // use part of a larger RAM to avoid generating more flavors of RAM logic [67:0] QAfull, QBfull; TSDN28HPCPA1024X68M4MW sramIP(.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, - .AA, .AB, .DA({32'b0, DA[35:0]}), .DB({32'b0, DB[35:0]}), - .BWEBA({32'b0, BWEBA[35:0]}), .BWEBB({32'b0, BWEBB[35:0]}), .QA(QAfull), .QB(QBfull)); + .AA, .AB, .DA({32'b0, DA[35:0]}), .DB({32'b0, DB[35:0]}), + .BWEBA({32'b0, BWEBA[35:0]}), .BWEBB({32'b0, BWEBB[35:0]}), .QA(QAfull), .QB(QBfull)); assign QA = QAfull[35:0]; assign QB = QBfull[35:0]; diff --git a/src/generic/mem/ram2p1r1wbe_1024x68.sv b/src/generic/mem/ram2p1r1wbe_1024x68.sv index 108530bee..6da7e06d6 100755 --- a/src/generic/mem/ram2p1r1wbe_1024x68.sv +++ b/src/generic/mem/ram2p1r1wbe_1024x68.sv @@ -27,8 +27,8 @@ module ram2p1r1wbe_1024x68( input logic CLKA, input logic CLKB, - input logic CEBA, - input logic CEBB, + input logic CEBA, + input logic CEBB, input logic WEBA, input logic WEBB, input logic [9:0] AA, @@ -43,8 +43,8 @@ module ram2p1r1wbe_1024x68( // replace "generic1024x68RAM" with "TSDN..1024X68.." module from your memory vendor //generic1024x68RAM sramIP (.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, - // .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); + // .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); TSDN28HPCPA1024X68M4MW sramIP(.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, - .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); + .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); endmodule diff --git a/src/generic/mem/ram2p1r1wbe_128x64.sv b/src/generic/mem/ram2p1r1wbe_128x64.sv index 49d2631ee..e181fdd07 100644 --- a/src/generic/mem/ram2p1r1wbe_128x64.sv +++ b/src/generic/mem/ram2p1r1wbe_128x64.sv @@ -27,8 +27,8 @@ module ram2p1r1wbe_128x64( input logic CLKA, input logic CLKB, - input logic CEBA, - input logic CEBB, + input logic CEBA, + input logic CEBB, input logic WEBA, input logic WEBB, input logic [6:0] AA, @@ -43,8 +43,8 @@ module ram2p1r1wbe_128x64( // replace "generic128x64RAM" with "TSDN..128X64.." module from your memory vendor TSDN28HPCPA128X64M4FW sramIP (.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, - .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); + .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); // generic128x64RAM sramIP (.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, -// .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); +// .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); endmodule diff --git a/src/generic/mem/ram2p1r1wbe_512x64.sv b/src/generic/mem/ram2p1r1wbe_512x64.sv index 14fbea75c..442eff90d 100644 --- a/src/generic/mem/ram2p1r1wbe_512x64.sv +++ b/src/generic/mem/ram2p1r1wbe_512x64.sv @@ -27,8 +27,8 @@ module ram2p1r1wbe_2048x64( input logic CLKA, input logic CLKB, - input logic CEBA, - input logic CEBB, + input logic CEBA, + input logic CEBB, input logic WEBA, input logic WEBB, input logic [8:0] AA, @@ -43,8 +43,8 @@ module ram2p1r1wbe_2048x64( // replace "generic2048x64RAM" with "TSDN..2048X64.." module from your memory vendor TSDN28HPCPA2048X64MMFW sramIP (.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, - .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); + .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); // generic2048x64RAM sramIP (.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, -// .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); +// .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); endmodule diff --git a/src/generic/mem/ram2p1r1wbe_64x32.sv b/src/generic/mem/ram2p1r1wbe_64x32.sv index e551099f4..4236bb3f6 100755 --- a/src/generic/mem/ram2p1r1wbe_64x32.sv +++ b/src/generic/mem/ram2p1r1wbe_64x32.sv @@ -27,8 +27,8 @@ module ram2p1r1wbe_64x32( input logic CLKA, input logic CLKB, - input logic CEBA, - input logic CEBB, + input logic CEBA, + input logic CEBB, input logic WEBA, input logic WEBB, input logic [5:0] AA, @@ -43,7 +43,7 @@ module ram2p1r1wbe_64x32( // replace "generic64x32RAM" with "TSDN..64X32.." module from your memory vendor //generic64x32RAM sramIP (.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, - // .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); + // .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); TSDN28HPCPA64X32M4MW sramIP(.CLKA, .CLKB, .CEBA, .CEBB, .WEBA, .WEBB, - .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); + .AA, .AB, .DA, .DB, .BWEBA, .BWEBB, .QA, .QB); endmodule diff --git a/src/generic/mem/rom1p1r.sv b/src/generic/mem/rom1p1r.sv index 6930bc0db..ef9c6da37 100644 --- a/src/generic/mem/rom1p1r.sv +++ b/src/generic/mem/rom1p1r.sv @@ -28,8 +28,8 @@ `include "wally-config.vh" module rom1p1r #(parameter ADDR_WIDTH = 8, - parameter DATA_WIDTH = 32, - parameter PRELOAD_ENABLED = 0) + parameter DATA_WIDTH = 32, + parameter PRELOAD_ENABLED = 0) (input logic clk, input logic ce, input logic [ADDR_WIDTH-1:0] addr, @@ -37,7 +37,7 @@ module rom1p1r #(parameter ADDR_WIDTH = 8, ); // Core Memory - logic [DATA_WIDTH-1:0] ROM [(2**ADDR_WIDTH)-1:0]; + logic [DATA_WIDTH-1:0] ROM [(2**ADDR_WIDTH)-1:0]; /* if ((`USE_SRAM == 1) & (ADDR_WDITH == 7) & (DATA_WIDTH == 64)) begin rom1p1r_128x64 rom1 (.CLK(clk), .CEB(~ce), .A(addr[6:0]), .Q(dout)); @@ -46,55 +46,55 @@ module rom1p1r #(parameter ADDR_WIDTH = 8, end else begin */ always @ (posedge clk) begin - if(ce) dout <= ROM[addr]; + if(ce) dout <= ROM[addr]; end // for FPGA, initialize with zero-stage bootloader if(PRELOAD_ENABLED) initial begin - ROM[0] = 64'h9581819300002197; - ROM[1] = 64'h4281420141014081; - ROM[2] = 64'h4481440143814301; - ROM[3] = 64'h4681460145814501; - ROM[4] = 64'h4881480147814701; - ROM[5] = 64'h4a814a0149814901; - ROM[6] = 64'h4c814c014b814b01; - ROM[7] = 64'h4e814e014d814d01; - ROM[8] = 64'h0110011b4f814f01; - ROM[9] = 64'h059b45011161016e; - ROM[10] = 64'h0004063705fe0010; - ROM[11] = 64'h05a000ef8006061b; - ROM[12] = 64'h0ff003930000100f; - ROM[13] = 64'h4e952e3110060e37; - ROM[14] = 64'hc602829b0053f2b7; - ROM[15] = 64'h2023fe02dfe312fd; - ROM[16] = 64'h829b0053f2b7007e; - ROM[17] = 64'hfe02dfe312fdc602; - ROM[18] = 64'h4de31efd000e2023; - ROM[19] = 64'h059bf1402573fdd0; - ROM[20] = 64'h0000061705e20870; - ROM[21] = 64'h0010029b01260613; - ROM[22] = 64'h11010002806702fe; - ROM[23] = 64'h84b2842ae426e822; - ROM[24] = 64'h892ee04aec064511; - ROM[25] = 64'h06e000ef07e000ef; - ROM[26] = 64'h979334fd02905563; - ROM[27] = 64'h07930177d4930204; - ROM[28] = 64'h4089093394be2004; - ROM[29] = 64'h04138522008905b3; - ROM[30] = 64'h19e3014000ef2004; - ROM[31] = 64'h64a2644260e2fe94; - ROM[32] = 64'h6749808261056902; - ROM[33] = 64'hdfed8b8510472783; - ROM[34] = 64'h2423479110a73823; - ROM[35] = 64'h10472783674910f7; - ROM[36] = 64'h20058693ffed8b89; - ROM[37] = 64'h05a1118737836749; - ROM[38] = 64'hfed59be3fef5bc23; - ROM[39] = 64'h1047278367498082; - ROM[40] = 64'h47858082dfed8b85; - ROM[41] = 64'h40a7853b4015551b; - ROM[42] = 64'h808210a7a02367c9; + ROM[0] = 64'h9581819300002197; + ROM[1] = 64'h4281420141014081; + ROM[2] = 64'h4481440143814301; + ROM[3] = 64'h4681460145814501; + ROM[4] = 64'h4881480147814701; + ROM[5] = 64'h4a814a0149814901; + ROM[6] = 64'h4c814c014b814b01; + ROM[7] = 64'h4e814e014d814d01; + ROM[8] = 64'h0110011b4f814f01; + ROM[9] = 64'h059b45011161016e; + ROM[10] = 64'h0004063705fe0010; + ROM[11] = 64'h05a000ef8006061b; + ROM[12] = 64'h0ff003930000100f; + ROM[13] = 64'h4e952e3110060e37; + ROM[14] = 64'hc602829b0053f2b7; + ROM[15] = 64'h2023fe02dfe312fd; + ROM[16] = 64'h829b0053f2b7007e; + ROM[17] = 64'hfe02dfe312fdc602; + ROM[18] = 64'h4de31efd000e2023; + ROM[19] = 64'h059bf1402573fdd0; + ROM[20] = 64'h0000061705e20870; + ROM[21] = 64'h0010029b01260613; + ROM[22] = 64'h11010002806702fe; + ROM[23] = 64'h84b2842ae426e822; + ROM[24] = 64'h892ee04aec064511; + ROM[25] = 64'h06e000ef07e000ef; + ROM[26] = 64'h979334fd02905563; + ROM[27] = 64'h07930177d4930204; + ROM[28] = 64'h4089093394be2004; + ROM[29] = 64'h04138522008905b3; + ROM[30] = 64'h19e3014000ef2004; + ROM[31] = 64'h64a2644260e2fe94; + ROM[32] = 64'h6749808261056902; + ROM[33] = 64'hdfed8b8510472783; + ROM[34] = 64'h2423479110a73823; + ROM[35] = 64'h10472783674910f7; + ROM[36] = 64'h20058693ffed8b89; + ROM[37] = 64'h05a1118737836749; + ROM[38] = 64'hfed59be3fef5bc23; + ROM[39] = 64'h1047278367498082; + ROM[40] = 64'h47858082dfed8b85; + ROM[41] = 64'h40a7853b4015551b; + ROM[42] = 64'h808210a7a02367c9; end endmodule diff --git a/src/generic/mem/rom1p1r_128x32.sv b/src/generic/mem/rom1p1r_128x32.sv index bc16a76dc..ea5b92054 100755 --- a/src/generic/mem/rom1p1r_128x32.sv +++ b/src/generic/mem/rom1p1r_128x32.sv @@ -26,7 +26,7 @@ module rom1p1r_128x32( input logic CLK, - input logic CEB, + input logic CEB, input logic [6:0] A, output logic [31:0] Q ); diff --git a/src/generic/mem/rom1p1r_128x64.sv b/src/generic/mem/rom1p1r_128x64.sv index 3c7ea4842..6712d10fa 100755 --- a/src/generic/mem/rom1p1r_128x64.sv +++ b/src/generic/mem/rom1p1r_128x64.sv @@ -25,14 +25,14 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module rom1p1r_128x64( - input logic CLK, - input logic CEB, + input logic CLK, + input logic CEB, input logic [6:0] A, output logic [63:0] Q ); // replace "generic64x128RAM" with "TS3N..64X128.." module from your memory vendor -ts3n28hpcpa128x64m8m romIP (.CLK, .CEB, .A, .Q); + ts3n28hpcpa128x64m8m romIP (.CLK, .CEB, .A, .Q); // generic64x128ROM romIP (.CLK, .CEB, .A, .Q); endmodule diff --git a/src/ieu/alu.sv b/src/ieu/alu.sv index 4725d6329..c4e0f3906 100644 --- a/src/ieu/alu.sv +++ b/src/ieu/alu.sv @@ -1,9 +1,9 @@ /////////////////////////////////////////// // alu.sv // -// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu +// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu, kekim@hmc.edu // Created: 9 January 2021 -// Modified: +// Modified: 3 March 2023 // // Purpose: RISC-V Arithmetic/Logic Unit // @@ -30,31 +30,34 @@ `include "wally-config.vh" module alu #(parameter WIDTH=32) ( - input logic [WIDTH-1:0] A, B, // Operands - input logic [2:0] ALUControl, // With Funct3, indicates operation to perform - input logic [2:0] Funct3, // With ALUControl, indicates operation to perform - output logic [WIDTH-1:0] Result, // ALU result - output logic [WIDTH-1:0] Sum); // Sum of operands + input logic [WIDTH-1:0] A, B, // Operands + input logic W64, // W64-type instruction + input logic SubArith, // Subtraction or arithmetic shift + input logic [2:0] ALUSelect, // ALU mux select signal + input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction + input logic [2:0] ZBBSelect, // ZBB mux select signal + input logic [2:0] Funct3, // For BMU decoding + input logic [1:0] CompFlags, // Comparator flags + input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage + output logic [WIDTH-1:0] Result, // ALU result + output logic [WIDTH-1:0] Sum); // Sum of operands // CondInvB = ~B when subtracting, B otherwise. Shift = shift result. SLT/U = result of a slt/u instruction. // FullResult = ALU result before adjusting for a RV64 w-suffix instruction. - logic [WIDTH-1:0] CondInvB, Shift, FullResult; // Intermediate results - logic Carry, Neg; // Flags: carry out, negative - logic LT, LTU; // Less than, Less than unsigned - logic W64; // RV64 W-type instruction - logic SubArith; // Performing subtraction or arithmetic right shift - logic ALUOp; // 0 for address generation addition or 1 for regular ALU ops - logic Asign, Bsign; // Sign bits of A, B - - // Extract control signals from ALUControl. - assign {W64, SubArith, ALUOp} = ALUControl; + logic [WIDTH-1:0] CondMaskInvB, Shift, FullResult, ALUResult; // Intermediate Signals + logic [WIDTH-1:0] CondMaskB; // Result of B mask select mux + logic [WIDTH-1:0] CondShiftA; // Result of A shifted select mux + logic [WIDTH-1:0] CondExtA; // Result of Zero Extend A select mux + logic Carry, Neg; // Flags: carry out, negative + logic LT, LTU; // Less than, Less than unsigned + logic Asign, Bsign; // Sign bits of A, B // Addition - assign CondInvB = SubArith ? ~B : B; - assign {Carry, Sum} = A + CondInvB + {{(WIDTH-1){1'b0}}, SubArith}; + assign CondMaskInvB = SubArith ? ~CondMaskB : CondMaskB; + assign {Carry, Sum} = CondShiftA + CondMaskInvB + {{(WIDTH-1){1'b0}}, SubArith}; - // Shifts - shifter sh(.A, .Amt(B[`LOG_XLEN-1:0]), .Right(Funct3[2]), .Arith(SubArith), .W64, .Y(Shift)); + // Shifts (configurable for rotation) + shifter sh(.A, .Amt(B[`LOG_XLEN-1:0]), .Right(Funct3[2]), .W64, .SubArith, .Y(Shift), .Rotate(BALUControl[2])); // Condition code flags are based on subtraction output Sum = A-B. // Overflow occurs when the numbers being subtracted have the opposite sign @@ -67,20 +70,31 @@ module alu #(parameter WIDTH=32) ( assign LTU = ~Carry; // Select appropriate ALU Result - always_comb - if (~ALUOp) FullResult = Sum; // Always add for ALUOp = 0 (address generation) - else casez (Funct3) // Otherwise check Funct3 - 3'b000: FullResult = Sum; // add or sub - 3'b?01: FullResult = Shift; // sll, sra, or srl - 3'b010: FullResult = {{(WIDTH-1){1'b0}}, LT}; // slt - 3'b011: FullResult = {{(WIDTH-1){1'b0}}, LTU}; // sltu - 3'b100: FullResult = A ^ B; // xor - 3'b110: FullResult = A | B; // or - 3'b111: FullResult = A & B; // and + always_comb begin + case (ALUSelect) + 3'b000: FullResult = Sum; // add or sub (including address generation) + 3'b001: FullResult = Shift; // sll, sra, or srl + 3'b010: FullResult = {{(WIDTH-1){1'b0}}, LT}; // slt + 3'b011: FullResult = {{(WIDTH-1){1'b0}}, LTU}; // sltu + 3'b100: FullResult = A ^ CondMaskInvB; // xor, xnor, binv + 3'b101: FullResult = (`ZBS_SUPPORTED | `ZBB_SUPPORTED) ? {{(WIDTH-1){1'b0}},{|(A & CondMaskB)}} : Shift; // bext (or IEU shift when BMU not supported) + 3'b110: FullResult = A | CondMaskInvB; // or, orn, bset + 3'b111: FullResult = A & CondMaskInvB; // and, bclr endcase + end // Support RV64I W-type addw/subw/addiw/shifts that discard upper 32 bits and sign-extend 32-bit result to 64 bits - if (WIDTH == 64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult; - else assign Result = FullResult; -endmodule + if (WIDTH == 64) assign ALUResult = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult; + else assign ALUResult = FullResult; + // Final Result B instruction select mux + if (`ZBC_SUPPORTED | `ZBS_SUPPORTED | `ZBA_SUPPORTED | `ZBB_SUPPORTED) begin : bitmanipalu + bitmanipalu #(WIDTH) balu(.A, .B, .W64, .BSelect, .ZBBSelect, + .Funct3, .CompFlags, .BALUControl, .ALUResult, .FullResult, + .CondMaskB, .CondShiftA, .Result); + end else begin + assign Result = ALUResult; + assign CondMaskB = B; + assign CondShiftA = A; + end +endmodule \ No newline at end of file diff --git a/src/ieu/bmu/bitmanipalu.sv b/src/ieu/bmu/bitmanipalu.sv new file mode 100644 index 000000000..07c7e5343 --- /dev/null +++ b/src/ieu/bmu/bitmanipalu.sv @@ -0,0 +1,99 @@ +/////////////////////////////////////////// +// bitmanipalu.sv +// +// Written: Kevin Kim +// Created: 23 March 2023 +// Modified: 23 March 2023 +// +// Purpose: RISC-V Arithmetic/Logic Unit Bit-Manipulation Extension +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module bitmanipalu #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] A, B, // Operands + input logic W64, // W64-type instruction + input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction + input logic [2:0] ZBBSelect, // ZBB mux select signal + input logic [2:0] Funct3, // Funct3 field of opcode indicates operation to perform + input logic [1:0] CompFlags, // Comparator flags + input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage + input logic [WIDTH-1:0] ALUResult, FullResult, // ALUResult, FullResult signals + output logic [WIDTH-1:0] CondMaskB, // B is conditionally masked for ZBS instructions + output logic [WIDTH-1:0] CondShiftA, // A is conditionally shifted for ShAdd instructions + output logic [WIDTH-1:0] Result); // Result + + logic [WIDTH-1:0] ZBBResult, ZBCResult; // ZBB, ZBC Result + logic [WIDTH-1:0] MaskB; // BitMask of B + logic [WIDTH-1:0] RevA; // Bit-reversed A + logic Rotate; // Indicates if it is Rotate instruction + logic Mask; // Indicates if it is ZBS instruction + logic PreShift; // Inidicates if it is sh1add, sh2add, sh3add instruction + logic [1:0] PreShiftAmt; // Amount to Pre-Shift A + logic [WIDTH-1:0] CondZextA; // A Conditional Extend Intermediary Signal + + // Extract control signals from bitmanip ALUControl. + assign {Mask, PreShift} = BALUControl[1:0]; + + // Mask Generation Mux + if (`ZBS_SUPPORTED) begin: zbsdec + decoder #($clog2(WIDTH)) maskgen(B[$clog2(WIDTH)-1:0], MaskB); + mux2 #(WIDTH) maskmux(B, MaskB, Mask, CondMaskB); + end else assign CondMaskB = B; + + // 0-3 bit Pre-Shift Mux + if (`ZBA_SUPPORTED) begin: zbapreshift + if (WIDTH == 64) begin + mux2 #(64) zextmux(A, {{32{1'b0}}, A[31:0]}, W64, CondZextA); + end else assign CondZextA = A; + assign PreShiftAmt = Funct3[2:1] & {2{PreShift}}; + assign CondShiftA = CondZextA << (PreShiftAmt); + end else begin + assign PreShiftAmt = 2'b0; + assign CondShiftA = A; + end + + // Bit reverse needed for some ZBB, ZBC instructions + if (`ZBC_SUPPORTED | `ZBB_SUPPORTED) begin: bitreverse + bitreverse #(WIDTH) brA(.A, .RevA); + end + + // ZBC Unit + if (`ZBC_SUPPORTED) begin: zbc + zbc #(WIDTH) ZBC(.A, .RevA, .B, .Funct3, .ZBCResult); + end else assign ZBCResult = 0; + + // ZBB Unit + if (`ZBB_SUPPORTED) begin: zbb + zbb #(WIDTH) ZBB(.A, .RevA, .B, .ALUResult, .W64, .lt(CompFlags[0]), .ZBBSelect, .ZBBResult); + end else assign ZBBResult = 0; + + // Result Select Mux + always_comb + case (BSelect) + // 00: ALU, 01: ZBA/ZBS, 10: ZBB, 11: ZBC + 2'b00: Result = ALUResult; + 2'b01: Result = FullResult; // NOTE: We don't use ALUResult because ZBA/ZBS instructions don't sign extend the MSB of the right-hand word. + 2'b10: Result = ZBBResult; + 2'b11: Result = ZBCResult; + endcase +endmodule diff --git a/src/ieu/bmu/bitreverse.sv b/src/ieu/bmu/bitreverse.sv new file mode 100644 index 000000000..e2afb0c95 --- /dev/null +++ b/src/ieu/bmu/bitreverse.sv @@ -0,0 +1,42 @@ + +/////////////////////////////////////////// +// bitreverse.sv +// +// Written: Kevin Kim and Kip Macsai-Goren +// Created: 1 February 2023 +// Modified: 6 March 2023 +// +// Purpose: Bit reverse submodule +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// +`include "wally-config.vh" + +module bitreverse #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] A, + output logic [WIDTH-1:0] RevA); + + genvar i; + for (i=0; i +// Created: 16 February 2023 +// Modified: 6 March 2023 +// +// Purpose: Top level bit manipulation instruction decoder +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module bmuctrl( + input logic clk, reset, + // Decode stage control signals + input logic StallD, FlushD, // Stall, flush Decode stage + input logic [31:0] InstrD, // Instruction in Decode stage + input logic ALUOpD, // Regular ALU Operation + output logic [1:0] BSelectD, // Indicates if ZBA_ZBB_ZBC_ZBS instruction in one-hot encoding in Decode stage + output logic [2:0] ZBBSelectD, // ZBB mux select signal in Decode stage NOTE: do we need this in decode? + output logic BRegWriteD, // Indicates if it is a R type B instruction in Decode Stage + output logic BALUSrcBD, // Indicates if it is an I/IW (non auipc) type B instruction in Decode Stage + output logic BW64D, // Indiciates if it is a W type B instruction in Decode Stage + output logic BSubArithD, // TRUE if ext, clr, andn, orn, xnor instruction in Decode Stage + output logic IllegalBitmanipInstrD, // Indicates if it is unrecognized B instruction in Decode Stage + // Execute stage control signals + input logic StallE, FlushE, // Stall, flush Execute stage + output logic [2:0] ALUSelectD, // ALU select + output logic [1:0] BSelectE, // Indicates if ZBA_ZBB_ZBC_ZBS instruction in one-hot encoding + output logic [2:0] ZBBSelectE, // ZBB mux select signal + output logic BRegWriteE, // Indicates if it is a R type B instruction in Execute + output logic BComparatorSignedE, // Indicates if comparator signed in Execute Stage + output logic [2:0] BALUControlE // ALU Control signals for B instructions in Execute Stage +); + + logic [6:0] OpD; // Opcode in Decode stage + logic [2:0] Funct3D; // Funct3 field in Decode stage + logic [6:0] Funct7D; // Funct7 field in Decode stage + logic [4:0] Rs2D; // Rs2 source register in Decode stage + logic BComparatorSignedD; // Indicates if comparator signed (max, min instruction) in Decode Stage + logic RotateD; // Indicates if rotate instruction in Decode Stage + logic MaskD; // Indicates if zbs instruction in Decode Stage + logic PreShiftD; // Indicates if sh1add, sh2add, sh3add instruction in Decode Stage + logic [2:0] BALUControlD; // ALU Control signals for B instructions + logic [2:0] BALUSelectD; // ALU Mux select signal in Decode Stage for BMU operations + logic BALUOpD; // Indicates if it is an ALU B instruction in Decode Stage + + `define BMUCTRLW 17 + + logic [`BMUCTRLW-1:0] BMUControlsD; // Main B Instructions Decoder control signals + + // Extract fields + assign OpD = InstrD[6:0]; + assign Funct3D = InstrD[14:12]; + assign Funct7D = InstrD[31:25]; + assign Rs2D = InstrD[24:20]; + + // Main Instruction Decoder + always_comb begin + // BALUSelect_BSelect_ZBBSelect_BRegWrite_BALUSrcB_BW64_BALUOp_BSubArithD_RotateD_MaskD_PreShiftD_IllegalBitmanipInstrD + BMUControlsD = `BMUCTRLW'b000_00_000_0_0_0_0_0_0_0_0_1; // default: Illegal bmu instruction; + if (`ZBA_SUPPORTED) begin + casez({OpD, Funct7D, Funct3D}) + 17'b0110011_0010000_010: BMUControlsD = `BMUCTRLW'b000_01_000_1_0_0_1_0_0_0_1_0; // sh1add + 17'b0110011_0010000_100: BMUControlsD = `BMUCTRLW'b000_01_000_1_0_0_1_0_0_0_1_0; // sh2add + 17'b0110011_0010000_110: BMUControlsD = `BMUCTRLW'b000_01_000_1_0_0_1_0_0_0_1_0; // sh3add + endcase + if (`XLEN==64) + casez({OpD, Funct7D, Funct3D}) + 17'b0111011_0010000_010: BMUControlsD = `BMUCTRLW'b000_01_000_1_0_1_1_0_0_0_1_0; // sh1add.uw + 17'b0111011_0010000_100: BMUControlsD = `BMUCTRLW'b000_01_000_1_0_1_1_0_0_0_1_0; // sh2add.uw + 17'b0111011_0010000_110: BMUControlsD = `BMUCTRLW'b000_01_000_1_0_1_1_0_0_0_1_0; // sh3add.uw + 17'b0111011_0000100_000: BMUControlsD = `BMUCTRLW'b000_01_000_1_0_1_1_0_0_0_0_0; // add.uw + 17'b0011011_000010?_001: BMUControlsD = `BMUCTRLW'b001_01_000_1_1_1_1_0_0_0_0_0; // slli.uw + endcase + end + if (`ZBB_SUPPORTED) begin + casez({OpD, Funct7D, Funct3D}) + 17'b0110011_0110000_001: BMUControlsD = `BMUCTRLW'b001_01_111_1_0_0_1_0_1_0_0_0; // rol + 17'b0110011_0110000_101: BMUControlsD = `BMUCTRLW'b001_01_111_1_0_0_1_0_1_0_0_0; // ror + 17'b0010011_0110000_001: if ((Rs2D[4:1] == 4'b0010)) + BMUControlsD = `BMUCTRLW'b000_10_001_1_1_0_1_0_0_0_0_0; // sign extend instruction + else if ((Rs2D[4:2]==3'b000) & ~(Rs2D[1] & Rs2D[0])) + BMUControlsD = `BMUCTRLW'b000_10_000_1_1_0_1_0_0_0_0_0; // count instruction + 17'b0110011_0000100_100: if (`XLEN == 32) + BMUControlsD = `BMUCTRLW'b000_10_001_1_1_0_1_0_0_0_0_0; // zexth (rv32) + 17'b0110011_0100000_111: BMUControlsD = `BMUCTRLW'b111_01_111_1_0_0_1_1_0_0_0_0; // andn + 17'b0110011_0100000_110: BMUControlsD = `BMUCTRLW'b110_01_111_1_0_0_1_1_0_0_0_0; // orn + 17'b0110011_0100000_100: BMUControlsD = `BMUCTRLW'b100_01_111_1_0_0_1_1_0_0_0_0; // xnor + 17'b0010011_011010?_101: if ((`XLEN == 32 ^ Funct7D[0]) & (Rs2D == 5'b11000)) + BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // rev8 + 17'b0010011_0010100_101: if (Rs2D[4:0] == 5'b00111) + BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // orc.b + 17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_0_0_0_0_0; // max + 17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_0_0_0_0_0; // maxu + 17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_0_0_0_0_0; // min + 17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_0_0_0_0_0; // minu + endcase + if (`XLEN==32) + casez({OpD, Funct7D, Funct3D}) + 17'b0110011_0000100_100: BMUControlsD = `BMUCTRLW'b000_10_001_1_1_0_1_0_0_0_0_0; // zexth (rv32) + 17'b0010011_0110000_101: BMUControlsD = `BMUCTRLW'b001_00_111_1_1_0_1_0_1_0_0_0; // rori (rv32) + endcase + else if (`XLEN==64) + casez({OpD, Funct7D, Funct3D}) + 17'b0111011_0000100_100: BMUControlsD = `BMUCTRLW'b000_10_001_1_0_0_1_0_0_0_0_0; // zexth (rv64) + 17'b0111011_0110000_001: BMUControlsD = `BMUCTRLW'b001_00_111_1_0_1_1_0_1_0_0_0; // rolw + 17'b0111011_0110000_101: BMUControlsD = `BMUCTRLW'b001_00_111_1_0_1_1_0_1_0_0_0; // rorw + 17'b0010011_011000?_101: BMUControlsD = `BMUCTRLW'b001_00_111_1_1_0_1_0_1_0_0_0; // rori (rv64) + 17'b0011011_0110000_101: BMUControlsD = `BMUCTRLW'b001_00_111_1_1_1_1_0_1_0_0_0; // roriw + 17'b0011011_0110000_001: if ((Rs2D[4:2]==3'b000) & ~(Rs2D[1] & Rs2D[0])) + BMUControlsD = `BMUCTRLW'b000_10_000_1_1_1_1_0_0_0_0_0; // count word instruction + endcase + end + if (`ZBC_SUPPORTED) + casez({OpD, Funct7D, Funct3D}) + 17'b0110011_0000101_0??: BMUControlsD = `BMUCTRLW'b000_11_000_1_0_0_1_0_0_0_0_0; // ZBC instruction + endcase + if (`ZBS_SUPPORTED) begin // ZBS + casez({OpD, Funct7D, Funct3D}) + 17'b0110011_0100100_001: BMUControlsD = `BMUCTRLW'b111_01_000_1_0_0_1_1_0_1_0_0; // bclr + 17'b0110011_0100100_101: BMUControlsD = `BMUCTRLW'b101_01_000_1_0_0_1_1_0_1_0_0; // bext + 17'b0110011_0110100_001: BMUControlsD = `BMUCTRLW'b100_01_000_1_0_0_1_0_0_1_0_0; // binv + 17'b0110011_0010100_001: BMUControlsD = `BMUCTRLW'b110_01_000_1_0_0_1_0_0_1_0_0; // bset + endcase + if (`XLEN==32) // ZBS 64-bit + casez({OpD, Funct7D, Funct3D}) + 17'b0010011_0100100_001: BMUControlsD = `BMUCTRLW'b111_01_000_1_1_0_1_1_0_1_0_0; // bclri + 17'b0010011_0100100_101: BMUControlsD = `BMUCTRLW'b101_01_000_1_1_0_1_1_0_1_0_0; // bexti + 17'b0010011_0110100_001: BMUControlsD = `BMUCTRLW'b100_01_000_1_1_0_1_0_0_1_0_0; // binvi + 17'b0010011_0010100_001: BMUControlsD = `BMUCTRLW'b110_01_000_1_1_0_1_0_0_1_0_0; // bseti + endcase + else if (`XLEN==64) // ZBS 64-bit + casez({OpD, Funct7D, Funct3D}) + 17'b0010011_010010?_001: BMUControlsD = `BMUCTRLW'b111_01_000_1_1_0_1_1_0_1_0_0; // bclri (rv64) + 17'b0010011_010010?_101: BMUControlsD = `BMUCTRLW'b101_01_000_1_1_0_1_1_0_1_0_0; // bexti (rv64) + 17'b0010011_011010?_001: BMUControlsD = `BMUCTRLW'b100_01_000_1_1_0_1_0_0_1_0_0; // binvi (rv64) + 17'b0010011_001010?_001: BMUControlsD = `BMUCTRLW'b110_01_000_1_1_0_1_0_0_1_0_0; // bseti (rv64) + endcase + end + if (`ZBB_SUPPORTED | `ZBS_SUPPORTED) // rv32i/64i shift instructions need BMU ALUSelect when BMU shifter is used + casez({OpD, Funct7D, Funct3D}) + 17'b0110011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_00_000_1_0_0_1_0_0_0_0_0; // sra, srl, sll + 17'b0010011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_00_000_1_1_0_1_0_0_0_0_0; // srai, srli, slli + 17'b0111011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_00_000_1_0_1_1_0_0_0_0_0; // sraw, srlw, sllw + 17'b0011011_0?0000?_?01: BMUControlsD = `BMUCTRLW'b001_00_000_1_1_1_1_0_0_0_0_0; // sraiw, srliw, slliw + endcase + end + + // Unpack Control Signals + assign {BALUSelectD, BSelectD, ZBBSelectD, BRegWriteD,BALUSrcBD, BW64D, BALUOpD, BSubArithD, RotateD, MaskD, PreShiftD, IllegalBitmanipInstrD} = BMUControlsD; + + // Pack BALUControl Signals + assign BALUControlD = {RotateD, MaskD, PreShiftD}; + + // Comparator should perform signed comparison when min/max instruction. We have overlap in funct3 with some branch instructions so we use opcode to differentiate betwen min/max and branches + assign BComparatorSignedD = (Funct3D[2]^Funct3D[0]) & ~OpD[6]; + + // Choose ALUSelect brom BMU for BMU operations, Funct3 for IEU operations, or 0 for addition + assign ALUSelectD = BALUOpD ? BALUSelectD : (ALUOpD ? Funct3D : 3'b000); + + // BMU Execute stage pipieline control register + flopenrc#(10) controlregBMU(clk, reset, FlushE, ~StallE, {BSelectD, ZBBSelectD, BRegWriteD, BComparatorSignedD, BALUControlD}, {BSelectE, ZBBSelectE, BRegWriteE, BComparatorSignedE, BALUControlE}); +endmodule diff --git a/src/ieu/bmu/byte.sv b/src/ieu/bmu/byte.sv new file mode 100644 index 000000000..db7a3b45c --- /dev/null +++ b/src/ieu/bmu/byte.sv @@ -0,0 +1,46 @@ +/////////////////////////////////////////// +// byte.sv +// +// Written: Kevin Kim +// Created: 1 February 2023 +// Modified: 6 March 2023 +// +// Purpose: RISCV bitmanip byte-wise operation unit +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module byteUnit #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] A, // Operands + input logic ByteSelect, // LSB of Immediate + output logic [WIDTH-1:0] ByteResult); // rev8, orcb result + + logic [WIDTH-1:0] OrcBResult, Rev8Result; + genvar i; + + for (i=0;i and Kip Macsai-Goren +// Created: 1 February 2023 +// Modified: +// +// Purpose: Carry-Less multiplication unit +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module clmul #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] A, B, // Operands + output logic [WIDTH-1:0] ClmulResult); // ZBS result + + logic [(WIDTH*WIDTH)-1:0] s; // intermediary signals for carry-less multiply + + integer i,j; + + always_comb begin + for (i=0;i +// Created: 4 February 2023 +// Modified: +// +// Purpose: Count Instruction Submodule +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module cnt #(parameter WIDTH = 32) ( + input logic [WIDTH-1:0] A, RevA, // Operands + input logic [4:0] B, // Last 5 bits of immediate + input logic W64, // Indicates word operation + output logic [WIDTH-1:0] CntResult // count result +); + + //count instructions + logic [WIDTH-1:0] czResult; // count zeros result + logic [WIDTH-1:0] cpopResult; // population count result + logic [WIDTH-1:0] lzcA, popcntA; + + //only in rv64 + if (WIDTH==64) begin + //clz input select mux + mux4 #(WIDTH) lzcmux64(A, {A[31:0],{32{1'b1}}}, RevA, {RevA[63:32],{32{1'b1}}}, {B[0],W64}, lzcA); + //cpop select mux + mux2 #(WIDTH) popcntmux64(A, {{32{1'b0}}, A[31:0]}, W64, popcntA); + end + //rv32 + else begin + assign popcntA = A; + mux2 #(WIDTH) lzcmux32(A, RevA, B[0], lzcA); + end + + lzc #(WIDTH) lzc(.num(lzcA), .ZeroCnt(czResult[$clog2(WIDTH):0])); + popcnt #(WIDTH) popcntw(.num(popcntA), .PopCnt(cpopResult[$clog2(WIDTH):0])); + // zero extend these results to fit into width + assign czResult[WIDTH-1:$clog2(WIDTH)+1] = '0; + assign cpopResult[WIDTH-1:$clog2(WIDTH)+1] = '0; + + mux2 #(WIDTH) cntresultmux(czResult, cpopResult, B[1], CntResult); +endmodule \ No newline at end of file diff --git a/src/ieu/bmu/ext.sv b/src/ieu/bmu/ext.sv new file mode 100644 index 000000000..12e690436 --- /dev/null +++ b/src/ieu/bmu/ext.sv @@ -0,0 +1,45 @@ + +/////////////////////////////////////////// +// ext.sv +// +// Written: Kevin Kim +// Created: 4 February 2023 +// Modified: +// +// Purpose: Sign/Zero Extension Submodule +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module ext #(parameter WIDTH = 32) ( + input logic [WIDTH-1:0] A, // Operands + input logic [1:0] ExtSelect, // B[2], B[0] of immediate + output logic [WIDTH-1:0] ExtResult); // Extend Result + + logic [WIDTH-1:0] sexthResult, zexthResult, sextbResult; + + assign sexthResult = {{(WIDTH-16){A[15]}},A[15:0]}; + assign zexthResult = {{(WIDTH-16){1'b0}},A[15:0]}; + assign sextbResult = {{(WIDTH-8){A[7]}},A[7:0]}; + + mux3 #(WIDTH) extmux(sextbResult, sexthResult, zexthResult, ExtSelect, ExtResult); +endmodule \ No newline at end of file diff --git a/src/ieu/bmu/popcnt.sv b/src/ieu/bmu/popcnt.sv new file mode 100644 index 000000000..77c4b6158 --- /dev/null +++ b/src/ieu/bmu/popcnt.sv @@ -0,0 +1,44 @@ + +/////////////////////////////////////////// +// popccnt.sv +// Written: Kevin Kim +// Modified: 2/4/2023 +// +// Purpose: Population Count +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +module popcnt #(parameter WIDTH = 32) ( + input logic [WIDTH-1:0] num, // number to count total ones + output logic [$clog2(WIDTH):0] PopCnt // the total number of ones +); + + logic [$clog2(WIDTH):0] sum; + + always_comb begin + sum = 0; + for (int i=0;i and Kip Macsai-Goren +// Created: 2 February 2023 +// Modified: March 6 2023 +// +// Purpose: RISC-V ZBB top level unit +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module zbb #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] A, RevA, B, // Operands + input logic [WIDTH-1:0] ALUResult, // ALU Result + input logic W64, // Indicates word operation + input logic lt, // lt flag + input logic [2:0] ZBBSelect, // Indicates word operation + output logic [WIDTH-1:0] ZBBResult); // ZBB result + + logic [WIDTH-1:0] CntResult; // count result + logic [WIDTH-1:0] MinMaxResult; // min,max result + logic [WIDTH-1:0] ByteResult; // byte results + logic [WIDTH-1:0] ExtResult; // sign/zero extend results + + cnt #(WIDTH) cnt(.A, .RevA, .B(B[4:0]), .W64, .CntResult); + byteUnit #(WIDTH) bu(.A, .ByteSelect(B[0]), .ByteResult); + ext #(WIDTH) ext(.A, .ExtSelect({~B[2], {B[2] & B[0]}}), .ExtResult); + + // ZBBSelect[2] differentiates between min(u) vs max(u) instruction + mux2 #(WIDTH) minmaxmux(B, A, lt^ZBBSelect[2], MinMaxResult); + + // ZBB Result select mux + mux4 #(WIDTH) zbbresultmux(CntResult, ExtResult, ByteResult, MinMaxResult, ZBBSelect[1:0], ZBBResult); +endmodule \ No newline at end of file diff --git a/src/ieu/bmu/zbc.sv b/src/ieu/bmu/zbc.sv new file mode 100644 index 000000000..05e05d38f --- /dev/null +++ b/src/ieu/bmu/zbc.sv @@ -0,0 +1,54 @@ +/////////////////////////////////////////// +// zbc.sv +// +// Written: Kevin Kim and Kip Macsai-Goren +// Created: 2 February 2023 +// Modified: 3 March 2023 +// +// Purpose: RISC-V ZBC top-level unit +// +// Documentation: RISC-V System on Chip Design Chapter 15 +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +`include "wally-config.vh" + +module zbc #(parameter WIDTH=32) ( + input logic [WIDTH-1:0] A, RevA, B, // Operands + input logic [2:0] Funct3, // Indicates operation to perform + output logic [WIDTH-1:0] ZBCResult); // ZBC result + + logic [WIDTH-1:0] ClmulResult, RevClmulResult; + logic [WIDTH-1:0] RevB; + logic [WIDTH-1:0] x,y; + logic [1:0] select; + + assign select = ~Funct3[1:0]; + + bitreverse #(WIDTH) brB(.A(B), .RevA(RevB)); + + mux3 #(WIDTH) xmux({RevA[WIDTH-2:0], {1'b0}}, RevA, A, select, x); + mux3 #(WIDTH) ymux({{1'b0},RevB[WIDTH-2:0]}, RevB, B, select, y); + + clmul #(WIDTH) clm(.A(x), .B(y), .ClmulResult(ClmulResult)); + + bitreverse #(WIDTH) brClmulResult(.A(ClmulResult), .RevA(RevClmulResult)); + + mux2 #(WIDTH) zbcresultmux(ClmulResult, RevClmulResult, Funct3[1], ZBCResult); +endmodule \ No newline at end of file diff --git a/src/ieu/controller.sv b/src/ieu/controller.sv index 9acaeb2ff..da99a48f6 100644 --- a/src/ieu/controller.sv +++ b/src/ieu/controller.sv @@ -1,9 +1,9 @@ /////////////////////////////////////////// // controller.sv // -// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu +// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu, kekim@hmc.edu // Created: 9 January 2021 -// Modified: +// Modified: 3 March 2023 // // Purpose: Top level controller module // @@ -31,7 +31,7 @@ module controller( - input logic clk, reset, + input logic clk, reset, // Decode stage control signals input logic StallD, FlushD, // Stall, flush Decode stage input logic [31:0] InstrD, // Instruction in Decode stage @@ -41,22 +41,27 @@ module controller( output logic JumpD, // Jump instruction output logic BranchD, // Branch instruction // Execute stage control signals - input logic StallE, FlushE, // Stall, flush Execute stage + input logic StallE, FlushE, // Stall, flush Execute stage input logic [1:0] FlagsE, // Comparison flags ({eq, lt}) input logic FWriteIntE, // Write integer register, coming from FPU controller output logic PCSrcE, // Select signal to choose next PC (for datapath and Hazard unit) - output logic [2:0] ALUControlE, // ALU operation to perform - output logic ALUSrcAE, ALUSrcBE, // ALU operands + output logic ALUSrcAE, ALUSrcBE, // ALU operands output logic ALUResultSrcE, // Selects result to pass on to Memory stage + output logic [2:0] ALUSelectE, // ALU mux select signal output logic MemReadE, CSRReadE, // Instruction reads memory, reads a CSR (needed for Hazard unit) output logic [2:0] Funct3E, // Instruction's funct3 field output logic IntDivE, // Integer divide output logic MDUE, // MDU (multiply/divide) operatio output logic W64E, // RV64 W-type operation + output logic SubArithE, // Subtraction or arithmetic shift output logic JumpE, // jump instruction output logic BranchE, // Branch instruction output logic SCE, // Store Conditional instruction output logic BranchSignedE, // Branch comparison operands are signed (if it's a branch) + output logic [1:0] BSelectE, // One-Hot encoding of if it's ZBA_ZBB_ZBC_ZBS instruction + output logic [2:0] ZBBSelectE, // ZBB mux select signal in Execute stage + output logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage + // Memory stage control signals input logic StallM, FlushM, // Stall, flush Memory stage output logic [1:0] MemRWM, // Mem read/write: MemRWM[1] = 1 for read, MemRWM[0] = 1 for write @@ -69,7 +74,7 @@ module controller( output logic FWriteIntM, // FPU controller writes integer register file // Writeback stage control signals input logic StallW, FlushW, // Stall, flush Writeback stage - output logic RegWriteW, IntDivW, // Instruction writes a register, is an integer divide + output logic RegWriteW, IntDivW, // Instruction writes a register, is an integer divide output logic [2:0] ResultSrcW, // Select source of result to write back to register file // Stall during CSRs output logic CSRWriteFenceM, // CSR write or fence instruction; needs to flush the following instructions @@ -84,12 +89,16 @@ module controller( `define CTRLW 23 // pipelined control signals - logic RegWriteD, RegWriteE; // RegWrite (register will be written) + logic RegWriteD, RegWriteE; // RegWrite (register will be written) logic [2:0] ResultSrcD, ResultSrcE, ResultSrcM; // Select which result to write back to register file logic [1:0] MemRWD, MemRWE; // Store (write to memory) - logic ALUOpD; // 0 for address generation, 1 for all other operations (must use Funct3) + logic ALUOpD; // 0 for address generation, 1 for all other operations (must use Funct3) + logic BaseW64D; // W64 for Base instructions specifically + logic BaseRegWriteD; // Indicates if Base instruction register write instruction + logic BaseSubArithD; // Indicates if Base instruction subtracts, sra, slt, sltu + logic BaseALUSrcBD; // Base instruction ALU B source select signal logic [2:0] ALUControlD; // Determines ALU operation - logic ALUSrcAD, ALUSrcBD; // ALU inputs + logic ALUSrcAD, ALUSrcBD; // ALU inputs logic ALUResultSrcD, W64D, MDUD; // ALU result, is RV64 W-type, is multiply/divide instruction logic CSRZeroSrcD; // Ignore setting and clearing zeros to CSR logic CSRReadD; // CSR read instruction @@ -100,22 +109,28 @@ module controller( logic PrivilegedD, PrivilegedE; // Privileged instruction logic InvalidateICacheE, FlushDCacheE;// Invalidate I$, flush D$ logic [`CTRLW-1:0] ControlsD; // Main Instruction Decoder control signals - logic SubArithD; // TRUE for R-type subtracts and sra, slt, sltu + logic SubArithD; // TRUE for R-type subtracts and sra, slt, sltu or B-type ext clr, andn, orn, xnor logic subD, sraD, sltD, sltuD; // Indicates if is one of these instructions + logic ALUOpE; // 0 for address generationm 1 for ALU operations logic BranchTakenE; // Branch is taken logic eqE, ltE; // Comparator outputs logic unused; - logic BranchFlagE; // Branch flag to use (chosen between eq or lt) + logic BranchFlagE; // Branch flag to use (chosen between eq or lt) logic IEURegWriteE; // Register write + logic BRegWriteE; // Register write from BMU controller in Execute Stage logic IllegalERegAdrD; // RV32E attempts to write upper 16 registers logic [1:0] AtomicE; // Atomic instruction logic FenceD, FenceE; // Fence instruction logic SFenceVmaD; // sfence.vma instruction logic IntDivM; // Integer divide instruction + logic [1:0] BSelectD; // One-Hot encoding if it's ZBA_ZBB_ZBC_ZBS instruction in decode stage + logic [2:0] ZBBSelectD; // ZBB Mux Select Signal + logic BComparatorSignedE; // Indicates if max, min (signed comarison) instruction in Execute Stage logic IFunctD, RFunctD, MFunctD; // Detect I, R, and M-type RV32IM/Rv64IM instructions logic LFunctD, SFunctD, BFunctD; // Detect load, store, branch instructions logic JFunctD; // detect jalr instruction logic FenceM; // Fence.I or sfence.VMA instruction in memory stage + logic [2:0] ALUSelectD; // ALU Output selection mux control // Extract fields assign OpD = InstrD[6:0]; @@ -131,29 +146,29 @@ module controller( logic Funct7ZeroD, Funct7b5D, IShiftD, INoShiftD; logic Funct7ShiftZeroD, Funct7Shiftb5D; - assign Funct7ZeroD = (Funct7D == 7'b0000000); // most R-type instructions - assign Funct7b5D = (Funct7D == 7'b0100000); // srai, sub + assign Funct7ZeroD = (Funct7D == 7'b0000000); // most R-type instructions + assign Funct7b5D = (Funct7D == 7'b0100000); // srai, sub assign Funct7ShiftZeroD = (`XLEN==64) ? (Funct7D[6:1] == 6'b000000) : Funct7ZeroD; assign Funct7Shiftb5D = (`XLEN==64) ? (Funct7D[6:1] == 6'b010000) : Funct7b5D; - assign IShiftD = (Funct3D == 3'b001 & Funct7ShiftZeroD) | (Funct3D == 3'b101 & (Funct7ShiftZeroD | Funct7Shiftb5D)); // slli, srli, srai, or w forms - assign INoShiftD = ((Funct3D != 3'b001) & (Funct3D != 3'b101)); - assign IFunctD = IShiftD | INoShiftD; - assign RFunctD = ((Funct3D == 3'b000 | Funct3D == 3'b101) & Funct7b5D) | Funct7ZeroD; - assign MFunctD = (Funct7D == 7'b0000001) & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv - assign LFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 | Funct3D == 3'b100 | Funct3D == 3'b101 | - ((`XLEN == 64) & (Funct3D == 3'b011 | Funct3D == 3'b110)); - assign SFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 | - ((`XLEN == 64) & (Funct3D == 3'b011)); - assign BFunctD = (Funct3D[2:1] != 2'b01); // legal branches - assign JFunctD = (Funct3D == 3'b000); + assign IShiftD = (Funct3D == 3'b001 & Funct7ShiftZeroD) | (Funct3D == 3'b101 & (Funct7ShiftZeroD | Funct7Shiftb5D)); // slli, srli, srai, or w forms + assign INoShiftD = ((Funct3D != 3'b001) & (Funct3D != 3'b101)); + assign IFunctD = IShiftD | INoShiftD; + assign RFunctD = ((Funct3D == 3'b000 | Funct3D == 3'b101) & Funct7b5D) | Funct7ZeroD; + assign MFunctD = (Funct7D == 7'b0000001) & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv + assign LFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 | Funct3D == 3'b100 | Funct3D == 3'b101 | + ((`XLEN == 64) & (Funct3D == 3'b011 | Funct3D == 3'b110)); + assign SFunctD = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b010 | + ((`XLEN == 64) & (Funct3D == 3'b011)); + assign BFunctD = (Funct3D[2:1] != 2'b01); // legal branches + assign JFunctD = (Funct3D == 3'b000); end else begin:legalcheck2 - assign IFunctD = 1; // Don't bother to separate out shift decoding - assign RFunctD = ~Funct7D[0]; // Not a multiply - assign MFunctD = Funct7D[0] & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv - assign LFunctD = 1; // don't bother to check Funct3 for loads - assign SFunctD = 1; // don't bother to check Funct3 for stores - assign BFunctD = 1; // don't bother to check Funct3 for branches - assign JFunctD = 1; // don't bother to check Funct3 for jumps + assign IFunctD = 1; // Don't bother to separate out shift decoding + assign RFunctD = ~Funct7D[0]; // Not a multiply + assign MFunctD = Funct7D[0] & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])); // muldiv + assign LFunctD = 1; // don't bother to check Funct3 for loads + assign SFunctD = 1; // don't bother to check Funct3 for stores + assign BFunctD = 1; // don't bother to check Funct3 for branches + assign JFunctD = 1; // don't bother to check Funct3 for jumps end // Main Instruction Decoder @@ -167,7 +182,7 @@ module controller( 7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_1; // flw - only legal if FP supported 7'b0001111: if (`ZIFENCEI_SUPPORTED) ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence - else + else ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_0; // fence treated as nop 7'b0010011: if (IFunctD) ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU @@ -213,24 +228,61 @@ module controller( // Squash control signals if coming from an illegal compressed instruction // On RV32E, can't write to upper 16 registers. Checking reads to upper 16 is more costly so disregard them. assign IllegalERegAdrD = `E_SUPPORTED & `ZICSR_SUPPORTED & ControlsD[`CTRLW-1] & InstrD[11]; - assign IllegalBaseInstrD = ControlsD[0] | IllegalERegAdrD; - assign {RegWriteD, ImmSrcD, ALUSrcAD, ALUSrcBD, MemRWD, - ResultSrcD, BranchD, ALUOpD, JumpD, ALUResultSrcD, W64D, CSRReadD, + //assign IllegalBaseInstrD = 1'b0; + assign {BaseRegWriteD, ImmSrcD, ALUSrcAD, BaseALUSrcBD, MemRWD, + ResultSrcD, BranchD, ALUOpD, JumpD, ALUResultSrcD, BaseW64D, CSRReadD, PrivilegedD, FenceXD, MDUD, AtomicD, unused} = IllegalIEUFPUInstrD ? `CTRLW'b0 : ControlsD; - assign CSRZeroSrcD = InstrD[14] ? (InstrD[19:15] == 0) : (Rs1D == 0); // Is a CSR instruction using zero as the source? assign CSRWriteD = CSRReadD & !(CSRZeroSrcD & InstrD[13]); // Don't write if setting or clearing zeros assign SFenceVmaD = PrivilegedD & (InstrD[31:25] == 7'b0001001); assign FenceD = SFenceVmaD | FenceXD; // possible sfence.vma or fence.i - + // ALU Decoding is lazy, only using func7[5] to distinguish add/sub and srl/sra - assign sltD = (Funct3D == 3'b010); - assign sltuD = (Funct3D == 3'b011); + assign sltuD = (Funct3D == 3'b011); assign subD = (Funct3D == 3'b000 & Funct7D[5] & OpD[5]); // OpD[5] needed to distinguish sub from addi assign sraD = (Funct3D == 3'b101 & Funct7D[5]); - assign SubArithD = ALUOpD & (subD | sraD | sltD | sltuD); // TRUE for R-type subtracts and sra, slt, sltu - assign ALUControlD = {W64D, SubArithD, ALUOpD}; + assign BaseSubArithD = ALUOpD & (subD | sraD | sltD | sltuD); + + // bit manipulation Configuration Block + if (`ZBS_SUPPORTED | `ZBA_SUPPORTED | `ZBB_SUPPORTED | `ZBC_SUPPORTED) begin: bitmanipi //change the conditional expression to OR any Z supported flags + logic IllegalBitmanipInstrD; // Unrecognized B instruction + logic BRegWriteD; // Indicates if it is a R type BMU instruction in decode stage + logic BW64D; // Indicates if it is a W type BMU instruction in decode stage + logic BSubArithD; // TRUE for BMU ext, clr, andn, orn, xnor + logic BALUSrcBD; // BMU alu src select signal + + bmuctrl bmuctrl(.clk, .reset, .StallD, .FlushD, .InstrD, .ALUOpD, .BSelectD, .ZBBSelectD, + .BRegWriteD, .BALUSrcBD, .BW64D, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE, + .ALUSelectD, .BSelectE, .ZBBSelectE, .BRegWriteE, .BComparatorSignedE, .BALUControlE); + if (`ZBA_SUPPORTED) begin + // ALU Decoding is more comprehensive when ZBA is supported. slt and slti conflicts with sh1add, sh1add.uw + assign sltD = (Funct3D == 3'b010 & (~(Funct7D[4]) | ~OpD[5])) ; + end else assign sltD = (Funct3D == 3'b010); + + // Combine base and bit manipulation signals + assign IllegalBaseInstrD = (ControlsD[0] & IllegalBitmanipInstrD) | IllegalERegAdrD ; + assign RegWriteD = BaseRegWriteD | BRegWriteD; + assign W64D = BaseW64D | BW64D; + assign ALUSrcBD = BaseALUSrcBD | BALUSrcBD; + assign SubArithD = BaseSubArithD | BSubArithD; // TRUE If BMU or R-type instruction involves inverted operand + + end else begin: bitmanipi + assign ALUSelectD = ALUOpD ? Funct3D : 3'b000; // add for address generation when not doing ALU operation + assign sltD = (Funct3D == 3'b010); + assign IllegalBaseInstrD = ControlsD[0] | IllegalERegAdrD ; + assign RegWriteD = BaseRegWriteD; + assign W64D = BaseW64D; + assign ALUSrcBD = BaseALUSrcBD; + assign SubArithD = BaseSubArithD; // TRUE If B-type or R-type instruction involves inverted operand + + // tie off unused bit manipulation signals + assign BSelectE = 2'b00; + assign BSelectD = 2'b00; + assign ZBBSelectE = 3'b000; + assign BComparatorSignedE = 1'b0; + assign BALUControlE = 3'b0; + end // Fences // Ordinary fence is presently a nop @@ -249,14 +301,15 @@ module controller( flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD); // Execute stage pipeline control register and logic - flopenrc #(28) controlregE(clk, reset, FlushE, ~StallE, - {RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, InstrValidD}, - {IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE}); + flopenrc #(29) controlregE(clk, reset, FlushE, ~StallE, + {ALUSelectD, RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUSrcAD, ALUSrcBD, ALUResultSrcD, CSRReadD, CSRWriteD, PrivilegedD, Funct3D, W64D, SubArithD, MDUD, AtomicD, InvalidateICacheD, FlushDCacheD, FenceD, InstrValidD}, + {ALUSelectE, IEURegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUSrcAE, ALUSrcBE, ALUResultSrcE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, W64E, SubArithE, MDUE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE}); // Branch Logic // The comparator handles both signed and unsigned branches using BranchSignedE // Hence, only eq and lt flags are needed - assign BranchSignedE = ~(Funct3E[2:1] == 2'b11); + // We also want comparator to handle signed comparison on a max/min bitmanip instruction + assign BranchSignedE = (~(Funct3E[2:1] == 2'b11) & BranchE) | BComparatorSignedE; assign {eqE, ltE} = FlagsE; mux2 #(1) branchflagmux(eqE, ltE, Funct3E[2], BranchFlagE); assign BranchTakenE = BranchFlagE ^ Funct3E[0]; diff --git a/src/ieu/datapath.sv b/src/ieu/datapath.sv index 60d43de92..a48b39402 100644 --- a/src/ieu/datapath.sv +++ b/src/ieu/datapath.sv @@ -40,11 +40,16 @@ module datapath ( input logic [2:0] Funct3E, // Funct3 field of instruction in Execute stage input logic StallE, FlushE, // Stall, flush Execute stage input logic [1:0] ForwardAE, ForwardBE, // Forward ALU operands from later stages - input logic [2:0] ALUControlE, // Indicate operation ALU performs + input logic W64E, // W64-type instruction + input logic SubArithE, // Subtraction or arithmetic shift input logic ALUSrcAE, ALUSrcBE, // ALU operands input logic ALUResultSrcE, // Selects result to pass on to Memory stage + input logic [2:0] ALUSelectE, // ALU mux select signal input logic JumpE, // Is a jump (j) instruction input logic BranchSignedE, // Branch comparison operands are signed (if it's a branch) + input logic [1:0] BSelectE, // One hot encoding of ZBA_ZBB_ZBC_ZBS instruction + input logic [2:0] ZBBSelectE, // ZBB mux select signal + input logic [2:0] BALUControlE, // ALU Control signals for B instructions in Execute Stage output logic [1:0] FlagsE, // Comparison flags ({eq, lt}) output logic [`XLEN-1:0] IEUAdrE, // Address computed by ALU output logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU sources before the mux chooses between them and PCE to put in srcA/B @@ -56,7 +61,7 @@ module datapath ( output logic [`XLEN-1:0] WriteDataM, // Write data in Memory stage // Writeback stage signals input logic StallW, FlushW, // Stall, flush Writeback stage - input logic RegWriteW, IntDivW, // Write register file, integer divide instruction + input logic RegWriteW, IntDivW, // Write register file, integer divide instruction input logic SquashSCW, // Squash a store conditional when a conflict arose input logic [2:0] ResultSrcW, // Select source of result to write back to register file input logic [`XLEN-1:0] FCvtIntResW, // FPU convert fp to integer result @@ -103,20 +108,20 @@ module datapath ( flopenrc #(5) Rs1EReg(clk, reset, FlushE, ~StallE, Rs1D, Rs1E); flopenrc #(5) Rs2EReg(clk, reset, FlushE, ~StallE, Rs2D, Rs2E); flopenrc #(5) RdEReg(clk, reset, FlushE, ~StallE, RdD, RdE); - + mux3 #(`XLEN) faemux(R1E, ResultW, IFResultM, ForwardAE, ForwardedSrcAE); mux3 #(`XLEN) fbemux(R2E, ResultW, IFResultM, ForwardBE, ForwardedSrcBE); comparator #(`XLEN) comp(ForwardedSrcAE, ForwardedSrcBE, BranchSignedE, FlagsE); mux2 #(`XLEN) srcamux(ForwardedSrcAE, PCE, ALUSrcAE, SrcAE); mux2 #(`XLEN) srcbmux(ForwardedSrcBE, ImmExtE, ALUSrcBE, SrcBE); - alu #(`XLEN) alu(SrcAE, SrcBE, ALUControlE, Funct3E, ALUResultE, IEUAdrE); + alu #(`XLEN) alu(SrcAE, SrcBE, W64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, FlagsE, BALUControlE, ALUResultE, IEUAdrE); mux2 #(`XLEN) altresultmux(ImmExtE, PCLinkE, JumpE, AltResultE); mux2 #(`XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE); // Memory stage pipeline register flopenrc #(`XLEN) SrcAMReg(clk, reset, FlushM, ~StallM, SrcAE, SrcAM); flopenrc #(`XLEN) IEUResultMReg(clk, reset, FlushM, ~StallM, IEUResultE, IEUResultM); - flopenrc #(5) RdMReg(clk, reset, FlushM, ~StallM, RdE, RdM); + flopenrc #(5) RdMReg(clk, reset, FlushM, ~StallM, RdE, RdM); flopenrc #(`XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, ForwardedSrcBE, WriteDataM); // Writeback stage pipeline register and logic @@ -141,4 +146,4 @@ module datapath ( // handle Store Conditional result if atomic extension supported if (`A_SUPPORTED) assign SCResultW = {{(`XLEN-1){1'b0}}, SquashSCW}; else assign SCResultW = 0; -endmodule +endmodule \ No newline at end of file diff --git a/src/ieu/forward.sv b/src/ieu/forward.sv index 8bfaa51c6..62cc5ea4f 100644 --- a/src/ieu/forward.sv +++ b/src/ieu/forward.sv @@ -34,7 +34,7 @@ module forward( input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW, // Source and destination registers input logic MemReadE, MDUE, CSRReadE, // Execute stage instruction is a load (MemReadE), divide (MDUE), or CSR read (CSRReadE) input logic RegWriteM, RegWriteW, // Instruction in Memory or Writeback stage writes register file - input logic FCvtIntE, // FPU convert float to int + input logic FCvtIntE, // FPU convert float to int input logic SCE, // Store Conditional instruction // Forwarding controls output logic [1:0] ForwardAE, ForwardBE, // Select signals for forwarding multiplexers diff --git a/src/ieu/ieu.sv b/src/ieu/ieu.sv index de99aebb4..d5b3e8f40 100644 --- a/src/ieu/ieu.sv +++ b/src/ieu/ieu.sv @@ -29,27 +29,27 @@ `include "wally-config.vh" module ieu ( - input logic clk, reset, + input logic clk, reset, // Decode stage signals - input logic [31:0] InstrD, // Instruction - input logic IllegalIEUFPUInstrD, // Illegal instruction - output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers + input logic [31:0] InstrD, // Instruction + input logic IllegalIEUFPUInstrD, // Illegal instruction + output logic IllegalBaseInstrD, // Illegal I-type instruction, or illegal RV32 access to upper 16 registers // Execute stage signals input logic [`XLEN-1:0] PCE, // PC input logic [`XLEN-1:0] PCLinkE, // PC + 4 - output logic PCSrcE, // Select next PC (between PC+4 and IEUAdrE) - input logic FWriteIntE, FCvtIntE, // FPU writes to integer register file, FPU converts float to int + output logic PCSrcE, // Select next PC (between PC+4 and IEUAdrE) + input logic FWriteIntE, FCvtIntE, // FPU writes to integer register file, FPU converts float to int output logic [`XLEN-1:0] IEUAdrE, // Memory address - output logic IntDivE, W64E, // Integer divide, RV64 W-type instruction - output logic [2:0] Funct3E, // Funct3 instruction field + output logic IntDivE, W64E, // Integer divide, RV64 W-type instruction + output logic [2:0] Funct3E, // Funct3 instruction field output logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // ALU src inputs before the mux choosing between them and PCE to put in srcA/B output logic [4:0] RdE, // Destination register // Memory stage signals - input logic SquashSCW, // Squash store conditional, from LSU - output logic [1:0] MemRWM, // Read/write control goes to LSU - output logic [1:0] AtomicM, // Atomic control goes to LSU + input logic SquashSCW, // Squash store conditional, from LSU + output logic [1:0] MemRWM, // Read/write control goes to LSU + output logic [1:0] AtomicM, // Atomic control goes to LSU output logic [`XLEN-1:0] WriteDataM, // Write data to LSU - output logic [2:0] Funct3M, // Funct3 (size and signedness) to LSU + output logic [2:0] Funct3M, // Funct3 (size and signedness) to LSU output logic [`XLEN-1:0] SrcAM, // ALU SrcA to Privileged unit and FPU output logic [4:0] RdM, // Destination register input logic [`XLEN-1:0] FIntResM, // Integer result from FPU (fmv, fclass, fcmp) @@ -66,23 +66,27 @@ module ieu ( output logic [4:0] RdW, // Destination register input logic [`XLEN-1:0] ReadDataW, // LSU's read data // Hazard unit signals - input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit - input logic FlushD, FlushE, FlushM, FlushW, // Flush signals - output logic FCvtIntStallD, LoadStallD, // Stall causes from IEU to hazard unit + input logic StallD, StallE, StallM, StallW, // Stall signals from hazard unit + input logic FlushD, FlushE, FlushM, FlushW, // Flush signals + output logic FCvtIntStallD, LoadStallD, // Stall causes from IEU to hazard unit output logic MDUStallD, CSRRdStallD, StoreStallD, - output logic CSRReadM, CSRWriteM, PrivilegedM,// CSR read, CSR write, is privileged instruction - output logic CSRWriteFenceM // CSR write or fence instruction needs to flush subsequent instructions + output logic CSRReadM, CSRWriteM, PrivilegedM,// CSR read, CSR write, is privileged instruction + output logic CSRWriteFenceM // CSR write or fence instruction needs to flush subsequent instructions ); logic [2:0] ImmSrcD; // Select type of immediate extension logic [1:0] FlagsE; // Comparison flags ({eq, lt}) - logic [2:0] ALUControlE; // ALU control indicates function to perform logic ALUSrcAE, ALUSrcBE; // ALU source operands logic [2:0] ResultSrcW; // Selects result in Writeback stage logic ALUResultSrcE; // Selects ALU result to pass on to Memory stage + logic [2:0] ALUSelectE; // ALU select mux signal logic SCE; // Store Conditional instruction logic FWriteIntM; // FPU writing to integer register file logic IntDivW; // Integer divide instruction + logic [1:0] BSelectE; // Indicates if ZBA_ZBB_ZBC_ZBS instruction in one-hot encoding + logic [2:0] ZBBSelectE; // ZBB Result Select Signal in Execute Stage + logic [2:0] BALUControlE; // ALU Control signals for B instructions in Execute Stage + logic SubArithE; // Subtraction or arithmetic shift // Forwarding signals logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E; // Source and destination registers @@ -92,19 +96,19 @@ module ieu ( logic BranchSignedE; // Branch does signed comparison on operands logic MDUE; // Multiply/divide instruction - controller c( +controller c( .clk, .reset, .StallD, .FlushD, .InstrD, .ImmSrcD, .IllegalIEUFPUInstrD, .IllegalBaseInstrD, .StallE, .FlushE, .FlagsE, .FWriteIntE, - .PCSrcE, .ALUControlE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .MemReadE, .CSRReadE, - .Funct3E, .IntDivE, .MDUE, .W64E, .BranchD, .BranchE, .JumpD, .JumpE, .SCE, .BranchSignedE, .StallM, .FlushM, .MemRWM, + .PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .MemReadE, .CSRReadE, + .Funct3E, .IntDivE, .MDUE, .W64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE, .SCE, .BranchSignedE, .BSelectE, .ZBBSelectE, .BALUControlE, .StallM, .FlushM, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M, .RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM, .StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .InvalidateICacheM, .StoreStallD); datapath dp( - .clk, .reset, .ImmSrcD, .InstrD, .StallE, .FlushE, .ForwardAE, .ForwardBE, - .ALUControlE, .Funct3E, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .JumpE, .BranchSignedE, - .PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE, + .clk, .reset, .ImmSrcD, .InstrD, .StallE, .FlushE, .ForwardAE, .ForwardBE, .W64E, .SubArithE, + .Funct3E, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .JumpE, .BranchSignedE, + .PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE, .BSelectE, .ZBBSelectE, .BALUControlE, .StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM, .FCvtIntW, .StallW, .FlushW, .RegWriteW, .IntDivW, .SquashSCW, .ResultSrcW, .ReadDataW, .FCvtIntResW, .CSRReadValW, .MDUResultW, .FIntDivResultW, .Rs1D, .Rs2D, .Rs1E, .Rs2E, .RdE, .RdM, .RdW); diff --git a/src/ieu/regfile.sv b/src/ieu/regfile.sv index cc0439c08..a4ee1cc3e 100644 --- a/src/ieu/regfile.sv +++ b/src/ieu/regfile.sv @@ -52,7 +52,7 @@ module regfile ( always_ff @(negedge clk) if (reset) for(i=1; i // Created: 9 January 2021 -// Modified: +// Modified: 6 February 2023 // // Purpose: RISC-V 32/64 bit shifter // @@ -30,48 +30,59 @@ `include "wally-config.vh" module shifter ( - input logic [`XLEN-1:0] A, // Source - input logic [`LOG_XLEN-1:0] Amt, // Shift amount - input logic Right, Arith, W64, // Shift right, arithmetic, RV64 W-type shift - output logic [`XLEN-1:0] Y); // Shifted result + input logic [`XLEN-1:0] A, // shift Source + input logic [`LOG_XLEN-1:0] Amt, // Shift amount + input logic Right, Rotate, W64, SubArith, // Shift right, rotate, W64-type operation, arithmetic shift + output logic [`XLEN-1:0] Y); // Shifted result - logic [2*`XLEN-2:0] z, zshift; // Input to funnel shifter, shifted amount before truncated to 32 or 64 bits - logic [`LOG_XLEN-1:0] amttrunc, offset; // Shift amount adjusted for RV64, right-shift amount + logic [2*`XLEN-2:0] Z, ZShift; // Input to funnel shifter, shifted amount before truncated to 32 or 64 bits + logic [`LOG_XLEN-1:0] TruncAmt, Offset; // Shift amount adjusted for RV64, right-shift amount + logic Sign; // Sign bit for sign extension - // Handle left and right shifts with a funnel shifter. - // For RV32, only 32-bit shifts are needed. - // For RV64, 32- and 64-bit shifts are needed, with sign extension. - - // Funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong) - if (`XLEN==32) begin:shifter // RV32 - always_comb // funnel mux - if (Right) - if (Arith) z = {{31{A[31]}}, A}; - else z = {31'b0, A}; - else z = {A, 31'b0}; - assign amttrunc = Amt; // shift amount - end else begin:shifter // RV64 - always_comb // funnel mux - if (W64) begin // 32-bit shifts - if (Right) - if (Arith) z = {64'b0, {31{A[31]}}, A[31:0]}; - else z = {95'b0, A[31:0]}; - else z = {32'b0, A[31:0], 63'b0}; - end else begin - if (Right) - if (Arith) z = {{63{A[63]}}, A}; - else z = {63'b0, A}; - else z = {A, 63'b0}; - end - assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32- or 64-bit shift + assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension + if (`XLEN==32) begin // rv32 + if (`ZBB_SUPPORTED) begin: rotfunnel32 //rv32 shifter with rotates + always_comb // funnel mux + case({Right, Rotate}) + 2'b00: Z = {A[31:0], 31'b0}; + 2'b01: Z = {A[31:0], A[31:1]}; + 2'b10: Z = {{31{Sign}}, A[31:0]}; + 2'b11: Z = {A[30:0], A[31:0]}; + endcase + end else begin: norotfunnel32 //rv32 shifter without rotates + always_comb // funnel mux + if (Right) Z = {{31{Sign}}, A[31:0]}; + else Z = {A[31:0], 31'b0}; + end + assign TruncAmt = Amt; // shift amount + end else begin // rv64 + logic [`XLEN-1:0] A64; + mux3 #(64) extendmux({{32{1'b0}}, A[31:0]}, {{32{A[31]}}, A[31:0]}, A, {~W64, SubArith}, A64); // bottom 32 bits are always A[31:0], so effectively a 32-bit upper mux + if (`ZBB_SUPPORTED) begin: rotfunnel64 // rv64 shifter with rotates + // shifter rotate source select mux + logic [`XLEN-1:0] RotA; // rotate source + mux2 #(`XLEN) rotmux(A, {A[31:0], A[31:0]}, W64, RotA); // W64 rotatons + always_comb // funnel mux + case ({Right, Rotate}) + 2'b00: Z = {A64[63:0],{63'b0}}; + 2'b01: Z = {RotA[63:0], RotA[63:1]}; + 2'b10: Z = {{63{Sign}}, A64[63:0]}; + 2'b11: Z = {RotA[62:0], RotA[63:0]}; + endcase + end else begin: norotfunnel64 // rv64 shifter without rotates + always_comb // funnel mux + if (Right) Z = {{63{Sign}}, A64[63:0]}; + else Z = {A64[63:0], {63'b0}}; + end + assign TruncAmt = W64 ? {1'b0, Amt[4:0]} : Amt; // 32- or 64-bit shift end - + // Opposite offset for right shifts - assign offset = Right ? amttrunc : ~amttrunc; + assign Offset = Right ? TruncAmt : ~TruncAmt; // Funnel operation - assign zshift = z >> offset; - assign Y = zshift[`XLEN-1:0]; + assign ZShift = Z >> Offset; + assign Y = ZShift[`XLEN-1:0]; endmodule diff --git a/src/ifu/bpred/RASPredictor.sv b/src/ifu/bpred/RASPredictor.sv index d5fd0c019..f1a39f75b 100644 --- a/src/ifu/bpred/RASPredictor.sv +++ b/src/ifu/bpred/RASPredictor.sv @@ -31,10 +31,10 @@ module RASPredictor #(parameter int StackSize = 16 )( input logic clk, - input logic reset, - input logic StallF, StallD, StallE, StallM, FlushD, FlushE, FlushM, - input logic BPReturnWrongD, // Prediction class is wrong - input logic ReturnD, + input logic reset, + input logic StallF, StallD, StallE, StallM, FlushD, FlushE, FlushM, + input logic BPReturnWrongD, // Prediction class is wrong + input logic ReturnD, input logic ReturnE, CallE, // Instr class input logic BPReturnF, input logic [`XLEN-1:0] PCLinkE, // PC of instruction after a call @@ -48,14 +48,14 @@ module RASPredictor #(parameter int StackSize = 16 )( logic [StackSize-1:0] [`XLEN-1:0] memory; integer index; - logic PopF; - logic PushE; - logic RepairD; - logic IncrRepairD, DecRepairD; + logic PopF; + logic PushE; + logic RepairD; + logic IncrRepairD, DecRepairD; - logic DecrementPtr; - logic FlushedReturnDE; - logic WrongPredReturnD; + logic DecrementPtr; + logic FlushedReturnDE; + logic WrongPredReturnD; assign PopF = BPReturnF & ~StallD & ~FlushD; @@ -85,7 +85,7 @@ module RASPredictor #(parameter int StackSize = 16 )( always_ff @ (posedge clk) begin if(reset) begin for(index=0; index $@.objdump +%.elf.objdump: %.elf + +# Change many things if bit width isn't 64 +%.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile + riscv64-unknown-elf-gcc -g -o $@ -march=rv64gc_zba_zbb_zbc_zbs -mabi=lp64 -mcmodel=medany \ + -nostartfiles -T../../examples/link/link.ld $< + riscv64-unknown-elf-objdump -S $@ > $@.objdump + riscv64-unknown-elf-elf2hex --bit-width 64 --input $@ --output $@.memfile + extractFunctionRadix.sh $@.objdump sim: %.elf spike +signature=%.signature.output +signature-granularity=8 %.elf @@ -15,7 +29,7 @@ sim: %.elf echo "Signature matches! Success!" clean: - rm -f *.elf *.objdump *.signature.output + rm -f *.elf *.objdump *.signature.output *.addr *.lab *.memfile diff --git a/tests/coverage/badinstr.S b/tests/coverage/csrwrites.S similarity index 65% rename from tests/coverage/badinstr.S rename to tests/coverage/csrwrites.S index e77f5c980..76e310e5f 100644 --- a/tests/coverage/badinstr.S +++ b/tests/coverage/csrwrites.S @@ -1,9 +1,9 @@ /////////////////////////////////////////// -// badinstr.S +// csrwrites.S // // Written: David_Harris@hmc.edu 21 March 2023 // -// Purpose: Test illegal instruction opcodes +// Purpose: Test writes to CSRs // // A component of the CORE-V-WALLY configurable RISC-V project. // @@ -27,22 +27,9 @@ #include "WALLY-init-lib.h" main: - .word 0x00000033 // legal R-type instruction - .word 0x80000033 // illegal R-type instruction - .word 0x00007003 // illegal Load instruction - .word 0x00000000 // illegal instruction + csrrw t0, stimecmp, t0 + csrrw t0, satp, t0 + csrrw t0, stvec, t0 + csrrw t0, sscratch, t0 j done -/* -main: - # Change to user mode - li a0, 0 # a0 = 0: argument to enter user mode - ecall # System call to enter user mode - - # Wait for timer interrupts - li t0, 0x1000 # loop counter start value -loop: - addi t0, t0, -1 # decrement counter - bne t0, zero, loop # and repeat until zero - -*/ \ No newline at end of file diff --git a/tests/coverage/ebu.S b/tests/coverage/ebu.S new file mode 100644 index 000000000..8c69f9d11 --- /dev/null +++ b/tests/coverage/ebu.S @@ -0,0 +1,45 @@ +/////////////////////////////////////////// +// ebu.S +// +// Written: David_Harris@hmc.edu 23 March 2023 +// +// Purpose: Test coverage for EBU +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work 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. +//////////////////////////////////////////////////////////////////////////////////////////////// + +// load code to initalize stack, handle interrupts, terminate +#include "WALLY-init-lib.h" + +main: + + # Test clz with all bits being 0 + li t0, 0 + clz t1, t0 + li t0, -1 + clz t1, t0 + li t0, 1 + clz t1, t0 + + # Test forwarding from store conditional + lr.w t0, 0(a0) + sc.w t0, a1, 0(a0) + addi t0, t0, 1 + + j done + diff --git a/tests/coverage/ieu.S b/tests/coverage/ieu.S new file mode 100644 index 000000000..e1b239371 --- /dev/null +++ b/tests/coverage/ieu.S @@ -0,0 +1,65 @@ +/////////////////////////////////////////// +// ieu.S +// +// Written: David_Harris@hmc.edu 21 March 2023 +// +// Purpose: Test coverage for IEU +// +// A component of the CORE-V-WALLY configurable RISC-V project. +// +// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work 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. +//////////////////////////////////////////////////////////////////////////////////////////////// + +// load code to initalize stack, handle interrupts, terminate +#include "WALLY-init-lib.h" + +main: + + # Test clz with all bits being 0 + li t0, 0 + clz t1, t0 + li t0, -1 + clz t1, t0 + li t0, 1 + clz t1, t0 + + # Test forwarding from store conditional + lr.w t0, 0(a0) + sc.w t0, a1, 0(a0) + addi t0, t0, 1 + + # Test illegal instructions are detected + .word 0x80000033 // illegal R-type instruction + .word 0x00007003 // illegal Load instruction + .word 0x80005013 // illegal I-type instruction: srli: op = 0010011, funct3 = 101, funct7 = 1000000 + .word 0x00000000 // illegal instruction + .word 0x0000701B // Illegal IW instruction + .word 0x00004023 // Illegal store instruction + .word 0x0400003B // Illegal RW or MulDivW instruction + .word 0x00007067 // Illegal JALR instruction + .word 0x00002063 // Illegal branch instruction + .word 0x60F01013 // Illegal BMU sign extend / count instruction + .word 0x60801013 // Illegal BMU sign extend / count instruction + .word 0x60301013 // Illegal BMU sign extend / count instruction + .word 0x6BF05013 // Illegal BMU similar to rev8 + .word 0x69805013 // Illegal BMU similar to rev8 + .word 0x28F05013 // Illegal BMU similar to or.c + .word 0x60F0101B // Illegal BMU similar to count word + .word 0x6080101B // Illegal BMU similar to count word + .word 0x6030101B // Illegal BMU similar to count word + + j done + diff --git a/tests/riscof/Makefile b/tests/riscof/Makefile index d963e4f0d..24b499d11 100644 --- a/tests/riscof/Makefile +++ b/tests/riscof/Makefile @@ -9,7 +9,7 @@ current_dir = $(shell pwd) #XLEN ?= 64 #all: root wally32 wally64 -all: root arch32 wally32 wally32e arch64 wally64 +all: root arch32 wally32 wally32e arch64 wally64 root: mkdir -p $(work_dir) diff --git a/tests/riscof/spike/riscof_spike.py b/tests/riscof/spike/riscof_spike.py index d7d65c0b3..308d55f28 100644 --- a/tests/riscof/spike/riscof_spike.py +++ b/tests/riscof/spike/riscof_spike.py @@ -105,6 +105,14 @@ class spike(pluginTemplate): self.isa += 'd' if "C" in ispec["ISA"]: self.isa += 'c' + if "Zba" in ispec["ISA"]: + self.isa += '_Zba' + if "Zbb" in ispec["ISA"]: + self.isa += '_Zbb' + if "Zbc" in ispec["ISA"]: + self.isa += '_Zbc' + if "Zbs" in ispec["ISA"]: + self.isa += '_Zbs' #TODO: The following assumes you are using the riscv-gcc toolchain. If # not please change appropriately diff --git a/tests/riscof/spike/spike_rv32gc_isa.yaml b/tests/riscof/spike/spike_rv32gc_isa.yaml index 478bbe56d..3438e17a0 100644 --- a/tests/riscof/spike/spike_rv32gc_isa.yaml +++ b/tests/riscof/spike/spike_rv32gc_isa.yaml @@ -1,7 +1,6 @@ hart_ids: [0] hart0: - ISA: RV32IMAFDCZicsr_Zifencei -# ISA: RV32IMAFDCZicsr_Zifencei_Zba_Zbb_Zbc_Zbs + ISA: RV32IMAFDCZicsr_Zifencei_Zba_Zbb_Zbc_Zbs physical_addr_sz: 32 User_Spec_Version: '2.3' supported_xlen: [32] diff --git a/tests/riscof/spike/spike_rv64gc_isa.yaml b/tests/riscof/spike/spike_rv64gc_isa.yaml index 8037ad6f6..a8837ac76 100644 --- a/tests/riscof/spike/spike_rv64gc_isa.yaml +++ b/tests/riscof/spike/spike_rv64gc_isa.yaml @@ -1,7 +1,6 @@ hart_ids: [0] hart0: - ISA: RV64IMAFDCSUZicsr_Zifencei -# ISA: RV64IMAFDCSUZicsr_Zifencei_Zba_Zbb_Zbc_Zbs + ISA: RV64IMAFDCSUZicsr_Zifencei_Zba_Zbb_Zbc_Zbs physical_addr_sz: 56 User_Spec_Version: '2.3' supported_xlen: [64] diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-s-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-s-01.reference_output index 089aeba9d..5ee52bee5 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-s-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-trap-s-01.reference_output @@ -29,10 +29,6 @@ 00000008 # scause from U mode ecall 00000000 # stval of ecall (*** defined to be zero for now) 00000000 # masked out mstatus.mpp = 0 (from U mode), mstatus.MPIE = 0, and mstatus.MIE = 0 -0007ec01 # value to indicate successful vectoring on s soft interrupt -80000001 # scause value from s soft interrupt -00000000 # stval for ssoft interrupt (0x0) -00000800 # masked out mstatus.mpp = 1, mstatus.MPIE = 0, and mstatus.MIE = 0 0007ec03 # value to indicate successful vectoring on m soft interrupt 80000003 # scause value from m soft interrupt 00000000 # stval for msoft interrupt (0x0) diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-trap-s-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-trap-s-01.S index 4b1e2afa4..85758b101 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-trap-s-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-trap-s-01.S @@ -57,12 +57,12 @@ GOTO_U_MODE // Causes S mode ecall GOTO_S_MODE // Causes U mode ecall -// some interrupts excluded becaus writing MIP is illegal from S mode -jal cause_s_soft_interrupt +// some interrupts excluded because writing MIP is illegal from S mode and writing SIP is only possible when delegated, which is tested below (priv spec 3.1.9) +//jal cause_s_soft_interrupt jal cause_m_soft_interrupt jal cause_m_time_interrupt li a3, 0x40 // this interrupt involves a time loop waiting for the interrupt to go off. -// since interrupts are not always enabled, +// since interrupts are not always enabled, we need to make it stop after a certain number of loops, which is the number in a3 jal cause_s_ext_interrupt_GPIO li a3, 0x40 jal cause_m_ext_interrupt diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-s-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-s-01.reference_output index fe559dfb7..cdc883697 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-s-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-trap-s-01.reference_output @@ -60,14 +60,6 @@ 00000000 00000000 # masked out mstatus.mpp = 0 (from U mode), mstatus.MPIE = 0, and mstatus.MIE = 0 00000000 -0007ec01 # value to indicate successful vectoring on s soft interrupt -00000000 -00000001 # scause value from s soft interrupt -80000000 -00000000 # stval for ssoft interrupt (0x0) -00000000 -00000800 # masked out mstatus.mpp = 1, mstatus.MPIE = 0, and mstatus.MIE = 0 -00000000 0007ec03 # value to indicate successful vectoring on m soft interrupt 00000000 00000003 # scause value from m soft interrupt diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-TEST-LIB-64.h b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-TEST-LIB-64.h index 00e235f35..85b5ab8c4 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-TEST-LIB-64.h +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-TEST-LIB-64.h @@ -162,6 +162,11 @@ cause_s_soft_interrupt: csrs sip, t3 // set supervisor software interrupt pending. SIP is a subset of MIP, so writing this should also change MIP. ret +cause_s_soft_from_m_interrupt: + li t3, 0x2 + csrs mip, t3 // set supervisor software interrupt pending. SIP is a subset of MIP, so writing this should also change MIP. + ret + cause_m_ext_interrupt: // ========== Configure PLIC ========== li a3, 0x40 diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-stvec-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-stvec-01.S index 4a4bdb768..05ecf515a 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-stvec-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-stvec-01.S @@ -49,7 +49,7 @@ jal cause_s_soft_interrupt // only cause one interrupt since we just want to tes GOTO_M_MODE -jal cause_s_soft_interrupt // set software interrupt pending without it firing so we can make it fire in U mode +jal cause_s_soft_from_m_interrupt // set software interrupt pending without it firing so we can make it fire in U mode GOTO_U_MODE // Should cause software interrupt to fire off. diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-trap-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-trap-01.S index 41d9cd072..b44b6440d 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-trap-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-trap-01.S @@ -50,7 +50,7 @@ GOTO_S_MODE // Causes U mode ecall GOTO_M_MODE // Causes S mode ecall -jal cause_s_soft_interrupt +jal cause_s_soft_from_m_interrupt jal cause_m_soft_interrupt jal cause_s_time_interrupt jal cause_m_time_interrupt @@ -72,7 +72,7 @@ jal cause_store_addr_misaligned jal cause_store_acc jal cause_ecall // M mode ecall -jal cause_s_soft_interrupt // The delegated S mode interrupts should not fire since we're running in M mode. +jal cause_s_soft_interrupt // S Mode Interrupts Ignored in M mode. sip writeable when mideleg = 1 jal cause_m_soft_interrupt jal cause_s_time_interrupt jal cause_m_time_interrupt diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-trap-s-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-trap-s-01.S index cfe02f3a6..525e79276 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-trap-s-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-trap-s-01.S @@ -56,12 +56,12 @@ GOTO_U_MODE // Causes S mode ecall GOTO_S_MODE // Causes U mode ecall -// some interrupts excluded becaus writing MIP is illegal from S mode -jal cause_s_soft_interrupt +// some interrupts excluded because writing MIP is illegal from S mode and writing SIP is only possible when delegated, which is tested below (priv spec 3.1.9) +//jal cause_s_soft_interrupt jal cause_m_soft_interrupt jal cause_m_time_interrupt li a3, 0x40 // this interrupt involves a time loop waiting for the interrupt to go off. -// since interrupts are not always enabled, +// since interrupts are not always enabled, we need to make it stop after a certain number of loops, which is the number in a3 jal cause_s_ext_interrupt_GPIO li a3, 0x40 jal cause_m_ext_interrupt