URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 55 to Rev 56
- ↔ Reverse comparison
Rev 55 → Rev 56
/neorv32/trunk/boards/arty-a7-35-test-setup/.gitignore
0,0 → 1,3
vivado* |
.Xil |
work/* |
/neorv32/trunk/boards/arty-a7-35-test-setup/README.md
0,0 → 1,47
# NEORV32 Test Setup for the Digilent Arty A7-35 FPGA Board |
|
This setup provides a very simple script-based "demo setup" that allows to check out the NEORV32 processor on the Digilent Arty A7-35 board. |
It uses the simplified [`neorv32_test_setup.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) top entity, which is a wrapper for the actual processor |
top entity that provides a minimalistic interface (clock, reset, UART and 4 LEDs). |
|
* FPGA Board: :books: [Digilent Arty A7-35 FPGA Board](https://reference.digilentinc.com/reference/programmable-logic/arty-a7/reference-manual) |
* FPGA: Xilinx Artix-7 `XC7A35TICSG324-1L` |
* Toolchain: Xilinx Vivado (tested with Vivado 2019.2) |
|
|
### NEORV32 Configuration |
|
:information_source: See the top entity [`rtl/top_templates/neorv32_test_setup.vhd` ](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) for |
configuration and entity details and [`arty_a7_35_test_setup.xdc`](https://github.com/stnolting/neorv32/blob/master/boards/arty-a7-35-test-setup/arty_a7_35_test_setup.xdc) |
for the according FPGA pin mapping. |
|
* CPU: `rv32imcu_Zicsr` + 4 `HPM` (hardware performance monitors) |
* Memory: 16kB instruction memory (internal IMEM), 8kB data memory (internal DMEM), bootloader ROM |
* Peripherals: `GPIO`, `MTIME`, `UART0`, `WDT` |
* Tested with version [`1.5.3.3`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md) |
* Clock: 100MHz from on-board oscillator |
* Reset: Via dedicated on-board "RESET" button |
* GPIO output port `gpio_o` |
* bits 0..3 are connected to the green on-board LEDs (LD4 - LD7); LD4 is the bootloader status LED |
* bits 4..7 are (not actually used) connected to PMOD `JA` connector pins 1-4 |
* UART0 signals `uart0_txd_o` and `uart0_rxd_i` are connected to the on-board USB-UART chip |
|
|
## How To Run |
|
The `create_project.tcl` TCL script in this directory can be used to create a complete Vivado project. |
If not already available, this script will create a `work` folder in this directory. |
|
1. start Vivado (in GUI mode) |
2. click on "TCL Console" at the bottom |
3. use the console to naviagte to **this** folder: `cd .../neorv32/boards/arty-a7-35-test-setup` |
4. execute `source create_project.tcl` - this will create the actual Vivado project in `work` |
5. when the Vivado project has openend, click on "Run Implementation" |
6. when the implementation is done create a bitstrem by clicking "Generate Bitstream" (maybe a prompt will ask for that) |
7. open the "Hardware Manager" (maybe a prompt will ask for that) |
8. click on "Open target/Auto Connect" |
9. click on "Program device" and select `work/neorv32_test_setup.runs/impl_1/neorv32_test_setup.bit`; click "Program" |
10. use a serial terminal (like :earth_asia: [Tera Term](https://ttssh2.osdn.jp/index.html.en)) to connect to the USB-UART interface using the following configuration: |
19200 Baud, 8 data bits, 1 stop bit, no parity bits, no transmission / flow control protocol (raw bytes only), newline on `\r\n` (carriage return & newline) |
11. now you can communicate with the bootloader console and upload a new program. Check out the [example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) |
and see section "Let's Get It Started" of the :page_facing_up: [NEORV32 data sheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf) for further resources. |
/neorv32/trunk/boards/arty-a7-35-test-setup/arty_a7_35_test_setup.xdc
0,0 → 1,26
## This file is a general .xdc for the Arty A7-35 Rev. D |
|
## For default neorv32_test_setup.vhd top entity |
|
## Clock signal |
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk_i }]; #IO_L12P_T1_MRCC_35 Sch=gclk[100] |
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { clk_i }]; |
|
## LEDs |
set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[0] }]; #IO_L24N_T3_35 Sch=led[4] |
set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[1] }]; #IO_25_35 Sch=led[5] |
set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[2] }]; #IO_L24P_T3_A01_D17_14 Sch=led[6] |
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[3] }]; #IO_L24N_T3_A00_D16_14 Sch=led[7] |
|
## Pmod Header JA (unused GPIO outputs) |
set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[4] }]; #IO_0_15 Sch=ja[1] |
set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[5] }]; #IO_L4P_T0_15 Sch=ja[2] |
set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[6] }]; #IO_L4N_T0_15 Sch=ja[3] |
set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[7] }]; #IO_L6P_T0_15 Sch=ja[4] |
|
## USB-UART Interface |
set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart0_txd_o }]; #IO_L19N_T3_VREF_16 Sch=uart_rxd_out |
set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart0_rxd_i }]; #IO_L14N_T2_SRCC_16 Sch=uart_txd_in |
|
## Misc. |
set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { rstn_i }]; #IO_L16P_T2_35 Sch=ck_rst |
/neorv32/trunk/boards/arty-a7-35-test-setup/create_project.tcl
0,0 → 1,29
# create and clear output directory |
set outputdir work |
file mkdir $outputdir |
|
set files [glob -nocomplain "$outputdir/*"] |
if {[llength $files] != 0} { |
puts "deleting contents of $outputdir" |
file delete -force {*}[glob -directory $outputdir *]; # clear folder contents |
} else { |
puts "$outputdir is empty" |
} |
|
|
# create project |
create_project -part "xc7a35ticsg324-1L" "arty-a7-35-test-setup" $outputdir |
|
|
# add source files: core sources |
add_files [glob ./../../rtl/core/*.vhd] |
set_property library neorv32 [get_files [glob ./../../rtl/core/*.vhd]] |
|
# add source file: top entity |
add_files [glob ./../../rtl/top_templates/neorv32_test_setup.vhd] |
|
# add source files: simulation-only |
add_files -fileset sim_1 ./../../sim/neorv32_tb.vhd |
|
# add source files: constraints |
add_files -fileset constrs_1 [glob ./*.xdc] |
/neorv32/trunk/boards/de0-nano-test-setup/.gitignore
0,0 → 1,7
db |
incremental_db |
output_files |
*.qpf |
*.qsf |
*.qws |
*.vhd |
/neorv32/trunk/boards/de0-nano-test-setup/README.md
0,0 → 1,50
# NEORV32 Test Setup for the Terasic DE0-Nano FPGA Board |
|
This setup provides a very simple script-based "demo setup" that allows to check out the NEORV32 processor on the Terasic DE0-Nano board. |
It uses the simplified [`neorv32_test_setup.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) top entity, which is a wrapper for the actual processor |
top entity that provides a minimalistic interface (clock, reset, UART and 8 LEDs). |
|
* FPGA Board: :books: [Terasic DE0-Nano FPGA Board](https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=139&No=593) |
* FPGA: Intel Cyclone-IV `EP4CE22F17C6N` |
* Toolchain: Intel Quartus Prime (tested with Quartus Prime 20.1.0 - Lite Edition) |
|
|
### NEORV32 Configuration |
|
:information_source: See the top entity [`rtl/top_templates/neorv32_test_setup.vhd` ](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) for |
configuration and entity details and `create_project.tcl` for the according FPGA pin mapping. |
|
* CPU: `rv32imcu_Zicsr` + 4 `HPM` (hardware performance monitors) |
* Memory: 16kB instruction memory (internal IMEM), 8kB data memory (internal DMEM), bootloader ROM |
* Peripherals: `GPIO`, `MTIME`, `UART0`, `WDT` |
* Tested with version [`1.5.3.8`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md) |
* Clock: 50MHz from on-board oscillator |
* Reset: via on-board button "KEY0" |
* GPIO output port `gpio_o` (8-bit) connected to the 8 green user LEDs ("LED7" - "LED0") |
* UART0 signals `uart0_txd_o` and `uart0_rxd_i` are connected to the 40-pin **GPIO_0** header |
* `uart0_txd_o:` output, connected to FPGA pin `C3` - header pin `GPIO_01` (pin number "4") |
* `uart0_rxd_i:` input, connected to FPGA pin `A3` - header pin `GPIO_03` (pin number "6") |
|
:warning: The default [`neorv32_test_setup.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) top entity |
is configured for a 100MHz input clock. Since the on-board oscillator of the DE0-nano board generates a 50MHz clock, the test setup has to be modified. |
This is automatically done by the `create_project.tcl` TCL script, which makes a local copy of the original test setup VHDL file |
(in *this* folder) and uses `sed` to configure the `CLOCK_FREQUENCY` generic (in the local copy) for 50MHz. The local copy is then used as actual |
top entity. |
|
|
## How To Run |
|
The `create_project.tcl` TCL script in this directory can be used to create a complete Quartus project. |
If not already available, this script will create a `work` folder in this directory. |
|
1. start Quartus (in GUI mode) |
2. in the menu line click "View/Utility Windows/Tcl console" to open the Tcl console |
3. use the console to naviagte to **this** folder: `cd .../neorv32/boards/de0-nano-test-setup` |
4. execute `source create_project.tcl` - this will create and open the actual Quartus project in this folder |
5. if a "select family" prompt appears select the "Cyclone IV E" family and click OK |
6. double click on "Compile Design" in the "Tasks" window. This will synthesize, map and place & route your design and will also generate the actual FPGA bitstream |
7. when the process is done open the programmer (for example via "Tools/Programmer") and click "Start" in the programmer window to upload the bitstream to your FPGA |
8. use a serial terminal (like :earth_asia: [Tera Term](https://ttssh2.osdn.jp/index.html.en)) to connect to the USB-UART interface using the following configuration: |
19200 Baud, 8 data bits, 1 stop bit, no parity bits, no transmission / flow control protocol (raw bytes only), newline on `\r\n` (carriage return & newline) |
9. now you can communicate with the bootloader console and upload a new program. Check out the [example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) |
and see section "Let's Get It Started" of the :page_facing_up: [NEORV32 data sheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf) for further resources. |
/neorv32/trunk/boards/de0-nano-test-setup/create_project.tcl
0,0 → 1,92
# make a local copy of original "./../../rtl/top_templates/neorv32_test_setup.vhd" file |
# and modify the default clock frequency: set to 50MHz |
set shell_script "cp -f ./../../rtl/top_templates/neorv32_test_setup.vhd . && sed -i '/CLOCK_FREQUENCY/c\CLOCK_FREQUENCY => 50000000,' neorv32_test_setup.vhd" |
exec sh -c $shell_script |
|
# Copyright (C) 2020 Intel Corporation. All rights reserved. |
# Your use of Intel Corporation's design tools, logic functions |
# and other software and tools, and any partner logic |
# functions, and any output files from any of the foregoing |
# (including device programming or simulation files), and any |
# associated documentation or information are expressly subject |
# to the terms and conditions of the Intel Program License |
# Subscription Agreement, the Intel Quartus Prime License Agreement, |
# the Intel FPGA IP License Agreement, or other applicable license |
# agreement, including, without limitation, that your use is for |
# the sole purpose of programming logic devices manufactured by |
# Intel and sold by Intel or its authorized distributors. Please |
# refer to the applicable agreement for further details, at |
# https://fpgasoftware.intel.com/eula. |
|
# Quartus Prime: Generate Tcl File for Project |
# File: de0_nano_test.tcl |
# Generated on: Sat Apr 10 16:57:48 2021 |
|
# Load Quartus Prime Tcl Project package |
package require ::quartus::project |
|
set need_to_close_project 0 |
set make_assignments 1 |
|
# Check that the right project is open |
if {[is_project_open]} { |
if {[string compare $quartus(project) "de0-nano-test-setup"]} { |
puts "Project de0-nano-test-setup is not open" |
set make_assignments 0 |
} |
} else { |
# Only open if not already open |
if {[project_exists de0-nano-test-setup]} { |
project_open -revision de0-nano-test-setup de0-nano-test-setup |
} else { |
project_new -revision de0-nano-test-setup de0-nano-test-setup |
} |
set need_to_close_project 1 |
} |
|
# Make assignments |
if {$make_assignments} { |
set_global_assignment -name FAMILY "Cyclone IV E" |
set_global_assignment -name DEVICE EP4CE22F17C6 |
set_global_assignment -name TOP_LEVEL_ENTITY neorv32_test_setup |
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 20.1.0 |
set_global_assignment -name PROJECT_CREATION_TIME_DATE "16:40:53 APRIL 10, 2021" |
set_global_assignment -name LAST_QUARTUS_VERSION "20.1.0 Lite Edition" |
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files |
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 |
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 |
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 |
|
# core VHDL files |
set core_src_dir [glob ./../../rtl/core/*.vhd] |
foreach core_src_file $core_src_dir { |
set_global_assignment -name VHDL_FILE $core_src_file -library neorv32 |
} |
|
# top entity: use local modified copy of the original test setup |
set_global_assignment -name VHDL_FILE "neorv32_test_setup.vhd" |
|
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" |
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" |
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top |
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top |
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top |
|
set_location_assignment PIN_R8 -to clk_i |
set_location_assignment PIN_L3 -to gpio_o[7] |
set_location_assignment PIN_B1 -to gpio_o[6] |
set_location_assignment PIN_F3 -to gpio_o[5] |
set_location_assignment PIN_D1 -to gpio_o[4] |
set_location_assignment PIN_A11 -to gpio_o[3] |
set_location_assignment PIN_B13 -to gpio_o[2] |
set_location_assignment PIN_A13 -to gpio_o[1] |
set_location_assignment PIN_A15 -to gpio_o[0] |
set_location_assignment PIN_J15 -to rstn_i |
set_location_assignment PIN_C3 -to uart0_txd_o |
set_location_assignment PIN_A3 -to uart0_rxd_i |
|
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top |
|
# Commit assignments |
export_assignments |
} |
/neorv32/trunk/boards/nexys-a7-test-setup/.gitignore
0,0 → 1,3
vivado* |
.Xil |
work/* |
/neorv32/trunk/boards/nexys-a7-test-setup/README.md
0,0 → 1,51
# NEORV32 Test Setup for the Digilent Nexys A7 and Nexys 4 DDR FPGA Boards |
|
This setup provides a very simple script-based "demo setup" that allows to check out the NEORV32 processor on the Digilent Nexys A7 and Nexys 4 DDR boards. |
It uses the simplified [`neorv32_test_setup.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) top entity, which is a wrapper for the actual processor |
top entity that provides a minimalistic interface (clock, reset, UART and 4 LEDs). |
|
* FPGA Boards: |
* :books: [Digilent Nexys A7 FPGA Boards](https://reference.digilentinc.com/reference/programmable-logic/nexys-a7/reference-manual) |
* :books: [Digilent Nexys 4 DDR FPGA Board](https://reference.digilentinc.com/reference/programmable-logic/nexys-4-ddr/reference-manual) |
* FPGAs: |
* Xilinx Artix-7 `XC7A50TCSG324-1` |
* Xilinx Artix-7 `XC7A100TCSG324-1` |
* Toolchain: Xilinx Vivado (tested with Vivado 2020.2) |
|
|
### NEORV32 Configuration |
|
:information_source: See the top entity [`rtl/top_templates/neorv32_test_setup.vhd` ](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) for |
configuration and entity details and [`nexys_a7_test_setup.xdc`](https://github.com/AWenzel83/neorv32/blob/nexys_a7_example/boards/nexys-a7-test-setup/nexys_a7_test_setup.xdc) |
for the according FPGA pin mapping. |
|
* CPU: `rv32imcu_Zicsr` + 4 `HPM` (hardware performance monitors) |
* Memory: 16kB instruction memory (internal IMEM), 8kB data memory (internal DMEM), bootloader ROM |
* Peripherals: `GPIO`, `MTIME`, `UART0`, `WDT` |
* Tested with version [`1.5.3.3`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md) |
* Clock: 100MHz from on-board oscillator |
* Reset: Via dedicated on-board "RESET" button |
* GPIO output port `gpio_o` bits 0..7 are connected to the green on-board LEDs (LD0 - LD7); LD0 is the bootloader status LED |
* UART0 signals `uart0_txd_o` and `uart0_rxd_i` are connected to the on-board USB-UART chip |
|
|
## How To Run |
|
The `create_project_nexys_a7_*.tcl` TCL scripts in this directory can be used to create a complete Vivado project. |
If not already available, this script will create a `work` folder in this directory. |
|
1. start Vivado (in GUI mode) |
2. click on "TCL Console" at the bottom |
3. use the console to naviagte to **this** folder: `cd .../neorv32/boards/nexys-a7-test-setup` |
4. execute the tcl-script according to your board, this will create the actual Vivado project in `work`: |
* `source create_project_nexys_a7_100.tcl`for a Nexys A7 100 or a Nexys 4 DDR board |
* `source create_project_nexys_a7_50.tcl`for a Nexys A7 50 board |
5. when the Vivado project has openend, click on "Run Implementation" |
6. when the implementation is done create a bitstrem by clicking "Generate Bitstream" (maybe a prompt will ask for that) |
7. open the "Hardware Manager" (maybe a prompt will ask for that) |
8. click on "Open target/Auto Connect" |
9. click on "Program device" and select `work/neorv32_test_setup.runs/impl_1/neorv32_test_setup.bit`; click "Program" |
10. use a serial terminal (like :earth_asia: [Tera Term](https://ttssh2.osdn.jp/index.html.en)) to connect to the USB-UART interface using the following configuration: |
19200 Baud, 8 data bits, 1 stop bit, no parity bits, no transmission / flow control protocol (raw bytes only), newline on `\r\n` (carriage return & newline) |
11. now you can communicate with the bootloader console and upload a new program. Check out the [example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) |
and see section "Let's Get It Started" of the :page_facing_up: [NEORV32 data sheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf) for further resources. |
/neorv32/trunk/boards/nexys-a7-test-setup/create_project_nexys_a7_100.tcl
0,0 → 1,29
# create and clear output directory |
set outputdir work |
file mkdir $outputdir |
|
set files [glob -nocomplain "$outputdir/*"] |
if {[llength $files] != 0} { |
puts "deleting contents of $outputdir" |
file delete -force {*}[glob -directory $outputdir *]; # clear folder contents |
} else { |
puts "$outputdir is empty" |
} |
|
|
# create project |
create_project -part "xc7a100tcsg324-1" "nexys-a7-100-test-setup" $outputdir |
|
|
# add source files: core sources |
add_files [glob ./../../rtl/core/*.vhd] |
set_property library neorv32 [get_files [glob ./../../rtl/core/*.vhd]] |
|
# add source file: top entity |
add_files [glob ./../../rtl/top_templates/neorv32_test_setup.vhd] |
|
# add source files: simulation-only |
add_files -fileset sim_1 ./../../sim/neorv32_tb.vhd |
|
# add source files: constraints |
add_files -fileset constrs_1 [glob ./*.xdc] |
/neorv32/trunk/boards/nexys-a7-test-setup/create_project_nexys_a7_50.tcl
0,0 → 1,29
# create and clear output directory |
set outputdir work |
file mkdir $outputdir |
|
set files [glob -nocomplain "$outputdir/*"] |
if {[llength $files] != 0} { |
puts "deleting contents of $outputdir" |
file delete -force {*}[glob -directory $outputdir *]; # clear folder contents |
} else { |
puts "$outputdir is empty" |
} |
|
|
# create project |
create_project -part "xc7a50tcsg324-1" "nexys-a7-50-test-setup" $outputdir |
|
|
# add source files: core sources |
add_files [glob ./../../rtl/core/*.vhd] |
set_property library neorv32 [get_files [glob ./../../rtl/core/*.vhd]] |
|
# add source file: top entity |
add_files [glob ./../../rtl/top_templates/neorv32_test_setup.vhd] |
|
# add source files: simulation-only |
add_files -fileset sim_1 ./../../sim/neorv32_tb.vhd |
|
# add source files: constraints |
add_files -fileset constrs_1 [glob ./*.xdc] |
/neorv32/trunk/boards/nexys-a7-test-setup/nexys_a7_test_setup.xdc
0,0 → 1,23
## This file is a general .xdc for the Nexys A7 and Nexys 4 DDR |
## For default neorv32_test_setup.vhd top entity |
|
## Clock signal |
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk_i }]; #IO_L12P_T1_MRCC_35 Sch=gclk[100] |
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { clk_i }]; |
|
## LEDs |
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[0] }]; #IO_L18P_T2_A24_15 Sch=led[0] |
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1] |
set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[2] }]; #IO_L17N_T2_A25_15 Sch=led[2] |
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[3] }]; #IO_L8P_T1_D11_14 Sch=led[3] |
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[4] }]; #IO_L7P_T1_D09_14 Sch=led[4] |
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5] |
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6] |
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { gpio_o[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7] |
|
## USB-UART Interface |
set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart0_txd_o }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out |
set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { uart0_rxd_i }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in |
|
## Misc. |
set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { rstn_i }]; #IO_L3P_T0_DQS_AD1P_15 Sch=ck_rst |
/neorv32/trunk/boards/README.md
0,0 → 1,26
# Exemplary FPGA Board Setups |
|
**:construction: This page is still under construction :construction:** |
|
This folder provides exemplary NEORV32 SoC setups for different FPGA platforms/boards. You can use one of the setups to directly get started |
or as a starting point to build your own setup. |
|
Project maintainers may make pull requests against this repository to add or link their setups. |
|
|
| Setup | Board | FPGA | Author | |
|:-----:|:------|:------|:------:| |
| :file_folder: [`arty-a7-35-test-setup`](https://github.com/stnolting/neorv32/tree/master/boards/arty-a7-35-test-setup) | [Digilent Arty A7-35](https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start) | Xilinx Artix-7 `XC7A35TICSG324-1L` | [stnolting](https://github.com/stnolting) | |
| :file_folder: [`nexys-a7-test-setup`](https://github.com/stnolting/neorv32/tree/master/boards/nexys-a7-test-setup) | [Digilent Nexys A7](https://reference.digilentinc.com/reference/programmable-logic/nexys-a7/start) | Xilinx Artix-7 `XC7A50TCSG324-1` | [AWenzel83](https://github.com/AWenzel83) | |
| :file_folder: [`nexys-a7-test-setup`](https://github.com/stnolting/neorv32/tree/master/boards/nexys-a7-test-setup) | [Digilent Nexys 4 DDR](https://reference.digilentinc.com/reference/programmable-logic/nexys-4-ddr/start) | Xilinx Artix-7 `XC7A100TCSG324-1` | [AWenzel83](https://github.com/AWenzel83) | |
| :file_folder: [`de0-nano-test-setup`](https://github.com/stnolting/neorv32/tree/master/boards/de0-nano-test-setup) | [Terasic DE0-Nano](https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=139&No=593) | Intel Cyclone IV `EP4CE22F17C6N` | [stnolting](https://github.com/stnolting) | |
|
|
### Adding Your Project Setup |
|
Please respect the following guidelines if you'd like to add (or link) your setup to the list. |
|
* check out the project's [code of conduct](https://github.com/stnolting/neorv32/tree/master/CODE_OF_CONDUCT.md) |
* add a link if the board you are using provides online documentation (and/or can be purchased somewhere) |
* use the :file_folder: emoji (`:file_folder:`) if the setup is located *in this* folder; use the :earth_africa: emoji (`:earth_africa:`) if it is a link to your local project |
* please add a `README` to give some brief information about the setup and a `.gitignore` to keep things clean; take a look at [`arty-a7-35-test-setup`](https://github.com/stnolting/neorv32/boards/arty-a7-35-test-setup) to get some ideas what a project setup might look like |
/neorv32/trunk/docs/NEORV32.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/neorv32/trunk/rtl/core/neorv32_application_image.vhd
6,7 → 6,7
|
package neorv32_application_image is |
|
type application_init_image_t is array (0 to 1068) of std_ulogic_vector(31 downto 0); |
type application_init_image_t is array (0 to 1071) of std_ulogic_vector(31 downto 0); |
constant application_init_image : application_init_image_t := ( |
00000000 => x"00000093", |
00000001 => x"00000113", |
19,68 → 19,68
00000008 => x"00000493", |
00000009 => x"00000713", |
00000010 => x"00000793", |
00000011 => x"00000597", |
00000012 => x"10c58593", |
00000013 => x"30559073", |
00000014 => x"00000813", |
00000015 => x"00000893", |
00000016 => x"00000913", |
00000017 => x"00000993", |
00000018 => x"00000a13", |
00000019 => x"00000a93", |
00000020 => x"00000b13", |
00000021 => x"00000b93", |
00000022 => x"00000c13", |
00000023 => x"00000c93", |
00000024 => x"00000d13", |
00000025 => x"00000d93", |
00000026 => x"00000e13", |
00000027 => x"00000e93", |
00000028 => x"00000f13", |
00000029 => x"00000f93", |
00000030 => x"00002537", |
00000031 => x"80050513", |
00000032 => x"30051073", |
00000033 => x"30401073", |
00000034 => x"80002117", |
00000035 => x"f7410113", |
00000036 => x"ffc17113", |
00000037 => x"00010413", |
00000038 => x"80000197", |
00000039 => x"76818193", |
00000040 => x"f0000593", |
00000041 => x"0005a023", |
00000042 => x"00458593", |
00000043 => x"feb01ce3", |
00000044 => x"80000597", |
00000045 => x"f5058593", |
00000046 => x"87418613", |
00000047 => x"00c5d863", |
00000048 => x"00058023", |
00000049 => x"00158593", |
00000050 => x"ff5ff06f", |
00000051 => x"00001597", |
00000052 => x"fe458593", |
00000053 => x"80000617", |
00000054 => x"f2c60613", |
00000055 => x"80000697", |
00000056 => x"f2468693", |
00000057 => x"00d65c63", |
00000058 => x"00058703", |
00000059 => x"00e60023", |
00000060 => x"00158593", |
00000061 => x"00160613", |
00000062 => x"fedff06f", |
00000063 => x"00000513", |
00000064 => x"00000593", |
00000065 => x"b0001073", |
00000066 => x"b8001073", |
00000067 => x"b0201073", |
00000068 => x"b8201073", |
00000069 => x"3063d073", |
00000070 => x"32001073", |
00000071 => x"80000637", |
00000072 => x"34261073", |
00000011 => x"00000517", |
00000012 => x"10c50513", |
00000013 => x"30551073", |
00000014 => x"34151073", |
00000015 => x"34301073", |
00000016 => x"34201073", |
00000017 => x"30001073", |
00000018 => x"30401073", |
00000019 => x"30601073", |
00000020 => x"ffa00593", |
00000021 => x"32059073", |
00000022 => x"b0001073", |
00000023 => x"b8001073", |
00000024 => x"b0201073", |
00000025 => x"b8201073", |
00000026 => x"00000813", |
00000027 => x"00000893", |
00000028 => x"00000913", |
00000029 => x"00000993", |
00000030 => x"00000a13", |
00000031 => x"00000a93", |
00000032 => x"00000b13", |
00000033 => x"00000b93", |
00000034 => x"00000c13", |
00000035 => x"00000c93", |
00000036 => x"00000d13", |
00000037 => x"00000d93", |
00000038 => x"00000e13", |
00000039 => x"00000e93", |
00000040 => x"00000f13", |
00000041 => x"00000f93", |
00000042 => x"80002117", |
00000043 => x"f5410113", |
00000044 => x"ffc17113", |
00000045 => x"00010413", |
00000046 => x"80000197", |
00000047 => x"74818193", |
00000048 => x"f0000593", |
00000049 => x"0005a023", |
00000050 => x"00458593", |
00000051 => x"feb01ce3", |
00000052 => x"80000597", |
00000053 => x"f3058593", |
00000054 => x"87418613", |
00000055 => x"00c5d863", |
00000056 => x"00058023", |
00000057 => x"00158593", |
00000058 => x"ff5ff06f", |
00000059 => x"00001597", |
00000060 => x"fd058593", |
00000061 => x"80000617", |
00000062 => x"f0c60613", |
00000063 => x"80000697", |
00000064 => x"f0468693", |
00000065 => x"00d65c63", |
00000066 => x"00058703", |
00000067 => x"00e60023", |
00000068 => x"00158593", |
00000069 => x"00160613", |
00000070 => x"fedff06f", |
00000071 => x"00000513", |
00000072 => x"00000593", |
00000073 => x"060000ef", |
00000074 => x"30047073", |
00000075 => x"00000013", |
111,19 → 111,19
00000100 => x"00000593", |
00000101 => x"b0050513", |
00000102 => x"00112623", |
00000103 => x"248000ef", |
00000104 => x"201000ef", |
00000103 => x"730000ef", |
00000104 => x"16d000ef", |
00000105 => x"02050063", |
00000106 => x"151000ef", |
00000106 => x"4a8000ef", |
00000107 => x"00000513", |
00000108 => x"1a5000ef", |
00000108 => x"4fc000ef", |
00000109 => x"00001537", |
00000110 => x"d4450513", |
00000111 => x"298000ef", |
00000110 => x"d5050513", |
00000111 => x"780000ef", |
00000112 => x"020000ef", |
00000113 => x"00001537", |
00000114 => x"d2050513", |
00000115 => x"288000ef", |
00000114 => x"d2c50513", |
00000115 => x"770000ef", |
00000116 => x"00c12083", |
00000117 => x"00000513", |
00000118 => x"01010113", |
133,949 → 133,952
00000122 => x"00812423", |
00000123 => x"00112623", |
00000124 => x"00000413", |
00000125 => x"1bd000ef", |
00000125 => x"129000ef", |
00000126 => x"0ff47513", |
00000127 => x"1b5000ef", |
00000127 => x"121000ef", |
00000128 => x"0c800513", |
00000129 => x"43c000ef", |
00000129 => x"14d000ef", |
00000130 => x"00140413", |
00000131 => x"fedff06f", |
00000132 => x"fd010113", |
00000133 => x"02812423", |
00000134 => x"02912223", |
00000135 => x"03212023", |
00000136 => x"01312e23", |
00000137 => x"01412c23", |
00000138 => x"02112623", |
00000139 => x"01512a23", |
00000140 => x"00001a37", |
00000141 => x"00050493", |
00000142 => x"00058413", |
00000143 => x"00058523", |
00000144 => x"00000993", |
00000145 => x"00410913", |
00000146 => x"d60a0a13", |
00000147 => x"00a00593", |
00000148 => x"00048513", |
00000149 => x"269000ef", |
00000150 => x"00aa0533", |
00000151 => x"00054783", |
00000152 => x"01390ab3", |
00000153 => x"00048513", |
00000154 => x"00fa8023", |
00000155 => x"00a00593", |
00000156 => x"205000ef", |
00000157 => x"00198993", |
00000158 => x"00a00793", |
00000159 => x"00050493", |
00000160 => x"fcf996e3", |
00000161 => x"00090693", |
00000162 => x"00900713", |
00000163 => x"03000613", |
00000164 => x"0096c583", |
00000165 => x"00070793", |
00000166 => x"fff70713", |
00000167 => x"01071713", |
00000168 => x"01075713", |
00000169 => x"00c59a63", |
00000170 => x"000684a3", |
00000171 => x"fff68693", |
00000172 => x"fe0710e3", |
00000173 => x"00000793", |
00000174 => x"00f907b3", |
00000175 => x"00000593", |
00000176 => x"0007c703", |
00000177 => x"00070c63", |
00000178 => x"00158693", |
00000179 => x"00b405b3", |
00000180 => x"00e58023", |
00000181 => x"01069593", |
00000182 => x"0105d593", |
00000183 => x"fff78713", |
00000184 => x"02f91863", |
00000185 => x"00b40433", |
00000186 => x"00040023", |
00000187 => x"02c12083", |
00000188 => x"02812403", |
00000189 => x"02412483", |
00000190 => x"02012903", |
00000191 => x"01c12983", |
00000192 => x"01812a03", |
00000193 => x"01412a83", |
00000194 => x"03010113", |
00000195 => x"00008067", |
00000196 => x"00070793", |
00000197 => x"fadff06f", |
00000198 => x"00001637", |
00000199 => x"00758693", |
00000200 => x"00000713", |
00000201 => x"d6c60613", |
00000202 => x"02000813", |
00000203 => x"00e557b3", |
00000204 => x"00f7f793", |
00000205 => x"00f607b3", |
00000206 => x"0007c783", |
00000207 => x"00470713", |
00000208 => x"fff68693", |
00000209 => x"00f680a3", |
00000210 => x"ff0712e3", |
00000211 => x"00058423", |
00000212 => x"00008067", |
00000213 => x"fa002023", |
00000214 => x"fe002703", |
00000215 => x"00151513", |
00000216 => x"00000793", |
00000217 => x"04a77463", |
00000218 => x"000016b7", |
00000219 => x"00000713", |
00000220 => x"ffe68693", |
00000221 => x"04f6e663", |
00000222 => x"00367613", |
00000223 => x"0035f593", |
00000224 => x"fff78793", |
00000225 => x"01461613", |
00000226 => x"00c7e7b3", |
00000227 => x"01659593", |
00000228 => x"01871713", |
00000229 => x"00b7e7b3", |
00000230 => x"00e7e7b3", |
00000231 => x"10000737", |
00000232 => x"00e7e7b3", |
00000233 => x"faf02023", |
00000234 => x"00008067", |
00000235 => x"00178793", |
00000236 => x"01079793", |
00000237 => x"40a70733", |
00000238 => x"0107d793", |
00000239 => x"fa9ff06f", |
00000240 => x"ffe70513", |
00000241 => x"0fd57513", |
00000242 => x"00051a63", |
00000243 => x"0037d793", |
00000244 => x"00170713", |
00000245 => x"0ff77713", |
00000246 => x"f9dff06f", |
00000247 => x"0017d793", |
00000248 => x"ff1ff06f", |
00000249 => x"f71ff06f", |
00000250 => x"fa002783", |
00000251 => x"fe07cee3", |
00000252 => x"faa02223", |
00000253 => x"00008067", |
00000254 => x"ff1ff06f", |
00000255 => x"ff010113", |
00000256 => x"00812423", |
00000257 => x"01212023", |
00000258 => x"00112623", |
00000259 => x"00912223", |
00000260 => x"00050413", |
00000261 => x"00a00913", |
00000262 => x"00044483", |
00000263 => x"00140413", |
00000264 => x"00049e63", |
00000265 => x"00c12083", |
00000266 => x"00812403", |
00000267 => x"00412483", |
00000268 => x"00012903", |
00000269 => x"01010113", |
00000270 => x"00008067", |
00000271 => x"01249663", |
00000272 => x"00d00513", |
00000273 => x"fa5ff0ef", |
00000274 => x"00048513", |
00000275 => x"f9dff0ef", |
00000276 => x"fc9ff06f", |
00000277 => x"fa9ff06f", |
00000278 => x"fa010113", |
00000279 => x"04f12a23", |
00000280 => x"04410793", |
00000281 => x"02812c23", |
00000282 => x"03212823", |
00000283 => x"03412423", |
00000284 => x"03512223", |
00000285 => x"03612023", |
00000286 => x"01712e23", |
00000287 => x"01812c23", |
00000288 => x"01912a23", |
00000289 => x"02112e23", |
00000290 => x"02912a23", |
00000291 => x"03312623", |
00000292 => x"00050413", |
00000293 => x"04b12223", |
00000294 => x"04c12423", |
00000295 => x"04d12623", |
00000296 => x"04e12823", |
00000297 => x"05012c23", |
00000298 => x"05112e23", |
00000299 => x"00f12023", |
00000300 => x"02500a13", |
00000301 => x"00a00a93", |
00000302 => x"07300913", |
00000303 => x"07500b13", |
00000304 => x"07800b93", |
00000305 => x"06300c13", |
00000306 => x"06900c93", |
00000307 => x"00044483", |
00000308 => x"02048063", |
00000309 => x"0f449a63", |
00000310 => x"00144783", |
00000311 => x"00240993", |
00000312 => x"07278463", |
00000313 => x"04f96063", |
00000314 => x"07878e63", |
00000315 => x"09978863", |
00000316 => x"03c12083", |
00000317 => x"03812403", |
00000318 => x"03412483", |
00000319 => x"03012903", |
00000320 => x"02c12983", |
00000321 => x"02812a03", |
00000322 => x"02412a83", |
00000323 => x"02012b03", |
00000324 => x"01c12b83", |
00000325 => x"01812c03", |
00000326 => x"01412c83", |
00000327 => x"06010113", |
00000328 => x"00008067", |
00000329 => x"09678663", |
00000330 => x"fd7794e3", |
00000331 => x"00012783", |
00000332 => x"00410593", |
00000333 => x"0007a503", |
00000334 => x"00478713", |
00000335 => x"00e12023", |
00000336 => x"dd9ff0ef", |
00000337 => x"0640006f", |
00000338 => x"00012783", |
00000339 => x"0007a503", |
00000340 => x"00478713", |
00000341 => x"00e12023", |
00000342 => x"ea5ff0ef", |
00000343 => x"00098413", |
00000344 => x"f6dff06f", |
00000345 => x"00012783", |
00000346 => x"0007c503", |
00000347 => x"00478713", |
00000348 => x"00e12023", |
00000349 => x"e75ff0ef", |
00000350 => x"fe5ff06f", |
00000351 => x"00012783", |
00000352 => x"0007a403", |
00000353 => x"00478713", |
00000354 => x"00e12023", |
00000355 => x"00045863", |
00000356 => x"02d00513", |
00000357 => x"40800433", |
00000358 => x"e51ff0ef", |
00000359 => x"00410593", |
00000360 => x"00040513", |
00000361 => x"c6dff0ef", |
00000362 => x"00410513", |
00000363 => x"fadff06f", |
00000364 => x"00012783", |
00000365 => x"00410593", |
00000366 => x"00478713", |
00000367 => x"0007a503", |
00000368 => x"00e12023", |
00000369 => x"fe1ff06f", |
00000370 => x"01549663", |
00000371 => x"00d00513", |
00000372 => x"e19ff0ef", |
00000373 => x"00140993", |
00000374 => x"00048513", |
00000375 => x"f99ff06f", |
00000376 => x"fd010113", |
00000377 => x"00112623", |
00000378 => x"00b12a23", |
00000379 => x"00c12c23", |
00000380 => x"00d12e23", |
00000381 => x"02e12023", |
00000382 => x"02f12223", |
00000383 => x"03012423", |
00000384 => x"03112623", |
00000385 => x"e55ff0ef", |
00000386 => x"00c12083", |
00000387 => x"03010113", |
00000388 => x"00008067", |
00000389 => x"ff010113", |
00000390 => x"c80026f3", |
00000391 => x"c0002773", |
00000392 => x"c80027f3", |
00000393 => x"fed79ae3", |
00000394 => x"00e12023", |
00000395 => x"00f12223", |
00000396 => x"00012503", |
00000397 => x"00412583", |
00000398 => x"01010113", |
00000399 => x"00008067", |
00000400 => x"fe010113", |
00000401 => x"00112e23", |
00000402 => x"00812c23", |
00000403 => x"00912a23", |
00000404 => x"00a12623", |
00000405 => x"fc1ff0ef", |
00000406 => x"00050493", |
00000407 => x"fe002503", |
00000408 => x"00058413", |
00000409 => x"3e800593", |
00000410 => x"60c000ef", |
00000411 => x"00c12603", |
00000412 => x"00000693", |
00000413 => x"00000593", |
00000414 => x"564000ef", |
00000415 => x"009504b3", |
00000416 => x"00a4b533", |
00000417 => x"00858433", |
00000418 => x"00850433", |
00000419 => x"f89ff0ef", |
00000420 => x"fe85eee3", |
00000421 => x"00b41463", |
00000422 => x"fe956ae3", |
00000423 => x"01c12083", |
00000424 => x"01812403", |
00000425 => x"01412483", |
00000426 => x"02010113", |
00000427 => x"00008067", |
00000428 => x"fc010113", |
00000429 => x"02112e23", |
00000430 => x"02512c23", |
00000431 => x"02612a23", |
00000432 => x"02712823", |
00000433 => x"02a12623", |
00000434 => x"02b12423", |
00000435 => x"02c12223", |
00000436 => x"02d12023", |
00000437 => x"00e12e23", |
00000438 => x"00f12c23", |
00000439 => x"01012a23", |
00000440 => x"01112823", |
00000441 => x"01c12623", |
00000442 => x"01d12423", |
00000443 => x"01e12223", |
00000444 => x"01f12023", |
00000445 => x"34102773", |
00000446 => x"34071073", |
00000447 => x"342027f3", |
00000448 => x"0807ca63", |
00000449 => x"00071683", |
00000450 => x"00300593", |
00000451 => x"0036f693", |
00000452 => x"00270613", |
00000453 => x"00b69463", |
00000454 => x"00470613", |
00000455 => x"34161073", |
00000456 => x"00b00713", |
00000457 => x"04f77c63", |
00000458 => x"000017b7", |
00000459 => x"93078793", |
00000460 => x"000780e7", |
00000461 => x"03c12083", |
00000462 => x"03812283", |
00000463 => x"03412303", |
00000464 => x"03012383", |
00000465 => x"02c12503", |
00000466 => x"02812583", |
00000467 => x"02412603", |
00000468 => x"02012683", |
00000469 => x"01c12703", |
00000470 => x"01812783", |
00000471 => x"01412803", |
00000472 => x"01012883", |
00000473 => x"00c12e03", |
00000474 => x"00812e83", |
00000475 => x"00412f03", |
00000476 => x"00012f83", |
00000477 => x"04010113", |
00000478 => x"30200073", |
00000479 => x"00001737", |
00000480 => x"00279793", |
00000481 => x"d8070713", |
00000482 => x"00e787b3", |
00000483 => x"0007a783", |
00000484 => x"00078067", |
00000485 => x"80000737", |
00000486 => x"ffd74713", |
00000487 => x"00e787b3", |
00000488 => x"01c00713", |
00000489 => x"f8f762e3", |
00000490 => x"00001737", |
00000491 => x"00279793", |
00000492 => x"db070713", |
00000493 => x"00e787b3", |
00000494 => x"0007a783", |
00000495 => x"00078067", |
00000496 => x"800007b7", |
00000497 => x"0007a783", |
00000498 => x"f69ff06f", |
00000499 => x"800007b7", |
00000500 => x"0047a783", |
00000501 => x"f5dff06f", |
00000502 => x"800007b7", |
00000503 => x"0087a783", |
00000504 => x"f51ff06f", |
00000505 => x"800007b7", |
00000506 => x"00c7a783", |
00000507 => x"f45ff06f", |
00000508 => x"8101a783", |
00000509 => x"f3dff06f", |
00000510 => x"8141a783", |
00000511 => x"f35ff06f", |
00000512 => x"8181a783", |
00000513 => x"f2dff06f", |
00000514 => x"81c1a783", |
00000515 => x"f25ff06f", |
00000516 => x"8201a783", |
00000517 => x"f1dff06f", |
00000518 => x"8241a783", |
00000519 => x"f15ff06f", |
00000520 => x"8281a783", |
00000521 => x"f0dff06f", |
00000522 => x"82c1a783", |
00000523 => x"f05ff06f", |
00000524 => x"8301a783", |
00000525 => x"efdff06f", |
00000526 => x"8341a783", |
00000527 => x"ef5ff06f", |
00000528 => x"8381a783", |
00000529 => x"eedff06f", |
00000530 => x"83c1a783", |
00000531 => x"ee5ff06f", |
00000532 => x"8401a783", |
00000533 => x"eddff06f", |
00000534 => x"8441a783", |
00000535 => x"ed5ff06f", |
00000536 => x"8481a783", |
00000537 => x"ecdff06f", |
00000538 => x"84c1a783", |
00000539 => x"ec5ff06f", |
00000540 => x"8501a783", |
00000541 => x"ebdff06f", |
00000542 => x"8541a783", |
00000543 => x"eb5ff06f", |
00000544 => x"8581a783", |
00000545 => x"eadff06f", |
00000546 => x"85c1a783", |
00000547 => x"ea5ff06f", |
00000548 => x"8601a783", |
00000549 => x"e9dff06f", |
00000550 => x"8641a783", |
00000551 => x"e95ff06f", |
00000552 => x"8681a783", |
00000553 => x"e8dff06f", |
00000554 => x"86c1a783", |
00000555 => x"e85ff06f", |
00000556 => x"8701a783", |
00000557 => x"e7dff06f", |
00000558 => x"00000000", |
00000559 => x"00000000", |
00000560 => x"fe010113", |
00000561 => x"01212823", |
00000562 => x"00050913", |
00000563 => x"00001537", |
00000564 => x"00912a23", |
00000565 => x"e2450513", |
00000566 => x"000014b7", |
00000567 => x"00812c23", |
00000568 => x"01312623", |
00000569 => x"00112e23", |
00000570 => x"01c00413", |
00000571 => x"b69ff0ef", |
00000572 => x"0a048493", |
00000573 => x"ffc00993", |
00000574 => x"008957b3", |
00000575 => x"00f7f793", |
00000576 => x"00f487b3", |
00000577 => x"0007c503", |
00000578 => x"ffc40413", |
00000579 => x"aedff0ef", |
00000580 => x"ff3414e3", |
00000581 => x"01c12083", |
00000582 => x"01812403", |
00000583 => x"01412483", |
00000584 => x"01012903", |
00000585 => x"00c12983", |
00000586 => x"02010113", |
00000587 => x"00008067", |
00000588 => x"00001537", |
00000589 => x"ff010113", |
00000590 => x"e2850513", |
00000591 => x"00112623", |
00000592 => x"00812423", |
00000593 => x"00912223", |
00000594 => x"b0dff0ef", |
00000595 => x"34202473", |
00000596 => x"00900713", |
00000597 => x"00f47793", |
00000598 => x"05778493", |
00000599 => x"00f76463", |
00000600 => x"03078493", |
00000601 => x"00b00793", |
00000602 => x"0087ee63", |
00000603 => x"00001737", |
00000604 => x"00241793", |
00000605 => x"fb470713", |
00000606 => x"00e787b3", |
00000607 => x"0007a783", |
00000608 => x"00078067", |
00000609 => x"800007b7", |
00000610 => x"00b78713", |
00000611 => x"12e40663", |
00000612 => x"02876663", |
00000613 => x"00378713", |
00000614 => x"10e40463", |
00000615 => x"00778793", |
00000616 => x"10f40663", |
00000617 => x"00001537", |
00000618 => x"f8850513", |
00000619 => x"aa9ff0ef", |
00000620 => x"00040513", |
00000621 => x"f0dff0ef", |
00000622 => x"0380006f", |
00000623 => x"ff07c793", |
00000624 => x"00f407b3", |
00000625 => x"00f00713", |
00000626 => x"fcf76ee3", |
00000627 => x"00001537", |
00000628 => x"f7850513", |
00000629 => x"a81ff0ef", |
00000630 => x"00048513", |
00000631 => x"a1dff0ef", |
00000632 => x"0100006f", |
00000633 => x"00001537", |
00000634 => x"e3050513", |
00000635 => x"a69ff0ef", |
00000636 => x"00001537", |
00000637 => x"fa050513", |
00000638 => x"a5dff0ef", |
00000639 => x"34002573", |
00000640 => x"ec1ff0ef", |
00000641 => x"00001537", |
00000642 => x"fa850513", |
00000643 => x"a49ff0ef", |
00000644 => x"34302573", |
00000645 => x"eadff0ef", |
00000646 => x"00812403", |
00000647 => x"00c12083", |
00000648 => x"00412483", |
00000649 => x"00001537", |
00000650 => x"01050513", |
00000651 => x"01010113", |
00000652 => x"a25ff06f", |
00000653 => x"00001537", |
00000654 => x"e5050513", |
00000655 => x"fb1ff06f", |
00000656 => x"00001537", |
00000657 => x"e6c50513", |
00000658 => x"fa5ff06f", |
00000659 => x"00001537", |
00000660 => x"e8050513", |
00000661 => x"f99ff06f", |
00000662 => x"00001537", |
00000663 => x"e8c50513", |
00000664 => x"f8dff06f", |
00000665 => x"00001537", |
00000666 => x"ea450513", |
00000667 => x"f81ff06f", |
00000668 => x"00001537", |
00000669 => x"eb850513", |
00000670 => x"f75ff06f", |
00000671 => x"00001537", |
00000672 => x"ed450513", |
00000673 => x"f69ff06f", |
00000674 => x"00001537", |
00000675 => x"ee850513", |
00000676 => x"f5dff06f", |
00000677 => x"00001537", |
00000678 => x"f0850513", |
00000679 => x"f51ff06f", |
00000680 => x"00001537", |
00000681 => x"f2850513", |
00000682 => x"f45ff06f", |
00000683 => x"00001537", |
00000684 => x"f4450513", |
00000685 => x"f39ff06f", |
00000686 => x"00001537", |
00000687 => x"f5c50513", |
00000688 => x"f2dff06f", |
00000689 => x"01f00793", |
00000690 => x"02a7e463", |
00000691 => x"800007b7", |
00000692 => x"00078793", |
00000693 => x"00251513", |
00000694 => x"00a78533", |
00000695 => x"000017b7", |
00000696 => x"93078793", |
00000697 => x"00f52023", |
00000698 => x"00000513", |
00000699 => x"00008067", |
00000700 => x"00100513", |
00000701 => x"00008067", |
00000702 => x"ff010113", |
00000703 => x"00112623", |
00000704 => x"00812423", |
00000705 => x"00912223", |
00000706 => x"301027f3", |
00000707 => x"00079863", |
00000708 => x"00001537", |
00000709 => x"fe450513", |
00000710 => x"93dff0ef", |
00000711 => x"6b000793", |
00000712 => x"30579073", |
00000713 => x"00000413", |
00000714 => x"01d00493", |
00000715 => x"00040513", |
00000716 => x"00140413", |
00000717 => x"0ff47413", |
00000718 => x"f8dff0ef", |
00000719 => x"fe9418e3", |
00000720 => x"00c12083", |
00000721 => x"00812403", |
00000722 => x"00412483", |
00000723 => x"01010113", |
00000724 => x"00008067", |
00000725 => x"ff010113", |
00000726 => x"00112623", |
00000727 => x"00812423", |
00000728 => x"30102673", |
00000729 => x"400005b7", |
00000730 => x"10058593", |
00000731 => x"00b677b3", |
00000732 => x"00000413", |
00000733 => x"00b78c63", |
00000734 => x"00100413", |
00000735 => x"00051863", |
00000736 => x"00001537", |
00000737 => x"01850513", |
00000738 => x"a59ff0ef", |
00000739 => x"00c12083", |
00000740 => x"00040513", |
00000741 => x"00812403", |
00000742 => x"01010113", |
00000743 => x"00008067", |
00000744 => x"fe802503", |
00000745 => x"01055513", |
00000746 => x"00157513", |
00000747 => x"00008067", |
00000748 => x"f8a02223", |
00000749 => x"00008067", |
00000750 => x"00050613", |
00000751 => x"00000513", |
00000752 => x"0015f693", |
00000753 => x"00068463", |
00000754 => x"00c50533", |
00000755 => x"0015d593", |
00000756 => x"00161613", |
00000757 => x"fe0596e3", |
00000758 => x"00008067", |
00000759 => x"00050313", |
00000760 => x"ff010113", |
00000761 => x"00060513", |
00000762 => x"00068893", |
00000763 => x"00112623", |
00000764 => x"00030613", |
00000765 => x"00050693", |
00000766 => x"00000713", |
00000767 => x"00000793", |
00000768 => x"00000813", |
00000769 => x"0016fe13", |
00000770 => x"00171e93", |
00000771 => x"000e0c63", |
00000772 => x"01060e33", |
00000773 => x"010e3833", |
00000774 => x"00e787b3", |
00000775 => x"00f807b3", |
00000776 => x"000e0813", |
00000777 => x"01f65713", |
00000778 => x"0016d693", |
00000779 => x"00eee733", |
00000780 => x"00161613", |
00000781 => x"fc0698e3", |
00000782 => x"00058663", |
00000783 => x"f7dff0ef", |
00000784 => x"00a787b3", |
00000785 => x"00088a63", |
00000786 => x"00030513", |
00000787 => x"00088593", |
00000788 => x"f69ff0ef", |
00000789 => x"00f507b3", |
00000790 => x"00c12083", |
00000791 => x"00080513", |
00000792 => x"00078593", |
00000793 => x"01010113", |
00000794 => x"00008067", |
00000795 => x"06054063", |
00000796 => x"0605c663", |
00000797 => x"00058613", |
00000798 => x"00050593", |
00000799 => x"fff00513", |
00000800 => x"02060c63", |
00000801 => x"00100693", |
00000802 => x"00b67a63", |
00000803 => x"00c05863", |
00000804 => x"00161613", |
00000805 => x"00169693", |
00000806 => x"feb66ae3", |
00000807 => x"00000513", |
00000808 => x"00c5e663", |
00000809 => x"40c585b3", |
00000810 => x"00d56533", |
00000811 => x"0016d693", |
00000812 => x"00165613", |
00000813 => x"fe0696e3", |
00000814 => x"00008067", |
00000815 => x"00008293", |
00000816 => x"fb5ff0ef", |
00000817 => x"00058513", |
00000818 => x"00028067", |
00000819 => x"40a00533", |
00000820 => x"00b04863", |
00000821 => x"40b005b3", |
00000822 => x"f9dff06f", |
00000823 => x"40b005b3", |
00000824 => x"00008293", |
00000825 => x"f91ff0ef", |
00000826 => x"40a00533", |
00000827 => x"00028067", |
00000828 => x"00008293", |
00000829 => x"0005ca63", |
00000830 => x"00054c63", |
00000831 => x"f79ff0ef", |
00000832 => x"00058513", |
00000833 => x"00028067", |
00000834 => x"40b005b3", |
00000835 => x"fe0558e3", |
00000836 => x"40a00533", |
00000837 => x"f61ff0ef", |
00000838 => x"40b00533", |
00000839 => x"00028067", |
00000840 => x"6f727245", |
00000841 => x"4e202172", |
00000842 => x"5047206f", |
00000843 => x"75204f49", |
00000844 => x"2074696e", |
00000845 => x"746e7973", |
00000846 => x"69736568", |
00000847 => x"2164657a", |
00000848 => x"0000000a", |
00000849 => x"6e696c42", |
00000850 => x"676e696b", |
00000851 => x"44454c20", |
00000852 => x"6d656420", |
00000853 => x"7270206f", |
00000854 => x"6172676f", |
00000855 => x"00000a6d", |
00000856 => x"33323130", |
00000857 => x"37363534", |
00000858 => x"00003938", |
00000859 => x"33323130", |
00000860 => x"37363534", |
00000861 => x"62613938", |
00000862 => x"66656463", |
00000863 => x"00000000", |
00000864 => x"000007c0", |
00000865 => x"000007cc", |
00000866 => x"000007d8", |
00000867 => x"000007e4", |
00000868 => x"000007f0", |
00000869 => x"000007f8", |
00000870 => x"00000800", |
00000871 => x"00000808", |
00000872 => x"00000810", |
00000873 => x"00000728", |
00000874 => x"00000728", |
00000875 => x"00000818", |
00000876 => x"00000820", |
00000877 => x"00000728", |
00000878 => x"00000728", |
00000879 => x"00000728", |
00000880 => x"00000828", |
00000881 => x"00000728", |
00000882 => x"00000728", |
00000883 => x"00000728", |
00000884 => x"00000830", |
00000885 => x"00000728", |
00000886 => x"00000728", |
00000887 => x"00000728", |
00000888 => x"00000728", |
00000889 => x"00000838", |
00000890 => x"00000840", |
00000891 => x"00000848", |
00000892 => x"00000850", |
00000893 => x"00000858", |
00000894 => x"00000860", |
00000895 => x"00000868", |
00000896 => x"00000870", |
00000897 => x"00000878", |
00000898 => x"00000880", |
00000899 => x"00000888", |
00000900 => x"00000890", |
00000901 => x"00000898", |
00000902 => x"000008a0", |
00000903 => x"000008a8", |
00000904 => x"000008b0", |
00000905 => x"00007830", |
00000906 => x"4554523c", |
00000907 => x"0000203e", |
00000908 => x"74736e49", |
00000909 => x"74637572", |
00000910 => x"206e6f69", |
00000911 => x"72646461", |
00000912 => x"20737365", |
00000913 => x"6173696d", |
00000914 => x"6e67696c", |
00000915 => x"00006465", |
00000916 => x"74736e49", |
00000917 => x"74637572", |
00000918 => x"206e6f69", |
00000919 => x"65636361", |
00000920 => x"66207373", |
00000921 => x"746c7561", |
00000922 => x"00000000", |
00000923 => x"656c6c49", |
00000924 => x"206c6167", |
00000925 => x"74736e69", |
00000926 => x"74637572", |
00000927 => x"006e6f69", |
00000928 => x"61657242", |
00000929 => x"696f706b", |
00000930 => x"0000746e", |
00000931 => x"64616f4c", |
00000932 => x"64646120", |
00000933 => x"73736572", |
00000934 => x"73696d20", |
00000935 => x"67696c61", |
00000936 => x"0064656e", |
00000937 => x"64616f4c", |
00000938 => x"63636120", |
00000939 => x"20737365", |
00000940 => x"6c756166", |
00000941 => x"00000074", |
00000942 => x"726f7453", |
00000943 => x"64612065", |
00000944 => x"73657264", |
00000945 => x"696d2073", |
00000946 => x"696c6173", |
00000947 => x"64656e67", |
00000948 => x"00000000", |
00000949 => x"726f7453", |
00000950 => x"63612065", |
00000951 => x"73736563", |
00000952 => x"75616620", |
00000953 => x"0000746c", |
00000954 => x"69766e45", |
00000955 => x"6d6e6f72", |
00000956 => x"20746e65", |
00000957 => x"6c6c6163", |
00000958 => x"6f726620", |
00000959 => x"2d55206d", |
00000960 => x"65646f6d", |
00000961 => x"00000000", |
00000962 => x"69766e45", |
00000963 => x"6d6e6f72", |
00000964 => x"20746e65", |
00000965 => x"6c6c6163", |
00000966 => x"6f726620", |
00000967 => x"2d4d206d", |
00000968 => x"65646f6d", |
00000969 => x"00000000", |
00000970 => x"6863614d", |
00000971 => x"20656e69", |
00000972 => x"74666f73", |
00000973 => x"65726177", |
00000974 => x"746e6920", |
00000975 => x"75727265", |
00000976 => x"00007470", |
00000977 => x"6863614d", |
00000978 => x"20656e69", |
00000979 => x"656d6974", |
00000980 => x"6e692072", |
00000981 => x"72726574", |
00000982 => x"00747075", |
00000983 => x"6863614d", |
00000984 => x"20656e69", |
00000985 => x"65747865", |
00000986 => x"6c616e72", |
00000987 => x"746e6920", |
00000988 => x"75727265", |
00000989 => x"00007470", |
00000990 => x"74736146", |
00000991 => x"746e6920", |
00000992 => x"75727265", |
00000993 => x"00207470", |
00000994 => x"6e6b6e55", |
00000995 => x"206e776f", |
00000996 => x"70617274", |
00000997 => x"75616320", |
00000998 => x"203a6573", |
00000132 => x"fc010113", |
00000133 => x"02112e23", |
00000134 => x"02512c23", |
00000135 => x"02612a23", |
00000136 => x"02712823", |
00000137 => x"02a12623", |
00000138 => x"02b12423", |
00000139 => x"02c12223", |
00000140 => x"02d12023", |
00000141 => x"00e12e23", |
00000142 => x"00f12c23", |
00000143 => x"01012a23", |
00000144 => x"01112823", |
00000145 => x"01c12623", |
00000146 => x"01d12423", |
00000147 => x"01e12223", |
00000148 => x"01f12023", |
00000149 => x"34102773", |
00000150 => x"34071073", |
00000151 => x"342027f3", |
00000152 => x"0807c863", |
00000153 => x"00071683", |
00000154 => x"00300593", |
00000155 => x"0036f693", |
00000156 => x"00270613", |
00000157 => x"00b69463", |
00000158 => x"00470613", |
00000159 => x"34161073", |
00000160 => x"00b00713", |
00000161 => x"04f77a63", |
00000162 => x"48c00793", |
00000163 => x"000780e7", |
00000164 => x"03c12083", |
00000165 => x"03812283", |
00000166 => x"03412303", |
00000167 => x"03012383", |
00000168 => x"02c12503", |
00000169 => x"02812583", |
00000170 => x"02412603", |
00000171 => x"02012683", |
00000172 => x"01c12703", |
00000173 => x"01812783", |
00000174 => x"01412803", |
00000175 => x"01012883", |
00000176 => x"00c12e03", |
00000177 => x"00812e83", |
00000178 => x"00412f03", |
00000179 => x"00012f83", |
00000180 => x"04010113", |
00000181 => x"30200073", |
00000182 => x"00001737", |
00000183 => x"00279793", |
00000184 => x"d6c70713", |
00000185 => x"00e787b3", |
00000186 => x"0007a783", |
00000187 => x"00078067", |
00000188 => x"80000737", |
00000189 => x"ffd74713", |
00000190 => x"00e787b3", |
00000191 => x"01c00713", |
00000192 => x"f8f764e3", |
00000193 => x"00001737", |
00000194 => x"00279793", |
00000195 => x"d9c70713", |
00000196 => x"00e787b3", |
00000197 => x"0007a783", |
00000198 => x"00078067", |
00000199 => x"800007b7", |
00000200 => x"0007a783", |
00000201 => x"f69ff06f", |
00000202 => x"800007b7", |
00000203 => x"0047a783", |
00000204 => x"f5dff06f", |
00000205 => x"800007b7", |
00000206 => x"0087a783", |
00000207 => x"f51ff06f", |
00000208 => x"800007b7", |
00000209 => x"00c7a783", |
00000210 => x"f45ff06f", |
00000211 => x"8101a783", |
00000212 => x"f3dff06f", |
00000213 => x"8141a783", |
00000214 => x"f35ff06f", |
00000215 => x"8181a783", |
00000216 => x"f2dff06f", |
00000217 => x"81c1a783", |
00000218 => x"f25ff06f", |
00000219 => x"8201a783", |
00000220 => x"f1dff06f", |
00000221 => x"8241a783", |
00000222 => x"f15ff06f", |
00000223 => x"8281a783", |
00000224 => x"f0dff06f", |
00000225 => x"82c1a783", |
00000226 => x"f05ff06f", |
00000227 => x"8301a783", |
00000228 => x"efdff06f", |
00000229 => x"8341a783", |
00000230 => x"ef5ff06f", |
00000231 => x"8381a783", |
00000232 => x"eedff06f", |
00000233 => x"83c1a783", |
00000234 => x"ee5ff06f", |
00000235 => x"8401a783", |
00000236 => x"eddff06f", |
00000237 => x"8441a783", |
00000238 => x"ed5ff06f", |
00000239 => x"8481a783", |
00000240 => x"ecdff06f", |
00000241 => x"84c1a783", |
00000242 => x"ec5ff06f", |
00000243 => x"8501a783", |
00000244 => x"ebdff06f", |
00000245 => x"8541a783", |
00000246 => x"eb5ff06f", |
00000247 => x"8581a783", |
00000248 => x"eadff06f", |
00000249 => x"85c1a783", |
00000250 => x"ea5ff06f", |
00000251 => x"8601a783", |
00000252 => x"e9dff06f", |
00000253 => x"8641a783", |
00000254 => x"e95ff06f", |
00000255 => x"8681a783", |
00000256 => x"e8dff06f", |
00000257 => x"86c1a783", |
00000258 => x"e85ff06f", |
00000259 => x"8701a783", |
00000260 => x"e7dff06f", |
00000261 => x"00000000", |
00000262 => x"00000000", |
00000263 => x"fe010113", |
00000264 => x"01212823", |
00000265 => x"00050913", |
00000266 => x"00001537", |
00000267 => x"00912a23", |
00000268 => x"e1050513", |
00000269 => x"000014b7", |
00000270 => x"00812c23", |
00000271 => x"01312623", |
00000272 => x"00112e23", |
00000273 => x"01c00413", |
00000274 => x"4f4000ef", |
00000275 => x"08c48493", |
00000276 => x"ffc00993", |
00000277 => x"008957b3", |
00000278 => x"00f7f793", |
00000279 => x"00f487b3", |
00000280 => x"0007c503", |
00000281 => x"ffc40413", |
00000282 => x"478000ef", |
00000283 => x"ff3414e3", |
00000284 => x"01c12083", |
00000285 => x"01812403", |
00000286 => x"01412483", |
00000287 => x"01012903", |
00000288 => x"00c12983", |
00000289 => x"02010113", |
00000290 => x"00008067", |
00000291 => x"00001537", |
00000292 => x"ff010113", |
00000293 => x"e1450513", |
00000294 => x"00112623", |
00000295 => x"00812423", |
00000296 => x"00912223", |
00000297 => x"498000ef", |
00000298 => x"34202473", |
00000299 => x"00900713", |
00000300 => x"00f47793", |
00000301 => x"05778493", |
00000302 => x"00f76463", |
00000303 => x"03078493", |
00000304 => x"00b00793", |
00000305 => x"0087ee63", |
00000306 => x"00001737", |
00000307 => x"00241793", |
00000308 => x"fa070713", |
00000309 => x"00e787b3", |
00000310 => x"0007a783", |
00000311 => x"00078067", |
00000312 => x"800007b7", |
00000313 => x"00b78713", |
00000314 => x"12e40663", |
00000315 => x"02876663", |
00000316 => x"00378713", |
00000317 => x"10e40463", |
00000318 => x"00778793", |
00000319 => x"10f40663", |
00000320 => x"00001537", |
00000321 => x"f7450513", |
00000322 => x"434000ef", |
00000323 => x"00040513", |
00000324 => x"f0dff0ef", |
00000325 => x"0380006f", |
00000326 => x"ff07c793", |
00000327 => x"00f407b3", |
00000328 => x"00f00713", |
00000329 => x"fcf76ee3", |
00000330 => x"00001537", |
00000331 => x"f6450513", |
00000332 => x"40c000ef", |
00000333 => x"00048513", |
00000334 => x"3a8000ef", |
00000335 => x"0100006f", |
00000336 => x"00001537", |
00000337 => x"e1c50513", |
00000338 => x"3f4000ef", |
00000339 => x"00001537", |
00000340 => x"f8c50513", |
00000341 => x"3e8000ef", |
00000342 => x"34002573", |
00000343 => x"ec1ff0ef", |
00000344 => x"00001537", |
00000345 => x"f9450513", |
00000346 => x"3d4000ef", |
00000347 => x"34302573", |
00000348 => x"eadff0ef", |
00000349 => x"00812403", |
00000350 => x"00c12083", |
00000351 => x"00412483", |
00000352 => x"00001537", |
00000353 => x"ffc50513", |
00000354 => x"01010113", |
00000355 => x"3b00006f", |
00000356 => x"00001537", |
00000357 => x"e3c50513", |
00000358 => x"fb1ff06f", |
00000359 => x"00001537", |
00000360 => x"e5850513", |
00000361 => x"fa5ff06f", |
00000362 => x"00001537", |
00000363 => x"e6c50513", |
00000364 => x"f99ff06f", |
00000365 => x"00001537", |
00000366 => x"e7850513", |
00000367 => x"f8dff06f", |
00000368 => x"00001537", |
00000369 => x"e9050513", |
00000370 => x"f81ff06f", |
00000371 => x"00001537", |
00000372 => x"ea450513", |
00000373 => x"f75ff06f", |
00000374 => x"00001537", |
00000375 => x"ec050513", |
00000376 => x"f69ff06f", |
00000377 => x"00001537", |
00000378 => x"ed450513", |
00000379 => x"f5dff06f", |
00000380 => x"00001537", |
00000381 => x"ef450513", |
00000382 => x"f51ff06f", |
00000383 => x"00001537", |
00000384 => x"f1450513", |
00000385 => x"f45ff06f", |
00000386 => x"00001537", |
00000387 => x"f3050513", |
00000388 => x"f39ff06f", |
00000389 => x"00001537", |
00000390 => x"f4850513", |
00000391 => x"f2dff06f", |
00000392 => x"01f00793", |
00000393 => x"02a7e263", |
00000394 => x"800007b7", |
00000395 => x"00078793", |
00000396 => x"00251513", |
00000397 => x"00a78533", |
00000398 => x"48c00793", |
00000399 => x"00f52023", |
00000400 => x"00000513", |
00000401 => x"00008067", |
00000402 => x"00100513", |
00000403 => x"00008067", |
00000404 => x"ff010113", |
00000405 => x"00112623", |
00000406 => x"00812423", |
00000407 => x"00912223", |
00000408 => x"301027f3", |
00000409 => x"00079863", |
00000410 => x"00001537", |
00000411 => x"fd050513", |
00000412 => x"2cc000ef", |
00000413 => x"21000793", |
00000414 => x"30579073", |
00000415 => x"00000413", |
00000416 => x"01d00493", |
00000417 => x"00040513", |
00000418 => x"00140413", |
00000419 => x"0ff47413", |
00000420 => x"f91ff0ef", |
00000421 => x"fe9418e3", |
00000422 => x"00c12083", |
00000423 => x"00812403", |
00000424 => x"00412483", |
00000425 => x"01010113", |
00000426 => x"00008067", |
00000427 => x"ff010113", |
00000428 => x"00112623", |
00000429 => x"00812423", |
00000430 => x"30102673", |
00000431 => x"400005b7", |
00000432 => x"10058593", |
00000433 => x"00b677b3", |
00000434 => x"00000413", |
00000435 => x"00b78c63", |
00000436 => x"00100413", |
00000437 => x"00051863", |
00000438 => x"00001537", |
00000439 => x"00450513", |
00000440 => x"3f8000ef", |
00000441 => x"00c12083", |
00000442 => x"00040513", |
00000443 => x"00812403", |
00000444 => x"01010113", |
00000445 => x"00008067", |
00000446 => x"fd010113", |
00000447 => x"02812423", |
00000448 => x"02912223", |
00000449 => x"03212023", |
00000450 => x"01312e23", |
00000451 => x"01412c23", |
00000452 => x"02112623", |
00000453 => x"01512a23", |
00000454 => x"00001a37", |
00000455 => x"00050493", |
00000456 => x"00058413", |
00000457 => x"00058523", |
00000458 => x"00000993", |
00000459 => x"00410913", |
00000460 => x"09ca0a13", |
00000461 => x"00a00593", |
00000462 => x"00048513", |
00000463 => x"58c000ef", |
00000464 => x"00aa0533", |
00000465 => x"00054783", |
00000466 => x"01390ab3", |
00000467 => x"00048513", |
00000468 => x"00fa8023", |
00000469 => x"00a00593", |
00000470 => x"528000ef", |
00000471 => x"00198993", |
00000472 => x"00a00793", |
00000473 => x"00050493", |
00000474 => x"fcf996e3", |
00000475 => x"00090693", |
00000476 => x"00900713", |
00000477 => x"03000613", |
00000478 => x"0096c583", |
00000479 => x"00070793", |
00000480 => x"fff70713", |
00000481 => x"01071713", |
00000482 => x"01075713", |
00000483 => x"00c59a63", |
00000484 => x"000684a3", |
00000485 => x"fff68693", |
00000486 => x"fe0710e3", |
00000487 => x"00000793", |
00000488 => x"00f907b3", |
00000489 => x"00000593", |
00000490 => x"0007c703", |
00000491 => x"00070c63", |
00000492 => x"00158693", |
00000493 => x"00b405b3", |
00000494 => x"00e58023", |
00000495 => x"01069593", |
00000496 => x"0105d593", |
00000497 => x"fff78713", |
00000498 => x"02f91863", |
00000499 => x"00b40433", |
00000500 => x"00040023", |
00000501 => x"02c12083", |
00000502 => x"02812403", |
00000503 => x"02412483", |
00000504 => x"02012903", |
00000505 => x"01c12983", |
00000506 => x"01812a03", |
00000507 => x"01412a83", |
00000508 => x"03010113", |
00000509 => x"00008067", |
00000510 => x"00070793", |
00000511 => x"fadff06f", |
00000512 => x"00001637", |
00000513 => x"00758693", |
00000514 => x"00000713", |
00000515 => x"0a860613", |
00000516 => x"02000813", |
00000517 => x"00e557b3", |
00000518 => x"00f7f793", |
00000519 => x"00f607b3", |
00000520 => x"0007c783", |
00000521 => x"00470713", |
00000522 => x"fff68693", |
00000523 => x"00f680a3", |
00000524 => x"ff0712e3", |
00000525 => x"00058423", |
00000526 => x"00008067", |
00000527 => x"fa002023", |
00000528 => x"fe002703", |
00000529 => x"00151513", |
00000530 => x"00000793", |
00000531 => x"04a77463", |
00000532 => x"000016b7", |
00000533 => x"00000713", |
00000534 => x"ffe68693", |
00000535 => x"04f6e663", |
00000536 => x"00367613", |
00000537 => x"0035f593", |
00000538 => x"fff78793", |
00000539 => x"01461613", |
00000540 => x"00c7e7b3", |
00000541 => x"01659593", |
00000542 => x"01871713", |
00000543 => x"00b7e7b3", |
00000544 => x"00e7e7b3", |
00000545 => x"10000737", |
00000546 => x"00e7e7b3", |
00000547 => x"faf02023", |
00000548 => x"00008067", |
00000549 => x"00178793", |
00000550 => x"01079793", |
00000551 => x"40a70733", |
00000552 => x"0107d793", |
00000553 => x"fa9ff06f", |
00000554 => x"ffe70513", |
00000555 => x"0fd57513", |
00000556 => x"00051a63", |
00000557 => x"0037d793", |
00000558 => x"00170713", |
00000559 => x"0ff77713", |
00000560 => x"f9dff06f", |
00000561 => x"0017d793", |
00000562 => x"ff1ff06f", |
00000563 => x"f71ff06f", |
00000564 => x"fa002783", |
00000565 => x"fe07cee3", |
00000566 => x"faa02223", |
00000567 => x"00008067", |
00000568 => x"ff1ff06f", |
00000569 => x"ff010113", |
00000570 => x"00812423", |
00000571 => x"01212023", |
00000572 => x"00112623", |
00000573 => x"00912223", |
00000574 => x"00050413", |
00000575 => x"00a00913", |
00000576 => x"00044483", |
00000577 => x"00140413", |
00000578 => x"00049e63", |
00000579 => x"00c12083", |
00000580 => x"00812403", |
00000581 => x"00412483", |
00000582 => x"00012903", |
00000583 => x"01010113", |
00000584 => x"00008067", |
00000585 => x"01249663", |
00000586 => x"00d00513", |
00000587 => x"fa5ff0ef", |
00000588 => x"00048513", |
00000589 => x"f9dff0ef", |
00000590 => x"fc9ff06f", |
00000591 => x"fa9ff06f", |
00000592 => x"fa010113", |
00000593 => x"04f12a23", |
00000594 => x"04410793", |
00000595 => x"02812c23", |
00000596 => x"03212823", |
00000597 => x"03412423", |
00000598 => x"03512223", |
00000599 => x"03612023", |
00000600 => x"01712e23", |
00000601 => x"01812c23", |
00000602 => x"01912a23", |
00000603 => x"02112e23", |
00000604 => x"02912a23", |
00000605 => x"03312623", |
00000606 => x"00050413", |
00000607 => x"04b12223", |
00000608 => x"04c12423", |
00000609 => x"04d12623", |
00000610 => x"04e12823", |
00000611 => x"05012c23", |
00000612 => x"05112e23", |
00000613 => x"00f12023", |
00000614 => x"02500a13", |
00000615 => x"00a00a93", |
00000616 => x"07300913", |
00000617 => x"07500b13", |
00000618 => x"07800b93", |
00000619 => x"06300c13", |
00000620 => x"06900c93", |
00000621 => x"00044483", |
00000622 => x"02049c63", |
00000623 => x"03c12083", |
00000624 => x"03812403", |
00000625 => x"03412483", |
00000626 => x"03012903", |
00000627 => x"02c12983", |
00000628 => x"02812a03", |
00000629 => x"02412a83", |
00000630 => x"02012b03", |
00000631 => x"01c12b83", |
00000632 => x"01812c03", |
00000633 => x"01412c83", |
00000634 => x"06010113", |
00000635 => x"00008067", |
00000636 => x"0d449863", |
00000637 => x"00240993", |
00000638 => x"00144403", |
00000639 => x"05240263", |
00000640 => x"00896e63", |
00000641 => x"05840c63", |
00000642 => x"07940663", |
00000643 => x"02500513", |
00000644 => x"ec1ff0ef", |
00000645 => x"00040513", |
00000646 => x"0540006f", |
00000647 => x"09640663", |
00000648 => x"ff7416e3", |
00000649 => x"00012783", |
00000650 => x"00410593", |
00000651 => x"0007a503", |
00000652 => x"00478713", |
00000653 => x"00e12023", |
00000654 => x"dc9ff0ef", |
00000655 => x"0640006f", |
00000656 => x"00012783", |
00000657 => x"0007a503", |
00000658 => x"00478713", |
00000659 => x"00e12023", |
00000660 => x"e95ff0ef", |
00000661 => x"00098413", |
00000662 => x"f5dff06f", |
00000663 => x"00012783", |
00000664 => x"0007c503", |
00000665 => x"00478713", |
00000666 => x"00e12023", |
00000667 => x"e65ff0ef", |
00000668 => x"fe5ff06f", |
00000669 => x"00012783", |
00000670 => x"0007a403", |
00000671 => x"00478713", |
00000672 => x"00e12023", |
00000673 => x"00045863", |
00000674 => x"02d00513", |
00000675 => x"40800433", |
00000676 => x"e41ff0ef", |
00000677 => x"00410593", |
00000678 => x"00040513", |
00000679 => x"c5dff0ef", |
00000680 => x"00410513", |
00000681 => x"fadff06f", |
00000682 => x"00012783", |
00000683 => x"00410593", |
00000684 => x"00478713", |
00000685 => x"0007a503", |
00000686 => x"00e12023", |
00000687 => x"fe1ff06f", |
00000688 => x"01549663", |
00000689 => x"00d00513", |
00000690 => x"e09ff0ef", |
00000691 => x"00140993", |
00000692 => x"00048513", |
00000693 => x"f99ff06f", |
00000694 => x"fd010113", |
00000695 => x"00112623", |
00000696 => x"00b12a23", |
00000697 => x"00c12c23", |
00000698 => x"00d12e23", |
00000699 => x"02e12023", |
00000700 => x"02f12223", |
00000701 => x"03012423", |
00000702 => x"03112623", |
00000703 => x"e45ff0ef", |
00000704 => x"00c12083", |
00000705 => x"03010113", |
00000706 => x"00008067", |
00000707 => x"fe802503", |
00000708 => x"01055513", |
00000709 => x"00157513", |
00000710 => x"00008067", |
00000711 => x"f8a02223", |
00000712 => x"00008067", |
00000713 => x"ff010113", |
00000714 => x"c80026f3", |
00000715 => x"c0002773", |
00000716 => x"c80027f3", |
00000717 => x"fed79ae3", |
00000718 => x"00e12023", |
00000719 => x"00f12223", |
00000720 => x"00012503", |
00000721 => x"00412583", |
00000722 => x"01010113", |
00000723 => x"00008067", |
00000724 => x"fe010113", |
00000725 => x"00112e23", |
00000726 => x"00812c23", |
00000727 => x"00912a23", |
00000728 => x"00a12623", |
00000729 => x"3200f073", |
00000730 => x"fbdff0ef", |
00000731 => x"00050493", |
00000732 => x"fe002503", |
00000733 => x"00058413", |
00000734 => x"3e800593", |
00000735 => x"104000ef", |
00000736 => x"00c12603", |
00000737 => x"00000693", |
00000738 => x"00000593", |
00000739 => x"05c000ef", |
00000740 => x"009504b3", |
00000741 => x"00a4b533", |
00000742 => x"00858433", |
00000743 => x"00850433", |
00000744 => x"f85ff0ef", |
00000745 => x"fe85eee3", |
00000746 => x"00b41463", |
00000747 => x"fe956ae3", |
00000748 => x"01c12083", |
00000749 => x"01812403", |
00000750 => x"01412483", |
00000751 => x"02010113", |
00000752 => x"00008067", |
00000753 => x"00050613", |
00000754 => x"00000513", |
00000755 => x"0015f693", |
00000756 => x"00068463", |
00000757 => x"00c50533", |
00000758 => x"0015d593", |
00000759 => x"00161613", |
00000760 => x"fe0596e3", |
00000761 => x"00008067", |
00000762 => x"00050313", |
00000763 => x"ff010113", |
00000764 => x"00060513", |
00000765 => x"00068893", |
00000766 => x"00112623", |
00000767 => x"00030613", |
00000768 => x"00050693", |
00000769 => x"00000713", |
00000770 => x"00000793", |
00000771 => x"00000813", |
00000772 => x"0016fe13", |
00000773 => x"00171e93", |
00000774 => x"000e0c63", |
00000775 => x"01060e33", |
00000776 => x"010e3833", |
00000777 => x"00e787b3", |
00000778 => x"00f807b3", |
00000779 => x"000e0813", |
00000780 => x"01f65713", |
00000781 => x"0016d693", |
00000782 => x"00eee733", |
00000783 => x"00161613", |
00000784 => x"fc0698e3", |
00000785 => x"00058663", |
00000786 => x"f7dff0ef", |
00000787 => x"00a787b3", |
00000788 => x"00088a63", |
00000789 => x"00030513", |
00000790 => x"00088593", |
00000791 => x"f69ff0ef", |
00000792 => x"00f507b3", |
00000793 => x"00c12083", |
00000794 => x"00080513", |
00000795 => x"00078593", |
00000796 => x"01010113", |
00000797 => x"00008067", |
00000798 => x"06054063", |
00000799 => x"0605c663", |
00000800 => x"00058613", |
00000801 => x"00050593", |
00000802 => x"fff00513", |
00000803 => x"02060c63", |
00000804 => x"00100693", |
00000805 => x"00b67a63", |
00000806 => x"00c05863", |
00000807 => x"00161613", |
00000808 => x"00169693", |
00000809 => x"feb66ae3", |
00000810 => x"00000513", |
00000811 => x"00c5e663", |
00000812 => x"40c585b3", |
00000813 => x"00d56533", |
00000814 => x"0016d693", |
00000815 => x"00165613", |
00000816 => x"fe0696e3", |
00000817 => x"00008067", |
00000818 => x"00008293", |
00000819 => x"fb5ff0ef", |
00000820 => x"00058513", |
00000821 => x"00028067", |
00000822 => x"40a00533", |
00000823 => x"00b04863", |
00000824 => x"40b005b3", |
00000825 => x"f9dff06f", |
00000826 => x"40b005b3", |
00000827 => x"00008293", |
00000828 => x"f91ff0ef", |
00000829 => x"40a00533", |
00000830 => x"00028067", |
00000831 => x"00008293", |
00000832 => x"0005ca63", |
00000833 => x"00054c63", |
00000834 => x"f79ff0ef", |
00000835 => x"00058513", |
00000836 => x"00028067", |
00000837 => x"40b005b3", |
00000838 => x"fe0558e3", |
00000839 => x"40a00533", |
00000840 => x"f61ff0ef", |
00000841 => x"40b00533", |
00000842 => x"00028067", |
00000843 => x"6f727245", |
00000844 => x"4e202172", |
00000845 => x"5047206f", |
00000846 => x"75204f49", |
00000847 => x"2074696e", |
00000848 => x"746e7973", |
00000849 => x"69736568", |
00000850 => x"2164657a", |
00000851 => x"0000000a", |
00000852 => x"6e696c42", |
00000853 => x"676e696b", |
00000854 => x"44454c20", |
00000855 => x"6d656420", |
00000856 => x"7270206f", |
00000857 => x"6172676f", |
00000858 => x"00000a6d", |
00000859 => x"0000031c", |
00000860 => x"00000328", |
00000861 => x"00000334", |
00000862 => x"00000340", |
00000863 => x"0000034c", |
00000864 => x"00000354", |
00000865 => x"0000035c", |
00000866 => x"00000364", |
00000867 => x"0000036c", |
00000868 => x"00000288", |
00000869 => x"00000288", |
00000870 => x"00000374", |
00000871 => x"0000037c", |
00000872 => x"00000288", |
00000873 => x"00000288", |
00000874 => x"00000288", |
00000875 => x"00000384", |
00000876 => x"00000288", |
00000877 => x"00000288", |
00000878 => x"00000288", |
00000879 => x"0000038c", |
00000880 => x"00000288", |
00000881 => x"00000288", |
00000882 => x"00000288", |
00000883 => x"00000288", |
00000884 => x"00000394", |
00000885 => x"0000039c", |
00000886 => x"000003a4", |
00000887 => x"000003ac", |
00000888 => x"000003b4", |
00000889 => x"000003bc", |
00000890 => x"000003c4", |
00000891 => x"000003cc", |
00000892 => x"000003d4", |
00000893 => x"000003dc", |
00000894 => x"000003e4", |
00000895 => x"000003ec", |
00000896 => x"000003f4", |
00000897 => x"000003fc", |
00000898 => x"00000404", |
00000899 => x"0000040c", |
00000900 => x"00007830", |
00000901 => x"4554523c", |
00000902 => x"0000203e", |
00000903 => x"74736e49", |
00000904 => x"74637572", |
00000905 => x"206e6f69", |
00000906 => x"72646461", |
00000907 => x"20737365", |
00000908 => x"6173696d", |
00000909 => x"6e67696c", |
00000910 => x"00006465", |
00000911 => x"74736e49", |
00000912 => x"74637572", |
00000913 => x"206e6f69", |
00000914 => x"65636361", |
00000915 => x"66207373", |
00000916 => x"746c7561", |
00000917 => x"00000000", |
00000918 => x"656c6c49", |
00000919 => x"206c6167", |
00000920 => x"74736e69", |
00000921 => x"74637572", |
00000922 => x"006e6f69", |
00000923 => x"61657242", |
00000924 => x"696f706b", |
00000925 => x"0000746e", |
00000926 => x"64616f4c", |
00000927 => x"64646120", |
00000928 => x"73736572", |
00000929 => x"73696d20", |
00000930 => x"67696c61", |
00000931 => x"0064656e", |
00000932 => x"64616f4c", |
00000933 => x"63636120", |
00000934 => x"20737365", |
00000935 => x"6c756166", |
00000936 => x"00000074", |
00000937 => x"726f7453", |
00000938 => x"64612065", |
00000939 => x"73657264", |
00000940 => x"696d2073", |
00000941 => x"696c6173", |
00000942 => x"64656e67", |
00000943 => x"00000000", |
00000944 => x"726f7453", |
00000945 => x"63612065", |
00000946 => x"73736563", |
00000947 => x"75616620", |
00000948 => x"0000746c", |
00000949 => x"69766e45", |
00000950 => x"6d6e6f72", |
00000951 => x"20746e65", |
00000952 => x"6c6c6163", |
00000953 => x"6f726620", |
00000954 => x"2d55206d", |
00000955 => x"65646f6d", |
00000956 => x"00000000", |
00000957 => x"69766e45", |
00000958 => x"6d6e6f72", |
00000959 => x"20746e65", |
00000960 => x"6c6c6163", |
00000961 => x"6f726620", |
00000962 => x"2d4d206d", |
00000963 => x"65646f6d", |
00000964 => x"00000000", |
00000965 => x"6863614d", |
00000966 => x"20656e69", |
00000967 => x"74666f73", |
00000968 => x"65726177", |
00000969 => x"746e6920", |
00000970 => x"75727265", |
00000971 => x"00007470", |
00000972 => x"6863614d", |
00000973 => x"20656e69", |
00000974 => x"656d6974", |
00000975 => x"6e692072", |
00000976 => x"72726574", |
00000977 => x"00747075", |
00000978 => x"6863614d", |
00000979 => x"20656e69", |
00000980 => x"65747865", |
00000981 => x"6c616e72", |
00000982 => x"746e6920", |
00000983 => x"75727265", |
00000984 => x"00007470", |
00000985 => x"74736146", |
00000986 => x"746e6920", |
00000987 => x"75727265", |
00000988 => x"00207470", |
00000989 => x"6e6b6e55", |
00000990 => x"206e776f", |
00000991 => x"70617274", |
00000992 => x"75616320", |
00000993 => x"203a6573", |
00000994 => x"00000000", |
00000995 => x"50204020", |
00000996 => x"00003d43", |
00000997 => x"544d202c", |
00000998 => x"3d4c4156", |
00000999 => x"00000000", |
00001000 => x"50204020", |
00001001 => x"00003d43", |
00001002 => x"544d202c", |
00001003 => x"3d4c4156", |
00001004 => x"00000000", |
00001005 => x"000009e4", |
00001006 => x"00000a34", |
00001007 => x"00000a40", |
00001008 => x"00000a4c", |
00001009 => x"00000a58", |
00001010 => x"00000a64", |
00001011 => x"00000a70", |
00001012 => x"00000a7c", |
00001013 => x"00000a88", |
00001014 => x"000009a4", |
00001015 => x"000009a4", |
00001016 => x"00000a94", |
00001017 => x"4554523c", |
00001018 => x"4157203e", |
00001019 => x"4e494e52", |
00001020 => x"43202147", |
00001021 => x"43205550", |
00001022 => x"73205253", |
00001023 => x"65747379", |
00001024 => x"6f6e206d", |
00001025 => x"76612074", |
00001026 => x"616c6961", |
00001027 => x"21656c62", |
00001028 => x"522f3c20", |
00001029 => x"003e4554", |
00001030 => x"5241570a", |
00001031 => x"474e494e", |
00001032 => x"57532021", |
00001033 => x"4153495f", |
00001034 => x"65662820", |
00001035 => x"72757461", |
00001036 => x"72207365", |
00001037 => x"69757165", |
00001038 => x"29646572", |
00001039 => x"20737620", |
00001040 => x"495f5748", |
00001041 => x"28204153", |
00001042 => x"74616566", |
00001043 => x"73657275", |
00001044 => x"61766120", |
00001045 => x"62616c69", |
00001046 => x"2029656c", |
00001047 => x"6d73696d", |
00001048 => x"68637461", |
00001049 => x"57530a21", |
00001050 => x"4153495f", |
00001051 => x"30203d20", |
00001052 => x"20782578", |
00001053 => x"6d6f6328", |
00001054 => x"656c6970", |
00001055 => x"6c662072", |
00001056 => x"29736761", |
00001057 => x"5f57480a", |
00001058 => x"20415349", |
00001059 => x"7830203d", |
00001060 => x"28207825", |
00001061 => x"6173696d", |
00001062 => x"72736320", |
00001063 => x"000a0a29", |
00001064 => x"33323130", |
00001065 => x"37363534", |
00001066 => x"42413938", |
00001067 => x"46454443", |
00001000 => x"00000540", |
00001001 => x"00000590", |
00001002 => x"0000059c", |
00001003 => x"000005a8", |
00001004 => x"000005b4", |
00001005 => x"000005c0", |
00001006 => x"000005cc", |
00001007 => x"000005d8", |
00001008 => x"000005e4", |
00001009 => x"00000500", |
00001010 => x"00000500", |
00001011 => x"000005f0", |
00001012 => x"4554523c", |
00001013 => x"4157203e", |
00001014 => x"4e494e52", |
00001015 => x"43202147", |
00001016 => x"43205550", |
00001017 => x"73205253", |
00001018 => x"65747379", |
00001019 => x"6f6e206d", |
00001020 => x"76612074", |
00001021 => x"616c6961", |
00001022 => x"21656c62", |
00001023 => x"522f3c20", |
00001024 => x"003e4554", |
00001025 => x"5241570a", |
00001026 => x"474e494e", |
00001027 => x"57532021", |
00001028 => x"4153495f", |
00001029 => x"65662820", |
00001030 => x"72757461", |
00001031 => x"72207365", |
00001032 => x"69757165", |
00001033 => x"29646572", |
00001034 => x"20737620", |
00001035 => x"495f5748", |
00001036 => x"28204153", |
00001037 => x"74616566", |
00001038 => x"73657275", |
00001039 => x"61766120", |
00001040 => x"62616c69", |
00001041 => x"2029656c", |
00001042 => x"6d73696d", |
00001043 => x"68637461", |
00001044 => x"57530a21", |
00001045 => x"4153495f", |
00001046 => x"30203d20", |
00001047 => x"20782578", |
00001048 => x"6d6f6328", |
00001049 => x"656c6970", |
00001050 => x"6c662072", |
00001051 => x"29736761", |
00001052 => x"5f57480a", |
00001053 => x"20415349", |
00001054 => x"7830203d", |
00001055 => x"28207825", |
00001056 => x"6173696d", |
00001057 => x"72736320", |
00001058 => x"000a0a29", |
00001059 => x"33323130", |
00001060 => x"37363534", |
00001061 => x"42413938", |
00001062 => x"46454443", |
00001063 => x"33323130", |
00001064 => x"37363534", |
00001065 => x"00003938", |
00001066 => x"33323130", |
00001067 => x"37363534", |
00001068 => x"62613938", |
00001069 => x"66656463", |
00001070 => x"00000000", |
others => x"00000000" |
); |
|
/neorv32/trunk/rtl/core/neorv32_bootloader_image.vhd
6,7 → 6,7
|
package neorv32_bootloader_image is |
|
type bootloader_init_image_t is array (0 to 1009) of std_ulogic_vector(31 downto 0); |
type bootloader_init_image_t is array (0 to 1014) of std_ulogic_vector(31 downto 0); |
constant bootloader_init_image : bootloader_init_image_t := ( |
00000000 => x"00000093", |
00000001 => x"00000113", |
19,52 → 19,52
00000008 => x"00000493", |
00000009 => x"00000713", |
00000010 => x"00000793", |
00000011 => x"00000597", |
00000012 => x"0cc58593", |
00000013 => x"30559073", |
00000014 => x"00002537", |
00000015 => x"80050513", |
00000016 => x"30051073", |
00000017 => x"30401073", |
00000018 => x"80012117", |
00000019 => x"fb410113", |
00000020 => x"ffc17113", |
00000021 => x"00010413", |
00000022 => x"80010197", |
00000023 => x"7a818193", |
00000024 => x"f0000593", |
00000025 => x"0005a023", |
00000026 => x"00458593", |
00000027 => x"feb01ce3", |
00000028 => x"80010597", |
00000029 => x"f9058593", |
00000030 => x"80818613", |
00000031 => x"00c5d863", |
00000032 => x"00058023", |
00000033 => x"00158593", |
00000034 => x"ff5ff06f", |
00000035 => x"00001597", |
00000036 => x"f3858593", |
00000037 => x"80010617", |
00000038 => x"f6c60613", |
00000039 => x"80010697", |
00000040 => x"f6468693", |
00000041 => x"00d65c63", |
00000042 => x"00058703", |
00000043 => x"00e60023", |
00000044 => x"00158593", |
00000045 => x"00160613", |
00000046 => x"fedff06f", |
00000047 => x"00000513", |
00000048 => x"00000593", |
00000049 => x"b0001073", |
00000050 => x"b8001073", |
00000051 => x"b0201073", |
00000052 => x"b8201073", |
00000053 => x"3063d073", |
00000054 => x"32001073", |
00000055 => x"80000637", |
00000056 => x"34261073", |
00000011 => x"80012117", |
00000012 => x"fd010113", |
00000013 => x"ffc17113", |
00000014 => x"00010413", |
00000015 => x"80010197", |
00000016 => x"7c418193", |
00000017 => x"00000517", |
00000018 => x"0b450513", |
00000019 => x"30551073", |
00000020 => x"34151073", |
00000021 => x"34301073", |
00000022 => x"34201073", |
00000023 => x"30001073", |
00000024 => x"30401073", |
00000025 => x"30601073", |
00000026 => x"ffa00593", |
00000027 => x"32059073", |
00000028 => x"b0001073", |
00000029 => x"b8001073", |
00000030 => x"b0201073", |
00000031 => x"b8201073", |
00000032 => x"f0000593", |
00000033 => x"0005a023", |
00000034 => x"00458593", |
00000035 => x"feb01ce3", |
00000036 => x"80010597", |
00000037 => x"f7058593", |
00000038 => x"80818613", |
00000039 => x"00c5d863", |
00000040 => x"00058023", |
00000041 => x"00158593", |
00000042 => x"ff5ff06f", |
00000043 => x"00001597", |
00000044 => x"f2c58593", |
00000045 => x"80010617", |
00000046 => x"f4c60613", |
00000047 => x"80010697", |
00000048 => x"f4468693", |
00000049 => x"00d65c63", |
00000050 => x"00058703", |
00000051 => x"00e60023", |
00000052 => x"00158593", |
00000053 => x"00160613", |
00000054 => x"fedff06f", |
00000055 => x"00000513", |
00000056 => x"00000593", |
00000057 => x"060000ef", |
00000058 => x"30047073", |
00000059 => x"00000013", |
134,32 → 134,32
00000123 => x"00000013", |
00000124 => x"00000013", |
00000125 => x"ffff1537", |
00000126 => x"edc50513", |
00000126 => x"eec50513", |
00000127 => x"309000ef", |
00000128 => x"f1302573", |
00000129 => x"260000ef", |
00000130 => x"ffff1537", |
00000131 => x"f1450513", |
00000131 => x"f2450513", |
00000132 => x"2f5000ef", |
00000133 => x"fe002503", |
00000134 => x"24c000ef", |
00000135 => x"ffff1537", |
00000136 => x"f1c50513", |
00000136 => x"f2c50513", |
00000137 => x"2e1000ef", |
00000138 => x"fe402503", |
00000139 => x"238000ef", |
00000140 => x"ffff1537", |
00000141 => x"f2450513", |
00000141 => x"f3450513", |
00000142 => x"2cd000ef", |
00000143 => x"30102573", |
00000144 => x"224000ef", |
00000145 => x"ffff1537", |
00000146 => x"f2c50513", |
00000146 => x"f3c50513", |
00000147 => x"2b9000ef", |
00000148 => x"fc002573", |
00000149 => x"210000ef", |
00000150 => x"ffff1537", |
00000151 => x"f3450513", |
00000151 => x"f4450513", |
00000152 => x"2a5000ef", |
00000153 => x"fe802503", |
00000154 => x"ffff14b7", |
166,25 → 166,25
00000155 => x"00341413", |
00000156 => x"1f4000ef", |
00000157 => x"ffff1537", |
00000158 => x"f3c50513", |
00000158 => x"f4c50513", |
00000159 => x"289000ef", |
00000160 => x"ff802503", |
00000161 => x"1e0000ef", |
00000162 => x"f4448513", |
00000162 => x"f5448513", |
00000163 => x"279000ef", |
00000164 => x"ff002503", |
00000165 => x"1d0000ef", |
00000166 => x"ffff1537", |
00000167 => x"f5050513", |
00000167 => x"f6050513", |
00000168 => x"265000ef", |
00000169 => x"ffc02503", |
00000170 => x"1bc000ef", |
00000171 => x"f4448513", |
00000171 => x"f5448513", |
00000172 => x"255000ef", |
00000173 => x"ff402503", |
00000174 => x"1ac000ef", |
00000175 => x"ffff1537", |
00000176 => x"f5850513", |
00000176 => x"f6850513", |
00000177 => x"241000ef", |
00000178 => x"0b9000ef", |
00000179 => x"00a404b3", |
193,7 → 193,7
00000182 => x"1d1000ef", |
00000183 => x"02050263", |
00000184 => x"ffff1537", |
00000185 => x"f8050513", |
00000185 => x"f9450513", |
00000186 => x"21d000ef", |
00000187 => x"0d9000ef", |
00000188 => x"02300793", |
215,12 → 215,12
00000204 => x"07500b93", |
00000205 => x"ffff14b7", |
00000206 => x"ffff1c37", |
00000207 => x"f8c90513", |
00000207 => x"fa090513", |
00000208 => x"1c5000ef", |
00000209 => x"155000ef", |
00000210 => x"00050413", |
00000211 => x"129000ef", |
00000212 => x"e9498513", |
00000212 => x"ea498513", |
00000213 => x"1b1000ef", |
00000214 => x"fb4400e3", |
00000215 => x"01541863", |
246,9 → 246,9
00000235 => x"02c000ef", |
00000236 => x"f8dff06f", |
00000237 => x"03f00793", |
00000238 => x"f94c0513", |
00000238 => x"fa8c0513", |
00000239 => x"00f40463", |
00000240 => x"fa848513", |
00000240 => x"fbc48513", |
00000241 => x"141000ef", |
00000242 => x"f75ff06f", |
00000243 => x"ffff1537", |
294,7 → 294,7
00000283 => x"00050913", |
00000284 => x"ffff1537", |
00000285 => x"00912a23", |
00000286 => x"e6050513", |
00000286 => x"e5450513", |
00000287 => x"ffff14b7", |
00000288 => x"00812c23", |
00000289 => x"01312623", |
301,7 → 301,7
00000290 => x"00112e23", |
00000291 => x"01c00413", |
00000292 => x"075000ef", |
00000293 => x"fb448493", |
00000293 => x"fc848493", |
00000294 => x"ffc00993", |
00000295 => x"008957b3", |
00000296 => x"00f7f793", |
373,12 → 373,12
00000362 => x"00100513", |
00000363 => x"02079863", |
00000364 => x"ffff1537", |
00000365 => x"e5450513", |
00000365 => x"e5850513", |
00000366 => x"74c000ef", |
00000367 => x"00040513", |
00000368 => x"ea5ff0ef", |
00000369 => x"ffff1537", |
00000370 => x"e5c50513", |
00000370 => x"e6c50513", |
00000371 => x"738000ef", |
00000372 => x"34102573", |
00000373 => x"e91ff0ef", |
519,7 → 519,7
00000508 => x"04079663", |
00000509 => x"02041863", |
00000510 => x"ffff1537", |
00000511 => x"e6450513", |
00000511 => x"e7450513", |
00000512 => x"504000ef", |
00000513 => x"008005b7", |
00000514 => x"00040513", |
530,7 → 530,7
00000519 => x"00000513", |
00000520 => x"01c0006f", |
00000521 => x"ffff1537", |
00000522 => x"e8450513", |
00000522 => x"e9450513", |
00000523 => x"4d8000ef", |
00000524 => x"db1ff0ef", |
00000525 => x"fc0518e3", |
556,7 → 556,7
00000545 => x"00200513", |
00000546 => x"fa049ae3", |
00000547 => x"ffff1537", |
00000548 => x"e9050513", |
00000548 => x"ea050513", |
00000549 => x"470000ef", |
00000550 => x"02c12083", |
00000551 => x"02812403", |
584,7 → 584,7
00000573 => x"00112623", |
00000574 => x"ea1ff0ef", |
00000575 => x"ffff1537", |
00000576 => x"e9450513", |
00000576 => x"ea450513", |
00000577 => x"400000ef", |
00000578 => x"ad1ff0ef", |
00000579 => x"0000006f", |
672,17 → 672,17
00000661 => x"02010113", |
00000662 => x"2ac0006f", |
00000663 => x"ffff1537", |
00000664 => x"e9850513", |
00000664 => x"ea850513", |
00000665 => x"2a0000ef", |
00000666 => x"00040513", |
00000667 => x"9f9ff0ef", |
00000668 => x"ffff1537", |
00000669 => x"ea450513", |
00000669 => x"eb450513", |
00000670 => x"28c000ef", |
00000671 => x"00800537", |
00000672 => x"9e5ff0ef", |
00000673 => x"ffff1537", |
00000674 => x"ec050513", |
00000674 => x"ed050513", |
00000675 => x"278000ef", |
00000676 => x"208000ef", |
00000677 => x"00050493", |
694,7 → 694,7
00000683 => x"00300513", |
00000684 => x"975ff0ef", |
00000685 => x"ffff1537", |
00000686 => x"ecc50513", |
00000686 => x"edc50513", |
00000687 => x"01045493", |
00000688 => x"244000ef", |
00000689 => x"00148493", |
724,7 → 724,7
00000713 => x"412005b3", |
00000714 => x"e41ff0ef", |
00000715 => x"ffff1537", |
00000716 => x"e9050513", |
00000716 => x"ea050513", |
00000717 => x"f05ff06f", |
00000718 => x"00090513", |
00000719 => x"e85ff0ef", |
925,98 → 925,103
00000914 => x"52450a07", |
00000915 => x"5f524f52", |
00000916 => x"00000000", |
00000917 => x"58450a0a", |
00000918 => x"00282043", |
00000919 => x"20402029", |
00000920 => x"00007830", |
00000921 => x"69617741", |
00000922 => x"676e6974", |
00000923 => x"6f656e20", |
00000924 => x"32337672", |
00000925 => x"6578655f", |
00000926 => x"6e69622e", |
00000927 => x"202e2e2e", |
00000928 => x"00000000", |
00000929 => x"64616f4c", |
00000930 => x"2e676e69", |
00000931 => x"00202e2e", |
00000932 => x"00004b4f", |
00000933 => x"0000000a", |
00000934 => x"74697257", |
00000935 => x"78302065", |
00000936 => x"00000000", |
00000937 => x"74796220", |
00000938 => x"74207365", |
00000939 => x"5053206f", |
00000940 => x"6c662049", |
00000941 => x"20687361", |
00000942 => x"78302040", |
00000943 => x"00000000", |
00000944 => x"7928203f", |
00000945 => x"20296e2f", |
00000946 => x"00000000", |
00000947 => x"616c460a", |
00000948 => x"6e696873", |
00000949 => x"2e2e2e67", |
00000950 => x"00000020", |
00000951 => x"0a0a0a0a", |
00000952 => x"4e203c3c", |
00000953 => x"56524f45", |
00000954 => x"42203233", |
00000955 => x"6c746f6f", |
00000956 => x"6564616f", |
00000957 => x"3e3e2072", |
00000958 => x"4c420a0a", |
00000959 => x"203a5644", |
00000960 => x"2072614d", |
00000961 => x"32203332", |
00000962 => x"0a313230", |
00000963 => x"3a565748", |
00000964 => x"00002020", |
00000965 => x"4b4c430a", |
00000966 => x"0020203a", |
00000967 => x"4553550a", |
00000968 => x"00203a52", |
00000969 => x"53494d0a", |
00000970 => x"00203a41", |
00000971 => x"58455a0a", |
00000972 => x"00203a54", |
00000973 => x"4f52500a", |
00000974 => x"00203a43", |
00000975 => x"454d490a", |
00000976 => x"00203a4d", |
00000977 => x"74796220", |
00000978 => x"40207365", |
00000979 => x"00000020", |
00000980 => x"454d440a", |
00000981 => x"00203a4d", |
00000982 => x"75410a0a", |
00000983 => x"6f626f74", |
00000984 => x"6920746f", |
00000985 => x"7338206e", |
00000986 => x"7250202e", |
00000987 => x"20737365", |
00000988 => x"2079656b", |
00000989 => x"61206f74", |
00000990 => x"74726f62", |
00000991 => x"00000a2e", |
00000992 => x"726f6241", |
00000993 => x"2e646574", |
00000994 => x"00000a0a", |
00000995 => x"444d430a", |
00000996 => x"00203e3a", |
00000997 => x"53207962", |
00000998 => x"68706574", |
00000999 => x"4e206e61", |
00001000 => x"69746c6f", |
00001001 => x"0000676e", |
00001002 => x"61766e49", |
00001003 => x"2064696c", |
00001004 => x"00444d43", |
00001005 => x"33323130", |
00001006 => x"37363534", |
00001007 => x"42413938", |
00001008 => x"46454443", |
00000917 => x"00007830", |
00000918 => x"58450a0a", |
00000919 => x"54504543", |
00000920 => x"204e4f49", |
00000921 => x"7561636d", |
00000922 => x"003d6573", |
00000923 => x"70204020", |
00000924 => x"00003d63", |
00000925 => x"69617741", |
00000926 => x"676e6974", |
00000927 => x"6f656e20", |
00000928 => x"32337672", |
00000929 => x"6578655f", |
00000930 => x"6e69622e", |
00000931 => x"202e2e2e", |
00000932 => x"00000000", |
00000933 => x"64616f4c", |
00000934 => x"2e676e69", |
00000935 => x"00202e2e", |
00000936 => x"00004b4f", |
00000937 => x"0000000a", |
00000938 => x"74697257", |
00000939 => x"78302065", |
00000940 => x"00000000", |
00000941 => x"74796220", |
00000942 => x"74207365", |
00000943 => x"5053206f", |
00000944 => x"6c662049", |
00000945 => x"20687361", |
00000946 => x"78302040", |
00000947 => x"00000000", |
00000948 => x"7928203f", |
00000949 => x"20296e2f", |
00000950 => x"00000000", |
00000951 => x"616c460a", |
00000952 => x"6e696873", |
00000953 => x"2e2e2e67", |
00000954 => x"00000020", |
00000955 => x"0a0a0a0a", |
00000956 => x"4e203c3c", |
00000957 => x"56524f45", |
00000958 => x"42203233", |
00000959 => x"6c746f6f", |
00000960 => x"6564616f", |
00000961 => x"3e3e2072", |
00000962 => x"4c420a0a", |
00000963 => x"203a5644", |
00000964 => x"20727041", |
00000965 => x"32203331", |
00000966 => x"0a313230", |
00000967 => x"3a565748", |
00000968 => x"00002020", |
00000969 => x"4b4c430a", |
00000970 => x"0020203a", |
00000971 => x"4553550a", |
00000972 => x"00203a52", |
00000973 => x"53494d0a", |
00000974 => x"00203a41", |
00000975 => x"58455a0a", |
00000976 => x"00203a54", |
00000977 => x"4f52500a", |
00000978 => x"00203a43", |
00000979 => x"454d490a", |
00000980 => x"00203a4d", |
00000981 => x"74796220", |
00000982 => x"40207365", |
00000983 => x"00000020", |
00000984 => x"454d440a", |
00000985 => x"00203a4d", |
00000986 => x"75410a0a", |
00000987 => x"6f626f74", |
00000988 => x"6920746f", |
00000989 => x"3828206e", |
00000990 => x"202e7329", |
00000991 => x"73657250", |
00000992 => x"656b2073", |
00000993 => x"6f742079", |
00000994 => x"6f626120", |
00000995 => x"0a2e7472", |
00000996 => x"00000000", |
00000997 => x"726f6241", |
00000998 => x"2e646574", |
00000999 => x"00000a0a", |
00001000 => x"444d430a", |
00001001 => x"00203e3a", |
00001002 => x"53207962", |
00001003 => x"68706574", |
00001004 => x"4e206e61", |
00001005 => x"69746c6f", |
00001006 => x"0000676e", |
00001007 => x"61766e49", |
00001008 => x"2064696c", |
00001009 => x"00444d43", |
00001010 => x"33323130", |
00001011 => x"37363534", |
00001012 => x"62613938", |
00001013 => x"66656463", |
others => x"00000000" |
); |
|
/neorv32/trunk/rtl/core/neorv32_cpu.vhd
11,7 → 11,7
-- # * neorv32_cpu_ctrl.vhd - CPU control and CSR system # |
-- # * neorv32_cpu_decompressor.vhd - Compressed instructions decoder # |
-- # * neorv32_cpu_regfile.vhd - Data register file # |
-- # * neorv32_package.vhd - Main CPU/processor package file # |
-- # * neorv32_package.vhd - Main CPU & Processor package file # |
-- # # |
-- # Check out the processor's data sheet for more information: docs/NEORV32.pdf # |
-- # ********************************************************************************************* # |
72,11 → 72,14
-- Extension Options -- |
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
TINY_SHIFT_EN : boolean := false; -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29) |
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH : natural := 40 -- total size of HPM counters (1..64) |
); |
port ( |
-- global control -- |
167,12 → 170,20
|
-- Sanity Checks -------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- hardware reset notifier -- |
assert not ((dedicated_reset_c = false) and (def_rst_val_c = '-')) report "NEORV32 CPU CONFIG NOTE: Using NO dedicated hardware reset for uncritical registers (default, might reduce area footprint). Set the package constant <dedicated_reset_c> to TRUE if you need a defined reset value." severity note; |
assert not ((dedicated_reset_c = true) and (def_rst_val_c = '0')) report "NEORV32 CPU CONFIG NOTE: Using defined hardware reset for uncritical registers (non-default, reset-to-zero, might increase area footprint)." severity note; |
assert not ((def_rst_val_c /= '-') and (def_rst_val_c /= '0')) report "NEORV32 CPU CONFIG ERROR! Invalid configuration of package <def_rst_val_c> constant (has to be '-' or '0')." severity error; |
|
-- CSR system -- |
assert not (CPU_EXTENSION_RISCV_Zicsr = false) report "NEORV32 CPU CONFIG WARNING! No exception/interrupt/trap/privileged features available when CPU_EXTENSION_RISCV_Zicsr = false." severity warning; |
assert not (CPU_EXTENSION_RISCV_Zicsr = false) report "NEORV32 CPU CONFIG WARNING! No exception/interrupt/trap/privileged features available when <CPU_EXTENSION_RISCV_Zicsr> = false." severity warning; |
|
-- CPU counters (cycle and instret) -- |
assert not ((CPU_CNT_WIDTH < 0) or (CPU_CNT_WIDTH > 64)) report "NEORV32 CPU CONFIG ERROR! Invalid <CPU_CNT_WIDTH> configuration. Has to be 0..64." severity error; |
assert not (CPU_CNT_WIDTH < 64) report "NEORV32 CPU CONFIG WARNING! Implementing CPU <cycle> and <instret> CSRs with reduced size (" & integer'image(CPU_CNT_WIDTH) & "-bit instead of 64-bit). This is not RISC-V compliant and might have unintended SW side effects." severity warning; |
|
-- U-extension requires Zicsr extension -- |
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_U = true)) report "NEORV32 CPU CONFIG ERROR! User mode requires CPU_EXTENSION_RISCV_Zicsr extension." severity error; |
-- PMP requires Zicsr extension -- |
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! Physical memory protection (PMP) requires CPU_EXTENSION_RISCV_Zicsr extension." severity error; |
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_U = true)) report "NEORV32 CPU CONFIG ERROR! User mode requires <CPU_EXTENSION_RISCV_Zicsr> extension to be enabled." severity error; |
|
-- Bus timeout -- |
assert not (BUS_TIMEOUT < 2) report "NEORV32 CPU CONFIG ERROR! Invalid bus access timeout value <BUS_TIMEOUT>. Has to be >= 2." severity error; |
183,7 → 194,7
assert not (CPU_EXTENSION_RISCV_A = true) report "NEORV32 CPU CONFIG WARNING! Atomic operations extension (A) only supports <lr.w> and <sc.w> instructions." severity warning; |
|
-- FIXME: Bit manipulation warning -- |
assert not (CPU_EXTENSION_RISCV_B = true) report "NEORV32 CPU CONFIG WARNING! Bit manipulation extension (B) is still HIGHLY EXPERIMENTAL (and spec. is not ratified yet)." severity warning; |
assert not (CPU_EXTENSION_RISCV_B = true) report "NEORV32 CPU CONFIG WARNING! Bit manipulation extension (B) is still EXPERIMENTAL (and spec. is not ratified yet)." severity warning; |
|
-- Co-processor timeout counter (for debugging only) -- |
assert not (cp_timeout_en_c = true) report "NEORV32 CPU CONFIG WARNING! Co-processor timeout counter enabled. This should be used for debugging/simulation only." severity warning; |
191,17 → 202,20
-- PMP regions check -- |
assert not (PMP_NUM_REGIONS > 64) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions <PMP_NUM_REGIONS> out xf valid range (0..64)." severity error; |
-- PMP granulartiy -- |
assert not ((is_power_of_two_f(PMP_MIN_GRANULARITY) = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! PMP granulartiy has to be a power of two." severity error; |
assert not ((PMP_MIN_GRANULARITY < 8) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! PMP granulartiy has to be >= 8 bytes." severity error; |
assert not ((is_power_of_two_f(PMP_MIN_GRANULARITY) = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! <PMP_MIN_GRANULARITY> has to be a power of two." severity error; |
assert not ((PMP_MIN_GRANULARITY < 8) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! <PMP_MIN_GRANULARITY> has to be >= 8 bytes." severity error; |
-- PMP notifier -- |
assert not (PMP_NUM_REGIONS > 0) report "NEORV32 CPU CONFIG NOTE: Implementing physical memory protection (PMP) with " & integer'image(PMP_NUM_REGIONS) & " regions and a minimal granularity of " & integer'image(PMP_MIN_GRANULARITY) & " bytes." severity note; |
-- PMP requires Zicsr extension -- |
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_NUM_REGIONS > 0)) report "NEORV32 CPU CONFIG ERROR! Physical memory protection (PMP) requires <CPU_EXTENSION_RISCV_Zicsr> extension to be enabled." severity error; |
|
-- HPM counters check -- |
assert not (HPM_NUM_CNTS > 29) report "NEORV32 CPU CONFIG ERROR! Number of HPM counters <HPM_NUM_CNTS> out of valid range (0..29)." severity error; |
assert not ((HPM_CNT_WIDTH < 1) or (HPM_CNT_WIDTH > 64)) report "NEORV32 CPU CONFIG ERROR! HPM counter width <HPM_CNT_WIDTH> has to be 1..64 bit." severity error; |
-- HPM counters notifier -- |
assert not (HPM_NUM_CNTS > 0) report "NEORV32 CPU CONFIG NOTE: Implementing " & integer'image(HPM_NUM_CNTS) & " HPM counters." severity note; |
assert not (HPM_NUM_CNTS > 0) report "NEORV32 CPU CONFIG NOTE: Implementing " & integer'image(HPM_NUM_CNTS) & " HPM counters (each " & integer'image(HPM_CNT_WIDTH) & "-bit wide)." severity note; |
-- HPM CNT requires Zicsr extension -- |
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (HPM_NUM_CNTS > 0)) report "NEORV32 CPU CONFIG ERROR! Performance monitors (HMP) require CPU_EXTENSION_RISCV_Zicsr extension." severity error; |
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (HPM_NUM_CNTS > 0)) report "NEORV32 CPU CONFIG ERROR! Hardware performance monitors (HPM) require <CPU_EXTENSION_RISCV_Zicsr> extension to be enabled." severity error; |
|
|
-- Control Unit --------------------------------------------------------------------------- |
220,11 → 234,14
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!) |
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.? |
-- Extension Options -- |
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64) |
-- Physical memory protection (PMP) -- |
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64) |
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS => HPM_NUM_CNTS -- number of implemented HPM counters (0..29) |
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH => HPM_CNT_WIDTH -- total size of HPM counters |
) |
port map ( |
-- global control -- |
299,7 → 316,8
neorv32_cpu_alu_inst: neorv32_cpu_alu |
generic map ( |
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension? |
FAST_SHIFT_EN => FAST_SHIFT_EN -- use barrel shifter for shift operations |
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations |
TINY_SHIFT_EN => TINY_SHIFT_EN -- use tiny (single-bit) shifter for shift operations |
) |
port map ( |
-- global control -- |
357,9 → 375,13
-- ------------------------------------------------------------------------------------------- |
-- "pseudo" co-processor for atomic operations |
-- required to get the result of a store-conditional operation into the data path |
atomic_op_cp: process(clk_i) |
atomic_op_cp: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
atomic_sc_val <= def_rst_val_c; |
atomic_sc_res <= def_rst_val_c; |
atomic_sc_res_ff <= def_rst_val_c; |
elsif rising_edge(clk_i) then |
atomic_sc_val <= cp_start(1); |
atomic_sc_res <= bus_excl_ok; |
if (atomic_sc_val = '1') then |
407,7 → 429,7
-- Co-Processor 3: CSR (Read) Access ('Zicsr' Extension) ---------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- "pseudo" co-processor for CSR *read* access operations |
-- required to get the CSR read data into the data path |
-- required to get CSR read data into the data path |
cp_result(3) <= csr_rdata when (CPU_EXTENSION_RISCV_Zicsr = true) else (others => '0'); |
cp_valid(3) <= cp_start(3); -- always assigned even if Zicsr extension is disabled to make sure CPU does not get stalled if there is an accidental access |
|
425,6 → 447,7
start_i => cp_start(4), -- trigger operation |
-- data input -- |
frm_i => fpu_rm, -- rounding mode |
cmp_i => comparator, -- comparator status |
rs1_i => rs1, -- rf source 1 |
rs2_i => rs2, -- rf source 2 |
-- result and status -- |
442,7 → 465,7
end generate; |
|
|
-- Co-Processor 5..7: Not Implemented Yet ------------------------------------------------- |
-- Co-Processor 5,6,7: Not Implemented Yet ------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
cp_result(5) <= (others => '0'); |
cp_valid(5) <= '0'; |
/neorv32/trunk/rtl/core/neorv32_cpu_alu.vhd
43,8 → 43,9
|
entity neorv32_cpu_alu is |
generic ( |
CPU_EXTENSION_RISCV_M : boolean := true; -- implement muld/div extension? |
FAST_SHIFT_EN : boolean := false -- use barrel shifter for shift operations |
CPU_EXTENSION_RISCV_M : boolean := true; -- implement muld/div extension? |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
TINY_SHIFT_EN : boolean := false -- use tiny (single-bit) shifter for shift operations |
); |
port ( |
-- global control -- |
176,7 → 177,8
shifter.cnt <= opb(index_size_f(data_width_c)-1 downto 0); -- shift amount |
elsif (shifter.run = '1') then -- running shift |
-- coarse shift: multiples of 4 -- |
if (or_all_f(shifter.cnt(shifter.cnt'left downto 2)) = '1') then -- shift amount >= 4 |
if (TINY_SHIFT_EN = false) and -- use coarse shifts first if TINY SHIFT option is NOT enabled |
(or_all_f(shifter.cnt(shifter.cnt'left downto 2)) = '1') then -- shift amount >= 4 |
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 4); |
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical |
shifter.sreg <= shifter.sreg(shifter.sreg'left-4 downto 0) & "0000"; |
186,7 → 188,7
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & |
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 4); |
end if; |
-- fine shift: single shifts, 0..3 times -- |
-- fine shift: single shifts, 0..3 times; use ONLY single-bit shifts if TINY_SHIFT_EN is enabled (even smaller than the default approach) -- |
else |
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 1); |
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical |
/neorv32/trunk/rtl/core/neorv32_cpu_bus.vhd
179,9 → 179,11
|
-- Data Interface: Access Address --------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
mem_adr_reg: process(clk_i) |
mem_adr_reg: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
mar <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (ctrl_i(ctrl_bus_mo_we_c) = '1') then |
mar <= addr_i; |
end if; |
213,9 → 215,11
|
-- Data Interface: Write Data ------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
mem_do_reg: process(clk_i) |
mem_do_reg: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
mdo <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (ctrl_i(ctrl_bus_mo_we_c) = '1') then |
mdo <= wdata_i; -- memory data output register (MDO) |
end if; |
254,9 → 258,11
|
-- Data Interface: Read Data -------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
mem_out_buf: process(clk_i) |
mem_out_buf: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
mdi <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (ctrl_i(ctrl_bus_mi_we_c) = '1') then |
mdi <= d_bus_rdata; -- memory data input register (MDI) |
end if; |
442,9 → 448,11
-- Physical Memory Protection (PMP) ------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- compute address masks (ITERATIVE!!!) -- |
pmp_masks: process(clk_i) |
pmp_masks: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then -- address mask computation (not the actual address check!) has a latency of max +32 cycles |
if (rstn_i = '0') then |
pmp.addr_mask <= (others => (others => def_rst_val_c)); |
elsif rising_edge(clk_i) then -- address mask computation (not the actual address check!) has a latency of max +32 cycles |
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions |
pmp.addr_mask(r) <= (others => '0'); |
for i in pmp_g_c to data_width_c-1 loop |
/neorv32/trunk/rtl/core/neorv32_cpu_control.vhd
60,11 → 60,14
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!) |
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.? |
-- Extension Options -- |
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64) |
-- Physical memory protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29) |
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH : natural := 40 -- total size of HPM counters (1..64) |
); |
port ( |
-- global control -- |
113,6 → 116,14
|
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is |
|
-- CPU core counter ([m]cycle, [m]instret) width - high/low parts -- |
constant cpu_cnt_lo_width_c : natural := natural(cond_sel_int_f(boolean(CPU_CNT_WIDTH < 32), CPU_CNT_WIDTH, 32)); |
constant cpu_cnt_hi_width_c : natural := natural(cond_sel_int_f(boolean(CPU_CNT_WIDTH > 32), CPU_CNT_WIDTH-32, 0)); |
|
-- HPM counter width - high/low parts -- |
constant hpm_cnt_lo_width_c : natural := natural(cond_sel_int_f(boolean(HPM_CNT_WIDTH < 32), HPM_CNT_WIDTH, 32)); |
constant hpm_cnt_hi_width_c : natural := natural(cond_sel_int_f(boolean(HPM_CNT_WIDTH > 32), HPM_CNT_WIDTH-32, 0)); |
|
-- instruction fetch enginge -- |
type fetch_engine_state_t is (IFETCH_RESET, IFETCH_REQUEST, IFETCH_ISSUE); |
type fetch_engine_t is record |
254,10 → 265,10
type pmp_ctrl_rd_t is array (0 to 63) of std_ulogic_vector(7 downto 0); |
type pmp_addr_rd_t is array (0 to 63) of std_ulogic_vector(data_width_c-1 downto 0); |
type mhpmevent_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0); |
type mhpmcnt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(32 downto 0); |
type mhpmcnth_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(31 downto 0); |
type mhpmcnt_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(32 downto 0); -- 32-bit, plus 1-bit overflow |
type mhpmcnth_t is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(31 downto 0); -- 32-bit |
type mhpmevent_rd_t is array (0 to 29) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0); |
type mhpmcnt_rd_t is array (0 to 29) of std_ulogic_vector(32 downto 0); |
type mhpmcnt_rd_t is array (0 to 29) of std_ulogic_vector(31 downto 0); |
type mhpmcnth_rd_t is array (0 to 29) of std_ulogic_vector(31 downto 0); |
type csr_t is record |
addr : std_ulogic_vector(11 downto 0); -- csr address |
302,9 → 313,9
mhpmevent_rd : mhpmevent_rd_t; -- mhpmevent*: actual read data |
-- |
mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W) |
-- |
mcycle : std_ulogic_vector(32 downto 0); -- mcycle (R/W), plus carry bit |
minstret : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit |
-- |
mcycleh : std_ulogic_vector(31 downto 0); -- mcycleh (R/W) |
minstreth : std_ulogic_vector(31 downto 0); -- minstreth (R/W) |
-- |
344,7 → 355,7
begin |
|
-- **************************************************************************************************************************** |
-- Instruction Fetch (always fetches aligned 32-bit chunks of data) |
-- Instruction Fetch (always fetch 32-bit-aligned 32-bit chunks of data) |
-- **************************************************************************************************************************** |
|
-- Fetch Engine FSM Sync ------------------------------------------------------------------ |
354,7 → 365,7
if (rstn_i = '0') then |
fetch_engine.state <= IFETCH_RESET; |
fetch_engine.state_prev <= IFETCH_RESET; |
fetch_engine.pc <= (others => '0'); |
fetch_engine.pc <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (fetch_engine.reset = '1') then |
fetch_engine.state <= IFETCH_RESET; |
425,9 → 436,12
|
-- Instruction Prefetch Buffer (FIFO) ----------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
instr_prefetch_buffer: process(clk_i) |
instr_prefetch_buffer_ctrl: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
ipb.w_pnt <= (others => def_rst_val_c); |
ipb.r_pnt <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
-- write port -- |
if (ipb.clear = '1') then |
ipb.w_pnt <= (others => '0'); |
434,9 → 448,6
elsif (ipb.we = '1') then |
ipb.w_pnt <= std_ulogic_vector(unsigned(ipb.w_pnt) + 1); |
end if; |
if (ipb.we = '1') then -- write data |
ipb.data(to_integer(unsigned(ipb.w_pnt(ipb.w_pnt'left-1 downto 0)))) <= ipb.wdata; |
end if; |
-- read port -- |
if (ipb.clear = '1') then |
ipb.r_pnt <= (others => '0'); |
444,8 → 455,17
ipb.r_pnt <= std_ulogic_vector(unsigned(ipb.r_pnt) + 1); |
end if; |
end if; |
end process instr_prefetch_buffer; |
end process instr_prefetch_buffer_ctrl; |
|
instr_prefetch_buffer_data: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (ipb.we = '1') then -- write access |
ipb.data(to_integer(unsigned(ipb.w_pnt(ipb.w_pnt'left-1 downto 0)))) <= ipb.wdata; |
end if; |
end if; |
end process instr_prefetch_buffer_data; |
|
-- async read -- |
ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.r_pnt'left-1 downto 0)))); |
|
468,7 → 488,7
if (rstn_i = '0') then |
issue_engine.state <= ISSUE_ACTIVE; |
issue_engine.align <= CPU_BOOT_ADDR(1); -- 32- or 16-bit boundary |
issue_engine.buf <= (others => '0'); |
issue_engine.buf <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (ipb.clear = '1') then |
if (CPU_EXTENSION_RISCV_C = true) then |
592,11 → 612,13
|
-- Immediate Generator -------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
imm_gen: process(execute_engine.i_reg, clk_i) |
imm_gen: process(execute_engine.i_reg, rstn_i, clk_i) |
variable opcode_v : std_ulogic_vector(6 downto 0); |
begin |
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
imm_o <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (execute_engine.state = BRANCH) then -- next_PC as immediate for jump-and-link operations (=return address) via ALU.MOV_B |
imm_o <= execute_engine.next_pc; |
else -- "normal" immediate from instruction word |
657,14 → 679,26
|
-- Execute Engine FSM Sync ---------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- for registers that DO require a specific reset state -- |
execute_engine_fsm_sync_rst: process(rstn_i, clk_i) |
execute_engine_fsm_sync: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
-- registers that DO require a specific reset state -- |
execute_engine.pc <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0'; |
execute_engine.state <= SYS_WAIT; |
execute_engine.sleep <= '0'; |
execute_engine.branched <= '1'; -- reset is a branch from "somewhere" |
-- no dedicated RESEt required -- |
execute_engine.state_prev <= SYS_WAIT; |
execute_engine.i_reg <= (others => def_rst_val_c); |
execute_engine.is_ci <= def_rst_val_c; |
execute_engine.is_cp_op <= def_rst_val_c; |
execute_engine.last_pc <= (others => def_rst_val_c); |
execute_engine.i_reg_last <= (others => def_rst_val_c); |
execute_engine.next_pc <= (others => def_rst_val_c); |
ctrl <= (others => def_rst_val_c); |
-- |
ctrl(ctrl_bus_rd_c) <= '0'; |
ctrl(ctrl_bus_wr_c) <= '0'; |
elsif rising_edge(clk_i) then |
-- PC update -- |
if (execute_engine.pc_we = '1') then |
678,14 → 712,7
execute_engine.state <= execute_engine.state_nxt; |
execute_engine.sleep <= execute_engine.sleep_nxt; |
execute_engine.branched <= execute_engine.branched_nxt; |
end if; |
end process execute_engine_fsm_sync_rst; |
|
|
-- for registers that do NOT require a specific reset state -- |
execute_engine_fsm_sync: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- |
execute_engine.state_prev <= execute_engine.state; |
execute_engine.i_reg <= execute_engine.i_reg_nxt; |
execute_engine.is_ci <= execute_engine.is_ci_nxt; |
707,6 → 734,7
end if; |
end process execute_engine_fsm_sync; |
|
|
-- PC increment for next linear instruction (+2 for compressed instr., +4 otherwise) -- |
execute_engine.next_pc_inc <= x"00000004" when ((execute_engine.is_ci = '0') or (CPU_EXTENSION_RISCV_C = false)) else x"00000002"; |
|
1139,7 → 1167,6
when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back) |
-- cp access or alu.shift? -- |
if (execute_engine.is_cp_op = '1') then |
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; |
1148,7 → 1175,8
end if; |
-- wait for result -- |
if (alu_wait_i = '0') then |
execute_engine.state_nxt <= DISPATCH; |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
execute_engine.state_nxt <= DISPATCH; |
end if; |
|
|
1266,7 → 1294,7
csr_access_check: process(execute_engine.i_reg, csr) |
variable csr_wacc_v : std_ulogic; -- to check access to read-only CSRs |
-- variable csr_racc_v : std_ulogic; -- to check access to write-only CSRs |
variable csr_mcounteren_hpm_v : std_ulogic_vector(28 downto 0); -- max 29 HPM counters |
variable csr_mcounteren_hpm_v : std_ulogic_vector(31 downto 0); -- max 29 HPM counters, plus 3 LSB-aligned dummy bits |
begin |
-- is this CSR instruction really going to write/read to/from a CSR? -- |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or |
1280,8 → 1308,8
|
-- low privilege level access to hpm counters? -- |
csr_mcounteren_hpm_v := (others => '0'); |
if (CPU_EXTENSION_RISCV_U = true) then |
csr_mcounteren_hpm_v(HPM_NUM_CNTS-1 downto 0) := csr.mcounteren_hpm(HPM_NUM_CNTS-1 downto 0); |
if (CPU_EXTENSION_RISCV_U = true) and (HPM_NUM_CNTS /= 0) then |
csr_mcounteren_hpm_v(3+(HPM_NUM_CNTS-1) downto 3+0) := csr.mcounteren_hpm(HPM_NUM_CNTS-1 downto 0); |
else -- 'mcounteren' CSR is hardwired to zero if user mode is not implemented |
csr_mcounteren_hpm_v := (others => '0'); |
end if; |
1288,25 → 1316,25
|
-- check CSR access -- |
case csr.addr is |
-- standard read/write CSRs -- |
when csr_fflags_c | csr_frm_c | csr_fcsr_c => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if Zfinx extension is enabled |
-- |
when csr_mstatus_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mstatush_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_misa_c => csr_acc_valid <= csr.priv_m_mode;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility |
when csr_mie_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mtvec_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mscratch_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mepc_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mcause_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mcounteren_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mtval_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_mip_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
-- |
|
-- user floating-point CSRs -- |
when csr_fflags_c | csr_frm_c | csr_fcsr_c => |
csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if Zfinx extension is implemented |
|
-- machine trap setup -- |
when csr_mstatus_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mcounteren_c | csr_mstatush_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only, NOTE: MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility |
|
-- machine trap handling -- |
when csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mtval_c | csr_mip_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
|
-- physical memory protection - configuration -- |
when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c | |
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
-- |
|
-- physical memory protection - address -- |
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c | |
csr_pmpaddr8_c | csr_pmpaddr9_c | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c | |
csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c | |
1316,9 → 1344,58
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c | |
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
-- |
when csr_mcountinhibit_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
-- |
|
-- machine counters/timers -- |
when csr_mcycle_c => |
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(cpu_cnt_lo_width_c > 0)); -- M-mode only, access if implemented |
when csr_mcycleh_c => |
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode only, access if implemented |
when csr_minstret_c => |
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(cpu_cnt_lo_width_c > 0)); -- M-mode only, access if implemented |
when csr_minstreth_c => |
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode only, access if implemented |
|
when csr_mhpmcounter3_c | csr_mhpmcounter4_c | csr_mhpmcounter5_c | csr_mhpmcounter6_c | csr_mhpmcounter7_c | csr_mhpmcounter8_c | -- LOW |
csr_mhpmcounter9_c | csr_mhpmcounter10_c | csr_mhpmcounter11_c | csr_mhpmcounter12_c | csr_mhpmcounter13_c | csr_mhpmcounter14_c | |
csr_mhpmcounter15_c | csr_mhpmcounter16_c | csr_mhpmcounter17_c | csr_mhpmcounter18_c | csr_mhpmcounter19_c | csr_mhpmcounter20_c | |
csr_mhpmcounter21_c | csr_mhpmcounter22_c | csr_mhpmcounter23_c | csr_mhpmcounter24_c | csr_mhpmcounter25_c | csr_mhpmcounter26_c | |
csr_mhpmcounter27_c | csr_mhpmcounter28_c | csr_mhpmcounter29_c | csr_mhpmcounter30_c | csr_mhpmcounter31_c | |
csr_mhpmcounter3h_c | csr_mhpmcounter4h_c | csr_mhpmcounter5h_c | csr_mhpmcounter6h_c | csr_mhpmcounter7h_c | csr_mhpmcounter8h_c | -- HIGH |
csr_mhpmcounter9h_c | csr_mhpmcounter10h_c | csr_mhpmcounter11h_c | csr_mhpmcounter12h_c | csr_mhpmcounter13h_c | csr_mhpmcounter14h_c | |
csr_mhpmcounter15h_c | csr_mhpmcounter16h_c | csr_mhpmcounter17h_c | csr_mhpmcounter18h_c | csr_mhpmcounter19h_c | csr_mhpmcounter20h_c | |
csr_mhpmcounter21h_c | csr_mhpmcounter22h_c | csr_mhpmcounter23h_c | csr_mhpmcounter24h_c | csr_mhpmcounter25h_c | csr_mhpmcounter26h_c | |
csr_mhpmcounter27h_c | csr_mhpmcounter28h_c | csr_mhpmcounter29h_c | csr_mhpmcounter30h_c | csr_mhpmcounter31h_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
|
-- user counters/timers -- |
when csr_cycle_c => |
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy) and bool_to_ulogic_f(boolean(cpu_cnt_lo_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented |
when csr_cycleh_c => |
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy) and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented |
when csr_instret_c => |
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir) and bool_to_ulogic_f(boolean(cpu_cnt_lo_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented |
when csr_instreth_c => |
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir) and bool_to_ulogic_f(boolean(cpu_cnt_hi_width_c > 0)); -- M-mode, U-mode if authorized, read-only, access if implemented |
|
when csr_time_c | csr_timeh_c => |
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only |
|
when csr_hpmcounter3_c | csr_hpmcounter4_c | csr_hpmcounter5_c | csr_hpmcounter6_c | csr_hpmcounter7_c | csr_hpmcounter8_c | -- LOW |
csr_hpmcounter9_c | csr_hpmcounter10_c | csr_hpmcounter11_c | csr_hpmcounter12_c | csr_hpmcounter13_c | csr_hpmcounter14_c | |
csr_hpmcounter15_c | csr_hpmcounter16_c | csr_hpmcounter17_c | csr_hpmcounter18_c | csr_hpmcounter19_c | csr_hpmcounter20_c | |
csr_hpmcounter21_c | csr_hpmcounter22_c | csr_hpmcounter23_c | csr_hpmcounter24_c | csr_hpmcounter25_c | csr_hpmcounter26_c | |
csr_hpmcounter27_c | csr_hpmcounter28_c | csr_hpmcounter29_c | csr_hpmcounter30_c | csr_hpmcounter31_c | |
csr_hpmcounter3h_c | csr_hpmcounter4h_c | csr_hpmcounter5h_c | csr_hpmcounter6h_c | csr_hpmcounter7h_c | csr_hpmcounter8h_c | -- HIGH |
csr_hpmcounter9h_c | csr_hpmcounter10h_c | csr_hpmcounter11h_c | csr_hpmcounter12h_c | csr_hpmcounter13h_c | csr_hpmcounter14h_c | |
csr_hpmcounter15h_c | csr_hpmcounter16h_c | csr_hpmcounter17h_c | csr_hpmcounter18h_c | csr_hpmcounter19h_c | csr_hpmcounter20h_c | |
csr_hpmcounter21h_c | csr_hpmcounter22h_c | csr_hpmcounter23h_c | csr_hpmcounter24h_c | csr_hpmcounter25h_c | csr_hpmcounter26h_c | |
csr_hpmcounter27h_c | csr_hpmcounter28h_c | csr_hpmcounter29h_c | csr_hpmcounter30h_c | csr_hpmcounter31h_c => |
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(to_integer(unsigned(csr.addr(4 downto 0))))); -- M-mode, U-mode if authorized, read-only |
|
-- machine counter setup -- |
when csr_mcountinhibit_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
|
when csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c | csr_mhpmevent8_c | |
csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c | |
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c | |
1325,104 → 1402,16
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c | |
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
-- |
when csr_mcycle_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_minstret_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
-- |
when csr_mhpmcounter3_c | csr_mhpmcounter4_c | csr_mhpmcounter5_c | csr_mhpmcounter6_c | csr_mhpmcounter7_c | csr_mhpmcounter8_c | |
csr_mhpmcounter9_c | csr_mhpmcounter10_c | csr_mhpmcounter11_c | csr_mhpmcounter12_c | csr_mhpmcounter13_c | csr_mhpmcounter14_c | |
csr_mhpmcounter15_c | csr_mhpmcounter16_c | csr_mhpmcounter17_c | csr_mhpmcounter18_c | csr_mhpmcounter19_c | csr_mhpmcounter20_c | |
csr_mhpmcounter21_c | csr_mhpmcounter22_c | csr_mhpmcounter23_c | csr_mhpmcounter24_c | csr_mhpmcounter25_c | csr_mhpmcounter26_c | |
csr_mhpmcounter27_c | csr_mhpmcounter28_c | csr_mhpmcounter29_c | csr_mhpmcounter30_c | csr_mhpmcounter31_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
-- |
when csr_mcycleh_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
when csr_minstreth_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
-- |
when csr_mhpmcounter3h_c | csr_mhpmcounter4h_c | csr_mhpmcounter5h_c | csr_mhpmcounter6h_c | csr_mhpmcounter7h_c | csr_mhpmcounter8h_c | |
csr_mhpmcounter9h_c | csr_mhpmcounter10h_c | csr_mhpmcounter11h_c | csr_mhpmcounter12h_c | csr_mhpmcounter13h_c | csr_mhpmcounter14h_c | |
csr_mhpmcounter15h_c | csr_mhpmcounter16h_c | csr_mhpmcounter17h_c | csr_mhpmcounter18h_c | csr_mhpmcounter19h_c | csr_mhpmcounter20h_c | |
csr_mhpmcounter21h_c | csr_mhpmcounter22h_c | csr_mhpmcounter23h_c | csr_mhpmcounter24h_c | csr_mhpmcounter25h_c | csr_mhpmcounter26h_c | |
csr_mhpmcounter27h_c | csr_mhpmcounter28h_c | csr_mhpmcounter29h_c | csr_mhpmcounter30h_c | csr_mhpmcounter31h_c => |
csr_acc_valid <= csr.priv_m_mode; -- M-mode only |
|
-- standard read-only CSRs -- |
when csr_cycle_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- M-mode, U-mode if authorized, read-only |
when csr_time_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only |
when csr_instret_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- M-mode, U-mode if authorized, read-only |
-- |
when csr_hpmcounter3_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(00)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter4_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(01)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter5_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(02)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter6_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(03)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter7_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(04)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter8_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(05)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter9_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(06)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter10_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(07)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter11_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(08)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter12_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(09)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter13_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(10)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter14_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(11)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter15_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(12)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter16_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(13)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter17_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(14)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter18_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(15)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter19_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(16)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter20_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(17)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter21_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(18)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter22_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(19)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter23_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(20)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter24_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(21)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter25_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(22)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter26_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(23)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter27_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(24)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter28_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(25)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter29_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(26)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter30_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(27)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter31_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(28)); -- M-mode, U-mode if authorized, read-only |
-- |
when csr_cycleh_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- M-mode, U-mode if authorized, read-only |
when csr_timeh_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only |
when csr_instreth_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- M-mode, U-mode if authorized, read-only |
-- |
when csr_hpmcounter3h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(00)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter4h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(01)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter5h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(02)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter6h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(03)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter7h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(04)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter8h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(05)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter9h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(06)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter10h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(07)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter11h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(08)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter12h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(09)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter13h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(10)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter14h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(11)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter15h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(12)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter16h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(13)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter17h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(14)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter18h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(15)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter19h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(16)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter20h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(17)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter21h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(18)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter22h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(19)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter23h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(20)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter24h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(21)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter25h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(22)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter26h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(23)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter27h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(24)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter28h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(25)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter29h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(26)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter30h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(27)); -- M-mode, U-mode if authorized, read-only |
when csr_hpmcounter31h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(28)); -- M-mode, U-mode if authorized, read-only |
-- |
when csr_mvendorid_c => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only |
when csr_marchid_c => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only |
when csr_mimpid_c => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only |
when csr_mhartid_c => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only |
-- custom read-only CSRs -- |
when csr_mzext_c => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only |
-- |
when others => csr_acc_valid <= '0'; -- invalid access |
-- machine information registers -- |
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c => |
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only |
-- custom (NEORV32-specific) read-only CSRs -- |
when csr_mzext_c => |
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only |
-- undefined / not implemented -- |
when others => |
csr_acc_valid <= '0'; -- invalid access |
end case; |
end process csr_access_check; |
|
1658,12 → 1647,12
begin |
if (rstn_i = '0') then |
trap_ctrl.exc_buf <= (others => '0'); |
trap_ctrl.irq_buf <= (others => '0'); |
trap_ctrl.irq_buf <= (others => def_rst_val_c); |
trap_ctrl.exc_ack <= '0'; |
trap_ctrl.irq_ack <= (others => '0'); |
trap_ctrl.env_start <= '0'; |
trap_ctrl.cause <= trap_reset_c; |
trap_ctrl.firq_sync <= (others => '0'); |
trap_ctrl.cause <= (others => def_rst_val_c); |
trap_ctrl.firq_sync <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (CPU_EXTENSION_RISCV_Zicsr = true) then |
-- exception buffer: misaligned load/store/instruction address |
1910,49 → 1899,51
-- ------------------------------------------------------------------------------------------- |
csr_write_access: process(rstn_i, clk_i) |
begin |
-- NOTE: Register that reset to "def_rst_val_c" do NOT actually have a real reset by default (def_rst_val_c = '-') and have to be |
-- explicitly initialized by software! |
-- see: https://forums.xilinx.com/t5/General-Technical-Discussion/quot-Don-t-care-quot-reset-value/td-p/412845 |
if (rstn_i = '0') then |
csr.we <= '0'; |
-- |
csr.mstatus_mie <= '0'; |
csr.mstatus_mpie <= '0'; |
csr.mstatus_mpp <= priv_mode_m_c; -- start in MACHINE mode |
csr.mstatus_mpp <= (others => '0'); |
csr.privilege <= priv_mode_m_c; -- start in MACHINE mode |
csr.mie_msie <= '0'; |
csr.mie_meie <= '0'; |
csr.mie_mtie <= '0'; |
csr.mie_firqe <= (others => '0'); |
csr.mtvec <= (others => '0'); |
csr.mscratch <= x"19880704"; -- :) |
csr.mepc <= (others => '0'); |
csr.mcause <= trap_reset_c; -- mcause = TRAP_CODE_RESET (hardware reset, "non-maskable interrupt") |
csr.mtval <= (others => '0'); |
csr.mip_clear <= (others => '0'); |
csr.mie_msie <= def_rst_val_c; |
csr.mie_meie <= def_rst_val_c; |
csr.mie_mtie <= def_rst_val_c; |
csr.mie_firqe <= (others => def_rst_val_c); |
csr.mtvec <= (others => def_rst_val_c); |
csr.mscratch <= x"19880704"; |
csr.mepc <= (others => def_rst_val_c); |
csr.mcause <= (others => def_rst_val_c); |
csr.mtval <= (others => def_rst_val_c); |
csr.mip_clear <= (others => def_rst_val_c); |
-- |
csr.pmpcfg <= (others => (others => '0')); |
csr.pmpaddr <= (others => (others => '1')); |
csr.pmpaddr <= (others => (others => def_rst_val_c)); |
-- |
csr.mhpmevent <= (others => (others => '0')); |
csr.mhpmevent <= (others => (others => def_rst_val_c)); |
-- |
csr.mcounteren_cy <= '0'; |
csr.mcounteren_tm <= '0'; |
csr.mcounteren_ir <= '0'; |
csr.mcounteren_hpm <= (others => '0'); |
csr.mcounteren_cy <= def_rst_val_c; |
csr.mcounteren_tm <= def_rst_val_c; |
csr.mcounteren_ir <= def_rst_val_c; |
csr.mcounteren_hpm <= (others => def_rst_val_c); |
-- |
csr.mcountinhibit_cy <= '0'; |
csr.mcountinhibit_ir <= '0'; |
csr.mcountinhibit_hpm <= (others => '0'); |
csr.mcountinhibit_cy <= def_rst_val_c; |
csr.mcountinhibit_ir <= def_rst_val_c; |
csr.mcountinhibit_hpm <= (others => def_rst_val_c); |
-- |
csr.fflags <= (others => '0'); |
csr.frm <= (others => '0'); |
csr.fflags <= (others => def_rst_val_c); |
csr.frm <= (others => def_rst_val_c); |
|
elsif rising_edge(clk_i) then |
-- write access? -- |
csr.we <= csr.we_nxt; |
-- defaults -- |
csr.mip_clear <= (others => '0'); |
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then |
|
-- defaults -- |
csr.mip_clear <= (others => '0'); |
|
-- -------------------------------------------------------------------------------- |
-- CSR access by application software |
-- -------------------------------------------------------------------------------- |
1960,25 → 1951,24
|
-- user floating-point CSRs -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_class_float_c) then -- floating point CSR class |
-- R/W: fflags - floating-point (FPU) exception flags -- |
if (csr.addr(3 downto 0) = csr_fflags_c(3 downto 0)) and (CPU_EXTENSION_RISCV_Zfinx = true) then |
csr.fflags <= csr.wdata(4 downto 0); |
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- floating point CSR class |
if (csr.addr(11 downto 4) = csr_class_float_c) and (csr.addr(3 downto 2) = csr_fcsr_c(3 downto 2)) then |
case csr.addr(1 downto 0) is |
when "01" => -- R/W: fflags - floating-point (FPU) exception flags |
csr.fflags <= csr.wdata(4 downto 0); |
when "10" => -- R/W: frm - floating-point (FPU) rounding mode |
csr.frm <= csr.wdata(2 downto 0); |
when "11" => -- R/W: fcsr - floating-point (FPU) control/status (frm + fflags) |
csr.frm <= csr.wdata(7 downto 5); |
csr.fflags <= csr.wdata(4 downto 0); |
when others => NULL; |
end case; |
end if; |
-- R/W: frm - floating-point (FPU) rounding mode -- |
if (csr.addr(3 downto 0) = csr_frm_c(3 downto 0)) and (CPU_EXTENSION_RISCV_Zfinx = true) then |
csr.frm <= csr.wdata(2 downto 0); |
end if; |
-- R/W: fflags - floating-point (FPU) control/status (frm + fflags) -- |
if (csr.addr(3 downto 0) = csr_fcsr_c(3 downto 0)) and (CPU_EXTENSION_RISCV_Zfinx = true) then |
csr.frm <= csr.wdata(7 downto 5); |
csr.fflags <= csr.wdata(4 downto 0); |
end if; |
end if; |
|
-- machine trap setup -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_setup_c) then -- ftrap setup CSR class |
if (csr.addr(11 downto 4) = csr_class_setup_c) then -- ftrap setup CSR class |
-- R/W: mstatus - machine status register -- |
if (csr.addr(3 downto 0) = csr_mstatus_c(3 downto 0)) then |
csr.mstatus_mie <= csr.wdata(03); |
2004,8 → 1994,8
csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0 |
end if; |
-- R/W: machine counter enable register -- |
if (csr.addr(3 downto 0) = csr_mcounteren_c(3 downto 0)) then |
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented |
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented |
if (csr.addr(3 downto 0) = csr_mcounteren_c(3 downto 0)) then |
csr.mcounteren_cy <= csr.wdata(0); -- enable user-level access to cycle[h] |
csr.mcounteren_tm <= csr.wdata(1); -- enable user-level access to time[h] |
csr.mcounteren_ir <= csr.wdata(2); -- enable user-level access to instret[h] |
2047,8 → 2037,8
|
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_class_pmpcfg_c) then -- pmp configuration CSR class |
if (PMP_NUM_REGIONS > 0) then |
if (PMP_NUM_REGIONS > 0) then |
if (csr.addr(11 downto 4) = csr_class_pmpcfg_c) then -- pmp configuration CSR class |
for i in 0 to PMP_NUM_REGIONS-1 loop |
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then |
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access |
2068,9 → 2058,9
|
-- physical memory protection: R/W: pmpaddr* - PMP address registers -- |
-- -------------------------------------------------------------------- |
if (csr.addr(11 downto 4) = csr_pmpaddr0_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr16_c(11 downto 4)) or |
(csr.addr(11 downto 4) = csr_pmpaddr32_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr48_c(11 downto 4)) then |
if (PMP_NUM_REGIONS > 0) then |
if (PMP_NUM_REGIONS > 0) then |
if (csr.addr(11 downto 4) = csr_pmpaddr0_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr16_c(11 downto 4)) or |
(csr.addr(11 downto 4) = csr_pmpaddr32_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr48_c(11 downto 4)) then |
for i in 0 to PMP_NUM_REGIONS-1 loop |
if (csr.addr(6 downto 0) = std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i)) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access |
csr.pmpaddr(i) <= csr.wdata; |
2082,22 → 2072,20
|
-- machine counter setup -- |
-- -------------------------------------------------------------------- |
-- R/W: mcountinhibit - machine counter-inhibit register -- |
if (csr.addr = csr_mcountinhibit_c) then |
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter |
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter |
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter |
end if; |
|
-- machine performance-monitoring event selector -- |
-- -------------------------------------------------------------------- |
if (unsigned(csr.addr) >= unsigned(csr_mhpmevent3_c)) and (unsigned(csr.addr) <= unsigned(csr_mhpmevent31_c)) then |
if (csr.addr(11 downto 5) = csr_cnt_setup_c) then -- counter configuration CSR class |
-- R/W: mcountinhibit - machine counter-inhibit register -- |
if (csr.addr(4 downto 0) = csr_mcountinhibit_c(4 downto 0)) then |
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter |
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter |
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter |
end if; |
-- machine performance-monitoring event selector -- |
if (HPM_NUM_CNTS > 0) then |
for i in 0 to HPM_NUM_CNTS-1 loop |
if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then |
csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0); |
csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME" |
end if; |
csr.mhpmevent(i)(hpmcnt_event_never_c) <= '0'; -- would be used for "TIME" |
end loop; -- i (CSRs) |
end if; |
end if; |
2123,7 → 2111,7
-- trap PC -- |
if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS |
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction |
else -- for EXCEPTIONS |
else -- for sync. EXCEPTIONS |
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction |
end if; |
-- trap value -- |
2194,6 → 2182,14
csr.mcountinhibit_hpm <= (others => '0'); |
end if; |
|
-- cpu counters disabled -- |
if (CPU_CNT_WIDTH = 0) then |
csr.mcounteren_cy <= '0'; |
csr.mcounteren_ir <= '0'; |
csr.mcountinhibit_cy <= '0'; |
csr.mcountinhibit_ir <= '0'; |
end if; |
|
-- floating-point extension disabled -- |
if (CPU_EXTENSION_RISCV_Zfinx = false) then |
csr.fflags <= (others => '0'); |
2203,7 → 2199,7
end if; |
end process csr_write_access; |
|
-- decode privilege mode -- |
-- decode current privilege mode -- |
csr.priv_m_mode <= '1' when (csr.privilege = priv_mode_m_c) else '0'; |
csr.priv_u_mode <= '1' when (csr.privilege = priv_mode_u_c) else '0'; |
|
2212,11 → 2208,13
begin |
pmp_addr_o <= (others => (others => '0')); |
pmp_ctrl_o <= (others => (others => '0')); |
for i in 0 to PMP_NUM_REGIONS-1 loop |
pmp_addr_o(i) <= csr.pmpaddr(i) & "11"; |
pmp_addr_o(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1'); |
pmp_ctrl_o(i) <= csr.pmpcfg(i); |
end loop; -- i |
if (PMP_NUM_REGIONS /= 0) then |
for i in 0 to PMP_NUM_REGIONS-1 loop |
pmp_addr_o(i) <= csr.pmpaddr(i) & "11"; |
pmp_addr_o(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1'); |
pmp_ctrl_o(i) <= csr.pmpcfg(i); |
end loop; -- i |
end if; |
end process pmp_output; |
|
-- PMP read dummy -- |
2224,13 → 2222,15
begin |
csr.pmpcfg_rd <= (others => (others => '0')); |
csr.pmpaddr_rd <= (others => (others => '0')); |
for i in 0 to PMP_NUM_REGIONS-1 loop |
csr.pmpcfg_rd(i) <= csr.pmpcfg(i); |
csr.pmpaddr_rd(i) <= csr.pmpaddr(i); |
if (csr.pmpcfg(i)(4 downto 3) = "00") then -- mode = off |
csr.pmpaddr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-3 downto 0) <= (others => '0'); -- required for granularity check by SW |
end if; |
end loop; -- i |
if (PMP_NUM_REGIONS /= 0) then |
for i in 0 to PMP_NUM_REGIONS-1 loop |
csr.pmpcfg_rd(i) <= csr.pmpcfg(i); |
csr.pmpaddr_rd(i) <= csr.pmpaddr(i); |
if (csr.pmpcfg(i)(4 downto 3) = "00") then -- mode = off |
csr.pmpaddr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-3 downto 0) <= (others => '0'); -- required for granularity check by SW |
end if; |
end loop; -- i |
end if; |
end process pmp_rd_dummy; |
|
-- FPU rounding mode -- |
2239,59 → 2239,94
|
-- Control and Status Registers - Counters ------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
csr_counters: process(clk_i) |
csr_counters: process(rstn_i, clk_i) |
begin |
-- Counter CSRs (each counter is split into two 32-bit counters) |
if rising_edge(clk_i) then |
-- Counter CSRs (each counter is split into two 32-bit counters - coupled via an MSB overflow detector) |
if (rstn_i = '0') then |
csr.mcycle <= (others => def_rst_val_c); |
mcycle_msb <= def_rst_val_c; |
csr.mcycleh <= (others => def_rst_val_c); |
csr.minstret <= (others => def_rst_val_c); |
minstret_msb <= def_rst_val_c; |
csr.minstreth <= (others => def_rst_val_c); |
csr.mhpmcounter <= (others => (others => def_rst_val_c)); |
mhpmcounter_msb <= (others => def_rst_val_c); |
csr.mhpmcounterh <= (others => (others => def_rst_val_c)); |
elsif rising_edge(clk_i) then |
|
-- [m]cycle -- |
if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access |
csr.mcycle <= '0' & csr.wdata; |
csr.mcycle(csr.mcycle'left downto cpu_cnt_lo_width_c+1) <= (others => '0'); -- set unsued bits to zero |
if (cpu_cnt_lo_width_c = 0) then |
csr.mcycle <= (others => '0'); |
mcycle_msb <= '0'; |
elsif (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access |
csr.mcycle(cpu_cnt_lo_width_c downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0); |
mcycle_msb <= '0'; |
elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update |
csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1); |
mcycle_msb <= csr.mcycle(csr.mcycle'left); |
csr.mcycle(cpu_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned(csr.mcycle(cpu_cnt_lo_width_c downto 0)) + 1); |
mcycle_msb <= csr.mcycle(cpu_cnt_lo_width_c); |
end if; |
|
-- [m]cycleh -- |
if (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access |
csr.mcycleh <= csr.wdata; |
elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update (continued) |
csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1); |
csr.mcycleh(csr.mcycleh'left downto cpu_cnt_hi_width_c+1) <= (others => '0'); -- set unsued bits to zero |
if (cpu_cnt_hi_width_c = 0) then |
csr.mcycleh <= (others => '0'); |
elsif (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access |
csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0); |
elsif ((mcycle_msb xor csr.mcycle(cpu_cnt_lo_width_c)) = '1') then -- automatic update (continued) |
csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0)) + 1); |
end if; |
|
-- [m]instret -- |
if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access |
csr.minstret <= '0' & csr.wdata; |
csr.minstret(csr.minstret'left downto cpu_cnt_lo_width_c+1) <= (others => '0'); -- set unsued bits to zero |
if (cpu_cnt_lo_width_c = 0) then |
csr.minstret <= (others => '0'); |
minstret_msb <= '0'; |
elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update |
csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1); |
elsif (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access |
csr.minstret(cpu_cnt_lo_width_c downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0); |
minstret_msb <= '0'; |
elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') then -- non-inhibited automatic update |
csr.minstret(cpu_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned(csr.minstret(cpu_cnt_lo_width_c downto 0)) + 1); |
minstret_msb <= csr.minstret(csr.minstret'left); |
end if; |
|
-- [m]instreth -- |
if (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access |
csr.minstreth <= csr.wdata; |
elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update (continued) |
csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1); |
csr.minstreth(csr.minstreth'left downto cpu_cnt_hi_width_c+1) <= (others => '0'); -- set unsued bits to zero |
if (cpu_cnt_hi_width_c = 0) then |
csr.minstreth <= (others => '0'); |
elsif (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access |
csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0); |
elsif ((minstret_msb xor csr.minstret(cpu_cnt_lo_width_c)) = '1') then -- automatic update (continued) |
csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.minstreth(cpu_cnt_hi_width_c-1 downto 0)) + 1); |
end if; |
|
-- [machine] hardware performance monitors (counters) -- |
for i in 0 to HPM_NUM_CNTS-1 loop |
-- [m]hpmcounter* -- |
if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access |
csr.mhpmcounter(i) <= '0' & csr.wdata; |
csr.mhpmcounter(i)(csr.mhpmcounter(i)'left downto hpm_cnt_lo_width_c+1) <= (others => '0'); -- set unsued bits to zero |
if (hpm_cnt_lo_width_c = 0) then |
csr.mhpmcounter(i) <= (others => '0'); |
mhpmcounter_msb(i) <= '0'; |
elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update |
csr.mhpmcounter(i) <= std_ulogic_vector(unsigned(csr.mhpmcounter(i)) + 1); |
mhpmcounter_msb(i) <= csr.mhpmcounter(i)(csr.mhpmcounter(i)'left); |
else |
-- [m]hpmcounter* -- |
if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access |
csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0) <= '0' & csr.wdata(hpm_cnt_lo_width_c-1 downto 0); |
mhpmcounter_msb(i) <= '0'; |
elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update |
csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0)) + 1); |
mhpmcounter_msb(i) <= csr.mhpmcounter(i)(csr.mhpmcounter(i)'left); |
end if; |
end if; |
|
-- [m]hpmcounter*h -- |
if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access |
csr.mhpmcounterh(i) <= csr.wdata; |
elsif ((mhpmcounter_msb(i) xor csr.mhpmcounter(i)(csr.mhpmcounter(i)'left)) = '1') then -- automatic update (continued) |
csr.mhpmcounterh(i) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)) + 1); |
csr.mhpmcounterh(i)(csr.mhpmcounterh(i)'left downto hpm_cnt_hi_width_c+1) <= (others => '0'); -- set unsued bits to zero |
if (hpm_cnt_hi_width_c = 0) then |
csr.mhpmcounterh(i) <= (others => '0'); |
else |
if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access |
csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= csr.wdata(hpm_cnt_hi_width_c-1 downto 0); |
elsif ((mhpmcounter_msb(i) xor csr.mhpmcounter(i)(hpm_cnt_lo_width_c)) = '1') then -- automatic update (continued) |
csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0)) + 1); |
end if; |
end if; |
end loop; -- i |
|
2304,34 → 2339,45
csr.mhpmevent_rd <= (others => (others => '0')); |
csr.mhpmcounter_rd <= (others => (others => '0')); |
csr.mhpmcounterh_rd <= (others => (others => '0')); |
for i in 0 to HPM_NUM_CNTS-1 loop |
csr.mhpmevent_rd(i) <= csr.mhpmevent(i); |
csr.mhpmcounter_rd(i) <= csr.mhpmcounter(i); |
csr.mhpmcounterh_rd(i) <= csr.mhpmcounterh(i); |
end loop; -- i |
if (HPM_NUM_CNTS /= 0) then |
for i in 0 to HPM_NUM_CNTS-1 loop |
csr.mhpmevent_rd(i) <= csr.mhpmevent(i); |
if (hpm_cnt_lo_width_c > 0) then |
csr.mhpmcounter_rd(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0); |
end if; |
if (hpm_cnt_hi_width_c > 0) then |
csr.mhpmcounterh_rd(i)(hpm_cnt_hi_width_c-1 downto 0) <= csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0); |
end if; |
end loop; -- i |
end if; |
end process hpm_rd_dummy; |
|
|
-- (HPM) Counter Event Control ------------------------------------------------------------ |
-- Hardware Performance Monitor - Counter Event Control ----------------------------------- |
-- ------------------------------------------------------------------------------------------- |
hpmcnt_ctrl: process(clk_i) |
hpmcnt_ctrl: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
cnt_event <= (others => def_rst_val_c); |
hpmcnt_trigger <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
-- buffer event sources -- |
cnt_event <= cnt_event_nxt; |
-- enable selected triggers by ANDing actual events and according CSR configuration bits -- |
-- OR everything to see if counter should increment -- |
hpmcnt_trigger <= (others => '0'); -- default |
for i in 0 to HPM_NUM_CNTS-1 loop |
hpmcnt_trigger(i) <= or_all_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0)); |
end loop; -- i |
if (HPM_NUM_CNTS /= 0) then |
for i in 0 to HPM_NUM_CNTS-1 loop |
hpmcnt_trigger(i) <= or_all_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0)); |
end loop; -- i |
end if; |
end if; |
end process hpmcnt_ctrl; |
|
-- counter event trigger - RISC-V specific -- |
cnt_event_nxt(hpmcnt_event_cy_c) <= not execute_engine.sleep; -- active cycle |
cnt_event_nxt(hpmcnt_event_never_c) <= '0'; -- undefined (never) |
cnt_event_nxt(hpmcnt_event_ir_c) <= '1' when (execute_engine.state = EXECUTE) else '0'; -- retired instruction |
-- counter event trigger - RISC-V-specific -- |
cnt_event_nxt(hpmcnt_event_cy_c) <= not execute_engine.sleep; -- active cycle |
cnt_event_nxt(hpmcnt_event_never_c) <= '0'; -- undefined (never) |
cnt_event_nxt(hpmcnt_event_ir_c) <= '1' when (execute_engine.state = EXECUTE) else '0'; -- retired instruction |
|
-- counter event trigger - custom / NEORV32-specific -- |
cnt_event_nxt(hpmcnt_event_cir_c) <= '1' when (execute_engine.state = EXECUTE) and (execute_engine.is_ci = '1') else '0'; -- retired compressed instruction |
2353,9 → 2399,12
|
-- Control and Status Registers - Read Access --------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
csr_read_access: process(clk_i) |
csr_read_access: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
csr.re <= def_rst_val_c; |
csr.rdata <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
csr.re <= csr.re_nxt; -- read access? |
csr.rdata <= (others => '0'); -- default output |
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then |
2373,7 → 2422,7
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented |
csr.rdata(2 downto 0) <= csr.frm; |
end if; |
when csr_fcsr_c => -- R/W: fflags - floating-point (FPU) control/status (frm + fflags) |
when csr_fcsr_c => -- R/W: fcsr - floating-point (FPU) control/status (frm + fflags) |
csr.rdata <= (others => '0'); |
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented |
csr.rdata(7 downto 5) <= csr.frm; |
2394,7 → 2443,6
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension |
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension |
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension |
csr.rdata(05) <= '0'; -- F CPU extension |
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E) |
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension |
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension |
2411,13 → 2459,12
when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions) |
csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0 |
when csr_mcounteren_c => -- R/W: machine counter enable register |
csr.rdata <= (others => '0'); |
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented |
csr.rdata(0) <= csr.mcounteren_cy; -- enable user-level access to cycle[h] |
csr.rdata(1) <= csr.mcounteren_tm; -- enable user-level access to time[h] |
csr.rdata(2) <= csr.mcounteren_ir; -- enable user-level access to instret[h] |
csr.rdata(csr.mcounteren_hpm'left+3 downto 3) <= csr.mcounteren_hpm; -- enable user-level access to hpmcounterx[h] |
else |
csr.rdata <= (others => '0'); |
end if; |
|
-- machine trap handling -- |
2562,17 → 2609,17
|
-- counters and timers -- |
when csr_cycle_c | csr_mcycle_c => -- (R)/(W): [m]cycle: Cycle counter LOW |
csr.rdata <= csr.mcycle(31 downto 0); |
csr.rdata(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle(cpu_cnt_lo_width_c-1 downto 0); |
when csr_time_c => -- (R)/-: time: System time LOW (from MTIME unit) |
csr.rdata <= time_i(31 downto 0); |
when csr_instret_c | csr_minstret_c => -- (R)/(W): [m]instret: Instructions-retired counter LOW |
csr.rdata <= csr.minstret(31 downto 0); |
csr.rdata(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret(cpu_cnt_lo_width_c-1 downto 0); |
when csr_cycleh_c | csr_mcycleh_c => -- (R)/(W): [m]cycleh: Cycle counter HIGH |
csr.rdata <= csr.mcycleh(31 downto 0); |
csr.rdata(cpu_cnt_hi_width_c-1 downto 0) <= csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0); |
when csr_timeh_c => -- (R)/-: timeh: System time HIGH (from MTIME unit) |
csr.rdata <= time_i(63 downto 32); |
when csr_instreth_c | csr_minstreth_c => -- (R)/(W): [m]instreth: Instructions-retired counter HIGH |
csr.rdata <= csr.minstreth(31 downto 0); |
csr.rdata(cpu_cnt_hi_width_c-1 downto 0) <= csr.minstreth(cpu_cnt_hi_width_c-1 downto 0); |
|
-- hardware performance counters -- |
when csr_hpmcounter3_c | csr_mhpmcounter3_c => csr.rdata <= csr.mhpmcounter_rd(00)(31 downto 0); -- (R)/(W): [m]hpmcounter3 - low |
2653,6 → 2700,16
csr.rdata(3) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zbs (B) |
csr.rdata(4) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zba (B) |
csr.rdata(5) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx ("F-alternative") |
if (CPU_CNT_WIDTH = 64) then |
csr.rdata(6) <= '0'; -- Zxscnt (custom) |
csr.rdata(7) <= '0'; -- Zxnocnt (custom) |
elsif (CPU_CNT_WIDTH = 0) then |
csr.rdata(6) <= '0'; -- Zxscnt (custom) |
csr.rdata(7) <= '1'; -- Zxnocnt (custom) |
else -- counters available but 0-bit < actual_size < 64-bit |
csr.rdata(6) <= '1'; -- Zxscnt (custom) |
csr.rdata(7) <= '0'; -- Zxnocnt (custom) |
end if; |
|
-- undefined/unavailable -- |
when others => |
/neorv32/trunk/rtl/core/neorv32_cpu_cp_bitmanip.vhd
181,10 → 181,10
begin |
if (rstn_i = '0') then |
ctrl_state <= S_IDLE; |
cmd_buf <= (others => '0'); |
rs1_reg <= (others => '0'); |
rs2_reg <= (others => '0'); |
less_ff <= '0'; |
cmd_buf <= (others => def_rst_val_c); |
rs1_reg <= (others => def_rst_val_c); |
rs2_reg <= (others => def_rst_val_c); |
less_ff <= def_rst_val_c; |
shifter.start <= '0'; |
valid <= '0'; |
elsif rising_edge(clk_i) then |
247,10 → 247,15
|
-- Shifter Function Core ------------------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
shifter_unit: process(clk_i) |
shifter_unit: process(rstn_i, clk_i) |
variable new_bit_v : std_ulogic; |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
shifter.cnt <= (others => def_rst_val_c); |
shifter.sreg <= (others => def_rst_val_c); |
shifter.cnt_max <= (others => def_rst_val_c); |
shifter.bcnt <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (shifter.start = '1') then -- trigger new shift |
shifter.cnt <= (others => '0'); |
-- shift operand -- |
397,9 → 402,11
|
-- Output Gate ---------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
output_gate: process(clk_i) |
output_gate: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
res_o <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
res_o <= (others => '0'); |
if (valid = '1') then |
res_o <= res_out(op_clz_c) or res_out(op_cpop_c) or -- res_out(op_ctz_c) is unused here |
/neorv32/trunk/rtl/core/neorv32_cpu_cp_fpu.vhd
64,6 → 64,7
start_i : in std_ulogic; -- trigger operation |
-- data input -- |
frm_i : in std_ulogic_vector(2 downto 0); -- rounding mode |
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status |
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1 |
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2 |
-- result and status -- |
168,9 → 169,9
signal fpu_operands : fpu_operands_t; |
|
-- floating-point comparator -- |
signal cmp_ff : std_ulogic_vector(01 downto 0); |
signal comp_equal_ff : std_ulogic; |
signal comp_less_ff : std_ulogic; |
signal comp_less : std_ulogic; |
|
-- functional units interface -- |
type fu_interface_t is record |
319,7 → 320,7
-- check special cases -- |
op_is_zero_v := op_e_all_zero_v and op_m_all_zero_v; -- zero |
op_is_inf_v := op_e_all_one_v and op_m_all_zero_v; -- infinity |
op_is_denorm_v := '0'; -- FIXME / TODO op_e_all_zero_v and (not op_m_all_zero_v); -- subnormal |
op_is_denorm_v := '0'; -- FIXME / TODO -- op_e_all_zero_v and (not op_m_all_zero_v); -- subnormal |
op_is_nan_v := op_e_all_one_v and (not op_m_all_zero_v); -- NaN |
|
-- actual attributes -- |
344,12 → 345,13
if (rstn_i = '0') then |
ctrl_engine.state <= S_IDLE; |
ctrl_engine.start <= '0'; |
fpu_operands.frm <= (others => '0'); |
fpu_operands.rs1 <= (others => '0'); |
fpu_operands.rs1_class <= (others => '0'); |
fpu_operands.rs2 <= (others => '0'); |
fpu_operands.rs2_class <= (others => '0'); |
funct_ff <= (others => '0'); |
fpu_operands.frm <= (others => def_rst_val_c); |
fpu_operands.rs1 <= (others => def_rst_val_c); |
fpu_operands.rs1_class <= (others => def_rst_val_c); |
fpu_operands.rs2 <= (others => def_rst_val_c); |
fpu_operands.rs2_class <= (others => def_rst_val_c); |
funct_ff <= (others => def_rst_val_c); |
cmp_ff <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
-- arbiter defaults -- |
ctrl_engine.valid <= '0'; |
361,6 → 363,7
when S_IDLE => -- waiting for operation trigger |
-- ------------------------------------------------------------ |
funct_ff <= cmd.funct; -- actual operation to execute |
cmp_ff <= cmp_i; -- main ALU comparator |
-- rounding mode -- |
-- TODO / FIXME "round to nearest, ties to max magnitude" (0b100) is not supported yet |
if (ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) = "111") then |
425,16 → 428,21
|
-- Floating-Point Comparator -------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
float_comparator: process(clk_i) |
float_comparator: process(rstn_i, clk_i) |
variable cond_v : std_ulogic_vector(1 downto 0); |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
comp_equal_ff <= def_rst_val_c; |
comp_less_ff <= def_rst_val_c; |
fu_compare.done <= def_rst_val_c; |
fu_min_max.done <= def_rst_val_c; |
elsif rising_edge(clk_i) then |
-- equal -- |
if ((fpu_operands.rs1_class(fp_class_pos_inf_c) = '1') and (fpu_operands.rs2_class(fp_class_pos_inf_c) = '1')) or -- +inf == +inf |
((fpu_operands.rs1_class(fp_class_neg_inf_c) = '1') and (fpu_operands.rs2_class(fp_class_neg_inf_c) = '1')) or -- -inf == -inf |
(((fpu_operands.rs1_class(fp_class_pos_zero_c) = '1') or (fpu_operands.rs1_class(fp_class_neg_zero_c) = '1')) and |
((fpu_operands.rs2_class(fp_class_pos_zero_c) = '1') or (fpu_operands.rs2_class(fp_class_neg_zero_c) = '1'))) or -- +/-zero == +/-zero |
(fpu_operands.rs1 = fpu_operands.rs2) then -- identical in every way |
(cmp_ff(cmp_equal_c) = '1') then -- identical in every way (comparator result from main ALU) |
comp_equal_ff <= '1'; |
else |
comp_equal_ff <= '0'; |
451,8 → 459,8
case cond_v is |
when "10" => comp_less_ff <= '1'; -- rs1 negative, rs2 positive |
when "01" => comp_less_ff <= '0'; -- rs1 positive, rs2 negative |
when "00" => comp_less_ff <= comp_less; -- both positive |
when "11" => comp_less_ff <= not comp_less; -- both negative |
when "00" => comp_less_ff <= cmp_ff(cmp_less_c); -- both positive (comparator result from main ALU) |
when "11" => comp_less_ff <= not cmp_ff(cmp_less_c); -- both negative (comparator result from main ALU) |
when others => comp_less_ff <= '0'; -- undefined |
end case; |
end if; |
463,10 → 471,7
end if; |
end process float_comparator; |
|
-- less than - only compare the "magnitude" part - sign bit has to be handled separately -- |
comp_less <= '1' when (unsigned(fpu_operands.rs1(30 downto 0)) < unsigned(fpu_operands.rs2(30 downto 0))) else '0'; |
|
|
-- Comparison (FEQ/FLT/FLE) --------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
float_comparison: process(fpu_operands, ctrl_i, comp_equal_ff, comp_less_ff) |
575,11 → 580,14
|
-- Convert: [unsigned] Integer to Float (FCVT.W.S) ---------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
convert_i2f: process(clk_i) |
convert_i2f: process(rstn_i, clk_i) |
begin |
-- this process only computes the absolute input value |
-- the actual conversion is done by the normalizer |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
fu_conv_i2f.result <= (others => def_rst_val_c); |
fu_conv_i2f.sign <= def_rst_val_c; |
elsif rising_edge(clk_i) then |
if (ctrl_i(ctrl_ir_funct12_0_c) = '0') and (rs1_i(31) = '1') then -- convert signed integer |
fu_conv_i2f.result <= std_ulogic_vector(0 - unsigned(rs1_i)); |
fu_conv_i2f.sign <= rs1_i(31); -- original sign |
594,13 → 602,24
|
-- Multiplier Core (FMUL) ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
multiplier_core: process(clk_i) |
begin |
if rising_edge(clk_i) then |
multiplier_core: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
multiplier.opa <= (others => '-'); -- these might be DSP regs! |
multiplier.opb <= (others => '-'); -- these might be DSP regs! |
multiplier.buf_ff <= (others => '-'); -- these might be DSP regs! |
multiplier.product <= (others => '-'); -- these might be DSP regs! |
multiplier.sign <= def_rst_val_c; |
multiplier.exp_res <= (others => def_rst_val_c); |
multiplier.flags(fp_exc_of_c) <= def_rst_val_c; |
multiplier.flags(fp_exc_uf_c) <= def_rst_val_c; |
multiplier.flags(fp_exc_nv_c) <= def_rst_val_c; |
multiplier.latency <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
-- multiplier core -- |
if (multiplier.start = '1') then -- FIXME / TODO remove buffer? |
multiplier.opa <= unsigned('1' & fpu_operands.rs1(22 downto 0)); -- append hidden one |
multiplier.opb <= unsigned('1' & fpu_operands.rs2(22 downto 0)); |
multiplier.opb <= unsigned('1' & fpu_operands.rs2(22 downto 0)); -- append hidden one |
end if; |
multiplier.buf_ff <= multiplier.opa * multiplier.opb; |
multiplier.product <= std_ulogic_vector(multiplier.buf_ff(47 downto 0)); -- let the register balancing do the magic here |
645,7 → 664,7
|
|
-- result class -- |
multiplier_class_core: process(clk_i) |
multiplier_class_core: process(rstn_i, clk_i) |
variable a_pos_norm_v, a_neg_norm_v, b_pos_norm_v, b_neg_norm_v : std_ulogic; |
variable a_pos_subn_v, a_neg_subn_v, b_pos_subn_v, b_neg_subn_v : std_ulogic; |
variable a_pos_zero_v, a_neg_zero_v, b_pos_zero_v, b_neg_zero_v : std_ulogic; |
652,7 → 671,14
variable a_pos_inf_v, a_neg_inf_v, b_pos_inf_v, b_neg_inf_v : std_ulogic; |
variable a_snan_v, a_qnan_v, b_snan_v, b_qnan_v : std_ulogic; |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
multiplier.res_class(fp_class_pos_norm_c) <= def_rst_val_c; |
multiplier.res_class(fp_class_neg_norm_c) <= def_rst_val_c; |
multiplier.res_class(fp_class_pos_inf_c) <= def_rst_val_c; |
multiplier.res_class(fp_class_neg_inf_c) <= def_rst_val_c; |
multiplier.res_class(fp_class_pos_zero_c) <= def_rst_val_c; |
multiplier.res_class(fp_class_neg_zero_c) <= def_rst_val_c; |
elsif rising_edge(clk_i) then |
-- minions -- |
a_pos_norm_v := fpu_operands.rs1_class(fp_class_pos_norm_c); b_pos_norm_v := fpu_operands.rs2_class(fp_class_pos_norm_c); |
a_neg_norm_v := fpu_operands.rs1_class(fp_class_neg_norm_c); b_neg_norm_v := fpu_operands.rs2_class(fp_class_neg_norm_c); |
745,9 → 771,21
|
-- Adder/Subtractor Core (FADD, FSUB) ----------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
adder_subtractor_core: process(clk_i) |
begin |
if rising_edge(clk_i) then |
adder_subtractor_core: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
addsub.latency <= (others => def_rst_val_c); |
addsub.exp_comp <= (others => def_rst_val_c); |
addsub.man_sreg <= (others => def_rst_val_c); |
addsub.exp_cnt <= (others => def_rst_val_c); |
addsub.man_g_ext <= def_rst_val_c; |
addsub.man_r_ext <= def_rst_val_c; |
addsub.man_s_ext <= def_rst_val_c; |
addsub.man_comp <= def_rst_val_c; |
addsub.add_stage <= (others => def_rst_val_c); |
addsub.res_sign <= def_rst_val_c; |
addsub.flags(fp_exc_nv_c) <= def_rst_val_c; |
elsif rising_edge(clk_i) then |
-- arbitration / latency -- |
if (ctrl_engine.state = S_IDLE) then -- hacky "reset" |
addsub.latency <= (others => '0'); |
865,7 → 903,7
|
|
-- result class -- |
adder_subtractor_class_core: process(clk_i) |
adder_subtractor_class_core: process(rstn_i, clk_i) |
variable a_pos_norm_v, a_neg_norm_v, b_pos_norm_v, b_neg_norm_v : std_ulogic; |
variable a_pos_subn_v, a_neg_subn_v, b_pos_subn_v, b_neg_subn_v : std_ulogic; |
variable a_pos_zero_v, a_neg_zero_v, b_pos_zero_v, b_neg_zero_v : std_ulogic; |
872,7 → 910,13
variable a_pos_inf_v, a_neg_inf_v, b_pos_inf_v, b_neg_inf_v : std_ulogic; |
variable a_snan_v, a_qnan_v, b_snan_v, b_qnan_v : std_ulogic; |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
addsub.res_class(fp_class_pos_inf_c) <= def_rst_val_c; |
addsub.res_class(fp_class_neg_inf_c) <= def_rst_val_c; |
addsub.res_class(fp_class_pos_zero_c) <= def_rst_val_c; |
addsub.res_class(fp_class_neg_zero_c) <= def_rst_val_c; |
addsub.res_class(fp_class_qnan_c) <= def_rst_val_c; |
elsif rising_edge(clk_i) then |
-- minions -- |
a_pos_norm_v := fpu_operands.rs1_class(fp_class_pos_norm_c); b_pos_norm_v := fpu_operands.rs2_class(fp_class_pos_norm_c); |
a_neg_norm_v := fpu_operands.rs1_class(fp_class_neg_norm_c); b_neg_norm_v := fpu_operands.rs2_class(fp_class_neg_norm_c); |
1079,9 → 1123,12
|
-- Result Output to CPU Pipeline ---------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
output_gate: process(clk_i) |
output_gate: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
res_o <= (others => def_rst_val_c); |
fflags_o <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (ctrl_engine.valid = '1') then |
case funct_ff is |
when op_class_c => |
1233,24 → 1280,24
begin |
if (rstn_i = '0') then |
ctrl.state <= S_IDLE; |
ctrl.norm_r <= '0'; |
ctrl.cnt <= (others => '0'); |
ctrl.cnt_pre <= (others => '0'); |
ctrl.cnt_of <= '0'; |
ctrl.cnt_uf <= '0'; |
ctrl.rounded <= '0'; |
ctrl.res_exp <= (others => '0'); |
ctrl.res_man <= (others => '0'); |
ctrl.res_sgn <= '0'; |
ctrl.class <= (others => '0'); |
ctrl.flags <= (others => '0'); |
ctrl.norm_r <= def_rst_val_c; |
ctrl.cnt <= (others => def_rst_val_c); |
ctrl.cnt_pre <= (others => def_rst_val_c); |
ctrl.cnt_of <= def_rst_val_c; |
ctrl.cnt_uf <= def_rst_val_c; |
ctrl.rounded <= def_rst_val_c; |
ctrl.res_exp <= (others => def_rst_val_c); |
ctrl.res_man <= (others => def_rst_val_c); |
ctrl.res_sgn <= def_rst_val_c; |
ctrl.class <= (others => def_rst_val_c); |
ctrl.flags <= (others => def_rst_val_c); |
-- |
sreg.upper <= (others => '0'); |
sreg.lower <= (others => '0'); |
sreg.dir <= '0'; |
sreg.ext_g <= '0'; |
sreg.ext_r <= '0'; |
sreg.ext_s <= '0'; |
sreg.upper <= (others => def_rst_val_c); |
sreg.lower <= (others => def_rst_val_c); |
sreg.dir <= def_rst_val_c; |
sreg.ext_g <= def_rst_val_c; |
sreg.ext_r <= def_rst_val_c; |
sreg.ext_s <= def_rst_val_c; |
-- |
done_o <= '0'; |
elsif rising_edge(clk_i) then |
1609,18 → 1656,18
begin |
if (rstn_i = '0') then |
ctrl.state <= S_IDLE; |
ctrl.cnt <= (others => '0'); |
ctrl.sign <= '0'; |
ctrl.class <= (others => '0'); |
ctrl.rounded <= '0'; |
ctrl.over <= '0'; |
ctrl.under <= '0'; |
ctrl.unsign <= '0'; |
ctrl.result <= (others => '0'); |
ctrl.result_tmp <= (others => '0'); |
sreg.int <= (others => '0'); |
sreg.mant <= (others => '0'); |
sreg.ext_s <= '0'; |
ctrl.cnt <= (others => def_rst_val_c); |
ctrl.sign <= def_rst_val_c; |
ctrl.class <= (others => def_rst_val_c); |
ctrl.rounded <= def_rst_val_c; |
ctrl.over <= def_rst_val_c; |
ctrl.under <= def_rst_val_c; |
ctrl.unsign <= def_rst_val_c; |
ctrl.result <= (others => def_rst_val_c); |
ctrl.result_tmp <= (others => def_rst_val_c); |
sreg.int <= (others => def_rst_val_c); |
sreg.mant <= (others => def_rst_val_c); |
sreg.ext_s <= def_rst_val_c; |
done_o <= '0'; |
elsif rising_edge(clk_i) then |
-- defaults -- |
/neorv32/trunk/rtl/core/neorv32_cpu_cp_muldiv.vhd
1,10 → 1,13
-- ################################################################################################# |
-- # << NEORV32 - CPU Co-Processor: Integer Multiplier/Divider Unit (RISC-V "M" Extension)>> # |
-- # ********************************************************************************************* # |
-- # Multiplier and Divider unit. Implements the RISC-V RV32-M CPU extension. # |
-- # Multiplier core (signed/unsigned) uses serial algorithm. -> 32+4 cycles latency # |
-- # Divider core (unsigned) uses serial algorithm. -> 32+6 cycles latency # |
-- # Multiplications can be mapped to DSP block when FAST_MUL_EN = true. # |
-- # Multiplier and Divider unit. Implements the RISC-V M CPU extension. # |
-- # # |
-- # Multiplier core (signed/unsigned) uses classical serial algorithm. Unit atency: 31+3 cycles # |
-- # Divider core (unsigned) uses classical serial algorithm. Unit latency: 32+4 cycles # |
-- # # |
-- # Multiplications can be mapped to DSP blocks (faster!) when FAST_MUL_EN = true. # |
-- # Unit latency: 3 cycles # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
65,9 → 68,6
|
architecture neorv32_cpu_cp_muldiv_rtl of neorv32_cpu_cp_muldiv is |
|
-- advanced configuration -- |
constant dsp_add_reg_stage_c : boolean := false; -- add another register stage to DSP-based multiplication for timing-closure |
|
-- operations -- |
constant cp_op_mul_c : std_ulogic_vector(2 downto 0) := "000"; -- mul |
constant cp_op_mulh_c : std_ulogic_vector(2 downto 0) := "001"; -- mulh |
79,16 → 79,18
constant cp_op_remu_c : std_ulogic_vector(2 downto 0) := "111"; -- remu |
|
-- controller -- |
type state_t is (IDLE, DECODE, INIT_OPX, INIT_OPY, PROCESSING, FINALIZE, COMPLETED, FAST_MUL); |
type state_t is (IDLE, DIV_PREPROCESS, PROCESSING, FINALIZE, COMPLETED); |
signal state : state_t; |
signal cnt : std_ulogic_vector(4 downto 0); |
signal cp_op : std_ulogic_vector(2 downto 0); -- operation to execute |
signal cp_op_ff : std_ulogic_vector(2 downto 0); -- operation that was executed |
signal start : std_ulogic; |
signal start_div : std_ulogic; |
signal start_mul : std_ulogic; |
signal operation : std_ulogic; |
signal rs1, opx, opy : std_ulogic_vector(data_width_c-1 downto 0); -- input operands |
signal opx_is_signed : std_ulogic; |
signal opy_is_signed : std_ulogic; |
signal div_opx : std_ulogic_vector(data_width_c-1 downto 0); |
signal div_opy : std_ulogic_vector(data_width_c-1 downto 0); |
signal rs1_is_signed : std_ulogic; |
signal rs2_is_signed : std_ulogic; |
signal opy_is_zero : std_ulogic; |
signal div_res_corr : std_ulogic; |
signal valid : std_ulogic; |
102,6 → 104,8
signal div_res : std_ulogic_vector(data_width_c-1 downto 0); |
|
-- multiplier core -- |
signal mul_product_p : std_ulogic_vector(63 downto 0); |
signal mul_product_s : std_ulogic_vector(63 downto 0); |
signal mul_product : std_ulogic_vector(63 downto 0); |
signal mul_do_add : std_ulogic_vector(data_width_c downto 0); |
signal mul_sign_cycle : std_ulogic; |
109,7 → 113,6
signal mul_op_x : signed(32 downto 0); -- for using DSPs |
signal mul_op_y : signed(32 downto 0); -- for using DSPs |
signal mul_buf_ff : signed(65 downto 0); -- for using DSPs |
signal mul_buf2_ff : signed(65 downto 0); -- for using DSPs |
|
begin |
|
119,72 → 122,64
begin |
if (rstn_i = '0') then |
state <= IDLE; |
opx <= (others => '0'); |
opy <= (others => '0'); |
rs1 <= (others => '0'); |
cnt <= (others => '0'); |
start <= '0'; |
div_opx <= (others => def_rst_val_c); |
div_opy <= (others => def_rst_val_c); |
cnt <= (others => def_rst_val_c); |
cp_op_ff <= (others => def_rst_val_c); |
start_div <= '0'; |
valid <= '0'; |
div_res_corr <= '0'; |
opy_is_zero <= '0'; |
cp_op_ff <= (others => '0'); |
div_res_corr <= def_rst_val_c; |
opy_is_zero <= def_rst_val_c; |
elsif rising_edge(clk_i) then |
-- defaults -- |
start <= '0'; |
valid <= '0'; |
cp_op_ff <= cp_op; |
start_div <= '0'; |
valid <= '0'; |
|
-- FSM -- |
case state is |
when IDLE => |
cp_op_ff <= cp_op; |
if (start_i = '1') then |
opx <= rs1_i; |
rs1 <= rs1_i; |
opy <= rs2_i; |
state <= DECODE; |
if (operation = '1') then -- division |
cnt <= "11111"; |
state <= DIV_PREPROCESS; |
else |
cnt <= "11110"; |
if (FAST_MUL_EN = true) then |
state <= FINALIZE; |
else |
state <= PROCESSING; |
end if; |
end if; |
end if; |
|
when DECODE => |
-- |
when DIV_PREPROCESS => |
-- check rlevatn input signs -- |
if (cp_op = cp_op_div_c) then -- result sign compensation for div? |
div_res_corr <= opx(opx'left) xor opy(opy'left); |
div_res_corr <= rs1_i(rs1_i'left) xor rs2_i(rs2_i'left); |
elsif (cp_op = cp_op_rem_c) then -- result sign compensation for rem? |
div_res_corr <= opx(opx'left); |
div_res_corr <= rs1_i(rs1_i'left); |
else |
div_res_corr <= '0'; |
end if; |
-- |
if (or_all_f(opy) = '0') then -- *divide* by 0? |
opy_is_zero <= '1'; |
-- divide by zero? -- |
opy_is_zero <= not or_all_f(rs2_i); -- set if rs2 = 0 |
-- abs(rs1) -- |
if ((rs1_i(rs1_i'left) and rs1_is_signed) = '1') then -- signed division? |
div_opx <= std_ulogic_vector(0 - unsigned(rs1_i)); -- make positive |
else |
opy_is_zero <= '0'; |
div_opx <= rs1_i; |
end if; |
-- abs(rs2) -- |
if ((rs2_i(rs2_i'left) and rs2_is_signed) = '1') then -- signed division? |
div_opy <= std_ulogic_vector(0 - unsigned(rs2_i)); -- make positive |
else |
div_opy <= rs2_i; |
end if; |
-- |
cnt <= "11111"; |
if (operation = '1') then -- division |
state <= INIT_OPX; |
else -- multiplication |
start <= '1'; |
if (FAST_MUL_EN = true) then |
state <= FAST_MUL; |
else |
state <= PROCESSING; |
end if; |
end if; |
start_div <= '1'; |
state <= PROCESSING; |
|
when INIT_OPX => |
if ((opx(opx'left) and opx_is_signed) = '1') then -- signed division? |
opx <= div_sign_comp; -- make positive |
end if; |
state <= INIT_OPY; |
|
when INIT_OPY => |
start <= '1'; |
if ((opy(opy'left) and opy_is_signed) = '1') then -- signed division? |
opy <= div_sign_comp; -- make positive |
end if; |
state <= PROCESSING; |
|
when PROCESSING => |
cnt <= std_ulogic_vector(unsigned(cnt) - 1); |
if (cnt = "00000") then |
191,9 → 186,6
state <= FINALIZE; |
end if; |
|
when FAST_MUL => |
state <= FINALIZE; |
|
when FINALIZE => |
state <= COMPLETED; |
|
207,56 → 199,63
-- co-processor command -- |
cp_op <= ctrl_i(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c); |
|
-- operation -- |
operation <= '1' when (cp_op = cp_op_div_c) or (cp_op = cp_op_divu_c) or (cp_op = cp_op_rem_c) or (cp_op = cp_op_remu_c) else '0'; |
-- operation: 0=mul, 1=div -- |
operation <= '1' when (cp_op(2) = '1') else '0'; |
|
-- opx (rs1) signed? -- |
opx_is_signed <= '1' when (cp_op = cp_op_mulh_c) or (cp_op = cp_op_mulhsu_c) or (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) else '0'; |
rs1_is_signed <= '1' when (cp_op = cp_op_mulh_c) or (cp_op = cp_op_mulhsu_c) or (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) else '0'; |
|
-- opy (rs2) signed? -- |
opy_is_signed <= '1' when (cp_op = cp_op_mulh_c) or (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) else '0'; |
rs2_is_signed <= '1' when (cp_op = cp_op_mulh_c) or (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) else '0'; |
|
-- start MUL operation (do it fast!) -- |
start_mul <= '1' when (state = IDLE) and (start_i = '1') and (operation = '0') else '0'; |
|
|
-- Multiplier Core (signed/unsigned) ------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
multiplier_core: process(clk_i) |
multiplier_core_serial: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
-- --------------------------------------------------------- |
if (rstn_i = '0') then |
mul_product_s <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (FAST_MUL_EN = false) then -- use small iterative computation |
if (start = '1') then -- start new multiplication |
mul_product(63 downto 32) <= (others => '0'); |
mul_product(31 downto 00) <= opy; |
elsif ((state = PROCESSING) or (state = FINALIZE)) and (operation = '0') then |
mul_product(63 downto 31) <= mul_do_add(32 downto 0); |
mul_product(30 downto 00) <= mul_product(31 downto 1); |
if (start_mul = '1') then -- start new multiplication |
mul_product_s(63 downto 32) <= (others => '0'); |
mul_product_s(31 downto 00) <= rs2_i; |
elsif (state = PROCESSING) or (state = FINALIZE) then -- processing step or sign-finalization step |
mul_product_s(63 downto 31) <= mul_do_add(32 downto 0); |
mul_product_s(30 downto 00) <= mul_product_s(31 downto 1); |
end if; |
-- --------------------------------------------------------- |
else -- use direct approach using (several!) DSP blocks |
if (start = '1') then |
mul_op_x <= signed((opx(opx'left) and opx_is_signed) & opx); |
mul_op_y <= signed((opy(opy'left) and opy_is_signed) & opy); |
end if; |
end if; |
end process multiplier_core_serial; |
|
multiplier_core_dsp: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (FAST_MUL_EN = true) then -- use direct approach using DSP blocks |
if (start_mul = '1') then |
mul_op_x <= signed((rs1_i(rs1_i'left) and rs1_is_signed) & rs1_i); |
mul_op_y <= signed((rs2_i(rs2_i'left) and rs2_is_signed) & rs2_i); |
end if; |
mul_buf_ff <= mul_op_x * mul_op_y; |
if (dsp_add_reg_stage_c = true) then -- add another reg stage? |
mul_buf2_ff <= mul_buf_ff; |
mul_product <= std_ulogic_vector(mul_buf2_ff(63 downto 0)); -- let the register balancing do the magic here |
else |
mul_product <= std_ulogic_vector(mul_buf_ff(63 downto 0)); -- let the register balancing do the magic here |
end if; |
mul_buf_ff <= mul_op_x * mul_op_y; |
mul_product_p <= std_ulogic_vector(mul_buf_ff(63 downto 0)); -- let the register balancing do the magic here |
end if; |
end if; |
end process multiplier_core; |
end process multiplier_core_dsp; |
|
-- MUL: do another addition -- |
mul_update: process(mul_product, mul_sign_cycle, mul_p_sext, opx_is_signed, opx) |
mul_product <= mul_product_p when (FAST_MUL_EN = true) else mul_product_s; |
|
-- do another addition -- |
mul_update: process(mul_product, mul_sign_cycle, mul_p_sext, rs1_is_signed, rs1_i) |
begin |
-- current bit of opy to take care of -- |
-- current bit of rs2_i to take care of -- |
if (mul_product(0) = '1') then -- multiply with 1 |
if (mul_sign_cycle = '1') then -- for signed operations only: take care of negative weighted MSB -> multiply with -1 |
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((opx(opx'left) and opx_is_signed) & opx)); |
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((rs1_i(rs1_i'left) and rs1_is_signed) & rs1_i)); |
else -- multiply with +1 |
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((opx(opx'left) and opx_is_signed) & opx)); |
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((rs1_i(rs1_i'left) and rs1_is_signed) & rs1_i)); |
end if; |
else -- multiply with 0 |
mul_do_add <= mul_p_sext & mul_product(63 downto 32); |
264,19 → 263,22
end process mul_update; |
|
-- sign control -- |
mul_sign_cycle <= opy_is_signed when (state = FINALIZE) else '0'; |
mul_p_sext <= mul_product(mul_product'left) and opx_is_signed; |
mul_sign_cycle <= rs2_is_signed when (state = FINALIZE) else '0'; |
mul_p_sext <= mul_product(mul_product'left) and rs1_is_signed; |
|
|
-- Divider Core (unsigned) ---------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
divider_core: process(clk_i) |
divider_core: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (start = '1') then -- start new division |
quotient <= opx; |
if (rstn_i = '0') then |
quotient <= (others => def_rst_val_c); |
remainder <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
if (start_div = '1') then -- start new division |
quotient <= div_opx; |
remainder <= (others => '0'); |
elsif ((state = PROCESSING) or (state = FINALIZE)) and (operation = '1') then -- running? |
elsif (state = PROCESSING) or (state = FINALIZE) then -- running? |
quotient <= quotient(30 downto 0) & (not div_sub(32)); |
if (div_sub(32) = '0') then -- still overflowing |
remainder <= div_sub(31 downto 0); |
287,24 → 289,22
end if; |
end process divider_core; |
|
-- DIV: try another subtraction -- |
div_sub <= std_ulogic_vector(unsigned('0' & remainder(30 downto 0) & quotient(31)) - unsigned('0' & opy)); |
-- try another subtraction -- |
div_sub <= std_ulogic_vector(unsigned('0' & remainder(30 downto 0) & quotient(31)) - unsigned('0' & div_opy)); |
|
-- Div sign compensation -- |
div_sign_comp_in <= opx when (state = INIT_OPX) else |
opy when (state = INIT_OPY) else |
quotient when ((cp_op = cp_op_div_c) or (cp_op = cp_op_divu_c)) else remainder; |
div_sign_comp <= std_ulogic_vector(0 - unsigned(div_sign_comp_in)); |
-- result sign compensation -- |
div_sign_comp_in <= quotient when (cp_op = cp_op_div_c) else remainder; |
div_sign_comp <= std_ulogic_vector(0 - unsigned(div_sign_comp_in)); |
div_res <= div_sign_comp when (div_res_corr = '1') and (opy_is_zero = '0') else div_sign_comp_in; |
|
-- result sign correction -- |
div_res <= div_sign_comp when (div_res_corr = '1') and (opy_is_zero = '0') else div_sign_comp_in; |
|
|
-- Data Output ---------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
operation_result: process(clk_i) |
operation_result: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
res_o <= (others => def_rst_val_c); |
elsif rising_edge(clk_i) then |
res_o <= (others => '0'); |
if (valid = '1') then |
case cp_op_ff is |
320,7 → 320,7
if (opy_is_zero = '0') then |
res_o <= div_res; |
else |
res_o <= rs1; |
res_o <= rs1_i; |
end if; |
when others => -- cp_op_remu_c |
res_o <= remainder; |
/neorv32/trunk/rtl/core/neorv32_icache.vhd
556,10 → 556,9
else |
tag_mem_s1(to_integer(unsigned(cache_index))) <= ctrl_acc_addr.tag; |
end if; |
else -- read access |
tag(0) <= tag_mem_s0(to_integer(unsigned(cache_index))); |
tag(1) <= tag_mem_s1(to_integer(unsigned(cache_index))); |
end if; |
tag(0) <= tag_mem_s0(to_integer(unsigned(cache_index))); |
tag(1) <= tag_mem_s1(to_integer(unsigned(cache_index))); |
end if; |
end process tag_memory; |
|
584,15 → 583,15
begin |
if rising_edge(clk_i) then |
if (cache_we = '1') then -- write access from control (full-word) |
if (set_select = '0') then |
if (set_select = '0') or (ICACHE_NUM_SETS = 1) then |
cache_data_memory_s0(to_integer(unsigned(cache_addr))) <= ctrl_wdata_i; |
else |
cache_data_memory_s1(to_integer(unsigned(cache_addr))) <= ctrl_wdata_i; |
end if; |
else -- read access from host (full-word) |
cache_rdata(0) <= cache_data_memory_s0(to_integer(unsigned(cache_addr))); |
cache_rdata(1) <= cache_data_memory_s1(to_integer(unsigned(cache_addr))); |
end if; |
-- read access from host (full-word) -- |
cache_rdata(0) <= cache_data_memory_s0(to_integer(unsigned(cache_addr))); |
cache_rdata(1) <= cache_data_memory_s1(to_integer(unsigned(cache_addr))); |
end if; |
end process cache_mem_access; |
|
/neorv32/trunk/rtl/core/neorv32_mtime.vhd
1,17 → 1,12
-- ################################################################################################# |
-- # << NEORV32 - Machine System Timer (MTIME) >> # |
-- # ********************************************************************************************* # |
-- # Compatible to RISC-V spec's mtime & mtimecmp. # |
-- # Write mtime.LO first when updating the system time. System time should be written only at # |
-- # system start. RISC-V spec. exception: The MTIME interrupt is ACKed by the processor itself. # |
-- # However, the achine time cannot issue a new interrupt until the mtimecmp.HI register is # |
-- # written again. # |
-- # Note: The 64-bit time and compare system is broken and de-coupled into two 32-bit systems. # |
-- # Note: The register of this unit can only be written in WORD MODE. # |
-- # Compatible to RISC-V spec's 64-bit MACHINE system timer including "mtime[h]" & "mtimecmp[h]". # |
-- # Note: The 64-bit counter and compare system is broken and de-coupled into two 32-bit systems. # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. # |
-- # # |
-- # Redistribution and use in source and binary forms, with or without modification, are # |
-- # permitted provided that the following conditions are met: # |
125,7 → 120,7
-- mtime high -- |
if (wren = '1') and (addr = mtime_time_hi_addr_c) then |
mtime_hi <= data_i; |
elsif ((mtime_lo_msb_ff xor mtime_lo(mtime_lo'left)) = '1') then -- mtime_lo carry? |
elsif ((mtime_lo_msb_ff xor mtime_lo(mtime_lo'left)) = '1') then -- auto increment: mtime_lo carry? |
mtime_hi <= std_ulogic_vector(unsigned(mtime_hi) + 1); |
end if; |
end if; |
147,7 → 142,7
data_o <= mtime_hi; |
when mtime_cmp_lo_addr_c => -- mtimecmp LOW |
data_o <= mtimecmp_lo; |
when others => -- mtime_cmp_hi_addr_c - mtimecmp HIGH |
when others => -- mtime_cmp_hi_addr_c -- mtimecmp HIGH |
data_o <= mtimecmp_hi; |
end case; |
end if; |
/neorv32/trunk/rtl/core/neorv32_package.vhd
50,8 → 50,9
constant xbus_big_endian_c : boolean := true; -- external memory access byte order: true=big endian (default); false=little endian |
|
-- CPU core -- |
constant ipb_entries_c : natural := 2; -- entries in CPU instruction prefetch buffer, has to be a power of 2, default=2 |
constant cp_timeout_en_c : boolean := false; -- auto-terminate pending co-processor operations after 256 cycles (for debugging only), default = false |
constant ipb_entries_c : natural := 2; -- entries in CPU instruction prefetch buffer, has to be a power of 2, default=2 |
constant cp_timeout_en_c : boolean := false; -- auto-terminate pending co-processor operations after 256 cycles (for debugging only), default = false |
constant dedicated_reset_c : boolean := false; -- use dedicated hardware reset value for UNCRITICAL registers (FALSE=reset value is irrelevant (might simplify HW), default; TRUE=defined LOW reset value) |
|
-- "critical" number of implemented PMP regions -- |
-- if more PMP regions (> pmp_num_regions_critical_c) are defined, another register stage is automatically inserted into the memory interfaces |
58,19 → 59,13
-- increasing instruction fetch & data access latency by +1 cycle but also reducing critical path length |
constant pmp_num_regions_critical_c : natural := 8; -- default=8 |
|
-- Architecture Constants (do not modify!) ------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
constant data_width_c : natural := 32; -- native data path width - do not change! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01050302"; -- no touchy! |
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED! |
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off! |
constant rf_r0_is_reg_c : boolean := true; -- reg_file.r0 is a *physical register* that has to be initialized to zero by the CPU HW |
|
-- Helper Functions ----------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
function index_size_f(input : natural) return natural; |
function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural; |
function cond_sel_int_f(cond : boolean; val_t : integer; val_f : integer) return integer; |
function cond_sel_stdulogicvector_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector; |
function cond_sel_stdulogic_f(cond : boolean; val_t : std_ulogic; val_f : std_ulogic) return std_ulogic; |
function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string; |
function bool_to_ulogic_f(cond : boolean) return std_ulogic; |
function or_all_f(a : std_ulogic_vector) return std_ulogic; |
83,6 → 78,14
function is_power_of_two_f(input : natural) return boolean; |
function bswap32_f(input : std_ulogic_vector) return std_ulogic_vector; |
|
-- Architecture Constants (do not modify!) ------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
constant data_width_c : natural := 32; -- native data path width - do not change! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01050400"; -- no touchy! |
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off! |
constant rf_r0_is_reg_c : boolean := true; -- x0 is a *physical register* that has to be initialized to zero by the CPU |
constant def_rst_val_c : std_ulogic := cond_sel_stdulogic_f(dedicated_reset_c, '0', '-'); |
|
-- Internal Types ------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
type pmp_ctrl_if_t is array (0 to 63) of std_ulogic_vector(07 downto 0); |
97,121 → 100,121
--> internal data/instruction memory sizes are configured via top's generics |
|
-- Internal Bootloader ROM -- |
constant boot_rom_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFF0000"; -- bootloader base address, fixed! |
constant boot_rom_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffff0000"; -- bootloader base address, fixed! |
constant boot_rom_size_c : natural := 4*1024; -- module's address space in bytes |
constant boot_rom_max_size_c : natural := 32*1024; -- max module's address space in bytes, fixed! |
|
-- IO: Peripheral Devices ("IO") Area -- |
-- Control register(s) (including the device-enable) should be located at the base address of each device |
constant io_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF00"; |
constant io_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff00"; |
constant io_size_c : natural := 64*4; -- module's address space in bytes, fixed! |
|
-- Custom Functions Subsystem (CFS) -- |
constant cfs_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF00"; -- base address |
constant cfs_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff00"; -- base address |
constant cfs_size_c : natural := 32*4; -- module's address space in bytes |
constant cfs_reg0_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF00"; |
constant cfs_reg1_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF04"; |
constant cfs_reg2_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF08"; |
constant cfs_reg3_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF0C"; |
constant cfs_reg4_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF10"; |
constant cfs_reg5_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF14"; |
constant cfs_reg6_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF18"; |
constant cfs_reg7_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF1C"; |
constant cfs_reg8_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF20"; |
constant cfs_reg9_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF24"; |
constant cfs_reg10_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF28"; |
constant cfs_reg11_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF2C"; |
constant cfs_reg12_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF30"; |
constant cfs_reg13_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF34"; |
constant cfs_reg14_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF38"; |
constant cfs_reg15_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF3C"; |
constant cfs_reg16_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF40"; |
constant cfs_reg17_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF44"; |
constant cfs_reg18_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF48"; |
constant cfs_reg19_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF4C"; |
constant cfs_reg20_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF50"; |
constant cfs_reg21_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF54"; |
constant cfs_reg22_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF58"; |
constant cfs_reg23_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF5C"; |
constant cfs_reg24_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF60"; |
constant cfs_reg25_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF64"; |
constant cfs_reg26_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF68"; |
constant cfs_reg27_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF6C"; |
constant cfs_reg28_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF70"; |
constant cfs_reg29_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF74"; |
constant cfs_reg30_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF78"; |
constant cfs_reg31_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF7C"; |
constant cfs_reg0_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff00"; |
constant cfs_reg1_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff04"; |
constant cfs_reg2_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff08"; |
constant cfs_reg3_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff0c"; |
constant cfs_reg4_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff10"; |
constant cfs_reg5_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff14"; |
constant cfs_reg6_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff18"; |
constant cfs_reg7_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff1c"; |
constant cfs_reg8_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff20"; |
constant cfs_reg9_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff24"; |
constant cfs_reg10_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff28"; |
constant cfs_reg11_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff2c"; |
constant cfs_reg12_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff30"; |
constant cfs_reg13_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff34"; |
constant cfs_reg14_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff38"; |
constant cfs_reg15_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff3c"; |
constant cfs_reg16_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff40"; |
constant cfs_reg17_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff44"; |
constant cfs_reg18_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff48"; |
constant cfs_reg19_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff4c"; |
constant cfs_reg20_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff50"; |
constant cfs_reg21_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff54"; |
constant cfs_reg22_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff58"; |
constant cfs_reg23_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff5c"; |
constant cfs_reg24_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff60"; |
constant cfs_reg25_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff64"; |
constant cfs_reg26_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff68"; |
constant cfs_reg27_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff6c"; |
constant cfs_reg28_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff70"; |
constant cfs_reg29_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff74"; |
constant cfs_reg30_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff78"; |
constant cfs_reg31_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff7c"; |
|
-- General Purpose Input/Output Unit (GPIO) -- |
constant gpio_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF80"; -- base address |
constant gpio_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff80"; -- base address |
constant gpio_size_c : natural := 2*4; -- module's address space in bytes |
constant gpio_in_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF80"; |
constant gpio_out_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF84"; |
constant gpio_in_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff80"; |
constant gpio_out_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff84"; |
|
-- True Random Number Generator (TRNG) -- |
constant trng_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF88"; -- base address |
constant trng_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff88"; -- base address |
constant trng_size_c : natural := 1*4; -- module's address space in bytes |
constant trng_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF88"; |
constant trng_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff88"; |
|
-- Watch Dog Timer (WDT) -- |
constant wdt_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF8C"; -- base address |
constant wdt_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff8c"; -- base address |
constant wdt_size_c : natural := 1*4; -- module's address space in bytes |
constant wdt_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF8C"; |
constant wdt_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff8c"; |
|
-- Machine System Timer (MTIME) -- |
constant mtime_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF90"; -- base address |
constant mtime_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff90"; -- base address |
constant mtime_size_c : natural := 4*4; -- module's address space in bytes |
constant mtime_time_lo_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF90"; |
constant mtime_time_hi_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF94"; |
constant mtime_cmp_lo_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF98"; |
constant mtime_cmp_hi_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF9C"; |
constant mtime_time_lo_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff90"; |
constant mtime_time_hi_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff94"; |
constant mtime_cmp_lo_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff98"; |
constant mtime_cmp_hi_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffff9c"; |
|
-- Universal Asynchronous Receiver/Transmitter 0 (UART0), primary UART -- |
constant uart0_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA0"; -- base address |
constant uart0_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffa0"; -- base address |
constant uart0_size_c : natural := 2*4; -- module's address space in bytes |
constant uart0_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA0"; |
constant uart0_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA4"; |
constant uart0_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffa0"; |
constant uart0_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffa4"; |
|
-- Serial Peripheral Interface (SPI) -- |
constant spi_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA8"; -- base address |
constant spi_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffa8"; -- base address |
constant spi_size_c : natural := 2*4; -- module's address space in bytes |
constant spi_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA8"; |
constant spi_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFAC"; |
constant spi_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffa8"; |
constant spi_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffac"; |
|
-- Two Wire Interface (TWI) -- |
constant twi_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB0"; -- base address |
constant twi_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffb0"; -- base address |
constant twi_size_c : natural := 2*4; -- module's address space in bytes |
constant twi_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB0"; |
constant twi_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB4"; |
constant twi_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffb0"; |
constant twi_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffb4"; |
|
-- Pulse-Width Modulation Controller (PWM) -- |
constant pwm_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB8"; -- base address |
constant pwm_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffb8"; -- base address |
constant pwm_size_c : natural := 2*4; -- module's address space in bytes |
constant pwm_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB8"; |
constant pwm_duty_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFBC"; |
constant pwm_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffb8"; |
constant pwm_duty_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffbc"; |
|
-- Numerically-Controlled Oscillator (NCO) -- |
constant nco_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC0"; -- base address |
constant nco_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffc0"; -- base address |
constant nco_size_c : natural := 4*4; -- module's address space in bytes |
constant nco_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC0"; |
constant nco_ch0_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC4"; |
constant nco_ch1_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC8"; |
constant nco_ch2_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFCC"; |
constant nco_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffc0"; |
constant nco_ch0_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffc4"; |
constant nco_ch1_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffc8"; |
constant nco_ch2_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffcc"; |
|
-- Universal Asynchronous Receiver/Transmitter 1 (UART1), secondary UART -- |
constant uart1_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD0"; -- base address |
constant uart1_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffd0"; -- base address |
constant uart1_size_c : natural := 2*4; -- module's address space in bytes |
constant uart1_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD0"; |
constant uart1_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD4"; |
constant uart1_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffd0"; |
constant uart1_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffd4"; |
|
-- Smart LED (WS2811/WS2812) Interface (NEOLED) -- |
constant neoled_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8"; -- base address |
constant neoled_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffd8"; -- base address |
constant neoled_size_c : natural := 2*4; -- module's address space in bytes |
constant neoled_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8"; |
constant neoled_data_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFDC"; |
constant neoled_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffd8"; |
constant neoled_data_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffdc"; |
|
-- System Information Memory (SYSINFO) -- |
constant sysinfo_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFE0"; -- base address |
constant sysinfo_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"ffffffe0"; -- base address |
constant sysinfo_size_c : natural := 8*4; -- module's address space in bytes |
|
-- Main Control Bus ----------------------------------------------------------------------- |
263,7 → 266,7
constant ctrl_bus_excl_c : natural := 41; -- exclusive bus access |
-- co-processors -- |
constant ctrl_cp_id_lsb_c : natural := 42; -- cp select ID lsb |
constant ctrl_cp_id_hsb_c : natural := 43; -- cp select ID hsb |
constant ctrl_cp_id_hsb_c : natural := 43; -- cp select ID |
constant ctrl_cp_id_msb_c : natural := 44; -- cp select ID msb |
-- current privilege level -- |
constant ctrl_priv_lvl_lsb_c : natural := 45; -- privilege level lsb |
438,23 → 441,23
|
-- RISC-V CSR Addresses ------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- read/write CSRs -- |
-- <<< standard read/write CSRs >>> -- |
-- user floating-point CSRs -- |
constant csr_class_float_c : std_ulogic_vector(07 downto 0) := x"00"; -- floating point |
constant csr_fflags_c : std_ulogic_vector(11 downto 0) := x"001"; |
constant csr_frm_c : std_ulogic_vector(11 downto 0) := x"002"; |
constant csr_fcsr_c : std_ulogic_vector(11 downto 0) := x"003"; |
-- |
constant csr_setup_c : std_ulogic_vector(07 downto 0) := x"30"; -- trap setup |
-- machine trap setup -- |
constant csr_class_setup_c : std_ulogic_vector(07 downto 0) := x"30"; -- trap setup |
constant csr_mstatus_c : std_ulogic_vector(11 downto 0) := x"300"; |
constant csr_misa_c : std_ulogic_vector(11 downto 0) := x"301"; |
constant csr_mie_c : std_ulogic_vector(11 downto 0) := x"304"; |
constant csr_mtvec_c : std_ulogic_vector(11 downto 0) := x"305"; |
constant csr_mcounteren_c : std_ulogic_vector(11 downto 0) := x"306"; |
-- |
constant csr_mstatush_c : std_ulogic_vector(11 downto 0) := x"310"; |
-- |
-- machine counter setup -- |
constant csr_cnt_setup_c : std_ulogic_vector(06 downto 0) := x"3" & "001"; -- counter setup |
constant csr_mcountinhibit_c : std_ulogic_vector(11 downto 0) := x"320"; |
-- |
constant csr_mhpmevent3_c : std_ulogic_vector(11 downto 0) := x"323"; |
constant csr_mhpmevent4_c : std_ulogic_vector(11 downto 0) := x"324"; |
constant csr_mhpmevent5_c : std_ulogic_vector(11 downto 0) := x"325"; |
484,7 → 487,7
constant csr_mhpmevent29_c : std_ulogic_vector(11 downto 0) := x"33d"; |
constant csr_mhpmevent30_c : std_ulogic_vector(11 downto 0) := x"33e"; |
constant csr_mhpmevent31_c : std_ulogic_vector(11 downto 0) := x"33f"; |
-- |
-- machine trap handling -- |
constant csr_class_trap_c : std_ulogic_vector(07 downto 0) := x"34"; -- machine trap handling |
constant csr_mscratch_c : std_ulogic_vector(11 downto 0) := x"340"; |
constant csr_mepc_c : std_ulogic_vector(11 downto 0) := x"341"; |
491,7 → 494,7
constant csr_mcause_c : std_ulogic_vector(11 downto 0) := x"342"; |
constant csr_mtval_c : std_ulogic_vector(11 downto 0) := x"343"; |
constant csr_mip_c : std_ulogic_vector(11 downto 0) := x"344"; |
-- |
-- physical memory protection - configuration -- |
constant csr_class_pmpcfg_c : std_ulogic_vector(07 downto 0) := x"3a"; -- pmp configuration |
constant csr_pmpcfg0_c : std_ulogic_vector(11 downto 0) := x"3a0"; |
constant csr_pmpcfg1_c : std_ulogic_vector(11 downto 0) := x"3a1"; |
509,7 → 512,7
constant csr_pmpcfg13_c : std_ulogic_vector(11 downto 0) := x"3ad"; |
constant csr_pmpcfg14_c : std_ulogic_vector(11 downto 0) := x"3ae"; |
constant csr_pmpcfg15_c : std_ulogic_vector(11 downto 0) := x"3af"; |
-- |
-- physical memory protection - address -- |
constant csr_pmpaddr0_c : std_ulogic_vector(11 downto 0) := x"3b0"; |
constant csr_pmpaddr1_c : std_ulogic_vector(11 downto 0) := x"3b1"; |
constant csr_pmpaddr2_c : std_ulogic_vector(11 downto 0) := x"3b2"; |
574,7 → 577,7
constant csr_pmpaddr61_c : std_ulogic_vector(11 downto 0) := x"3ed"; |
constant csr_pmpaddr62_c : std_ulogic_vector(11 downto 0) := x"3ee"; |
constant csr_pmpaddr63_c : std_ulogic_vector(11 downto 0) := x"3ef"; |
-- |
-- machine counters/timers -- |
constant csr_mcycle_c : std_ulogic_vector(11 downto 0) := x"b00"; |
constant csr_minstret_c : std_ulogic_vector(11 downto 0) := x"b02"; |
-- |
641,7 → 644,8
constant csr_mhpmcounter30h_c : std_ulogic_vector(11 downto 0) := x"b9e"; |
constant csr_mhpmcounter31h_c : std_ulogic_vector(11 downto 0) := x"b9f"; |
|
-- read-only CSRs -- |
-- <<< standard read-only CSRs >>> -- |
-- user counters/timers -- |
constant csr_cycle_c : std_ulogic_vector(11 downto 0) := x"c00"; |
constant csr_time_c : std_ulogic_vector(11 downto 0) := x"c01"; |
constant csr_instret_c : std_ulogic_vector(11 downto 0) := x"c02"; |
709,13 → 713,12
constant csr_hpmcounter29h_c : std_ulogic_vector(11 downto 0) := x"c9d"; |
constant csr_hpmcounter30h_c : std_ulogic_vector(11 downto 0) := x"c9e"; |
constant csr_hpmcounter31h_c : std_ulogic_vector(11 downto 0) := x"c9f"; |
-- |
-- machine information registers -- |
constant csr_mvendorid_c : std_ulogic_vector(11 downto 0) := x"f11"; |
constant csr_marchid_c : std_ulogic_vector(11 downto 0) := x"f12"; |
constant csr_mimpid_c : std_ulogic_vector(11 downto 0) := x"f13"; |
constant csr_mhartid_c : std_ulogic_vector(11 downto 0) := x"f14"; |
|
-- custom read-only CSRs -- |
-- <<< custom (NEORV32-specific) read-only CSRs >>> -- |
constant csr_mzext_c : std_ulogic_vector(11 downto 0) := x"fc0"; |
|
-- Co-Processor IDs ----------------------------------------------------------------------- |
763,7 → 766,6
constant trap_mti_c : std_ulogic_vector(5 downto 0) := "1" & "00111"; -- 1.7: machine timer interrupt |
constant trap_mei_c : std_ulogic_vector(5 downto 0) := "1" & "01011"; -- 1.11: machine external interrupt |
-- NEORV32-specific (custom) interrupts (async. exceptions) -- |
constant trap_reset_c : std_ulogic_vector(5 downto 0) := "1" & "00000"; -- 1.0: hardware reset |
constant trap_firq0_c : std_ulogic_vector(5 downto 0) := "1" & "10000"; -- 1.16: fast interrupt 0 |
constant trap_firq1_c : std_ulogic_vector(5 downto 0) := "1" & "10001"; -- 1.17: fast interrupt 1 |
constant trap_firq2_c : std_ulogic_vector(5 downto 0) := "1" & "10010"; -- 1.18: fast interrupt 2 |
827,7 → 829,7
-- HPM Event System ----------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant hpmcnt_event_cy_c : natural := 0; -- Active cycle |
constant hpmcnt_event_never_c : natural := 1; |
constant hpmcnt_event_never_c : natural := 1; -- Unused / never (actually, this would be used for TIME) |
constant hpmcnt_event_ir_c : natural := 2; -- Retired instruction |
constant hpmcnt_event_cir_c : natural := 3; -- Retired compressed instruction |
constant hpmcnt_event_wait_if_c : natural := 4; -- Instruction fetch memory wait cycle |
871,17 → 873,20
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!) |
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!) |
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.? |
-- Extension Options -- |
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
TINY_SHIFT_EN : boolean := false; -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (1..64) |
-- Internal Instruction memory -- |
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes |
907,7 → 912,7
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)? |
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic |
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits |
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)? |
993,11 → 998,14
-- Extension Options -- |
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
TINY_SHIFT_EN : boolean := false; -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29) |
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH : natural := 40 -- total size of HPM counters (1..64) |
); |
port ( |
-- global control -- |
1059,11 → 1067,14
CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!) |
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.? |
-- Extension Options -- |
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64) |
-- Physical memory protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0 -- number of implemented HPM counters (0..29) |
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH : natural := 40 -- total size of HPM counters (1..64) |
); |
port ( |
-- global control -- |
1134,8 → 1145,9
-- ------------------------------------------------------------------------------------------- |
component neorv32_cpu_alu |
generic ( |
CPU_EXTENSION_RISCV_M : boolean := true; -- implement muld/div extension? |
FAST_SHIFT_EN : boolean := false -- use barrel shifter for shift operations |
CPU_EXTENSION_RISCV_M : boolean := true; -- implement muld/div extension? |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
TINY_SHIFT_EN : boolean := false -- use tiny (single-bit) shifter for shift operations |
); |
port ( |
-- global control -- |
1210,6 → 1222,7
start_i : in std_ulogic; -- trigger operation |
-- data input -- |
frm_i : in std_ulogic_vector(2 downto 0); -- rounding mode |
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status |
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1 |
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2 |
-- result and status -- |
1804,6 → 1817,17
end if; |
end function cond_sel_natural_f; |
|
-- Function: Conditional select integer --------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
function cond_sel_int_f(cond : boolean; val_t : integer; val_f : integer) return integer is |
begin |
if (cond = true) then |
return val_t; |
else |
return val_f; |
end if; |
end function cond_sel_int_f; |
|
-- Function: Conditional select std_ulogic_vector ----------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
function cond_sel_stdulogicvector_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector is |
1815,6 → 1839,17
end if; |
end function cond_sel_stdulogicvector_f; |
|
-- Function: Conditional select std_ulogic ------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
function cond_sel_stdulogic_f(cond : boolean; val_t : std_ulogic; val_f : std_ulogic) return std_ulogic is |
begin |
if (cond = true) then |
return val_t; |
else |
return val_f; |
end if; |
end function cond_sel_stdulogic_f; |
|
-- Function: Conditional select string ---------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string is |
1842,9 → 1877,9
function or_all_f(a : std_ulogic_vector) return std_ulogic is |
variable tmp_v : std_ulogic; |
begin |
tmp_v := a(a'low); |
tmp_v := '0'; |
if (a'low < a'high) then -- not null range? |
for i in a'low+1 to a'high loop |
for i in a'low to a'high loop |
tmp_v := tmp_v or a(i); |
end loop; -- i |
end if; |
1856,9 → 1891,9
function and_all_f(a : std_ulogic_vector) return std_ulogic is |
variable tmp_v : std_ulogic; |
begin |
tmp_v := a(a'low); |
tmp_v := '1'; |
if (a'low < a'high) then -- not null range? |
for i in a'low+1 to a'high loop |
for i in a'low to a'high loop |
tmp_v := tmp_v and a(i); |
end loop; -- i |
end if; |
1870,9 → 1905,9
function xor_all_f(a : std_ulogic_vector) return std_ulogic is |
variable tmp_v : std_ulogic; |
begin |
tmp_v := a(a'low); |
tmp_v := '0'; |
if (a'low < a'high) then -- not null range? |
for i in a'low+1 to a'high loop |
for i in a'low to a'high loop |
tmp_v := tmp_v xor a(i); |
end loop; -- i |
end if; |
1884,9 → 1919,9
function xnor_all_f(a : std_ulogic_vector) return std_ulogic is |
variable tmp_v : std_ulogic; |
begin |
tmp_v := a(a'low); |
tmp_v := '1'; |
if (a'low < a'high) then -- not null range? |
for i in a'low+1 to a'high loop |
for i in a'low to a'high loop |
tmp_v := tmp_v xnor a(i); |
end loop; -- i |
end if; |
/neorv32/trunk/rtl/core/neorv32_top.vhd
67,6 → 67,8
-- Extension Options -- |
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
TINY_SHIFT_EN : boolean := false; -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64) |
|
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
74,6 → 76,7
|
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (1..64) |
|
-- Internal Instruction memory -- |
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory |
104,7 → 107,7
IO_WDT_EN : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)? |
IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)? |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0); -- custom CFS configuration generic |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic |
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits |
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits |
IO_NCO_EN : boolean := true; -- implement numerically-controlled oscillator (NCO)? |
422,11 → 425,13
-- Extension Options -- |
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations |
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64) |
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS => HPM_NUM_CNTS -- number of implemented HPM counters (0..29) |
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH => HPM_CNT_WIDTH -- total size of HPM counters (1..64) |
) |
port map ( |
-- global control -- |
/neorv32/trunk/rtl/core/neorv32_uart.vhd
403,6 → 403,9
|
-- SIMULATION Output ---------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
-- pragma translate_off |
-- synthesis translate_off |
-- RTL_SYNTHESIS OFF |
sim_output: process(clk_i) -- for SIMULATION ONLY! |
file file_uart_text_out : text open write_mode is sim_uart_text_file_c; |
file file_uart_data_out : text open write_mode is sim_uart_data_file_c; |
451,6 → 454,8
end if; |
end if; |
end process sim_output; |
-- RTL_SYNTHESIS ON |
-- synthesis translate_on |
-- pragma translate_on |
|
|
end neorv32_uart_rtl; |
/neorv32/trunk/rtl/core/neorv32_wishbone.vhd
193,8 → 193,8
ctrl.rd_req <= '0'; |
ctrl.wr_req <= '0'; |
-- buffer all outgoing signals -- |
ctrl.we <= wren_i; |
ctrl.adr <= addr_i; |
ctrl.we <= wren_i or ctrl.wr_req; |
ctrl.adr <= addr_i; |
if (xbus_big_endian_c = true) then -- endianness conversion |
ctrl.wdat <= data_i; |
ctrl.sel <= ben_i; |
206,7 → 206,7
ctrl.excl <= excl_i; |
ctrl.priv <= priv_i; |
-- valid new or buffered read/write request -- |
if ((xbus_access and (wren_i or ctrl.wr_req or rden_i or ctrl.rd_req)) = '1') then |
if ((xbus_access and (wren_i or ctrl.wr_req or rden_i or ctrl.rd_req) and (not cancel_i)) = '1') then |
ctrl.state <= BUSY; |
end if; |
|
237,6 → 237,8
|
when RESYNC => -- make sure transfer is done! |
-- ------------------------------------------------------------ |
ctrl.wr_req <= ctrl.wr_req or wren_i; -- buffer new request |
ctrl.rd_req <= ctrl.rd_req or rden_i; -- buffer new request |
if (wb_ack_i = '0') then |
ctrl.state <= IDLE; |
end if; |
/neorv32/trunk/rtl/top_templates/neorv32_test_setup.vhd
86,11 → 86,14
-- Extension Options -- |
FAST_MUL_EN => false, -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN => false, -- use barrel shifter for shift operations |
TINY_SHIFT_EN => false, -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH => 64, -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS => 2, -- number of regions (0..64) |
PMP_NUM_REGIONS => 0, -- number of regions (0..64) |
PMP_MIN_GRANULARITY => 64*1024, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS => 2, -- number of implemented HPM counters (0..29) |
HPM_NUM_CNTS => 4, -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH => 40, -- total size of HPM counters (1..64) |
-- Internal Instruction memory -- |
MEM_INT_IMEM_EN => true, -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE => 16*1024, -- size of processor-internal instruction memory in bytes |
/neorv32/trunk/rtl/top_templates/neorv32_top_axi4lite.vhd
65,11 → 65,14
-- Extension Options -- |
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
TINY_SHIFT_EN : boolean := false; -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (1..64) |
-- Internal Instruction memory -- |
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes |
266,11 → 269,14
-- Extension Options -- |
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations |
TINY_SHIFT_EN => TINY_SHIFT_EN, -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64) |
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (1..64) |
-- Internal Instruction memory -- |
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes |
/neorv32/trunk/rtl/top_templates/neorv32_top_stdlogic.vhd
59,11 → 59,14
-- Extension Options -- |
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
TINY_SHIFT_EN : boolean := false; -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH : natural := 64; -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64) |
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS : natural := 0; -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH : natural := 40; -- total size of HPM counters (1..64) |
-- Internal Instruction memory -- |
MEM_INT_IMEM_EN : boolean := true; -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes |
236,11 → 239,14
-- Extension Options -- |
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations |
TINY_SHIFT_EN => TINY_SHIFT_EN, -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH => CPU_CNT_WIDTH, -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (0..64) |
PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS => HPM_NUM_CNTS, -- number of implemented HPM counters (0..29) |
HPM_CNT_WIDTH => HPM_CNT_WIDTH, -- total size of HPM counters (1..64) |
-- Internal Instruction memory -- |
MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes |
/neorv32/trunk/sim/ghdl/ghdl_sim.sh
24,15 → 24,15
echo "" |
|
# List files |
echo "Simulation source files:" |
ls -l $srcdir_core |
ls -l $srcdir_sim |
ls -l $srcdir_top_templates |
#echo "Simulation source files:" |
#ls -l $srcdir_core |
#ls -l $srcdir_sim |
#ls -l $srcdir_top_templates |
#echo "" |
|
# Just a hint |
echo "Tip: Compile application with USER_FLAGS+=-DUART[0/1]_SIM_MODE to auto-enable UART[0/1]'s simulation mode (redirect UART output to simulator console)." |
echo "" |
echo "Tip: Compile application with USER_FLAGS+=-DUART_SIM_MODE to auto-enable UART's SIM MODE." |
echo "" |
|
# Analyse sources; libs and images at first! |
ghdl -a --work=neorv32 $srcdir_core/neorv32_package.vhd |
/neorv32/trunk/sim/neorv32_tb.vhd
70,7 → 70,7
constant ext_mem_b_base_addr_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- wishbone memory base address (external DMEM base) |
constant ext_mem_b_size_c : natural := dmem_size_c; -- wishbone memory size in bytes |
constant ext_mem_b_latency_c : natural := 8; -- latency in clock cycles (min 1, max 255), plus 1 cycle initial delay |
-- simulated external Wishbone memory C (can be used as external IO) -- |
-- simulated external Wishbone memory C (can be used to simulate external IO access) -- |
constant ext_mem_c_base_addr_c : std_ulogic_vector(31 downto 0) := x"F0000000"; -- wishbone memory base address (default begin of EXTERNAL IO area) |
constant ext_mem_c_size_c : natural := 64; -- wishbone memory size in bytes |
constant ext_mem_c_latency_c : natural := 3; -- latency in clock cycles (min 1, max 255), plus 1 cycle initial delay |
206,11 → 206,14
-- Extension Options -- |
FAST_MUL_EN => false, -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN => false, -- use barrel shifter for shift operations |
TINY_SHIFT_EN => false, -- use tiny (single-bit) shifter for shift operations |
CPU_CNT_WIDTH => 64, -- total width of CPU cycle and instret counters (0..64) |
-- Physical Memory Protection (PMP) -- |
PMP_NUM_REGIONS => 4, -- number of regions (0..64) |
PMP_MIN_GRANULARITY => 64*1024, -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes |
-- Hardware Performance Monitors (HPM) -- |
HPM_NUM_CNTS => 12, -- number of inmplemnted HPM counters (0..29) |
HPM_CNT_WIDTH => 40, -- total size of HPM counters (1..64) |
-- Internal Instruction memory -- |
MEM_INT_IMEM_EN => int_imem_c , -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE => imem_size_c, -- size of processor-internal instruction memory in bytes |
/neorv32/trunk/sw/bootloader/bootloader.c
68,11 → 68,11
/** Enable auto-boot sequence if != 0 */ |
#define AUTOBOOT_EN (1) |
/** Time until the auto-boot sequence starts (in seconds) */ |
#define AUTOBOOT_TIMEOUT 8 |
#define AUTOBOOT_TIMEOUT (8) |
/** Set to 0 to disable bootloader status LED */ |
#define STATUS_LED_EN (1) |
/** SPI_DIRECT_BOOT_EN: Define/uncomment to enable SPI direct boot (disables the entire user console!) */ |
//#define SPI_DIRECT_BOOT_EN |
/** Set to 1 to enable SPI direct boot (disables the entire user console!) */ |
#define SPI_DIRECT_BOOT_EN (0) |
/** Bootloader status LED at GPIO output port */ |
#define STATUS_LED (0) |
/** SPI flash boot image base address (warning! address might wrap-around!) */ |
84,7 → 84,7
/** SPI flash sector size in bytes (default = 64kb) */ |
#define SPI_FLASH_SECTOR_SIZE (64*1024) |
/** ASCII char to start fast executable upload process (for use with automatic upload scripts) */ |
#define FAST_UPLOAD_CMD '#' |
#define FAST_UPLOAD_CMD ('#') |
/**@}*/ |
|
|
191,8 → 191,9
**************************************************************************/ |
int main(void) { |
|
#ifdef __riscv_compressed |
#warning In order to allow the bootloader to run on any CPU configuration it should be compiled using the base ISA (rv32i/e) only. |
// check ISA |
#if defined __riscv_atomic || defined __riscv_a || __riscv_b || __riscv_compressed || defined __riscv_c || defined __riscv_mul || defined __riscv_m |
#warning In order to allow the bootloader to run on *ANY* CPU configuration it should be compiled using the base ISA (rv32i/e) only. |
#endif |
|
exe_available = 0; // global variable for executable size; 0 means there is no exe available |
214,10 → 215,10
neorv32_spi_setup(CLK_PRSC_128, 0, 0); |
} |
|
if (STATUS_LED_EN == 1) { |
#if (STATUS_LED_EN != 0) |
// activate status LED, clear all others |
neorv32_gpio_port_set(1 << STATUS_LED); |
} |
#endif |
|
// init UART (no parity bit, no hardware flow control) |
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE); |
238,7 → 239,7
// Bootloader will directly boot and execute image from SPI memory. |
// No user UART console is available in this mode! |
// ------------------------------------------------ |
#ifdef SPI_DIRECT_BOOT_EN |
#if (SPI_DIRECT_BOOT_EN != 0) |
#warning Compiling bootloader in 'SPI direct boot mode'. Bootloader will directly boot from SPI memory. No user UART console will be available. |
|
neorv32_uart_print("\nNEORV32 bootloader\nAccessing SPI flash at "); |
418,10 → 419,10
|
// make sure this was caused by MTIME IRQ |
if (cause == TRAP_CODE_MTI) { // raw exception code for MTI |
if (STATUS_LED_EN == 1) { |
#if (STATUS_LED_EN != 0) |
// toggle status LED |
neorv32_gpio_pin_toggle(STATUS_LED); |
} |
#endif |
// set time for next IRQ |
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (SYSINFO_CLK/4)); |
} |
433,9 → 434,9
} |
// unknown error |
else { |
neorv32_uart_print("\n\nEXC ("); |
neorv32_uart_print("\n\nEXCEPTION mcause="); |
print_hex_word(cause); |
neorv32_uart_print(") @ 0x"); |
neorv32_uart_print(" @ pc="); |
print_hex_word(neorv32_cpu_csr_read(CSR_MEPC)); |
system_error(ERROR_SYSTEM); |
} |
633,7 → 634,7
**************************************************************************/ |
void print_hex_word(uint32_t num) { |
|
static const char hex_symbols[16] = "0123456789ABCDEF"; |
static const char hex_symbols[16] = "0123456789abcdef"; |
|
neorv32_uart_print("0x"); |
|
/neorv32/trunk/sw/common/crt0.S
69,14 → 69,58
|
|
// ********************************************************* |
// Initialize dummy trap handler base address |
// Setup pointers using linker script symbols |
// ********************************************************* |
__crt0_neorv32_trap_init: |
la x11, __crt0_dummy_trap_handler |
csrw mtvec, x11 // set address of first-level exception handler |
__crt0_pointer_init: |
.option push |
.option norelax |
la sp, __crt0_stack_begin |
andi sp, sp, 0xfffffffc // make sure this is aligned |
addi fp, sp, 0 // frame pointer = stack pointer |
la gp, __global_pointer$ // global pointer |
.option pop |
|
|
// ********************************************************* |
// Setup CPU core CSRs (some of them DO NOT have a dedicated reset and need to be explicitly initialized) |
// ********************************************************* |
__crt0_cpu_csr_init: |
|
// set address of first-level exception handler |
la x10, __crt0_dummy_trap_handler |
csrw mtvec, x10 |
csrw mepc, x10 |
csrw mtval, zero |
csrw mcause, zero |
|
// no global IRQ enable (is also done by hardware) |
csrw mstatus, zero |
|
// absolutely no interrupts, thanks |
csrw mie, zero |
|
// no access from less-privileged modes to counter CSRs |
csrw mcounteren, zero |
|
// stop all counters except for [m]cycle[h] and [m]instret[h] |
li x11, ~5 |
csrw mcountinhibit, x11 |
|
// clear cycle counters |
csrw mcycle, zero |
csrw mcycleh, zero |
|
// clear instruction counters |
csrw minstret, zero |
csrw minstreth, zero |
|
#if defined(__riscv_flen) && (__riscv_flen != 0) |
// clear floating-point CSR (rounding mode & exception flags) |
csrw fcsr, zero |
#endif |
|
|
// ********************************************************* |
// Clear integer register file (upper half, if no E extension) |
// ********************************************************* |
#ifndef __riscv_32e |
103,28 → 147,6
|
|
// ********************************************************* |
// No interrupts, thanks |
// ********************************************************* |
__crt0_status_init: |
li x10, 0x00001800 // clear mstatus and set mpp(1:0) |
csrrw zero, mstatus, x10 |
csrrw zero, mie, zero // clear mie |
|
|
// ********************************************************* |
// Setup pointers using linker script symbols |
// ********************************************************* |
__crt0_pointer_init: |
.option push |
.option norelax |
la sp, __crt0_stack_begin |
andi sp, sp, 0xfffffffc // make sure this is aligned |
addi fp, sp, 0 // frame pointer = stack pointer |
la gp, __global_pointer$ // global pointer |
.option pop |
|
|
// ********************************************************* |
// Reset/deactivate IO/peripheral devices |
// Devices, that are not implemented, will cause a store access fault |
// which is captured but actually ignored due to the dummy handler. |
182,20 → 204,6
addi x10, zero, 0 // argc = 0 |
addi x11, zero, 0 // argv = 0 |
|
// clear cycle and instruction counters |
csrw mcycle, zero |
csrw mcycleh, zero |
csrw minstret, zero |
csrw minstreth, zero |
// enable read-access from user-mode for cycle[h], time[h] and instret[h] |
csrwi 0x306, 7 // mcounteren |
// enable auto-increment of all counters |
csrw 0x320, x0 // mcountinhibit |
|
// restore mcause reset value (so that 'main' knows we are coming from reset) |
li x12, 0x80000000 |
csrw mcause, x12 |
|
// call actual app's main function |
jal ra, main |
|
/neorv32/trunk/sw/example/cpu_test/main.c
48,13 → 48,17
**************************************************************************/ |
/**@{*/ |
/** UART BAUD rate */ |
#define BAUD_RATE 19200 |
#define BAUD_RATE (19200) |
//** Reachable unaligned address */ |
#define ADDR_UNALIGNED 0x00000002 |
#define ADDR_UNALIGNED (0x00000002) |
//** Unreachable word-aligned address */ |
#define ADDR_UNREACHABLE (IO_BASE_ADDRESS-4) |
//* external memory base address */ |
#define EXT_MEM_BASE 0xF0000000 |
#define ADDR_UNREACHABLE (IO_BASE_ADDRESS-4) |
//** external memory base address */ |
#define EXT_MEM_BASE (0xF0000000) |
//** exclusive access to this address will always succeed */ |
#define ATOMIC_SUCCESS_ADDR (EXT_MEM_BASE + 0) |
//** exclusive access to this address will always fail */ |
#define ATOMIC_FAILURE_ADDR (EXT_MEM_BASE + 4) |
/**@}*/ |
|
|
71,30 → 75,11
int cnt_ok = 0; |
/// Global counter for total number of tests |
int cnt_test = 0; |
/// Global timestamp for traps (stores mcycle.low on trap enter) |
uint32_t trap_timestamp32 = 0; |
/// Global numbe rof available HPMs |
uint32_t num_hpm_cnts_global = 0; |
|
|
/**********************************************************************//** |
* Unreachable memory-mapped register that should be always available |
**************************************************************************/ |
#define MMR_UNREACHABLE (*(IO_REG32 (ADDR_UNREACHABLE))) |
|
|
/**********************************************************************//** |
* "Simulated external IO" - exclusive access will always succeed |
**************************************************************************/ |
# define ATOMIC_SUCCESS (*(IO_REG32 (EXT_MEM_BASE + 0))) |
|
/**********************************************************************//** |
* "Simulated external IO" - exclusive access will always fail |
**************************************************************************/ |
# define ATOMIC_FAILURE (*(IO_REG32 (EXT_MEM_BASE + 4))) |
|
|
/**********************************************************************//** |
* High-level CPU/processor test program. |
* |
* @note Applications has to be compiler with <USER_FLAGS+=-DRUN_CPUTEST> |
103,7 → 88,6
**************************************************************************/ |
int main() { |
|
volatile uint64_t temp64; |
register uint32_t tmp_a, tmp_b; |
volatile uint32_t dummy_dst __attribute__((unused)); |
uint8_t id; |
110,7 → 94,7
uint32_t is_simulation = 0; |
|
|
// init UART at default baud rate, no parity bits, ho hw flow control |
// init UART at default baud rate, no parity bits, no hw flow control |
neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE); |
|
// Disable cpu_test compilation by default |
131,26 → 115,25
is_simulation = 0; |
} |
|
neorv32_uart_printf("\n<< CPU/PROCESSOR TEST >>\n"); |
neorv32_uart_printf("build: "__DATE__" "__TIME__"\n"); |
// ---------------------------------------------- |
// setup RTE |
neorv32_rte_setup(); // this will install a full-detailed debug handler for ALL traps |
// ---------------------------------------------- |
|
// check if we came from hardware reset |
neorv32_uart_printf("\nComing from HW reset? "); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_RESET) { |
neorv32_uart_printf("yes\n"); |
} |
else { |
neorv32_uart_printf("unknown\n"); |
} |
|
// check available hardware extensions and compare with compiler flags |
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch |
|
|
// intro |
neorv32_uart_printf("\n<< CPU/PROCESSOR TEST >>\n"); |
neorv32_uart_printf("build: "__DATE__" "__TIME__"\n"); |
|
|
// reset performance counter |
neorv32_cpu_set_minstret(0); |
neorv32_cpu_set_mcycle(0); |
|
neorv32_cpu_csr_write(CSR_MCYCLEH, 0); |
neorv32_cpu_csr_write(CSR_MCYCLE, 0); |
neorv32_cpu_csr_write(CSR_MINSTRETH, 0); |
neorv32_cpu_csr_write(CSR_MINSTRET, 0); |
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // enable performance counter auto increment (ALL counters) |
neorv32_cpu_csr_write(CSR_MCOUNTEREN, 7); // allow access from user-mode code to standard counters only |
|
174,10 → 157,8
|
// configure RTE |
// ----------------------------------------------- |
neorv32_uart_printf("\n\nInitializing NEORV32 RTE... "); |
neorv32_uart_printf("\n\nConfiguring NEORV32 RTE... "); |
|
neorv32_rte_setup(); // this will install a full-detailed debug handler for all traps |
|
int install_err = 0; |
// initialize ALL provided trap handler (overriding the default debug handlers) |
for (id=0; id<NEORV32_RTE_NUM_TRAPS; id++) { |
210,15 → 191,15
|
cnt_test++; |
|
// get current cycle counter |
temp64 = neorv32_cpu_get_cycle(); |
// make sure counter is enabled |
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_CY)); |
|
// wait some time to have a nice increment |
asm volatile ("nop"); |
asm volatile ("nop"); |
// get current cycle counter LOW |
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLE); |
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLE) - tmp_a; |
|
// make sure cycle counter has incremented and there was no exception during access |
if ((neorv32_cpu_get_cycle() > temp64) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
if ((tmp_a > 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
test_ok(); |
} |
else { |
234,17 → 215,22
|
cnt_test++; |
|
// get current instruction counter |
temp64 = neorv32_cpu_get_instret(); |
// make sure counter is enabled |
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_IR)); |
|
// wait some time to have a nice increment |
asm volatile ("nop"); |
asm volatile ("nop"); |
// get instruction counter LOW |
tmp_a = neorv32_cpu_csr_read(CSR_INSTRET); |
tmp_a = neorv32_cpu_csr_read(CSR_INSTRET) - tmp_a; |
|
// make sure instruction counter has incremented and there was no exception during access |
if ((neorv32_cpu_get_instret() > temp64) && |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
test_ok(); |
if ((tmp_a > 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
if (tmp_a > 1) { |
neorv32_uart_printf("INSTRET_diff > 1 (%u)!", tmp_a); |
test_fail(); |
} |
else { |
test_ok(); |
} |
} |
else { |
test_fail(); |
274,7 → 260,7
tmp_b = neorv32_cpu_csr_read(CSR_CYCLE); |
|
// make sure instruction counter has NOT incremented and there was no exception during access |
if ((tmp_a == tmp_b) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
if ((tmp_a == tmp_b) && (tmp_a != 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
test_ok(); |
} |
else { |
366,29 → 352,27
} |
|
|
// ---------------------------------------------------------- |
// Bus timeout latency estimation |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Estimating bus time-out latency: ", cnt_test); |
cnt_test++; |
//// ---------------------------------------------------------- |
//// Bus timeout latency estimation |
//// out of order :P |
//// ---------------------------------------------------------- |
//neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
//neorv32_uart_printf("[%i] Estimating bus time-out latency: ", cnt_test); |
//cnt_test++; |
// |
//// start timing |
//neorv32_cpu_csr_write(CSR_MCYCLE, 0); |
// |
//// make sure there was a timeout |
//if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) { |
// neorv32_uart_printf("~%u cycles ", trap_timestamp32-175); // remove trap handler overhead - empiric value ;) |
// test_ok(); |
//} |
//else { |
// test_fail(); |
//} |
|
// start timing |
neorv32_cpu_csr_write(CSR_MCYCLE, 0); |
|
// this store access will timeout |
MMR_UNREACHABLE = 0; // trap handler will store mcycle.low to "trap_timestamp32" |
|
// make sure there was a timeout |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) { |
neorv32_uart_printf("~%u cycles ", trap_timestamp32-175); // remove trap handler overhead - empiric value ;) |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
|
// ---------------------------------------------------------- |
// External memory interface test |
// ---------------------------------------------------------- |
751,7 → 735,7
cnt_test++; |
|
// load from unreachable aligned address |
dummy_dst = MMR_UNREACHABLE; |
dummy_dst = neorv32_cpu_load_unsigned_word(ADDR_UNREACHABLE); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) { |
test_ok(); |
787,7 → 771,7
cnt_test++; |
|
// store to unreachable aligned address |
MMR_UNREACHABLE = 0; |
neorv32_cpu_store_unsigned_word(ADDR_UNREACHABLE, 0); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) { |
test_ok(); |
1589,11 → 1573,11
|
cnt_test++; |
|
ATOMIC_SUCCESS = 0x11223344; |
neorv32_cpu_store_unsigned_word(ATOMIC_SUCCESS_ADDR, 0x11223344); |
|
// atomic compare-and-swap |
if ((neorv32_cpu_atomic_cas((uint32_t)(&ATOMIC_SUCCESS), 0x11223344, 0xAABBCCDD) == 0) && // status: success |
(ATOMIC_SUCCESS == 0xAABBCCDD) && // data written correctly |
if ((neorv32_cpu_atomic_cas((uint32_t)ATOMIC_SUCCESS_ADDR, 0x11223344, 0xAABBCCDD) == 0) && // status: success |
(neorv32_cpu_load_unsigned_word(ATOMIC_SUCCESS_ADDR) == 0xAABBCCDD) && // data written correctly |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception triggered |
test_ok(); |
} |
1627,10 → 1611,10
|
cnt_test++; |
|
ATOMIC_FAILURE = 0x55667788; |
neorv32_cpu_store_unsigned_word(ATOMIC_FAILURE_ADDR, 0x55667788); |
|
// atomic compare-and-swap |
if ((neorv32_cpu_atomic_cas((uint32_t)(&ATOMIC_FAILURE), 0x55667788, 0xEEFFDDBB) != 0) && // staus: failed |
if ((neorv32_cpu_atomic_cas((uint32_t)ATOMIC_FAILURE_ADDR, 0x55667788, 0xEEFFDDBB) != 0) && // staus: failed |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception triggered |
test_ok(); |
} |
1675,7 → 1659,7
// ---------------------------------------------------------- |
// Final test reports |
// ---------------------------------------------------------- |
neorv32_uart_printf("\n\nTest results:\nOK: %i/%i\nFAILED: %i/%i\n\n", cnt_ok, cnt_test, cnt_fail, cnt_test); |
neorv32_uart_printf("\n\nTest results:\nOK: %i/%i\nFAILED: %i/%i\n\n", cnt_ok, cnt_test, cnt_fail, cnt_test); |
|
// final result |
if (cnt_fail == 0) { |
1705,9 → 1689,6
**************************************************************************/ |
void global_trap_handler(void) { |
|
// store time stamp |
trap_timestamp32 = neorv32_cpu_csr_read(CSR_MCYCLE); |
|
// hack: always come back in MACHINE MODE |
register uint32_t mask = (1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L); |
asm volatile ("csrrs zero, mstatus, %[input_j]" : : [input_j] "r" (mask)); |
/neorv32/trunk/sw/example/floating_point_test/README.md
1,5 → 1,7
# NEORV32 `Zfinx` Floating-Point Extension |
|
The NEORV32 floating-point unit (FPU) implements the `Zfinx` RISC-V extension. The extensions can be enabled via the `CPU_EXTENSION_RISCV_Zfinx` top configuration generic. |
|
The RISC-V `Zfinx` single-precision floating-point extensions uses the integer register file `x` instead of the dedicated floating-point `f` register file (which is |
defined by the RISC-V `F` single-precision floating-point extension). Hence, the standard data transfer instructions from the `F` extension are **not** available in `Zfinx`: |
|
6,7 → 8,6
* floating-point load/store operations (`FLW`, `FSW`) and their compressed versions |
* integer register file `x` <-> floating point register file `f` move operations (`FMV.W.X`, `FMV.X.W`) |
|
|
:information_source: More information regarding the RISC-V `Zfinx` single-precision floating-point extension can be found in the officail GitHub repo: |
[`github.com/riscv/riscv-zfinx`](https://github.com/riscv/riscv-zfinx). |
|
14,6 → 15,12
Make sure you **do not** use the `f` ISA attribute when compiling applications that use floating-point arithmetic (`-march=rv32i*f*` is **NOT ALLOWED!**). |
|
|
### :warning: FPU Limitations |
|
* The FPU **does not support subnormal numbers** yet. Subnormal FPU inputs and subnormal FPU results are always *flushed to zero*. The *classify* instruction `FCLASS` will never set the "subnormal" mask bits. |
* Rounding mode `ob100` "round to nearest, ties to max magnitude" is not supported yet (this and all invalid rounding mode configurations behave as "round towards zero" (truncation)). |
|
|
## Intrinsic Library |
|
The NEORV32 `Zfinx` floating-point extension can still be used using the provided **intrinsic library**. This library uses "custom" inline assmbly instructions |
36,3 → 43,10
|
The provided test program `main.c` verifies all currently implemented `Zfinx` instructions by checking the functionality against the pure software-based emulation model |
(GCC soft-float library). |
|
|
## Resources |
|
* Great page with online calculators for floating-point artihmetic: [http://www.ecs.umass.edu/ece/koren/arith/simulator/](http://www.ecs.umass.edu/ece/koren/arith/simulator/) |
* A handy tool for visualizing floating-point numbers in their binary representation: [https://www.h-schmidt.net/FloatConverter/IEEE754.html](https://www.h-schmidt.net/FloatConverter/IEEE754.html) |
* This helped me to understand what results the different FPU operation generate when having "special" inputs like NaN: [https://techdocs.altium.com/display/FPGA/IEEE+754+Standard+-+Overview](https://techdocs.altium.com/display/FPGA/IEEE+754+Standard+-+Overview) |
/neorv32/trunk/sw/example/floating_point_test/main.c
82,6 → 82,8
#define RUN_CLASSIFY_TESTS (1) |
//** Run unsupported instructions tests when != 0 */ |
#define RUN_UNAVAIL_TESTS (1) |
//** Run average instruction execution time test when != 0 */ |
#define RUN_TIMING_TESTS (0) |
/**@}*/ |
|
|
143,7 → 145,8
#if (SILENT_MODE != 0) |
neorv32_uart_printf("SILENT_MODE enabled (only showing actual errors)\n"); |
#endif |
neorv32_uart_printf("Test cases per instruction: %u\n\n", (uint32_t)NUM_TEST_CASES); |
neorv32_uart_printf("Test cases per instruction: %u\n", (uint32_t)NUM_TEST_CASES); |
neorv32_uart_printf("NOTE: The NEORV32 FPU does not support subnormal numbers yet. Subnormal numbers are flushed to zero.\n\n"); |
|
|
// clear exception status word |
413,7 → 416,7
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
riscv_intrinsic_fdivs(opa.float_value, opb.float_value); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) { |
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
426,7 → 429,7
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
riscv_intrinsic_fsqrts(opa.float_value); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) { |
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
439,7 → 442,7
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
riscv_intrinsic_fmadds(opa.float_value, opb.float_value, -opa.float_value); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) { |
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
452,7 → 455,7
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
riscv_intrinsic_fmsubs(opa.float_value, opb.float_value, -opa.float_value); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) { |
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
465,7 → 468,7
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
riscv_intrinsic_fnmadds(opa.float_value, opb.float_value, -opa.float_value); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) { |
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
478,7 → 481,7
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
riscv_intrinsic_fnmadds(opa.float_value, opb.float_value, -opa.float_value); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_I_ILLEGAL) { |
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
488,7 → 491,325
#endif |
|
|
// final report |
// ---------------------------------------------------------------------------- |
// Instruction execution timing test |
// ---------------------------------------------------------------------------- |
|
#if (RUN_TIMING_TESTS != 0) |
|
uint32_t time_start, time_sw, time_hw; |
const uint32_t num_runs = 4096; |
|
neorv32_uart_printf("\nAverage execution time tests (%u runs)\n", num_runs); |
|
|
// signed integer to float |
neorv32_uart_printf("FCVT.S.W: "); |
time_sw = 0; |
time_hw = 0; |
err_cnt = 0; |
for (i=0; i<num_runs; i++) { |
opa.binary_value = get_test_vector(); |
|
// hardware execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_hw.float_value = riscv_intrinsic_fcvt_sw((int32_t)opa.binary_value); |
} |
time_hw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
time_hw -= 4; // remove the 2 dummy instructions |
|
// software (emulation) execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_sw.float_value = riscv_emulate_fcvt_sw((int32_t)opa.binary_value); |
} |
time_sw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
|
if (res_sw.binary_value != res_hw.binary_value) { |
err_cnt++; |
} |
} |
|
if (err_cnt == 0) { |
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs); |
} |
else { |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
|
|
// float to signed integer |
neorv32_uart_printf("FCVT.W.S: "); |
time_sw = 0; |
time_hw = 0; |
err_cnt = 0; |
for (i=0; i<num_runs; i++) { |
opa.binary_value = get_test_vector(); |
|
// hardware execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_hw.binary_value = (uint32_t)riscv_intrinsic_fcvt_ws(opa.float_value); |
} |
time_hw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
time_hw -= 4; // remove the 2 dummy instructions |
|
// software (emulation) execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_sw.binary_value = (uint32_t)riscv_emulate_fcvt_ws(opa.float_value); |
} |
time_sw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
|
if (res_sw.binary_value != res_hw.binary_value) { |
err_cnt++; |
} |
} |
|
if (err_cnt == 0) { |
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs); |
} |
else { |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
|
|
// addition |
neorv32_uart_printf("FADD.S: "); |
time_sw = 0; |
time_hw = 0; |
err_cnt = 0; |
for (i=0; i<num_runs; i++) { |
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
|
// hardware execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_hw.float_value = riscv_intrinsic_fadds(opa.float_value, opb.float_value); |
} |
time_hw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
time_hw -= 4; // remove the 2 dummy instructions |
|
// software (emulation) execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_sw.float_value = riscv_emulate_fadds(opa.float_value, opb.float_value); |
} |
time_sw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
|
if (res_sw.binary_value != res_hw.binary_value) { |
err_cnt++; |
} |
} |
|
if (err_cnt == 0) { |
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs); |
} |
else { |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
|
|
// subtraction |
neorv32_uart_printf("FSUB.S: "); |
time_sw = 0; |
time_hw = 0; |
err_cnt = 0; |
for (i=0; i<num_runs; i++) { |
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
|
// hardware execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_hw.float_value = riscv_intrinsic_fsubs(opa.float_value, opb.float_value); |
} |
time_hw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
time_hw -= 4; // remove the 2 dummy instructions |
|
// software (emulation) execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_sw.float_value = riscv_emulate_fsubs(opa.float_value, opb.float_value); |
} |
time_sw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
|
if (res_sw.binary_value != res_hw.binary_value) { |
err_cnt++; |
} |
} |
|
if (err_cnt == 0) { |
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs); |
} |
else { |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
|
|
// multiplication |
neorv32_uart_printf("FMUL.S: "); |
time_sw = 0; |
time_hw = 0; |
err_cnt = 0; |
for (i=0; i<num_runs; i++) { |
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
|
// hardware execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_hw.float_value = riscv_intrinsic_fmuls(opa.float_value, opb.float_value); |
} |
time_hw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
time_hw -= 4; // remove the 2 dummy instructions |
|
// software (emulation) execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_sw.float_value = riscv_emulate_fmuls(opa.float_value, opb.float_value); |
} |
time_sw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
|
if (res_sw.binary_value != res_hw.binary_value) { |
err_cnt++; |
} |
} |
|
if (err_cnt == 0) { |
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs); |
} |
else { |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
|
|
// Max |
neorv32_uart_printf("FMAX.S: "); |
time_sw = 0; |
time_hw = 0; |
err_cnt = 0; |
for (i=0; i<num_runs; i++) { |
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
|
// hardware execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_hw.float_value = riscv_intrinsic_fmaxs(opa.float_value, opb.float_value); |
} |
time_hw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
time_hw -= 4; // remove the 2 dummy instructions |
|
// software (emulation) execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_sw.float_value = riscv_emulate_fmaxs(opa.float_value, opb.float_value); |
} |
time_sw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
|
if (res_sw.binary_value != res_hw.binary_value) { |
err_cnt++; |
} |
} |
|
if (err_cnt == 0) { |
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs); |
} |
else { |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
|
|
// Comparison |
neorv32_uart_printf("FLE.S: "); |
time_sw = 0; |
time_hw = 0; |
err_cnt = 0; |
for (i=0; i<num_runs; i++) { |
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
|
// hardware execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_hw.float_value = riscv_intrinsic_fles(opa.float_value, opb.float_value); |
} |
time_hw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
time_hw -= 4; // remove the 2 dummy instructions |
|
// software (emulation) execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_sw.float_value = riscv_emulate_fles(opa.float_value, opb.float_value); |
} |
time_sw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
|
if (res_sw.binary_value != res_hw.binary_value) { |
err_cnt++; |
} |
} |
|
if (err_cnt == 0) { |
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs); |
} |
else { |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
|
|
// Sign-injection |
neorv32_uart_printf("FSGNJX.S: "); |
time_sw = 0; |
time_hw = 0; |
err_cnt = 0; |
for (i=0; i<num_runs; i++) { |
opa.binary_value = get_test_vector(); |
opb.binary_value = get_test_vector(); |
|
// hardware execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_hw.float_value = riscv_intrinsic_fsgnjxs(opa.float_value, opb.float_value); |
} |
time_hw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
time_hw -= 4; // remove the 2 dummy instructions |
|
// software (emulation) execution time |
time_start = neorv32_cpu_csr_read(CSR_CYCLE); |
{ |
res_sw.float_value = riscv_emulate_fsgnjxs(opa.float_value, opb.float_value); |
} |
time_sw += neorv32_cpu_csr_read(CSR_CYCLE) - time_start; |
|
if (res_sw.binary_value != res_hw.binary_value) { |
err_cnt++; |
} |
} |
|
if (err_cnt == 0) { |
neorv32_uart_printf("cycles[SW] = %u vs. cycles[HW] = %u\n", time_sw/num_runs, time_hw/num_runs); |
} |
else { |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
err_cnt_total++; |
} |
#endif |
|
|
// ---------------------------------------------------------------------------- |
// Final report |
// ---------------------------------------------------------------------------- |
|
if (err_cnt_total != 0) { |
neorv32_uart_printf("\n%c[1m[ZFINX EXTENSION VERIFICATION FAILED!]%c[0m\n", 27, 27); |
neorv32_uart_printf("%u errors in %u test cases\n", err_cnt_total, test_cnt*(uint32_t)NUM_TEST_CASES); |
529,10 → 850,6
tmp.binary_value = xorshift32(); |
} |
|
// subnormal numbers are not supported yet! |
// flush them to zero |
//tmp.float_value = subnormal_flush(tmp.float_value); |
|
return tmp.binary_value; |
} |
|
/neorv32/trunk/sw/example/floating_point_test/neorv32_zfinx_extension_intrinsics.h
90,7 → 90,7
* |
* @warning Subnormal numbers are not supported yet! Flush them to zero. |
* |
* @param[in] tmp Source operand 1. |
* @param[in] tmp Source operand. |
* @return Result. |
**************************************************************************/ |
float subnormal_flush(float tmp) { |
167,13 → 167,11
/**********************************************************************//** |
* Single-precision floating-point addition |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fadds(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fadds(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
189,6 → 187,9
// fadd.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0000000, a1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
197,13 → 198,11
/**********************************************************************//** |
* Single-precision floating-point subtraction |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fsubs(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsubs(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
219,6 → 218,9
// fsub.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0000100, a1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
227,13 → 229,11
/**********************************************************************//** |
* Single-precision floating-point multiplication |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fmuls(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmuls(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
249,6 → 249,9
// fmul.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0001000, a1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
257,13 → 260,11
/**********************************************************************//** |
* Single-precision floating-point minimum |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fmins(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmins(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
279,6 → 280,9
// fmin.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0010100, a1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
287,13 → 291,11
/**********************************************************************//** |
* Single-precision floating-point maximum |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fmaxs(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmaxs(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
309,6 → 311,9
// fmax.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0010100, a1, a0, 0b001, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
317,12 → 322,10
/**********************************************************************//** |
* Single-precision floating-point convert float to unsigned integer |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @return Result. |
**************************************************************************/ |
uint32_t __attribute__ ((noinline)) riscv_intrinsic_fcvt_wus(float rs1) { |
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fcvt_wus(float rs1) { |
|
float_conv_t opa; |
opa.float_value = rs1; |
336,6 → 339,9
// fcvt.wu.s a0, a0 |
CUSTOM_INSTR_R2_TYPE(0b1100000, x1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
return result; |
} |
|
343,12 → 349,10
/**********************************************************************//** |
* Single-precision floating-point convert float to signed integer |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @return Result. |
**************************************************************************/ |
int32_t __attribute__ ((noinline)) riscv_intrinsic_fcvt_ws(float rs1) { |
inline int32_t __attribute__ ((always_inline)) riscv_intrinsic_fcvt_ws(float rs1) { |
|
float_conv_t opa; |
opa.float_value = rs1; |
362,6 → 366,9
// fcvt.w.s a0, a0 |
CUSTOM_INSTR_R2_TYPE(0b1100000, x0, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
return (int32_t)result; |
} |
|
369,12 → 376,10
/**********************************************************************//** |
* Single-precision floating-point convert unsigned integer to float |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fcvt_swu(uint32_t rs1) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fcvt_swu(uint32_t rs1) { |
|
float_conv_t res; |
|
387,6 → 392,9
// fcvt.s.wu a0, a0 |
CUSTOM_INSTR_R2_TYPE(0b1101000, x1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
395,12 → 403,10
/**********************************************************************//** |
* Single-precision floating-point convert signed integer to float |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fcvt_sw(int32_t rs1) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fcvt_sw(int32_t rs1) { |
|
float_conv_t res; |
|
413,6 → 419,9
// fcvt.s.w a0, a0 |
CUSTOM_INSTR_R2_TYPE(0b1101000, x0, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
421,13 → 430,11
/**********************************************************************//** |
* Single-precision floating-point equal comparison |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
uint32_t __attribute__ ((noinline)) riscv_intrinsic_feqs(float rs1, float rs2) { |
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_feqs(float rs1, float rs2) { |
|
float_conv_t opa, opb; |
opa.float_value = rs1; |
443,6 → 450,9
// feq.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b010, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
return result; |
} |
|
450,13 → 460,11
/**********************************************************************//** |
* Single-precision floating-point less-than comparison |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
uint32_t __attribute__ ((noinline)) riscv_intrinsic_flts(float rs1, float rs2) { |
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_flts(float rs1, float rs2) { |
|
float_conv_t opa, opb; |
opa.float_value = rs1; |
472,6 → 480,9
// flt.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b001, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
return result; |
} |
|
479,13 → 490,11
/**********************************************************************//** |
* Single-precision floating-point less-than-or-equal comparison |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
uint32_t __attribute__ ((noinline)) riscv_intrinsic_fles(float rs1, float rs2) { |
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fles(float rs1, float rs2) { |
|
float_conv_t opa, opb; |
opa.float_value = rs1; |
501,6 → 510,9
// fle.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b1010000, a1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
return result; |
} |
|
508,13 → 520,11
/**********************************************************************//** |
* Single-precision floating-point sign-injection |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fsgnjs(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjs(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
530,6 → 540,9
// fsgnj.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
538,13 → 551,11
/**********************************************************************//** |
* Single-precision floating-point sign-injection NOT |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fsgnjns(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjns(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
560,6 → 571,9
// fsgnjn.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b001, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
568,13 → 582,11
/**********************************************************************//** |
* Single-precision floating-point sign-injection XOR |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fsgnjxs(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsgnjxs(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
590,6 → 602,9
// fsgnjx.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b010, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
598,12 → 613,10
/**********************************************************************//** |
* Single-precision floating-point number classification |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @return Result. |
**************************************************************************/ |
uint32_t __attribute__ ((noinline)) riscv_intrinsic_fclasss(float rs1) { |
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_fclasss(float rs1) { |
|
float_conv_t opa; |
opa.float_value = rs1; |
617,6 → 630,9
// fclass.s a0, a0 |
CUSTOM_INSTR_R2_TYPE(0b1110000, x0, a0, 0b001, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
return result; |
} |
|
628,8 → 644,6
/**********************************************************************//** |
* Single-precision floating-point division |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @warning This instruction is not supported and should raise an illegal instruction exception when executed. |
* |
* @param[in] rs1 Source operand 1 (a0). |
636,7 → 650,7
* @param[in] rs2 Source operand 2 (a1). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fdivs(float rs1, float rs2) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fdivs(float rs1, float rs2) { |
|
float_conv_t opa, opb, res; |
opa.float_value = rs1; |
652,6 → 666,9
// fdiv.s a0, a0, x1 |
CUSTOM_INSTR_R2_TYPE(0b0001100, a1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
660,14 → 677,12
/**********************************************************************//** |
* Single-precision floating-point square root |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0 and a1. |
* |
* @warning This instruction is not supported and should raise an illegal instruction exception when executed. |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fsqrts(float rs1) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fsqrts(float rs1) { |
|
float_conv_t opa, res; |
opa.float_value = rs1; |
681,6 → 696,9
// fsqrt.s a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0101100, a1, a0, 0b000, a0, 0b1010011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
689,8 → 707,6
/**********************************************************************//** |
* Single-precision floating-point fused multiply-add |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0, a1 and a2. |
* |
* @warning This instruction is not supported and should raise an illegal instruction exception when executed. |
* |
* @param[in] rs1 Source operand 1 (a0) |
698,7 → 714,7
* @param[in] rs3 Source operand 3 (a2) |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fmadds(float rs1, float rs2, float rs3) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmadds(float rs1, float rs2, float rs3) { |
|
float_conv_t opa, opb, opc, res; |
opa.float_value = rs1; |
717,6 → 733,9
// fmadd.s a0, a0, a1, a2 |
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1000011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
725,8 → 744,6
/**********************************************************************//** |
* Single-precision floating-point fused multiply-sub |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0, a1 and a2. |
* |
* @warning This instruction is not supported and should raise an illegal instruction exception when executed. |
* |
* @param[in] rs1 Source operand 1 (a0) |
734,7 → 751,7
* @param[in] rs3 Source operand 3 (a2) |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fmsubs(float rs1, float rs2, float rs3) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fmsubs(float rs1, float rs2, float rs3) { |
|
float_conv_t opa, opb, opc, res; |
opa.float_value = rs1; |
753,6 → 770,9
// fmsub.s a0, a0, a1, a2 |
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1000111); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
761,8 → 781,6
/**********************************************************************//** |
* Single-precision floating-point fused negated multiply-sub |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0, a1 and a2. |
* |
* @warning This instruction is not supported and should raise an illegal instruction exception when executed. |
* |
* @param[in] rs1 Source operand 1 (a0) |
770,7 → 788,7
* @param[in] rs3 Source operand 3 (a2) |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fnmsubs(float rs1, float rs2, float rs3) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fnmsubs(float rs1, float rs2, float rs3) { |
|
float_conv_t opa, opb, opc, res; |
opa.float_value = rs1; |
789,6 → 807,9
// fnmsub.s a0, a0, a1, a2 |
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1001011); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
797,8 → 818,6
/**********************************************************************//** |
* Single-precision floating-point fused negated multiply-add |
* |
* @note "noinline" attributed to make sure arguments/return values are in a0, a1 and a2. |
* |
* @warning This instruction is not supported and should raise an illegal instruction exception when executed. |
* |
* @param[in] rs1 Source operand 1 (a0) |
806,7 → 825,7
* @param[in] rs3 Source operand 3 (a2) |
* @return Result. |
**************************************************************************/ |
float __attribute__ ((noinline)) riscv_intrinsic_fnmadds(float rs1, float rs2, float rs3) { |
inline float __attribute__ ((always_inline)) riscv_intrinsic_fnmadds(float rs1, float rs2, float rs3) { |
|
float_conv_t opa, opb, opc, res; |
opa.float_value = rs1; |
825,6 → 844,9
// fnmadd.s a0, a0, a1, a2 |
CUSTOM_INSTR_R3_TYPE(a2, a1, a0, 0b000, a0, 0b1001111); |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("add %[res], %[input], x0" : [res] "=r" (result) : [input] "r" (result) ); |
|
res.binary_value = result; |
return res.float_value; |
} |
841,7 → 863,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fadds(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fadds(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
858,7 → 880,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fsubs(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fsubs(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
875,7 → 897,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fmuls(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fmuls(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
892,7 → 914,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fmins(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fmins(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
933,7 → 955,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fmaxs(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fmaxs(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
974,7 → 996,7
* @param[in] rs1 Source operand 1. |
* @return Result. |
**************************************************************************/ |
uint32_t riscv_emulate_fcvt_wus(float rs1) { |
uint32_t __attribute__ ((noinline)) riscv_emulate_fcvt_wus(float rs1) { |
|
float opa = subnormal_flush(rs1); |
|
988,7 → 1010,7
* @param[in] rs1 Source operand 1. |
* @return Result. |
**************************************************************************/ |
int32_t riscv_emulate_fcvt_ws(float rs1) { |
int32_t __attribute__ ((noinline)) riscv_emulate_fcvt_ws(float rs1) { |
|
float opa = subnormal_flush(rs1); |
|
1002,7 → 1024,7
* @param[in] rs1 Source operand 1. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fcvt_swu(uint32_t rs1) { |
float __attribute__ ((noinline)) riscv_emulate_fcvt_swu(uint32_t rs1) { |
|
return (float)rs1; |
} |
1014,7 → 1036,7
* @param[in] rs1 Source operand 1. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fcvt_sw(int32_t rs1) { |
float __attribute__ ((noinline)) riscv_emulate_fcvt_sw(int32_t rs1) { |
|
return (float)rs1; |
} |
1027,7 → 1049,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
uint32_t riscv_emulate_feqs(float rs1, float rs2) { |
uint32_t __attribute__ ((noinline)) riscv_emulate_feqs(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1055,7 → 1077,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
uint32_t riscv_emulate_flts(float rs1, float rs2) { |
uint32_t __attribute__ ((noinline)) riscv_emulate_flts(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1080,7 → 1102,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
uint32_t riscv_emulate_fles(float rs1, float rs2) { |
uint32_t __attribute__ ((noinline)) riscv_emulate_fles(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1105,7 → 1127,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fsgnjs(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fsgnjs(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1142,7 → 1164,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fsgnjns(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fsgnjns(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1179,7 → 1201,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fsgnjxs(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fsgnjxs(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1215,7 → 1237,7
* @param[in] rs1 Source operand 1. |
* @return Result. |
**************************************************************************/ |
uint32_t riscv_emulate_fclasss(float rs1) { |
uint32_t __attribute__ ((noinline)) riscv_emulate_fclasss(float rs1) { |
|
float opa = subnormal_flush(rs1); |
|
1287,7 → 1309,7
* @param[in] rs2 Source operand 2. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fdivs(float rs1, float rs2) { |
float __attribute__ ((noinline)) riscv_emulate_fdivs(float rs1, float rs2) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1303,7 → 1325,7
* @param[in] rs1 Source operand 1. |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fsqrts(float rs1) { |
float __attribute__ ((noinline)) riscv_emulate_fsqrts(float rs1) { |
|
float opa = subnormal_flush(rs1); |
|
1324,7 → 1346,7
* @param[in] rs3 Source operand 3 |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fmadds(float rs1, float rs2, float rs3) { |
float __attribute__ ((noinline)) riscv_emulate_fmadds(float rs1, float rs2, float rs3) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1343,7 → 1365,7
* @param[in] rs3 Source operand 3 |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fmsubs(float rs1, float rs2, float rs3) { |
float __attribute__ ((noinline)) riscv_emulate_fmsubs(float rs1, float rs2, float rs3) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1362,7 → 1384,7
* @param[in] rs3 Source operand 3 |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fnmsubs(float rs1, float rs2, float rs3) { |
float __attribute__ ((noinline)) riscv_emulate_fnmsubs(float rs1, float rs2, float rs3) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
1381,7 → 1403,7
* @param[in] rs3 Source operand 3 |
* @return Result. |
**************************************************************************/ |
float riscv_emulate_fnmadds(float rs1, float rs2, float rs3) { |
float __attribute__ ((noinline)) riscv_emulate_fnmadds(float rs1, float rs2, float rs3) { |
|
float opa = subnormal_flush(rs1); |
float opb = subnormal_flush(rs2); |
/neorv32/trunk/sw/example/hex_viewer/main.c
158,10 → 158,8
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
register uint32_t mem_data = 0; |
uint32_t mem_data = neorv32_cpu_load_unsigned_word(mem_address); |
|
asm volatile ("lw %[rdata], 0(%[raddr])" : [rdata] "=r" (mem_data) : [raddr] "r" (mem_address)); |
|
// show memory content if there was no exception |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
neorv32_uart_printf("0x%x", mem_data); |
181,12 → 179,12
// enter address |
neorv32_uart_printf("Enter address (8 hex chars): 0x"); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
|
// enter data |
neorv32_uart_printf("\nEnter data (8 hex chars): 0x"); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_data = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
uint32_t mem_data = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
|
// perform write access |
neorv32_uart_printf("\n[0x%x] = ", mem_address); |
193,8 → 191,7
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
asm volatile ("sw %[wdata], 0(%[waddr])" : : [wdata] "r" (mem_data), [waddr] "r" (mem_address)); |
asm volatile ("nop"); |
neorv32_cpu_store_unsigned_word(mem_address, mem_data); |
|
// show memory content if there was no exception |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
254,7 → 251,7
// enter base address |
neorv32_uart_printf("Enter base address (8 hex chars): 0x"); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
|
neorv32_uart_printf("\nPress key to start dumping. Press any key to abort.\n"); |
|
261,7 → 258,7
neorv32_uart_getc(); // wait for key |
|
// perform read accesses |
register uint32_t mem_data = 0; |
uint32_t mem_data = 0; |
while(neorv32_uart_char_received() == 0) { |
|
neorv32_uart_printf("[0x%x] = ", mem_address); |
268,8 → 265,7
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
asm volatile ("lw %[rdata], 0(%[raddr])" : [rdata] "=r" (mem_data) : [raddr] "r" (mem_address)); |
asm volatile ("nop"); |
mem_data = neorv32_cpu_load_unsigned_word(mem_address); |
|
// show memory content if there was no exception |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
/neorv32/trunk/sw/lib/include/neorv32.h
351,9 → 351,39
* CPU <b>mcounteren</b> CSR (r/w): Machine counter enable (RISC-V spec.) |
**************************************************************************/ |
enum NEORV32_CSR_MCOUNTEREN_enum { |
CSR_MCOUNTEREN_CY = 0, /**< CPU mcounteren CSR (0): CY - Allow access to cycle[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_TM = 1, /**< CPU mcounteren CSR (1): TM - Allow access to time[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_IR = 2 /**< CPU mcounteren CSR (2): IR - Allow access to instret[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_CY = 0, /**< CPU mcounteren CSR (0): CY - Allow access to cycle[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_TM = 1, /**< CPU mcounteren CSR (1): TM - Allow access to time[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_IR = 2, /**< CPU mcounteren CSR (2): IR - Allow access to instret[h] CSRs from U-mode when set (r/w) */ |
|
CSR_MCOUNTEREN_HPM3 = 3, /**< CPU mcounteren CSR (3): HPM3 - Allow access to hpmcnt3[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM4 = 4, /**< CPU mcounteren CSR (4): HPM4 - Allow access to hpmcnt4[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM5 = 5, /**< CPU mcounteren CSR (5): HPM5 - Allow access to hpmcnt5[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM6 = 6, /**< CPU mcounteren CSR (6): HPM6 - Allow access to hpmcnt6[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM7 = 7, /**< CPU mcounteren CSR (7): HPM7 - Allow access to hpmcnt7[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM8 = 8, /**< CPU mcounteren CSR (8): HPM8 - Allow access to hpmcnt8[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM9 = 9, /**< CPU mcounteren CSR (9): HPM9 - Allow access to hpmcnt9[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM10 = 10, /**< CPU mcounteren CSR (10): HPM10 - Allow access to hpmcnt10[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM11 = 11, /**< CPU mcounteren CSR (11): HPM11 - Allow access to hpmcnt11[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM12 = 12, /**< CPU mcounteren CSR (12): HPM12 - Allow access to hpmcnt12[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM13 = 13, /**< CPU mcounteren CSR (13): HPM13 - Allow access to hpmcnt13[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM14 = 14, /**< CPU mcounteren CSR (14): HPM14 - Allow access to hpmcnt14[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM15 = 15, /**< CPU mcounteren CSR (15): HPM15 - Allow access to hpmcnt15[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM16 = 16, /**< CPU mcounteren CSR (16): HPM16 - Allow access to hpmcnt16[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM17 = 17, /**< CPU mcounteren CSR (17): HPM17 - Allow access to hpmcnt17[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM18 = 18, /**< CPU mcounteren CSR (18): HPM18 - Allow access to hpmcnt18[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM19 = 19, /**< CPU mcounteren CSR (19): HPM19 - Allow access to hpmcnt19[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM20 = 20, /**< CPU mcounteren CSR (20): HPM20 - Allow access to hpmcnt20[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM21 = 21, /**< CPU mcounteren CSR (21): HPM21 - Allow access to hpmcnt21[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM22 = 22, /**< CPU mcounteren CSR (22): HPM22 - Allow access to hpmcnt22[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM23 = 23, /**< CPU mcounteren CSR (23): HPM23 - Allow access to hpmcnt23[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM24 = 24, /**< CPU mcounteren CSR (24): HPM24 - Allow access to hpmcnt24[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM25 = 25, /**< CPU mcounteren CSR (25): HPM25 - Allow access to hpmcnt25[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM26 = 26, /**< CPU mcounteren CSR (26): HPM26 - Allow access to hpmcnt26[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM27 = 27, /**< CPU mcounteren CSR (27): HPM27 - Allow access to hpmcnt27[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM28 = 28, /**< CPU mcounteren CSR (28): HPM28 - Allow access to hpmcnt28[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM29 = 29, /**< CPU mcounteren CSR (29): HPM29 - Allow access to hpmcnt29[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM30 = 30, /**< CPU mcounteren CSR (30): HPM30 - Allow access to hpmcnt30[h] CSRs from U-mode when set (r/w) */ |
CSR_MCOUNTEREN_HPM31 = 31 /**< CPU mcounteren CSR (31): HPM31 - Allow access to hpmcnt31[h] CSRs from U-mode when set (r/w) */ |
}; |
|
|
361,8 → 391,38
* CPU <b>mcountinhibit</b> CSR (r/w): Machine counter-inhibit (RISC-V spec.) |
**************************************************************************/ |
enum NEORV32_CSR_MCOUNTINHIBIT_enum { |
CSR_MCOUNTINHIBIT_CY = 0, /**< CPU mcountinhibit CSR (0): CY - Enable auto-increment of [m]cycle[h] CSR when set (r/w) */ |
CSR_MCOUNTINHIBIT_IR = 2 /**< CPU mcountinhibit CSR (2): IR - Enable auto-increment of [m]instret[h] CSR when set (r/w) */ |
CSR_MCOUNTINHIBIT_CY = 0, /**< CPU mcountinhibit CSR (0): CY - Enable auto-increment of [m]cycle[h] CSR when set (r/w) */ |
CSR_MCOUNTINHIBIT_IR = 2, /**< CPU mcountinhibit CSR (2): IR - Enable auto-increment of [m]instret[h] CSR when set (r/w) */ |
|
CSR_MCOUNTINHIBIT_HPM3 = 3, /**< CPU mcountinhibit CSR (3): HPM3 - Enable auto-increment of hpmcnt3[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM4 = 4, /**< CPU mcountinhibit CSR (4): HPM4 - Enable auto-increment of hpmcnt4[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM5 = 5, /**< CPU mcountinhibit CSR (5): HPM5 - Enable auto-increment of hpmcnt5[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM6 = 6, /**< CPU mcountinhibit CSR (6): HPM6 - Enable auto-increment of hpmcnt6[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM7 = 7, /**< CPU mcountinhibit CSR (7): HPM7 - Enable auto-increment of hpmcnt7[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM8 = 8, /**< CPU mcountinhibit CSR (8): HPM8 - Enable auto-increment of hpmcnt8[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM9 = 9, /**< CPU mcountinhibit CSR (9): HPM9 - Enable auto-increment of hpmcnt9[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM10 = 10, /**< CPU mcountinhibit CSR (10): HPM10 - Enable auto-increment of hpmcnt10[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM11 = 11, /**< CPU mcountinhibit CSR (11): HPM11 - Enable auto-increment of hpmcnt11[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM12 = 12, /**< CPU mcountinhibit CSR (12): HPM12 - Enable auto-increment of hpmcnt12[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM13 = 13, /**< CPU mcountinhibit CSR (13): HPM13 - Enable auto-increment of hpmcnt13[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM14 = 14, /**< CPU mcountinhibit CSR (14): HPM14 - Enable auto-increment of hpmcnt14[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM15 = 15, /**< CPU mcountinhibit CSR (15): HPM15 - Enable auto-increment of hpmcnt15[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM16 = 16, /**< CPU mcountinhibit CSR (16): HPM16 - Enable auto-increment of hpmcnt16[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM17 = 17, /**< CPU mcountinhibit CSR (17): HPM17 - Enable auto-increment of hpmcnt17[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM18 = 18, /**< CPU mcountinhibit CSR (18): HPM18 - Enable auto-increment of hpmcnt18[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM19 = 19, /**< CPU mcountinhibit CSR (19): HPM19 - Enable auto-increment of hpmcnt19[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM20 = 20, /**< CPU mcountinhibit CSR (20): HPM20 - Enable auto-increment of hpmcnt20[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM21 = 21, /**< CPU mcountinhibit CSR (21): HPM21 - Enable auto-increment of hpmcnt21[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM22 = 22, /**< CPU mcountinhibit CSR (22): HPM22 - Enable auto-increment of hpmcnt22[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM23 = 23, /**< CPU mcountinhibit CSR (23): HPM23 - Enable auto-increment of hpmcnt23[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM24 = 24, /**< CPU mcountinhibit CSR (24): HPM24 - Enable auto-increment of hpmcnt24[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM25 = 25, /**< CPU mcountinhibit CSR (25): HPM25 - Enable auto-increment of hpmcnt25[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM26 = 26, /**< CPU mcountinhibit CSR (26): HPM26 - Enable auto-increment of hpmcnt26[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM27 = 27, /**< CPU mcountinhibit CSR (27): HPM27 - Enable auto-increment of hpmcnt27[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM28 = 28, /**< CPU mcountinhibit CSR (28): HPM28 - Enable auto-increment of hpmcnt28[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM29 = 29, /**< CPU mcountinhibit CSR (29): HPM29 - Enable auto-increment of hpmcnt29[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM30 = 30, /**< CPU mcountinhibit CSR (30): HPM30 - Enable auto-increment of hpmcnt30[h] when set (r/w) */ |
CSR_MCOUNTINHIBIT_HPM31 = 31 /**< CPU mcountinhibit CSR (31): HPM31 - Enable auto-increment of hpmcnt31[h] when set (r/w) */ |
}; |
|
|
449,7 → 509,9
CSR_MZEXT_ZBB = 2, /**< CPU mzext CSR (2): Zbb extension (B sub-extension) available when set (r/-) */ |
CSR_MZEXT_ZBS = 3, /**< CPU mzext CSR (3): Zbs extension (B sub-extension) available when set (r/-) */ |
CSR_MZEXT_ZBA = 4, /**< CPU mzext CSR (4): Zba extension (B sub-extension) available when set (r/-) */ |
CSR_MZEXT_ZFINX = 5 /**< CPU mzext CSR (5): Zfinx extension (F sub-/alternative-extension) available when set (r/-) */ |
CSR_MZEXT_ZFINX = 5, /**< CPU mzext CSR (5): Zfinx extension (F sub-/alternative-extension) available when set (r/-) */ |
CSR_MZEXT_ZXSCNT = 6, /**< CPU mzext CSR (6): Custom extension - Small CPU counters: "cycle" & "instret" CSRs have less than 64-bit when set (r/-) */ |
CSR_MZEXT_ZXNOCNT = 7 /**< CPU mzext CSR (7): Custom extension - NO CPU counters: "cycle" & "instret" CSRs are NOT available at all when set (r/-) */ |
}; |
|
|
491,7 → 553,6
TRAP_CODE_S_ACCESS = 0x00000007, /**< 0.7: Store (bus) access fault */ |
TRAP_CODE_UENV_CALL = 0x00000008, /**< 0.8: Environment call from user mode (ECALL instruction) */ |
TRAP_CODE_MENV_CALL = 0x0000000b, /**< 0.11: Environment call from machine mode (ECALL instruction) */ |
TRAP_CODE_RESET = 0x80000000, /**< 1.0: Hardware reset */ |
TRAP_CODE_MSI = 0x80000003, /**< 1.3: Machine software interrupt */ |
TRAP_CODE_MTI = 0x80000007, /**< 1.7: Machine timer interrupt */ |
TRAP_CODE_MEI = 0x8000000b, /**< 1.11: Machine external interrupt */ |
/neorv32/trunk/sw/lib/include/neorv32_cpu.h
50,7 → 50,7
uint64_t neorv32_cpu_get_instret(void); |
void neorv32_cpu_set_minstret(uint64_t value); |
uint64_t neorv32_cpu_get_systime(void); |
void neorv32_cpu_delay_ms(uint32_t time_ms); |
void neorv32_cpu_delay_ms(int16_t time_ms); |
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void); |
int neorv32_cpu_atomic_cas(uint32_t addr, uint32_t expected, uint32_t desired); |
uint32_t neorv32_cpu_pmp_get_num_regions(void); |
57,10 → 57,115
uint32_t neorv32_cpu_pmp_get_granularity(void); |
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint32_t size, uint8_t config); |
uint32_t neorv32_cpu_hpm_get_counters(void); |
uint32_t neorv32_cpu_hpm_get_size(void); |
int neorv32_check_zextension(uint32_t); |
|
|
/**********************************************************************//** |
* Store unsigned word to address space. |
* |
* @note An unaligned access address will raise an alignment exception. |
* |
* @param[in] addr Address (32-bit). |
* @param[in] wdata Data word (32-bit) to store. |
**************************************************************************/ |
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_word(uint32_t addr, uint32_t wdata) { |
|
register uint32_t reg_addr = addr; |
register uint32_t reg_data = wdata; |
|
asm volatile ("sw %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr)); |
} |
|
|
/**********************************************************************//** |
* Store unsigned half-word to address space. |
* |
* @note An unaligned access address will raise an alignment exception. |
* |
* @param[in] addr Address (32-bit). |
* @param[in] wdata Data half-word (16-bit) to store. |
**************************************************************************/ |
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_half(uint32_t addr, uint16_t wdata) { |
|
register uint32_t reg_addr = addr; |
register uint32_t reg_data = (uint32_t)wdata; |
|
asm volatile ("sh %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr)); |
} |
|
|
/**********************************************************************//** |
* Store unsigned byte to address space. |
* |
* @param[in] addr Address (32-bit). |
* @param[in] wdata Data byte (8-bit) to store. |
**************************************************************************/ |
inline void __attribute__ ((always_inline)) neorv32_cpu_store_unsigned_byte(uint32_t addr, uint8_t wdata) { |
|
register uint32_t reg_addr = addr; |
register uint32_t reg_data = (uint32_t)wdata; |
|
asm volatile ("sb %[da], 0(%[ad])" : : [da] "r" (reg_data), [ad] "r" (reg_addr)); |
} |
|
|
/**********************************************************************//** |
* Load unsigned word from address space. |
* |
* @note An unaligned access address will raise an alignment exception. |
* |
* @param[in] addr Address (32-bit). |
* @return Read data word (32-bit). |
**************************************************************************/ |
inline uint32_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_word(uint32_t addr) { |
|
register uint32_t reg_addr = addr; |
register uint32_t reg_data; |
|
asm volatile ("lw %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr)); |
|
return (uint32_t)reg_data; |
} |
|
|
/**********************************************************************//** |
* Load unsigned half-word from address space. |
* |
* @note An unaligned access address will raise an alignment exception. |
* |
* @param[in] addr Address (32-bit). |
* @return Read data half-word (16-bit). |
**************************************************************************/ |
inline uint16_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_half(uint32_t addr) { |
|
register uint32_t reg_addr = addr; |
register uint32_t reg_data; |
|
asm volatile ("lhu %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr)); |
|
return (uint16_t)reg_data; |
} |
|
|
/**********************************************************************//** |
* Load unsigned byte from address space. |
* |
* @param[in] addr Address (32-bit). |
* @return Read data byte (8-bit). |
**************************************************************************/ |
inline uint8_t __attribute__ ((always_inline)) neorv32_cpu_load_unsigned_byte(uint32_t addr) { |
|
register uint32_t reg_addr = addr; |
register uint32_t reg_data; |
|
asm volatile ("lbu %[da], 0(%[ad])" : [da] "=r" (reg_data) : [ad] "r" (reg_addr)); |
|
return (uint8_t)reg_data; |
} |
|
|
/**********************************************************************//** |
* Read data from CPU configuration and status register (CSR). |
* |
* @param[in] csr_id ID of CSR to read. See #NEORV32_CSR_enum. |
96,8 → 201,8
* @note This function executes the WFI insstruction. |
* The WFI (wait for interrupt) instruction will make the CPU stall until |
* an interupt request is detected. Interrupts have to be globally enabled |
* and at least one external source must be enabled (e.g., the CLIC or the machine |
* timer) to allow the CPU to wake up again. If 'Zicsr' CPU extension is disabled, |
* and at least one external source must be enabled (like the MTI machine |
* timer interrupt) to allow the CPU to wake up again. If 'Zicsr' CPU extension is disabled, |
* this will permanently stall the CPU. |
**************************************************************************/ |
inline void __attribute__ ((always_inline)) neorv32_cpu_sleep(void) { |
/neorv32/trunk/sw/lib/source/neorv32_cpu.c
271,27 → 271,36
|
|
/**********************************************************************//** |
* Simple delay function using busy wait. |
* Simple delay function using busy wait (simple loop). |
* |
* @warning This function requires the cycle CSR(s). Hence, the Zicsr extension is mandatory. |
* @warning This function is not really precise (especially if there is no M extension available)! Use a timer-based approach (using cycle or time CSRs) for precise timings. |
* |
* @param[in] time_ms Time in ms to wait. |
* @param[in] time_ms Time in ms to wait (max 32767ms). |
**************************************************************************/ |
void neorv32_cpu_delay_ms(uint32_t time_ms) { |
void neorv32_cpu_delay_ms(int16_t time_ms) { |
|
uint64_t time_resume = neorv32_cpu_get_cycle(); |
const uint32_t loop_cycles_c = 16; // clock cycles per iteration of the ASM loop |
|
// check input |
if (time_ms < 0) { |
time_ms = -time_ms; |
} |
|
uint32_t clock = SYSINFO_CLK; // clock ticks per second |
clock = clock / 1000; // clock ticks per ms |
|
uint64_t wait_cycles = ((uint64_t)clock) * ((uint64_t)time_ms); |
time_resume += wait_cycles; |
uint32_t ticks = (uint32_t)(wait_cycles / loop_cycles_c); |
|
while(1) { |
if (neorv32_cpu_get_cycle() >= time_resume) { |
break; |
} |
} |
asm volatile (" .balign 4 \n" // make sure this is 32-bit aligned |
" __neorv32_cpu_delay_ms_start: \n" |
" beq %[cnt_r], zero, __neorv32_cpu_delay_ms_end \n" // 3 cycles (not taken) |
" beq %[cnt_r], zero, __neorv32_cpu_delay_ms_end \n" // 3 cycles (never taken) |
" addi %[cnt_w], %[cnt_r], -1 \n" // 2 cycles |
" nop \n" // 2 cycles |
" j __neorv32_cpu_delay_ms_start \n" // 6 cycles |
" __neorv32_cpu_delay_ms_end: " |
: [cnt_w] "=r" (ticks) : [cnt_r] "r" (ticks)); |
} |
|
|
304,10 → 313,10
|
// make sure to use NO registers in here! -> naked |
|
asm volatile ("csrw mepc, ra \n\t" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here |
"li ra, %[input_imm] \n\t" // bit mask to clear the two MPP bits |
"csrrc zero, mstatus, ra \n\t" // clear MPP bits -> MPP=u-mode |
"mret \n\t" // return and switch to user mode |
asm volatile ("csrw mepc, ra \n" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here |
"li ra, %[input_imm] \n" // bit mask to clear the two MPP bits |
"csrrc zero, mstatus, ra \n" // clear MPP bits -> MPP=u-mode |
"mret \n" // return and switch to user mode |
: : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L))); |
} |
|
621,6 → 630,11
**************************************************************************/ |
uint32_t neorv32_cpu_hpm_get_counters(void) { |
|
// inhibit all HPM counters |
uint32_t tmp = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT); |
tmp |= 0xfffffff8; |
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, tmp); |
|
// try setting all mhpmcounter* CSRs to 1 |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER4, 1); |
650,7 → 664,7
neorv32_cpu_csr_write(CSR_MHPMCOUNTER28, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER29, 1); |
|
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0) |
// sum up all written ones (only available HPM counter CSRs will return =! 0) |
uint32_t num_hpm_cnts = 0; |
|
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER3); |
686,6 → 700,42
|
|
/**********************************************************************//** |
* Hardware performance monitors (HPM): Get total counter width |
* |
* @warning This function overrides mhpmcounter3[h] CSRs. |
* |
* @return Size of HPM counter bits (1-64). |
**************************************************************************/ |
uint32_t neorv32_cpu_hpm_get_size(void) { |
|
// inhibt auto-update |
asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTEREN_HPM3)); |
|
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3, 0xffffffff); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3H, 0xffffffff); |
|
uint32_t tmp, size, i; |
|
if (neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H) == 0) { |
size = 0; |
tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3); |
} |
else { |
size = 32; |
tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H); |
} |
|
for (i=0; i<32; i++) { |
if (tmp & (1<<i)) { |
size++; |
} |
} |
|
return size; |
} |
|
|
/**********************************************************************//** |
* Check if certain Z* extension is available |
* |
* @param[in] flag Index of the Z-extension to check from #NEORV32_CSR_MZEXT_enum |
/neorv32/trunk/sw/lib/source/neorv32_rte.c
282,7 → 282,6
|
// ID |
neorv32_uart_printf("Hart ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID)); |
|
neorv32_uart_printf("Vendor ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MVENDORID)); |
|
tmp = neorv32_cpu_csr_read(CSR_MARCHID); |
353,6 → 352,12
if (tmp & (1<<CSR_MZEXT_ZFINX)) { |
neorv32_uart_printf("Zfinx "); |
} |
if (tmp & (1<<CSR_MZEXT_ZXNOCNT)) { |
neorv32_uart_printf("Zxnocnt(!) "); |
} |
if (tmp & (1<<CSR_MZEXT_ZXSCNT)) { |
neorv32_uart_printf("Zxscnt(!) "); |
} |
|
// check physical memory protection |
neorv32_uart_printf("\nPMP: "); |
365,7 → 370,7
} |
|
// check hardware performance monitors |
neorv32_uart_printf("HPM Counters: %u\n", neorv32_cpu_hpm_get_counters()); |
neorv32_uart_printf("HPM Counters: %ux, %u-bit wide\n", neorv32_cpu_hpm_get_counters(), neorv32_cpu_hpm_get_size()); |
|
|
// Memory configuration |
372,17 → 377,27
neorv32_uart_printf("\n=== << Memory Configuration >> ===\n"); |
|
neorv32_uart_printf("Instr. base address: 0x%x\n", SYSINFO_ISPACE_BASE); |
|
// IMEM |
neorv32_uart_printf("Internal IMEM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM)); |
neorv32_uart_printf("IMEM size: %u bytes\n", SYSINFO_IMEM_SIZE); |
neorv32_uart_printf("Internal IMEM as ROM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM)) { |
neorv32_uart_printf("yes, %u bytes", SYSINFO_IMEM_SIZE); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) { |
neorv32_uart_printf(", read-only (ROM)"); |
} |
} |
else { |
neorv32_uart_printf("no"); |
} |
neorv32_uart_printf("\n"); |
|
// DMEM |
neorv32_uart_printf("Data base address: 0x%x\n", SYSINFO_DSPACE_BASE); |
neorv32_uart_printf("Internal DMEM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)); |
neorv32_uart_printf("DMEM size: %u bytes\n", SYSINFO_DMEM_SIZE); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)) { neorv32_uart_printf("yes, %u bytes\n", SYSINFO_DMEM_SIZE); } |
else { neorv32_uart_printf("no\n"); } |
|
// i-cache |
neorv32_uart_printf("Internal i-cache: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)) { |
/neorv32/trunk/CHANGELOG.md
6,7 → 6,7
A list of all releases can be found [here](https://github.com/stnolting/neorv32/releases). The most recent version of the *NEORV32 data sheet* |
can be found [here](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf) (pdf). |
|
:information_source: To see a list of all commits between release run `git log RELEASE_A..RELEASE_B` (example: `v1.4.7.0..v1.4.8.0`). |
:information_source: To see a list of all commits between releases run `git log RELEASE_A..RELEASE_B` (example: `v1.4.7.0..v1.4.8.0`). |
|
:information_source: The processor can determine it's version from the `mimpid` CSR (at CSR address 0xf13). A 8x4-bit BCD representation is used. |
Leading zeros are optional. Example: `CSR(mimpid) = 0x01040312 => 01.04.03.12 = Version 01.04.03.12 = v1.4.3.12`. The version number is globally |
24,6 → 24,18
|
| Date (*dd.mm.yyyy*) | Version | Comment | |
|:----------:|:-------:|:--------| |
| 17.04.2021 | [**:rocket:1.5.4.0**](https://github.com/stnolting/neorv32/releases/tag/v1.5.4.0) | **New release** | |
| 16.04.2021 | 1.5.3.13 | :warning: added new top configuration generic `TINY_SHIFT_EN` (type = `boolean`, default = `false`) to configure a tiny single-bit (iterative) shifter for CPU ALU shift operations (for highly area-constrained setups) | |
| 16.04.2021 | 1.5.3.12 | :sparkles: reworked reset system of the complete CPU: by default most registers (= "uncritical registers") **do not** provide an initialization via hardware reset; a **defined reset value** can be enabled by setting a constant from the main VHDL package (`rtl/core/neorv32_package.vhd`): `constant dedicated_reset_c : boolean := false;` (set `true` to enable CPU-wide dedicated register reset); see new section "2.11. CPU Hardware Reset" of NEORV32.pdf for more information | |
| 14.04.2021 | 1.5.3.11 | minor rtl edits to allow synthesis using [`ghdl-yosys-plugin`](https://github.com/ghdl/ghdl-yosys-plugin) (:construction: work in progress :construction:) |
| 13.04.2021 | 1.5.3.10 | :bug: fixed bug when configuring `HPM_CNT_WIDTH` less than 32; :warning: added new generic `CPU_CNT_WIDTH` to configure total size of CPU's `cycle` and `instret` CSRs (default = 64-bit); added `Zxnocnt` (no counters) and `Zxscnt` (small counters) flags to `mzexr` CSR to check if `CPU_CNT_WIDTH` is zero or less than 64, respectively; :bug: fixed bug in `crt0.S` start-up code: stack pointer has to be initialized before an exception can occur; updated `cpu_test` example program | |
| 11.04.2021 | 1.5.3.9 | :warning: reworked CPU reset system (in addition to modifications in v1.5.3.7): default reset: most register are "initialized" with '-' (don't care) since no real reset is required; however, a "real" reset can be configured using the packages 'def_rst_val_c' constant that defines the reset value for all "uncritical regsiter" (see new NEORV32.pdf section 2.11 "CPU Hardware Reset") | |
| 09.04.2021 | 1.5.3.8 | optimized CPU control: register write back during multi-cycle ALU operation only when result is really available (reducing switching activity; avoids possible source operand corruption); optimized `M` extension's co-processor: multiplications and divisions are 2 cycles faster | |
| 08.04.2021 | 1.5.3.7 | :bug: fixed bug in HPM event configuration via `mhpmevent*` CSRs - there was a CSR address decoding overlap between the HPM event CSRs and the machine trap setup CSRs (introduced in version 1.5.3.6); :warning: reworked CPU core CSRs: most CSRs are not reset by hardware and need explicit initialization (done by crt0.S start-up code) | |
| 02.04.2021 | 1.5.3.6 | :bug: fixed bug in external memory interface (`neorv32_wishbone.vhd`) that caused bus exceptions when using external memories with very high access latencies (race condition in bus timeouts); VHDL code clean-up | |
| 30.03.2021 | 1.5.3.5 | added new top's generic `HPM_CNT_WIDTH` (type `natural`, default=40) to configure the total bit width of the hardware performance monitors (HPM) counter (min 1, max 64); mofified `crt0.S`: stops all counters (incl. HPMs), no user-level access to ANY counter; `neorv32.h`: added missing `mcounteren` and `mcountinhibit` CSR bit definitions | |
| 28.03.2021 | 1.5.3.4 | default "test setup" `rtl/top_templetes/neorv32_test_setup.vhd`: disabled PMP, implementing 4 HPM counters; :sparkles: added [`boards`](https://github.com/stnolting/neorv32/tree/master/boards) folder for exemplary FPGA setups | |
| 27.03.2021 | 1.5.3.3 | minor optimization in CPU control engine; FPU comparator now uses comparatos results from main ALU (reduces FPU hardware footprint) | |
| 26.03.2021 | 1.5.3.2 | :sparkles: **added single-precision floating-point unit (FPU)** `rtl/core/neorv32_cpu_cp_fpu.vhd` implementing the `Zfinx` CPU extension; added/updated `Zfinx` **intrinsic library** and verification framework: [`sw/example/floating_point_test`](https://github.com/stnolting/neorv32/tree/master/sw/example/floating_point_test); added co-processor timeout counter to CPU to auto-terminate co-processor operations (for debugging only; defaullt=deactivated) | |
| 25.03.2021 | 1.5.3.1 | :bug: fixed bug in invalid floating-point instruction detection (caused CPU to stall if executing an invalid floating-point operation); intrinsic core library (mainly used for not-yet-supported CPU extensions like `B` and `Zfinx`): clean-up, added R3 instruction type | |
| 24.03.2021 | [**:rocket:1.5.3.0**](https://github.com/stnolting/neorv32/releases/tag/v1.5.3.0) | **New release** | |
/neorv32/trunk/README.md
24,7 → 24,7
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_processor.png) |
|
The NEORV32 Processor is a customizable microcontroller-like system on chip (SoC) that is based |
on the RISC-V NEORV32 CPU. The processor is intended as auxiliary processor within a larger SoC |
on the RISC-V NEORV32 CPU. The processor is intended as auxiliary processor in larger SoC |
designs or as *ready-to-go* stand-alone custom microcontroller. |
|
:books: For detailed information take a look at the [NEORV32 data sheet (pdf)](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf). |
33,6 → 33,8
:label: The project’s change log is available as [CHANGELOG.md](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md) in the root directory of this repository. |
To see the changes between *stable* releases visit the project's [release page](https://github.com/stnolting/neorv32/releases). |
|
:rocket: The [`boards`](https://github.com/stnolting/neorv32/tree/master/boards) folder provides exemplary setups targeting various FPGA boards to get you started. |
|
:spiral_notepad: Check out the [project boards](https://github.com/stnolting/neorv32/projects) for a list of current **ideas**, |
**TODOs**, features being **planned** and **work-in-progress**. |
|
57,7 → 59,7
* [`X`](#X---NEORV32-specific-CPU-extensions) - NEORV32-specific extensions (always enabled) |
* [`Zfinx`](#Zfinx---Single-precision-floating-point-extension) - Single-precision floating-point extensions (optional) |
* [`Zicsr`](#Zicsr---Privileged-architecture---CSR-access-extension) - control and status register access instructions (+ exception/irq system) (optional) |
* [`Zifencei`](#Zifencei---Privileged-architecture---Instruction-stream-synchronization-extension) - instruction stream synchronization (optional) |
* [`Zifencei`](#Zifencei---Instruction-stream-synchronization-extension) - instruction stream synchronization (optional) |
* [`PMP`](#PMP---Privileged-architecture---Physical-memory-protection) - physical memory protection (optional) |
* [`HPM`](#HPM---Privileged-architecture---Hardware-performance-monitors) - hardware performance monitors (optional) |
* Full-scale RISC-V microcontroller system / **SoC** [**NEORV32 Processor**](#NEORV32-Processor-Features) with optional submodules |
140,7 → 142,9
* smart LED interface (**NEOLED**) - WS2812 / NeoPixel(c) compatible |
* system configuration information memory to check hardware configuration by software (**SYSINFO**) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
### NEORV32 CPU Features |
|
The NEORV32 CPU implements the |
163,12 → 167,16
* Privilege levels: `machine` mode, `user` mode (if enabled via `U` extension) |
* Official [RISC-V open-source architecture ID](https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `A` - Atomic memory access extension |
|
* Supported instructions: `LR.W` (load-reservate) `SC.W` (store-conditional) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `B` - Bit manipulation instructions extension |
|
* :construction: **work-in-progress** :construction: |
180,7 → 188,9
* `Zbs` single-bit instructions: `SBSET[I]` `SBCLR[I]` `SBINV[I]` `SBEXT[I]` |
* `Zba` shifted-add instructions: `SH1ADD` `SH2ADD` `SH3ADD` |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `C` - Compressed instructions extension |
|
* ALU instructions: `C.ADDI4SPN` `C.ADD[I]` `C.ADDI16SP` `C.LI` `C.LUI` `C.SLLI` `C.SRLI` `C.SRAI` `C.ANDI` `C.SUB` `C.XOR` `C.OR` `C.AND` `C.MV` `C.NOP` |
189,11 → 199,16
* System instructions: `C.EBREAK` (requires `Zicsr` extension) |
* Pseudo-instructions are not listed |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `E` - Embedded CPU version extension |
|
* Reduced register file (only the 16 lowest registers are implemented) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `I` - Base integer instruction set |
|
* ALU instructions: `LUI` `AUIPC` `ADD[I]` `SLT[I][U]` `XOR[I]` `OR[I]` `AND[I]` `SLL[I]` `SRL[I]` `SRA[I]` `SUB` |
202,7 → 217,9
* System instructions: `ECALL` `EBREAK` `FENCE` |
* Pseudo-instructions are not listed |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `M` - Integer multiplication and division hardware extension |
|
* Multiplication instructions: `MUL` `MULH` `MULHSU` `MULHU` |
210,13 → 227,17
* By default, the multiplier and divider cores use an iterative bit-serial processing scheme |
* Multiplications can be mapped to DSPs via the `FAST_MUL_EN` generic to increase performance |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `U` - Privileged architecture - User mode extension |
|
* Requires `Zicsr` extension |
* Privilege levels: `M` (machine mode) + less-privileged `U` (user mode) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `X` - NEORV32-specific CPU extensions |
|
* The NEORV32-specific extensions are always enabled and are indicated via the `X` bit set in the `misa` CSR. |
224,7 → 245,9
* `mzext` CSR to check for implemented `Z*` CPU extensions (like `Zifencei`) |
* All undefined/umimplemented/malformed/illegal instructions do raise an illegal instruction exception |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `Zfinx` - Single-precision floating-point extension |
|
* :warning: this extension has not been officially ratified yet! |
235,6 → 258,8
* Comparison instructions: `FMIN.S` `FMAX.S` `FEQ.S` `FLT.S` `FLE.S` |
* Conversion instructions: `FCVT.W.S` `FCVT.WU.S` `FCVT.S.W` `FCVT.S.WU` |
* Additional CSRs: `fcsr` `frm` `fflags` |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `Zicsr` - Privileged architecture - CSR access extension |
262,12 → 287,16
* RISC-V machine external interrupt `mei` (via external signal) |
* 16 fast interrupt requests, 6+1 available for custom usage |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
#### `Zifencei` - Privileged architecture - Instruction stream synchronization extension |
|
#### `Zifencei` - Instruction stream synchronization extension |
|
* System instructions: `FENCE.I` (among others, used to clear and reload instruction cache) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `PMP` - Privileged architecture - Physical memory protection |
|
* Requires `Zicsr` extension |
274,7 → 303,9
* Configurable number of regions (0..63) |
* Additional machine CSRs: `pmpcfg*`(0..15) `pmpaddr*`(0..63) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
#### `HPM` - Privileged architecture - Hardware performance monitors |
|
* Requires `Zicsr` extension |
281,17 → 312,20
* Configurable number of counters (0..29) |
* Additional machine CSRs: `mhpmevent*`(3..31) `[m]hpmcounter*[h]`(3..31) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
### :warning: Non-RISC-V-Compatible Issues and Limitations |
|
* CPU and Processor are BIG-ENDIAN, but this should be no problem as the external memory bus interface provides big- and little-endian configurations |
* `misa` CSR is read-only - no dynamic enabling/disabling of synthesized CPU extensions during runtime; for compatibility: write accesses (in m-mode) are ignored and do not cause an exception |
* The physical memory protection (**PMP**) only supports `NAPOT` mode yet and a minimal granularity of 8 bytes |
* The `A` extension only implements `lr.w` and `sc.w` instructions yet. However, these instructions are sufficient to emulate all further AMO operations |
* The `mcause` trap code `0x80000000` (originally reserved in the RISC-V specs) is used to indicate a hardware reset (as "non-maskable interrupt") |
* The `A` extension only implements `lr.w` and `sc.w` instructions yet. However, these instructions are sufficient to emulate all remaining AMO operations |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
|
## FPGA Implementation Results |
|
### NEORV32 CPU |
313,12 → 347,14
| `rv32imac` + `Zicsr` | 2685 | 1156 | 1024 | 0 | 124 MHz | |
| `rv32imac` + `Zicsr` + `u` | 2698 | 1162 | 1024 | 0 | 124 MHz | |
| `rv32imac` + `Zicsr` + `u` + `Zifencei` | 2715 | 1162 | 1024 | 0 | 122 MHz | |
| `rv32imac` + `Zicsr` + `u` + `Zifencei` + `Zfinx` | 4004 | 1812 | 1024 | 0 | 121 MHz | |
| `rv32imac` + `Zicsr` + `u` + `Zifencei` + `Zfinx` | 4004 | 1812 | 1024 | 7 | 121 MHz | |
|
Setups with enabled "embedded CPU extension" `E` show the same LUT and FF utilization and identical f_max as the according `I` configuration. |
However, the size of the register file is cut in half. |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
### NEORV32 Processor-Internal Peripherals and Memories |
|
Results generated for hardware version [`1.5.3.2`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md). |
344,14 → 380,16
| WDT | Watchdog timer | 60 | 45 | 0 | 0 | |
| WISHBONE | External memory interface | 129 | 104 | 0 | 0 | |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
### NEORV32 Processor - Exemplary FPGA Setups |
|
Exemplary processor implementation results for different FPGA platforms. The processor setup uses *the default peripheral configuration* (like no _CFS_ and no _TRNG_), |
no external memory interface and only internal instruction and data memories. IMEM uses 16kB and DMEM uses 8kB memory space. The setup's top entity connects most of the |
processor's [top entity](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd) signals |
to FPGA pins - except for the Wishbone bus and the interrupt signals. The "default" strategy of each toolchain is used. |
:information_source: Check out the [`boards`](https://github.com/stnolting/neorv32/tree/master/boards) folder for exemplary setups targeting various FPGA boards. |
|
The following tables show exemplary processor implementation results for different FPGA platforms. The processor setups use *the default peripheral configuration* (like no *CFS* and no *TRNG*), |
no external memory interface and only internal instruction and data memories. IMEM uses 16kB and DMEM uses 8kB memory space. |
|
Results generated for hardware version [`1.4.9.0`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md). |
|
| Vendor | FPGA | Board | Toolchain | CPU Configuration | LUT / LE | FF / REG | DSP (9-bit) | Memory Bits | BRAM / EBR | SPRAM | Frequency | |
361,6 → 399,7
| Xilinx | Artix-7 `XC7A35TICSG324-1L` | Arty A7-35T | Vivado 2019.2 | `rv32imc` + `u` + `Zicsr` + `Zifencei` + `PMP` | 2465 (12%) | 1912 (5%) | 0 (0%) | - | 8 (16%) | - | *c* 100 MHz | |
|
**_Notes_** |
* The "default" implementation strategy of the according toolchain is used. |
* The Lattice iCE40 UltraPlus setup uses the FPGA's SPRAM memory primitives for the internal IMEM and DMEM (each 64kb). |
The FPGA-specific memory components can be found in [`rtl/fpga_specific`](https://github.com/stnolting/neorv32/blob/master/rtl/fpga_specific/lattice_ice40up). |
* The clock frequencies marked with a "c" are constrained clocks. The remaining ones are _f_max_ results from the place and route timing reports. |
369,8 → 408,10
* The setups with `PMP` implement 2 regions with a minimal granularity of 64kB. |
* No HPM counters are implemented. |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
|
## Performance |
|
### CoreMark Benchmark |
381,21 → 422,20
|
~~~ |
**Configuration** |
Hardware: 32kB IMEM, 16kB DMEM, no caches, 100MHz clock |
Hardware: 32kB IMEM, 8kB DMEM, no caches, 100MHz clock |
CoreMark: 2000 iterations, MEM_METHOD is MEM_STACK |
Compiler: RISCV32-GCC 10.1.0 (rv32i toolchain) |
Compiler flags: default, see makefile |
Optimization: -O3 |
Peripherals: UART for printing the results |
~~~ |
|
Results generated for hardware version [`1.4.9.8`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md). |
|
| CPU (including `Zicsr`) | Executable Size | Optimization | CoreMark Score | CoreMarks/MHz | |
| CPU (including `Zicsr` extension) | Executable Size | Optimization | CoreMark Score | CoreMarks/MHz | |
|:--------------------------------------------|:---------------:|:------------:|:--------------:|:-------------:| |
| `rv32i` | 28 756 bytes | `-O3` | 36.36 | **0.3636** | |
| `rv32im` | 27 516 bytes | `-O3` | 68.97 | **0.6897** | |
| `rv32imc` | 22 008 bytes | `-O3` | 68.97 | **0.6897** | |
| `rv32imc` + `FAST_MUL_EN` | 22 008 bytes | `-O3` | 86.96 | **0.8696** | |
| `rv32imc` + `FAST_MUL_EN` + `FAST_SHIFT_EN` | 22 008 bytes | `-O3` | 90.91 | **0.9091** | |
|
The `FAST_MUL_EN` configuration uses DSPs for the multiplier of the `M` extension (enabled via the `FAST_MUL_EN` generic). The `FAST_SHIFT_EN` configuration |
403,7 → 443,9
|
When the `C` extension is enabled, branches to an unaligned uncompressed instruction require additional instruction fetch cycles. |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
### Instruction Cycles |
|
The NEORV32 CPU is based on a two-stages pipelined architecutre. Each stage uses a multi-cycle processing scheme. Hence, |
419,12 → 461,10
|
Results generated for hardware version [`1.4.9.8`](https://github.com/stnolting/neorv32/blob/master/CHANGELOG.md). |
|
| CPU (including `Zicsr`) | Required Clock Cycles | Executed Instructions | Average CPI | |
| CPU (including `Zicsr` extension) | Required Clock Cycles | Executed Instructions | Average CPI | |
|:--------------------------------------------|----------------------:|----------------------:|:-----------:| |
| `rv32i` | 5 595 750 503 | 1 466 028 607 | **3.82** | |
| `rv32im` | 2 966 086 503 | 598 651 143 | **4.95** | |
| `rv32imc` | 2 981 786 734 | 611 814 918 | **4.87** | |
| `rv32imc` + `FAST_MUL_EN` | 2 399 234 734 | 611 814 918 | **3.92** | |
| `rv32imc` + `FAST_MUL_EN` + `FAST_SHIFT_EN` | 2 265 135 174 | 611 814 948 | **3.70** | |
|
The `FAST_MUL_EN` configuration uses DSPs for the multiplier of the `M` extension (enabled via the `FAST_MUL_EN` generic). The `FAST_SHIFT_EN` configuration |
432,8 → 472,10
|
When the `C` extension is enabled branches to an unaligned uncompressed instruction require additional instruction fetch cycles. |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
|
## Top Entities |
|
The top entity of the **NEORV32 Processor** (SoC) is [`rtl/core/neorv32_top.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd), |
454,7 → 496,9
**Alternative top entities**, like the simplified ["hello world" test setup](#Create-a-new-Hardware-Project) or CPU/Processor |
wrappers with resolved port signal types (i.e. *std_logic*), can be found in [`rtl/top_templates`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates). |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
### AXI4 Connectivity |
|
Via the [`rtl/top_templates/neorv32_top_axi4lite.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_top_axi4lite.vhd) |
474,8 → 518,10
the attached block RAMs are used for storing instructions and data: the first RAM is used as instruction memory |
and is mapped to address `0x00000000 - 0x00003fff` (16kB), the second RAM is used as data memory and is mapped to address `0x80000000 - 0x80001fff` (8kB). |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
|
## Getting Started |
|
This overview is just a short excerpt from the *Let's Get It Started* section of the NEORV32 documentary: |
520,6 → 566,9
|
### 3. Create a new FPGA Project |
|
:information_source: If want to use a script-based exemplary project setup check out the [`boards`](https://github.com/stnolting/neorv32/tree/master/boards) folder, |
which provides exemplary setups targeting various FPGA boards. |
|
Create a new project with your FPGA design tool of choice. Add all the `*.vhd` files from the [`rtl/core`](https://github.com/stnolting/neorv32/blob/master/rtl) |
folder to this project. Make sure to add these files to a **new design library** called `neorv32`. |
|
609,6 → 658,7
|
Going further: Take a look at the _Let's Get It Started!_ chapter of the [:page_facing_up: NEORV32 data sheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf). |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
## Contribute/Feedback/Questions |
628,7 → 678,9
6. Push to the branch: `git push origin awesome_new_feature_branch` |
7. Create a new [pull request](https://github.com/stnolting/neorv32/pulls) |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
## Legal |
|
This project is released under the BSD 3-Clause license. No copyright infringement intended. |
690,8 → 742,10
|
"NeoPixel" is a trademark of Adafruit Industries. |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
|
|
## Acknowledgements |
|
[![RISC-V](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/riscv_logo.png)](https://riscv.org/) |
704,6 → 758,8
|
This project is not affiliated with or endorsed by the Open Source Initiative (https://www.oshwa.org / https://opensource.org). |
|
[[back to top](#The-NEORV32-RISC-V-Processor)] |
|
-------- |
|
Made with :coffee: in Hannover, Germany :eu: |