Merged bit manip

This commit is contained in:
David Harris 2023-03-23 06:55:29 -07:00
commit ba4e0d2721
27 changed files with 999 additions and 461 deletions

333
Install
View File

@ -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 doesnt 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. Dont be surprised if the installation directions have changed since the book was written or dont 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 dont 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 doesnt work for our purposes because it doesnt 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 wont 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 wont 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 servers 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.
<SIDEBAR>
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).
</END>
$ 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, dont 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 havent 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, youll 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 users 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 institutions 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 <to location of repo clone>
make
cd sim
./regression-wally #(depends on having Questa installed)

View File

@ -63,10 +63,10 @@ This section describes the open source toolchain installation. These steps shou
## 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 full installation 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 <optional, install directory, defaults to /opt/riscv>
$ sudo bin/wally-tool-chain-install.sh <optional, install directory, defaults to /opt/riscv>
## Detailed Toolchain Install Guide

View File

@ -39,6 +39,7 @@ sudo mkdir -p $RISCV
# UPDATE / UPGRADE
apt update
apt upgrade
# 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
@ -137,3 +138,7 @@ curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo
&& 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
# Other python libraries used through the book.
sudo pip3 install matplotlib scipy sklearn adjustText leif

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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,8 +126,7 @@ 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 = ["coverage64gc", "arch64f", "arch64d", "arch64i", "arch64priv", "arch64c", "arch64m", "arch64zi", "wally64a", "wally64periph", "wally64priv", "imperas64f", "imperas64d", "imperas64c", "imperas64i"]

View File

