mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'bitmanip_cleanup' of https://github.com/kipmacsaigoren/cvw into bitmanip_cleanup
This commit is contained in:
commit
bd1ac13f5f
@ -34,8 +34,8 @@ Clone your fork of the repo and run the setup script.
|
||||
|
||||
$ cd
|
||||
$ git clone --recurse-submodules https://github.com/<yourgithubid>/cvw
|
||||
$ git remote add upstream https://github.com/openhwgroup/cvw
|
||||
$ cd cvw
|
||||
$ git remote add upstream https://github.com/openhwgroup/cvw
|
||||
$ source ./setup.sh
|
||||
|
||||
Add the following lines to your .bashrc or .bash_profile to run the setup script each time you log in.
|
||||
|
@ -29,7 +29,7 @@
|
||||
`include "wally-shared.vh"
|
||||
|
||||
`define FPGA 1
|
||||
`define QEMU 1
|
||||
`define QEMU 0
|
||||
// RV32 or RV64: XLEN = 32 or 64
|
||||
`define XLEN 64
|
||||
|
||||
|
41
docs/README-linux.md
Normal file
41
docs/README-linux.md
Normal file
@ -0,0 +1,41 @@
|
||||
### 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.
|
||||
Depending on your system configuration this makefile may need a bit of tweaking. It places the output buildroot images in $RISCV/linux-testvectors and the buildroot object dumps in $RISCV/buildroot/output/images/disassembly. If these directories are owned by root then the makefile will likely fail. You can either change the makefile's target directories or change temporarily change the owner of the two directories.
|
||||
|
||||
$ 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
|
251
fpga/constraints/constraints-artyA7.xdc
Normal file
251
fpga/constraints/constraints-artyA7.xdc
Normal file
@ -0,0 +1,251 @@
|
||||
# The main clocks are all autogenerated by the Xilinx IP
|
||||
# mmcm_clkout1 is the 22Mhz clock from the DDR4 IP used to drive wally and the AHBLite Bus.
|
||||
# mmcm_clkout0 is the clock output of the DDR4 memory interface / 4.
|
||||
# This clock is not used by wally or the AHBLite Bus. However it is used by the AXI BUS on the DD4 IP.
|
||||
|
||||
create_generated_clock -name CLKDiv64_Gen -source [get_pins wallypipelinedsoc/uncore.uncore/sdc.SDC/sd_top/slow_clk_divider/clkMux/I0] -multiply_by 1 -divide_by 2 [get_pins wallypipelinedsoc/uncore.uncore/sdc.SDC/sd_top/slow_clk_divider/clkMux/O]
|
||||
|
||||
##### GPI ####
|
||||
set_property PACKAGE_PIN D9 [get_ports {GPI[0]}]
|
||||
set_property PACKAGE_PIN C9 [get_ports {GPI[1]}]
|
||||
set_property PACKAGE_PIN B9 [get_ports {GPI[2]}]
|
||||
set_property PACKAGE_PIN B8 [get_ports {GPI[3]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {GPI[3]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {GPI[2]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {GPI[1]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {GPI[0]}]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 2.000 [get_ports {GPI[*]}]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 2.000 [get_ports {GPI[*]}]
|
||||
set_max_delay -from [get_ports {GPI[*]}] 10.000
|
||||
|
||||
##### GPO ####
|
||||
set_property PACKAGE_PIN G6 [get_ports {GPO[0]}]
|
||||
set_property PACKAGE_PIN F6 [get_ports {GPO[1]}]
|
||||
set_property PACKAGE_PIN E1 [get_ports {GPO[2]}]
|
||||
set_property PACKAGE_PIN G3 [get_ports {GPO[4]}]
|
||||
set_property PACKAGE_PIN J4 [get_ports {GPO[3]}]
|
||||
set_property IOSTANDARD LVCMOS12 [get_ports {GPO[4]}]
|
||||
set_property IOSTANDARD LVCMOS12 [get_ports {GPO[3]}]
|
||||
set_property IOSTANDARD LVCMOS12 [get_ports {GPO[2]}]
|
||||
set_property IOSTANDARD LVCMOS12 [get_ports {GPO[1]}]
|
||||
set_property IOSTANDARD LVCMOS12 [get_ports {GPO[0]}]
|
||||
set_max_delay -to [get_ports {GPO[*]}] 10.000
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 0.000 [get_ports {GPO[*]}]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 0.000 [get_ports {GPO[*]}]
|
||||
|
||||
|
||||
##### UART #####
|
||||
# *** IOSTANDARD is probably wrong
|
||||
set_property PACKAGE_PIN A9 [get_ports UARTSin]
|
||||
set_property PACKAGE_PIN D0 [get_ports UARTSout]
|
||||
set_max_delay -from [get_ports UARTSin] 10.000
|
||||
set_max_delay -to [get_ports UARTSout] 10.000
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports UARTSin]
|
||||
set_property IOSTANDARD LVCMOS3 [get_ports UARTSout]
|
||||
set_property DRIVE 6 [get_ports UARTSout]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 2.000 [get_ports UARTSin]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 2.000 [get_ports UARTSin]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 0.000 [get_ports UARTSout]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 0.000 [get_ports UARTSout]
|
||||
|
||||
|
||||
##### reset #####
|
||||
#************** reset is inverted
|
||||
set_input_delay -clock [get_clocks default_250mhz_clk1_0_p] -min -add_delay 2.000 [get_ports reset]
|
||||
set_input_delay -clock [get_clocks default_250mhz_clk1_0_p] -max -add_delay 2.000 [get_ports reset]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout0] -min -add_delay 0.000 [get_ports reset]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout0] -max -add_delay 0.000 [get_ports reset]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 0.000 [get_ports reset]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 0.000 [get_ports reset]
|
||||
set_max_delay -from [get_ports reset] 15.000
|
||||
set_false_path -from [get_ports reset]
|
||||
set_property PACKAGE_PIN C2 [get_ports {reset}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {reset}]
|
||||
|
||||
|
||||
|
||||
##### cpu_reset #####
|
||||
# ***********
|
||||
set_property PACKAGE_PIN AV36 [get_ports {cpu_reset}]
|
||||
set_property IOSTANDARD LVCMOS12 [get_ports {cpu_reset}]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 0.000 [get_ports {cpu_reset}]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 0.000 [get_ports {cpu_reset}]
|
||||
|
||||
|
||||
##### calib #####
|
||||
# **********
|
||||
set_property PACKAGE_PIN BA37 [get_ports calib]
|
||||
set_property IOSTANDARD LVCMOS12 [get_ports calib]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 0.000 [get_ports calib]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 20.000 [get_ports calib]
|
||||
set_max_delay -from [get_pins xlnx_ddr4_c0/inst/u_ddr4_mem_intfc/u_ddr_cal_top/calDone_gated_reg/C] -to [get_ports calib] 50.000
|
||||
|
||||
|
||||
##### ahblite_resetn #####
|
||||
# ***************
|
||||
set_property PACKAGE_PIN AU37 [get_ports {ahblite_resetn}]
|
||||
set_property IOSTANDARD LVCMOS12 [get_ports {ahblite_resetn}]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 0.000 [get_ports {ahblite_resetn}]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 0.000 [get_ports {ahblite_resetn}]
|
||||
|
||||
|
||||
##### south_rst #####
|
||||
# ***********************
|
||||
set_property PACKAGE_PIN BE22 [get_ports south_rst]
|
||||
set_property IOSTANDARD LVCMOS18 [get_ports south_rst]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 2.000 [get_ports south_rst]
|
||||
set_input_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 2.000 [get_ports south_rst]
|
||||
|
||||
|
||||
##### SD Card I/O #####
|
||||
#***** may have to switch to Pmod JB or JC.
|
||||
set_property PACKAGE_PIN D4 [get_ports {SDCDat[3]}]
|
||||
set_property PACKAGE_PIN D2 [get_ports {SDCDat[2]}]
|
||||
set_property PACKAGE_PIN E2 [get_ports {SDCDat[1]}]
|
||||
set_property PACKAGE_PIN F4 [get_ports {SDCDat[0]}]
|
||||
set_property PACKAGE_PIN F2 [get_ports SDCCLK]
|
||||
set_property PACKAGE_PIN D3 [get_ports {SDCCmd}]
|
||||
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[3]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[2]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[1]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {SDCDat[0]}]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports SDCCLK]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports {SDCCmd}]
|
||||
set_property PULLUP true [get_ports {SDCDat[3]}]
|
||||
set_property PULLUP true [get_ports {SDCDat[2]}]
|
||||
set_property PULLUP true [get_ports {SDCDat[1]}]
|
||||
set_property PULLUP true [get_ports {SDCDat[0]}]
|
||||
set_property PULLUP true [get_ports {SDCCmd}]
|
||||
|
||||
|
||||
set_input_delay -clock [get_clocks CLKDiv64_Gen] -min -add_delay 2.500 [get_ports {SDCDat[*]}]
|
||||
set_input_delay -clock [get_clocks CLKDiv64_Gen] -max -add_delay 21.000 [get_ports {SDCDat[*]}]
|
||||
|
||||
set_input_delay -clock [get_clocks CLKDiv64_Gen] -min -add_delay 2.500 [get_ports {SDCCmd}]
|
||||
set_input_delay -clock [get_clocks CLKDiv64_Gen] -max -add_delay 14.000 [get_ports {SDCCmd}]
|
||||
|
||||
|
||||
set_output_delay -clock [get_clocks CLKDiv64_Gen] -min -add_delay 2.000 [get_ports {SDCCmd}]
|
||||
set_output_delay -clock [get_clocks CLKDiv64_Gen] -max -add_delay 6.000 [get_ports {SDCCmd}]
|
||||
|
||||
set_output_delay -clock [get_clocks CLKDiv64_Gen] 0.000 [get_ports SDCCLK]
|
||||
|
||||
# *********************************
|
||||
set_property DCI_CASCADE {64} [get_iobanks 65]
|
||||
set_property INTERNAL_VREF 0.9 [get_iobanks 65]
|
||||
|
||||
# ddr3
|
||||
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[0]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[1]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[2]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[3]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[4]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[5]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[6]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[7]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[8]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[9]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[10]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[11]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[12]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[13]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[14]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dq[15]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dm[0]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_dm[1]
|
||||
set_property IOSTANDARD DIFF [get_ports ddr3_dqs_p[0]
|
||||
set_property IOSTANDARD DIFF [get_ports ddr3_dqs_n[0]
|
||||
set_property IOSTANDARD DIFF [get_ports ddr3_dqs_p[1]
|
||||
set_property IOSTANDARD DIFF [get_ports ddr3_dqs_n[1]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[13]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[12]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[11]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[10]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[9]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[8]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[7]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[6]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[5]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[4]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[3]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[2]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[1]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_addr[0]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_ba[2]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_ba[1]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_ba[0]
|
||||
set_property IOSTANDARD DIFF [get_ports ddr3_ck_p[0]
|
||||
set_property IOSTANDARD DIFF [get_ports ddr3_ck_n[0]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_ras_n
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_cas_n
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_we_n
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_reset_n
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_cke[0]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_odt[0]
|
||||
set_property IOSTANDARD SSTL135 [get_ports ddr3_cs_n[0]
|
||||
|
||||
|
||||
set_properity PACKAGE_PIN K5 [get_ports ddr3_dq[0]]
|
||||
set_properity PACKAGE_PIN L3 [get_ports ddr3_dq[1]]
|
||||
set_properity PACKAGE_PIN K3 [get_ports ddr3_dq[2]]
|
||||
set_properity PACKAGE_PIN L6 [get_ports ddr3_dq[3]]
|
||||
set_properity PACKAGE_PIN M3 [get_ports ddr3_dq[4]]
|
||||
set_properity PACKAGE_PIN M1 [get_ports ddr3_dq[5]]
|
||||
set_properity PACKAGE_PIN L4 [get_ports ddr3_dq[6]]
|
||||
set_properity PACKAGE_PIN M2 [get_ports ddr3_dq[7]]
|
||||
set_properity PACKAGE_PIN V4 [get_ports ddr3_dq[8]]
|
||||
set_properity PACKAGE_PIN T5 [get_ports ddr3_dq[9]]
|
||||
set_properity PACKAGE_PIN U4 [get_ports ddr3_dq[10]]
|
||||
set_properity PACKAGE_PIN V5 [get_ports ddr3_dq[11]]
|
||||
set_properity PACKAGE_PIN V1 [get_ports ddr3_dq[12]]
|
||||
set_properity PACKAGE_PIN T3 [get_ports ddr3_dq[13]]
|
||||
set_properity PACKAGE_PIN U3 [get_ports ddr3_dq[14]]
|
||||
set_properity PACKAGE_PIN R3 [get_ports ddr3_dq[15]]
|
||||
set_properity PACKAGE_PIN L1 [get_ports ddr3_dm[0]]
|
||||
set_properity PACKAGE_PIN U1 [get_ports ddr3_dm[1]]
|
||||
set_properity PACKAGE_PIN N2 [get_ports ddr3_dqs_p[0]]
|
||||
set_properity PACKAGE_PIN N1 [get_ports ddr3_dqs_n[0]]
|
||||
set_properity PACKAGE_PIN U2 [get_ports ddr3_dqs_p[1]]
|
||||
set_properity PACKAGE_PIN V2 [get_ports ddr3_dqs_n[1]]
|
||||
set_properity PACKAGE_PIN T8 [get_ports ddr3_addr[13]]
|
||||
set_properity PACKAGE_PIN T6 [get_ports ddr3_addr[12]]
|
||||
set_properity PACKAGE_PIN U6 [get_ports ddr3_addr[11]]
|
||||
set_properity PACKAGE_PIN R6 [get_ports ddr3_addr[10]]
|
||||
set_properity PACKAGE_PIN V7 [get_ports ddr3_addr[9]]
|
||||
set_properity PACKAGE_PIN R8 [get_ports ddr3_addr[8]]
|
||||
set_properity PACKAGE_PIN U7 [get_ports ddr3_addr[7]]
|
||||
set_properity PACKAGE_PIN V6 [get_ports ddr3_addr[6]]
|
||||
set_properity PACKAGE_PIN R7 [get_ports ddr3_addr[5]]
|
||||
set_properity PACKAGE_PIN N6 [get_ports ddr3_addr[4]]
|
||||
set_properity PACKAGE_PIN T1 [get_ports ddr3_addr[3]]
|
||||
set_properity PACKAGE_PIN N4 [get_ports ddr3_addr[2]]
|
||||
set_properity PACKAGE_PIN M6 [get_ports ddr3_addr[1]]
|
||||
set_properity PACKAGE_PIN R2 [get_ports ddr3_addr[0]]
|
||||
set_properity PACKAGE_PIN P2 [get_ports ddr3_ba[2]]
|
||||
set_properity PACKAGE_PIN P4 [get_ports ddr3_ba[1]]
|
||||
set_properity PACKAGE_PIN R1 [get_ports ddr3_ba[0]]
|
||||
set_properity PACKAGE_PIN U9 [get_ports ddr3_ck_p[0]]
|
||||
set_properity PACKAGE_PIN V9 [get_ports ddr3_ck_n[0]]
|
||||
set_properity PACKAGE_PIN P3 [get_ports ddr3_ras_n]
|
||||
set_properity PACKAGE_PIN M4 [get_ports ddr3_cas_n]
|
||||
set_properity PACKAGE_PIN P5 [get_ports ddr3_we_n]
|
||||
set_properity PACKAGE_PIN K6 [get_ports ddr3_reset_n]
|
||||
set_properity PACKAGE_PIN N5 [get_ports ddr3_cke[0]]
|
||||
set_properity PACKAGE_PIN R5 [get_ports ddr3_odt[0]]
|
||||
set_properity PACKAGE_PIN U8 [get_ports ddr3_cs_n[0]]
|
||||
|
||||
|
||||
|
||||
set_max_delay -datapath_only -from [get_pins xlnx_ddr4_c0/inst/u_ddr4_mem_intfc/u_ddr_cal_top/calDone_gated_reg/C] -to [get_pins xlnx_proc_sys_reset_0/U0/EXT_LPF/lpf_int_reg/D] 10.000
|
||||
|
||||
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -min -add_delay 0.000 [get_ports c0_ddr4_reset_n]
|
||||
set_output_delay -clock [get_clocks mmcm_clkout1] -max -add_delay 20.000 [get_ports c0_ddr4_reset_n]
|
||||
|
||||
|
||||
|
||||
set_max_delay -from [get_pins {xlnx_ddr4_c0/inst/u_ddr4_mem_intfc/u_ddr_cal_top/cal_RESET_n_reg[0]/C}] -to [get_ports c0_ddr4_reset_n] 50.000
|
||||
|
||||
|
@ -120,8 +120,6 @@ ebu/ebu.sv: logic HCLK
|
||||
ebu/ebu.sv: logic HREADY
|
||||
ebu/ebu.sv: logic HRESP
|
||||
ebu/ebu.sv: logic HADDR
|
||||
ebu/ebu.sv: logic HWDATA
|
||||
ebu/ebu.sv: logic HWSTRB
|
||||
ebu/ebu.sv: logic HWRITE
|
||||
ebu/ebu.sv: logic HSIZE
|
||||
ebu/ebu.sv: logic HBURST
|
||||
|
@ -88,7 +88,7 @@ module fpgaTop
|
||||
|
||||
|
||||
|
||||
wire [31:0] GPIOPinsIn, GPIOPinsOut, GPIOPinsEn;
|
||||
wire [31:0] GPIOIN, GPIOOUT, GPIOEN;
|
||||
|
||||
wire SDCCmdIn;
|
||||
wire SDCCmdOE;
|
||||
@ -183,8 +183,8 @@ module fpgaTop
|
||||
|
||||
|
||||
|
||||
assign GPIOPinsIn = {28'b0, GPI};
|
||||
assign GPO = GPIOPinsOut[4:0];
|
||||
assign GPIOIN = {28'b0, GPI};
|
||||
assign GPO = GPIOOUT[4:0];
|
||||
assign ahblite_resetn = peripheral_aresetn;
|
||||
assign cpu_reset = bus_struct_reset;
|
||||
assign calib = c0_init_calib_complete;
|
||||
@ -231,9 +231,9 @@ module fpgaTop
|
||||
.HMASTLOCK(HMASTLOCK),
|
||||
.HREADY(HREADY),
|
||||
// GPIO
|
||||
.GPIOPinsIn(GPIOPinsIn),
|
||||
.GPIOPinsOut(GPIOPinsOut),
|
||||
.GPIOPinsEn(GPIOPinsEn),
|
||||
.GPIOIN(GPIOIN),
|
||||
.GPIOOUT(GPIOOUT),
|
||||
.GPIOEN(GPIOEN),
|
||||
// UART
|
||||
.UARTSin(UARTSin),
|
||||
.UARTSout(UARTSout),
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
all: riscoftests memfiles
|
||||
all: riscoftests memfiles coveragetests
|
||||
# *** 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
|
||||
@ -50,3 +50,6 @@ riscoftests:
|
||||
make -C ../tests/riscof/
|
||||
memfiles:
|
||||
make -f makefile-memfile wally-sim-files --jobs
|
||||
|
||||
coveragetests:
|
||||
make -C ../tests/coverage/
|
||||
|
@ -1,5 +1,7 @@
|
||||
#--showoverrides
|
||||
#--showcommands
|
||||
#--mpdconsole
|
||||
#--gdbconsole
|
||||
--showoverrides
|
||||
--showcommands
|
||||
|
||||
# Core settings
|
||||
--override cpu/unaligned=F
|
||||
@ -9,7 +11,12 @@
|
||||
--override cpu/misa_Extensions_mask=0x0
|
||||
|
||||
# THIS NEEDS FIXING to 16
|
||||
--override cpu/PMP_registers=0
|
||||
--override cpu/PMP_registers=16
|
||||
--override cpu/PMP_undefined=T
|
||||
|
||||
# Illegal instruction should not contain the bit pattern
|
||||
# illegal pmp read contained this
|
||||
# --override cpu/tval_ii_code=F
|
||||
|
||||
# PMA Settings
|
||||
# 'r': read access allowed
|
||||
@ -24,16 +31,16 @@
|
||||
# '8': 8-byte accesses allowed
|
||||
# '-', space: ignored (use for input string formatting).
|
||||
#
|
||||
# SV39 Memory 0x0000000000 0x7FFFFFFFFF
|
||||
# SVxx Memory 0x0000000000 0x7FFFFFFFFF
|
||||
#
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0000000000 -hi 0x7FFFFFFFFF -attributes " ------ ---- "; # INITIAL
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0000001000 -hi 0x0000001FFF -attributes " r-x-A- 1248 "; # BOOTROM
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0000012100 -hi 0x000001211F -attributes " rw--A- --48 "; # SDC
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0002000000 -hi 0x000200FFFF -attributes " rw--A- 1248 "; # CLINT
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x000C000000 -hi 0x000FFFFFFF -attributes " rw--A- --4- "; # PLIC
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0010000000 -hi 0x0010000007 -attributes " rw--A- 1--- "; # UART0 error - 0x10000000 - 0x100000FF
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0010060000 -hi 0x00100600FF -attributes " rw--A- --4- "; # GPIO error - 0x10006000 - 0x100060FF
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0080000000 -hi 0x008FFFFFFF -attributes " rwx--- 1248 "; # UNCORE_RAM
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0000000000 -hi 0x7FFFFFFFFF -attributes " ------ ---- " # INITIAL
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0000001000 -hi 0x0000001FFF -attributes " r-x-A- 1248 " # BOOTROM
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0000012100 -hi 0x000001211F -attributes " rw--A- --48 " # SDC
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0002000000 -hi 0x000200FFFF -attributes " rw--A- 1248 " # CLINT
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x000C000000 -hi 0x000FFFFFFF -attributes " rw--A- --4- " # PLIC
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0010000000 -hi 0x0010000007 -attributes " rw--A- 1--- " # UART0 error - 0x10000000 - 0x100000FF
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0010060000 -hi 0x00100600FF -attributes " rw--A- --4- " # GPIO error - 0x10006000 - 0x100060FF
|
||||
--callcommand refRoot/cpu/setPMA -lo 0x0080000000 -hi 0x008FFFFFFF -attributes " rwx--- 1248 " # UNCORE_RAM
|
||||
|
||||
# Enable the Imperas instruction coverage
|
||||
#-extlib refRoot/cpu/cv=imperas.com/intercept/riscvInstructionCoverage/1.0
|
||||
@ -42,7 +49,7 @@
|
||||
|
||||
# Add Imperas simulator application instruction tracing
|
||||
--override cpu/show_c_prefix=T
|
||||
--trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange
|
||||
--trace --tracechange --traceshowicount --tracemode -tracemem ASX --monitornetschange --traceafter 10500000
|
||||
|
||||
# Exceptions and pagetables debug
|
||||
--override cpu/debugflags=6
|
||||
|
9
sim/run-imperas-linux.sh
Executable file
9
sim/run-imperas-linux.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
#export RISCV=/scratch/moore/RISCV
|
||||
|
||||
export IMPERAS_TOOLS=$(pwd)/imperas.ic
|
||||
export OTHERFLAGS="+TRACE2LOG_ENABLE=1"
|
||||
export OTHERFLAGS="+TRACE2LOG_ENABLE=1 +TRACE2LOG_AFTER=10500000"
|
||||
|
||||
vsim -c -do "do wally-linux-imperas.do buildroot buildroot-no-trace $::env(RISCV) 0 0 0"
|
@ -51,7 +51,7 @@ vlog +incdir+../config/$1 \
|
||||
-suppress 7063 \
|
||||
+acc
|
||||
vopt +acc work.testbench -G DEBUG=1 -o workopt
|
||||
vsim workopt +nowarn3829 -fatal 7 \
|
||||
eval vsim workopt +nowarn3829 -fatal 7 \
|
||||
-sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \
|
||||
+testDir=$env(TESTDIR) $env(OTHERFLAGS) +TRACE2COV_ENABLE=1 \
|
||||
-do "coverage save -onexit ./riscv.ucdb"
|
||||
|
@ -34,7 +34,7 @@ vlog +incdir+../config/$1 \
|
||||
-suppress 2583 \
|
||||
-suppress 7063
|
||||
vopt +acc work.testbench -G DEBUG=1 -o workopt
|
||||
vsim workopt +nowarn3829 -fatal 7 \
|
||||
eval vsim workopt +nowarn3829 -fatal 7 \
|
||||
+testDir=$env(TESTDIR) $env(OTHERFLAGS)
|
||||
view wave
|
||||
#-- display input and output signals as hexidecimal values
|
||||
|
@ -45,7 +45,7 @@ vlog +incdir+../config/$1 \
|
||||
-suppress 7063
|
||||
|
||||
vopt +acc work.testbench -G DEBUG=1 -o workopt
|
||||
vsim workopt +nowarn3829 -fatal 7 \
|
||||
eval vsim workopt +nowarn3829 -fatal 7 \
|
||||
-sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \
|
||||
+testDir=$env(TESTDIR) $env(OTHERFLAGS)
|
||||
view wave
|
||||
|
150
sim/wally-linux-imperas.do
Normal file
150
sim/wally-linux-imperas.do
Normal file
@ -0,0 +1,150 @@
|
||||
# wally.do
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
#
|
||||
# Modification by Oklahoma State University & Harvey Mudd College
|
||||
# Use with Testbench
|
||||
# James Stine, 2008; David Harris 2021
|
||||
# Go Cowboys!!!!!!
|
||||
#
|
||||
# Takes 1:10 to run RV64IC tests using gui
|
||||
|
||||
# run with vsim -do "do wally-pipelined.do rv64ic riscvarchtest-64m"
|
||||
|
||||
# Use this wally-pipelined.do file to run this example.
|
||||
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
|
||||
# do wally.do
|
||||
# or, to run from a shell, type the following at the shell prompt:
|
||||
# vsim -do wally.do -c
|
||||
# (omit the "-c" to see the GUI while running from the shell)
|
||||
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
}
|
||||
vlib work
|
||||
|
||||
# compile source files
|
||||
# suppress spurious warnngs about
|
||||
# "Extra checking for conflicts with always_comb done at vopt time"
|
||||
# because vsim will run vopt
|
||||
|
||||
# start and run simulation
|
||||
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
|
||||
if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} {
|
||||
vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
|
||||
# start and run simulation
|
||||
vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G CHECKPOINT=$6 -G NO_SPOOFING=0 -o testbenchopt
|
||||
vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7
|
||||
|
||||
#-- Run the Simulation
|
||||
#run -all
|
||||
add log -recursive /*
|
||||
do linux-wave.do
|
||||
run -all
|
||||
|
||||
exec ./slack-notifier/slack-notifier.py
|
||||
|
||||
} elseif {$2 eq "buildroot-no-trace"} {
|
||||
vlog -lint -work work_${1}_${2} \
|
||||
+define+USE_IMPERAS_DV \
|
||||
+incdir+../config/$1 \
|
||||
+incdir+../config/shared \
|
||||
+incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \
|
||||
+incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \
|
||||
$env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvvi-api-pkg.sv \
|
||||
$env(IMPERAS_HOME)/ImpPublic/source/host/rvvi/rvvi-trace.sv \
|
||||
$env(IMPERAS_HOME)/ImpProprietary/source/host/rvvi/rvvi-pkg.sv \
|
||||
$env(IMPERAS_HOME)/ImpProprietary/source/host/rvvi/imperasDV-api-pkg.sv \
|
||||
$env(IMPERAS_HOME)/ImpProprietary/source/host/rvvi/trace2api.sv \
|
||||
$env(IMPERAS_HOME)/ImpProprietary/source/host/rvvi/trace2log.sv \
|
||||
$env(IMPERAS_HOME)/ImpProprietary/source/host/rvvi/trace2cov.sv \
|
||||
../testbench/testbench-linux-imperas.sv \
|
||||
../testbench/common/*.sv ../src/*/*.sv \
|
||||
../src/*/*/*.sv -suppress 2583
|
||||
|
||||
#
|
||||
# start and run simulation
|
||||
# for profiling add
|
||||
# vopt -fprofile
|
||||
# vsim -fprofile+perf
|
||||
# visualizer -fprofile+perf+dir=fprofile
|
||||
#
|
||||
eval vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 \
|
||||
-G INSTR_LIMIT=0 -G INSTR_WAVEON=0 -G CHECKPOINT=0 -G NO_SPOOFING=1 -o testbenchopt
|
||||
eval vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7 \
|
||||
-sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \
|
||||
$env(OTHERFLAGS)
|
||||
|
||||
#-- Run the Simulation
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "Don't forget to change DEBUG_LEVEL = 0."
|
||||
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
#run 100 ns
|
||||
#force -deposit testbench/dut/core/priv/priv/csr/csri/IE_REGW 16'h2aa
|
||||
#force -deposit testbench/dut/uncore/uncore/clint/clint/MTIMECMP 64'h1000
|
||||
run 14000 ms
|
||||
#add log -recursive /*
|
||||
#do linux-wave.do
|
||||
#run -all
|
||||
|
||||
exec ./slack-notifier/slack-notifier.py
|
||||
|
||||
} elseif {$2 eq "fpga"} {
|
||||
echo "hello"
|
||||
vlog -work work +incdir+../config/fpga +incdir+../config/shared ../testbench/testbench.sv ../testbench/sdc/*.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv ../../fpga/sim/*.sv -suppress 8852,12070,3084,3829,2583,7063,13286
|
||||
vopt +acc work.testbench -G TEST=$2 -G DEBUG=0 -o workopt
|
||||
vsim workopt +nowarn3829 -fatal 7
|
||||
|
||||
do fpga-wave.do
|
||||
add log -r /*
|
||||
run 20 ms
|
||||
|
||||
} else {
|
||||
if {$2 eq "ahb"} {
|
||||
vlog +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063 +define+RAM_LATENCY=$3 +define+BURST_EN=$4
|
||||
} else {
|
||||
# *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings.
|
||||
vlog +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063
|
||||
}
|
||||
vopt +acc work.testbench -G TEST=$2 -G DEBUG=1 -o workopt
|
||||
|
||||
vsim workopt +nowarn3829 -fatal 7
|
||||
|
||||
view wave
|
||||
#-- display input and output signals as hexidecimal values
|
||||
#do ./wave-dos/peripheral-waves.do
|
||||
add log -recursive /*
|
||||
do wave.do
|
||||
#do wave-bus.do
|
||||
|
||||
# power add generates the logging necessary for saif generation.
|
||||
#power add -r /dut/core/*
|
||||
#-- Run the Simulation
|
||||
|
||||
run -all
|
||||
#power off -r /dut/core/*
|
||||
#power report -all -bsaif power.saif
|
||||
noview ../testbench/testbench.sv
|
||||
view wave
|
||||
}
|
||||
|
||||
|
||||
|
||||
#elseif {$2 eq "buildroot-no-trace""} {
|
||||
# vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583
|
||||
# start and run simulation
|
||||
# vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=470350800 -G INSTR_WAVEON=470350800 -G CHECKPOINT=470350800 -G DEBUG_TRACE=0 -o testbenchopt
|
||||
# vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829
|
||||
|
||||
#-- Run the Simulation
|
||||
# run 100 ns
|
||||
# force -deposit testbench/dut/core/priv/priv/csr/csri/IE_REGW 16'h2aa
|
||||
# force -deposit testbench/dut/uncore/uncore/clint/clint/MTIMECMP 64'h1000
|
||||
# add log -recursive /*
|
||||
# do linux-wave.do
|
||||
# run -all
|
||||
|
||||
# exec ./slack-notifier/slack-notifier.py
|
||||
#}
|
22
src/cache/cache.sv
vendored
22
src/cache/cache.sv
vendored
@ -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
|
||||
|
78
src/cache/cachefsm.sv
vendored
78
src/cache/cachefsm.sv
vendored
@ -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,31 +111,31 @@ 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
|
||||
|
||||
// com back to CPU
|
||||
assign CacheCommitted = CurrState != STATE_READY;
|
||||
assign CacheCommitted = (CurrState != STATE_READY) & ~(READ_ONLY_CACHE & CurrState == STATE_READ_HOLD);
|
||||
assign CacheStall = (CurrState == STATE_READY & (FlushCache | AnyMiss)) |
|
||||
(CurrState == STATE_FETCH) |
|
||||
(CurrState == STATE_WRITEBACK) |
|
||||
@ -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) |
|
||||
|
14
src/cache/cacheway.sv
vendored
14
src/cache/cacheway.sv
vendored
@ -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
|
||||
|
6
src/cache/subcachelineread.sv
vendored
6
src/cache/subcachelineread.sv
vendored
@ -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
|
||||
|
@ -33,9 +33,10 @@ module ahbcacheinterface #(
|
||||
parameter BEATSPERLINE, // Number of AHBW words (beats) in cacheline
|
||||
parameter AHBWLOGBWPL, // Log2 of ^
|
||||
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)
|
||||
parameter LLENPOVERAHBW, // Number of AHB beats in a LLEN word. AHBW cannot be larger than LLEN. (implementation limitation)
|
||||
parameter READ_ONLY_CACHE
|
||||
)(
|
||||
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 +57,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 +77,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 +101,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];
|
||||
@ -115,8 +116,8 @@ module ahbcacheinterface #(
|
||||
|
||||
flopen #(`AHBW/8) HWSTRBReg(HCLK, HREADY, BusByteMaskM[`AHBW/8-1:0], HWSTRB);
|
||||
|
||||
buscachefsm #(BeatCountThreshold, AHBWLOGBWPL) AHBBuscachefsm(
|
||||
buscachefsm #(BeatCountThreshold, AHBWLOGBWPL, READ_ONLY_CACHE) AHBBuscachefsm(
|
||||
.HCLK, .HRESETn, .Flush, .BusRW, .Stall, .BusCommitted, .BusStall, .CaptureEn, .SelBusBeat,
|
||||
.CacheBusRW, .CacheBusAck, .BeatCount, .BeatCountDelayed,
|
||||
.HREADY, .HTRANS, .HWRITE, .HBURST);
|
||||
.HREADY, .HTRANS, .HWRITE, .HBURST);
|
||||
endmodule
|
||||
|
@ -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
|
||||
|
@ -33,35 +33,36 @@
|
||||
// HCLK and clk must be the same clock!
|
||||
module buscachefsm #(
|
||||
parameter BeatCountThreshold, // Largest beat index
|
||||
parameter AHBWLOGBWPL // Log2 of BEATSPERLINE
|
||||
parameter AHBWLOGBWPL, // Log2 of BEATSPERLINE
|
||||
parameter READ_ONLY_CACHE
|
||||
)(
|
||||
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 +71,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 +99,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,11 +118,11 @@ 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;
|
||||
assign BusCommitted = (CurrState != ADR_PHASE) & ~(READ_ONLY_CACHE & CurrState == MEM3);
|
||||
|
||||
// AHB bus interface
|
||||
assign HTRANS = (CurrState == ADR_PHASE & HREADY & ((|BusRW) | (|CacheBusRW)) & ~Flush) |
|
||||
@ -144,7 +145,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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -33,29 +33,29 @@
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module controllerinputstage #(
|
||||
module controllerinput #(
|
||||
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;
|
@ -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;
|
||||
|
||||
@ -101,14 +98,14 @@ module ebu (
|
||||
// input stages and muxing for IFU and LSU
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
controllerinputstage IFUInput(.HCLK, .HRESETn, .Save(IFUSave), .Restore(IFURestore), .Disable(IFUDisable),
|
||||
controllerinput IFUInput(.HCLK, .HRESETn, .Save(IFUSave), .Restore(IFURestore), .Disable(IFUDisable),
|
||||
.Request(IFUReq),
|
||||
.HWRITEIn(1'b0), .HSIZEIn(IFUHSIZE), .HBURSTIn(IFUHBURST), .HTRANSIn(IFUHTRANS), .HADDRIn(IFUHADDR),
|
||||
.HWRITEOut(IFUHWRITEOut), .HSIZEOut(IFUHSIZEOut), .HBURSTOut(IFUHBURSTOut), .HREADYOut(IFUHREADY),
|
||||
.HTRANSOut(IFUHTRANSOut), .HADDROut(IFUHADDROut), .HREADYIn(HREADY));
|
||||
|
||||
// LSU always has priority so there should never be a need to save and restore the address phase inputs.
|
||||
controllerinputstage #(0) LSUInput(.HCLK, .HRESETn, .Save(1'b0), .Restore(1'b0), .Disable(LSUDisable),
|
||||
controllerinput #(0) LSUInput(.HCLK, .HRESETn, .Save(1'b0), .Restore(1'b0), .Disable(LSUDisable),
|
||||
.Request(LSUReq),
|
||||
.HWRITEIn(LSUHWRITE), .HSIZEIn(LSUHSIZE), .HBURSTIn(LSUHBURST), .HTRANSIn(LSUHTRANS), .HADDRIn(LSUHADDR), .HREADYOut(LSUHREADY),
|
||||
.HWRITEOut(LSUHWRITEOut), .HSIZEOut(LSUHSIZEOut), .HBURSTOut(LSUHBURSTOut),
|
||||
@ -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
|
||||
|
||||
|
@ -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 [3:0] 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;
|
||||
@ -98,29 +97,26 @@ module ebufsmarb (
|
||||
// Burst mode logic
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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;
|
||||
counter #(4) BeatCounter(HCLK, ~HRESETn | CntReset | FinalBeat, BeatCntEn, BeatCount);
|
||||
// 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.
|
||||
// HBURST[2:1] Beats
|
||||
// 00 1
|
||||
// 01 4
|
||||
// 10 8
|
||||
// 11 16
|
||||
// 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;
|
||||
/* 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 */
|
||||
endmodule
|
||||
|
198
src/fpu/fctrl.sv
198
src/fpu/fctrl.sv
@ -31,88 +31,86 @@ 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, Fmt2; // format - before possible reduction
|
||||
logic SupportedFmt; // is the format supported
|
||||
logic SupportedFmt2; // is the source format supported for fp -> fp
|
||||
logic FCvtIntD, FCvtIntM; // convert to integer opperation
|
||||
|
||||
// FPU Instruction Decoder
|
||||
assign Fmt = Funct7D[1:0];
|
||||
assign Fmt2 = Rs2D[1:0]; // source format for fcvt fp->fp
|
||||
|
||||
// Note: only Fmt is checked; fcvt does not check destination format
|
||||
assign SupportedFmt = (Fmt == 2'b00 | (Fmt == 2'b01 & `D_SUPPORTED) |
|
||||
(Fmt == 2'b10 & `ZFH_SUPPORTED) | (Fmt == 2'b11 & `Q_SUPPORTED));
|
||||
assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & `D_SUPPORTED) |
|
||||
(Fmt2 == 2'b10 & `ZFH_SUPPORTED) | (Fmt2 == 2'b11 & `Q_SUPPORTED));
|
||||
|
||||
// decode the instruction
|
||||
always_comb
|
||||
// ControlsD: FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt
|
||||
always_comb
|
||||
if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled
|
||||
ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0;
|
||||
else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt)
|
||||
ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // for anything other than loads and stores, check for supported format
|
||||
else case(OpD)
|
||||
// FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt
|
||||
else begin
|
||||
ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // default: illegal FPU instruction
|
||||
/* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed
|
||||
case(OpD)
|
||||
7'b0000111: case(Funct3D)
|
||||
3'b010: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flw
|
||||
3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // fld
|
||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fld not supported
|
||||
3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flq
|
||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // flq not supported
|
||||
3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flh
|
||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // flh not supported
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
||||
endcase
|
||||
7'b0100111: case(Funct3D)
|
||||
3'b010: ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsw
|
||||
3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsd
|
||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsd not supported
|
||||
3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsq
|
||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsq not supported
|
||||
3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsh
|
||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsh not supported
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
||||
endcase
|
||||
7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0; // fmadd
|
||||
7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0; // fmsub
|
||||
@ -128,56 +126,82 @@ module fctrl (
|
||||
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
|
||||
3'b010: ControlsD = `FCTRLW'b1_0_00_xx_010_0_0_0; // fsgnjx
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
||||
endcase
|
||||
endcase
|
||||
7'b00101??: case(Funct3D)
|
||||
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_110_0_0_0; // fmin
|
||||
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_101_0_0_0; // fmax
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
||||
endcase
|
||||
7'b10100??: case(Funct3D)
|
||||
3'b010: ControlsD = `FCTRLW'b0_1_00_xx_010_0_0_0; // feq
|
||||
3'b001: ControlsD = `FCTRLW'b0_1_00_xx_001_0_0_0; // flt
|
||||
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 & 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
|
||||
7'b1101000: case(Rs2D[1:0])
|
||||
2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s
|
||||
2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s
|
||||
2'b10: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s
|
||||
2'b11: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s
|
||||
ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass
|
||||
else if (Funct3D == 3'b000 & Rs2D == 5'b00000)
|
||||
ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.w / fmv.x.d to int register
|
||||
7'b111100?: if (Funct3D == 3'b000 & Rs2D == 5'b00000)
|
||||
ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.w.x / fmv.d.x to fp reg
|
||||
7'b0100000: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b00)
|
||||
ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.(d/q/h)
|
||||
7'b0100001: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b01)
|
||||
ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.(s/h/q)
|
||||
7'b0100010: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b10)
|
||||
ControlsD = `FCTRLW'b1_0_01_00_010_0_0_0; // fcvt.h.(s/d/q)
|
||||
7'b0100011: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b11)
|
||||
ControlsD = `FCTRLW'b1_0_01_00_011_0_0_0; // fcvt.q.(s/h/d)
|
||||
7'b1101000: case(Rs2D)
|
||||
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s
|
||||
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s
|
||||
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s
|
||||
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s
|
||||
endcase
|
||||
7'b1100000: case(Rs2D[1:0])
|
||||
2'b00: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w
|
||||
2'b01: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu
|
||||
2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l
|
||||
2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu
|
||||
7'b1100000: case(Rs2D)
|
||||
5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w
|
||||
5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu
|
||||
5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l
|
||||
5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu
|
||||
endcase
|
||||
7'b1111000: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.w.x to fp reg
|
||||
7'b0100000: ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.d
|
||||
7'b1101001: case(Rs2D[1:0])
|
||||
2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d
|
||||
2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d
|
||||
2'b10: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d
|
||||
2'b11: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d
|
||||
7'b1101001: case(Rs2D)
|
||||
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d
|
||||
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d
|
||||
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d
|
||||
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d
|
||||
endcase
|
||||
7'b1100001: case(Rs2D[1:0])
|
||||
2'b00: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w
|
||||
2'b01: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu
|
||||
2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l
|
||||
2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu
|
||||
7'b1100001: case(Rs2D)
|
||||
5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w
|
||||
5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu
|
||||
5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l
|
||||
5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu
|
||||
endcase
|
||||
7'b1111001: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.d.x to fp reg
|
||||
7'b0100001: ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.s
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
||||
7'b1101010: case(Rs2D)
|
||||
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.h.w w->h
|
||||
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.h.wu wu->h
|
||||
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.h.l l->h
|
||||
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.h.lu lu->h
|
||||
endcase
|
||||
7'b1100010: case(Rs2D)
|
||||
5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.h h->w
|
||||
5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.h h->wu
|
||||
5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.h h->l
|
||||
5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.h h->lu
|
||||
endcase
|
||||
7'b1101011: case(Rs2D)
|
||||
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.q.w w->q
|
||||
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.q.wu wu->q
|
||||
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.q.l l->q
|
||||
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.q.lu lu->q
|
||||
endcase
|
||||
7'b1100011: case(Rs2D)
|
||||
5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.q q->w
|
||||
5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.q q->wu
|
||||
5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.q q->l
|
||||
5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.q q->lu
|
||||
endcase
|
||||
endcase
|
||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
||||
endcase
|
||||
endcase
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
end
|
||||
|
||||
// unswizzle control bits
|
||||
assign #1 {FRegWriteD, FWriteIntD, FResSelD, PostProcSelD, OpCtrlD, FDivStartD, IllegalFPUInstrD, FCvtIntD} = ControlsD;
|
||||
|
@ -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?
|
||||
|
@ -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
|
||||
endmodule
|
||||
|
@ -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
|
||||
endmodule
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
222
src/fpu/fpu.sv
222
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);
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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])
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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
|
||||
|
@ -30,7 +30,7 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module bmuctrl(
|
||||
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
|
||||
@ -43,7 +43,7 @@ module bmuctrl(
|
||||
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
|
||||
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
|
||||
@ -66,7 +66,7 @@ module bmuctrl(
|
||||
|
||||
`define BMUCTRLW 17
|
||||
|
||||
logic [`BMUCTRLW-1:0] BMUControlsD; // Main B Instructions Decoder control signals
|
||||
logic [`BMUCTRLW-1:0] BMUControlsD; // Main B Instructions Decoder control signals
|
||||
|
||||
// Extract fields
|
||||
assign OpD = InstrD[6:0];
|
||||
@ -180,4 +180,4 @@ module bmuctrl(
|
||||
|
||||
// BMU Execute stage pipieline control register
|
||||
flopenrc#(10) controlregBMU(clk, reset, FlushE, ~StallE, {BSelectD, ZBBSelectD, BRegWriteD, BComparatorSignedD, BALUControlD}, {BSelectE, ZBBSelectE, BRegWriteE, BComparatorSignedE, BALUControlE});
|
||||
endmodule
|
||||
endmodule
|
||||
|
@ -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,11 +41,11 @@ 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 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)
|
||||
@ -74,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
|
||||
@ -89,16 +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 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 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
|
||||
@ -115,7 +115,7 @@ module controller(
|
||||
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
|
||||
@ -131,6 +131,7 @@ module controller(
|
||||
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
|
||||
logic IWValidFunct3D; // Detects if Funct3 is valid for IW instructions
|
||||
|
||||
// Extract fields
|
||||
assign OpD = InstrD[6:0];
|
||||
@ -146,29 +147,31 @@ 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);
|
||||
assign IWValidFunct3D = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b101;
|
||||
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
|
||||
assign IWValidFunct3D = 1;
|
||||
end
|
||||
|
||||
// Main Instruction Decoder
|
||||
@ -182,12 +185,12 @@ 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
|
||||
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
|
||||
7'b0011011: if (IFunctD & `XLEN == 64)
|
||||
7'b0011011: if (IFunctD & IWValidFunct3D & `XLEN == 64)
|
||||
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
|
||||
7'b0100011: if (SFunctD)
|
||||
ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // stores
|
||||
@ -337,4 +340,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
|
||||
|
@ -108,7 +108,7 @@ 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);
|
||||
@ -121,7 +121,7 @@ module datapath (
|
||||
// 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
|
||||
|
@ -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
|
||||
|
@ -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,12 +66,12 @@ 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
|
||||
|
@ -52,7 +52,7 @@ module regfile (
|
||||
|
||||
always_ff @(negedge clk)
|
||||
if (reset) for(i=1; i<NUMREGS; i++) rf[i] <= 0;
|
||||
else if (we3) rf[a3] <= wd3;
|
||||
else if (we3) rf[a3] <= wd3;
|
||||
|
||||
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;
|
||||
assign #2 rd2 = (a2 != 0) ? rf[a2] : 0;
|
||||
|
@ -35,8 +35,8 @@ module shifter (
|
||||
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
|
||||
|
||||
assign Sign = A[`XLEN-1] & SubArith; // sign bit for sign extension
|
||||
@ -44,17 +44,17 @@ module shifter (
|
||||
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]};
|
||||
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};
|
||||
if (Right) Z = {{31{Sign}}, A[31:0]};
|
||||
else Z = {A[31:0], 31'b0};
|
||||
end
|
||||
assign amttrunc = Amt; // shift amount
|
||||
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
|
||||
@ -64,25 +64,25 @@ module shifter (
|
||||
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]};
|
||||
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}};
|
||||
if (Right) Z = {{63{Sign}}, A64[63:0]};
|
||||
else Z = {A64[63:0], {63'b0}};
|
||||
end
|
||||
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32- or 64-bit shift
|
||||
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
|
||||
|
||||
|
||||
|
@ -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<StackSize; index++)
|
||||
memory[index] <= {`XLEN{1'b0}};
|
||||
memory[index] <= {`XLEN{1'b0}};
|
||||
end else if(PushE) begin
|
||||
memory[NextPtr] <= #1 PCLinkE;
|
||||
end
|
||||
|
@ -69,35 +69,33 @@ module bpred (
|
||||
output logic IClassWrongM // Class prediction is wrong
|
||||
);
|
||||
|
||||
logic [1:0] BPDirPredF;
|
||||
logic [1:0] BPDirPredF;
|
||||
|
||||
logic [`XLEN-1:0] BPBTAF, RASPCF;
|
||||
logic BPPCWrongE;
|
||||
logic IClassWrongE;
|
||||
logic BPDirPredWrongE;
|
||||
logic [`XLEN-1:0] BPBTAF, RASPCF;
|
||||
logic BPPCWrongE;
|
||||
logic IClassWrongE;
|
||||
logic BPDirPredWrongE;
|
||||
|
||||
logic BPPCSrcF;
|
||||
logic [`XLEN-1:0] BPPCF;
|
||||
logic [`XLEN-1:0] PC0NextF;
|
||||
logic [`XLEN-1:0] PCCorrectE;
|
||||
logic [3:0] WrongPredInstrClassD;
|
||||
logic BPPCSrcF;
|
||||
logic [`XLEN-1:0] BPPCF;
|
||||
logic [`XLEN-1:0] PC0NextF;
|
||||
logic [`XLEN-1:0] PCCorrectE;
|
||||
logic [3:0] WrongPredInstrClassD;
|
||||
|
||||
logic BTBTargetWrongE;
|
||||
logic RASTargetWrongE;
|
||||
logic BTBTargetWrongE;
|
||||
logic RASTargetWrongE;
|
||||
|
||||
logic [`XLEN-1:0] BPBTAD;
|
||||
logic [`XLEN-1:0] BPBTAD;
|
||||
|
||||
logic BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF;
|
||||
logic BPBranchF, BPJumpF, BPReturnF, BPCallF;
|
||||
logic BPBranchD, BPJumpD, BPReturnD, BPCallD;
|
||||
logic ReturnD, CallD;
|
||||
logic ReturnE, CallE;
|
||||
logic BranchM, JumpM, ReturnM, CallM;
|
||||
logic BranchW, JumpW, ReturnW, CallW;
|
||||
logic BPReturnWrongD;
|
||||
logic [`XLEN-1:0] BPBTAE;
|
||||
|
||||
|
||||
logic BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF;
|
||||
logic BPBranchF, BPJumpF, BPReturnF, BPCallF;
|
||||
logic BPBranchD, BPJumpD, BPReturnD, BPCallD;
|
||||
logic ReturnD, CallD;
|
||||
logic ReturnE, CallE;
|
||||
logic BranchM, JumpM, ReturnM, CallM;
|
||||
logic BranchW, JumpW, ReturnW, CallW;
|
||||
logic BPReturnWrongD;
|
||||
logic [`XLEN-1:0] BPBTAE;
|
||||
|
||||
// Part 1 branch direction prediction
|
||||
// look into the 2 port Sram model. something is wrong.
|
||||
@ -128,7 +126,7 @@ module bpred (
|
||||
gsharebasic #(`BPRED_SIZE, 0) DirPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
|
||||
.PCNextF, .PCM, .BPDirPredF, .BPDirPredWrongE,
|
||||
.BranchE, .BranchM, .PCSrcE);
|
||||
|
||||
|
||||
end else if (`BPRED_TYPE == "BPLOCALPAg") begin:Predictor
|
||||
// *** Fix me
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
@ -149,25 +147,25 @@ module bpred (
|
||||
|
||||
btb #(`BTB_SIZE)
|
||||
TargetPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
|
||||
.PCNextF, .PCF, .PCD, .PCE, .PCM,
|
||||
.BPBTAF, .BPBTAD, .BPBTAE,
|
||||
.BTBIClassF({BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF}),
|
||||
.IClassWrongM, .IClassWrongE,
|
||||
.IEUAdrE, .IEUAdrM,
|
||||
.InstrClassD({CallD, ReturnD, JumpD, BranchD}),
|
||||
.InstrClassE({CallE, ReturnE, JumpE, BranchE}),
|
||||
.InstrClassM({CallM, ReturnM, JumpM, BranchM}),
|
||||
.InstrClassW({CallW, ReturnW, JumpW, BranchW}));
|
||||
.PCNextF, .PCF, .PCD, .PCE, .PCM,
|
||||
.BPBTAF, .BPBTAD, .BPBTAE,
|
||||
.BTBIClassF({BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF}),
|
||||
.IClassWrongM, .IClassWrongE,
|
||||
.IEUAdrE, .IEUAdrM,
|
||||
.InstrClassD({CallD, ReturnD, JumpD, BranchD}),
|
||||
.InstrClassE({CallE, ReturnE, JumpE, BranchE}),
|
||||
.InstrClassM({CallM, ReturnM, JumpM, BranchM}),
|
||||
.InstrClassW({CallW, ReturnW, JumpW, BranchW}));
|
||||
|
||||
icpred #(`INSTR_CLASS_PRED) icpred(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
|
||||
.PostSpillInstrRawF, .InstrD, .BranchD, .BranchE, .JumpD, .JumpE, .BranchM, .BranchW, .JumpM, .JumpW,
|
||||
.CallD, .CallE, .CallM, .CallW, .ReturnD, .ReturnE, .ReturnM, .ReturnW, .BTBCallF, .BTBReturnF, .BTBJumpF,
|
||||
.BTBBranchF, .BPCallF, .BPReturnF, .BPJumpF, .BPBranchF, .IClassWrongM, .IClassWrongE, .BPReturnWrongD);
|
||||
.PostSpillInstrRawF, .InstrD, .BranchD, .BranchE, .JumpD, .JumpE, .BranchM, .BranchW, .JumpM, .JumpW,
|
||||
.CallD, .CallE, .CallM, .CallW, .ReturnD, .ReturnE, .ReturnM, .ReturnW, .BTBCallF, .BTBReturnF, .BTBJumpF,
|
||||
.BTBBranchF, .BPCallF, .BPReturnF, .BPJumpF, .BPBranchF, .IClassWrongM, .IClassWrongE, .BPReturnWrongD);
|
||||
|
||||
// Part 3 RAS
|
||||
RASPredictor RASPredictor(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM,
|
||||
.BPReturnF, .ReturnD, .ReturnE, .CallE,
|
||||
.BPReturnWrongD, .RASPCF, .PCLinkE);
|
||||
.BPReturnF, .ReturnD, .ReturnE, .CallE,
|
||||
.BPReturnWrongD, .RASPCF, .PCLinkE);
|
||||
|
||||
// Check the prediction
|
||||
// if it is a CFI then check if the next instruction address (PCD) matches the branch's target or fallthrough address.
|
||||
@ -192,11 +190,11 @@ module bpred (
|
||||
// If the fence/csrw was predicted as a taken branch then we select PCF, rather PCE.
|
||||
// Effectively this is PCM+4 or the non-existant PCLinkM
|
||||
if(`INSTR_CLASS_PRED) mux2 #(`XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPWrongM, NextValidPCE);
|
||||
else assign NextValidPCE = PCE;
|
||||
else assign NextValidPCE = PCE;
|
||||
|
||||
if(`ZICOUNTERS_SUPPORTED) begin
|
||||
logic [`XLEN-1:0] RASPCD, RASPCE;
|
||||
logic BTAWrongE, RASPredPCWrongE;
|
||||
logic [`XLEN-1:0] RASPCD, RASPCE;
|
||||
logic BTAWrongE, RASPredPCWrongE;
|
||||
// performance counters
|
||||
// 1. class (class wrong / minstret) (IClassWrongM / csr) // Correct now
|
||||
// 2. target btb (btb target wrong / class[0,1,3]) (btb target wrong / (br + j + jal)
|
||||
@ -207,15 +205,15 @@ module bpred (
|
||||
// could be wrong or the fall through address selected for branch predict not taken.
|
||||
// By pipeline the BTB's PC and RAS address through the pipeline we can measure the accuracy of
|
||||
// both without the above inaccuracies.
|
||||
// **** use BPBTAWrongM from BTB.
|
||||
// **** use BPBTAWrongM from BTB.
|
||||
assign BTAWrongE = (BPBTAE != IEUAdrE) & (BranchE | JumpE & ~ReturnE) & PCSrcE;
|
||||
assign RASPredPCWrongE = (RASPCE != IEUAdrE) & ReturnE & PCSrcE;
|
||||
|
||||
flopenrc #(`XLEN) RASTargetDReg(clk, reset, FlushD, ~StallD, RASPCF, RASPCD);
|
||||
flopenrc #(`XLEN) RASTargetEReg(clk, reset, FlushE, ~StallE, RASPCD, RASPCE);
|
||||
flopenrc #(3) BPPredWrongRegM(clk, reset, FlushM, ~StallM,
|
||||
{BPDirPredWrongE, BTAWrongE, RASPredPCWrongE},
|
||||
{BPDirPredWrongM, BTAWrongM, RASPredPCWrongM});
|
||||
{BPDirPredWrongE, BTAWrongE, RASPredPCWrongE},
|
||||
{BPDirPredWrongM, BTAWrongM, RASPredPCWrongM});
|
||||
|
||||
end else begin
|
||||
assign {BTAWrongM, RASPredPCWrongM} = '0;
|
||||
|
@ -31,34 +31,34 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module btb #(parameter Depth = 10 ) (
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW, FlushD, FlushE, FlushM, FlushW,
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW, FlushD, FlushE, FlushM, FlushW,
|
||||
input logic [`XLEN-1:0] PCNextF, PCF, PCD, PCE, PCM,// PC at various stages
|
||||
output logic [`XLEN-1:0] BPBTAF, // BTB's guess at PC
|
||||
output logic [`XLEN-1:0] BPBTAD,
|
||||
output logic [`XLEN-1:0] BPBTAE,
|
||||
output logic [3:0] BTBIClassF, // BTB's guess at instruction class
|
||||
output logic [3:0] BTBIClassF, // BTB's guess at instruction class
|
||||
// update
|
||||
input logic IClassWrongM, // BTB's instruction class guess was wrong
|
||||
input logic IClassWrongM, // BTB's instruction class guess was wrong
|
||||
input logic IClassWrongE,
|
||||
input logic [`XLEN-1:0] IEUAdrE, // Branch/jump target address to insert into btb
|
||||
input logic [`XLEN-1:0] IEUAdrM, // Branch/jump target address to insert into btb
|
||||
input logic [3:0] InstrClassD, // Instruction class to insert into btb
|
||||
input logic [3:0] InstrClassE, // Instruction class to insert into btb
|
||||
input logic [3:0] InstrClassM, // Instruction class to insert into btb
|
||||
input logic [3:0] InstrClassD, // Instruction class to insert into btb
|
||||
input logic [3:0] InstrClassE, // Instruction class to insert into btb
|
||||
input logic [3:0] InstrClassM, // Instruction class to insert into btb
|
||||
input logic [3:0] InstrClassW
|
||||
);
|
||||
|
||||
logic [Depth-1:0] PCNextFIndex, PCFIndex, PCDIndex, PCEIndex, PCMIndex, PCWIndex;
|
||||
logic [`XLEN-1:0] ResetPC;
|
||||
logic MatchD, MatchE, MatchM, MatchW, MatchX;
|
||||
logic [`XLEN+3:0] ForwardBTBPrediction, ForwardBTBPredictionF;
|
||||
logic [`XLEN+3:0] TableBTBPredF;
|
||||
logic [`XLEN-1:0] IEUAdrW;
|
||||
logic [Depth-1:0] PCNextFIndex, PCFIndex, PCDIndex, PCEIndex, PCMIndex, PCWIndex;
|
||||
logic [`XLEN-1:0] ResetPC;
|
||||
logic MatchD, MatchE, MatchM, MatchW, MatchX;
|
||||
logic [`XLEN+3:0] ForwardBTBPrediction, ForwardBTBPredictionF;
|
||||
logic [`XLEN+3:0] TableBTBPredF;
|
||||
logic [`XLEN-1:0] IEUAdrW;
|
||||
logic [`XLEN-1:0] PCW;
|
||||
logic BTBWrongE, BPBTAWrongE;
|
||||
logic BTBWrongM, BPBTAWrongM;
|
||||
logic BTBWrongE, BPBTAWrongE;
|
||||
logic BTBWrongM, BPBTAWrongM;
|
||||
|
||||
|
||||
// hashing function for indexing the PC
|
||||
@ -111,5 +111,4 @@ module btb #(parameter Depth = 10 ) (
|
||||
flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW);
|
||||
flopenr #(`XLEN) IEUAdrWReg(clk, reset, ~StallW, IEUAdrM, IEUAdrW);
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -42,30 +42,30 @@ module gshare #(parameter k = 10,
|
||||
input logic BPBranchF, BranchD, BranchE, BranchM, BranchW, PCSrcE
|
||||
);
|
||||
|
||||
logic MatchF, MatchD, MatchE, MatchM, MatchW;
|
||||
logic MatchX;
|
||||
logic MatchF, MatchD, MatchE, MatchM, MatchW;
|
||||
logic MatchX;
|
||||
|
||||
logic [1:0] TableBPDirPredF, BPDirPredD, BPDirPredE, FwdNewDirPredF;
|
||||
logic [1:0] NewBPDirPredE, NewBPDirPredM, NewBPDirPredW;
|
||||
logic [1:0] TableBPDirPredF, BPDirPredD, BPDirPredE, FwdNewDirPredF;
|
||||
logic [1:0] NewBPDirPredE, NewBPDirPredM, NewBPDirPredW;
|
||||
|
||||
logic [k-1:0] IndexNextF, IndexF, IndexD, IndexE, IndexM, IndexW;
|
||||
logic [k-1:0] IndexNextF, IndexF, IndexD, IndexE, IndexM, IndexW;
|
||||
|
||||
logic [k-1:0] GHRF, GHRD, GHRE, GHRM;
|
||||
logic [k-1:0] GHRNextM, GHRNextF;
|
||||
logic PCSrcM;
|
||||
logic [k-1:0] GHRF, GHRD, GHRE, GHRM;
|
||||
logic [k-1:0] GHRNextM, GHRNextF;
|
||||
logic PCSrcM;
|
||||
|
||||
if(TYPE == 1) begin
|
||||
assign IndexNextF = GHRNextF ^ {PCNextF[k+1] ^ PCNextF[1], PCNextF[k:2]};
|
||||
assign IndexF = GHRF ^ {PCF[k+1] ^ PCF[1], PCF[k:2]};
|
||||
assign IndexD = GHRD ^ {PCD[k+1] ^ PCD[1], PCD[k:2]};
|
||||
assign IndexE = GHRE ^ {PCE[k+1] ^ PCE[1], PCE[k:2]};
|
||||
assign IndexM = GHRM ^ {PCM[k+1] ^ PCM[1], PCM[k:2]};
|
||||
assign IndexNextF = GHRNextF ^ {PCNextF[k+1] ^ PCNextF[1], PCNextF[k:2]};
|
||||
assign IndexF = GHRF ^ {PCF[k+1] ^ PCF[1], PCF[k:2]};
|
||||
assign IndexD = GHRD ^ {PCD[k+1] ^ PCD[1], PCD[k:2]};
|
||||
assign IndexE = GHRE ^ {PCE[k+1] ^ PCE[1], PCE[k:2]};
|
||||
assign IndexM = GHRM ^ {PCM[k+1] ^ PCM[1], PCM[k:2]};
|
||||
end else if(TYPE == 0) begin
|
||||
assign IndexNextF = GHRNextF;
|
||||
assign IndexF = GHRF;
|
||||
assign IndexD = GHRD;
|
||||
assign IndexE = GHRE;
|
||||
assign IndexM = GHRM;
|
||||
assign IndexNextF = GHRNextF;
|
||||
assign IndexF = GHRF;
|
||||
assign IndexD = GHRD;
|
||||
assign IndexE = GHRE;
|
||||
assign IndexM = GHRM;
|
||||
end
|
||||
|
||||
flopenrc #(k) IndexWReg(clk, reset, FlushW, ~StallW, IndexM, IndexW);
|
||||
@ -79,7 +79,7 @@ module gshare #(parameter k = 10,
|
||||
assign FwdNewDirPredF = MatchD ? {2{BPDirPredD[1]}} :
|
||||
MatchE ? {NewBPDirPredE} :
|
||||
MatchM ? {NewBPDirPredM} :
|
||||
NewBPDirPredW ;
|
||||
NewBPDirPredW ;
|
||||
|
||||
assign BPDirPredF = MatchX ? FwdNewDirPredF : TableBPDirPredF;
|
||||
|
||||
|
@ -42,20 +42,20 @@ module gsharebasic #(parameter k = 10,
|
||||
input logic BranchE, BranchM, PCSrcE
|
||||
);
|
||||
|
||||
logic [k-1:0] IndexNextF, IndexM;
|
||||
logic [1:0] BPDirPredD, BPDirPredE;
|
||||
logic [1:0] NewBPDirPredE, NewBPDirPredM;
|
||||
logic [k-1:0] IndexNextF, IndexM;
|
||||
logic [1:0] BPDirPredD, BPDirPredE;
|
||||
logic [1:0] NewBPDirPredE, NewBPDirPredM;
|
||||
|
||||
logic [k-1:0] GHRF, GHRD, GHRE, GHRM, GHR;
|
||||
logic [k-1:0] GHRNext;
|
||||
logic PCSrcM;
|
||||
logic [k-1:0] GHRF, GHRD, GHRE, GHRM, GHR;
|
||||
logic [k-1:0] GHRNext;
|
||||
logic PCSrcM;
|
||||
|
||||
if(TYPE == 1) begin
|
||||
assign IndexNextF = GHR ^ {PCNextF[k+1] ^ PCNextF[1], PCNextF[k:2]};
|
||||
assign IndexM = GHRM ^ {PCM[k+1] ^ PCM[1], PCM[k:2]};
|
||||
assign IndexNextF = GHR ^ {PCNextF[k+1] ^ PCNextF[1], PCNextF[k:2]};
|
||||
assign IndexM = GHRM ^ {PCM[k+1] ^ PCM[1], PCM[k:2]};
|
||||
end else if(TYPE == 0) begin
|
||||
assign IndexNextF = GHRNext;
|
||||
assign IndexM = GHRM;
|
||||
assign IndexNextF = GHRNext;
|
||||
assign IndexM = GHRM;
|
||||
end
|
||||
|
||||
ram2p1r1wbe #(2**k, 2) PHT(.clk(clk),
|
||||
|
@ -45,16 +45,16 @@ module icpred #(parameter INSTR_CLASS_PRED = 1)(
|
||||
output logic IClassWrongM, BPReturnWrongD, IClassWrongE
|
||||
);
|
||||
|
||||
logic IClassWrongD;
|
||||
logic BPBranchD, BPJumpD, BPReturnD, BPCallD;
|
||||
logic IClassWrongD;
|
||||
logic BPBranchD, BPJumpD, BPReturnD, BPCallD;
|
||||
|
||||
if (!INSTR_CLASS_PRED) begin : DirectClassDecode
|
||||
// This section is mainly for testing, verification, and PPA comparison.
|
||||
// An alternative to using the BTB to store the instruction class is to partially decode
|
||||
// the instructions in the Fetch stage into, Call, Return, Jump, and Branch instructions.
|
||||
// This logic is not described in the text book as of 23 February 2023.
|
||||
logic ccall, cj, cjr, ccallr, CJumpF, CBranchF;
|
||||
logic NCJumpF, NCBranchF;
|
||||
logic ccall, cj, cjr, ccallr, CJumpF, CBranchF;
|
||||
logic NCJumpF, NCBranchF;
|
||||
|
||||
if(`C_SUPPORTED) begin
|
||||
logic [4:0] CompressedOpcF;
|
||||
@ -75,10 +75,10 @@ module icpred #(parameter INSTR_CLASS_PRED = 1)(
|
||||
assign BPBranchF = NCBranchF | (`C_SUPPORTED & CBranchF);
|
||||
assign BPJumpF = NCJumpF | (`C_SUPPORTED & (CJumpF));
|
||||
assign BPReturnF = (NCJumpF & (PostSpillInstrRawF[19:15] & 5'h1B) == 5'h01) | // returnurn must returnurn to ra or r5
|
||||
(`C_SUPPORTED & (ccallr | cjr) & ((PostSpillInstrRawF[11:7] & 5'h1B) == 5'h01));
|
||||
(`C_SUPPORTED & (ccallr | cjr) & ((PostSpillInstrRawF[11:7] & 5'h1B) == 5'h01));
|
||||
|
||||
assign BPCallF = (NCJumpF & (PostSpillInstrRawF[11:07] & 5'h1B) == 5'h01) | // call(r) must link to ra or x5
|
||||
(`C_SUPPORTED & (ccall | (ccallr & (PostSpillInstrRawF[11:7] & 5'h1b) == 5'h01)));
|
||||
(`C_SUPPORTED & (ccall | (ccallr & (PostSpillInstrRawF[11:7] & 5'h1b) == 5'h01)));
|
||||
|
||||
end else begin
|
||||
// This section connects the BTB's instruction class prediction.
|
||||
|
198
src/ifu/ifu.sv
198
src/ifu/ifu.sv
@ -28,116 +28,116 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module ifu (
|
||||
input logic clk, reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation
|
||||
input logic clk, reset,
|
||||
input logic StallF, StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
output logic IFUStallF, // IFU stalsl pipeline during a multicycle operation
|
||||
// Command from CPU
|
||||
input logic InvalidateICacheM, // Clears all instruction cache valid bits
|
||||
input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE)
|
||||
input logic InstrValidD, InstrValidE, InstrValidM,
|
||||
input logic BranchD, BranchE,
|
||||
input logic JumpD, JumpE,
|
||||
// Bus interface
|
||||
output logic [`PA_BITS-1:0] IFUHADDR, // Bus address from IFU to EBU
|
||||
input logic [`XLEN-1:0] HRDATA, // Bus read data from IFU to EBU
|
||||
input logic IFUHREADY, // Bus ready from IFU to EBU
|
||||
output logic IFUHWRITE, // Bus write operation from IFU to EBU
|
||||
output logic [2:0] IFUHSIZE, // Bus operation size from IFU to EBU
|
||||
output logic [2:0] IFUHBURST, // Bus burst from IFU to EBU
|
||||
output logic [1:0] IFUHTRANS, // Bus transaction type from IFU to EBU
|
||||
input logic InvalidateICacheM, // Clears all instruction cache valid bits
|
||||
input logic CSRWriteFenceM, // CSR write or fence instruction, PCNextF = the next valid PC (typically PCE)
|
||||
input logic InstrValidD, InstrValidE, InstrValidM,
|
||||
input logic BranchD, BranchE,
|
||||
input logic JumpD, JumpE,
|
||||
// Bus interface
|
||||
output logic [`PA_BITS-1:0] IFUHADDR, // Bus address from IFU to EBU
|
||||
input logic [`XLEN-1:0] HRDATA, // Bus read data from IFU to EBU
|
||||
input logic IFUHREADY, // Bus ready from IFU to EBU
|
||||
output logic IFUHWRITE, // Bus write operation from IFU to EBU
|
||||
output logic [2:0] IFUHSIZE, // Bus operation size from IFU to EBU
|
||||
output logic [2:0] IFUHBURST, // Bus burst from IFU to EBU
|
||||
output logic [1:0] IFUHTRANS, // Bus transaction type from IFU to EBU
|
||||
|
||||
output logic [`XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW
|
||||
output logic [`XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW
|
||||
// Execute
|
||||
output logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
||||
input logic PCSrcE, // Executation stage branch is taken
|
||||
input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address
|
||||
input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address
|
||||
output logic [`XLEN-1:0] PCE, // Execution stage instruction address
|
||||
output logic BPWrongE, // Prediction is wrong
|
||||
output logic BPWrongM, // Prediction is wrong
|
||||
output logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
||||
input logic PCSrcE, // Executation stage branch is taken
|
||||
input logic [`XLEN-1:0] IEUAdrE, // The branch/jump target address
|
||||
input logic [`XLEN-1:0] IEUAdrM, // The branch/jump target address
|
||||
output logic [`XLEN-1:0] PCE, // Execution stage instruction address
|
||||
output logic BPWrongE, // Prediction is wrong
|
||||
output logic BPWrongM, // Prediction is wrong
|
||||
// Mem
|
||||
output logic CommittedF, // I$ or bus memory operation started, delay interrupts
|
||||
input logic [`XLEN-1:0] UnalignedPCNextF, // The next PCF, but not aligned to 2 bytes.
|
||||
output logic [`XLEN-1:0] PC2NextF, // Selected PC between branch prediction and next valid PC if CSRWriteFence
|
||||
output logic [31:0] InstrD, // The decoded instruction in Decode stage
|
||||
output logic [31:0] InstrM, // The decoded instruction in Memory stage
|
||||
output logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||
output logic [`XLEN-1:0] PCM, // Memory stage instruction address
|
||||
output logic CommittedF, // I$ or bus memory operation started, delay interrupts
|
||||
input logic [`XLEN-1:0] UnalignedPCNextF, // The next PCF, but not aligned to 2 bytes.
|
||||
output logic [`XLEN-1:0] PC2NextF, // Selected PC between branch prediction and next valid PC if CSRWriteFence
|
||||
output logic [31:0] InstrD, // The decoded instruction in Decode stage
|
||||
output logic [31:0] InstrM, // The decoded instruction in Memory stage
|
||||
output logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||
output logic [`XLEN-1:0] PCM, // Memory stage instruction address
|
||||
// branch predictor
|
||||
output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br
|
||||
output logic BPDirPredWrongM, // Prediction direction is wrong
|
||||
output logic BTAWrongM, // Prediction target wrong
|
||||
output logic RASPredPCWrongM, // RAS prediction is wrong
|
||||
output logic IClassWrongM, // Class prediction is wrong
|
||||
output logic ICacheStallF, // I$ busy with multicycle operation
|
||||
output logic [3:0] InstrClassM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br
|
||||
output logic BPDirPredWrongM, // Prediction direction is wrong
|
||||
output logic BTAWrongM, // Prediction target wrong
|
||||
output logic RASPredPCWrongM, // RAS prediction is wrong
|
||||
output logic IClassWrongM, // Class prediction is wrong
|
||||
output logic ICacheStallF, // I$ busy with multicycle operation
|
||||
// Faults
|
||||
input logic IllegalBaseInstrD, // Illegal non-compressed instruction
|
||||
input logic IllegalFPUInstrD, // Illegal FP instruction
|
||||
output logic InstrPageFaultF, // Instruction page fault
|
||||
output logic IllegalIEUFPUInstrD, // Illegal instruction including compressed & FP
|
||||
output logic InstrMisalignedFaultM, // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||
input logic IllegalBaseInstrD, // Illegal non-compressed instruction
|
||||
input logic IllegalFPUInstrD, // Illegal FP instruction
|
||||
output logic InstrPageFaultF, // Instruction page fault
|
||||
output logic IllegalIEUFPUInstrD, // Illegal instruction including compressed & FP
|
||||
output logic InstrMisalignedFaultM, // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||
// mmu management
|
||||
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
|
||||
input logic [`XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
|
||||
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
|
||||
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
|
||||
input logic [`XLEN-1:0] SATP_REGW, // Location of the root page table and page table configuration
|
||||
input logic STATUS_MXR, // Status CSR: make executable page readable
|
||||
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
||||
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
||||
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
|
||||
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
||||
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||
output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
||||
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
||||
input var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP address from privileged unit
|
||||
output logic InstrAccessFaultF, // Instruction access fault
|
||||
output logic ICacheAccess, // Report I$ read to performance counters
|
||||
output logic ICacheMiss // Report I$ miss to performance counters
|
||||
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
|
||||
input logic [`XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
|
||||
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
|
||||
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
|
||||
input logic [`XLEN-1:0] SATP_REGW, // Location of the root page table and page table configuration
|
||||
input logic STATUS_MXR, // Status CSR: make executable page readable
|
||||
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
|
||||
input logic STATUS_MPRV, // Status CSR: modify machine privilege
|
||||
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
|
||||
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
|
||||
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||
output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
||||
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
||||
input var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP address from privileged unit
|
||||
output logic InstrAccessFaultF, // Instruction access fault
|
||||
output logic ICacheAccess, // Report I$ read to performance counters
|
||||
output logic ICacheMiss // Report I$ miss to performance counters
|
||||
);
|
||||
|
||||
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
||||
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
||||
|
||||
logic [`XLEN-1:0] PCNextF; // Next PCF, selected from Branch predictor, Privilege, or PC+2/4
|
||||
logic BranchMisalignedFaultE; // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||
logic [`XLEN-1:0] PCPlus2or4F; // PCF + 2 (CompressedF) or PCF + 4 (Non-compressed)
|
||||
logic [`XLEN-1:0] PCSpillNextF; // Next PCF after possible + 2 to handle spill
|
||||
logic [`XLEN-1:0] PCLinkD; // PCF2or4F delayed 1 cycle. This is next PC after a control flow instruction (br or j)
|
||||
logic [`XLEN-1:2] PCPlus4F; // PCPlus4F is always PCF + 4. Fancy way to compute PCPlus2or4F
|
||||
logic [`XLEN-1:0] PCD; // Decode stage instruction address
|
||||
logic [`XLEN-1:0] NextValidPCE; // The PC of the next valid instruction in the pipeline after csr write or fence
|
||||
logic [`XLEN-1:0] PCF; // Fetch stage instruction address
|
||||
logic [`PA_BITS-1:0] PCPF; // Physical address after address translation
|
||||
logic [`XLEN+1:0] PCFExt; //
|
||||
logic [`XLEN-1:0] PCNextF; // Next PCF, selected from Branch predictor, Privilege, or PC+2/4
|
||||
logic BranchMisalignedFaultE; // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||
logic [`XLEN-1:0] PCPlus2or4F; // PCF + 2 (CompressedF) or PCF + 4 (Non-compressed)
|
||||
logic [`XLEN-1:0] PCSpillNextF; // Next PCF after possible + 2 to handle spill
|
||||
logic [`XLEN-1:0] PCLinkD; // PCF2or4F delayed 1 cycle. This is next PC after a control flow instruction (br or j)
|
||||
logic [`XLEN-1:2] PCPlus4F; // PCPlus4F is always PCF + 4. Fancy way to compute PCPlus2or4F
|
||||
logic [`XLEN-1:0] PCD; // Decode stage instruction address
|
||||
logic [`XLEN-1:0] NextValidPCE; // The PC of the next valid instruction in the pipeline after csr write or fence
|
||||
logic [`XLEN-1:0] PCF; // Fetch stage instruction address
|
||||
logic [`PA_BITS-1:0] PCPF; // Physical address after address translation
|
||||
logic [`XLEN+1:0] PCFExt; //
|
||||
|
||||
logic [31:0] IROMInstrF; // Instruction from the IROM
|
||||
logic [31:0] ICacheInstrF; // Instruction from the I$
|
||||
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
||||
logic CompressedF; // The fetched instruction is compressed
|
||||
logic CompressedD; // The decoded instruction is compressed
|
||||
logic CompressedE; // The execution instruction is compressed
|
||||
logic CompressedM; // The execution instruction is compressed
|
||||
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
||||
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
||||
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
||||
logic [31:0] IROMInstrF; // Instruction from the IROM
|
||||
logic [31:0] ICacheInstrF; // Instruction from the I$
|
||||
logic [31:0] InstrRawF; // Instruction from the IROM, I$, or bus
|
||||
logic CompressedF; // The fetched instruction is compressed
|
||||
logic CompressedD; // The decoded instruction is compressed
|
||||
logic CompressedE; // The execution instruction is compressed
|
||||
logic CompressedM; // The execution instruction is compressed
|
||||
logic [31:0] PostSpillInstrRawF; // Fetch instruction after merge two halves of spill
|
||||
logic [31:0] InstrRawD; // Non-decompressed instruction in the Decode stage
|
||||
logic IllegalIEUInstrD; // IEU Instruction (regular or compressed) is not good
|
||||
|
||||
logic [1:0] IFURWF; // IFU alreays read IFURWF = 10
|
||||
logic [31:0] InstrE; // Instruction in the Execution stage
|
||||
logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush
|
||||
logic [1:0] IFURWF; // IFU alreays read IFURWF = 10
|
||||
logic [31:0] InstrE; // Instruction in the Execution stage
|
||||
logic [31:0] NextInstrD, NextInstrE; // Instruction into the next stage after possible stage flush
|
||||
|
||||
|
||||
logic CacheableF; // PMA indicates instruction address is cacheable
|
||||
logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF
|
||||
logic BusStall; // Bus interface busy with multicycle operation
|
||||
logic IFUCacheBusStallD; // EIther I$ or bus busy with multicycle operation
|
||||
logic GatedStallD; // StallD gated by selected next spill
|
||||
logic CacheableF; // PMA indicates instruction address is cacheable
|
||||
logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF
|
||||
logic BusStall; // Bus interface busy with multicycle operation
|
||||
logic IFUCacheBusStallD; // EIther I$ or bus busy with multicycle operation
|
||||
logic GatedStallD; // StallD gated by selected next spill
|
||||
// branch predictor signal
|
||||
logic [`XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
||||
logic BusCommittedF; // Bus memory operation in flight, delay interrupts
|
||||
logic CacheCommittedF; // I$ memory operation started, delay interrupts
|
||||
logic SelIROM; // PMA indicates instruction address is in the IROM
|
||||
logic [15:0] InstrRawE, InstrRawM;
|
||||
logic [`XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
||||
logic BusCommittedF; // Bus memory operation in flight, delay interrupts
|
||||
logic CacheCommittedF; // I$ memory operation started, delay interrupts
|
||||
logic SelIROM; // PMA indicates instruction address is in the IROM
|
||||
logic [15:0] InstrRawE, InstrRawM;
|
||||
|
||||
assign PCFExt = {2'b00, PCSpillF};
|
||||
|
||||
@ -208,13 +208,13 @@ module ifu (
|
||||
// delay the interrupt until the LSU is in a clean state.
|
||||
assign CommittedF = CacheCommittedF | BusCommittedF;
|
||||
|
||||
logic IgnoreRequest;
|
||||
logic IgnoreRequest;
|
||||
assign IgnoreRequest = ITLBMissF | FlushD;
|
||||
|
||||
// The IROM uses untranslated addresses, so it is not compatible with virtual memory.
|
||||
if (`IROM_SUPPORTED) begin : irom
|
||||
logic IROMce;
|
||||
assign IROMce = ~GatedStallD | reset;
|
||||
logic IROMce;
|
||||
assign IROMce = ~GatedStallD | reset;
|
||||
assign IFURWF = 2'b10;
|
||||
irom irom(.clk, .ce(IROMce), .Adr(PCSpillNextF[`XLEN-1:0]), .IROMInstrF);
|
||||
end else begin
|
||||
@ -251,7 +251,7 @@ module ifu (
|
||||
.NextSet(PCSpillNextF[11:0]),
|
||||
.PAdr(PCPF),
|
||||
.CacheCommitted(CacheCommittedF), .InvalidateCache(InvalidateICacheM));
|
||||
ahbcacheinterface #(WORDSPERLINE, LOGBWPL, LINELEN, LLENPOVERAHBW)
|
||||
ahbcacheinterface #(WORDSPERLINE, LOGBWPL, LINELEN, LLENPOVERAHBW, 1)
|
||||
ahbcacheinterface(.HCLK(clk), .HRESETn(~reset),
|
||||
.HRDATA,
|
||||
.Flush(FlushD), .CacheBusRW, .HSIZE(IFUHSIZE), .HBURST(IFUHBURST), .HTRANS(IFUHTRANS), .HWSTRB(),
|
||||
|
@ -27,10 +27,10 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module irom(
|
||||
input logic clk,
|
||||
input logic ce, // Chip Enable. 0: Holds IROMInstrF constant
|
||||
input logic clk,
|
||||
input logic ce, // Chip Enable. 0: Holds IROMInstrF constant
|
||||
input logic [`XLEN-1:0] Adr, // PCNextFSpill
|
||||
output logic [31:0] IROMInstrF // Instruction read data
|
||||
output logic [31:0] IROMInstrF // Instruction read data
|
||||
);
|
||||
|
||||
localparam XLENBYTES = `XLEN/8;
|
||||
@ -38,16 +38,16 @@ module irom(
|
||||
localparam OFFSET = $clog2(XLENBYTES);
|
||||
|
||||
logic [`XLEN-1:0] IROMInstrFFull;
|
||||
logic [31:0] RawIROMInstrF;
|
||||
logic [31:0] RawIROMInstrF;
|
||||
|
||||
logic [1:0] AdrD;
|
||||
logic [1:0] AdrD;
|
||||
flopen #(2) AdrReg(clk, ce, Adr[2:1], AdrD);
|
||||
|
||||
rom1p1r #(ADDR_WDITH, `XLEN) rom(.clk, .ce, .addr(Adr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(IROMInstrFFull));
|
||||
if (`XLEN == 32) assign RawIROMInstrF = IROMInstrFFull;
|
||||
else begin
|
||||
// IROM is aligned to XLEN words, but instructions are 32 bits. Select between the two
|
||||
// haves. Adr is the Next PCF not PCF so we delay 1 cycle.
|
||||
// IROM is aligned to XLEN words, but instructions are 32 bits. Select between the two
|
||||
// haves. Adr is the Next PCF not PCF so we delay 1 cycle.
|
||||
assign RawIROMInstrF = AdrD[1] ? IROMInstrFFull[63:32] : IROMInstrFFull[31:0];
|
||||
end
|
||||
// If the memory addres is aligned to 2 bytes return the upper 2 bytes in the lower 2 bytes.
|
||||
|
@ -34,31 +34,32 @@
|
||||
module spill #(
|
||||
parameter CACHE_ENABLED // Changes spill threshold to 1 if there is no cache
|
||||
)(input logic clk,
|
||||
input logic reset,
|
||||
input logic StallD, FlushD,
|
||||
input logic reset,
|
||||
input logic StallD, FlushD,
|
||||
input logic [`XLEN-1:0] PCF, // 2 byte aligned PC in Fetch stage
|
||||
input logic [`XLEN-1:2] PCPlus4F, // PCF + 4
|
||||
input logic [`XLEN-1:0] PCNextF, // The next PCF
|
||||
input logic [31:0] InstrRawF, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
|
||||
input logic IFUCacheBusStallD, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
|
||||
input logic ITLBMissF, // ITLB miss, ignore memory request
|
||||
input logic InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
|
||||
input logic [31:0] InstrRawF, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
|
||||
input logic IFUCacheBusStallD, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
|
||||
input logic ITLBMissF, // ITLB miss, ignore memory request
|
||||
input logic InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
|
||||
output logic [`XLEN-1:0] PCSpillNextF, // The next PCF for one of the two memory addresses of the spill
|
||||
output logic [`XLEN-1:0] PCSpillF, // PCF for one of the two memory addresses of the spill
|
||||
output logic SelSpillNextF, // During the transition between the two spill operations, the IFU should stall the pipeline
|
||||
output logic [31:0] PostSpillInstrRawF,// The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
||||
output logic CompressedF); // The fetched instruction is compressed
|
||||
output logic SelSpillNextF, // During the transition between the two spill operations, the IFU should stall the pipeline
|
||||
output logic [31:0] PostSpillInstrRawF,// The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
||||
output logic CompressedF); // The fetched instruction is compressed
|
||||
|
||||
// Spill threshold occurs when all the cache offset PC bits are 1 (except [0]). Without a cache this is just PCF[1]
|
||||
typedef enum logic [1:0] {STATE_READY, STATE_SPILL} statetype;
|
||||
statetype CurrState, NextState;
|
||||
localparam SPILLTHRESHOLD = CACHE_ENABLED ? `ICACHE_LINELENINBITS/32 : 1;
|
||||
logic [`XLEN-1:0] PCPlus2F;
|
||||
logic TakeSpillF;
|
||||
logic SpillF;
|
||||
logic SelSpillF;
|
||||
logic SpillSaveF;
|
||||
logic [15:0] InstrFirstHalfF;
|
||||
|
||||
statetype CurrState, NextState;
|
||||
logic [`XLEN-1:0] PCPlus2F;
|
||||
logic TakeSpillF;
|
||||
logic SpillF;
|
||||
logic SelSpillF;
|
||||
logic SpillSaveF;
|
||||
logic [15:0] InstrFirstHalfF;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PC logic
|
||||
@ -109,7 +110,7 @@ module spill #(
|
||||
|
||||
// Need to use always comb to avoid pessimistic x propagation if PostSpillInstrRawF is x
|
||||
always_comb
|
||||
if (PostSpillInstrRawF[1:0] != 2'b11) CompressedF = 1'b1;
|
||||
else CompressedF = 1'b0;
|
||||
if (PostSpillInstrRawF[1:0] != 2'b11) CompressedF = 1'b1;
|
||||
else CompressedF = 1'b0;
|
||||
|
||||
endmodule
|
||||
|
@ -30,14 +30,14 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module dtim(
|
||||
input logic clk,
|
||||
input logic FlushW,
|
||||
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
|
||||
input logic [1:0] MemRWM, // Read/Write control
|
||||
input logic clk,
|
||||
input logic FlushW,
|
||||
input logic ce, // Chip Enable. 0: Holds ReadDataWordM
|
||||
input logic [1:0] MemRWM, // Read/Write control
|
||||
input logic [`PA_BITS-1:0] DTIMAdr, // No stall: Execution stage memory address. Stall: Memory stage memory address
|
||||
input logic [`LLEN-1:0] WriteDataM, // Write data from IEU
|
||||
input logic [`LLEN-1:0] WriteDataM, // Write data from IEU
|
||||
input logic [`LLEN/8-1:0] ByteMaskM, // Selects which bytes within a word to write
|
||||
output logic [`LLEN-1:0] ReadDataWordM // Read data before subword selection
|
||||
output logic [`LLEN-1:0] ReadDataWordM // Read data before subword selection
|
||||
);
|
||||
|
||||
logic we;
|
||||
|
@ -37,17 +37,17 @@ module lrsc(
|
||||
input logic MemReadM, // Memory read
|
||||
input logic [1:0] PreLSURWM, // Memory operation from the HPTW or IEU [1]: read, [0]: write
|
||||
output logic [1:0] LSURWM, // Memory operation after potential squash of SC
|
||||
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
||||
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
||||
input logic [`PA_BITS-1:0] PAdrM, // Physical memory address
|
||||
output logic SquashSCW // Squash the store conditional by not allowing rf write
|
||||
);
|
||||
|
||||
// possible bug: *** double check if PreLSURWM needs to be flushed by ignorerequest.
|
||||
// Handle atomic load reserved / store conditional
|
||||
logic [`PA_BITS-1:2] ReservationPAdrW;
|
||||
logic ReservationValidM, ReservationValidW;
|
||||
logic lrM, scM, WriteAdrMatchM;
|
||||
logic SquashSCM;
|
||||
logic [`PA_BITS-1:2] ReservationPAdrW;
|
||||
logic ReservationValidM, ReservationValidW;
|
||||
logic lrM, scM, WriteAdrMatchM;
|
||||
logic SquashSCM;
|
||||
|
||||
assign lrM = MemReadM & LSUAtomicM[0];
|
||||
assign scM = PreLSURWM[0] & LSUAtomicM[0];
|
||||
@ -56,7 +56,7 @@ module lrsc(
|
||||
assign LSURWM = SquashSCM ? 2'b00 : PreLSURWM;
|
||||
always_comb begin // ReservationValidM (next value of valid reservation)
|
||||
if (lrM) ReservationValidM = 1; // set valid on load reserve
|
||||
// if we implement multiple harts invalidate reservation if another hart stores to this reservation.
|
||||
// if we implement multiple harts invalidate reservation if another hart stores to this reservation.
|
||||
else if (scM) ReservationValidM = 0; // clear valid on store to same address or any sc
|
||||
else ReservationValidM = ReservationValidW; // otherwise don't change valid
|
||||
end
|
||||
|
110
src/lsu/lsu.sv
110
src/lsu/lsu.sv
@ -78,61 +78,61 @@ module lsu (
|
||||
output logic [`XLEN/8-1:0] LSUHWSTRB, // Bus byte write enables from LSU to EBU
|
||||
// page table walker
|
||||
input logic [`XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
|
||||
input logic [1:0] STATUS_MPP, // Machine previous privilege mode
|
||||
input logic [`XLEN-1:0] PCSpillF, // Fetch PC
|
||||
input logic [`XLEN-1:0] PCSpillF, // Fetch PC
|
||||
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
|
||||
input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
||||
input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
|
||||
output logic [`XLEN-1:0] PTE, // Page table entry write to ITLB
|
||||
output logic [1:0] PageType, // Type of page table entry to write to ITLB
|
||||
output logic ITLBWriteF, // Write PTE to ITLB
|
||||
output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE
|
||||
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
||||
input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration from privileged unit
|
||||
input var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0] // PMP address from privileged unit
|
||||
);
|
||||
|
||||
logic [`XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
|
||||
logic [`XLEN+1:0] IEUAdrExtE; // Execution stage address zero-extended to PA_BITS or XLEN whichever is longer
|
||||
logic [`PA_BITS-1:0] PAdrM; // Physical memory address
|
||||
logic [`XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
|
||||
logic [`XLEN+1:0] IEUAdrExtM; // Memory stage address zero-extended to PA_BITS or XLEN whichever is longer
|
||||
logic [`XLEN+1:0] IEUAdrExtE; // Execution stage address zero-extended to PA_BITS or XLEN whichever is longer
|
||||
logic [`PA_BITS-1:0] PAdrM; // Physical memory address
|
||||
logic [`XLEN+1:0] IHAdrM; // Either IEU or HPTW memory address
|
||||
|
||||
logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
|
||||
logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
|
||||
logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
|
||||
logic [6:0] LSUFunct7M; // AMO function gated by HPTW
|
||||
logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
|
||||
logic [1:0] PreLSURWM; // IEU or HPTW Read/Write signal
|
||||
logic [1:0] LSURWM; // IEU or HPTW Read/Write signal gated by LR/SC
|
||||
logic [2:0] LSUFunct3M; // IEU or HPTW memory operation size
|
||||
logic [6:0] LSUFunct7M; // AMO function gated by HPTW
|
||||
logic [1:0] LSUAtomicM; // AMO signal gated by HPTW
|
||||
|
||||
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
|
||||
|
||||
logic BusStall; // Bus interface busy with multicycle operation
|
||||
logic HPTWStall; // HPTW busy with multicycle operation
|
||||
logic GatedStallW; // Hazard unit StallW gated when SelHPTW = 1
|
||||
|
||||
logic BusStall; // Bus interface busy with multicycle operation
|
||||
logic HPTWStall; // HPTW busy with multicycle operation
|
||||
|
||||
logic CacheableM; // PMA indicates memory address is cacheable
|
||||
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
|
||||
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
|
||||
logic CacheableM; // PMA indicates memory address is cacheable
|
||||
logic BusCommittedM; // Bus memory operation in flight, delay interrupts
|
||||
logic DCacheCommittedM; // D$ memory operation started, delay interrupts
|
||||
|
||||
logic [`LLEN-1:0] DTIMReadDataWordM; // DTIM read data
|
||||
logic [`LLEN-1:0] DCacheReadDataWordM; // D$ read data
|
||||
logic [`LLEN-1:0] ReadDataWordMuxM; // DTIM or D$ read data
|
||||
logic [`LLEN-1:0] LittleEndianReadDataWordM; // Endian-swapped read data
|
||||
logic [`LLEN-1:0] ReadDataWordM; // Read data before subword selection
|
||||
logic [`LLEN-1:0] ReadDataM; // Final read data
|
||||
logic [`LLEN-1:0] DTIMReadDataWordM; // DTIM read data
|
||||
logic [`LLEN-1:0] DCacheReadDataWordM; // D$ read data
|
||||
logic [`LLEN-1:0] ReadDataWordMuxM; // DTIM or D$ read data
|
||||
logic [`LLEN-1:0] LittleEndianReadDataWordM; // Endian-swapped read data
|
||||
logic [`LLEN-1:0] ReadDataWordM; // Read data before subword selection
|
||||
logic [`LLEN-1:0] ReadDataM; // Final read data
|
||||
|
||||
logic [`XLEN-1:0] IHWriteDataM; // IEU or HPTW write data
|
||||
logic [`XLEN-1:0] IMAWriteDataM; // IEU, HPTW, or AMO write data
|
||||
logic [`LLEN-1:0] IMAFWriteDataM; // IEU, HPTW, AMO, or FPU write data
|
||||
logic [`LLEN-1:0] LittleEndianWriteDataM; // Ending-swapped write data
|
||||
logic [`LLEN-1:0] LSUWriteDataM; // Final write data
|
||||
logic [(`LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
|
||||
logic [`XLEN-1:0] IHWriteDataM; // IEU or HPTW write data
|
||||
logic [`XLEN-1:0] IMAWriteDataM; // IEU, HPTW, or AMO write data
|
||||
logic [`LLEN-1:0] IMAFWriteDataM; // IEU, HPTW, AMO, or FPU write data
|
||||
logic [`LLEN-1:0] LittleEndianWriteDataM; // Ending-swapped write data
|
||||
logic [`LLEN-1:0] LSUWriteDataM; // Final write data
|
||||
logic [(`LLEN-1)/8:0] ByteMaskM; // Selects which bytes within a word to write
|
||||
|
||||
logic DTLBMissM; // DTLB miss causes HPTW walk
|
||||
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
||||
logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
|
||||
logic LSULoadAccessFaultM; // Load acces fault
|
||||
logic LSUStoreAmoAccessFaultM; // Store access fault
|
||||
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
|
||||
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
|
||||
logic SelDTIM; // Select DTIM rather than bus or D$
|
||||
logic DTLBMissM; // DTLB miss causes HPTW walk
|
||||
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
||||
logic DataUpdateDAM; // DTLB hit needs to update dirty or access bits
|
||||
logic LSULoadAccessFaultM; // Load acces fault
|
||||
logic LSUStoreAmoAccessFaultM; // Store access fault
|
||||
logic IgnoreRequestTLB; // On either ITLB or DTLB miss, ignore miss so HPTW can handle
|
||||
logic IgnoreRequest; // On FlushM or TLB miss ignore memory operation
|
||||
logic SelDTIM; // Select DTIM rather than bus or D$
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -164,8 +164,8 @@ module lsu (
|
||||
assign PreLSURWM = MemRWM;
|
||||
assign IHAdrM = IEUAdrExtM;
|
||||
assign LSUFunct3M = Funct3M;
|
||||
assign LSUFunct7M = Funct7M;
|
||||
assign LSUAtomicM = AtomicM;
|
||||
assign LSUFunct7M = Funct7M;
|
||||
assign LSUAtomicM = AtomicM;
|
||||
assign IHWriteDataM = WriteDataM;
|
||||
assign LoadAccessFaultM = LSULoadAccessFaultM;
|
||||
assign StoreAmoAccessFaultM = LSUStoreAmoAccessFaultM;
|
||||
@ -194,7 +194,7 @@ module lsu (
|
||||
.PhysicalAddress(PAdrM), .TLBMiss(DTLBMissM), .Cacheable(CacheableM), .Idempotent(), .SelTIM(SelDTIM),
|
||||
.InstrAccessFaultF(), .LoadAccessFaultM(LSULoadAccessFaultM),
|
||||
.StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM,
|
||||
.StoreAmoPageFaultM,
|
||||
.StoreAmoPageFaultM,
|
||||
.LoadMisalignedFaultM, .StoreAmoMisalignedFaultM, // *** these faults need to be supressed during hptw.
|
||||
.UpdateDA(DataUpdateDAM),
|
||||
.AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),
|
||||
@ -227,7 +227,7 @@ module lsu (
|
||||
logic [1:0] DTIMMemRWM;
|
||||
|
||||
// The DTIM uses untranslated addresses, so it is not compatible with virtual memory.
|
||||
mux2 #(`PA_BITS) DTIMAdrMux(IEUAdrExtE[`PA_BITS-1:0], IEUAdrExtM[`PA_BITS-1:0], MemRWM[0], DTIMAdr);
|
||||
mux2 #(`PA_BITS) DTIMAdrMux(IEUAdrExtE[`PA_BITS-1:0], IEUAdrExtM[`PA_BITS-1:0], MemRWM[0], DTIMAdr);
|
||||
assign DTIMMemRWM = SelDTIM & ~IgnoreRequestTLB ? LSURWM : '0;
|
||||
// **** fix ReadDataWordM to be LLEN. ByteMask is wrong length.
|
||||
// **** create config to support DTIM with floating point.
|
||||
@ -250,18 +250,18 @@ module lsu (
|
||||
logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
|
||||
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
|
||||
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
|
||||
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
||||
logic [1:0] BusRW; // Uncached bus memory access
|
||||
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
||||
logic [1:0] BusRW; // Uncached bus memory access
|
||||
logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
|
||||
logic [1:0] CacheRWM; // Cache read (10), write (01), AMO (11)
|
||||
logic [1:0] CacheAtomicM; // Cache AMO
|
||||
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
||||
logic [1:0] CacheRWM; // Cache read (10), write (01), AMO (11)
|
||||
logic [1:0] CacheAtomicM; // Cache AMO
|
||||
logic FlushDCache; // Suppress d cache flush if there is an ITLB miss.
|
||||
|
||||
assign BusRW = ~CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
|
||||
assign CacheableOrFlushCacheM = CacheableM | FlushDCacheM;
|
||||
assign CacheRWM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSURWM : '0;
|
||||
assign CacheAtomicM = CacheableM & ~IgnoreRequestTLB & ~SelDTIM ? LSUAtomicM : '0;
|
||||
assign FlushDCache = FlushDCacheM & ~(IgnoreRequestTLB | SelHPTW);
|
||||
assign FlushDCache = FlushDCacheM & ~(IgnoreRequestTLB | SelHPTW);
|
||||
|
||||
cache #(.LINELEN(`DCACHE_LINELENINBITS), .NUMLINES(`DCACHE_WAYSIZEINBYTES*8/LINELEN),
|
||||
.NUMWAYS(`DCACHE_NUMWAYS), .LOGBWPL(LLENLOGBWPL), .WORDLEN(`LLEN), .MUXINTERVAL(`LLEN), .READ_ONLY_CACHE(0)) dcache(
|
||||
@ -275,7 +275,7 @@ module lsu (
|
||||
.FetchBuffer, .CacheBusRW,
|
||||
.CacheBusAck(DCacheBusAck), .InvalidateCache(1'b0));
|
||||
|
||||
ahbcacheinterface #(.BEATSPERLINE(BEATSPERLINE), .AHBWLOGBWPL(AHBWLOGBWPL), .LINELEN(LINELEN), .LLENPOVERAHBW(LLENPOVERAHBW)) ahbcacheinterface(
|
||||
ahbcacheinterface #(.BEATSPERLINE(BEATSPERLINE), .AHBWLOGBWPL(AHBWLOGBWPL), .LINELEN(LINELEN), .LLENPOVERAHBW(LLENPOVERAHBW), .READ_ONLY_CACHE(0)) ahbcacheinterface(
|
||||
.HCLK(clk), .HRESETn(~reset), .Flush(FlushW),
|
||||
.HRDATA, .HWDATA(LSUHWDATA), .HWSTRB(LSUHWSTRB),
|
||||
.HSIZE(LSUHSIZE), .HBURST(LSUHBURST), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HREADY(LSUHREADY),
|
||||
@ -285,8 +285,8 @@ module lsu (
|
||||
.Cacheable(CacheableOrFlushCacheM), .BusRW, .Stall(GatedStallW),
|
||||
.BusStall, .BusCommitted(BusCommittedM));
|
||||
|
||||
// Mux between the 3 sources of read data, 0: cache, 1: Bus, 2: DTIM
|
||||
// Uncache bus access may be smaller width than LLEN. Duplicate LLENPOVERAHBW times.
|
||||
// Mux between the 3 sources of read data, 0: cache, 1: Bus, 2: DTIM
|
||||
// Uncache bus access may be smaller width than LLEN. Duplicate LLENPOVERAHBW times.
|
||||
// *** DTIMReadDataWordM should be increased to LLEN.
|
||||
// pma should generate exception for LLEN read to periph.
|
||||
mux3 #(`LLEN) UnCachedDataMux(.d0(DCacheReadDataWordM), .d1({LLENPOVERAHBW{FetchBuffer[`XLEN-1:0]}}),
|
||||
@ -305,7 +305,7 @@ module lsu (
|
||||
.HWSTRB(LSUHWSTRB), .BusRW, .ByteMask(ByteMaskM), .WriteData(LSUWriteDataM),
|
||||
.Stall(GatedStallW), .BusStall, .BusCommitted(BusCommittedM), .FetchBuffer(FetchBuffer));
|
||||
|
||||
// Mux between the 2 sources of read data, 0: Bus, 1: DTIM
|
||||
// Mux between the 2 sources of read data, 0: Bus, 1: DTIM
|
||||
if(`DTIM_SUPPORTED) mux2 #(`XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM, SelDTIM, ReadDataWordMuxM);
|
||||
else assign ReadDataWordMuxM = FetchBuffer[`XLEN-1:0];
|
||||
assign LSUHBURST = 3'b0;
|
||||
@ -338,7 +338,7 @@ module lsu (
|
||||
// Subword Accesses
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
subwordread subwordread(.ReadDataWordMuxM(LittleEndianReadDataWordM), .PAdrM(PAdrM[2:0]), .BigEndianM,
|
||||
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
|
||||
.FpLoadStoreM, .Funct3M(LSUFunct3M), .ReadDataM);
|
||||
subwordwrite subwordwrite(.LSUFunct3M, .IMAFWriteDataM, .LittleEndianWriteDataM);
|
||||
|
||||
// Compute byte masks
|
||||
|
@ -31,16 +31,16 @@
|
||||
|
||||
module subwordread
|
||||
(
|
||||
input logic [`LLEN-1:0] ReadDataWordMuxM,
|
||||
input logic [2:0] PAdrM,
|
||||
input logic [2:0] Funct3M,
|
||||
input logic [`LLEN-1:0] ReadDataWordMuxM,
|
||||
input logic [2:0] PAdrM,
|
||||
input logic [2:0] Funct3M,
|
||||
input logic FpLoadStoreM,
|
||||
input logic BigEndianM,
|
||||
output logic [`LLEN-1:0] ReadDataM
|
||||
);
|
||||
|
||||
logic [7:0] ByteM;
|
||||
logic [15:0] HalfwordM;
|
||||
logic [7:0] ByteM;
|
||||
logic [15:0] HalfwordM;
|
||||
logic [2:0] PAdrSwap;
|
||||
// Funct3M[2] is the unsigned bit. mask upper bits.
|
||||
// Funct3M[1:0] is the size of the memory access.
|
||||
@ -87,11 +87,11 @@ module subwordread
|
||||
3'b001: ReadDataM = {{`LLEN-16{HalfwordM[15]|FpLoadStoreM}}, HalfwordM[15:0]}; // lh/flh
|
||||
3'b010: ReadDataM = {{`LLEN-32{WordM[31]|FpLoadStoreM}}, WordM[31:0]}; // lw/flw
|
||||
3'b011: ReadDataM = {{`LLEN-64{DblWordM[63]|FpLoadStoreM}}, DblWordM[63:0]}; // ld/fld
|
||||
3'b100: ReadDataM = {{`LLEN-8{1'b0}}, ByteM[7:0]}; // lbu
|
||||
// 3'b100: ReadDataM = FpLoadStoreM ? ReadDataWordMuxM : {{`LLEN-8{1'b0}}, ByteM[7:0]}; // lbu/flq - only needed when LLEN=128
|
||||
3'b101: ReadDataM = {{`LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
||||
3'b110: ReadDataM = {{`LLEN-32{1'b0}}, WordM[31:0]}; // lwu
|
||||
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||
3'b100: ReadDataM = {{`LLEN-8{1'b0}}, ByteM[7:0]}; // lbu
|
||||
//3'b100: ReadDataM = FpLoadStoreM ? ReadDataWordMuxM : {{`LLEN-8{1'b0}}, ByteM[7:0]}; // lbu/flq - only needed when LLEN=128
|
||||
3'b101: ReadDataM = {{`LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
||||
3'b110: ReadDataM = {{`LLEN-32{1'b0}}, WordM[31:0]}; // lwu
|
||||
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||
endcase
|
||||
|
||||
end else begin:swrmux // 32-bit
|
||||
@ -114,13 +114,13 @@ module subwordread
|
||||
// sign extension
|
||||
always_comb
|
||||
case(Funct3M)
|
||||
3'b000: ReadDataM = {{`LLEN-8{ByteM[7]}}, ByteM}; // lb
|
||||
3'b001: ReadDataM = {{`LLEN-16{HalfwordM[15]|FpLoadStoreM}}, HalfwordM[15:0]}; // lh/flh
|
||||
3'b010: ReadDataM = {{`LLEN-32{ReadDataWordMuxM[31]|FpLoadStoreM}}, ReadDataWordMuxM[31:0]}; // lw/flw
|
||||
3'b011: ReadDataM = ReadDataWordMuxM; // fld
|
||||
3'b100: ReadDataM = {{`LLEN-8{1'b0}}, ByteM[7:0]}; // lbu
|
||||
3'b101: ReadDataM = {{`LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
||||
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||
3'b000: ReadDataM = {{`LLEN-8{ByteM[7]}}, ByteM}; // lb
|
||||
3'b001: ReadDataM = {{`LLEN-16{HalfwordM[15]|FpLoadStoreM}}, HalfwordM[15:0]}; // lh/flh
|
||||
3'b010: ReadDataM = {{`LLEN-32{ReadDataWordMuxM[31]|FpLoadStoreM}}, ReadDataWordMuxM[31:0]}; // lw/flw
|
||||
3'b011: ReadDataM = ReadDataWordMuxM; // fld
|
||||
3'b100: ReadDataM = {{`LLEN-8{1'b0}}, ByteM[7:0]}; // lbu
|
||||
3'b101: ReadDataM = {{`LLEN-16{1'b0}}, HalfwordM[15:0]}; // lhu
|
||||
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
@ -36,7 +36,7 @@ module div(
|
||||
input logic IntDivE, // integer division/remainder instruction of any type
|
||||
input logic DivSignedE, // signed division
|
||||
input logic W64E, // W-type instructions (divw, divuw, remw, remuw)
|
||||
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // Forwarding mux outputs for Source A and B
|
||||
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE,// Forwarding mux outputs for Source A and B
|
||||
output logic DivBusyE, // Divide is busy - stall pipeline
|
||||
output logic [`XLEN-1:0] QuotM, RemM // Quotient and remainder outputs
|
||||
);
|
||||
@ -76,7 +76,7 @@ module div(
|
||||
mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE);
|
||||
end else begin // RV32 has no W-type instructions
|
||||
assign XinE = ForwardedSrcAE;
|
||||
assign DinE = ForwardedSrcBE;
|
||||
assign DinE = ForwardedSrcBE;
|
||||
end
|
||||
|
||||
// Extract sign bits and check fo division by zero
|
||||
|
100
src/mdu/mdu.sv
100
src/mdu/mdu.sv
@ -29,62 +29,62 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module mdu(
|
||||
input logic clk, reset,
|
||||
input logic StallM, StallW,
|
||||
input logic FlushE, FlushM, FlushW,
|
||||
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // inputs A and B from IEU forwarding mux output
|
||||
input logic [2:0] Funct3E, Funct3M, // type of MDU operation
|
||||
input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
||||
output logic [`XLEN-1:0] MDUResultW, // multiply/divide result
|
||||
output logic DivBusyE // busy signal to stall pipeline in Execute stage
|
||||
input logic clk, reset,
|
||||
input logic StallM, StallW,
|
||||
input logic FlushE, FlushM, FlushW,
|
||||
input logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // inputs A and B from IEU forwarding mux output
|
||||
input logic [2:0] Funct3E, Funct3M, // type of MDU operation
|
||||
input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
||||
output logic [`XLEN-1:0] MDUResultW, // multiply/divide result
|
||||
output logic DivBusyE // busy signal to stall pipeline in Execute stage
|
||||
);
|
||||
|
||||
logic [`XLEN*2-1:0] ProdM; // double-width product from mul
|
||||
logic [`XLEN-1:0] QuotM, RemM; // quotient and remainder from intdivrestoring
|
||||
logic [`XLEN-1:0] PrelimResultM; // selected result before W truncation
|
||||
logic [`XLEN-1:0] MDUResultM; // result after W truncation
|
||||
logic W64M; // W-type instruction
|
||||
logic [`XLEN*2-1:0] ProdM; // double-width product from mul
|
||||
logic [`XLEN-1:0] QuotM, RemM; // quotient and remainder from intdivrestoring
|
||||
logic [`XLEN-1:0] PrelimResultM; // selected result before W truncation
|
||||
logic [`XLEN-1:0] MDUResultM; // result after W truncation
|
||||
logic W64M; // W-type instruction
|
||||
|
||||
// Multiplier
|
||||
mul mul(.clk, .reset, .StallM, .FlushM, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .ProdM);
|
||||
// Multiplier
|
||||
mul mul(.clk, .reset, .StallM, .FlushM, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .ProdM);
|
||||
|
||||
// Divider
|
||||
// Start a divide when a new division instruction is received and the divider isn't already busy or finishing
|
||||
// When IDIV_ON_FPU is set, use the FPU divider instead
|
||||
// In ZMMUL, with M_SUPPORTED = 0, omit the divider
|
||||
if ((`IDIV_ON_FPU) || (!`M_SUPPORTED)) begin:nodiv
|
||||
assign QuotM = 0;
|
||||
assign RemM = 0;
|
||||
assign DivBusyE = 0;
|
||||
end else begin:div
|
||||
div div(.clk, .reset, .StallM, .FlushE, .DivSignedE(~Funct3E[0]), .W64E, .IntDivE,
|
||||
.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM);
|
||||
end
|
||||
|
||||
// Result multiplexer
|
||||
// For ZMMUL, QuotM and RemM are tied to 0, so the mux automatically simplifies
|
||||
always_comb
|
||||
case (Funct3M)
|
||||
3'b000: PrelimResultM = ProdM[`XLEN-1:0]; // mul
|
||||
3'b001: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulh
|
||||
3'b010: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulhsu
|
||||
3'b011: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulhu
|
||||
3'b100: PrelimResultM = QuotM; // div
|
||||
3'b101: PrelimResultM = QuotM; // divu
|
||||
3'b110: PrelimResultM = RemM; // rem
|
||||
3'b111: PrelimResultM = RemM; // remu
|
||||
endcase
|
||||
// Divider
|
||||
// Start a divide when a new division instruction is received and the divider isn't already busy or finishing
|
||||
// When IDIV_ON_FPU is set, use the FPU divider instead
|
||||
// In ZMMUL, with M_SUPPORTED = 0, omit the divider
|
||||
if ((`IDIV_ON_FPU) || (!`M_SUPPORTED)) begin:nodiv
|
||||
assign QuotM = 0;
|
||||
assign RemM = 0;
|
||||
assign DivBusyE = 0;
|
||||
end else begin:div
|
||||
div div(.clk, .reset, .StallM, .FlushE, .DivSignedE(~Funct3E[0]), .W64E, .IntDivE,
|
||||
.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM);
|
||||
end
|
||||
|
||||
// Result multiplexer
|
||||
// For ZMMUL, QuotM and RemM are tied to 0, so the mux automatically simplifies
|
||||
always_comb
|
||||
case (Funct3M)
|
||||
3'b000: PrelimResultM = ProdM[`XLEN-1:0]; // mul
|
||||
3'b001: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulh
|
||||
3'b010: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulhsu
|
||||
3'b011: PrelimResultM = ProdM[`XLEN*2-1:`XLEN]; // mulhu
|
||||
3'b100: PrelimResultM = QuotM; // div
|
||||
3'b101: PrelimResultM = QuotM; // divu
|
||||
3'b110: PrelimResultM = RemM; // rem
|
||||
3'b111: PrelimResultM = RemM; // remu
|
||||
endcase
|
||||
|
||||
// Handle sign extension for W-type instructions
|
||||
flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M);
|
||||
if (`XLEN == 64) begin:resmux // RV64 has W-type instructions
|
||||
assign MDUResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
|
||||
end else begin:resmux // RV32 has no W-type instructions
|
||||
assign MDUResultM = PrelimResultM;
|
||||
end
|
||||
// Handle sign extension for W-type instructions
|
||||
flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M);
|
||||
if (`XLEN == 64) begin:resmux // RV64 has W-type instructions
|
||||
assign MDUResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
|
||||
end else begin:resmux // RV32 has no W-type instructions
|
||||
assign MDUResultM = PrelimResultM;
|
||||
end
|
||||
|
||||
// Writeback stage pipeline register
|
||||
flopenrc #(`XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW);
|
||||
// Writeback stage pipeline register
|
||||
flopenrc #(`XLEN) MDUResultWReg(clk, reset, FlushW, ~StallW, MDUResultM, MDUResultW);
|
||||
endmodule // mdu
|
||||
|
||||
|
||||
|
354
src/mmu/hptw.sv
354
src/mmu/hptw.sv
@ -32,118 +32,118 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module hptw (
|
||||
input logic clk, reset,
|
||||
input logic [`XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table
|
||||
input logic [`XLEN-1:0] PCSpillF, // addresses to translate
|
||||
input logic [`XLEN+1:0] IEUAdrExtM, // addresses to translate
|
||||
input logic [1:0] MemRWM, AtomicM,
|
||||
// system status
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] ReadDataM, // page table entry from LSU
|
||||
input logic [`XLEN-1:0] WriteDataM,
|
||||
input logic DCacheStallM, // stall from LSU
|
||||
input logic [2:0] Funct3M,
|
||||
input logic [6:0] Funct7M,
|
||||
input logic ITLBMissF,
|
||||
input logic DTLBMissM,
|
||||
input logic FlushW,
|
||||
input logic InstrUpdateDAF,
|
||||
input logic DataUpdateDAM,
|
||||
output logic [`XLEN-1:0] PTE, // page table entry to TLBs
|
||||
output logic [1:0] PageType, // page type to TLBs
|
||||
output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
|
||||
output logic [1:0] PreLSURWM,
|
||||
output logic [`XLEN+1:0] IHAdrM,
|
||||
output logic [`XLEN-1:0] IHWriteDataM,
|
||||
output logic [1:0] LSUAtomicM,
|
||||
output logic [2:0] LSUFunct3M,
|
||||
output logic [6:0] LSUFunct7M,
|
||||
output logic IgnoreRequestTLB,
|
||||
output logic SelHPTW,
|
||||
output logic HPTWStall,
|
||||
input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM,
|
||||
output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultM
|
||||
input logic clk, reset,
|
||||
input logic [`XLEN-1:0] SATP_REGW, // includes SATP.MODE to determine number of levels in page table
|
||||
input logic [`XLEN-1:0] PCSpillF, // addresses to translate
|
||||
input logic [`XLEN+1:0] IEUAdrExtM, // addresses to translate
|
||||
input logic [1:0] MemRWM, AtomicM,
|
||||
// system status
|
||||
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
input logic [1:0] STATUS_MPP,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] ReadDataM, // page table entry from LSU
|
||||
input logic [`XLEN-1:0] WriteDataM,
|
||||
input logic DCacheStallM, // stall from LSU
|
||||
input logic [2:0] Funct3M,
|
||||
input logic [6:0] Funct7M,
|
||||
input logic ITLBMissF,
|
||||
input logic DTLBMissM,
|
||||
input logic FlushW,
|
||||
input logic InstrUpdateDAF,
|
||||
input logic DataUpdateDAM,
|
||||
output logic [`XLEN-1:0] PTE, // page table entry to TLBs
|
||||
output logic [1:0] PageType, // page type to TLBs
|
||||
output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
|
||||
output logic [1:0] PreLSURWM,
|
||||
output logic [`XLEN+1:0] IHAdrM,
|
||||
output logic [`XLEN-1:0] IHWriteDataM,
|
||||
output logic [1:0] LSUAtomicM,
|
||||
output logic [2:0] LSUFunct3M,
|
||||
output logic [6:0] LSUFunct7M,
|
||||
output logic IgnoreRequestTLB,
|
||||
output logic SelHPTW,
|
||||
output logic HPTWStall,
|
||||
input logic LSULoadAccessFaultM, LSUStoreAmoAccessFaultM,
|
||||
output logic LoadAccessFaultM, StoreAmoAccessFaultM, HPTWInstrAccessFaultM
|
||||
);
|
||||
|
||||
typedef enum logic [3:0] {L0_ADR, L0_RD,
|
||||
L1_ADR, L1_RD,
|
||||
L2_ADR, L2_RD,
|
||||
L3_ADR, L3_RD,
|
||||
LEAF, IDLE, UPDATE_PTE} statetype;
|
||||
L1_ADR, L1_RD,
|
||||
L2_ADR, L2_RD,
|
||||
L3_ADR, L3_RD,
|
||||
LEAF, IDLE, UPDATE_PTE} statetype;
|
||||
|
||||
logic DTLBWalk; // register TLBs translation miss requests
|
||||
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
||||
logic [`PPN_BITS-1:0] CurrentPPN;
|
||||
logic Executable, Writable, Readable, Valid, PTE_U;
|
||||
logic Misaligned, MegapageMisaligned;
|
||||
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
|
||||
logic StartWalk;
|
||||
logic TLBMiss;
|
||||
logic PRegEn;
|
||||
logic [1:0] NextPageType;
|
||||
logic DTLBWalk; // register TLBs translation miss requests
|
||||
logic [`PPN_BITS-1:0] BasePageTablePPN;
|
||||
logic [`PPN_BITS-1:0] CurrentPPN;
|
||||
logic Executable, Writable, Readable, Valid, PTE_U;
|
||||
logic Misaligned, MegapageMisaligned;
|
||||
logic ValidPTE, LeafPTE, ValidLeafPTE, ValidNonLeafPTE;
|
||||
logic StartWalk;
|
||||
logic TLBMiss;
|
||||
logic PRegEn;
|
||||
logic [1:0] NextPageType;
|
||||
logic [`SVMODE_BITS-1:0] SvMode;
|
||||
logic [`XLEN-1:0] TranslationVAdr;
|
||||
logic [`XLEN-1:0] NextPTE;
|
||||
logic UpdatePTE;
|
||||
logic HPTWUpdateDA;
|
||||
logic [`PA_BITS-1:0] HPTWReadAdr;
|
||||
logic SelHPTWAdr;
|
||||
logic [`XLEN+1:0] HPTWAdrExt;
|
||||
logic ITLBMissOrUpdateDAF;
|
||||
logic DTLBMissOrUpdateDAM;
|
||||
logic [`XLEN-1:0] TranslationVAdr;
|
||||
logic [`XLEN-1:0] NextPTE;
|
||||
logic UpdatePTE;
|
||||
logic HPTWUpdateDA;
|
||||
logic [`PA_BITS-1:0] HPTWReadAdr;
|
||||
logic SelHPTWAdr;
|
||||
logic [`XLEN+1:0] HPTWAdrExt;
|
||||
logic ITLBMissOrUpdateDAF;
|
||||
logic DTLBMissOrUpdateDAM;
|
||||
logic LSUAccessFaultM;
|
||||
logic [`PA_BITS-1:0] HPTWAdr;
|
||||
logic [1:0] HPTWRW;
|
||||
logic [2:0] HPTWSize; // 32 or 64 bit access
|
||||
statetype WalkerState, NextWalkerState, InitialWalkerState;
|
||||
logic [`PA_BITS-1:0] HPTWAdr;
|
||||
logic [1:0] HPTWRW;
|
||||
logic [2:0] HPTWSize; // 32 or 64 bit access
|
||||
statetype WalkerState, NextWalkerState, InitialWalkerState;
|
||||
|
||||
// map hptw access faults onto either the original LSU load/store fault or instruction access fault
|
||||
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
||||
assign LoadAccessFaultM = WalkerState == IDLE ? LSULoadAccessFaultM : LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||
assign StoreAmoAccessFaultM = WalkerState == IDLE ? LSUStoreAmoAccessFaultM : LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
||||
assign HPTWInstrAccessFaultM = WalkerState == IDLE ? 1'b0: LSUAccessFaultM & ~DTLBWalk;
|
||||
assign LSUAccessFaultM = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM;
|
||||
assign LoadAccessFaultM = WalkerState == IDLE ? LSULoadAccessFaultM : LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0];
|
||||
assign StoreAmoAccessFaultM = WalkerState == IDLE ? LSUStoreAmoAccessFaultM : LSUAccessFaultM & DTLBWalk & MemRWM[0];
|
||||
assign HPTWInstrAccessFaultM = WalkerState == IDLE ? 1'b0: LSUAccessFaultM & ~DTLBWalk;
|
||||
|
||||
// Extract bits from CSRs and inputs
|
||||
assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS];
|
||||
assign BasePageTablePPN = SATP_REGW[`PPN_BITS-1:0];
|
||||
assign TLBMiss = (DTLBMissOrUpdateDAM | ITLBMissOrUpdateDAF);
|
||||
// Extract bits from CSRs and inputs
|
||||
assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS];
|
||||
assign BasePageTablePPN = SATP_REGW[`PPN_BITS-1:0];
|
||||
assign TLBMiss = (DTLBMissOrUpdateDAM | ITLBMissOrUpdateDAF);
|
||||
|
||||
// Determine which address to translate
|
||||
mux2 #(`XLEN) vadrmux(PCSpillF, IEUAdrExtM[`XLEN-1:0], DTLBWalk, TranslationVAdr);
|
||||
assign CurrentPPN = PTE[`PPN_BITS+9:10];
|
||||
// Determine which address to translate
|
||||
mux2 #(`XLEN) vadrmux(PCSpillF, IEUAdrExtM[`XLEN-1:0], DTLBWalk, TranslationVAdr);
|
||||
assign CurrentPPN = PTE[`PPN_BITS+9:10];
|
||||
|
||||
// State flops
|
||||
flopenr #(1) TLBMissMReg(clk, reset, StartWalk, DTLBMissOrUpdateDAM, DTLBWalk); // when walk begins, record whether it was for DTLB (or record 0 for ITLB)
|
||||
assign PRegEn = HPTWRW[1] & ~DCacheStallM | UpdatePTE;
|
||||
flopenr #(`XLEN) PTEReg(clk, reset, PRegEn, NextPTE, PTE); // Capture page table entry from data cache
|
||||
// State flops
|
||||
flopenr #(1) TLBMissMReg(clk, reset, StartWalk, DTLBMissOrUpdateDAM, DTLBWalk); // when walk begins, record whether it was for DTLB (or record 0 for ITLB)
|
||||
assign PRegEn = HPTWRW[1] & ~DCacheStallM | UpdatePTE;
|
||||
flopenr #(`XLEN) PTEReg(clk, reset, PRegEn, NextPTE, PTE); // Capture page table entry from data cache
|
||||
|
||||
// Assign PTE descriptors common across all XLEN values
|
||||
// For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table
|
||||
assign {PTE_U, Executable, Writable, Readable, Valid} = PTE[4:0];
|
||||
assign LeafPTE = Executable | Writable | Readable;
|
||||
assign ValidPTE = Valid & ~(Writable & ~Readable);
|
||||
assign ValidLeafPTE = ValidPTE & LeafPTE;
|
||||
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
|
||||
// Assign PTE descriptors common across all XLEN values
|
||||
// For non-leaf PTEs, D, A, U bits are reserved and ignored. They do not cause faults while walking the page table
|
||||
assign {PTE_U, Executable, Writable, Readable, Valid} = PTE[4:0];
|
||||
assign LeafPTE = Executable | Writable | Readable;
|
||||
assign ValidPTE = Valid & ~(Writable & ~Readable);
|
||||
assign ValidLeafPTE = ValidPTE & LeafPTE;
|
||||
assign ValidNonLeafPTE = ValidPTE & ~LeafPTE;
|
||||
|
||||
if(`SVADU_SUPPORTED) begin : hptwwrites
|
||||
logic ReadAccess, WriteAccess;
|
||||
logic InvalidRead, InvalidWrite, InvalidOp;
|
||||
logic UpperBitsUnequal;
|
||||
logic OtherPageFault;
|
||||
logic [1:0] EffectivePrivilegeMode;
|
||||
logic ImproperPrivilege;
|
||||
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
||||
logic [`PA_BITS-1:0] HPTWWriteAdr;
|
||||
logic SetDirty;
|
||||
logic Dirty, Accessed;
|
||||
logic [`XLEN-1:0] AccessedPTE;
|
||||
logic ReadAccess, WriteAccess;
|
||||
logic InvalidRead, InvalidWrite, InvalidOp;
|
||||
logic UpperBitsUnequal;
|
||||
logic OtherPageFault;
|
||||
logic [1:0] EffectivePrivilegeMode;
|
||||
logic ImproperPrivilege;
|
||||
logic SaveHPTWAdr, SelHPTWWriteAdr;
|
||||
logic [`PA_BITS-1:0] HPTWWriteAdr;
|
||||
logic SetDirty;
|
||||
logic Dirty, Accessed;
|
||||
logic [`XLEN-1:0] AccessedPTE;
|
||||
|
||||
assign AccessedPTE = {PTE[`XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
|
||||
mux2 #(`XLEN) NextPTEMux(ReadDataM, AccessedPTE, UpdatePTE, NextPTE);
|
||||
assign AccessedPTE = {PTE[`XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
|
||||
mux2 #(`XLEN) NextPTEMux(ReadDataM, AccessedPTE, UpdatePTE, NextPTE);
|
||||
flopenr #(`PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr);
|
||||
|
||||
|
||||
assign SaveHPTWAdr = WalkerState == L0_ADR;
|
||||
assign SelHPTWWriteAdr = UpdatePTE | HPTWRW[0];
|
||||
mux2 #(`PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr);
|
||||
@ -158,11 +158,11 @@ module hptw (
|
||||
((EffectivePrivilegeMode == `S_MODE) & PTE_U & (~STATUS_SUM & DTLBWalk));
|
||||
|
||||
// Check for page faults
|
||||
vm64check vm64check(.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .VAdr(TranslationVAdr),
|
||||
.SV39Mode(), .UpperBitsUnequal);
|
||||
vm64check vm64check(.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .VAdr(TranslationVAdr),
|
||||
.SV39Mode(), .UpperBitsUnequal);
|
||||
assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable);
|
||||
assign InvalidWrite = WriteAccess & ~Writable;
|
||||
assign InvalidOp = DTLBWalk ? (InvalidRead | InvalidWrite) : ~Executable;
|
||||
assign InvalidOp = DTLBWalk ? (InvalidRead | InvalidWrite) : ~Executable;
|
||||
assign OtherPageFault = ImproperPrivilege | InvalidOp | UpperBitsUnequal | Misaligned | ~Valid;
|
||||
|
||||
// hptw needs to know if there is a Dirty or Access fault occuring on this
|
||||
@ -181,62 +181,62 @@ module hptw (
|
||||
assign HPTWRW[0] = '0;
|
||||
end
|
||||
|
||||
// Enable and select signals based on states
|
||||
assign StartWalk = (WalkerState == IDLE) & TLBMiss;
|
||||
assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
|
||||
assign DTLBWriteM = (WalkerState == LEAF & ~HPTWUpdateDA) & DTLBWalk;
|
||||
assign ITLBWriteF = (WalkerState == LEAF & ~HPTWUpdateDA) & ~DTLBWalk;
|
||||
// Enable and select signals based on states
|
||||
assign StartWalk = (WalkerState == IDLE) & TLBMiss;
|
||||
assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD);
|
||||
assign DTLBWriteM = (WalkerState == LEAF & ~HPTWUpdateDA) & DTLBWalk;
|
||||
assign ITLBWriteF = (WalkerState == LEAF & ~HPTWUpdateDA) & ~DTLBWalk;
|
||||
|
||||
// FSM to track PageType based on the levels of the page table traversed
|
||||
flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType);
|
||||
always_comb
|
||||
case (WalkerState)
|
||||
L3_RD: NextPageType = 2'b11; // terapage
|
||||
L2_RD: NextPageType = 2'b10; // gigapage
|
||||
L1_RD: NextPageType = 2'b01; // megapage
|
||||
L0_RD: NextPageType = 2'b00; // kilopage
|
||||
default: NextPageType = PageType;
|
||||
endcase
|
||||
// FSM to track PageType based on the levels of the page table traversed
|
||||
flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType);
|
||||
always_comb
|
||||
case (WalkerState)
|
||||
L3_RD: NextPageType = 2'b11; // terapage
|
||||
L2_RD: NextPageType = 2'b10; // gigapage
|
||||
L1_RD: NextPageType = 2'b01; // megapage
|
||||
L0_RD: NextPageType = 2'b00; // kilopage
|
||||
default: NextPageType = PageType;
|
||||
endcase
|
||||
|
||||
// HPTWAdr muxing
|
||||
if (`XLEN==32) begin // RV32
|
||||
logic [9:0] VPN;
|
||||
logic [`PPN_BITS-1:0] PPN;
|
||||
assign VPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? TranslationVAdr[31:22] : TranslationVAdr[21:12]; // select VPN field based on HPTW state
|
||||
assign PPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? BasePageTablePPN : CurrentPPN;
|
||||
assign HPTWReadAdr = {PPN, VPN, 2'b00};
|
||||
assign HPTWSize = 3'b010;
|
||||
end else begin // RV64
|
||||
logic [8:0] VPN;
|
||||
logic [`PPN_BITS-1:0] PPN;
|
||||
always_comb
|
||||
case (WalkerState) // select VPN field based on HPTW state
|
||||
L3_ADR, L3_RD: VPN = TranslationVAdr[47:39];
|
||||
L2_ADR, L2_RD: VPN = TranslationVAdr[38:30];
|
||||
L1_ADR, L1_RD: VPN = TranslationVAdr[29:21];
|
||||
default: VPN = TranslationVAdr[20:12];
|
||||
endcase
|
||||
assign PPN = ((WalkerState == L3_ADR) | (WalkerState == L3_RD) |
|
||||
(SvMode != `SV48 & ((WalkerState == L2_ADR) | (WalkerState == L2_RD)))) ? BasePageTablePPN : CurrentPPN;
|
||||
assign HPTWReadAdr = {PPN, VPN, 3'b000};
|
||||
assign HPTWSize = 3'b011;
|
||||
end
|
||||
// HPTWAdr muxing
|
||||
if (`XLEN==32) begin // RV32
|
||||
logic [9:0] VPN;
|
||||
logic [`PPN_BITS-1:0] PPN;
|
||||
assign VPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? TranslationVAdr[31:22] : TranslationVAdr[21:12]; // select VPN field based on HPTW state
|
||||
assign PPN = ((WalkerState == L1_ADR) | (WalkerState == L1_RD)) ? BasePageTablePPN : CurrentPPN;
|
||||
assign HPTWReadAdr = {PPN, VPN, 2'b00};
|
||||
assign HPTWSize = 3'b010;
|
||||
end else begin // RV64
|
||||
logic [8:0] VPN;
|
||||
logic [`PPN_BITS-1:0] PPN;
|
||||
always_comb
|
||||
case (WalkerState) // select VPN field based on HPTW state
|
||||
L3_ADR, L3_RD: VPN = TranslationVAdr[47:39];
|
||||
L2_ADR, L2_RD: VPN = TranslationVAdr[38:30];
|
||||
L1_ADR, L1_RD: VPN = TranslationVAdr[29:21];
|
||||
default: VPN = TranslationVAdr[20:12];
|
||||
endcase
|
||||
assign PPN = ((WalkerState == L3_ADR) | (WalkerState == L3_RD) |
|
||||
(SvMode != `SV48 & ((WalkerState == L2_ADR) | (WalkerState == L2_RD)))) ? BasePageTablePPN : CurrentPPN;
|
||||
assign HPTWReadAdr = {PPN, VPN, 3'b000};
|
||||
assign HPTWSize = 3'b011;
|
||||
end
|
||||
|
||||
// Initial state and misalignment for RV32/64
|
||||
if (`XLEN == 32) begin
|
||||
assign InitialWalkerState = L1_ADR;
|
||||
assign MegapageMisaligned = |(CurrentPPN[9:0]); // must have zero PPN0
|
||||
assign Misaligned = ((WalkerState == L0_ADR) & MegapageMisaligned);
|
||||
end else begin
|
||||
logic GigapageMisaligned, TerapageMisaligned;
|
||||
assign InitialWalkerState = (SvMode == `SV48) ? L3_ADR : L2_ADR;
|
||||
assign TerapageMisaligned = |(CurrentPPN[26:0]); // must have zero PPN2, PPN1, PPN0
|
||||
assign GigapageMisaligned = |(CurrentPPN[17:0]); // must have zero PPN1 and PPN0
|
||||
assign MegapageMisaligned = |(CurrentPPN[8:0]); // must have zero PPN0
|
||||
assign Misaligned = ((WalkerState == L2_ADR) & TerapageMisaligned) | ((WalkerState == L1_ADR) & GigapageMisaligned) | ((WalkerState == L0_ADR) & MegapageMisaligned);
|
||||
end
|
||||
// Initial state and misalignment for RV32/64
|
||||
if (`XLEN == 32) begin
|
||||
assign InitialWalkerState = L1_ADR;
|
||||
assign MegapageMisaligned = |(CurrentPPN[9:0]); // must have zero PPN0
|
||||
assign Misaligned = ((WalkerState == L0_ADR) & MegapageMisaligned);
|
||||
end else begin
|
||||
logic GigapageMisaligned, TerapageMisaligned;
|
||||
assign InitialWalkerState = (SvMode == `SV48) ? L3_ADR : L2_ADR;
|
||||
assign TerapageMisaligned = |(CurrentPPN[26:0]); // must have zero PPN2, PPN1, PPN0
|
||||
assign GigapageMisaligned = |(CurrentPPN[17:0]); // must have zero PPN1 and PPN0
|
||||
assign MegapageMisaligned = |(CurrentPPN[8:0]); // must have zero PPN0
|
||||
assign Misaligned = ((WalkerState == L2_ADR) & TerapageMisaligned) | ((WalkerState == L1_ADR) & GigapageMisaligned) | ((WalkerState == L0_ADR) & MegapageMisaligned);
|
||||
end
|
||||
|
||||
// Page Table Walker FSM
|
||||
// Page Table Walker FSM
|
||||
// there is a bug here. Each memory access needs to be potentially flushed if the PMA/P checkers
|
||||
// generate an access fault. Specially the store on UDPATE_PTE needs to check for access violation.
|
||||
// I think the solution is to do 1 of the following
|
||||
@ -244,32 +244,32 @@ module hptw (
|
||||
// 2. If the store would generate an exception don't store to dcache but still write the TLB. When we go back
|
||||
// to LEAF then the PMA/P. Wait this does not work. The PMA/P won't be looking a the address in the table, but
|
||||
// rather than physical address of the translated instruction/data. So we must generate the exception.
|
||||
flopenl #(.TYPE(statetype)) WalkerStateReg(clk, reset | FlushW, 1'b1, NextWalkerState, IDLE, WalkerState);
|
||||
always_comb
|
||||
case (WalkerState)
|
||||
IDLE: if (TLBMiss & ~DCacheStallM) NextWalkerState = InitialWalkerState;
|
||||
else NextWalkerState = IDLE;
|
||||
L3_ADR: NextWalkerState = L3_RD; // first access in SV48
|
||||
L3_RD: if (DCacheStallM) NextWalkerState = L3_RD;
|
||||
else NextWalkerState = L2_ADR;
|
||||
L2_ADR: if (InitialWalkerState == L2_ADR | ValidNonLeafPTE) NextWalkerState = L2_RD; // first access in SV39
|
||||
else NextWalkerState = LEAF;
|
||||
L2_RD: if (DCacheStallM) NextWalkerState = L2_RD;
|
||||
else NextWalkerState = L1_ADR;
|
||||
L1_ADR: if (InitialWalkerState == L1_ADR | ValidNonLeafPTE) NextWalkerState = L1_RD; // first access in SV32
|
||||
else NextWalkerState = LEAF;
|
||||
L1_RD: if (DCacheStallM) NextWalkerState = L1_RD;
|
||||
else NextWalkerState = L0_ADR;
|
||||
L0_ADR: if (ValidNonLeafPTE) NextWalkerState = L0_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
L0_RD: if (DCacheStallM) NextWalkerState = L0_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
LEAF: if (`SVADU_SUPPORTED & HPTWUpdateDA) NextWalkerState = UPDATE_PTE;
|
||||
else NextWalkerState = IDLE;
|
||||
UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE;
|
||||
else NextWalkerState = LEAF;
|
||||
default: NextWalkerState = IDLE; // should never be reached
|
||||
endcase // case (WalkerState)
|
||||
flopenl #(.TYPE(statetype)) WalkerStateReg(clk, reset | FlushW, 1'b1, NextWalkerState, IDLE, WalkerState);
|
||||
always_comb
|
||||
case (WalkerState)
|
||||
IDLE: if (TLBMiss & ~DCacheStallM) NextWalkerState = InitialWalkerState;
|
||||
else NextWalkerState = IDLE;
|
||||
L3_ADR: NextWalkerState = L3_RD; // first access in SV48
|
||||
L3_RD: if (DCacheStallM) NextWalkerState = L3_RD;
|
||||
else NextWalkerState = L2_ADR;
|
||||
L2_ADR: if (InitialWalkerState == L2_ADR | ValidNonLeafPTE) NextWalkerState = L2_RD; // first access in SV39
|
||||
else NextWalkerState = LEAF;
|
||||
L2_RD: if (DCacheStallM) NextWalkerState = L2_RD;
|
||||
else NextWalkerState = L1_ADR;
|
||||
L1_ADR: if (InitialWalkerState == L1_ADR | ValidNonLeafPTE) NextWalkerState = L1_RD; // first access in SV32
|
||||
else NextWalkerState = LEAF;
|
||||
L1_RD: if (DCacheStallM) NextWalkerState = L1_RD;
|
||||
else NextWalkerState = L0_ADR;
|
||||
L0_ADR: if (ValidNonLeafPTE) NextWalkerState = L0_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
L0_RD: if (DCacheStallM) NextWalkerState = L0_RD;
|
||||
else NextWalkerState = LEAF;
|
||||
LEAF: if (`SVADU_SUPPORTED & HPTWUpdateDA) NextWalkerState = UPDATE_PTE;
|
||||
else NextWalkerState = IDLE;
|
||||
UPDATE_PTE: if(DCacheStallM) NextWalkerState = UPDATE_PTE;
|
||||
else NextWalkerState = LEAF;
|
||||
default: NextWalkerState = IDLE; // should never be reached
|
||||
endcase // case (WalkerState)
|
||||
|
||||
assign IgnoreRequestTLB = WalkerState == IDLE & TLBMiss;
|
||||
assign SelHPTW = WalkerState != IDLE;
|
||||
|
@ -108,12 +108,12 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) (
|
||||
.Cacheable, .Idempotent, .SelTIM,
|
||||
.PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM);
|
||||
|
||||
if (`PMP_ENTRIES > 0)
|
||||
if (`PMP_ENTRIES > 0) begin : pmp
|
||||
pmpchecker pmpchecker(.PhysicalAddress, .PrivilegeModeW,
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||
.ExecuteAccessF, .WriteAccessM, .ReadAccessM,
|
||||
.PMPInstrAccessFaultF, .PMPLoadAccessFaultM, .PMPStoreAmoAccessFaultM);
|
||||
else begin
|
||||
end else begin
|
||||
assign PMPInstrAccessFaultF = 0;
|
||||
assign PMPStoreAmoAccessFaultM = 0;
|
||||
assign PMPLoadAccessFaultM = 0;
|
||||
|
@ -38,7 +38,7 @@ module pmpadrdec (
|
||||
input logic [`PA_BITS-3:0] PMPAdr,
|
||||
input logic PAgePMPAdrIn,
|
||||
output logic PAgePMPAdrOut,
|
||||
output logic Match, Active,
|
||||
output logic Match,
|
||||
output logic L, X, W, R
|
||||
);
|
||||
|
||||
@ -84,7 +84,6 @@ module pmpadrdec (
|
||||
assign X = PMPCfg[2];
|
||||
assign W = PMPCfg[1];
|
||||
assign R = PMPCfg[0];
|
||||
assign Active = |PMPCfg[4:3];
|
||||
|
||||
// known bug: The size of the access is not yet checked. For example, if an NA4 entry matches 0xC-0xF and the system
|
||||
// attempts an 8-byte access to 0x8, the access should fail (see page 60 of privileged specification 20211203). This
|
||||
|
@ -53,25 +53,23 @@ module pmpchecker (
|
||||
logic EnforcePMP; // should PMP be checked in this privilege level
|
||||
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
|
||||
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
|
||||
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
|
||||
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
|
||||
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
|
||||
|
||||
if (`PMP_ENTRIES > 0) // prevent complaints about array of no elements when PMP_ENTRIES = 0
|
||||
if (`PMP_ENTRIES > 0) begin: pmp // prevent complaints about array of no elements when PMP_ENTRIES = 0
|
||||
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
|
||||
.PhysicalAddress,
|
||||
.PMPCfg(PMPCFG_ARRAY_REGW),
|
||||
.PMPAdr(PMPADDR_ARRAY_REGW),
|
||||
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
|
||||
.PAgePMPAdrOut(PAgePMPAdr),
|
||||
.Match, .Active, .L, .X, .W, .R);
|
||||
.Match, .L, .X, .W, .R);
|
||||
end
|
||||
|
||||
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
|
||||
|
||||
// Only enforce PMP checking for S and U modes or in Machine mode when L bit is set in selected region
|
||||
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |(L & FirstMatch) : |Active;
|
||||
// assign EnforcePMP = (PrivilegeModeW != `M_MODE) | |(L & FirstMatch); // *** switch to this logic when PMP is initialized for non-machine mode
|
||||
// *** remove unused Active lines from pmpadrdecs
|
||||
assign EnforcePMP = (PrivilegeModeW != `M_MODE) | |(L & FirstMatch); // *** switch to this logic when PMP is initialized for non-machine mode
|
||||
|
||||
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|(X & FirstMatch) ;
|
||||
assign PMPStoreAmoAccessFaultM = EnforcePMP & WriteAccessM & ~|(W & FirstMatch) ;
|
||||
|
@ -84,8 +84,8 @@ module tlb #(parameter TLB_ENTRIES = 8, ITLB = 0) (
|
||||
logic [1:0] HitPageType;
|
||||
logic CAMHit;
|
||||
logic SV39Mode;
|
||||
logic Misaligned;
|
||||
logic MegapageMisaligned;
|
||||
logic Misaligned;
|
||||
logic MegapageMisaligned;
|
||||
|
||||
if(`XLEN == 32) begin
|
||||
assign MegapageMisaligned = |(PPN[9:0]); // must have zero PPN0
|
||||
@ -94,7 +94,7 @@ module tlb #(parameter TLB_ENTRIES = 8, ITLB = 0) (
|
||||
logic GigapageMisaligned, TerapageMisaligned;
|
||||
assign TerapageMisaligned = |(PPN[26:0]); // must have zero PPN2, PPN1, PPN0
|
||||
assign GigapageMisaligned = |(PPN[17:0]); // must have zero PPN1 and PPN0
|
||||
assign MegapageMisaligned = |(PPN[8:0]); // must have zero PPN0
|
||||
assign MegapageMisaligned = |(PPN[8:0]); // must have zero PPN0
|
||||
assign Misaligned = ((HitPageType == 2'b11) & TerapageMisaligned) |
|
||||
((HitPageType == 2'b10) & GigapageMisaligned) |
|
||||
((HitPageType == 2'b01) & MegapageMisaligned);
|
||||
|
@ -55,7 +55,7 @@ module csr #(parameter
|
||||
input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR
|
||||
input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
|
||||
input logic [1:0] PrivilegeModeW, // current privilege mode
|
||||
input logic [`LOG_XLEN-1:0] CauseM, // Trap cause
|
||||
input logic [3:0] CauseM, // Trap cause
|
||||
input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode
|
||||
// inputs for performance counters
|
||||
input logic LoadStallD,
|
||||
@ -79,7 +79,7 @@ module csr #(parameter
|
||||
// outputs from CSRs
|
||||
output logic [1:0] STATUS_MPP,
|
||||
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
|
||||
output logic [`XLEN-1:0] MEDELEG_REGW,
|
||||
output logic [15:0] MEDELEG_REGW,
|
||||
output logic [`XLEN-1:0] SATP_REGW,
|
||||
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||
output logic STATUS_MIE, STATUS_SIE,
|
||||
@ -96,18 +96,19 @@ module csr #(parameter
|
||||
);
|
||||
|
||||
logic [`XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM;
|
||||
logic [`XLEN-1:0] CSRReadValM;
|
||||
logic [`XLEN-1:0] CSRSrcM;
|
||||
logic [`XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
|
||||
logic [`XLEN-1:0] CSRWriteValM;
|
||||
logic [`XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW;
|
||||
logic [`XLEN-1:0] CSRReadValM;
|
||||
logic [`XLEN-1:0] CSRSrcM;
|
||||
logic [`XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
|
||||
logic [`XLEN-1:0] CSRWriteValM;
|
||||
logic [`XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW;
|
||||
logic [`XLEN-1:0] STVEC_REGW, MTVEC_REGW;
|
||||
logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW;
|
||||
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
|
||||
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
|
||||
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
|
||||
logic WriteFRMM, WriteFFLAGSM;
|
||||
logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextCauseM, NextMtvalM;
|
||||
logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
|
||||
logic [4:0] NextCauseM;
|
||||
logic [11:0] CSRAdrM;
|
||||
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM;
|
||||
logic InsufficientCSRPrivilegeM;
|
||||
@ -117,7 +118,7 @@ module csr #(parameter
|
||||
logic [`XLEN-1:0] TVecM, TrapVectorM, NextFaultMtvalM;
|
||||
logic MTrapM, STrapM;
|
||||
logic [`XLEN-1:0] EPC;
|
||||
logic RetM;
|
||||
logic RetM;
|
||||
logic SelMtvecM;
|
||||
logic [`XLEN-1:0] TVecAlignedM;
|
||||
logic InstrValidNotFlushedM;
|
||||
@ -153,7 +154,7 @@ module csr #(parameter
|
||||
logic VectoredM;
|
||||
logic [`XLEN-1:0] TVecPlusCauseM;
|
||||
assign VectoredM = InterruptM & (TVecM[1:0] == 2'b01);
|
||||
assign TVecPlusCauseM = {TVecAlignedM[`XLEN-1:6], CauseM[3:0], 2'b00}; // 64-byte alignment allows concatenation rather than addition
|
||||
assign TVecPlusCauseM = {TVecAlignedM[`XLEN-1:6], CauseM, 2'b00}; // 64-byte alignment allows concatenation rather than addition
|
||||
mux2 #(`XLEN) trapvecmux(TVecAlignedM, TVecPlusCauseM, VectoredM, TrapVectorM);
|
||||
end else
|
||||
assign TrapVectorM = TVecAlignedM;
|
||||
@ -196,7 +197,7 @@ module csr #(parameter
|
||||
assign CSRAdrM = InstrM[31:20];
|
||||
assign UnalignedNextEPCM = TrapM ? ((wfiM & IntPendingM) ? PCM+4 : PCM) : CSRWriteValM;
|
||||
assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[`XLEN-1:1], 1'b0} : {UnalignedNextEPCM[`XLEN-1:2], 2'b00}; // 3.1.15 alignment
|
||||
assign NextCauseM = TrapM ? {InterruptM, {(`XLEN-`LOG_XLEN-1){1'b0}}, CauseM}: CSRWriteValM;
|
||||
assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[`XLEN-1], CSRWriteValM[3:0]};
|
||||
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM;
|
||||
assign CSRMWriteM = CSRWriteM & (PrivilegeModeW == `M_MODE);
|
||||
assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW);
|
||||
|
@ -40,52 +40,52 @@ module csrc #(parameter
|
||||
TIME = 12'hC01,
|
||||
TIMEH = 12'hC81
|
||||
) (
|
||||
input logic clk, reset,
|
||||
input logic StallE, StallM,
|
||||
input logic FlushM,
|
||||
input logic InstrValidNotFlushedM, LoadStallD, StoreStallD,
|
||||
input logic CSRMWriteM, CSRWriteM,
|
||||
input logic BPDirPredWrongM,
|
||||
input logic BTAWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic IClassWrongM,
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic ICacheMiss,
|
||||
input logic ICacheAccess,
|
||||
input logic ICacheStallF,
|
||||
input logic DCacheStallM,
|
||||
input logic sfencevmaM,
|
||||
input logic InterruptM,
|
||||
input logic ExceptionM,
|
||||
input logic InvalidateICacheM,
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
output logic [`XLEN-1:0] CSRCReadValM,
|
||||
output logic IllegalCSRCAccessM
|
||||
input logic clk, reset,
|
||||
input logic StallE, StallM,
|
||||
input logic FlushM,
|
||||
input logic InstrValidNotFlushedM, LoadStallD, StoreStallD,
|
||||
input logic CSRMWriteM, CSRWriteM,
|
||||
input logic BPDirPredWrongM,
|
||||
input logic BTAWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic IClassWrongM,
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic ICacheMiss,
|
||||
input logic ICacheAccess,
|
||||
input logic ICacheStallF,
|
||||
input logic DCacheStallM,
|
||||
input logic sfencevmaM,
|
||||
input logic InterruptM,
|
||||
input logic ExceptionM,
|
||||
input logic InvalidateICacheM,
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
output logic [`XLEN-1:0] CSRCReadValM,
|
||||
output logic IllegalCSRCAccessM
|
||||
);
|
||||
|
||||
logic [4:0] CounterNumM;
|
||||
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
|
||||
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
|
||||
logic LoadStallE, LoadStallM;
|
||||
logic StoreStallE, StoreStallM;
|
||||
logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
|
||||
logic [`COUNTERS-1:0] CounterEvent;
|
||||
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
|
||||
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0];
|
||||
genvar i;
|
||||
logic [4:0] CounterNumM;
|
||||
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
|
||||
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
|
||||
logic LoadStallE, LoadStallM;
|
||||
logic StoreStallE, StoreStallM;
|
||||
logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
|
||||
logic [`COUNTERS-1:0] CounterEvent;
|
||||
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
|
||||
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0];
|
||||
genvar i;
|
||||
|
||||
// Interface signals
|
||||
flopenrc #(2) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d({StoreStallD, LoadStallD}), .q({StoreStallE, LoadStallE})); // don't flush the load stall during a load stall.
|
||||
flopenrc #(2) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d({StoreStallE, LoadStallE}), .q({StoreStallM, LoadStallM}));
|
||||
flopenrc #(2) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d({StoreStallE, LoadStallE}), .q({StoreStallM, LoadStallM}));
|
||||
|
||||
// Determine when to increment each counter
|
||||
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
|
||||
@ -97,11 +97,11 @@ module csrc #(parameter
|
||||
assign CounterEvent[3] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
|
||||
assign CounterEvent[4] = InstrClassM[1] & ~InstrClassM[2] & InstrValidNotFlushedM; // jump and not return instructions
|
||||
assign CounterEvent[5] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
|
||||
assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
|
||||
assign CounterEvent[6] = BPWrongM & InstrValidNotFlushedM; // branch predictor wrong
|
||||
assign CounterEvent[7] = BPDirPredWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
|
||||
assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
|
||||
assign CounterEvent[8] = BTAWrongM & InstrValidNotFlushedM; // branch predictor wrong target
|
||||
assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
|
||||
assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
|
||||
assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
|
||||
assign CounterEvent[11] = LoadStallM & InstrValidNotFlushedM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
|
||||
assign CounterEvent[12] = StoreStallM & InstrValidNotFlushedM; // Store Stall
|
||||
assign CounterEvent[13] = DCacheAccess & InstrValidNotFlushedM; // data cache access
|
||||
@ -111,7 +111,7 @@ module csrc #(parameter
|
||||
assign CounterEvent[17] = ICacheMiss; // instruction cache miss. Miss asserted 1 cycle at start of cache miss
|
||||
assign CounterEvent[18] = ICacheStallF; // i cache miss cycles
|
||||
assign CounterEvent[19] = CSRWriteM & InstrValidNotFlushedM; // CSR writes
|
||||
assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i
|
||||
assign CounterEvent[20] = InvalidateICacheM & InstrValidNotFlushedM; // fence.i
|
||||
assign CounterEvent[21] = sfencevmaM & InstrValidNotFlushedM; // sfence.vma
|
||||
assign CounterEvent[22] = InterruptM; // interrupt, InstrValidNotFlushedM will be low
|
||||
assign CounterEvent[23] = ExceptionM; // exceptions, InstrValidNotFlushedM will be low
|
||||
|
@ -34,14 +34,14 @@ module csri #(parameter
|
||||
MIP = 12'h344,
|
||||
SIE = 12'h104,
|
||||
SIP = 12'h144) (
|
||||
input logic clk, reset,
|
||||
input logic InstrValidNotFlushedM,
|
||||
input logic CSRMWriteM, CSRSWriteM,
|
||||
input logic clk, reset,
|
||||
input logic InstrValidNotFlushedM,
|
||||
input logic CSRMWriteM, CSRSWriteM,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt,
|
||||
input logic [11:0] MIDELEG_REGW,
|
||||
output logic [11:0] MIP_REGW, MIE_REGW,
|
||||
output logic [11:0] MIP_REGW, MIE_REGW,
|
||||
output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0
|
||||
);
|
||||
|
||||
|
@ -69,33 +69,33 @@ module csrm #(parameter
|
||||
DSCRATCH1 = 12'h7B3,
|
||||
// Constants
|
||||
ZERO = {(`XLEN){1'b0}},
|
||||
MEDELEG_MASK = ~(ZERO | `XLEN'b1 << 11),
|
||||
MEDELEG_MASK = 16'hB3FF,
|
||||
MIDELEG_MASK = 12'h222 // we choose to not make machine interrupts delegable
|
||||
) (
|
||||
input logic clk, reset,
|
||||
input logic InstrValidNotFlushedM,
|
||||
input logic CSRMWriteM, MTrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [11:0] MIP_REGW, MIE_REGW,
|
||||
output logic [`XLEN-1:0] CSRMReadValM, MTVEC_REGW,
|
||||
output logic [`XLEN-1:0] MEPC_REGW,
|
||||
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
|
||||
output logic [`XLEN-1:0] MEDELEG_REGW,
|
||||
output logic [11:0] MIDELEG_REGW,
|
||||
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
|
||||
input logic clk, reset,
|
||||
input logic InstrValidNotFlushedM,
|
||||
input logic CSRMWriteM, MTrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [`XLEN-1:0] NextEPCM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW,
|
||||
input logic [4:0] NextCauseM,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [11:0] MIP_REGW, MIE_REGW,
|
||||
output logic [`XLEN-1:0] CSRMReadValM, MTVEC_REGW,
|
||||
output logic [`XLEN-1:0] MEPC_REGW,
|
||||
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
|
||||
output logic [15:0] MEDELEG_REGW,
|
||||
output logic [11:0] MIDELEG_REGW,
|
||||
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
|
||||
output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
|
||||
output logic WriteMSTATUSM, WriteMSTATUSHM,
|
||||
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM
|
||||
output logic WriteMSTATUSM, WriteMSTATUSHM,
|
||||
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM
|
||||
);
|
||||
|
||||
logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW;
|
||||
logic [`XLEN-1:0] MSCRATCH_REGW;
|
||||
logic [`XLEN-1:0] MCAUSE_REGW, MTVAL_REGW;
|
||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||
logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW;
|
||||
logic [`XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW;
|
||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||
|
||||
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
|
||||
genvar i;
|
||||
@ -150,13 +150,13 @@ module csrm #(parameter
|
||||
// CSRs
|
||||
flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW);
|
||||
if (`S_SUPPORTED) begin:deleg // DELEG registers should exist
|
||||
flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK, MEDELEG_REGW);
|
||||
flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW);
|
||||
flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW);
|
||||
flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW);
|
||||
end else assign {MEDELEG_REGW, MIDELEG_REGW} = 0;
|
||||
|
||||
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
|
||||
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
|
||||
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
|
||||
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, {NextCauseM[4], {(`XLEN-5){1'b0}}, NextCauseM[3:0]}, MCAUSE_REGW);
|
||||
if(`QEMU) assign MTVAL_REGW = `XLEN'b0; // MTVAL tied to 0 in QEMU configuration
|
||||
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
|
||||
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW);
|
||||
@ -192,7 +192,7 @@ module csrm #(parameter
|
||||
MSTATUS: CSRMReadValM = MSTATUS_REGW;
|
||||
MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
|
||||
MTVEC: CSRMReadValM = MTVEC_REGW;
|
||||
MEDELEG: CSRMReadValM = MEDELEG_REGW;
|
||||
MEDELEG: CSRMReadValM = {{(`XLEN-16){1'b0}}, MEDELEG_REGW};
|
||||
MIDELEG: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIDELEG_REGW};
|
||||
MIP: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIP_REGW};
|
||||
MIE: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIE_REGW};
|
||||
|
@ -44,23 +44,24 @@ module csrs #(parameter
|
||||
STIMECMP = 12'h14D,
|
||||
STIMECMPH = 12'h15D,
|
||||
SATP = 12'h180) (
|
||||
input logic clk, reset,
|
||||
input logic InstrValidNotFlushedM,
|
||||
input logic CSRSWriteM, STrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW,
|
||||
input logic STATUS_TVM,
|
||||
input logic clk, reset,
|
||||
input logic InstrValidNotFlushedM,
|
||||
input logic CSRSWriteM, STrapM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [`XLEN-1:0] NextEPCM, NextMtvalM, SSTATUS_REGW,
|
||||
input logic [4:0] NextCauseM,
|
||||
input logic STATUS_TVM,
|
||||
input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
output logic [`XLEN-1:0] CSRSReadValM, STVEC_REGW,
|
||||
output logic [`XLEN-1:0] SEPC_REGW,
|
||||
output logic [31:0] SCOUNTEREN_REGW,
|
||||
output logic [`XLEN-1:0] SATP_REGW,
|
||||
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
output logic WriteSSTATUSM,
|
||||
output logic IllegalCSRSAccessM,
|
||||
output logic WriteSSTATUSM,
|
||||
output logic IllegalCSRSAccessM,
|
||||
output logic STimerInt
|
||||
);
|
||||
|
||||
@ -68,13 +69,12 @@ module csrs #(parameter
|
||||
localparam ZERO = {(`XLEN){1'b0}};
|
||||
localparam SEDELEG_MASK = ~(ZERO | `XLEN'b111 << 9);
|
||||
|
||||
logic WriteSTVECM;
|
||||
logic WriteSSCRATCHM, WriteSEPCM;
|
||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||
logic WriteSTIMECMPM, WriteSTIMECMPHM;
|
||||
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW;
|
||||
logic [`XLEN-1:0] SCAUSE_REGW;
|
||||
logic [63:0] STIMECMP_REGW;
|
||||
logic WriteSTVECM;
|
||||
logic WriteSSCRATCHM, WriteSEPCM;
|
||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||
logic WriteSTIMECMPM, WriteSTIMECMPHM;
|
||||
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW, SCAUSE_REGW;
|
||||
logic [63:0] STIMECMP_REGW;
|
||||
|
||||
// write enables
|
||||
// *** can InstrValidNotFlushed be factored out of all these writes into CSRWriteM?
|
||||
@ -93,7 +93,7 @@ module csrs #(parameter
|
||||
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
|
||||
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
|
||||
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
|
||||
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW);
|
||||
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(`XLEN-5){1'b0}}, NextCauseM[3:0]}, SCAUSE_REGW);
|
||||
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
|
||||
if (`VIRTMEM_SUPPORTED)
|
||||
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
|
||||
@ -129,10 +129,10 @@ module csrs #(parameter
|
||||
SCAUSE: CSRSReadValM = SCAUSE_REGW;
|
||||
STVAL: CSRSReadValM = STVAL_REGW;
|
||||
SATP: if (`VIRTMEM_SUPPORTED & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
|
||||
else begin
|
||||
CSRSReadValM = 0;
|
||||
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
|
||||
end
|
||||
else begin
|
||||
CSRSReadValM = 0;
|
||||
IllegalCSRSAccessM = 1;
|
||||
end
|
||||
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
|
||||
STIMECMP: if (`SSTC_SUPPORTED & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM)) CSRSReadValM = STIMECMP_REGW[`XLEN-1:0];
|
||||
else begin
|
||||
|
@ -52,7 +52,7 @@ module csrsr (
|
||||
logic [1:0] STATUS_SXL, STATUS_UXL, STATUS_XS, STATUS_FS_INT, STATUS_MPP_NEXT;
|
||||
logic STATUS_MPIE, STATUS_SPIE, STATUS_UBE, STATUS_SBE, STATUS_MBE;
|
||||
logic nextMBE, nextSBE;
|
||||
|
||||
|
||||
// STATUS REGISTER FIELD
|
||||
// See Privileged Spec Section 3.1.6
|
||||
// Lower privilege status registers are a subset of the full status register
|
||||
@ -68,7 +68,7 @@ module csrsr (
|
||||
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
|
||||
STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE,
|
||||
/*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0};
|
||||
assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
|
||||
assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be.
|
||||
end else begin: csrsr32 // RV32
|
||||
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
|
||||
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
|
||||
|
@ -48,7 +48,7 @@ module csru #(parameter
|
||||
logic [4:0] FFLAGS_REGW;
|
||||
logic [2:0] NextFRMM;
|
||||
logic [4:0] NextFFLAGSM;
|
||||
logic SetOrWriteFFLAGSM;
|
||||
logic SetOrWriteFFLAGSM;
|
||||
|
||||
// Write enables
|
||||
//assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & InstrValidNotFlushedM;
|
||||
|
@ -34,86 +34,86 @@ module privileged (
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
// CSR Reads and Writes, and values needed for traps
|
||||
input logic CSRReadM, CSRWriteM, // Read or write CSRs
|
||||
input logic [`XLEN-1:0] SrcAM, // GPR register to write
|
||||
input logic [31:0] InstrM, // Instruction
|
||||
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||
input logic [`XLEN-1:0] IEUAdrM, // address from IEU
|
||||
input logic [`XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic
|
||||
// control signals
|
||||
input logic InstrValidM, // Current instruction is valid (not flushed)
|
||||
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
|
||||
input logic PrivilegedM, // privileged instruction
|
||||
// processor events for performance counter logging
|
||||
input logic FRegWriteM, // instruction will write floating-point registers
|
||||
input logic LoadStallD, // load instruction is stalling
|
||||
input logic StoreStallD, // store instruction is stalling
|
||||
input logic ICacheStallF, // I cache stalled
|
||||
input logic DCacheStallM, // D cache stalled
|
||||
input logic BPDirPredWrongM, // branch predictor guessed wrong direction
|
||||
input logic BTAWrongM, // branch predictor guessed wrong target
|
||||
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
||||
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM, // actual instruction class
|
||||
input logic DCacheMiss, // data cache miss
|
||||
input logic DCacheAccess, // data cache accessed (hit or miss)
|
||||
input logic ICacheMiss, // instruction cache miss
|
||||
input logic ICacheAccess, // instruction cache access
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
// fault sources
|
||||
input logic InstrAccessFaultF, // instruction access fault
|
||||
input logic LoadAccessFaultM, StoreAmoAccessFaultM, // load or store access fault
|
||||
input logic HPTWInstrAccessFaultM, // hardware page table access fault while fetching instruction PTE
|
||||
input logic InstrPageFaultF, // page faults
|
||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults
|
||||
input logic InstrMisalignedFaultM, // misaligned instruction fault
|
||||
input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault
|
||||
input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU
|
||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources
|
||||
input logic [63:0] MTIME_CLINT, // timer value from CLINT
|
||||
input logic [4:0] SetFflagsM, // set FCSR flags from FPU
|
||||
input logic SelHPTW, // HPTW in use. Causes system to use S-mode endianness for accesses
|
||||
// CSR outputs
|
||||
output logic [`XLEN-1:0] CSRReadValW, // Value read from CSR
|
||||
output logic [1:0] PrivilegeModeW, // current privilege mode
|
||||
output logic [`XLEN-1:0] SATP_REGW, // supervisor address translation register
|
||||
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // status register bits
|
||||
output logic [1:0] STATUS_MPP, STATUS_FS, // status register bits
|
||||
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration entries to MMU
|
||||
output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], // PMP address entries to MMU
|
||||
output logic [2:0] FRM_REGW, // FPU rounding mode
|
||||
// PC logic output in privileged unit
|
||||
output logic [`XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
|
||||
// control outputs
|
||||
output logic RetM, TrapM, // return instruction, or trap
|
||||
output logic sfencevmaM, // sfence.vma instruction
|
||||
input logic InvalidateICacheM, // fence instruction
|
||||
output logic BigEndianM, // Use big endian in current privilege mode
|
||||
// Fault outputs
|
||||
output logic BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire
|
||||
output logic WFIStallM // Stall in Memory stage for WFI until interrupt or timeout
|
||||
);
|
||||
|
||||
logic [`LOG_XLEN-1:0] CauseM; // trap cause
|
||||
logic [`XLEN-1:0] MEDELEG_REGW; // exception delegation CSR
|
||||
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
|
||||
logic sretM, mretM; // supervisor / machine return instruction
|
||||
logic IllegalCSRAccessM; // Illegal access to CSR
|
||||
logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage
|
||||
logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage
|
||||
logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages
|
||||
logic IllegalInstrFaultM; // Illegal instruction fault
|
||||
logic STATUS_SPP, STATUS_TSR, STATUS_TW, STATUS_TVM; // Status bits needed within privileged unit
|
||||
logic STATUS_MIE, STATUS_SIE; // status bits: interrupt enables
|
||||
logic [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
||||
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
||||
logic DelegateM; // trap should be delegated
|
||||
logic wfiM; // wait for interrupt instruction
|
||||
logic IntPendingM; // interrupt is pending, even if not enabled. ends wfi
|
||||
logic InterruptM; // interrupt occuring
|
||||
logic ExceptionM; // Memory stage instruction caused a fault
|
||||
input logic CSRReadM, CSRWriteM, // Read or write CSRs
|
||||
input logic [`XLEN-1:0] SrcAM, // GPR register to write
|
||||
input logic [31:0] InstrM, // Instruction
|
||||
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||
input logic [`XLEN-1:0] IEUAdrM, // address from IEU
|
||||
input logic [`XLEN-1:0] PCM, PC2NextF, // program counter, next PC going to trap/return PC logic
|
||||
// control signals
|
||||
input logic InstrValidM, // Current instruction is valid (not flushed)
|
||||
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
|
||||
input logic PrivilegedM, // privileged instruction
|
||||
// processor events for performance counter logging
|
||||
input logic FRegWriteM, // instruction will write floating-point registers
|
||||
input logic LoadStallD, // load instruction is stalling
|
||||
input logic StoreStallD, // store instruction is stalling
|
||||
input logic ICacheStallF, // I cache stalled
|
||||
input logic DCacheStallM, // D cache stalled
|
||||
input logic BPDirPredWrongM, // branch predictor guessed wrong direction
|
||||
input logic BTAWrongM, // branch predictor guessed wrong target
|
||||
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
||||
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] InstrClassM, // actual instruction class
|
||||
input logic DCacheMiss, // data cache miss
|
||||
input logic DCacheAccess, // data cache accessed (hit or miss)
|
||||
input logic ICacheMiss, // instruction cache miss
|
||||
input logic ICacheAccess, // instruction cache access
|
||||
input logic DivBusyE, // integer divide busy
|
||||
input logic FDivBusyE, // floating point divide busy
|
||||
// fault sources
|
||||
input logic InstrAccessFaultF, // instruction access fault
|
||||
input logic LoadAccessFaultM, StoreAmoAccessFaultM, // load or store access fault
|
||||
input logic HPTWInstrAccessFaultM, // hardware page table access fault while fetching instruction PTE
|
||||
input logic InstrPageFaultF, // page faults
|
||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // page faults
|
||||
input logic InstrMisalignedFaultM, // misaligned instruction fault
|
||||
input logic LoadMisalignedFaultM, StoreAmoMisalignedFaultM, // misaligned data fault
|
||||
input logic IllegalIEUFPUInstrD, // illegal instruction from IEU or FPU
|
||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt, // interrupt sources
|
||||
input logic [63:0] MTIME_CLINT, // timer value from CLINT
|
||||
input logic [4:0] SetFflagsM, // set FCSR flags from FPU
|
||||
input logic SelHPTW, // HPTW in use. Causes system to use S-mode endianness for accesses
|
||||
// CSR outputs
|
||||
output logic [`XLEN-1:0] CSRReadValW, // Value read from CSR
|
||||
output logic [1:0] PrivilegeModeW, // current privilege mode
|
||||
output logic [`XLEN-1:0] SATP_REGW, // supervisor address translation register
|
||||
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // status register bits
|
||||
output logic [1:0] STATUS_MPP, STATUS_FS, // status register bits
|
||||
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], // PMP configuration entries to MMU
|
||||
output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], // PMP address entries to MMU
|
||||
output logic [2:0] FRM_REGW, // FPU rounding mode
|
||||
// PC logic output in privileged unit
|
||||
output logic [`XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
|
||||
// control outputs
|
||||
output logic RetM, TrapM, // return instruction, or trap
|
||||
output logic sfencevmaM, // sfence.vma instruction
|
||||
input logic InvalidateICacheM, // fence instruction
|
||||
output logic BigEndianM, // Use big endian in current privilege mode
|
||||
// Fault outputs
|
||||
output logic BreakpointFaultM, EcallFaultM, // breakpoint and Ecall traps should retire
|
||||
output logic WFIStallM // Stall in Memory stage for WFI until interrupt or timeout
|
||||
);
|
||||
|
||||
logic [3:0] CauseM; // trap cause
|
||||
logic [15:0] MEDELEG_REGW; // exception delegation CSR
|
||||
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
|
||||
logic sretM, mretM; // supervisor / machine return instruction
|
||||
logic IllegalCSRAccessM; // Illegal access to CSR
|
||||
logic IllegalIEUFPUInstrM; // Illegal IEU or FPU instruction, delayed to Mem stage
|
||||
logic InstrPageFaultM; // Instruction page fault, delayed to Mem stage
|
||||
logic InstrAccessFaultM; // Instruction access fault, delayed to Mem stages
|
||||
logic IllegalInstrFaultM; // Illegal instruction fault
|
||||
logic STATUS_SPP, STATUS_TSR, STATUS_TW, STATUS_TVM; // Status bits needed within privileged unit
|
||||
logic STATUS_MIE, STATUS_SIE; // status bits: interrupt enables
|
||||
logic [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
||||
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
||||
logic DelegateM; // trap should be delegated
|
||||
logic wfiM; // wait for interrupt instruction
|
||||
logic IntPendingM; // interrupt is pending, even if not enabled. ends wfi
|
||||
logic InterruptM; // interrupt occuring
|
||||
logic ExceptionM; // Memory stage instruction caused a fault
|
||||
|
||||
// track the current privilege level
|
||||
privmode privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
|
||||
|
@ -29,33 +29,33 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module trap (
|
||||
input logic reset,
|
||||
input logic InstrMisalignedFaultM, InstrAccessFaultM, HPTWInstrAccessFaultM, IllegalInstrFaultM,
|
||||
input logic BreakpointFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM,
|
||||
input logic LoadAccessFaultM, StoreAmoAccessFaultM, EcallFaultM, InstrPageFaultM,
|
||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // various trap sources
|
||||
input logic mretM, sretM, // return instructions
|
||||
input logic wfiM, // wait for interrupt instruction
|
||||
input logic [1:0] PrivilegeModeW, // current privilege mode
|
||||
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, // interrupt pending, enabled, and delegate CSRs
|
||||
input logic [`XLEN-1:0] MEDELEG_REGW, // exception delegation SR
|
||||
input logic STATUS_MIE, STATUS_SIE, // machine/supervisor interrupt enables
|
||||
input logic InstrValidM, // current instruction is valid, not flushed
|
||||
input logic CommittedM, CommittedF, // LSU/IFU has committed to a bus operation that can't be interrupted
|
||||
output logic TrapM, // Trap is occurring
|
||||
output logic RetM, // Return instruction being executed
|
||||
output logic InterruptM, // Interrupt is occurring
|
||||
output logic ExceptionM, // exception is occurring
|
||||
output logic IntPendingM, // Interrupt is pending, might occur if enabled
|
||||
output logic DelegateM, // Delegate trap to supervisor handler
|
||||
output logic WFIStallM, // Stall due to WFI instruction
|
||||
output logic [`LOG_XLEN-1:0] CauseM // trap cause
|
||||
input logic reset,
|
||||
input logic InstrMisalignedFaultM, InstrAccessFaultM, HPTWInstrAccessFaultM, IllegalInstrFaultM,
|
||||
input logic BreakpointFaultM, LoadMisalignedFaultM, StoreAmoMisalignedFaultM,
|
||||
input logic LoadAccessFaultM, StoreAmoAccessFaultM, EcallFaultM, InstrPageFaultM,
|
||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // various trap sources
|
||||
input logic mretM, sretM, // return instructions
|
||||
input logic wfiM, // wait for interrupt instruction
|
||||
input logic [1:0] PrivilegeModeW, // current privilege mode
|
||||
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, // interrupt pending, enabled, and delegate CSRs
|
||||
input logic [15:0] MEDELEG_REGW, // exception delegation SR
|
||||
input logic STATUS_MIE, STATUS_SIE, // machine/supervisor interrupt enables
|
||||
input logic InstrValidM, // current instruction is valid, not flushed
|
||||
input logic CommittedM, CommittedF, // LSU/IFU has committed to a bus operation that can't be interrupted
|
||||
output logic TrapM, // Trap is occurring
|
||||
output logic RetM, // Return instruction being executed
|
||||
output logic InterruptM, // Interrupt is occurring
|
||||
output logic ExceptionM, // exception is occurring
|
||||
output logic IntPendingM, // Interrupt is pending, might occur if enabled
|
||||
output logic DelegateM, // Delegate trap to supervisor handler
|
||||
output logic WFIStallM, // Stall due to WFI instruction
|
||||
output logic [3:0] CauseM // trap cause
|
||||
);
|
||||
|
||||
logic MIntGlobalEnM, SIntGlobalEnM; // Global interupt enables
|
||||
logic Committed; // LSU or IFU has committed to a bus operation that can't be interrupted
|
||||
logic BothInstrAccessFaultM; // instruction or HPTW ITLB fill caused an Instruction Access Fault
|
||||
logic [11:0] PendingIntsM, ValidIntsM, EnabledIntsM; // interrupts are pending, valid, or enabled
|
||||
logic MIntGlobalEnM, SIntGlobalEnM; // Global interupt enables
|
||||
logic Committed; // LSU or IFU has committed to a bus operation that can't be interrupted
|
||||
logic BothInstrAccessFaultM; // instruction or HPTW ITLB fill caused an Instruction Access Fault
|
||||
logic [11:0] PendingIntsM, ValidIntsM, EnabledIntsM; // interrupts are pending, valid, or enabled
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Determine pending enabled interrupts
|
||||
@ -72,7 +72,7 @@ module trap (
|
||||
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
||||
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
||||
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
|
||||
assign DelegateM = `S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM[3:0]] : MEDELEG_REGW[CauseM]) &
|
||||
assign DelegateM = `S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
|
||||
(PrivilegeModeW == `U_MODE | PrivilegeModeW == `S_MODE);
|
||||
assign WFIStallM = wfiM & ~IntPendingM;
|
||||
|
||||
@ -109,7 +109,7 @@ module trap (
|
||||
else if (IllegalInstrFaultM) CauseM = 2;
|
||||
else if (InstrMisalignedFaultM) CauseM = 0;
|
||||
else if (BreakpointFaultM) CauseM = 3;
|
||||
else if (EcallFaultM) CauseM = {{(`LOG_XLEN-4){1'b0}}, {2'b10}, PrivilegeModeW};
|
||||
else if (EcallFaultM) CauseM = {2'b10, PrivilegeModeW};
|
||||
else if (LoadMisalignedFaultM) CauseM = 4;
|
||||
else if (StoreAmoMisalignedFaultM) CauseM = 6;
|
||||
else if (LoadPageFaultM) CauseM = 13;
|
||||
|
@ -40,7 +40,7 @@ module clint_apb (
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
output logic [63:0] MTIME,
|
||||
output logic MTimerInt, MSwInt
|
||||
output logic MTimerInt, MSwInt
|
||||
);
|
||||
|
||||
logic MSIP;
|
||||
|
@ -41,8 +41,8 @@ module gpio_apb (
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic [31:0] iof0, iof1,
|
||||
input logic [31:0] GPIOPinsIn,
|
||||
output logic [31:0] GPIOPinsOut, GPIOPinsEn,
|
||||
input logic [31:0] GPIOIN,
|
||||
output logic [31:0] GPIOOUT, GPIOEN,
|
||||
output logic GPIOIntr
|
||||
);
|
||||
|
||||
@ -138,8 +138,8 @@ module gpio_apb (
|
||||
|
||||
// chip i/o
|
||||
// connect OUT to IN for loopback testing
|
||||
if (`GPIO_LOOPBACK_TEST) assign input0d = ((output_en & GPIOPinsOut) | (~output_en & GPIOPinsIn)) & input_en;
|
||||
else assign input0d = GPIOPinsIn & input_en;
|
||||
if (`GPIO_LOOPBACK_TEST) assign input0d = ((output_en & GPIOOUT) | (~output_en & GPIOIN)) & input_en;
|
||||
else assign input0d = GPIOIN & input_en;
|
||||
|
||||
// synchroninzer for inputs
|
||||
flop #(32) sync1(PCLK,input0d,input1d);
|
||||
@ -148,8 +148,8 @@ module gpio_apb (
|
||||
assign input_val = input3d;
|
||||
assign iof_out = iof_sel & iof1 | ~iof_sel & iof0; // per-bit mux between iof1 and iof0
|
||||
assign gpio_out = iof_en & iof_out | ~iof_en & output_val; // per-bit mux between IOF and output_val
|
||||
assign GPIOPinsOut = gpio_out ^ out_xor; // per-bit flip output polarity
|
||||
assign GPIOPinsEn = output_en;
|
||||
assign GPIOOUT = gpio_out ^ out_xor; // per-bit flip output polarity
|
||||
assign GPIOEN = output_en;
|
||||
|
||||
assign GPIOIntr = |{(rise_ip & rise_ie),(fall_ip & fall_ie),(high_ip & high_ie),(low_ip & low_ie)};
|
||||
endmodule
|
||||
|
@ -43,37 +43,37 @@
|
||||
// hardcoded to 2 contexts for now; later upgrade to arbitrary (up to 15872) contexts
|
||||
|
||||
module plic_apb (
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [27:0] PADDR,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic PCLK, PRESETn,
|
||||
input logic PSEL,
|
||||
input logic [27:0] PADDR,
|
||||
input logic [`XLEN-1:0] PWDATA,
|
||||
input logic [`XLEN/8-1:0] PSTRB,
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic UARTIntr,GPIOIntr,
|
||||
output logic MExtInt, SExtInt
|
||||
input logic PWRITE,
|
||||
input logic PENABLE,
|
||||
output logic [`XLEN-1:0] PRDATA,
|
||||
output logic PREADY,
|
||||
input logic UARTIntr,GPIOIntr,
|
||||
output logic MExtInt, SExtInt
|
||||
);
|
||||
|
||||
logic memwrite, memread;
|
||||
logic [23:0] entry;
|
||||
logic [31:0] Din, Dout;
|
||||
logic memwrite, memread;
|
||||
logic [23:0] entry;
|
||||
logic [31:0] Din, Dout;
|
||||
|
||||
// context-independent signals
|
||||
logic [`N:1] requests;
|
||||
logic [`N:1][2:0] intPriority;
|
||||
logic [`N:1] intInProgress, intPending, nextIntPending;
|
||||
logic [`N:1] requests;
|
||||
logic [`N:1][2:0] intPriority;
|
||||
logic [`N:1] intInProgress, intPending, nextIntPending;
|
||||
|
||||
// context-dependent signals
|
||||
logic [`C-1:0][2:0] intThreshold;
|
||||
logic [`C-1:0][`N:1] intEn;
|
||||
logic [`C-1:0][5:0] intClaim; // ID's are 6 bits if we stay within 63 sources
|
||||
logic [`C-1:0][7:1][`N:1] irqMatrix;
|
||||
logic [`C-1:0][7:1] priorities_with_irqs;
|
||||
logic [`C-1:0][7:1] max_priority_with_irqs;
|
||||
logic [`C-1:0][`N:1] irqs_at_max_priority;
|
||||
logic [`C-1:0][7:1] threshMask;
|
||||
logic [`C-1:0][2:0] intThreshold;
|
||||
logic [`C-1:0][`N:1] intEn;
|
||||
logic [`C-1:0][5:0] intClaim; // ID's are 6 bits if we stay within 63 sources
|
||||
logic [`C-1:0][7:1][`N:1] irqMatrix;
|
||||
logic [`C-1:0][7:1] priorities_with_irqs;
|
||||
logic [`C-1:0][7:1] max_priority_with_irqs;
|
||||
logic [`C-1:0][`N:1] irqs_at_max_priority;
|
||||
logic [`C-1:0][7:1] threshMask;
|
||||
|
||||
// =======
|
||||
// AHB I/O
|
||||
@ -97,7 +97,7 @@ module plic_apb (
|
||||
// ==================
|
||||
// Register Interface
|
||||
// ==================
|
||||
always @(posedge PCLK,negedge PRESETn) begin
|
||||
always @(posedge PCLK) begin
|
||||
// resetting
|
||||
if (~PRESETn) begin
|
||||
intPriority <= #1 {`N{3'b0}};
|
||||
@ -128,7 +128,7 @@ module plic_apb (
|
||||
if (memread)
|
||||
casez(entry)
|
||||
24'h000000: Dout <= #1 32'b0; // there is no intPriority[0]
|
||||
24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]};
|
||||
24'h0000??: Dout <= #1 {29'b0,intPriority[entry[7:2]]};
|
||||
`ifdef PLIC_NUM_SRC_LT_32
|
||||
24'h001000: Dout <= #1 {{(31-`N){1'b0}},intPending,1'b0};
|
||||
24'h002000: Dout <= #1 {{(31-`N){1'b0}},intEn[0],1'b0};
|
||||
|
@ -30,27 +30,27 @@
|
||||
`define RAM_LATENCY 0
|
||||
|
||||
module ram_ahb #(parameter BASE=0, RANGE = 65535) (
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELRam,
|
||||
input logic [`PA_BITS-1:0] HADDR,
|
||||
input logic HWRITE,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic [`XLEN-1:0] HREADRam,
|
||||
output logic HRESPRam, HREADYRam
|
||||
input logic HCLK, HRESETn,
|
||||
input logic HSELRam,
|
||||
input logic [`PA_BITS-1:0] HADDR,
|
||||
input logic HWRITE,
|
||||
input logic HREADY,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic [`XLEN-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic [`XLEN-1:0] HREADRam,
|
||||
output logic HRESPRam, HREADYRam
|
||||
);
|
||||
|
||||
localparam ADDR_WIDTH = $clog2(RANGE/8);
|
||||
localparam OFFSET = $clog2(`XLEN/8);
|
||||
|
||||
logic [`XLEN/8-1:0] ByteMask;
|
||||
logic [`PA_BITS-1:0] HADDRD, RamAddr;
|
||||
logic initTrans;
|
||||
logic memwrite, memwriteD, memread;
|
||||
logic nextHREADYRam;
|
||||
logic DelayReady;
|
||||
logic [`XLEN/8-1:0] ByteMask;
|
||||
logic [`PA_BITS-1:0] HADDRD, RamAddr;
|
||||
logic initTrans;
|
||||
logic memwrite, memwriteD, memread;
|
||||
logic nextHREADYRam;
|
||||
logic DelayReady;
|
||||
|
||||
// a new AHB transactions starts when HTRANS requests a transaction,
|
||||
// the peripheral is selected, and the previous transaction is completing
|
||||
@ -92,13 +92,13 @@ module ram_ahb #(parameter BASE=0, RANGE = 65535) (
|
||||
else CurrState <= #1 NextState;
|
||||
|
||||
always_comb begin
|
||||
case(CurrState)
|
||||
READY: if(initTrans & ~CycleFlag) NextState = DELAY;
|
||||
case(CurrState)
|
||||
READY: if(initTrans & ~CycleFlag) NextState = DELAY;
|
||||
else NextState = READY;
|
||||
DELAY: if(CycleFlag) NextState = READY;
|
||||
else NextState = DELAY;
|
||||
default: NextState = READY;
|
||||
endcase
|
||||
else NextState = DELAY;
|
||||
default: NextState = READY;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign CycleFlag = Cycle == `RAM_LATENCY;
|
||||
@ -108,7 +108,6 @@ module ram_ahb #(parameter BASE=0, RANGE = 65535) (
|
||||
end else begin
|
||||
assign DelayReady = 0;
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -37,19 +37,19 @@
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
|
||||
module uartPC16550D(
|
||||
// Processor Interface
|
||||
input logic PCLK, PRESETn, // UART clock and active low reset
|
||||
input logic [2:0] A, // address input (8 registers)
|
||||
input logic [7:0] Din, // 8-bit WriteData
|
||||
output logic [7:0] Dout, // 8-bit ReadData
|
||||
input logic MEMRb, MEMWb, // Active low memory read/write
|
||||
output logic INTR, TXRDYb, RXRDYb, // interrupt and ready lines
|
||||
// Clocks
|
||||
output logic BAUDOUTb, // active low baud clock
|
||||
input logic RCLK, // usually BAUDOUTb tied to RCLK externally
|
||||
// E1A Driver
|
||||
input logic SIN, DSRb, DCDb, CTSb, RIb, // UART external serial and flow-control inputs
|
||||
output logic SOUT, RTSb, DTRb, OUT1b, OUT2b // UART external serial and flow-control outputs
|
||||
// Processor Interface
|
||||
input logic PCLK, PRESETn, // UART clock and active low reset
|
||||
input logic [2:0] A, // address input (8 registers)
|
||||
input logic [7:0] Din, // 8-bit WriteData
|
||||
output logic [7:0] Dout, // 8-bit ReadData
|
||||
input logic MEMRb, MEMWb, // Active low memory read/write
|
||||
output logic INTR, TXRDYb, RXRDYb, // interrupt and ready lines
|
||||
// Clocks
|
||||
output logic BAUDOUTb, // active low baud clock
|
||||
input logic RCLK, // usually BAUDOUTb tied to RCLK externally
|
||||
// E1A Driver
|
||||
input logic SIN, DSRb, DCDb, CTSb, RIb, // UART external serial and flow-control inputs
|
||||
output logic SOUT, RTSb, DTRb, OUT1b, OUT2b // UART external serial and flow-control outputs
|
||||
);
|
||||
|
||||
// transmit and receive states
|
||||
@ -62,63 +62,63 @@ module uartPC16550D(
|
||||
logic [4:0] MCR;
|
||||
|
||||
// Syncrhonized and delayed UART signals
|
||||
logic SINd, DSRbd, DCDbd, CTSbd, RIbd;
|
||||
logic SINsync, DSRbsync, DCDbsync, CTSbsync, RIbsync;
|
||||
logic DSRb2, DCDb2, CTSb2, RIb2;
|
||||
logic SOUTbit;
|
||||
logic SINd, DSRbd, DCDbd, CTSbd, RIbd;
|
||||
logic SINsync, DSRbsync, DCDbsync, CTSbsync, RIbsync;
|
||||
logic DSRb2, DCDb2, CTSb2, RIb2;
|
||||
logic SOUTbit;
|
||||
|
||||
// Control signals
|
||||
logic loop; // loopback mode
|
||||
logic DLAB; // Divisor Latch Access Bit (LCR bit 7)
|
||||
logic loop; // loopback mode
|
||||
logic DLAB; // Divisor Latch Access Bit (LCR bit 7)
|
||||
|
||||
// Baud and rx/tx timing
|
||||
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
|
||||
logic baudpulse, txbaudpulse, rxbaudpulse; // high one system clk cycle each baud/16 period
|
||||
logic [16+`UART_PRESCALE-1:0] baudcount;
|
||||
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
|
||||
logic [3:0] rxbitsreceived, txbitssent;
|
||||
statetype rxstate, txstate;
|
||||
logic [3:0] rxoversampledcnt, txoversampledcnt; // count oversampled-by-16
|
||||
logic [3:0] rxbitsreceived, txbitssent;
|
||||
statetype rxstate, txstate;
|
||||
|
||||
// shift registrs and FIFOs
|
||||
logic [9:0] rxshiftreg;
|
||||
logic [10:0] rxfifo[15:0];
|
||||
logic [7:0] txfifo[15:0];
|
||||
logic [4:0] rxfifotailunwrapped;
|
||||
logic [3:0] rxfifohead, rxfifotail, txfifohead, txfifotail, rxfifotriggerlevel;
|
||||
logic [3:0] rxfifoentries, txfifoentries;
|
||||
logic [3:0] rxbitsexpected, txbitsexpected;
|
||||
logic [9:0] rxshiftreg;
|
||||
logic [10:0] rxfifo[15:0];
|
||||
logic [7:0] txfifo[15:0];
|
||||
logic [4:0] rxfifotailunwrapped;
|
||||
logic [3:0] rxfifohead, rxfifotail, txfifohead, txfifotail, rxfifotriggerlevel;
|
||||
logic [3:0] rxfifoentries, txfifoentries;
|
||||
logic [3:0] rxbitsexpected, txbitsexpected;
|
||||
|
||||
// receive data
|
||||
logic [10:0] RXBR;
|
||||
logic [9:0] rxtimeoutcnt;
|
||||
logic rxcentered;
|
||||
logic rxparity, rxparitybit, rxstopbit;
|
||||
logic rxparityerr, rxoverrunerr, rxframingerr, rxbreak, rxfifohaserr;
|
||||
logic rxdataready;
|
||||
logic rxfifoempty, rxfifotriggered, rxfifotimeout;
|
||||
logic rxfifodmaready;
|
||||
logic [8:0] rxdata9;
|
||||
logic [7:0] rxdata;
|
||||
logic [15:0] RXerrbit, rxfullbit;
|
||||
logic [31:0] rxfullbitunwrapped;
|
||||
logic [10:0] RXBR;
|
||||
logic [9:0] rxtimeoutcnt;
|
||||
logic rxcentered;
|
||||
logic rxparity, rxparitybit, rxstopbit;
|
||||
logic rxparityerr, rxoverrunerr, rxframingerr, rxbreak, rxfifohaserr;
|
||||
logic rxdataready;
|
||||
logic rxfifoempty, rxfifotriggered, rxfifotimeout;
|
||||
logic rxfifodmaready;
|
||||
logic [8:0] rxdata9;
|
||||
logic [7:0] rxdata;
|
||||
logic [15:0] RXerrbit, rxfullbit;
|
||||
logic [31:0] rxfullbitunwrapped;
|
||||
|
||||
// transmit data
|
||||
logic [7:0] TXHR, nexttxdata;
|
||||
logic [11:0] txdata, txsr;
|
||||
logic txnextbit, txhrfull, txsrfull;
|
||||
logic txparity;
|
||||
logic txfifoempty, txfifofull, txfifodmaready;
|
||||
logic [7:0] TXHR, nexttxdata;
|
||||
logic [11:0] txdata, txsr;
|
||||
logic txnextbit, txhrfull, txsrfull;
|
||||
logic txparity;
|
||||
logic txfifoempty, txfifofull, txfifodmaready;
|
||||
|
||||
// control signals
|
||||
logic fifoenabled, fifodmamodesel, evenparitysel;
|
||||
logic fifoenabled, fifodmamodesel, evenparitysel;
|
||||
|
||||
// interrupts
|
||||
logic RXerr, RXerrIP, squashRXerrIP, prevSquashRXerrIP, setSquashRXerrIP, resetSquashRXerrIP;
|
||||
logic THRE, THRE_IP, squashTHRE_IP, prevSquashTHRE_IP, setSquashTHRE_IP, resetSquashTHRE_IP;
|
||||
logic rxdataavailintr, modemstatusintr, intrpending;
|
||||
logic [2:0] intrID;
|
||||
logic RXerr, RXerrIP, squashRXerrIP, prevSquashRXerrIP, setSquashRXerrIP, resetSquashRXerrIP;
|
||||
logic THRE, THRE_IP, squashTHRE_IP, prevSquashTHRE_IP, setSquashTHRE_IP, resetSquashTHRE_IP;
|
||||
logic rxdataavailintr, modemstatusintr, intrpending;
|
||||
logic [2:0] intrID;
|
||||
|
||||
logic baudpulseComb;
|
||||
logic HeadPointerLastMove;
|
||||
logic baudpulseComb;
|
||||
logic HeadPointerLastMove;
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Input synchronization: 2-stage synchronizer
|
||||
@ -126,7 +126,7 @@ module uartPC16550D(
|
||||
always_ff @(posedge PCLK) begin
|
||||
{SINd, DSRbd, DCDbd, CTSbd, RIbd} <= #1 {SIN, DSRb, DCDb, CTSb, RIb};
|
||||
{SINsync, DSRbsync, DCDbsync, CTSbsync, RIbsync} <= #1 loop ? {SOUTbit, ~MCR[0], ~MCR[3], ~MCR[1], ~MCR[2]} :
|
||||
{SINd, DSRbd, DCDbd, CTSbd, RIbd}; // syncrhonized signals, handle loopback testing
|
||||
{SINd, DSRbd, DCDbd, CTSbd, RIbd}; // syncrhonized signals, handle loopback testing
|
||||
{DSRb2, DCDb2, CTSb2, RIb2} <= #1 {DSRbsync, DCDbsync, CTSbsync, RIbsync}; // for detecting state changes
|
||||
end
|
||||
|
||||
@ -141,8 +141,8 @@ module uartPC16550D(
|
||||
MCR <= #1 5'b0;
|
||||
LSR <= #1 8'b01100000;
|
||||
MSR <= #1 4'b0;
|
||||
DLL <= #1 8'd1; // this cannot be zero with DLM also zer0.
|
||||
DLM <= #1 8'b0;
|
||||
DLL <= #1 8'd1; // this cannot be zero with DLM also zer0.
|
||||
DLM <= #1 8'b0;
|
||||
SCR <= #1 8'b0; // not strictly necessary to reset
|
||||
end else begin
|
||||
if (~MEMWb) begin
|
||||
@ -290,7 +290,7 @@ module uartPC16550D(
|
||||
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
|
||||
|
||||
// receive FIFO and register
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
always_ff @(posedge PCLK)
|
||||
if (~PRESETn) begin
|
||||
rxfifohead <= #1 0; rxfifotail <= #1 0; rxdataready <= #1 0; RXBR <= #1 0;
|
||||
end else begin
|
||||
@ -367,7 +367,7 @@ module uartPC16550D(
|
||||
end
|
||||
|
||||
///////////////////////////////////////////
|
||||
// transmit timing and control
|
||||
// transmit timing and control
|
||||
///////////////////////////////////////////
|
||||
always_ff @(posedge PCLK, negedge PRESETn)
|
||||
if (~PRESETn) begin
|
||||
@ -455,20 +455,20 @@ module uartPC16550D(
|
||||
end
|
||||
|
||||
always_ff @(posedge PCLK, negedge PRESETn) begin
|
||||
// special condition to check if the fifo is empty or full. Because the head
|
||||
// pointer indicates where the next write goes and not the location of the
|
||||
// current head, the head and tail pointer being equal imply two different
|
||||
// things. First it could mean the fifo is empty and second it could mean
|
||||
// the fifo is full. To differenciate we need to know which pointer moved
|
||||
// to cause them to be equal. If the head pointer moved then it is full.
|
||||
// If the tail pointer moved then it is empty. it resets to empty so
|
||||
// if reset with the tail pointer indicating the last update.
|
||||
if(~PRESETn)
|
||||
HeadPointerLastMove <= 1'b0;
|
||||
else if(fifoenabled & ~MEMWb & A == 3'b000 & ~DLAB)
|
||||
HeadPointerLastMove <= 1'b1;
|
||||
else if(fifoenabled & ~txfifoempty & ~txsrfull & txstate == UART_IDLE)
|
||||
HeadPointerLastMove <= 1'b0;
|
||||
// special condition to check if the fifo is empty or full. Because the head
|
||||
// pointer indicates where the next write goes and not the location of the
|
||||
// current head, the head and tail pointer being equal imply two different
|
||||
// things. First it could mean the fifo is empty and second it could mean
|
||||
// the fifo is full. To differenciate we need to know which pointer moved
|
||||
// to cause them to be equal. If the head pointer moved then it is full.
|
||||
// If the tail pointer moved then it is empty. it resets to empty so
|
||||
// if reset with the tail pointer indicating the last update.
|
||||
if(~PRESETn)
|
||||
HeadPointerLastMove <= 1'b0;
|
||||
else if(fifoenabled & ~MEMWb & A == 3'b000 & ~DLAB)
|
||||
HeadPointerLastMove <= 1'b1;
|
||||
else if(fifoenabled & ~txfifoempty & ~txsrfull & txstate == UART_IDLE)
|
||||
HeadPointerLastMove <= 1'b0;
|
||||
end
|
||||
|
||||
assign txfifoempty = (txfifohead == txfifotail) & ~HeadPointerLastMove;
|
||||
@ -477,7 +477,7 @@ module uartPC16550D(
|
||||
(txfifohead + 16 - txfifotail);
|
||||
// verilator lint_on WIDTH
|
||||
//assign txfifofull = (txfifoentries == 4'b1111);
|
||||
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
|
||||
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
|
||||
|
||||
// transmit buffer ready bit
|
||||
always_ff @(posedge PCLK, negedge PRESETn) // track txrdy for DMA mode (FCR3 = FCR0 = 1)
|
||||
|
@ -31,58 +31,58 @@
|
||||
|
||||
module uncore (
|
||||
// AHB Bus Interface
|
||||
input logic HCLK, HRESETn,
|
||||
input logic TIMECLK,
|
||||
input logic HCLK, HRESETn,
|
||||
input logic TIMECLK,
|
||||
input logic [`PA_BITS-1:0] HADDR,
|
||||
input logic [`AHBW-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
input logic HWRITE,
|
||||
input logic [2:0] HSIZE,
|
||||
input logic [2:0] HBURST,
|
||||
input logic [3:0] HPROT,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HMASTLOCK,
|
||||
input logic [`AHBW-1:0] HRDATAEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
output logic [`AHBW-1:0] HRDATA,
|
||||
output logic HREADY, HRESP,
|
||||
output logic HSELEXT,
|
||||
// peripheral pins
|
||||
output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT
|
||||
output logic MExtInt, SExtInt, // External interrupts from PLIC
|
||||
output logic [63:0] MTIME_CLINT, // MTIME, from CLINT
|
||||
input logic [31:0] GPIOPinsIn, // GPIO pin input value
|
||||
output logic [31:0] GPIOPinsOut, GPIOPinsEn, // GPIO pin output value and enable
|
||||
input logic UARTSin, // UART serial input
|
||||
output logic UARTSout, // UART serial output
|
||||
output logic SDCCmdOut, // SD Card command output
|
||||
output logic SDCCmdOE, // SD Card command output enable
|
||||
input logic SDCCmdIn, // SD Card command input
|
||||
input logic [3:0] SDCDatIn, // SD Card data input
|
||||
output logic SDCCLK // SD Card clock
|
||||
input logic [`AHBW-1:0] HWDATA,
|
||||
input logic [`XLEN/8-1:0] HWSTRB,
|
||||
input logic HWRITE,
|
||||
input logic [2:0] HSIZE,
|
||||
input logic [2:0] HBURST,
|
||||
input logic [3:0] HPROT,
|
||||
input logic [1:0] HTRANS,
|
||||
input logic HMASTLOCK,
|
||||
input logic [`AHBW-1:0] HRDATAEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
output logic [`AHBW-1:0] HRDATA,
|
||||
output logic HREADY, HRESP,
|
||||
output logic HSELEXT,
|
||||
// peripheral pins
|
||||
output logic MTimerInt, MSwInt, // Timer and software interrupts from CLINT
|
||||
output logic MExtInt, SExtInt, // External interrupts from PLIC
|
||||
output logic [63:0] MTIME_CLINT, // MTIME, from CLINT
|
||||
input logic [31:0] GPIOIN, // GPIO pin input value
|
||||
output logic [31:0] GPIOOUT, GPIOEN, // GPIO pin output value and enable
|
||||
input logic UARTSin, // UART serial input
|
||||
output logic UARTSout, // UART serial output
|
||||
output logic SDCCmdOut, // SD Card command output
|
||||
output logic SDCCmdOE, // SD Card command output enable
|
||||
input logic SDCCmdIn, // SD Card command input
|
||||
input logic [3:0] SDCDatIn, // SD Card data input
|
||||
output logic SDCCLK // SD Card clock
|
||||
);
|
||||
|
||||
logic [`XLEN-1:0] HREADRam, HREADSDC;
|
||||
logic [`XLEN-1:0] HREADRam, HREADSDC;
|
||||
|
||||
logic [10:0] HSELRegions;
|
||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD;
|
||||
logic HRESPRam, HRESPSDC;
|
||||
logic HREADYRam, HRESPSDCD;
|
||||
logic [`XLEN-1:0] HREADBootRom;
|
||||
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
||||
logic HSELNoneD;
|
||||
logic UARTIntr,GPIOIntr;
|
||||
logic SDCIntM;
|
||||
logic [10:0] HSELRegions;
|
||||
logic HSELDTIM, HSELIROM, HSELRam, HSELCLINT, HSELPLIC, HSELGPIO, HSELUART, HSELSDC;
|
||||
logic HSELDTIMD, HSELIROMD, HSELEXTD, HSELRamD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD;
|
||||
logic HRESPRam, HRESPSDC;
|
||||
logic HREADYRam, HRESPSDCD;
|
||||
logic [`XLEN-1:0] HREADBootRom;
|
||||
logic HSELBootRom, HSELBootRomD, HRESPBootRom, HREADYBootRom, HREADYSDC;
|
||||
logic HSELNoneD;
|
||||
logic UARTIntr,GPIOIntr;
|
||||
logic SDCIntM;
|
||||
|
||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||
logic [3:0] PSEL, PREADY;
|
||||
logic [31:0] PADDR;
|
||||
logic [`XLEN-1:0] PWDATA;
|
||||
logic [`XLEN/8-1:0] PSTRB;
|
||||
logic [3:0][`XLEN-1:0] PRDATA;
|
||||
logic [`XLEN-1:0] HREADBRIDGE;
|
||||
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
|
||||
logic PCLK, PRESETn, PWRITE, PENABLE;
|
||||
logic [3:0] PSEL, PREADY;
|
||||
logic [31:0] PADDR;
|
||||
logic [`XLEN-1:0] PWDATA;
|
||||
logic [`XLEN/8-1:0] PSTRB;
|
||||
logic [3:0][`XLEN-1:0] PRDATA;
|
||||
logic [`XLEN-1:0] HREADBRIDGE;
|
||||
logic HRESPBRIDGE, HREADYBRIDGE, HSELBRIDGE, HSELBRIDGED;
|
||||
|
||||
// Determine which region of physical memory (if any) is being accessed
|
||||
// Use a trimmed down portion of the PMA checker - only the address decoders
|
||||
@ -133,9 +133,9 @@ module uncore (
|
||||
gpio_apb gpio(
|
||||
.PCLK, .PRESETn, .PSEL(PSEL[0]), .PADDR(PADDR[7:0]), .PWDATA, .PSTRB, .PWRITE, .PENABLE,
|
||||
.PRDATA(PRDATA[0]), .PREADY(PREADY[0]),
|
||||
.iof0(), .iof1(), .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn, .GPIOIntr);
|
||||
.iof0(), .iof1(), .GPIOIN, .GPIOOUT, .GPIOEN, .GPIOIntr);
|
||||
end else begin : gpio
|
||||
assign GPIOPinsOut = 0; assign GPIOPinsEn = 0; assign GPIOIntr = 0;
|
||||
assign GPIOOUT = 0; assign GPIOEN = 0; assign GPIOIntr = 0;
|
||||
end
|
||||
if (`UART_SUPPORTED == 1) begin : uart
|
||||
uart_apb uart(
|
||||
@ -153,7 +153,7 @@ module uncore (
|
||||
// sdc interface
|
||||
.SDCCmdOut, .SDCCmdIn, .SDCCmdOE, .SDCDatIn, .SDCCLK,
|
||||
// interrupt to PLIC
|
||||
.SDCIntM
|
||||
.SDCIntM
|
||||
);
|
||||
end else begin : sdc
|
||||
assign SDCCLK = 0;
|
||||
@ -163,22 +163,22 @@ module uncore (
|
||||
|
||||
// AHB Read Multiplexer
|
||||
assign HRDATA = ({`XLEN{HSELRamD}} & HREADRam) |
|
||||
({`XLEN{HSELEXTD}} & HRDATAEXT) |
|
||||
({`XLEN{HSELEXTD}} & HRDATAEXT) |
|
||||
({`XLEN{HSELBRIDGED}} & HREADBRIDGE) |
|
||||
({`XLEN{HSELBootRomD}} & HREADBootRom) |
|
||||
({`XLEN{HSELSDCD}} & HREADSDC);
|
||||
|
||||
assign HRESP = HSELRamD & HRESPRam |
|
||||
HSELEXTD & HRESPEXT |
|
||||
HSELEXTD & HRESPEXT |
|
||||
HSELBRIDGE & HRESPBRIDGE |
|
||||
HSELBootRomD & HRESPBootRom |
|
||||
HSELSDC & HRESPSDC;
|
||||
HSELSDC & HRESPSDC;
|
||||
|
||||
assign HREADY = HSELRamD & HREADYRam |
|
||||
HSELEXTD & HREADYEXT |
|
||||
HSELEXTD & HREADYEXT |
|
||||
HSELBRIDGED & HREADYBRIDGE |
|
||||
HSELBootRomD & HREADYBootRom |
|
||||
HSELSDCD & HREADYSDC |
|
||||
HSELSDCD & HREADYSDC |
|
||||
HSELNoneD; // don't lock up the bus if no region is being accessed
|
||||
|
||||
// Address Decoder Delay (figure 4-2 in spec)
|
||||
|
@ -35,12 +35,12 @@ module wallypipelinedcore (
|
||||
input logic MTimerInt, MExtInt, SExtInt, MSwInt,
|
||||
input logic [63:0] MTIME_CLINT,
|
||||
// Bus Interface
|
||||
input logic [`AHBW-1:0] HRDATA,
|
||||
input logic [`AHBW-1:0] HRDATA,
|
||||
input logic HREADY, HRESP,
|
||||
output logic HCLK, HRESETn,
|
||||
output logic [`PA_BITS-1:0] HADDR,
|
||||
output logic [`AHBW-1:0] HWDATA,
|
||||
output logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic [`PA_BITS-1:0] HADDR,
|
||||
output logic [`AHBW-1:0] HWDATA,
|
||||
output logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic HWRITE,
|
||||
output logic [2:0] HSIZE,
|
||||
output logic [2:0] HBURST,
|
||||
@ -58,17 +58,17 @@ module wallypipelinedcore (
|
||||
logic IntDivE, W64E;
|
||||
logic CSRReadM, CSRWriteM, PrivilegedM;
|
||||
logic [1:0] AtomicM;
|
||||
logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE;
|
||||
logic [`XLEN-1:0] SrcAM;
|
||||
logic [`XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE;
|
||||
logic [`XLEN-1:0] SrcAM;
|
||||
logic [2:0] Funct3E;
|
||||
logic [31:0] InstrD;
|
||||
logic [31:0] InstrM, InstrOrigM;
|
||||
logic [`XLEN-1:0] PCSpillF, PCE, PCLinkE;
|
||||
logic [`XLEN-1:0] PCM;
|
||||
logic [`XLEN-1:0] CSRReadValW, MDUResultW;
|
||||
logic [`XLEN-1:0] UnalignedPCNextF, PC2NextF;
|
||||
logic [1:0] MemRWM;
|
||||
logic InstrValidD, InstrValidE, InstrValidM;
|
||||
logic [31:0] InstrM, InstrOrigM;
|
||||
logic [`XLEN-1:0] PCSpillF, PCE, PCLinkE;
|
||||
logic [`XLEN-1:0] PCM;
|
||||
logic [`XLEN-1:0] CSRReadValW, MDUResultW;
|
||||
logic [`XLEN-1:0] UnalignedPCNextF, PC2NextF;
|
||||
logic [1:0] MemRWM;
|
||||
logic InstrValidD, InstrValidE, InstrValidM;
|
||||
logic InstrMisalignedFaultM;
|
||||
logic IllegalBaseInstrD, IllegalFPUInstrD, IllegalIEUFPUInstrD;
|
||||
logic InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM;
|
||||
@ -86,8 +86,8 @@ module wallypipelinedcore (
|
||||
logic [4:0] RdE, RdM, RdW;
|
||||
logic FPUStallD;
|
||||
logic FWriteIntE;
|
||||
logic [`FLEN-1:0] FWriteDataM;
|
||||
logic [`XLEN-1:0] FIntResM;
|
||||
logic [`FLEN-1:0] FWriteDataM;
|
||||
logic [`XLEN-1:0] FIntResM;
|
||||
logic [`XLEN-1:0] FCvtIntResW;
|
||||
logic FCvtIntW;
|
||||
logic FDivBusyE;
|
||||
@ -95,22 +95,22 @@ module wallypipelinedcore (
|
||||
logic FCvtIntStallD;
|
||||
logic FpLoadStoreM;
|
||||
logic [4:0] SetFflagsM;
|
||||
logic [`XLEN-1:0] FIntDivResultW;
|
||||
logic [`XLEN-1:0] FIntDivResultW;
|
||||
|
||||
// memory management unit signals
|
||||
logic ITLBWriteF;
|
||||
logic ITLBMissF;
|
||||
logic [`XLEN-1:0] SATP_REGW;
|
||||
logic [`XLEN-1:0] SATP_REGW;
|
||||
logic STATUS_MXR, STATUS_SUM, STATUS_MPRV;
|
||||
logic [1:0] STATUS_MPP, STATUS_FS;
|
||||
logic [1:0] STATUS_MPP, STATUS_FS;
|
||||
logic [1:0] PrivilegeModeW;
|
||||
logic [`XLEN-1:0] PTE;
|
||||
logic [`XLEN-1:0] PTE;
|
||||
logic [1:0] PageType;
|
||||
logic sfencevmaM, WFIStallM;
|
||||
logic SelHPTW;
|
||||
|
||||
// PMA checker signals
|
||||
var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0];
|
||||
var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0];
|
||||
var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0];
|
||||
|
||||
// IMem stalls
|
||||
@ -119,14 +119,14 @@ module wallypipelinedcore (
|
||||
|
||||
// cpu lsu interface
|
||||
logic [2:0] Funct3M;
|
||||
logic [`XLEN-1:0] IEUAdrE;
|
||||
logic [`XLEN-1:0] WriteDataM;
|
||||
logic [`XLEN-1:0] IEUAdrM;
|
||||
logic [`LLEN-1:0] ReadDataW;
|
||||
logic [`XLEN-1:0] IEUAdrE;
|
||||
logic [`XLEN-1:0] WriteDataM;
|
||||
logic [`XLEN-1:0] IEUAdrM;
|
||||
logic [`LLEN-1:0] ReadDataW;
|
||||
logic CommittedM;
|
||||
|
||||
// AHB ifu interface
|
||||
logic [`PA_BITS-1:0] IFUHADDR;
|
||||
logic [`PA_BITS-1:0] IFUHADDR;
|
||||
logic [2:0] IFUHBURST;
|
||||
logic [1:0] IFUHTRANS;
|
||||
logic [2:0] IFUHSIZE;
|
||||
@ -134,9 +134,9 @@ module wallypipelinedcore (
|
||||
logic IFUHREADY;
|
||||
|
||||
// AHB LSU interface
|
||||
logic [`PA_BITS-1:0] LSUHADDR;
|
||||
logic [`XLEN-1:0] LSUHWDATA;
|
||||
logic [`XLEN/8-1:0] LSUHWSTRB;
|
||||
logic [`PA_BITS-1:0] LSUHADDR;
|
||||
logic [`XLEN-1:0] LSUHWDATA;
|
||||
logic [`XLEN/8-1:0] LSUHWSTRB;
|
||||
logic LSUHWRITE;
|
||||
logic LSUHREADY;
|
||||
|
||||
@ -160,8 +160,8 @@ module wallypipelinedcore (
|
||||
logic BigEndianM;
|
||||
logic FCvtIntE;
|
||||
logic CommittedF;
|
||||
logic BranchD, BranchE, JumpD, JumpE;
|
||||
logic DCacheStallM, ICacheStallF;
|
||||
logic BranchD, BranchE, JumpD, JumpE;
|
||||
logic DCacheStallM, ICacheStallF;
|
||||
|
||||
// instruction fetch unit: PC, branch prediction, instruction cache
|
||||
ifu ifu(.clk, .reset,
|
||||
@ -247,20 +247,10 @@ module wallypipelinedcore (
|
||||
ebu ebu(// IFU connections
|
||||
.clk, .reset,
|
||||
// IFU interface
|
||||
.IFUHADDR,
|
||||
.IFUHBURST,
|
||||
.IFUHTRANS,
|
||||
.IFUHREADY,
|
||||
.IFUHSIZE,
|
||||
.IFUHADDR, .IFUHBURST, .IFUHTRANS, .IFUHREADY, .IFUHSIZE,
|
||||
// LSU interface
|
||||
.LSUHADDR,
|
||||
.LSUHWDATA,
|
||||
.LSUHWSTRB,
|
||||
.LSUHSIZE,
|
||||
.LSUHBURST,
|
||||
.LSUHTRANS,
|
||||
.LSUHWRITE,
|
||||
.LSUHREADY,
|
||||
.LSUHADDR, .LSUHWDATA, .LSUHWSTRB, .LSUHSIZE, .LSUHBURST,
|
||||
.LSUHTRANS, .LSUHWRITE, .LSUHREADY,
|
||||
// BUS interface
|
||||
.HREADY, .HRESP, .HCLK, .HRESETn,
|
||||
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST,
|
||||
|
@ -30,43 +30,43 @@
|
||||
`include "wally-config.vh"
|
||||
|
||||
module wallypipelinedsoc (
|
||||
input logic clk,
|
||||
input logic clk,
|
||||
input logic reset_ext, // external asynchronous reset pin
|
||||
output logic reset, // reset synchronized to clk to prevent races on release
|
||||
// AHB Interface
|
||||
input logic [`AHBW-1:0] HRDATAEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
output logic HSELEXT,
|
||||
input logic [`AHBW-1:0] HRDATAEXT,
|
||||
input logic HREADYEXT, HRESPEXT,
|
||||
output logic HSELEXT,
|
||||
// outputs to external memory, shared with uncore memory
|
||||
output logic HCLK, HRESETn,
|
||||
output logic [`PA_BITS-1:0] HADDR,
|
||||
output logic [`AHBW-1:0] HWDATA,
|
||||
output logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic HWRITE,
|
||||
output logic [2:0] HSIZE,
|
||||
output logic [2:0] HBURST,
|
||||
output logic [3:0] HPROT,
|
||||
output logic [1:0] HTRANS,
|
||||
output logic HMASTLOCK,
|
||||
output logic HREADY,
|
||||
output logic HCLK, HRESETn,
|
||||
output logic [`PA_BITS-1:0] HADDR,
|
||||
output logic [`AHBW-1:0] HWDATA,
|
||||
output logic [`XLEN/8-1:0] HWSTRB,
|
||||
output logic HWRITE,
|
||||
output logic [2:0] HSIZE,
|
||||
output logic [2:0] HBURST,
|
||||
output logic [3:0] HPROT,
|
||||
output logic [1:0] HTRANS,
|
||||
output logic HMASTLOCK,
|
||||
output logic HREADY,
|
||||
// I/O Interface
|
||||
input logic TIMECLK, // optional for CLINT MTIME counter
|
||||
input logic [31:0] GPIOPinsIn, // inputs from GPIO
|
||||
output logic [31:0] GPIOPinsOut, // output values for GPIO
|
||||
output logic [31:0] GPIOPinsEn, // output enables for GPIO
|
||||
input logic UARTSin, // UART serial data input
|
||||
output logic UARTSout, // UART serial data output
|
||||
input logic SDCCmdIn, // SDC Command input
|
||||
output logic SDCCmdOut, // SDC Command output
|
||||
output logic SDCCmdOE, // SDC Command output enable
|
||||
input logic [3:0] SDCDatIn, // SDC data input
|
||||
output logic SDCCLK // SDC clock
|
||||
input logic [31:0] GPIOIN, // inputs from GPIO
|
||||
output logic [31:0] GPIOOUT, // output values for GPIO
|
||||
output logic [31:0] GPIOEN, // output enables for GPIO
|
||||
input logic UARTSin, // UART serial data input
|
||||
output logic UARTSout, // UART serial data output
|
||||
input logic SDCCmdIn, // SDC Command input
|
||||
output logic SDCCmdOut, // SDC Command output
|
||||
output logic SDCCmdOE, // SDC Command output enable
|
||||
input logic [3:0] SDCDatIn, // SDC data input
|
||||
output logic SDCCLK // SDC clock
|
||||
);
|
||||
|
||||
// Uncore signals
|
||||
logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore
|
||||
logic [`AHBW-1:0] HRDATA; // from AHB mux in uncore
|
||||
logic HRESP; // response from AHB
|
||||
logic MTimerInt, MSwInt; // timer and software interrupts from CLINT
|
||||
logic MTimerInt, MSwInt;// timer and software interrupts from CLINT
|
||||
logic [63:0] MTIME_CLINT; // from CLINT to CSRs
|
||||
logic MExtInt,SExtInt; // from PLIC
|
||||
|
||||
@ -85,9 +85,9 @@ module wallypipelinedsoc (
|
||||
uncore uncore(.HCLK, .HRESETn, .TIMECLK,
|
||||
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HRDATAEXT,
|
||||
.HREADYEXT, .HRESPEXT, .HRDATA, .HREADY, .HRESP, .HSELEXT,
|
||||
.MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOPinsIn, .GPIOPinsOut, .GPIOPinsEn, .UARTSin,
|
||||
.UARTSout, .MTIME_CLINT,
|
||||
.SDCCmdOut, .SDCCmdOE, .SDCCmdIn, .SDCDatIn, .SDCCLK);
|
||||
.MTimerInt, .MSwInt, .MExtInt, .SExtInt, .GPIOIN, .GPIOOUT, .GPIOEN, .UARTSin,
|
||||
.UARTSout, .MTIME_CLINT,
|
||||
.SDCCmdOut, .SDCCmdOE, .SDCCmdIn, .SDCDatIn, .SDCCLK);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -90,6 +90,7 @@ module wallyTracer(rvviTrace rvvi);
|
||||
assign STATUS_UXL = testbench.dut.core.priv.priv.csr.csrsr.STATUS_UXL;
|
||||
|
||||
logic valid;
|
||||
int csrid;
|
||||
|
||||
always_comb begin
|
||||
// Since we are detected the CSR change by comparing the old value we need to
|
||||
@ -116,7 +117,6 @@ module wallyTracer(rvviTrace rvvi);
|
||||
pmp |= testbench.dut.core.priv.priv.csr.csrm.PMPCFG_ARRAY_REGW[i8+7] << 56;
|
||||
|
||||
csrid = 12'h3A0 + i4;
|
||||
//if (CSRArray[csrid] != pmp) $display("Info: %m pmpcfg%0d [%03X] %016X -> %016X", i4, csrid, CSRArray[csrid], pmp);
|
||||
CSRArray[csrid] = pmp;
|
||||
end
|
||||
|
||||
@ -125,7 +125,6 @@ module wallyTracer(rvviTrace rvvi);
|
||||
pmp = testbench.dut.core.priv.priv.csr.csrm.PMPADDR_ARRAY_REGW[i];
|
||||
|
||||
csrid = 12'h3B0 + i;
|
||||
//if (CSRArray[csrid] != pmp) $display("Info: %m Change pmpaddr%0d [%03X] %016X -> %016X", i, csrid, CSRArray[csrid], pmp);
|
||||
CSRArray[csrid] = pmp;
|
||||
end
|
||||
|
||||
@ -167,7 +166,17 @@ module wallyTracer(rvviTrace rvvi);
|
||||
CSRArray[12'h001] = testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW;
|
||||
CSRArray[12'h002] = testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW;
|
||||
CSRArray[12'h003] = {testbench.dut.core.priv.priv.csr.csru.csru.FRM_REGW, testbench.dut.core.priv.priv.csr.csru.csru.FFLAGS_REGW};
|
||||
|
||||
end else begin // hold the old value if the pipeline is stalled.
|
||||
|
||||
// PMP CFG 3A0 to 3AF
|
||||
for(csrid='h3A0; csrid<='h3AF; csrid++)
|
||||
CSRArray[csrid] = CSRArrayOld[csrid];
|
||||
|
||||
// PMP ADDR 3B0 to 3EF
|
||||
for(csrid='h3B0; csrid<='h3EF; csrid++)
|
||||
CSRArray[csrid] = CSRArrayOld[csrid];
|
||||
|
||||
CSRArray[12'h300] = CSRArrayOld[12'h300];
|
||||
CSRArray[12'h310] = CSRArrayOld[12'h310];
|
||||
CSRArray[12'h305] = CSRArrayOld[12'h305];
|
||||
@ -209,7 +218,7 @@ module wallyTracer(rvviTrace rvvi);
|
||||
end
|
||||
end
|
||||
|
||||
genvar index;
|
||||
genvar index;
|
||||
assign rf[0] = '0;
|
||||
for(index = 1; index < NUMREGS; index += 1)
|
||||
assign rf[index] = testbench.dut.core.ieu.dp.regf.rf[index];
|
||||
@ -286,27 +295,177 @@ module wallyTracer(rvviTrace rvvi);
|
||||
// record previous csr value.
|
||||
integer index4;
|
||||
always_ff @(posedge clk) begin
|
||||
for (index4 = 0; index4 < `NUM_CSRS; index4 += 1) begin
|
||||
// IMPERAS
|
||||
//CSR_W[index4] = (CSRArrayOld[index4] != CSRArray[index4]) ? 1 : 0;
|
||||
CSRArrayOld[index4] = CSRArray[index4];
|
||||
end
|
||||
CSRArrayOld[12'h300] = CSRArray[12'h300];
|
||||
CSRArrayOld[12'h310] = CSRArray[12'h310];
|
||||
CSRArrayOld[12'h305] = CSRArray[12'h305];
|
||||
CSRArrayOld[12'h341] = CSRArray[12'h341];
|
||||
CSRArrayOld[12'h306] = CSRArray[12'h306];
|
||||
CSRArrayOld[12'h320] = CSRArray[12'h320];
|
||||
CSRArrayOld[12'h302] = CSRArray[12'h302];
|
||||
CSRArrayOld[12'h303] = CSRArray[12'h303];
|
||||
CSRArrayOld[12'h344] = CSRArray[12'h344];
|
||||
CSRArrayOld[12'h304] = CSRArray[12'h304];
|
||||
CSRArrayOld[12'h301] = CSRArray[12'h301];
|
||||
CSRArrayOld[12'hF14] = CSRArray[12'hF14];
|
||||
CSRArrayOld[12'h340] = CSRArray[12'h340];
|
||||
CSRArrayOld[12'h342] = CSRArray[12'h342];
|
||||
CSRArrayOld[12'h343] = CSRArray[12'h343];
|
||||
CSRArrayOld[12'hF11] = CSRArray[12'hF11];
|
||||
CSRArrayOld[12'hF12] = CSRArray[12'hF12];
|
||||
CSRArrayOld[12'hF13] = CSRArray[12'hF13];
|
||||
CSRArrayOld[12'hF15] = CSRArray[12'hF15];
|
||||
CSRArrayOld[12'h34A] = CSRArray[12'h34A];
|
||||
// MCYCLE and MINSTRET
|
||||
CSRArrayOld[12'hB00] = CSRArray[12'hB00];
|
||||
CSRArrayOld[12'hB02] = CSRArray[12'hB02];
|
||||
// supervisor CSRs
|
||||
CSRArrayOld[12'h100] = CSRArray[12'h100];
|
||||
CSRArrayOld[12'h104] = CSRArray[12'h104];
|
||||
CSRArrayOld[12'h105] = CSRArray[12'h105];
|
||||
CSRArrayOld[12'h141] = CSRArray[12'h141];
|
||||
CSRArrayOld[12'h106] = CSRArray[12'h106];
|
||||
CSRArrayOld[12'h180] = CSRArray[12'h180];
|
||||
CSRArrayOld[12'h140] = CSRArray[12'h140];
|
||||
CSRArrayOld[12'h143] = CSRArray[12'h143];
|
||||
CSRArrayOld[12'h142] = CSRArray[12'h142];
|
||||
CSRArrayOld[12'h144] = CSRArray[12'h144];
|
||||
// user CSRs
|
||||
CSRArrayOld[12'h001] = CSRArray[12'h001];
|
||||
CSRArrayOld[12'h002] = CSRArray[12'h002];
|
||||
CSRArrayOld[12'h003] = CSRArray[12'h003];
|
||||
|
||||
// PMP CFG 3A0 to 3AF
|
||||
for(index4='h3A0; index4<='h3AF; index4++)
|
||||
CSRArrayOld[index4] = CSRArray[index4];
|
||||
|
||||
// PMP ADDR 3B0 to 3EF
|
||||
for(index4='h3B0; index4<='h3EF; index4++)
|
||||
CSRArrayOld[index4] = CSRArray[index4];
|
||||
end
|
||||
|
||||
// check for csr value change.
|
||||
genvar index5;
|
||||
for(index5 = 0; index5 < `NUM_CSRS; index5 += 1) begin
|
||||
// CSR_W should only indicate the change when the Writeback stage is not stalled and valid.
|
||||
assign #2 CSR_W[index5] = (CSRArrayOld[index5] != CSRArray[index5]) ? 1 : 0;
|
||||
assign rvvi.csr_wb[0][0][index5] = CSR_W[index5];
|
||||
assign rvvi.csr[0][0][index5] = CSRArray[index5];
|
||||
assign #2 CSR_W[12'h300] = (CSRArrayOld[12'h300] != CSRArray[12'h300]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h310] = (CSRArrayOld[12'h310] != CSRArray[12'h310]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h305] = (CSRArrayOld[12'h305] != CSRArray[12'h305]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h341] = (CSRArrayOld[12'h341] != CSRArray[12'h341]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h306] = (CSRArrayOld[12'h306] != CSRArray[12'h306]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h320] = (CSRArrayOld[12'h320] != CSRArray[12'h320]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h302] = (CSRArrayOld[12'h302] != CSRArray[12'h302]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h303] = (CSRArrayOld[12'h303] != CSRArray[12'h303]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h344] = (CSRArrayOld[12'h344] != CSRArray[12'h344]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h304] = (CSRArrayOld[12'h304] != CSRArray[12'h304]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h301] = (CSRArrayOld[12'h301] != CSRArray[12'h301]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'hF14] = (CSRArrayOld[12'hF14] != CSRArray[12'hF14]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h340] = (CSRArrayOld[12'h340] != CSRArray[12'h340]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h342] = (CSRArrayOld[12'h342] != CSRArray[12'h342]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h343] = (CSRArrayOld[12'h343] != CSRArray[12'h343]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'hF11] = (CSRArrayOld[12'hF11] != CSRArray[12'hF11]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'hF12] = (CSRArrayOld[12'hF12] != CSRArray[12'hF12]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'hF13] = (CSRArrayOld[12'hF13] != CSRArray[12'hF13]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'hF15] = (CSRArrayOld[12'hF15] != CSRArray[12'hF15]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h34A] = (CSRArrayOld[12'h34A] != CSRArray[12'h34A]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'hB00] = (CSRArrayOld[12'hB00] != CSRArray[12'hB00]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'hB02] = (CSRArrayOld[12'hB02] != CSRArray[12'hB02]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h100] = (CSRArrayOld[12'h100] != CSRArray[12'h100]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h104] = (CSRArrayOld[12'h104] != CSRArray[12'h104]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h105] = (CSRArrayOld[12'h105] != CSRArray[12'h105]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h141] = (CSRArrayOld[12'h141] != CSRArray[12'h141]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h106] = (CSRArrayOld[12'h106] != CSRArray[12'h106]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h180] = (CSRArrayOld[12'h180] != CSRArray[12'h180]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h140] = (CSRArrayOld[12'h140] != CSRArray[12'h140]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h143] = (CSRArrayOld[12'h143] != CSRArray[12'h143]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h142] = (CSRArrayOld[12'h142] != CSRArray[12'h142]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h144] = (CSRArrayOld[12'h144] != CSRArray[12'h144]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h001] = (CSRArrayOld[12'h001] != CSRArray[12'h001]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h002] = (CSRArrayOld[12'h002] != CSRArray[12'h002]) ? 1 : 0;
|
||||
assign #2 CSR_W[12'h003] = (CSRArrayOld[12'h003] != CSRArray[12'h003]) ? 1 : 0;
|
||||
|
||||
assign rvvi.csr_wb[0][0][12'h300] = CSR_W[12'h300];
|
||||
assign rvvi.csr_wb[0][0][12'h310] = CSR_W[12'h310];
|
||||
assign rvvi.csr_wb[0][0][12'h305] = CSR_W[12'h305];
|
||||
assign rvvi.csr_wb[0][0][12'h341] = CSR_W[12'h341];
|
||||
assign rvvi.csr_wb[0][0][12'h306] = CSR_W[12'h306];
|
||||
assign rvvi.csr_wb[0][0][12'h320] = CSR_W[12'h320];
|
||||
assign rvvi.csr_wb[0][0][12'h302] = CSR_W[12'h302];
|
||||
assign rvvi.csr_wb[0][0][12'h303] = CSR_W[12'h303];
|
||||
assign rvvi.csr_wb[0][0][12'h344] = CSR_W[12'h344];
|
||||
assign rvvi.csr_wb[0][0][12'h304] = CSR_W[12'h304];
|
||||
assign rvvi.csr_wb[0][0][12'h301] = CSR_W[12'h301];
|
||||
assign rvvi.csr_wb[0][0][12'hF14] = CSR_W[12'hF14];
|
||||
assign rvvi.csr_wb[0][0][12'h340] = CSR_W[12'h340];
|
||||
assign rvvi.csr_wb[0][0][12'h342] = CSR_W[12'h342];
|
||||
assign rvvi.csr_wb[0][0][12'h343] = CSR_W[12'h343];
|
||||
assign rvvi.csr_wb[0][0][12'hF11] = CSR_W[12'hF11];
|
||||
assign rvvi.csr_wb[0][0][12'hF12] = CSR_W[12'hF12];
|
||||
assign rvvi.csr_wb[0][0][12'hF13] = CSR_W[12'hF13];
|
||||
assign rvvi.csr_wb[0][0][12'hF15] = CSR_W[12'hF15];
|
||||
assign rvvi.csr_wb[0][0][12'h34A] = CSR_W[12'h34A];
|
||||
assign rvvi.csr_wb[0][0][12'hB00] = CSR_W[12'hB00];
|
||||
assign rvvi.csr_wb[0][0][12'hB02] = CSR_W[12'hB02];
|
||||
assign rvvi.csr_wb[0][0][12'h100] = CSR_W[12'h100];
|
||||
assign rvvi.csr_wb[0][0][12'h104] = CSR_W[12'h104];
|
||||
assign rvvi.csr_wb[0][0][12'h105] = CSR_W[12'h105];
|
||||
assign rvvi.csr_wb[0][0][12'h141] = CSR_W[12'h141];
|
||||
assign rvvi.csr_wb[0][0][12'h106] = CSR_W[12'h106];
|
||||
assign rvvi.csr_wb[0][0][12'h180] = CSR_W[12'h180];
|
||||
assign rvvi.csr_wb[0][0][12'h140] = CSR_W[12'h140];
|
||||
assign rvvi.csr_wb[0][0][12'h143] = CSR_W[12'h143];
|
||||
assign rvvi.csr_wb[0][0][12'h142] = CSR_W[12'h142];
|
||||
assign rvvi.csr_wb[0][0][12'h144] = CSR_W[12'h144];
|
||||
assign rvvi.csr_wb[0][0][12'h001] = CSR_W[12'h001];
|
||||
assign rvvi.csr_wb[0][0][12'h002] = CSR_W[12'h002];
|
||||
assign rvvi.csr_wb[0][0][12'h003] = CSR_W[12'h003];
|
||||
|
||||
assign rvvi.csr[0][0][12'h300] = CSRArray[12'h300];
|
||||
assign rvvi.csr[0][0][12'h310] = CSRArray[12'h310];
|
||||
assign rvvi.csr[0][0][12'h305] = CSRArray[12'h305];
|
||||
assign rvvi.csr[0][0][12'h341] = CSRArray[12'h341];
|
||||
assign rvvi.csr[0][0][12'h306] = CSRArray[12'h306];
|
||||
assign rvvi.csr[0][0][12'h320] = CSRArray[12'h320];
|
||||
assign rvvi.csr[0][0][12'h302] = CSRArray[12'h302];
|
||||
assign rvvi.csr[0][0][12'h303] = CSRArray[12'h303];
|
||||
assign rvvi.csr[0][0][12'h344] = CSRArray[12'h344];
|
||||
assign rvvi.csr[0][0][12'h304] = CSRArray[12'h304];
|
||||
assign rvvi.csr[0][0][12'h301] = CSRArray[12'h301];
|
||||
assign rvvi.csr[0][0][12'hF14] = CSRArray[12'hF14];
|
||||
assign rvvi.csr[0][0][12'h340] = CSRArray[12'h340];
|
||||
assign rvvi.csr[0][0][12'h342] = CSRArray[12'h342];
|
||||
assign rvvi.csr[0][0][12'h343] = CSRArray[12'h343];
|
||||
assign rvvi.csr[0][0][12'hF11] = CSRArray[12'hF11];
|
||||
assign rvvi.csr[0][0][12'hF12] = CSRArray[12'hF12];
|
||||
assign rvvi.csr[0][0][12'hF13] = CSRArray[12'hF13];
|
||||
assign rvvi.csr[0][0][12'hF15] = CSRArray[12'hF15];
|
||||
assign rvvi.csr[0][0][12'h34A] = CSRArray[12'h34A];
|
||||
assign rvvi.csr[0][0][12'hB00] = CSRArray[12'hB00];
|
||||
assign rvvi.csr[0][0][12'hB02] = CSRArray[12'hB02];
|
||||
assign rvvi.csr[0][0][12'h100] = CSRArray[12'h100];
|
||||
assign rvvi.csr[0][0][12'h104] = CSRArray[12'h104];
|
||||
assign rvvi.csr[0][0][12'h105] = CSRArray[12'h105];
|
||||
assign rvvi.csr[0][0][12'h141] = CSRArray[12'h141];
|
||||
assign rvvi.csr[0][0][12'h106] = CSRArray[12'h106];
|
||||
assign rvvi.csr[0][0][12'h180] = CSRArray[12'h180];
|
||||
assign rvvi.csr[0][0][12'h140] = CSRArray[12'h140];
|
||||
assign rvvi.csr[0][0][12'h143] = CSRArray[12'h143];
|
||||
assign rvvi.csr[0][0][12'h142] = CSRArray[12'h142];
|
||||
assign rvvi.csr[0][0][12'h144] = CSRArray[12'h144];
|
||||
assign rvvi.csr[0][0][12'h001] = CSRArray[12'h001];
|
||||
assign rvvi.csr[0][0][12'h002] = CSRArray[12'h002];
|
||||
assign rvvi.csr[0][0][12'h003] = CSRArray[12'h003];
|
||||
|
||||
// PMP CFG 3A0 to 3AF
|
||||
for(index='h3A0; index<='h3AF; index++) begin
|
||||
assign #2 CSR_W[index] = (CSRArrayOld[index] != CSRArray[index]) ? 1 : 0;
|
||||
assign rvvi.csr_wb[0][0][index] = CSR_W[index];
|
||||
assign rvvi.csr[0][0][index] = CSRArray[index];
|
||||
end
|
||||
|
||||
// always @rvvi.clk $display("%t @rvvi.clk=%X", $time, rvvi.clk);
|
||||
// always @rvvi.csr[0][0]['h300] $display("%t rvvi.csr[0][0]['h300]=%X", $time, rvvi.csr[0][0]['h300]);
|
||||
// always @rvvi.csr_wb[0][0]['h300] $display("%t rvvi.csr_wb[0][0]['h300]=%X", $time, rvvi.csr_wb[0][0]['h300]);
|
||||
// always @rvvi.valid[0][0] $display("%t rvvi.valid[0][0]=%X", $time, rvvi.valid[0][0]);
|
||||
|
||||
|
||||
// PMP ADDR 3B0 to 3EF
|
||||
for(index='h3B0; index<='h3EF; index++) begin
|
||||
assign #2 CSR_W[index] = (CSRArrayOld[index] != CSRArray[index]) ? 1 : 0;
|
||||
assign rvvi.csr_wb[0][0][index] = CSR_W[index];
|
||||
assign rvvi.csr[0][0][index] = CSRArray[index];
|
||||
end
|
||||
|
||||
// *** implementation only cancel? so sc does not clear?
|
||||
assign rvvi.lrsc_cancel[0][0] = '0;
|
||||
|
||||
|
@ -702,7 +702,7 @@ module testbenchfp;
|
||||
|
||||
if (TEST === "cvtfp" | TEST === "cvtint" | TEST === "all") begin : fcvt
|
||||
fcvt fcvt (.Xs(Xs), .Xe(Xe), .Xm(Xm), .Int(SrcA), .ToInt(WriteIntVal),
|
||||
.XZero(XZero), .XSubnorm(XSubnorm), .OpCtrl(OpCtrlVal), .IntZero,
|
||||
.XZero(XZero), .OpCtrl(OpCtrlVal), .IntZero,
|
||||
.Fmt(ModFmt), .Ce(CvtCalcExpE), .ShiftAmt(CvtShiftAmtE), .ResSubnormUf(CvtResSubnormUfE), .Cs(CvtResSgnE), .LzcIn(CvtLzcInE));
|
||||
end
|
||||
|
||||
|
1030
testbench/testbench-linux-imperas.sv
Normal file
1030
testbench/testbench-linux-imperas.sv
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user