@ -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,80 @@
`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 [2:0] ALUControl, // With Funct3, indicates operation to perform
input logic [2:0] ALUSelect, // ALU mux select signal
input logic [1:0] BSelect, // One-Hot 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, // With ALUControl, indicates operation to perform NOTE: Change signal name to ALUSelect
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
logic [WIDTH-1:0] CondMaskInvB, Shift, FullResult,ALUResult; // Intermediate Signals
logic [WIDTH-1:0] ZBCResult, ZBBResult; // Result of ZBB, ZBC
logic [WIDTH-1:0] MaskB; // BitMask of B
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 [WIDTH-1:0] RevA; // Bit-reversed A
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
logic shSignA;
logic [WIDTH-1:0] rotA; // XLEN bit input source to shifter
logic [1:0] shASelect; // select signal for shifter source generation mux
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
// Extract control signals from ALUControl.
assign {W64, SubArith, ALUOp} = ALUControl;
// Extract control signals from bitmanip ALUControl.
assign {Rotate, Mask, PreShift} = BALUControl;
// Pack control signals into shifter select
assign shASelect = {W64,SubArith};
assign PreShiftAmt = Funct3[2:1] & {2{PreShift}};
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;
if (WIDTH == 64) begin
mux3 #(1) signmux(A[63], A[31], 1'b0, {~SubArith, W64}, shSignA);
mux3 #(64) extendmux({{32{1'b0}}, A[31:0]},{{32{A[31]}}, A[31:0]}, A,{~W64, SubArith}, CondExtA);
end else begin
mux2 #(1) signmux(1'b0, A[31], SubArith, shSignA);
assign CondExtA = A;
end
// shifter rotate source select mux
if (`ZBB_SUPPORTED & WIDTH == 64) begin
mux2 #(WIDTH) rotmux(A, {A[31:0], A[31:0]}, W64, rotA);
end else assign rotA = A;
if (`ZBA_SUPPORTED) begin: zbapreshift
// Pre-Shift
assign CondShiftA = CondExtA << (PreShiftAmt);
end else assign CondShiftA = A;
// 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(.shA(CondExtA), .Sign(shSignA), .rotA, .Amt(B[`LOG_XLEN-1:0]), .Right(Funct3[2]), .W64, .Y(Shift), .Rotate);
// Condition code flags are based on subtraction output Sum = A-B.
// Overflow occurs when the numbers being subtracted have the opposite sign
@ -67,20 +116,59 @@ 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
endcase
if (`ZBS_SUPPORTED | `ZBB_SUPPORTED) begin
always_comb
if (~ALUOp) FullResult = Sum; // Always add for ALUOp = 0 (address generation)
else casez (ALUSelect) // Otherwise check Funct3 NOTE: change signal name to ALUSelect
3'b000: FullResult = Sum; // add or sub
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 = {{(WIDTH-1){1'b0}},{|(A & CondMaskB)}};// bext
3'b110: FullResult = A | CondMaskInvB; // or, orn, bset
3'b111: FullResult = A & CondMaskInvB; // and, bclr
endcase
end
else begin
always_comb
if (~ALUOp) FullResult = Sum; // Always add for ALUOp = 0 (address generation)
else casez (ALUSelect) // Otherwise check Funct3 NOTE: change signal name to ALUSelect
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
endcase
end
if (`ZBC_SUPPORTED | `ZBB_SUPPORTED) begin: bitreverse
bitreverse #(WIDTH) brA(.A, .RevA);
end
if (`ZBC_SUPPORTED) begin: zbc
zbc #(WIDTH) ZBC(.A, .RevA, .B, .Funct3, .ZBCResult);
end else assign ZBCResult = 0;
if (`ZBB_SUPPORTED) begin: zbb
zbb #(WIDTH) ZBB(.A, .RevA, .B, .ALUResult, .W64, .lt(CompFlags[0]), .ZBBSelect, .ZBBResult);
end else assign ZBBResult = 0;
// 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 : zbdecoder
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
end else assign Result = ALUResult;
endmodule

42
src/ieu/bmu/bitreverse.sv Normal file
View File

@ -0,0 +1,42 @@
///////////////////////////////////////////
// bitreverse.sv
//
// Written: Kevin Kim <kekim@hmc.edu> and Kip Macsai-Goren <kmacsaigoren@hmc.edu>
// 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<WIDTH;i++) begin:loop
assign RevA[WIDTH-i-1] = A[i];
end
endmodule

192
src/ieu/bmu/bmuctrl.sv Normal file
View File

@ -0,0 +1,192 @@
///////////////////////////////////////////
// bmuctrl.sv
//
// Written: Kevin Kim <kekim@hmc.edu>
// 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
output logic [2:0] ALUSelectD, // ALU Mux select signal in Decode Stage
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 BALUOpD, // Indicates if it is an ALU 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] ALUSelectE,
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
`define BMUCTRLW 17
`define BMUCTRLWSUB3 14
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
BMUControlsD = {Funct3D, `BMUCTRLWSUB3'b00_000_0_0_0_0_0_0_0_0_1}; // default: Illegal instruction
casez({OpD, Funct7D, Funct3D})
// ALUSelect_BSelect_ZBBSelect_BRegWrite_BALUSrcB_BW64_BALUOp_BSubArithD_RotateD_MaskD_PreShiftD_IllegalBitmanipInstrD
// ZBS
17'b0010011_0100100_001: if (`ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b111_01_000_1_1_0_1_1_0_1_0_0; // bclri
17'b0010011_0100101_001: if (`XLEN == 64 & `ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b111_01_000_1_1_0_1_1_0_1_0_0; // bclri (rv64)
17'b0010011_0100100_101: if (`ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b101_01_000_1_1_0_1_1_0_1_0_0; // bexti
17'b0010011_0100101_101: if (`XLEN == 64 & `ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b101_01_000_1_1_0_1_1_0_1_0_0; // bexti (rv64)
17'b0010011_0110100_001: if (`ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b100_01_000_1_1_0_1_0_0_1_0_0; // binvi
17'b0010011_0110101_001: if (`XLEN == 64 & `ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b100_01_000_1_1_0_1_0_0_1_0_0; // binvi (rv64)
17'b0010011_0010100_001: if (`ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b110_01_000_1_1_0_1_0_0_1_0_0; // bseti
17'b0010011_0010101_001: if (`XLEN == 64 & `ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b110_01_000_1_1_0_1_0_0_1_0_0; // bseti (rv64)
17'b0110011_0100100_001: if (`ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b111_01_000_1_0_0_1_1_0_1_0_0; // bclr
17'b0110011_0100100_101: if (`ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b101_01_000_1_0_0_1_1_0_1_0_0; // bext
17'b0110011_0110100_001: if (`ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b100_01_000_1_0_0_1_0_0_1_0_0; // binv
17'b0110011_0010100_001: if (`ZBS_SUPPORTED)
BMUControlsD = `BMUCTRLW'b110_01_000_1_0_0_1_0_0_1_0_0; // bset
17'b0110011_0?0000?_?01: if (`ZBS_SUPPORTED | `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_00_000_1_0_0_1_0_0_0_0_0; // sra, srl, sll
17'b0010011_0?0000?_?01: if (`ZBS_SUPPORTED | `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_00_000_1_1_0_1_0_0_0_0_0; // srai, srli, slli
17'b0111011_0?0000?_?01: if (`ZBS_SUPPORTED | `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_00_000_1_0_1_1_0_0_0_0_0; // sraw, srlw, sllw
17'b0011011_0?0000?_?01: if (`ZBS_SUPPORTED | `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_00_000_1_1_1_1_0_0_0_0_0; // sraiw, srliw, slliw
// ZBC
17'b0110011_0000101_0??: if (`ZBC_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_11_000_1_0_0_1_0_0_0_0_0; // ZBC instruction
// ZBA
17'b0110011_0010000_010: if (`ZBA_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_01_000_1_0_0_1_0_0_0_1_0; // sh1add
17'b0110011_0010000_100: if (`ZBA_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_01_000_1_0_0_1_0_0_0_1_0; // sh2add
17'b0110011_0010000_110: if (`ZBA_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_01_000_1_0_0_1_0_0_0_1_0; // sh3add
17'b0111011_0010000_010: if (`XLEN == 64 & `ZBA_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_01_000_1_0_1_1_0_0_0_1_0; // sh1add.uw
17'b0111011_0010000_100: if (`XLEN == 64 & `ZBA_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_01_000_1_0_1_1_0_0_0_1_0; // sh2add.uw
17'b0111011_0010000_110: if (`XLEN == 64 & `ZBA_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_01_000_1_0_1_1_0_0_0_1_0; // sh3add.uw
17'b0111011_0000100_000: if (`XLEN == 64 & `ZBA_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_01_000_1_0_1_1_0_0_0_0_0; // add.uw
17'b0011011_000010?_001: if (`XLEN == 64 & `ZBA_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_01_000_1_1_1_1_0_0_0_0_0; // slli.uw
// ZBB
17'b0110011_0110000_001: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_01_111_1_0_0_1_0_1_0_0_0; // rol
17'b0111011_0110000_001: if (`XLEN == 64 & `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_00_111_1_0_1_1_0_1_0_0_0; // rolw
17'b0110011_0110000_101: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_01_111_1_0_0_1_0_1_0_0_0; // ror
17'b0111011_0110000_101: if (`XLEN == 64 & `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_00_111_1_0_1_1_0_1_0_0_0; // rorw
//17'b0010011_0110000_101: if (`ZBB_SUPPORTED)
// BMUControlsD = `BMUCTRLW'b001_00_111_1_1_0_1_0_1_0_0_0; // rori (rv32)
17'b0010011_011000?_101: if ((`XLEN == 64 | ~Funct7D[0]) & `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_00_111_1_1_0_1_0_1_0_0_0; // rori (rv64)
17'b0011011_0110000_101: if (`XLEN == 64 & `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b001_00_111_1_1_1_1_0_1_0_0_0; // roriw
17'b0010011_0110000_001: if (`ZBB_SUPPORTED & (Rs2D[4:1] == 4'b0010))
BMUControlsD = `BMUCTRLW'b000_10_001_1_1_0_1_0_0_0_0_0; // sign extend instruction
else if (`ZBB_SUPPORTED & ((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'b0011011_0110000_001: if (`XLEN == 64 & `ZBB_SUPPORTED & ((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
17'b0111011_0000100_100: if (`XLEN == 64 & `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_10_001_1_0_0_1_0_0_0_0_0; // zexth (rv64)
17'b0110011_0000100_100: if (`XLEN == 32 & `ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_10_001_1_1_0_1_0_0_0_0_0; // zexth (rv32)
17'b0110011_0100000_111: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b111_01_111_1_0_0_1_1_0_0_0_0; // andn
17'b0110011_0100000_110: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b110_01_111_1_0_0_1_1_0_0_0_0; // orn
17'b0110011_0100000_100: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b100_01_111_1_0_0_1_1_0_0_0_0; // xnor
17'b0010011_011010?_101: if ((`XLEN == 32 ^ Funct7D[0]) & `ZBB_SUPPORTED & (Rs2D == 5'b11000))
BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // rev8
17'b0010011_0010100_101: if (`ZBB_SUPPORTED & 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: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_0_0_0_0_0; // max
17'b0110011_0000101_111: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_0_0_0_0_0; // maxu
17'b0110011_0000101_100: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_0_0_0_0_0; // min
17'b0110011_0000101_101: if (`ZBB_SUPPORTED)
BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_0_0_0_0_0; // minu
endcase
end
// Unpack Control Signals
assign {ALUSelectD,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];
// BMU Execute stage pipieline control register
flopenrc#(13) controlregBMU(clk, reset, FlushE, ~StallE, {ALUSelectD, BSelectD, ZBBSelectD, BRegWriteD, BComparatorSignedD, BALUControlD}, {ALUSelectE, BSelectE, ZBBSelectE, BRegWriteE, BComparatorSignedE, BALUControlE});
endmodule

46
src/ieu/bmu/byte.sv Normal file
View File

@ -0,0 +1,46 @@
///////////////////////////////////////////
// byte.sv
//
// Written: Kevin Kim <kekim@hmc.edu>
// 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<WIDTH;i+=8) begin:loop
assign OrcBResult[i+7:i] = {8{|A[i+7:i]}};
assign Rev8Result[WIDTH-i-1:WIDTH-i-8] = A[i+7:i];
end
mux2 #(WIDTH) bytemux(Rev8Result, OrcBResult, ByteSelect, ByteResult);
endmodule

51
src/ieu/bmu/clmul.sv Normal file
View File

@ -0,0 +1,51 @@
///////////////////////////////////////////
// clmul.sv
//
// Written: Kevin Kim <kekim@hmc.edu> and Kip Macsai-Goren <kmacsaigoren@hmc.edu>
// 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<WIDTH;i++) begin: outer
s[WIDTH*i]=A[0]&B[i];
for (j=1;j<=i;j++) begin: inner
s[WIDTH*i+j] = (A[j]&B[i-j])^s[WIDTH*i+j-1];
end
ClmulResult[i] = s[WIDTH*i+j-1];
end
end
endmodule

65
src/ieu/bmu/cnt.sv Normal file
View File

@ -0,0 +1,65 @@
///////////////////////////////////////////
// cnt.sv
//
// Written: Kevin Kim <kekim@hmc.edu>
// 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

45
src/ieu/bmu/ext.sv Normal file
View File

@ -0,0 +1,45 @@
///////////////////////////////////////////
// ext.sv
//
// Written: Kevin Kim <kekim@hmc.edu>
// 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

44
src/ieu/bmu/popcnt.sv Normal file
View File

@ -0,0 +1,44 @@
///////////////////////////////////////////
// popccnt.sv
// Written: Kevin Kim <kekim@hmc.edu>
// 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<WIDTH;i++) begin:loop
sum = (num[i]) ? sum + 1 : sum;
end
end
assign PopCnt = sum;
endmodule

55
src/ieu/bmu/zbb.sv Normal file
View File

@ -0,0 +1,55 @@
///////////////////////////////////////////
// zbb.sv
//
// Written: Kevin Kim <kekim@hmc.edu> and Kip Macsai-Goren <kmacsaigoren@hmc.edu>
// 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

54
src/ieu/bmu/zbc.sv Normal file
View File

@ -0,0 +1,54 @@
///////////////////////////////////////////
// zbc.sv
//
// Written: Kevin Kim <kekim@hmc.edu> and Kip Macsai-Goren <kmacsaigoren@hmc.edu>
// 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

View File

@ -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
//
@ -48,6 +48,7 @@ module controller(
output logic [2:0] ALUControlE, // ALU operation to perform
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
@ -57,6 +58,10 @@ module controller(
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
@ -88,7 +93,12 @@ module controller(
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 BaseALUOpD, BaseW64D; // ALU operation and 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 [2:0] ALUSelectD; // ALU mux select signal
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
@ -100,18 +110,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 BranchTakenE; // Branch is taken
logic eqE, ltE; // Comparator outputs
logic unused;
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 IllegalBitmanipInstrD; // Unrecognized B instruction
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 BRegWriteD; // Indicates if it is a R type B instruction in decode stage
logic BW64D; // Indicates if it is a W type B instruction in decode stage
logic BALUOpD; // Indicates if it is an ALU B instruction in decode stage
logic BSubArithD; // TRUE for B-type ext, clr, andn, orn, xnor
logic BALUSrcBD; // B-type alu src 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
@ -213,25 +233,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 = (ControlsD[0] & IllegalBitmanipInstrD) | IllegalERegAdrD ; //NOTE: Do we want to segregate the IllegalBitmanipInstrD into its own output signal
//assign IllegalBaseInstrD = 1'b0;
assign {BaseRegWriteD, ImmSrcD, ALUSrcAD, BaseALUSrcBD, MemRWD,
ResultSrcD, BranchD, BaseALUOpD, JumpD, ALUResultSrcD, BaseW64D, CSRReadD,
PrivilegedD, FenceXD, MDUD, AtomicD, unused} = IllegalIEUFPUInstrD ? `CTRLW'b0 : ControlsD;
// If either bitmanip signal or base instruction signal
assign ALUOpD = BaseALUOpD | BALUOpD;
assign RegWriteD = BaseRegWriteD | BRegWriteD;
assign W64D = BaseW64D | BW64D;
assign ALUSrcBD = BaseALUSrcBD | BALUSrcBD;
assign SubArithD = BaseSubArithD | BSubArithD; // TRUE If B-type or R-type instruction involves inverted operand
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 BaseSubArithD = ALUOpD & (subD | sraD | sltD | sltuD);
assign ALUControlD = {W64D, SubArithD, ALUOpD};
// 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
bmuctrl bmuctrl(.clk, .reset, .StallD, .FlushD, .InstrD, .ALUSelectD, .BSelectD, .ZBBSelectD,
.BRegWriteD, .BALUSrcBD, .BW64D, .BALUOpD, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE,
.ALUSelectE, .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);
end else begin: bitmanipi
assign ALUSelectD = Funct3D;
assign ALUSelectE = Funct3E;
assign BSelectE = 2'b00;
assign BSelectD = 2'b00;
assign ZBBSelectE = 3'b000;
assign BRegWriteD = 1'b0;
assign BW64D = 1'b0;
assign BALUOpD = 1'b0;
assign BRegWriteE = 1'b0;
assign BSubArithD = 1'b0;
assign BComparatorSignedE = 1'b0;
assign BALUControlE = 3'b0;
assign BALUSrcBD = 1'b0;
assign sltD = (Funct3D == 3'b010);
assign IllegalBitmanipInstrD = 1'b1;
end
// Fences
// Ordinary fence is presently a nop
// fence.i flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
@ -256,7 +312,8 @@ module controller(
// 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];
@ -284,4 +341,4 @@ module controller(
// the synchronous DTIM cannot read immediately after write
// a cache cannot read or write immediately after a write
assign StoreStallD = MemRWE[0] & ((MemRWD[1] | (MemRWD[0] & `DCACHE_SUPPORTED)) | (|AtomicD));
endmodule
endmodule

View File

@ -43,8 +43,12 @@ module datapath (
input logic [2:0] ALUControlE, // Indicate operation ALU performs
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 +60,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
@ -109,7 +113,7 @@ module datapath (
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, ALUControlE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, FlagsE, BALUControlE, ALUResultE, IEUAdrE);
mux2 #(`XLEN) altresultmux(ImmExtE, PCLinkE, JumpE, AltResultE);
mux2 #(`XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE);
@ -141,4 +145,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

View File

@ -80,9 +80,13 @@ module ieu (
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
// 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, .ALUControlE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .MemReadE, .CSRReadE,
.Funct3E, .IntDivE, .MDUE, .W64E, .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,
.ALUControlE, .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);

View File

@ -1,9 +1,9 @@
///////////////////////////////////////////
// shifter.sv
//
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu
// Written: David_Harris@hmc.edu, Sarah.Harris@unlv.edu, Kevin Kim <kekim@hmc.edu>
// Created: 9 January 2021
// Modified:
// Modified: 6 February 2023
//
// Purpose: RISC-V 32/64 bit shifter
//
@ -30,42 +30,49 @@
`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] shA, // shift Source
input logic [`XLEN-1:0] rotA, // rotate source
input logic [`LOG_XLEN-1:0] Amt, // Shift amount
input logic Right, Rotate, W64, Sign, // Shift right, rotate signals
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] amttrunc, offset; // Shift amount adjusted for RV64, right-shift amount
// 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
if (`ZBB_SUPPORTED) begin: rotfunnel
if (`XLEN==32) begin // rv32 with rotates
always_comb // funnel mux
case({Right, Rotate})
2'b00: z = {shA[31:0], 31'b0};
2'b01: z = {rotA,rotA[31:1]};
2'b10: z = {{31{Sign}}, shA[31:0]};
2'b11: z = {rotA[30:0],rotA};
endcase
assign amttrunc = Amt; // shift amount
end else begin // rv64 with rotates
always_comb // funnel mux
case ({Right, Rotate})
2'b00: z = {shA[63:0],{63'b0}};
2'b01: z = {rotA, rotA[63:1]};
2'b10: z = {{63{Sign}},shA[63:0]};
2'b11: z = {rotA[62:0],rotA[63:0]};
endcase
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32- or 64-bit shift
end
end else begin: norotfunnel
if (`XLEN==32) begin:shifter // RV32
always_comb // funnel mux
if (Right) z = {{31{Sign}}, shA[31:0]};
else z = {shA[31:0], 31'b0};
assign amttrunc = Amt; // shift amount
end else begin:shifter // RV64
always_comb // funnel mux
if (Right) z = {{63{Sign}},shA[63:0]};
else z = {shA[63:0],{63'b0}};
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32- or 64-bit shift
end
end
// Opposite offset for right shifts
assign offset = Right ? amttrunc : ~amttrunc;

View File

@ -107,6 +107,10 @@ logic [3:0] dummy;
"fpga": tests = fpga;
"ahb" : tests = ahb;
"coverage64gc" : tests = coverage64gc;
"arch64zba": if (`ZBA_SUPPORTED) tests = arch64zba;
"arch64zbb": if (`ZBB_SUPPORTED) tests = arch64zbb;
"arch64zbc": if (`ZBC_SUPPORTED) tests = arch64zbc;
"arch64zbs": if (`ZBS_SUPPORTED) tests = arch64zbs;
endcase
end else begin // RV32
case (TEST)
@ -131,7 +135,10 @@ logic [3:0] dummy;
"wally32periph": tests = wally32periph;
"embench": tests = embench;
"coremark": tests = coremark;
"arch32ba": if (`ZBA_SUPPORTED) tests = arch32ba;
"arch32zba": if (`ZBA_SUPPORTED) tests = arch32zba;
"arch32zbb": if (`ZBB_SUPPORTED) tests = arch32zbb;
"arch32zbc": if (`ZBC_SUPPORTED) tests = arch32zbc;
"arch32zbs": if (`ZBS_SUPPORTED) tests = arch32zbs;
endcase
end
if (tests.size() == 0) begin

View File

@ -885,12 +885,52 @@ string imperas32f[] = '{
"rv32i_m/Zifencei/src/Fencei.S"
};
string arch32ba[] = '{
string arch32zba[] = '{
`RISCVARCHTEST,
// *** unclear why add.uw isn't in the list
"rv64i_m/B/src/sh1add-01.S",
"rv64i_m/B/src/sh1add-02.S",
"rv64i_m/B/src/sh1add-013.S"
"rv32i_m/B/src/sh1add-01.S",
"rv32i_m/B/src/sh2add-01.S",
"rv32i_m/B/src/sh3add-01.S"
};
string arch32zbb[] = '{
`RISCVARCHTEST,
"rv32i_m/B/src/max-01.S",
"rv32i_m/B/src/maxu-01.S",
"rv32i_m/B/src/min-01.S",
"rv32i_m/B/src/minu-01.S",
"rv32i_m/B/src/orcb_32-01.S",
"rv32i_m/B/src/rev8_32-01.S",
"rv32i_m/B/src/andn-01.S",
"rv32i_m/B/src/orn-01.S",
"rv32i_m/B/src/xnor-01.S",
"rv32i_m/B/src/zext.h_32-01.S",
"rv32i_m/B/src/sext.b-01.S",
"rv32i_m/B/src/sext.h-01.S",
"rv32i_m/B/src/clz-01.S",
"rv32i_m/B/src/cpop-01.S",
"rv32i_m/B/src/ctz-01.S",
"rv32i_m/B/src/ror-01.S",
"rv32i_m/B/src/rori-01.S",
"rv32i_m/B/src/rol-01.S"
};
string arch32zbc[] = '{
`RISCVARCHTEST,
"rv32i_m/B/src/clmul-01.S",
"rv32i_m/B/src/clmulh-01.S",
"rv32i_m/B/src/clmulr-01.S"
};
string arch32zbs[] = '{
`RISCVARCHTEST,
"rv32i_m/B/src/bclr-01.S",
"rv32i_m/B/src/bclri-01.S",
"rv32i_m/B/src/bext-01.S",
"rv32i_m/B/src/bexti-01.S",
"rv32i_m/B/src/binv-01.S",
"rv32i_m/B/src/binvi-01.S",
"rv32i_m/B/src/bset-01.S",
"rv32i_m/B/src/bseti-01.S"
};
string arch64m[] = '{
@ -1330,6 +1370,65 @@ string imperas32f[] = '{
"rv64i_m/D/src/fssub.d_b8-01.S"
};
string arch64zba[] = '{
`RISCVARCHTEST,
"rv64i_m/B/src/slli.uw-01.S",
"rv64i_m/B/src/add.uw-01.S",
"rv64i_m/B/src/sh1add-01.S",
"rv64i_m/B/src/sh2add-01.S",
"rv64i_m/B/src/sh3add-01.S",
"rv64i_m/B/src/sh1add.uw-01.S",
"rv64i_m/B/src/sh2add.uw-01.S",
"rv64i_m/B/src/sh3add.uw-01.S"
};
string arch64zbb[] = '{
`RISCVARCHTEST,
"rv64i_m/B/src/max-01.S",
"rv64i_m/B/src/maxu-01.S",
"rv64i_m/B/src/min-01.S",
"rv64i_m/B/src/minu-01.S",
"rv64i_m/B/src/orcb_64-01.S",
"rv64i_m/B/src/rev8-01.S",
"rv64i_m/B/src/andn-01.S",
"rv64i_m/B/src/orn-01.S",
"rv64i_m/B/src/xnor-01.S",
"rv64i_m/B/src/zext.h-01.S",
"rv64i_m/B/src/sext.b-01.S",
"rv64i_m/B/src/sext.h-01.S",
"rv64i_m/B/src/clz-01.S",
"rv64i_m/B/src/clzw-01.S",
"rv64i_m/B/src/cpop-01.S",
"rv64i_m/B/src/cpopw-01.S",
"rv64i_m/B/src/ctz-01.S",
"rv64i_m/B/src/ctzw-01.S",
"rv64i_m/B/src/rolw-01.S",
"rv64i_m/B/src/ror-01.S",
"rv64i_m/B/src/rori-01.S",
"rv64i_m/B/src/roriw-01.S",
"rv64i_m/B/src/rorw-01.S",
"rv64i_m/B/src/rol-01.S"
};
string arch64zbc[] = '{
`RISCVARCHTEST,
"rv64i_m/B/src/clmul-01.S",
"rv64i_m/B/src/clmulh-01.S",
"rv64i_m/B/src/clmulr-01.S"
};
string arch64zbs[] = '{
`RISCVARCHTEST,
"rv64i_m/B/src/bclr-01.S",
"rv64i_m/B/src/bclri-01.S",
"rv64i_m/B/src/bext-01.S",
"rv64i_m/B/src/bexti-01.S",
"rv64i_m/B/src/binv-01.S",
"rv64i_m/B/src/binvi-01.S",
"rv64i_m/B/src/bset-01.S",
"rv64i_m/B/src/bseti-01.S"
};
string arch32priv[] = '{
`RISCVARCHTEST,
"rv32i_m/privilege/src/ebreak.S",

View File

@ -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)

View File

@ -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

View File

@ -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]

View File

@ -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]