mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-04-24 22:17:05 -04:00
Merge remote-tracking branch 'origin/master' into dev
This commit is contained in:
commit
02db756b21
132 changed files with 28372 additions and 1888 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
|||
*.class
|
||||
*.log
|
||||
*.bak
|
||||
.*.swp
|
||||
|
||||
# sbt specific
|
||||
.cache/
|
||||
|
@ -24,6 +25,7 @@ out
|
|||
bin/
|
||||
.classpath
|
||||
.project
|
||||
.cproject
|
||||
.settings
|
||||
.cache-main
|
||||
|
||||
|
@ -39,6 +41,7 @@ obj_dir
|
|||
*.yaml
|
||||
*.memTrace
|
||||
*.regTrace
|
||||
*.debugTrace
|
||||
*.tcl
|
||||
*.o
|
||||
*.bin
|
||||
|
@ -46,4 +49,4 @@ obj_dir
|
|||
simWorkspace/
|
||||
tmp/
|
||||
/archive.tar.gz
|
||||
*.out32
|
||||
*.out32
|
||||
|
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "src/test/resources/VexRiscvRegressionData"]
|
||||
path = src/test/resources/VexRiscvRegressionData
|
||||
url = ../VexRiscvRegressionData.git
|
105
.travis.yml
105
.travis.yml
|
@ -1,64 +1,89 @@
|
|||
language: scala
|
||||
|
||||
dist: xenial
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: never
|
||||
|
||||
# See 'project/Version.scala'
|
||||
scala:
|
||||
- 2.11.6
|
||||
- 2.11.12
|
||||
|
||||
sbt_args: -no-colors -J-Xss2m
|
||||
|
||||
script:
|
||||
- export VEXRISCV_REGRESSION_CONFIG_COUNT=100
|
||||
- export VEXRISCV_REGRESSION_FREERTOS_COUNT=no
|
||||
- sbt -jvm-opts travis/jvmopts.compile compile
|
||||
- sbt -jvm-opts travis/jvmopts.test test
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- git
|
||||
- make
|
||||
- autoconf
|
||||
- g++
|
||||
- flex
|
||||
- bison
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
# - oraclejdk7
|
||||
# - openjdk7
|
||||
- openjdk10
|
||||
|
||||
env:
|
||||
- secure: "v7FHP8yK/zixpv1ML05qcRhZfDVDFdTmTPjfMZHL7gmrJveVDgze22x4tY4tB1+JEXhKuVTYvimOrX/Ok+rOOT5gVKLowv4PUQwCR+HgWVIbqjcfZNLsa369v03/p4K/zbjJSiXFahZYOXa0ApED2KWHcVfCrNsPv0UF7YZGiIa1Q/lPBwfmpN1rLih2Mpgn4KVaJky22t7JXJyVrNdGVmIA51slVbyFwFAE8Ww/0tkC+i2PUcWWRMIxtXP4iyq/9Npcq5VdqOatKfWHqAElLfKSPNMYLMlcyxyNpNx4paq8cL6fQxFcBLi9M2msz2i/qpKv30a0tzNo5bQQgucAXOQJB2Buks728upLuqsr+k25hwcqrtjyMOr9UQkt7qXAJH/0kimW7aW1yoMxbm/6mNG98X9D1EzNRewHAKatwJeFy1bw5qIuSQxPBwQMGloManrHOHGotmHKk7Y+dgM/z1UlaAdxSQuKWGXBc8QlQvif8puPYEdJMoInJNRxiWfYu06XnmzTXgMketK7RdULM9DVYzw8hzS2EIWKu8Oa0zn0PTevD2YeJNd4G8mDqO0vz5hloIc7pFsq/exQUB/kFozfCsnvhW8P+MPN0LpuSpptBQTsLWbM5BH0hd46HoWcneDdlMvVrUcgsTPmmSroIkLIEUo+Y2iN5eQHPPp85Cw="
|
||||
jobs:
|
||||
include:
|
||||
- stage: prepare cache-verilator
|
||||
script:
|
||||
- cp scripts/regression/verilator.mk $HOME/makefile
|
||||
- cd $HOME
|
||||
- make verilator_binary
|
||||
- &test
|
||||
stage: Test
|
||||
name: Dhrystone
|
||||
script:
|
||||
- make regression_dhrystone -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Baremetal
|
||||
script:
|
||||
- make regression_random_baremetal -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Machine OS
|
||||
script:
|
||||
- make regression_random_machine_os -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Machine OS
|
||||
script:
|
||||
- make regression_random_machine_os -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Mixed
|
||||
script:
|
||||
- make regression_random -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Linux
|
||||
script:
|
||||
- make regression_random_linux -C scripts/regression
|
||||
- <<: *test
|
||||
stage: Test
|
||||
name: Linux
|
||||
script:
|
||||
- make regression_random_linux -C scripts/regression
|
||||
|
||||
before_install:
|
||||
# JDK fix
|
||||
- cat /etc/hosts # optionally check the content *before*
|
||||
- sudo hostname "$(hostname | cut -c1-63)"
|
||||
- sed -e "s/^\\(127\\.0\\.0\\.1.*\\)/\\1 $(hostname | cut -c1-63)/" /etc/hosts | sudo tee /etc/hosts
|
||||
- cat /etc/hosts # optionally check the content *after*
|
||||
- cd ..
|
||||
|
||||
# Verilator
|
||||
- sudo apt-get install git make autoconf g++ flex bison -y # First time prerequisites
|
||||
- git clone http://git.veripool.org/git/verilator # Only first time
|
||||
- unset VERILATOR_ROOT # For bash
|
||||
- cd verilator
|
||||
- git pull # Make sure we're up-to-date
|
||||
- git checkout verilator_3_916
|
||||
- autoconf # Create ./configure script
|
||||
- ./configure
|
||||
- make -j$(nproc)
|
||||
- sudo make install
|
||||
- cd ..
|
||||
|
||||
- git clone https://github.com/SpinalHDL/SpinalHDL.git -b dev
|
||||
|
||||
- cd VexRiscv
|
||||
#- curl -T README.md -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/README.md
|
||||
#- curl -X POST -udolu1990:$BINTRAY_KEY https://api.bintray.com/content/spinalhdl/VexRiscv/test/0.0.4/publish
|
||||
#- sbt compile
|
||||
|
||||
- export VERILATOR_ROOT=$HOME/verilator
|
||||
- export PATH=$VERILATOR_ROOT/bin:$PATH
|
||||
|
||||
before_cache:
|
||||
# Tricks to avoid unnecessary cache updates
|
||||
- find $HOME/.ivy2 -name "ivydata-*.properties" -delete
|
||||
- find $HOME/.sbt -name "*.lock" -delete
|
||||
- rm -fv $HOME/.ivy2/.sbt.ivy.lock
|
||||
- find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete
|
||||
- find $HOME/.sbt -name "*.lock" -print -delete
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.ivy2/cache
|
||||
- $HOME/.sbt/boot/
|
||||
- $HOME/.sbt
|
||||
- $HOME/verilator
|
||||
|
||||
|
|
232
README.md
232
README.md
|
@ -12,6 +12,7 @@
|
|||
* [By using FreedomStudio](#by-using-freedomstudio)
|
||||
- [Briey SoC](#briey-soc)
|
||||
- [Murax SoC](#murax-soc)
|
||||
- [Running Linux](#running-linux)
|
||||
- [Build the RISC-V GCC](#build-the-risc-v-gcc)
|
||||
- [CPU parametrization and instantiation example](#cpu-parametrization-and-instantiation-example)
|
||||
- [Add a custom instruction to the CPU via the plugin system](#add-a-custom-instruction-to-the-cpu-via-the-plugin-system)
|
||||
|
@ -26,22 +27,21 @@
|
|||
|
||||
This repository hosts a RISC-V implementation written in SpinalHDL. Here are some specs :
|
||||
|
||||
- RV32I[M][C] instruction set
|
||||
- Pipelined with 5 stages (Fetch, Decode, Execute, Memory, WriteBack)
|
||||
- RV32I[M][C][A] instruction set (Atomic only inside a single core)
|
||||
- Pipelined from 2 to 5+ stages ([Fetch*X], Decode, Execute, [Memory], [WriteBack])
|
||||
- 1.44 DMIPS/Mhz --no-inline when nearly all features are enabled (1.57 DMIPS/Mhz when the divider lookup table is enabled)
|
||||
- Optimized for FPGA, fully portable
|
||||
- AXI4 and Avalon ready
|
||||
- Optimized for FPGA, do not use any vendor specific IP block / primitive
|
||||
- AXI4, Avalon, wishbone ready
|
||||
- Optional MUL/DIV extensions
|
||||
- Optional instruction and data caches
|
||||
- Optional MMU
|
||||
- Optional hardware refilled MMU
|
||||
- Optional debug extension allowing Eclipse debugging via a GDB >> openOCD >> JTAG connection
|
||||
- Optional interrupts and exception handling with Machine and User modes as defined in the [RISC-V Privileged ISA Specification v1.9](https://riscv.org/specifications/privileged-isa/).
|
||||
- Optional interrupts and exception handling with Machine, [Supervisor] and [User] modes as defined in the [RISC-V Privileged ISA Specification v1.10](https://riscv.org/specifications/privileged-isa/).
|
||||
- Two implementations of shift instructions: Single cycle and shiftNumber cycles
|
||||
- Each stage can have optional bypass or interlock hazard logic
|
||||
- Zephyr RISC-V port compatible
|
||||
- Linux compatible
|
||||
- Zephyr compatible
|
||||
- [FreeRTOS port](https://github.com/Dolu1990/FreeRTOS-RISCV)
|
||||
- The data cache supports atomic LR/SC
|
||||
- Optional RV32 compressed instruction support in the reworkFetch branch for configurations without instruction cache (will be merge in master, WIP)
|
||||
|
||||
The hardware description of this CPU is done by using a very software oriented approach
|
||||
(without any overhead in the generated hardware). Here is a list of software concepts used:
|
||||
|
@ -66,48 +66,54 @@ The CPU configurations used below can be found in the `src/scala/vexriscv/demo`
|
|||
|
||||
```
|
||||
VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) ->
|
||||
Artix 7 -> 346 Mhz 481 LUT 539 FF
|
||||
Cyclone V -> 201 Mhz 347 ALMs
|
||||
Cyclone IV -> 190 Mhz 673 LUT 529 FF
|
||||
iCE40 -> 81 Mhz 1130 LC
|
||||
Artix 7 -> 366 Mhz 488 LUT 505 FF
|
||||
Cyclone V -> 181 Mhz 350 ALMs
|
||||
Cyclone IV -> 177 Mhz 732 LUT 494 FF
|
||||
iCE40 -> 85 Mhz 1131 LC
|
||||
|
||||
VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) ->
|
||||
Artix 7 -> 340 Mhz 562 LUT 589 FF
|
||||
Cyclone V -> 202 Mhz 387 ALMs
|
||||
Cyclone IV -> 180 Mhz 780 LUT 579 FF
|
||||
iCE40 -> 71 Mhz 1278 LC
|
||||
Artix 7 -> 317 Mhz 539 LUT 559 FF
|
||||
Cyclone V -> 191 Mhz 393 ALMs
|
||||
Cyclone IV -> 171 Mhz 826 LUT 547 FF
|
||||
iCE40 -> 72 Mhz 1284 LC
|
||||
|
||||
VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) ->
|
||||
Artix 7 -> 327 Mhz 698 LUT 558 FF
|
||||
Cyclone V -> 158 Mhz 524 ALMs
|
||||
Cyclone IV -> 146 Mhz 1,061 LUT 552 FF
|
||||
iCE40 -> 55 Mhz 1541 LC
|
||||
Artix 7 -> 338 Mhz 697 LUT 527 FF
|
||||
Cyclone V -> 149 Mhz 495 ALMs
|
||||
Cyclone IV -> 137 Mhz 1,103 LUT 522 FF
|
||||
iCE40 -> 65 Mhz 1593 LC
|
||||
|
||||
VexRiscv small and productive with I$ (RV32I, 0.72 DMIPS/Mhz, 4KB-I$) ->
|
||||
Artix 7 -> 331 Mhz 727 LUT 600 FF
|
||||
Cyclone V -> 152 Mhz 536 ALMs
|
||||
Cyclone IV -> 156 Mhz 1,075 LUT 565 FF
|
||||
iCE40 -> 54 Mhz 1686 LC
|
||||
VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) ->
|
||||
Artix 7 -> 314 Mhz 721 LUT 562 FF
|
||||
Cyclone V -> 152 Mhz 504 ALMs
|
||||
Cyclone IV -> 142 Mhz 1,146 LUT 528 FF
|
||||
iCE40 -> 69 Mhz 1661 LC
|
||||
|
||||
VexRiscv full no cache (RV32IM, 1.22 DMIPS/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) ->
|
||||
Artix 7 -> 295 Mhz 1399 LUT 971 FF
|
||||
Cyclone V -> 151 Mhz 922 ALMs
|
||||
Cyclone IV -> 136 Mhz 1,859 LUT 992 FF
|
||||
VexRiscv full no cache (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) ->
|
||||
Artix 7 -> 325 Mhz 1448 LUT 976 FF
|
||||
Cyclone V -> 141 Mhz 957 ALMs
|
||||
Cyclone IV -> 139 Mhz 2,001 LUT 966 FF
|
||||
|
||||
VexRiscv full (RV32IM, 1.21 DMIPS/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) ->
|
||||
Artix 7 -> 253 Mhz 1840 LUT 1394 FF
|
||||
Cyclone V -> 126 Mhz 1,172 ALMs
|
||||
Cyclone IV -> 117 Mhz 2,548 LUT 1,703 FF
|
||||
VexRiscv full (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) ->
|
||||
Artix 7 -> 241 Mhz 1692 LUT 1202 FF
|
||||
Cyclone V -> 132 Mhz 1,127 ALMs
|
||||
Cyclone IV -> 124 Mhz 2,296 LUT 1,115 FF
|
||||
|
||||
VexRiscv full max perf -> (RV32IM, 1.44 DMIPS/Mhz, 16KB-I$,16KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) ->
|
||||
Artix 7 -> 183 Mhz 1813 LUT 1424 FF
|
||||
Cyclone V -> 93 Mhz 1,253 ALMs
|
||||
Cyclone IV -> 84 Mhz 2,642 LUT 1,711 FF
|
||||
VexRiscv full max dmips/mhz -> (RV32IM, 1.44 DMIPS/Mhz 2.70 Coremark/Mhz,, 16KB-I$,16KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) ->
|
||||
Artix 7 -> 195 Mhz 1824 LUT 1110 FF
|
||||
Cyclone V -> 83 Mhz 1,067 ALMs
|
||||
Cyclone IV -> 78 Mhz 2,335 LUT 1,045 FF
|
||||
|
||||
VexRiscv full with MMU (RV32IM, 1.24 DMIPS/Mhz 2.35 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) ->
|
||||
Artix 7 -> 218 Mhz 1966 LUT 1551 FF
|
||||
Cyclone V -> 123 Mhz 1,298 ALMs
|
||||
Cyclone IV -> 109 Mhz 2,703 LUT 1,498 FF
|
||||
|
||||
VexRiscv linux balanced (RV32IMA, 1.21 DMIPS/Mhz 2.27 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, catch exceptions, static branch, MMU, Supervisor, Compatible with mainstream linux) ->
|
||||
Artix 7 -> 239 Mhz 2483 LUT 2134 FF
|
||||
Cyclone V -> 130 Mhz 1,636 ALMs
|
||||
Cyclone IV -> 116 Mhz 3,324 LUT 2,010 FF
|
||||
|
||||
VexRiscv full with MMU (RV32IM, 1.26 DMIPS/Mhz with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) ->
|
||||
Artix 7 -> 214 Mhz 2070 LUT 1913 FF
|
||||
Cyclone V -> 108 Mhz 1,430 ALMs
|
||||
Cyclone IV -> 100 Mhz 2,976 LUT 2,201 FF
|
||||
```
|
||||
|
||||
The following configuration results in 1.44 DMIPS/MHz:
|
||||
|
@ -127,7 +133,7 @@ Note that recently, the capability to remove the Fetch/Memory/WriteBack stage wa
|
|||
On Ubuntu 14 :
|
||||
|
||||
```sh
|
||||
# JAVA JDK 8. Do not try with JDK >= 9
|
||||
# JAVA JDK 8
|
||||
sudo add-apt-repository -y ppa:openjdk-r/ppa
|
||||
sudo apt-get update
|
||||
sudo apt-get install openjdk-8-jdk -y
|
||||
|
@ -177,6 +183,9 @@ NOTES:
|
|||
do a "sbt clean compile publish-local" in it as described in the dependencies chapter.
|
||||
|
||||
## Regression tests
|
||||
|
||||
[](https://travis-ci.org/SpinalHDL/VexRiscv)
|
||||
|
||||
To run tests (need the verilator simulator), go in the src/test/cpp/regression folder and run :
|
||||
|
||||
```sh
|
||||
|
@ -223,7 +232,19 @@ continue
|
|||
|
||||
## Using Eclipse to run the software and debug it
|
||||
|
||||
### By using Zylin plugin
|
||||
### By using gnu-mcu-eclipse
|
||||
|
||||
You can download releases of the IDE here : https://github.com/gnu-mcu-eclipse/org.eclipse.epp.packages/releases
|
||||
|
||||
In the IDE, you can import a makefile project by :
|
||||
- file -> import -> C/C++ -> existing Code as Makefile Project
|
||||
- Select the folder which contain the makefile, select "Cross GCC" (not "RISC-V Cross GCC")
|
||||
|
||||
To create a new debug configuration :
|
||||
- run -> Debug Configurations -> GDB OpenOCD Debugging double click
|
||||
- Look at https://drive.google.com/open?id=1c46tyEV0xLwOsk76b0y2qqs8CYy7Zq3f for a configuration example
|
||||
|
||||
### By using Zylin plugin (old)
|
||||
You can use the Eclipse + Zylin embedded CDT plugin to do it (http://opensource.zylin.com/embeddedcdt.html). Tested with Helios Service Release 2 (http://www.Eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/helios/SR2/Eclipse-cpp-helios-SR2-linux-gtk-x86_64.tar.gz) and the corresponding zylin plugin.
|
||||
|
||||
To following commands will download Eclipse and install the plugin.
|
||||
|
@ -238,13 +259,6 @@ See https://drive.google.com/drive/folders/1NseNHH05B6lmIXqQFVwK8xRjWE4ydeG-?usp
|
|||
|
||||
Note that sometime this Eclipse need to be restarted in order to be able to place new breakpoints.
|
||||
|
||||
### By using FreedomStudio
|
||||
|
||||
You can get FreedomStudio (which is package with Eclipse and some plugins) here: https://www.sifive.com/products/tools/
|
||||
|
||||
See https://drive.google.com/drive/folders/1a7FyMOYgFc9UDhfsWUSCjyqDCvOrts2J?usp=sharing to import a makefile project and create a debug configuration.
|
||||
|
||||
|
||||
## Briey SoC
|
||||
As a demonstrator, a SoC named Briey is implemented in `src/main/scala/vexriscv/demo/Briey.scala`. This SoC is very similar to
|
||||
the [Pinsec SOC](https://spinalhdl.github.io/SpinalDoc/spinal/lib/pinsec/hardware/):
|
||||
|
@ -282,9 +296,9 @@ You can find some FPGA projects which instantiate the Briey SoC here (DE1-SoC, D
|
|||
Here are some measurements of Briey SoC timings and area :
|
||||
|
||||
```
|
||||
Artix 7 -> 239 Mhz 3227 LUT 3410 FF
|
||||
Cyclone V -> 125 Mhz 2,207 ALMs
|
||||
Cyclone IV -> 112 Mhz 4,594 LUT 3,620
|
||||
Artix 7 -> 232 Mhz 3042 LUT 3281 FF
|
||||
Cyclone V -> 138 Mhz 2,179 ALMs
|
||||
Cyclone IV -> 120 Mhz 4,333 LUT 3,167 FF
|
||||
```
|
||||
|
||||
## Murax SoC
|
||||
|
@ -337,18 +351,16 @@ Here are some timing and area measurements of the Murax SoC:
|
|||
|
||||
```
|
||||
Murax interlocked stages (0.45 DMIPS/Mhz, 8 bits GPIO) ->
|
||||
Artix 7 -> 299 Mhz 984 LUT 1186 FF
|
||||
Cyclone V -> 175 Mhz 710 ALMs
|
||||
Cyclone IV -> 137 Mhz 1,436 LUT 1,193 FF
|
||||
iCE40 -> 48 Mhz 2337 LC (icestorm)
|
||||
iCE40Ultra -> 20 Mhz 2337 LC (icestorm)
|
||||
Artix 7 - > 301 Mhz 1032 LUT 1199 FF
|
||||
Cyclone V -> 183 Mhz 736 ALMs
|
||||
Cyclone IV -> 148 Mhz 1,481 LUT 1,204 FF
|
||||
iCE40 -> 69 Mhz 2403 LC (nextpnr)
|
||||
|
||||
MuraxFast bypassed stages (0.65 DMIPS/Mhz, 8 bits GPIO) ->
|
||||
Artix 7 -> 294 Mhz 1128 LUT 1219 FF
|
||||
Cyclone V -> 165 Mhz 840 ALMs
|
||||
Cyclone IV -> 141 Mhz 1,680 LUT 1,227 FF
|
||||
iCE40 -> 48 Mhz 2702 LC (icestorm)
|
||||
iCE40Ultra -> 22 Mhz 2702 LC (icestorm)
|
||||
Artix 7 -> 321 Mhz 1198 LUT 1298 FF
|
||||
Cyclone V -> 165 Mhz 873 ALMs
|
||||
Cyclone IV -> 145 Mhz 1,691 LUT 1,239 FF
|
||||
iCE40 -> 61 Mhz 2778 LC (nextpnr)
|
||||
```
|
||||
|
||||
Some scripts to generate the SoC and call the icestorm toolchain can be found here: `scripts/Murax/`
|
||||
|
@ -362,6 +374,18 @@ To run it :
|
|||
sbt "test:runMain vexriscv.MuraxSim"
|
||||
```
|
||||
|
||||
## Running Linux
|
||||
|
||||
A default configuration is located in src/main/scala/vexriscv/demo/Linux.scala
|
||||
|
||||
This file also contains
|
||||
- The commands to compile the buildroot image
|
||||
- How to run the Verilator simulation in interative mode
|
||||
|
||||
There is currently no SoC to run it on hardware, it is WIP. But the CPU simulation can already boot linux and run user space application (even python).
|
||||
|
||||
Note that VexRiscv can run Linux on both cache full and cache less design.
|
||||
|
||||
## Build the RISC-V GCC
|
||||
|
||||
A prebuild GCC toolsuite can be found here:
|
||||
|
@ -653,18 +677,18 @@ This chapter describes plugins currently implemented.
|
|||
This plugin implement the CPU frontend (instruction fetch) via a very simple and neutral memory interface going outside the CPU.
|
||||
|
||||
| Parameters | type | description |
|
||||
| ------ | ----------- | ------ |
|
||||
| catchAccessFault | Boolean | If an the read response specify an read error and this parameter is true, it will generate an CPU exception trap |
|
||||
| resetVector | BigInt | Address of the program counter after the reset |
|
||||
| cmdForkOnSecondStage | Boolean | By default jump have an asynchronous immediate effect on the program counter, which allow to reduce the branch penalties by one cycle but could reduce the FMax as it will combinatorialy drive the instruction bus address signal. To avoid this you can set this parameter to true, which will make the jump affecting the programm counter in a sequancial way, which will cut the combinatorial path but add one additional cycle of penalty when a jump occur. |
|
||||
| cmdForkPersistence | Boolean | If this parameter is false, then request on the iBus can disappear/change before their completion. Which reduce area but isn't safe/supported by many arbitration/slaves. If you set this parameter to true, then the iBus cmd will stay until they are completed.
|
||||
| compressedGen | Boolean | Enable RVC support |
|
||||
| busLatencyMin | Int | Specify the minimal latency between the iBus.cmd and iBus.rsp, which will add the corresponding number of stages into the frontend to keep the IPC to 1.|
|
||||
| injectorStage | Boolean | Add a stage between the frontend and the decode stage of the CPU to improve FMax. (busLatencyMin + injectorStage) should be at least two. |
|
||||
| prediction | BranchPrediction | Can be set to NONE/STATIC/DYNAMIC/DYNAMIC_TARGET to specify the branch predictor implementation, see bellow for more descriptions |
|
||||
| historyRamSizeLog2 | Int | Specify the number of entries in the direct mapped prediction cache of DYNAMIC/DYNAMIC_TARGET implementation. 2 pow historyRamSizeLog2 entries |
|
||||
| ------ | ----------- | ------ |
|
||||
| catchAccessFault | Boolean | When true, an instruction read response with read error asserted results in a CPU exception trap. |
|
||||
| resetVector | BigInt | Address of the program counter after the reset. |
|
||||
| cmdForkOnSecondStage | Boolean | When false, branches immediately update the program counter. This minimizes branch penalties but might reduce FMax because the instruction bus address signal is a combinatorial path. When true, this combinatorial path is removed and the program counter is updated one cycle after a branch is detected. While FMax may improve, an additional branch penalty will be incurred as well. |
|
||||
| cmdForkPersistence | Boolean | When false, requests on the iBus can disappear/change before they are acknowledged. This reduces area but isn't safe/supported by many arbitration/slaves. When true, once initiated, iBus requests will stay until they are acknowledged. |
|
||||
| compressedGen | Boolean | Enable RISC-V compressed instruction (RVC) support. |
|
||||
| busLatencyMin | Int | Specifies the minimal latency between the iBus.cmd and iBus.rsp. A corresponding number of stages are added to the frontend to keep the IPC to 1.|
|
||||
| injectorStage | Boolean | When true, a stage between the frontend and the decode stage of the CPU is added to improve FMax. (busLatencyMin + injectorStage) should be at least two. |
|
||||
| prediction | BranchPrediction | Can be set to NONE/STATIC/DYNAMIC/DYNAMIC_TARGET to specify the branch predictor implementation. See below for more details. |
|
||||
| historyRamSizeLog2 | Int | Specify the number of entries in the direct mapped prediction cache of DYNAMIC/DYNAMIC_TARGET implementation. 2 pow historyRamSizeLog2 entries. |
|
||||
|
||||
Here is the SimpleBus interface definition
|
||||
Here is the SimpleBus interface definition:
|
||||
|
||||
```scala
|
||||
case class IBusSimpleCmd() extends Bundle{
|
||||
|
@ -695,9 +719,9 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
|
|||
|
||||
Setting cmdForkPersistence and cmdForkOnSecondStage improves iBus cmd timings.
|
||||
|
||||
Note that bridges are implemented to convert this interface into AXI4 and Avalon
|
||||
The iBusSimplePlugin includes bridges to convert from the IBusSimpleBus to AXI4, Avalon, and Wishbone interfaces.
|
||||
|
||||
The jump interface implemented by this plugin allow all other plugin to request jumps. The stage argument specify from which stage the jump is asked, which will allow the PcManagerSimplePlugin plugin to manage priorities between jump requests.
|
||||
This plugin implements a jump interface that allows all other plugins to issue a jump:
|
||||
|
||||
```scala
|
||||
trait JumpService{
|
||||
|
@ -705,6 +729,8 @@ trait JumpService{
|
|||
}
|
||||
```
|
||||
|
||||
The stage argument specifies the stage from which the jump is asked. This allows the PcManagerSimplePlugin plugin to manage priorities between jump requests from
|
||||
diffent stages.
|
||||
|
||||
#### IBusCachedPlugin
|
||||
|
||||
|
@ -712,35 +738,35 @@ Simple and light multi-way instruction cache.
|
|||
|
||||
| Parameters | type | description |
|
||||
| ------ | ----------- | ------ |
|
||||
| cacheSize | Int | Total storage capacity of the cache |
|
||||
| bytePerLine | Int | Number of bytes per cache line |
|
||||
| wayCount | Int | Number of cache ways |
|
||||
| twoCycleRam | Boolean | Check the tags values in the decode stage instead of the fetch stage to relax timings |
|
||||
| asyncTagMemory | Boolean | Read the cache tags in a asyncronus manner instead of syncronous one |
|
||||
| addressWidth | Int | Address width, should be 32 |
|
||||
| cpuDataWidth | Int | Cpu data width, should be 32 |
|
||||
| memDataWidth | Int | Memory data width, could potentialy be something else than 32, but only 32 is currently tested |
|
||||
| catchIllegalAccess | Boolean | Catch when a memory access is done on non valid memory address (MMU) |
|
||||
| catchAccessFault | Boolean | Catch when the memeory bus is responding with an error |
|
||||
| catchMemoryTranslationMiss | Boolean | Catch when the MMU miss a TLB |
|
||||
| resetVector | BigInt | Address of the program counter after the reset |
|
||||
| relaxedPcCalculation | Boolean | By default jump have an asynchronous immediate effect on the program counter, which allow to reduce the branch penalties by one cycle but could reduce the FMax as it will combinatorialy drive the instruction bus address signal. To avoid this you can set this parameter to true, which will make the jump affecting the programm counter in a sequancial way, which will cut the combinatorial path but add one additional cycle of penalty when a jump occur. |
|
||||
| compressedGen | Boolean | Enable RVC support |
|
||||
| prediction | BranchPrediction | Can be set to NONE/STATIC/DYNAMIC/DYNAMIC_TARGET to specify the branch predictor implementation, see bellow for more descriptions |
|
||||
| resetVector | BigInt | Address of the program counter after the reset. |
|
||||
| relaxedPcCalculation | Boolean | When false, branches immediately update the program counter. This minimizes branch penalties but might reduce FMax because the instruction bus address signal is a combinatorial path. When true, this combinatorial path is removed and the program counter is updated one cycle after a branch is detected. While FMax may improve, an additional branch penalty will be incurred as well. |
|
||||
| prediction | BranchPrediction | Can be set to NONE/STATIC/DYNAMIC/DYNAMIC_TARGET to specify the branch predictor implementation. See below for more details. |
|
||||
| historyRamSizeLog2 | Int | Specify the number of entries in the direct mapped prediction cache of DYNAMIC/DYNAMIC_TARGET implementation. 2 pow historyRamSizeLog2 entries |
|
||||
| compressedGen | Boolean | Enable RISC-V compressed instruction (RVC) support. |
|
||||
| config.cacheSize | Int | Total storage capacity of the cache in bytes. |
|
||||
| config.bytePerLine | Int | Number of bytes per cache line |
|
||||
| config.wayCount | Int | Number of cache ways |
|
||||
| config.twoCycleRam | Boolean | Check the tags values in the decode stage instead of the fetch stage to relax timings |
|
||||
| config.asyncTagMemory | Boolean | Read the cache tags in an asynchronous manner instead of syncronous one |
|
||||
| config.addressWidth | Int | CPU address width. Should be 32 |
|
||||
| config.cpuDataWidth | Int | CPU data width. Should be 32 |
|
||||
| config.memDataWidth | Int | Memory data width. Could potentialy be something else than 32, but only 32 is currently tested |
|
||||
| config.catchIllegalAccess | Boolean | Catch when a memory access is done on non-valid memory address (MMU) |
|
||||
| config.catchAccessFault | Boolean | Catch when the memeory bus is responding with an error |
|
||||
| config.catchMemoryTranslationMiss | Boolean | Catch when the MMU miss a TLB |
|
||||
|
||||
Note: If you enable the twoCycleRam option and if wayCount is bigger than one, then the register file plugin should be configured to read the regFile in a asynchronous manner.
|
||||
Note: If you enable the twoCycleRam option and if wayCount is bigger than one, then the register file plugin should be configured to read the regFile in an asynchronous manner.
|
||||
|
||||
#### DecoderSimplePlugin
|
||||
|
||||
This plugin provides instruction decoding capabilities to others plugins.
|
||||
|
||||
For instance, for a given instruction, the pipeline hazard plugin needs to know if it uses the register file source 1/2 in order stall the pipeline until the hazard is gone.
|
||||
For instance, for a given instruction, the pipeline hazard plugin needs to know if it uses the register file source 1/2 in order to stall the pipeline until the hazard is gone.
|
||||
To provide this kind of information, each plugin which implements an instruction documents this kind of information to the DecoderSimplePlugin plugin.
|
||||
|
||||
| Parameters | type | description |
|
||||
| ------ | ----------- | ------ |
|
||||
| catchIllegalInstruction | Boolean | If set to true, instruction which have no decoding specification will generate a trap exception |
|
||||
| catchIllegalInstruction | Boolean | When true, instructions that don't match a decoding specification will generate a trap exception |
|
||||
|
||||
Here is a usage example :
|
||||
|
||||
|
@ -752,11 +778,11 @@ Here is a usage example :
|
|||
|
||||
//Decoding specification when the 'key' pattern is recognized in the instruction
|
||||
List(
|
||||
IS_SIMD_ADD -> True,
|
||||
REGFILE_WRITE_VALID -> True, //Enable the register file write
|
||||
IS_SIMD_ADD -> True, //Inform the pipeline that the current instruction is a SIMD_ADD instruction
|
||||
REGFILE_WRITE_VALID -> True, //Notify the hazard management unit that this instruction writes to the register file
|
||||
BYPASSABLE_EXECUTE_STAGE -> True, //Notify the hazard management unit that the instruction result is already accessible in the EXECUTE stage (Bypass ready)
|
||||
BYPASSABLE_MEMORY_STAGE -> True, //Same as above but for the memory stage
|
||||
RS1_USE -> True, //Notify the hazard management unit that this instruction use the RS1 value
|
||||
RS1_USE -> True, //Notify the hazard management unit that this instruction uses the RS1 value
|
||||
RS2_USE -> True //Same than above but for RS2.
|
||||
)
|
||||
)
|
||||
|
@ -853,7 +879,7 @@ The down side is that this predictor has a long combinatorial path coming from t
|
|||
|
||||
#### DBusSimplePlugin
|
||||
|
||||
This plugin implements the load and store instructions (LB/LH/LW/LBU/LHU/LWU/SB/SH/SW) via a simple and neutral memory bus going out of the CPU.
|
||||
This plugin implements the load and store instructions (LB/LH/LW/LBU/LHU/LWU/SB/SH/SW) via a simple memory bus going out of the CPU.
|
||||
|
||||
| Parameters | type | description |
|
||||
| ------ | ----------- | ------ |
|
||||
|
@ -899,7 +925,7 @@ There is at least one cycle latency between a cmd and the corresponding rsp. The
|
|||
|
||||
#### DBusCachedPlugin
|
||||
|
||||
Single way cache implementation with a victim buffer. (Documentation is WIP)
|
||||
Multi way cache implementation with writh-through and allocate on read strategy. (Documentation is WIP)
|
||||
|
||||
#### MulPlugin
|
||||
|
||||
|
@ -968,10 +994,10 @@ stage before jumping to mtvec.
|
|||
|
||||
Static memory translator plugin which allows one to specify which range of the memory addresses is IO mapped and shouldn't be cached.
|
||||
|
||||
#### MemoryTranslatorPlugin
|
||||
#### MmuPlugin
|
||||
|
||||
Simple software refilled MMU implementation. Allows others plugins such as DBusCachedPlugin/IBusCachedPlugin to instanciate memory address translation ports. Each port has a small dedicated
|
||||
fully associative TLB cache which is refilled from a larger software filled TLB cache via a query which looks up one entry per cycle.
|
||||
Hardware refilled MMU implementation. Allows others plugins such as DBusCachedPlugin/IBusCachedPlugin to instanciate memory address translation ports. Each port has a small dedicated
|
||||
fully associative TLB cache which is refilled automaticaly via a dbus access sharing.
|
||||
|
||||
#### DebugPlugin
|
||||
|
||||
|
|
14
build.sbt
14
build.sbt
|
@ -4,19 +4,19 @@ lazy val root = (project in file(".")).
|
|||
inThisBuild(List(
|
||||
organization := "com.github.spinalhdl",
|
||||
scalaVersion := "2.11.12",
|
||||
version := "1.0.0"
|
||||
version := "2.0.0"
|
||||
)),
|
||||
libraryDependencies ++= Seq(
|
||||
// "com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.2",
|
||||
// "com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.2",
|
||||
"com.github.spinalhdl" % "spinalhdl-core_2.11" % "1.3.3",
|
||||
"com.github.spinalhdl" % "spinalhdl-lib_2.11" % "1.3.3",
|
||||
"org.scalatest" % "scalatest_2.11" % "2.2.1",
|
||||
"org.yaml" % "snakeyaml" % "1.8"
|
||||
),
|
||||
name := "VexRiscv"
|
||||
).dependsOn(spinalHdlSim,spinalHdlCore,spinalHdlLib)
|
||||
lazy val spinalHdlSim = ProjectRef(file("../SpinalHDL"), "sim")
|
||||
lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "core")
|
||||
lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "lib")
|
||||
)//.dependsOn(spinalHdlSim,spinalHdlCore,spinalHdlLib)
|
||||
//lazy val spinalHdlSim = ProjectRef(file("../SpinalHDL"), "sim")
|
||||
//lazy val spinalHdlCore = ProjectRef(file("../SpinalHDL"), "core")
|
||||
//lazy val spinalHdlLib = ProjectRef(file("../SpinalHDL"), "lib")
|
||||
|
||||
|
||||
fork := true
|
|
@ -2,7 +2,8 @@ This example is for the
|
|||
[Lattice iCE40HX-8K Breakout Board](http://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx).
|
||||
|
||||
An image of this board is shown below;
|
||||
![img/iCE40HX8K-breakout-revA.png]
|
||||
|
||||

|
||||
|
||||
This board can be purchased for ~$USD 49 directly from Lattice and is supported
|
||||
by the IceStorm
|
||||
|
@ -20,7 +21,8 @@ mode. This requires removing jumper `J7` and putting the pair of jumpers on
|
|||
This is shown in **Figure 5** of the
|
||||
[iCE40HX-8K Breakout Board User Guide](http://www.latticesemi.com/view_document?document_id=50373).
|
||||
which is also reproduced below;
|
||||
![img/cram-programming-config.png]
|
||||
|
||||

|
||||
|
||||
Once your board is ready, you should follow the setup instructions at the
|
||||
[top level](../../../README.md).
|
||||
|
|
|
@ -2,7 +2,8 @@ This example is for the
|
|||
[Lattice iCE40HX-8K Breakout Board](http://www.latticesemi.com/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx).
|
||||
|
||||
An image of this board is shown below;
|
||||
![img/iCE40HX8K-breakout-revA.png]
|
||||
|
||||

|
||||
|
||||
This board can be purchased for ~$USD 49 directly from Lattice and is supported
|
||||
by the IceStorm
|
||||
|
@ -20,7 +21,8 @@ mode. This requires removing jumper `J7` and putting the pair of jumpers on
|
|||
This is shown in **Figure 5** of the
|
||||
[iCE40HX-8K Breakout Board User Guide](http://www.latticesemi.com/view_document?document_id=50373).
|
||||
which is also reproduced below;
|
||||
![img/cram-programming-config.png]
|
||||
|
||||

|
||||
|
||||
Once your board is ready, you should follow the setup instructions at the
|
||||
[top level](../../../README.md).
|
||||
|
|
3
scripts/regression/.gitignore
vendored
Normal file
3
scripts/regression/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
verilator*
|
||||
verilator
|
||||
!verilator.mk
|
7
scripts/regression/makefile
Normal file
7
scripts/regression/makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
.ONESHELL:
|
||||
|
||||
include verilator.mk
|
||||
include regression.mk
|
||||
|
||||
|
||||
|
45
scripts/regression/regression.mk
Normal file
45
scripts/regression/regression.mk
Normal file
|
@ -0,0 +1,45 @@
|
|||
.ONESHELL:
|
||||
|
||||
|
||||
regression_random:
|
||||
cd ../..
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=4
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=1
|
||||
export VEXRISCV_REGRESSION_ZEPHYR_COUNT=4
|
||||
export VEXRISCV_REGRESSION_THREAD_COUNT=1
|
||||
sbt "testOnly vexriscv.TestIndividualFeatures"
|
||||
|
||||
regression_random_linux:
|
||||
cd ../..
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=3
|
||||
export VEXRISCV_REGRESSION_CONFIG_LINUX_RATE=1.0
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=1
|
||||
export VEXRISCV_REGRESSION_ZEPHYR_COUNT=2
|
||||
export VEXRISCV_REGRESSION_THREAD_COUNT=1
|
||||
sbt "testOnly vexriscv.TestIndividualFeatures"
|
||||
|
||||
|
||||
regression_random_machine_os:
|
||||
cd ../..
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=15
|
||||
export VEXRISCV_REGRESSION_CONFIG_LINUX_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE=1.0
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=1
|
||||
export VEXRISCV_REGRESSION_ZEPHYR_COUNT=2
|
||||
export VEXRISCV_REGRESSION_THREAD_COUNT=1
|
||||
sbt "testOnly vexriscv.TestIndividualFeatures"
|
||||
|
||||
regression_random_baremetal:
|
||||
cd ../..
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=40
|
||||
export VEXRISCV_REGRESSION_CONFIG_LINUX_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE=0.0
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=1
|
||||
export VEXRISCV_REGRESSION_ZEPHYR_COUNT=no
|
||||
export VEXRISCV_REGRESSION_THREAD_COUNT=1
|
||||
sbt "testOnly vexriscv.TestIndividualFeatures"
|
||||
|
||||
|
||||
regression_dhrystone:
|
||||
cd ../..
|
||||
sbt "testOnly vexriscv.DhrystoneBench"
|
20
scripts/regression/verilator.mk
Normal file
20
scripts/regression/verilator.mk
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
.ONESHELL:
|
||||
|
||||
verilator/configure:
|
||||
rm -rf verilator*
|
||||
wget https://www.veripool.org/ftp/verilator-4.012.tgz
|
||||
tar xvzf verilator*.t*gz
|
||||
mv verilator-4.012 verilator
|
||||
|
||||
verilator/Makefile: verilator/configure
|
||||
cd verilator
|
||||
./configure
|
||||
|
||||
verilator/bin/verilator_bin: verilator/Makefile
|
||||
cd verilator
|
||||
make -j$(shell nproc)
|
||||
rm -rf src/obj_dbg
|
||||
rm -rf src/obj_opt
|
||||
|
||||
verilator_binary: verilator/bin/verilator_bin
|
151
src/main/c/common/ram.ld
Executable file
151
src/main/c/common/ram.ld
Executable file
|
@ -0,0 +1,151 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
ENTRY( _start )
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram : ORIGIN = 0x80000000, LENGTH = 64k
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
}> ram
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(.note.gnu.build-id)
|
||||
} > ram
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} > ram
|
||||
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} > ram
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} > ram
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} > ram
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} > ram
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} > ram
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
} > ram
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data = . );
|
||||
} > ram
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} >ram
|
||||
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _edata = . );
|
||||
PROVIDE( edata = . );
|
||||
|
||||
PROVIDE( _fbss = . );
|
||||
PROVIDE( __bss_start = . );
|
||||
.bss :
|
||||
{
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
} >ram
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _end = . );
|
||||
PROVIDE( end = . );
|
||||
|
||||
.stack :
|
||||
{
|
||||
PROVIDE( _heap_end = . );
|
||||
. = __stack_size;
|
||||
PROVIDE( _sp = . );
|
||||
} > ram
|
||||
}
|
16
src/main/c/common/riscv64-unknown-elf.mk
Normal file
16
src/main/c/common/riscv64-unknown-elf.mk
Normal file
|
@ -0,0 +1,16 @@
|
|||
RISCV_BIN ?= riscv64-unknown-elf-
|
||||
RISCV_CC=${RISCV_BIN}gcc
|
||||
RISCV_OBJCOPY=${RISCV_BIN}objcopy
|
||||
RISCV_OBJDUMP=${RISCV_BIN}objdump
|
||||
|
||||
MARCH := rv32i
|
||||
ifeq ($(MULDIV),yes)
|
||||
MARCH := $(MARCH)M
|
||||
endif
|
||||
ifeq ($(COMPRESSED),yes)
|
||||
MARCH := $(MARCH)AC
|
||||
endif
|
||||
|
||||
CFLAGS += -march=$(MARCH) -mabi=ilp32 -DUSE_GP
|
||||
LDFLAGS += -march=$(MARCH) -mabi=ilp32
|
||||
|
74
src/main/c/common/standalone.mk
Normal file
74
src/main/c/common/standalone.mk
Normal file
|
@ -0,0 +1,74 @@
|
|||
|
||||
|
||||
LDFLAGS += -lc
|
||||
|
||||
CFLAGS += -I${STANDALONE}/include
|
||||
|
||||
|
||||
|
||||
|
||||
ifeq ($(DEBUG),yes)
|
||||
CFLAGS += -g3 -Og
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),no)
|
||||
CFLAGS += -O3
|
||||
endif
|
||||
|
||||
|
||||
LDFLAGS += -nostdlib -lgcc -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage
|
||||
|
||||
|
||||
|
||||
OBJDIR ?= build
|
||||
OBJS := $(SRCS)
|
||||
OBJS := $(OBJS:.c=.o)
|
||||
OBJS := $(OBJS:.cpp=.o)
|
||||
OBJS := $(OBJS:.S=.o)
|
||||
OBJS := $(OBJS:..=miaou)
|
||||
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
|
||||
|
||||
|
||||
|
||||
all: $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).bin
|
||||
|
||||
$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
|
||||
$(RISCV_CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||
|
||||
%.hex: %.elf
|
||||
$(RISCV_OBJCOPY) -O ihex $^ $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(RISCV_OBJCOPY) -O binary $^ $@
|
||||
|
||||
%.v: %.elf
|
||||
$(RISCV_OBJCOPY) -O verilog $^ $@
|
||||
|
||||
%.asm: %.elf
|
||||
$(RISCV_OBJDUMP) -S -d $^ > $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
|
||||
$(OBJDIR)/%.o: %.S
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).elf
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).hex
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).map
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).v
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).bin
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).asm
|
||||
find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
|
||||
|
||||
.SECONDARY: $(OBJS)
|
6
src/main/c/emulator/.gitignore
vendored
Normal file
6
src/main/c/emulator/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
||||
*.hex
|
||||
!*.bin
|
620
src/main/c/emulator/build/emulator.asm
Normal file
620
src/main/c/emulator/build/emulator.asm
Normal file
|
@ -0,0 +1,620 @@
|
|||
|
||||
build/emulator.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .init:
|
||||
|
||||
80000000 <_start>:
|
||||
80000000: 00001117 auipc sp,0x1
|
||||
80000004: 18810113 addi sp,sp,392 # 80001188 <_sp>
|
||||
80000008: 00001517 auipc a0,0x1
|
||||
8000000c: 8dc50513 addi a0,a0,-1828 # 800008e4 <__init_array_end>
|
||||
80000010: 00001597 auipc a1,0x1
|
||||
80000014: 8d458593 addi a1,a1,-1836 # 800008e4 <__init_array_end>
|
||||
80000018: 00001617 auipc a2,0x1
|
||||
8000001c: 97060613 addi a2,a2,-1680 # 80000988 <__bss_start>
|
||||
80000020: 00c5fc63 bgeu a1,a2,80000038 <_start+0x38>
|
||||
80000024: 00052283 lw t0,0(a0)
|
||||
80000028: 0055a023 sw t0,0(a1)
|
||||
8000002c: 00450513 addi a0,a0,4
|
||||
80000030: 00458593 addi a1,a1,4
|
||||
80000034: fec5e8e3 bltu a1,a2,80000024 <_start+0x24>
|
||||
80000038: 00001517 auipc a0,0x1
|
||||
8000003c: 95050513 addi a0,a0,-1712 # 80000988 <__bss_start>
|
||||
80000040: 00001597 auipc a1,0x1
|
||||
80000044: 94858593 addi a1,a1,-1720 # 80000988 <__bss_start>
|
||||
80000048: 00b57863 bgeu a0,a1,80000058 <_start+0x58>
|
||||
8000004c: 00052023 sw zero,0(a0)
|
||||
80000050: 00450513 addi a0,a0,4
|
||||
80000054: feb56ce3 bltu a0,a1,8000004c <_start+0x4c>
|
||||
80000058: 7e4000ef jal ra,8000083c <__libc_init_array>
|
||||
8000005c: 178000ef jal ra,800001d4 <init>
|
||||
80000060: 00000097 auipc ra,0x0
|
||||
80000064: 01408093 addi ra,ra,20 # 80000074 <done>
|
||||
80000068: 00000513 li a0,0
|
||||
8000006c: c30005b7 lui a1,0xc3000
|
||||
80000070: 30200073 mret
|
||||
|
||||
80000074 <done>:
|
||||
80000074: 0000006f j 80000074 <done>
|
||||
|
||||
80000078 <_init>:
|
||||
80000078: 00008067 ret
|
||||
|
||||
8000007c <trapEntry>:
|
||||
8000007c: 34011173 csrrw sp,mscratch,sp
|
||||
80000080: 00112223 sw ra,4(sp)
|
||||
80000084: 00312623 sw gp,12(sp)
|
||||
80000088: 00412823 sw tp,16(sp)
|
||||
8000008c: 00512a23 sw t0,20(sp)
|
||||
80000090: 00612c23 sw t1,24(sp)
|
||||
80000094: 00712e23 sw t2,28(sp)
|
||||
80000098: 02812023 sw s0,32(sp)
|
||||
8000009c: 02912223 sw s1,36(sp)
|
||||
800000a0: 02a12423 sw a0,40(sp)
|
||||
800000a4: 02b12623 sw a1,44(sp)
|
||||
800000a8: 02c12823 sw a2,48(sp)
|
||||
800000ac: 02d12a23 sw a3,52(sp)
|
||||
800000b0: 02e12c23 sw a4,56(sp)
|
||||
800000b4: 02f12e23 sw a5,60(sp)
|
||||
800000b8: 05012023 sw a6,64(sp)
|
||||
800000bc: 05112223 sw a7,68(sp)
|
||||
800000c0: 05212423 sw s2,72(sp)
|
||||
800000c4: 05312623 sw s3,76(sp)
|
||||
800000c8: 05412823 sw s4,80(sp)
|
||||
800000cc: 05512a23 sw s5,84(sp)
|
||||
800000d0: 05612c23 sw s6,88(sp)
|
||||
800000d4: 05712e23 sw s7,92(sp)
|
||||
800000d8: 07812023 sw s8,96(sp)
|
||||
800000dc: 07912223 sw s9,100(sp)
|
||||
800000e0: 07a12423 sw s10,104(sp)
|
||||
800000e4: 07b12623 sw s11,108(sp)
|
||||
800000e8: 07c12823 sw t3,112(sp)
|
||||
800000ec: 07d12a23 sw t4,116(sp)
|
||||
800000f0: 07e12c23 sw t5,120(sp)
|
||||
800000f4: 07f12e23 sw t6,124(sp)
|
||||
800000f8: 2c4000ef jal ra,800003bc <trap>
|
||||
800000fc: 00412083 lw ra,4(sp)
|
||||
80000100: 00c12183 lw gp,12(sp)
|
||||
80000104: 01012203 lw tp,16(sp)
|
||||
80000108: 01412283 lw t0,20(sp)
|
||||
8000010c: 01812303 lw t1,24(sp)
|
||||
80000110: 01c12383 lw t2,28(sp)
|
||||
80000114: 02012403 lw s0,32(sp)
|
||||
80000118: 02412483 lw s1,36(sp)
|
||||
8000011c: 02812503 lw a0,40(sp)
|
||||
80000120: 02c12583 lw a1,44(sp)
|
||||
80000124: 03012603 lw a2,48(sp)
|
||||
80000128: 03412683 lw a3,52(sp)
|
||||
8000012c: 03812703 lw a4,56(sp)
|
||||
80000130: 03c12783 lw a5,60(sp)
|
||||
80000134: 04012803 lw a6,64(sp)
|
||||
80000138: 04412883 lw a7,68(sp)
|
||||
8000013c: 04812903 lw s2,72(sp)
|
||||
80000140: 04c12983 lw s3,76(sp)
|
||||
80000144: 05012a03 lw s4,80(sp)
|
||||
80000148: 05412a83 lw s5,84(sp)
|
||||
8000014c: 05812b03 lw s6,88(sp)
|
||||
80000150: 05c12b83 lw s7,92(sp)
|
||||
80000154: 06012c03 lw s8,96(sp)
|
||||
80000158: 06412c83 lw s9,100(sp)
|
||||
8000015c: 06812d03 lw s10,104(sp)
|
||||
80000160: 06c12d83 lw s11,108(sp)
|
||||
80000164: 07012e03 lw t3,112(sp)
|
||||
80000168: 07412e83 lw t4,116(sp)
|
||||
8000016c: 07812f03 lw t5,120(sp)
|
||||
80000170: 07c12f83 lw t6,124(sp)
|
||||
80000174: 34011173 csrrw sp,mscratch,sp
|
||||
80000178: 30200073 mret
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
8000017c <putString>:
|
||||
8000017c: ff010113 addi sp,sp,-16
|
||||
80000180: 00812423 sw s0,8(sp)
|
||||
80000184: 00112623 sw ra,12(sp)
|
||||
80000188: 00050413 mv s0,a0
|
||||
8000018c: 00054503 lbu a0,0(a0)
|
||||
80000190: 00050a63 beqz a0,800001a4 <putString+0x28>
|
||||
80000194: 00140413 addi s0,s0,1
|
||||
80000198: 668000ef jal ra,80000800 <putC>
|
||||
8000019c: 00044503 lbu a0,0(s0)
|
||||
800001a0: fe051ae3 bnez a0,80000194 <putString+0x18>
|
||||
800001a4: 00c12083 lw ra,12(sp)
|
||||
800001a8: 00812403 lw s0,8(sp)
|
||||
800001ac: 01010113 addi sp,sp,16
|
||||
800001b0: 00008067 ret
|
||||
|
||||
800001b4 <setup_pmp>:
|
||||
800001b4: 01f00793 li a5,31
|
||||
800001b8: fff00713 li a4,-1
|
||||
800001bc: 00000297 auipc t0,0x0
|
||||
800001c0: 01428293 addi t0,t0,20 # 800001d0 <setup_pmp+0x1c>
|
||||
800001c4: 30529073 csrw mtvec,t0
|
||||
800001c8: 3b071073 csrw pmpaddr0,a4
|
||||
800001cc: 3a079073 csrw pmpcfg0,a5
|
||||
800001d0: 00008067 ret
|
||||
|
||||
800001d4 <init>:
|
||||
800001d4: ff010113 addi sp,sp,-16
|
||||
800001d8: 00112623 sw ra,12(sp)
|
||||
800001dc: 00812423 sw s0,8(sp)
|
||||
800001e0: 01f00793 li a5,31
|
||||
800001e4: fff00713 li a4,-1
|
||||
800001e8: 00000297 auipc t0,0x0
|
||||
800001ec: 01428293 addi t0,t0,20 # 800001fc <init+0x28>
|
||||
800001f0: 30529073 csrw mtvec,t0
|
||||
800001f4: 3b071073 csrw pmpaddr0,a4
|
||||
800001f8: 3a079073 csrw pmpcfg0,a5
|
||||
800001fc: 80001437 lui s0,0x80001
|
||||
80000200: 638000ef jal ra,80000838 <halInit>
|
||||
80000204: 95840413 addi s0,s0,-1704 # 80000958 <_sp+0xfffff7d0>
|
||||
80000208: 02a00513 li a0,42
|
||||
8000020c: 00140413 addi s0,s0,1
|
||||
80000210: 5f0000ef jal ra,80000800 <putC>
|
||||
80000214: 00044503 lbu a0,0(s0)
|
||||
80000218: fe051ae3 bnez a0,8000020c <init+0x38>
|
||||
8000021c: 800007b7 lui a5,0x80000
|
||||
80000220: 07c78793 addi a5,a5,124 # 8000007c <_sp+0xffffeef4>
|
||||
80000224: 30579073 csrw mtvec,a5
|
||||
80000228: 800017b7 lui a5,0x80001
|
||||
8000022c: 10878793 addi a5,a5,264 # 80001108 <_sp+0xffffff80>
|
||||
80000230: 34079073 csrw mscratch,a5
|
||||
80000234: 000017b7 lui a5,0x1
|
||||
80000238: 88078793 addi a5,a5,-1920 # 880 <__stack_size+0x80>
|
||||
8000023c: 30079073 csrw mstatus,a5
|
||||
80000240: 30405073 csrwi mie,0
|
||||
80000244: c00007b7 lui a5,0xc0000
|
||||
80000248: 34179073 csrw mepc,a5
|
||||
8000024c: 0000b7b7 lui a5,0xb
|
||||
80000250: 10078793 addi a5,a5,256 # b100 <__stack_size+0xa900>
|
||||
80000254: 30279073 csrw medeleg,a5
|
||||
80000258: 22200793 li a5,546
|
||||
8000025c: 30379073 csrw mideleg,a5
|
||||
80000260: 14305073 csrwi stval,0
|
||||
80000264: 80001437 lui s0,0x80001
|
||||
80000268: 97040413 addi s0,s0,-1680 # 80000970 <_sp+0xfffff7e8>
|
||||
8000026c: 02a00513 li a0,42
|
||||
80000270: 00140413 addi s0,s0,1
|
||||
80000274: 58c000ef jal ra,80000800 <putC>
|
||||
80000278: 00044503 lbu a0,0(s0)
|
||||
8000027c: fe051ae3 bnez a0,80000270 <init+0x9c>
|
||||
80000280: 00c12083 lw ra,12(sp)
|
||||
80000284: 00812403 lw s0,8(sp)
|
||||
80000288: 01010113 addi sp,sp,16
|
||||
8000028c: 00008067 ret
|
||||
|
||||
80000290 <readRegister>:
|
||||
80000290: 800017b7 lui a5,0x80001
|
||||
80000294: 10878793 addi a5,a5,264 # 80001108 <_sp+0xffffff80>
|
||||
80000298: 00251513 slli a0,a0,0x2
|
||||
8000029c: 00f50533 add a0,a0,a5
|
||||
800002a0: 00052503 lw a0,0(a0)
|
||||
800002a4: 00008067 ret
|
||||
|
||||
800002a8 <writeRegister>:
|
||||
800002a8: 800017b7 lui a5,0x80001
|
||||
800002ac: 00251513 slli a0,a0,0x2
|
||||
800002b0: 10878793 addi a5,a5,264 # 80001108 <_sp+0xffffff80>
|
||||
800002b4: 00f50533 add a0,a0,a5
|
||||
800002b8: 00b52023 sw a1,0(a0)
|
||||
800002bc: 00008067 ret
|
||||
|
||||
800002c0 <redirectTrap>:
|
||||
800002c0: ff010113 addi sp,sp,-16
|
||||
800002c4: 00112623 sw ra,12(sp)
|
||||
800002c8: 530000ef jal ra,800007f8 <stopSim>
|
||||
800002cc: 343027f3 csrr a5,mtval
|
||||
800002d0: 14379073 csrw stval,a5
|
||||
800002d4: 341027f3 csrr a5,mepc
|
||||
800002d8: 14179073 csrw sepc,a5
|
||||
800002dc: 342027f3 csrr a5,mcause
|
||||
800002e0: 14279073 csrw scause,a5
|
||||
800002e4: 105027f3 csrr a5,stvec
|
||||
800002e8: 34179073 csrw mepc,a5
|
||||
800002ec: 00c12083 lw ra,12(sp)
|
||||
800002f0: 01010113 addi sp,sp,16
|
||||
800002f4: 00008067 ret
|
||||
|
||||
800002f8 <emulationTrapToSupervisorTrap>:
|
||||
800002f8: 800007b7 lui a5,0x80000
|
||||
800002fc: 07c78793 addi a5,a5,124 # 8000007c <_sp+0xffffeef4>
|
||||
80000300: 30579073 csrw mtvec,a5
|
||||
80000304: 343027f3 csrr a5,mtval
|
||||
80000308: 14379073 csrw stval,a5
|
||||
8000030c: 342027f3 csrr a5,mcause
|
||||
80000310: 14279073 csrw scause,a5
|
||||
80000314: 14151073 csrw sepc,a0
|
||||
80000318: 105027f3 csrr a5,stvec
|
||||
8000031c: 34179073 csrw mepc,a5
|
||||
80000320: 0035d793 srli a5,a1,0x3
|
||||
80000324: 00459713 slli a4,a1,0x4
|
||||
80000328: 02077713 andi a4,a4,32
|
||||
8000032c: 1007f793 andi a5,a5,256
|
||||
80000330: 00e7e7b3 or a5,a5,a4
|
||||
80000334: ffffe737 lui a4,0xffffe
|
||||
80000338: 6dd70713 addi a4,a4,1757 # ffffe6dd <_sp+0x7fffd555>
|
||||
8000033c: 00e5f5b3 and a1,a1,a4
|
||||
80000340: 00b7e7b3 or a5,a5,a1
|
||||
80000344: 000015b7 lui a1,0x1
|
||||
80000348: 88058593 addi a1,a1,-1920 # 880 <__stack_size+0x80>
|
||||
8000034c: 00b7e7b3 or a5,a5,a1
|
||||
80000350: 30079073 csrw mstatus,a5
|
||||
80000354: 00008067 ret
|
||||
|
||||
80000358 <readWord>:
|
||||
80000358: 00020737 lui a4,0x20
|
||||
8000035c: 30072073 csrs mstatus,a4
|
||||
80000360: 00000717 auipc a4,0x0
|
||||
80000364: 01870713 addi a4,a4,24 # 80000378 <readWord+0x20>
|
||||
80000368: 30571073 csrw mtvec,a4
|
||||
8000036c: 00100693 li a3,1
|
||||
80000370: 00052783 lw a5,0(a0)
|
||||
80000374: 00000693 li a3,0
|
||||
80000378: 00020737 lui a4,0x20
|
||||
8000037c: 30073073 csrc mstatus,a4
|
||||
80000380: 00068513 mv a0,a3
|
||||
80000384: 00f5a023 sw a5,0(a1)
|
||||
80000388: 00008067 ret
|
||||
|
||||
8000038c <writeWord>:
|
||||
8000038c: 00020737 lui a4,0x20
|
||||
80000390: 30072073 csrs mstatus,a4
|
||||
80000394: 00000717 auipc a4,0x0
|
||||
80000398: 01870713 addi a4,a4,24 # 800003ac <writeWord+0x20>
|
||||
8000039c: 30571073 csrw mtvec,a4
|
||||
800003a0: 00100793 li a5,1
|
||||
800003a4: 00b52023 sw a1,0(a0)
|
||||
800003a8: 00000793 li a5,0
|
||||
800003ac: 00020737 lui a4,0x20
|
||||
800003b0: 30073073 csrc mstatus,a4
|
||||
800003b4: 00078513 mv a0,a5
|
||||
800003b8: 00008067 ret
|
||||
|
||||
800003bc <trap>:
|
||||
800003bc: fe010113 addi sp,sp,-32
|
||||
800003c0: 00112e23 sw ra,28(sp)
|
||||
800003c4: 00812c23 sw s0,24(sp)
|
||||
800003c8: 00912a23 sw s1,20(sp)
|
||||
800003cc: 01212823 sw s2,16(sp)
|
||||
800003d0: 01312623 sw s3,12(sp)
|
||||
800003d4: 342027f3 csrr a5,mcause
|
||||
800003d8: 0807cc63 bltz a5,80000470 <trap+0xb4>
|
||||
800003dc: 00200713 li a4,2
|
||||
800003e0: 0ce78463 beq a5,a4,800004a8 <trap+0xec>
|
||||
800003e4: 00900693 li a3,9
|
||||
800003e8: 04d79463 bne a5,a3,80000430 <trap+0x74>
|
||||
800003ec: 80001437 lui s0,0x80001
|
||||
800003f0: 18840413 addi s0,s0,392 # 80001188 <_sp+0x0>
|
||||
800003f4: fc442783 lw a5,-60(s0)
|
||||
800003f8: 00100693 li a3,1
|
||||
800003fc: fa842503 lw a0,-88(s0)
|
||||
80000400: 2ed78463 beq a5,a3,800006e8 <trap+0x32c>
|
||||
80000404: 2ee78e63 beq a5,a4,80000700 <trap+0x344>
|
||||
80000408: 2a078c63 beqz a5,800006c0 <trap+0x304>
|
||||
8000040c: 01812403 lw s0,24(sp)
|
||||
80000410: 01c12083 lw ra,28(sp)
|
||||
80000414: 01412483 lw s1,20(sp)
|
||||
80000418: 01012903 lw s2,16(sp)
|
||||
8000041c: 00c12983 lw s3,12(sp)
|
||||
80000420: 02010113 addi sp,sp,32
|
||||
80000424: 3d40006f j 800007f8 <stopSim>
|
||||
80000428: 00777713 andi a4,a4,7
|
||||
8000042c: 12f70c63 beq a4,a5,80000564 <trap+0x1a8>
|
||||
80000430: 3c8000ef jal ra,800007f8 <stopSim>
|
||||
80000434: 343027f3 csrr a5,mtval
|
||||
80000438: 14379073 csrw stval,a5
|
||||
8000043c: 341027f3 csrr a5,mepc
|
||||
80000440: 14179073 csrw sepc,a5
|
||||
80000444: 342027f3 csrr a5,mcause
|
||||
80000448: 14279073 csrw scause,a5
|
||||
8000044c: 105027f3 csrr a5,stvec
|
||||
80000450: 34179073 csrw mepc,a5
|
||||
80000454: 01c12083 lw ra,28(sp)
|
||||
80000458: 01812403 lw s0,24(sp)
|
||||
8000045c: 01412483 lw s1,20(sp)
|
||||
80000460: 01012903 lw s2,16(sp)
|
||||
80000464: 00c12983 lw s3,12(sp)
|
||||
80000468: 02010113 addi sp,sp,32
|
||||
8000046c: 00008067 ret
|
||||
80000470: 0ff7f793 andi a5,a5,255
|
||||
80000474: 00700713 li a4,7
|
||||
80000478: fae79ce3 bne a5,a4,80000430 <trap+0x74>
|
||||
8000047c: 02000793 li a5,32
|
||||
80000480: 1447a073 csrs sip,a5
|
||||
80000484: 08000793 li a5,128
|
||||
80000488: 3047b073 csrc mie,a5
|
||||
8000048c: 01c12083 lw ra,28(sp)
|
||||
80000490: 01812403 lw s0,24(sp)
|
||||
80000494: 01412483 lw s1,20(sp)
|
||||
80000498: 01012903 lw s2,16(sp)
|
||||
8000049c: 00c12983 lw s3,12(sp)
|
||||
800004a0: 02010113 addi sp,sp,32
|
||||
800004a4: 00008067 ret
|
||||
800004a8: 341024f3 csrr s1,mepc
|
||||
800004ac: 300025f3 csrr a1,mstatus
|
||||
800004b0: 34302473 csrr s0,mtval
|
||||
800004b4: 02f00613 li a2,47
|
||||
800004b8: 07f47693 andi a3,s0,127
|
||||
800004bc: 00c45713 srli a4,s0,0xc
|
||||
800004c0: f6c684e3 beq a3,a2,80000428 <trap+0x6c>
|
||||
800004c4: 07300613 li a2,115
|
||||
800004c8: f6c694e3 bne a3,a2,80000430 <trap+0x74>
|
||||
800004cc: 00377713 andi a4,a4,3
|
||||
800004d0: 10f70c63 beq a4,a5,800005e8 <trap+0x22c>
|
||||
800004d4: 00300793 li a5,3
|
||||
800004d8: 10f70863 beq a4,a5,800005e8 <trap+0x22c>
|
||||
800004dc: 00100993 li s3,1
|
||||
800004e0: 03370463 beq a4,s3,80000508 <trap+0x14c>
|
||||
800004e4: 314000ef jal ra,800007f8 <stopSim>
|
||||
800004e8: 343027f3 csrr a5,mtval
|
||||
800004ec: 14379073 csrw stval,a5
|
||||
800004f0: 341027f3 csrr a5,mepc
|
||||
800004f4: 14179073 csrw sepc,a5
|
||||
800004f8: 342027f3 csrr a5,mcause
|
||||
800004fc: 14279073 csrw scause,a5
|
||||
80000500: 105027f3 csrr a5,stvec
|
||||
80000504: 34179073 csrw mepc,a5
|
||||
80000508: 00001737 lui a4,0x1
|
||||
8000050c: 01445793 srli a5,s0,0x14
|
||||
80000510: c0070693 addi a3,a4,-1024 # c00 <__stack_size+0x400>
|
||||
80000514: 0ed7e263 bltu a5,a3,800005f8 <trap+0x23c>
|
||||
80000518: c0270713 addi a4,a4,-1022
|
||||
8000051c: 0cf77063 bgeu a4,a5,800005dc <trap+0x220>
|
||||
80000520: fffff737 lui a4,0xfffff
|
||||
80000524: 38070713 addi a4,a4,896 # fffff380 <_sp+0x7fffe1f8>
|
||||
80000528: 00e787b3 add a5,a5,a4
|
||||
8000052c: 00200713 li a4,2
|
||||
80000530: 0cf76463 bltu a4,a5,800005f8 <trap+0x23c>
|
||||
80000534: 2e4000ef jal ra,80000818 <rdtimeh>
|
||||
80000538: 00050913 mv s2,a0
|
||||
8000053c: 1c099e63 bnez s3,80000718 <trap+0x35c>
|
||||
80000540: 00545413 srli s0,s0,0x5
|
||||
80000544: 800017b7 lui a5,0x80001
|
||||
80000548: 10878793 addi a5,a5,264 # 80001108 <_sp+0xffffff80>
|
||||
8000054c: 07c47413 andi s0,s0,124
|
||||
80000550: 00f40433 add s0,s0,a5
|
||||
80000554: 01242023 sw s2,0(s0)
|
||||
80000558: 00448493 addi s1,s1,4
|
||||
8000055c: 34149073 csrw mepc,s1
|
||||
80000560: ef5ff06f j 80000454 <trap+0x98>
|
||||
80000564: 00d45713 srli a4,s0,0xd
|
||||
80000568: 01245793 srli a5,s0,0x12
|
||||
8000056c: 800016b7 lui a3,0x80001
|
||||
80000570: 10868693 addi a3,a3,264 # 80001108 <_sp+0xffffff80>
|
||||
80000574: 07c77713 andi a4,a4,124
|
||||
80000578: 07c7f793 andi a5,a5,124
|
||||
8000057c: 00d70733 add a4,a4,a3
|
||||
80000580: 00d787b3 add a5,a5,a3
|
||||
80000584: 00072703 lw a4,0(a4)
|
||||
80000588: 0007a603 lw a2,0(a5)
|
||||
8000058c: 00020537 lui a0,0x20
|
||||
80000590: 30052073 csrs mstatus,a0
|
||||
80000594: 00000517 auipc a0,0x0
|
||||
80000598: 01850513 addi a0,a0,24 # 800005ac <trap+0x1f0>
|
||||
8000059c: 30551073 csrw mtvec,a0
|
||||
800005a0: 00100793 li a5,1
|
||||
800005a4: 00072803 lw a6,0(a4)
|
||||
800005a8: 00000793 li a5,0
|
||||
800005ac: 00020537 lui a0,0x20
|
||||
800005b0: 30053073 csrc mstatus,a0
|
||||
800005b4: 18079663 bnez a5,80000740 <trap+0x384>
|
||||
800005b8: 01b45793 srli a5,s0,0x1b
|
||||
800005bc: 01c00513 li a0,28
|
||||
800005c0: e6f568e3 bltu a0,a5,80000430 <trap+0x74>
|
||||
800005c4: 80001537 lui a0,0x80001
|
||||
800005c8: 00279793 slli a5,a5,0x2
|
||||
800005cc: 8e450513 addi a0,a0,-1820 # 800008e4 <_sp+0xfffff75c>
|
||||
800005d0: 00a787b3 add a5,a5,a0
|
||||
800005d4: 0007a783 lw a5,0(a5)
|
||||
800005d8: 00078067 jr a5
|
||||
800005dc: 234000ef jal ra,80000810 <rdtime>
|
||||
800005e0: 00050913 mv s2,a0
|
||||
800005e4: f59ff06f j 8000053c <trap+0x180>
|
||||
800005e8: 00f45993 srli s3,s0,0xf
|
||||
800005ec: 01f9f993 andi s3,s3,31
|
||||
800005f0: 013039b3 snez s3,s3
|
||||
800005f4: f15ff06f j 80000508 <trap+0x14c>
|
||||
800005f8: 200000ef jal ra,800007f8 <stopSim>
|
||||
800005fc: 343027f3 csrr a5,mtval
|
||||
80000600: 14379073 csrw stval,a5
|
||||
80000604: 341027f3 csrr a5,mepc
|
||||
80000608: 14179073 csrw sepc,a5
|
||||
8000060c: 342027f3 csrr a5,mcause
|
||||
80000610: 14279073 csrw scause,a5
|
||||
80000614: 105027f3 csrr a5,stvec
|
||||
80000618: 34179073 csrw mepc,a5
|
||||
8000061c: f21ff06f j 8000053c <trap+0x180>
|
||||
80000620: 01067463 bgeu a2,a6,80000628 <trap+0x26c>
|
||||
80000624: 00080613 mv a2,a6
|
||||
80000628: 00020537 lui a0,0x20
|
||||
8000062c: 30052073 csrs mstatus,a0
|
||||
80000630: 00000517 auipc a0,0x0
|
||||
80000634: 01850513 addi a0,a0,24 # 80000648 <trap+0x28c>
|
||||
80000638: 30551073 csrw mtvec,a0
|
||||
8000063c: 00100793 li a5,1
|
||||
80000640: 00c72023 sw a2,0(a4)
|
||||
80000644: 00000793 li a5,0
|
||||
80000648: 00020537 lui a0,0x20
|
||||
8000064c: 30053073 csrc mstatus,a0
|
||||
80000650: 80000737 lui a4,0x80000
|
||||
80000654: 07c70713 addi a4,a4,124 # 8000007c <_sp+0xffffeef4>
|
||||
80000658: 14079463 bnez a5,800007a0 <trap+0x3e4>
|
||||
8000065c: 00545793 srli a5,s0,0x5
|
||||
80000660: 07c7f793 andi a5,a5,124
|
||||
80000664: 00d786b3 add a3,a5,a3
|
||||
80000668: 0106a023 sw a6,0(a3)
|
||||
8000066c: 00448493 addi s1,s1,4
|
||||
80000670: 34149073 csrw mepc,s1
|
||||
80000674: 30571073 csrw mtvec,a4
|
||||
80000678: dddff06f j 80000454 <trap+0x98>
|
||||
8000067c: 01064633 xor a2,a2,a6
|
||||
80000680: fa9ff06f j 80000628 <trap+0x26c>
|
||||
80000684: fac872e3 bgeu a6,a2,80000628 <trap+0x26c>
|
||||
80000688: 00080613 mv a2,a6
|
||||
8000068c: f9dff06f j 80000628 <trap+0x26c>
|
||||
80000690: f9065ce3 bge a2,a6,80000628 <trap+0x26c>
|
||||
80000694: 00080613 mv a2,a6
|
||||
80000698: f91ff06f j 80000628 <trap+0x26c>
|
||||
8000069c: f8c856e3 bge a6,a2,80000628 <trap+0x26c>
|
||||
800006a0: 00080613 mv a2,a6
|
||||
800006a4: f85ff06f j 80000628 <trap+0x26c>
|
||||
800006a8: 01067633 and a2,a2,a6
|
||||
800006ac: f7dff06f j 80000628 <trap+0x26c>
|
||||
800006b0: 01066633 or a2,a2,a6
|
||||
800006b4: f75ff06f j 80000628 <trap+0x26c>
|
||||
800006b8: 01060633 add a2,a2,a6
|
||||
800006bc: f6dff06f j 80000628 <trap+0x26c>
|
||||
800006c0: fac42583 lw a1,-84(s0)
|
||||
800006c4: 15c000ef jal ra,80000820 <setMachineTimerCmp>
|
||||
800006c8: 08000793 li a5,128
|
||||
800006cc: 3047a073 csrs mie,a5
|
||||
800006d0: 02000793 li a5,32
|
||||
800006d4: 1447b073 csrc sip,a5
|
||||
800006d8: 341027f3 csrr a5,mepc
|
||||
800006dc: 00478793 addi a5,a5,4
|
||||
800006e0: 34179073 csrw mepc,a5
|
||||
800006e4: d71ff06f j 80000454 <trap+0x98>
|
||||
800006e8: 0ff57513 andi a0,a0,255
|
||||
800006ec: 114000ef jal ra,80000800 <putC>
|
||||
800006f0: 341027f3 csrr a5,mepc
|
||||
800006f4: 00478793 addi a5,a5,4
|
||||
800006f8: 34179073 csrw mepc,a5
|
||||
800006fc: d59ff06f j 80000454 <trap+0x98>
|
||||
80000700: 108000ef jal ra,80000808 <getC>
|
||||
80000704: faa42423 sw a0,-88(s0)
|
||||
80000708: 341027f3 csrr a5,mepc
|
||||
8000070c: 00478793 addi a5,a5,4
|
||||
80000710: 34179073 csrw mepc,a5
|
||||
80000714: d41ff06f j 80000454 <trap+0x98>
|
||||
80000718: 0e0000ef jal ra,800007f8 <stopSim>
|
||||
8000071c: 343027f3 csrr a5,mtval
|
||||
80000720: 14379073 csrw stval,a5
|
||||
80000724: 341027f3 csrr a5,mepc
|
||||
80000728: 14179073 csrw sepc,a5
|
||||
8000072c: 342027f3 csrr a5,mcause
|
||||
80000730: 14279073 csrw scause,a5
|
||||
80000734: 105027f3 csrr a5,stvec
|
||||
80000738: 34179073 csrw mepc,a5
|
||||
8000073c: e05ff06f j 80000540 <trap+0x184>
|
||||
80000740: 800007b7 lui a5,0x80000
|
||||
80000744: 07c78793 addi a5,a5,124 # 8000007c <_sp+0xffffeef4>
|
||||
80000748: 30579073 csrw mtvec,a5
|
||||
8000074c: 343027f3 csrr a5,mtval
|
||||
80000750: 14379073 csrw stval,a5
|
||||
80000754: 342027f3 csrr a5,mcause
|
||||
80000758: 14279073 csrw scause,a5
|
||||
8000075c: 14149073 csrw sepc,s1
|
||||
80000760: 105027f3 csrr a5,stvec
|
||||
80000764: 34179073 csrw mepc,a5
|
||||
80000768: 0035d793 srli a5,a1,0x3
|
||||
8000076c: 00459713 slli a4,a1,0x4
|
||||
80000770: 02077713 andi a4,a4,32
|
||||
80000774: 1007f793 andi a5,a5,256
|
||||
80000778: 00e7e7b3 or a5,a5,a4
|
||||
8000077c: ffffe737 lui a4,0xffffe
|
||||
80000780: 6dd70713 addi a4,a4,1757 # ffffe6dd <_sp+0x7fffd555>
|
||||
80000784: 00e5f5b3 and a1,a1,a4
|
||||
80000788: 00001737 lui a4,0x1
|
||||
8000078c: 00b7e7b3 or a5,a5,a1
|
||||
80000790: 88070713 addi a4,a4,-1920 # 880 <__stack_size+0x80>
|
||||
80000794: 00e7e7b3 or a5,a5,a4
|
||||
80000798: 30079073 csrw mstatus,a5
|
||||
8000079c: cb9ff06f j 80000454 <trap+0x98>
|
||||
800007a0: 30571073 csrw mtvec,a4
|
||||
800007a4: 343027f3 csrr a5,mtval
|
||||
800007a8: 14379073 csrw stval,a5
|
||||
800007ac: 342027f3 csrr a5,mcause
|
||||
800007b0: 14279073 csrw scause,a5
|
||||
800007b4: 14149073 csrw sepc,s1
|
||||
800007b8: 105027f3 csrr a5,stvec
|
||||
800007bc: 34179073 csrw mepc,a5
|
||||
800007c0: 0035d793 srli a5,a1,0x3
|
||||
800007c4: 00459713 slli a4,a1,0x4
|
||||
800007c8: 02077713 andi a4,a4,32
|
||||
800007cc: 1007f793 andi a5,a5,256
|
||||
800007d0: 00e7e7b3 or a5,a5,a4
|
||||
800007d4: ffffe737 lui a4,0xffffe
|
||||
800007d8: 6dd70713 addi a4,a4,1757 # ffffe6dd <_sp+0x7fffd555>
|
||||
800007dc: 00e5f5b3 and a1,a1,a4
|
||||
800007e0: 00b7e5b3 or a1,a5,a1
|
||||
800007e4: 000017b7 lui a5,0x1
|
||||
800007e8: 88078793 addi a5,a5,-1920 # 880 <__stack_size+0x80>
|
||||
800007ec: 00f5e7b3 or a5,a1,a5
|
||||
800007f0: 30079073 csrw mstatus,a5
|
||||
800007f4: c61ff06f j 80000454 <trap+0x98>
|
||||
|
||||
800007f8 <stopSim>:
|
||||
800007f8: fe002e23 sw zero,-4(zero) # fffffffc <_sp+0x7fffee74>
|
||||
800007fc: 0000006f j 800007fc <stopSim+0x4>
|
||||
|
||||
80000800 <putC>:
|
||||
80000800: fea02c23 sw a0,-8(zero) # fffffff8 <_sp+0x7fffee70>
|
||||
80000804: 00008067 ret
|
||||
|
||||
80000808 <getC>:
|
||||
80000808: ff802503 lw a0,-8(zero) # fffffff8 <_sp+0x7fffee70>
|
||||
8000080c: 00008067 ret
|
||||
|
||||
80000810 <rdtime>:
|
||||
80000810: fe002503 lw a0,-32(zero) # ffffffe0 <_sp+0x7fffee58>
|
||||
80000814: 00008067 ret
|
||||
|
||||
80000818 <rdtimeh>:
|
||||
80000818: fe402503 lw a0,-28(zero) # ffffffe4 <_sp+0x7fffee5c>
|
||||
8000081c: 00008067 ret
|
||||
|
||||
80000820 <setMachineTimerCmp>:
|
||||
80000820: fec00793 li a5,-20
|
||||
80000824: fff00713 li a4,-1
|
||||
80000828: 00e7a023 sw a4,0(a5)
|
||||
8000082c: fea02423 sw a0,-24(zero) # ffffffe8 <_sp+0x7fffee60>
|
||||
80000830: 00b7a023 sw a1,0(a5)
|
||||
80000834: 00008067 ret
|
||||
|
||||
80000838 <halInit>:
|
||||
80000838: 00008067 ret
|
||||
|
||||
8000083c <__libc_init_array>:
|
||||
8000083c: ff010113 addi sp,sp,-16
|
||||
80000840: 00000797 auipc a5,0x0
|
||||
80000844: 0a478793 addi a5,a5,164 # 800008e4 <__init_array_end>
|
||||
80000848: 00812423 sw s0,8(sp)
|
||||
8000084c: 00000417 auipc s0,0x0
|
||||
80000850: 09840413 addi s0,s0,152 # 800008e4 <__init_array_end>
|
||||
80000854: 40f40433 sub s0,s0,a5
|
||||
80000858: 00912223 sw s1,4(sp)
|
||||
8000085c: 01212023 sw s2,0(sp)
|
||||
80000860: 00112623 sw ra,12(sp)
|
||||
80000864: 40245413 srai s0,s0,0x2
|
||||
80000868: 00000493 li s1,0
|
||||
8000086c: 00078913 mv s2,a5
|
||||
80000870: 04849263 bne s1,s0,800008b4 <__libc_init_array+0x78>
|
||||
80000874: 805ff0ef jal ra,80000078 <_init>
|
||||
80000878: 00000797 auipc a5,0x0
|
||||
8000087c: 06c78793 addi a5,a5,108 # 800008e4 <__init_array_end>
|
||||
80000880: 00000417 auipc s0,0x0
|
||||
80000884: 06440413 addi s0,s0,100 # 800008e4 <__init_array_end>
|
||||
80000888: 40f40433 sub s0,s0,a5
|
||||
8000088c: 40245413 srai s0,s0,0x2
|
||||
80000890: 00000493 li s1,0
|
||||
80000894: 00078913 mv s2,a5
|
||||
80000898: 02849a63 bne s1,s0,800008cc <__libc_init_array+0x90>
|
||||
8000089c: 00c12083 lw ra,12(sp)
|
||||
800008a0: 00812403 lw s0,8(sp)
|
||||
800008a4: 00412483 lw s1,4(sp)
|
||||
800008a8: 00012903 lw s2,0(sp)
|
||||
800008ac: 01010113 addi sp,sp,16
|
||||
800008b0: 00008067 ret
|
||||
800008b4: 00249793 slli a5,s1,0x2
|
||||
800008b8: 00f907b3 add a5,s2,a5
|
||||
800008bc: 0007a783 lw a5,0(a5)
|
||||
800008c0: 00148493 addi s1,s1,1
|
||||
800008c4: 000780e7 jalr a5
|
||||
800008c8: fa9ff06f j 80000870 <__libc_init_array+0x34>
|
||||
800008cc: 00249793 slli a5,s1,0x2
|
||||
800008d0: 00f907b3 add a5,s2,a5
|
||||
800008d4: 0007a783 lw a5,0(a5)
|
||||
800008d8: 00148493 addi s1,s1,1
|
||||
800008dc: 000780e7 jalr a5
|
||||
800008e0: fb9ff06f j 80000898 <__libc_init_array+0x5c>
|
BIN
src/main/c/emulator/build/emulator.bin
Executable file
BIN
src/main/c/emulator/build/emulator.bin
Executable file
Binary file not shown.
157
src/main/c/emulator/build/emulator.hex
Normal file
157
src/main/c/emulator/build/emulator.hex
Normal file
|
@ -0,0 +1,157 @@
|
|||
:0200000480007A
|
||||
:100000001711000013018118171500001305C58D85
|
||||
:10001000971500009385458D171600001306069767
|
||||
:1000200063FCC5008322050023A05500130545008D
|
||||
:1000300093854500E3E8C5FE1715000013050595F7
|
||||
:1000400097150000938585946378B50023200500FB
|
||||
:1000500013054500E36CB5FEEF00407EEF0080170E
|
||||
:10006000970000009380400113050000B70500C30E
|
||||
:10007000730020306F0000006780000073110134AE
|
||||
:10008000232211002326310023284100232A510076
|
||||
:10009000232C6100232E7100232081022322910250
|
||||
:1000A0002324A1022326B1022328C102232AD1023C
|
||||
:1000B000232CE102232EF102232001052322110526
|
||||
:1000C000232421052326310523284105232A510510
|
||||
:1000D000232C6105232E71052320810723229107FC
|
||||
:1000E0002324A1072326B1072328C107232AD107E8
|
||||
:1000F000232CE107232EF107EF00402C8320410041
|
||||
:100100008321C100032201018322410103238101D4
|
||||
:100110008323C101032401028324410203258102B8
|
||||
:100120008325C1020326010383264103032781039C
|
||||
:100130008327C10303280104832841040329810480
|
||||
:100140008329C104032A0105832A4105032B810564
|
||||
:10015000832BC105032C0106832C4106032D810648
|
||||
:10016000832DC106032E0107832E4107032F81072C
|
||||
:0C017000832FC10773110134730020308D
|
||||
:10017C00130101FF23248100232611001304050021
|
||||
:10018C0003450500630A050013041400EF008066A4
|
||||
:10019C0003450400E31A05FE8320C10003248100FB
|
||||
:1001AC0013010101678000009307F0011307F0FFB2
|
||||
:1001BC009702000093824201739052307310073BF8
|
||||
:1001CC007390073A67800000130101FF232611008A
|
||||
:1001DC00232481009307F0011307F0FF970200001E
|
||||
:1001EC0093824201739052307310073B7390073A1D
|
||||
:1001FC0037140080EF008063130484951305A0026C
|
||||
:10020C0013041400EF00005F03450400E31A05FE1D
|
||||
:10021C00B70700809387C70773905730B7170080D4
|
||||
:10022C009387871073900734B7170000938707885C
|
||||
:10023C007390073073504030B70700C07390173479
|
||||
:10024C00B7B70000938707107390273093072022CD
|
||||
:10025C0073903730735030143714008013040497A4
|
||||
:10026C001305A00213041400EF00C058034504004A
|
||||
:10027C00E31A05FE8320C100032481001301010150
|
||||
:10028C0067800000B717008093878710131525002F
|
||||
:10029C003305F5000325050067800000B7170080C3
|
||||
:1002AC0013152500938787103305F5002320B5001F
|
||||
:1002BC0067800000130101FF23261100EF0000539B
|
||||
:1002CC00F327303473903714F327103473901714CA
|
||||
:1002DC00F327203473902714F3275010739017349E
|
||||
:1002EC008320C1001301010167800000B707008063
|
||||
:1002FC009387C70773905730F327303473903714B4
|
||||
:10030C00F32720347390271473101514F32750100F
|
||||
:10031C007390173493D73500139745001377070262
|
||||
:10032C0093F70710B3E7E70037E7FFFF1307D76D25
|
||||
:10033C00B3F5E500B3E7B700B71500009385058862
|
||||
:10034C00B3E7B700739007306780000037070200EF
|
||||
:10035C0073200730170700001307870173105730FD
|
||||
:10036C009306100083270500930600003707020050
|
||||
:10037C00733007301385060023A0F500678000005A
|
||||
:10038C003707020073200730170700001307870197
|
||||
:10039C0073105730930710002320B500930700000B
|
||||
:1003AC0037070200733007301385070067800000A1
|
||||
:1003BC00130101FE232E1100232C8100232A91000E
|
||||
:1003CC002328210123263101F327203463CC07088D
|
||||
:1003DC00130720006384E70C930690006394D70402
|
||||
:1003EC003714008013048418832744FC93061000F0
|
||||
:1003FC00032584FA6384D72E638EE72E638C072A39
|
||||
:10040C00032481018320C1018324410103290101BB
|
||||
:10041C008329C100130101026F00403D137777005F
|
||||
:10042C00630CF712EF00803CF327303473903714D1
|
||||
:10043C00F327103473901714F32720347390271478
|
||||
:10044C00F3275010739017348320C10103248101CA
|
||||
:10045C0083244101032901018329C10013010102F5
|
||||
:10046C006780000093F7F70F13077000E39CE7FA1F
|
||||
:10047C009307000273A047149307000873B047302A
|
||||
:10048C008320C1010324810183244101032901013B
|
||||
:10049C008329C1001301010267800000F32410348A
|
||||
:1004AC00F3250030732430341306F0029376F407EE
|
||||
:1004BC001357C400E384C6F613063007E394C6F65C
|
||||
:1004CC0013773700630CF710930730006308F710AD
|
||||
:1004DC009309100063043703EF004031F3273034E5
|
||||
:1004EC0073903714F327103473901714F3272034B8
|
||||
:1004FC0073902714F327501073901734371700009C
|
||||
:10050C0093574401930607C063E2D70E130727C025
|
||||
:10051C006370F70C37F7FFFF13070738B387E70053
|
||||
:10052C00130720006364F70CEF00402E130905003D
|
||||
:10053C00639E091C13545400B717008093878710CF
|
||||
:10054C001374C4073304F40023202401938444005F
|
||||
:10055C00739014346FF05FEF1357D400935724014A
|
||||
:10056C00B7160080938686101377C70793F7C707D3
|
||||
:10057C003307D700B387D7000327070003A607006C
|
||||
:10058C00370502007320053017050000130585019F
|
||||
:10059C0073105530930710000328070093070000D1
|
||||
:1005AC003705020073300530639607189357B40172
|
||||
:1005BC001305C001E368F5E6371500809397270013
|
||||
:1005CC001305458EB387A70083A707006780070034
|
||||
:1005DC00EF004023130905006FF09FF59359F400C9
|
||||
:1005EC0093F9F901B33930016FF05FF1EF0000209E
|
||||
:1005FC00F327303473903714F32710347390171497
|
||||
:10060C00F327203473902714F3275010739017346A
|
||||
:10061C006FF01FF263740601130608003705020021
|
||||
:10062C007320053017050000130585017310553034
|
||||
:10063C00930710002320C700930700003705020022
|
||||
:10064C0073300530370700801307C707639407140E
|
||||
:10065C009357540093F7C707B386D70023A006011E
|
||||
:10066C009384440073901434731057306FF0DFDDB3
|
||||
:10067C00334606016FF09FFAE372C8FA13060800BE
|
||||
:10068C006FF0DFF9E35C06F9130608006FF01FF951
|
||||
:10069C00E356C8F8130608006FF05FF833760601CE
|
||||
:1006AC006FF0DFF7336606016FF05FF73306060174
|
||||
:1006BC006FF0DFF68325C4FAEF00C015930700082E
|
||||
:1006CC0073A047309307000273B04714F32710341C
|
||||
:1006DC0093874700739017346FF01FD71375F50F7E
|
||||
:1006EC00EF004011F32710349387470073901734B1
|
||||
:1006FC006FF09FD5EF0080102324A4FAF327103459
|
||||
:10070C0093874700739017346FF01FD4EF00000EDF
|
||||
:10071C00F327303473903714F32710347390171475
|
||||
:10072C00F327203473902714F32750107390173449
|
||||
:10073C006FF05FE0B70700809387C707739057305F
|
||||
:10074C00F327303473903714F32720347390271425
|
||||
:10075C0073901414F32750107390173493D73500FB
|
||||
:10076C00139745001377070293F70710B3E7E700D9
|
||||
:10077C0037E7FFFF1307D76DB3F5E5003717000018
|
||||
:10078C00B3E7B70013070788B3E7E70073900730A8
|
||||
:10079C006FF09FCB73105730F327303473903714AE
|
||||
:1007AC00F32720347390271473901414F3275010EC
|
||||
:1007BC007390173493D735001397450013770702BE
|
||||
:1007CC0093F70710B3E7E70037E7FFFF1307D76D81
|
||||
:1007DC00B3F5E500B3E5B700B717000093870788BA
|
||||
:1007EC00B3E7F500739007306FF01FC6232E00FEA1
|
||||
:1007FC006F000000232CA0FE67800000032580FF03
|
||||
:10080C0067800000032500FE67800000032540FE82
|
||||
:10081C00678000009307C0FE1307F0FF23A0E700DA
|
||||
:10082C002324A0FE23A0B70067800000678000008F
|
||||
:10083C00130101FF970700009387470A23248100C7
|
||||
:10084C0017040000130484093304F440232291009C
|
||||
:10085C00232021012326110013542440930400006B
|
||||
:10086C001389070063928404EFF05F809707000000
|
||||
:10087C009387C70617040000130444063304F4409E
|
||||
:10088C00135424409304000013890700639A8402D4
|
||||
:10089C008320C1000324810083244100032901002B
|
||||
:1008AC00130101016780000093972400B307F9003E
|
||||
:1008BC0083A7070093841400E78007006FF09FFA6A
|
||||
:1008CC0093972400B307F90083A7070093841400BF
|
||||
:0808DC00E78007006FF09FFBAD
|
||||
:1008E400B8060080280600803004008030040080B0
|
||||
:1008F4007C060080300400803004008030040080D6
|
||||
:10090400B006008030040080300400803004008091
|
||||
:10091400A806008030040080300400803004008089
|
||||
:100924009C06008030040080300400803004008085
|
||||
:100934009006008030040080300400803004008081
|
||||
:10094400840600803004008030040080300400807D
|
||||
:10095400200600802A2A2A20566578526973637615
|
||||
:100964002042494F53202A2A2A0A00002A2A2A20F0
|
||||
:1009740053757065727669736F72202A2A2A0A0089
|
||||
:04098400000000006F
|
||||
:040000058000000077
|
||||
:00000001FF
|
17
src/main/c/emulator/makefile
Executable file
17
src/main/c/emulator/makefile
Executable file
|
@ -0,0 +1,17 @@
|
|||
PROJ_NAME=emulator
|
||||
DEBUG=no
|
||||
MULDIV=no
|
||||
COMPRESSED=no
|
||||
STANDALONE = ..
|
||||
|
||||
|
||||
SRCS = $(wildcard src/*.c) \
|
||||
$(wildcard src/*.cpp) \
|
||||
$(wildcard src/*.S)
|
||||
|
||||
|
||||
LDSCRIPT = ${STANDALONE}/common/ram.ld
|
||||
|
||||
include ${STANDALONE}/common/riscv64-unknown-elf.mk
|
||||
include ${STANDALONE}/common/standalone.mk
|
||||
|
9
src/main/c/emulator/src/config.h
Normal file
9
src/main/c/emulator/src/config.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
//#define QEMU
|
||||
#define SIM
|
||||
#define OS_CALL 0xC0000000
|
||||
#define DTB 0xC3000000
|
||||
|
||||
#endif
|
148
src/main/c/emulator/src/hal.c
Normal file
148
src/main/c/emulator/src/hal.c
Normal file
|
@ -0,0 +1,148 @@
|
|||
#include "hal.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef SIM
|
||||
void stopSim(){
|
||||
*((volatile uint32_t*) 0xFFFFFFFC) = 0;
|
||||
while(1);
|
||||
}
|
||||
|
||||
void putC(char c){
|
||||
*((volatile uint32_t*) 0xFFFFFFF8) = c;
|
||||
}
|
||||
|
||||
int32_t getC(){
|
||||
return *((volatile int32_t*) 0xFFFFFFF8);
|
||||
}
|
||||
|
||||
uint32_t rdtime(){
|
||||
return *((volatile uint32_t*) 0xFFFFFFE0);
|
||||
}
|
||||
|
||||
uint32_t rdtimeh(){
|
||||
return *((volatile uint32_t*) 0xFFFFFFE4);
|
||||
}
|
||||
|
||||
void setMachineTimerCmp(uint32_t low, uint32_t high){
|
||||
volatile uint32_t* base = (volatile uint32_t*) 0xFFFFFFE8;
|
||||
base[1] = 0xffffffff;
|
||||
base[0] = low;
|
||||
base[1] = high;
|
||||
}
|
||||
|
||||
|
||||
void halInit(){
|
||||
// putC('*');
|
||||
// putC('*');
|
||||
// putC('*');
|
||||
// while(1){
|
||||
// int32_t c = getC();
|
||||
// if(c > 0) putC(c);
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef QEMU
|
||||
#define VIRT_CLINT 0x2000000
|
||||
#define SIFIVE_TIMECMP_BASE (VIRT_CLINT + 0x4000)
|
||||
#define SIFIVE_TIME_BASE (VIRT_CLINT + 0xBFF8)
|
||||
#define NS16550A_UART0_CTRL_ADDR 0x10000000
|
||||
#define UART0_CLOCK_FREQ 32000000
|
||||
#define UART0_BAUD_RATE 115200
|
||||
enum {
|
||||
UART_RBR = 0x00, /* Receive Buffer Register */
|
||||
UART_THR = 0x00, /* Transmit Hold Register */
|
||||
UART_IER = 0x01, /* Interrupt Enable Register */
|
||||
UART_DLL = 0x00, /* Divisor LSB (LCR_DLAB) */
|
||||
UART_DLM = 0x01, /* Divisor MSB (LCR_DLAB) */
|
||||
UART_FCR = 0x02, /* FIFO Control Register */
|
||||
UART_LCR = 0x03, /* Line Control Register */
|
||||
UART_MCR = 0x04, /* Modem Control Register */
|
||||
UART_LSR = 0x05, /* Line Status Register */
|
||||
UART_MSR = 0x06, /* Modem Status Register */
|
||||
UART_SCR = 0x07, /* Scratch Register */
|
||||
|
||||
UART_LCR_DLAB = 0x80, /* Divisor Latch Bit */
|
||||
UART_LCR_8BIT = 0x03, /* 8-bit */
|
||||
UART_LCR_PODD = 0x08, /* Parity Odd */
|
||||
|
||||
UART_LSR_DA = 0x01, /* Data Available */
|
||||
UART_LSR_OE = 0x02, /* Overrun Error */
|
||||
UART_LSR_PE = 0x04, /* Parity Error */
|
||||
UART_LSR_FE = 0x08, /* Framing Error */
|
||||
UART_LSR_BI = 0x10, /* Break indicator */
|
||||
UART_LSR_RE = 0x20, /* THR is empty */
|
||||
UART_LSR_RI = 0x40, /* THR is empty and line is idle */
|
||||
UART_LSR_EF = 0x80, /* Erroneous data in FIFO */
|
||||
};
|
||||
|
||||
static volatile uint8_t *uart;
|
||||
|
||||
static void ns16550a_init()
|
||||
{
|
||||
uart = (uint8_t *)(void *)(NS16550A_UART0_CTRL_ADDR);
|
||||
uint32_t uart_freq = (UART0_CLOCK_FREQ);
|
||||
uint32_t baud_rate = (UART0_BAUD_RATE);
|
||||
uint32_t divisor = uart_freq / (16 * baud_rate);
|
||||
uart[UART_LCR] = UART_LCR_DLAB;
|
||||
uart[UART_DLL] = divisor & 0xff;
|
||||
uart[UART_DLM] = (divisor >> 8) & 0xff;
|
||||
uart[UART_LCR] = UART_LCR_PODD | UART_LCR_8BIT;
|
||||
}
|
||||
|
||||
//static int ns16550a_getchar()
|
||||
//{
|
||||
// if (uart[UART_LSR] & UART_LSR_DA) {
|
||||
// return uart[UART_RBR];
|
||||
// } else {
|
||||
// return -1;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//static int ns16550a_putchar(int ch)
|
||||
//{
|
||||
// while ((uart[UART_LSR] & UART_LSR_RI) == 0);
|
||||
// return uart[UART_THR] = ch & 0xff;
|
||||
//}
|
||||
|
||||
void stopSim(){
|
||||
while(1);
|
||||
}
|
||||
|
||||
void putC(char ch){
|
||||
while ((uart[UART_LSR] & UART_LSR_RI) == 0);
|
||||
uart[UART_THR] = ch & 0xff;
|
||||
}
|
||||
|
||||
int32_t getC(){
|
||||
if (uart[UART_LSR] & UART_LSR_DA) {
|
||||
return uart[UART_RBR];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t rdtime(){
|
||||
return *((volatile uint32_t*) SIFIVE_TIME_BASE);
|
||||
}
|
||||
|
||||
uint32_t rdtimeh(){
|
||||
return *((volatile uint32_t*) (SIFIVE_TIME_BASE + 4));
|
||||
}
|
||||
|
||||
void setMachineTimerCmp(uint32_t low, uint32_t high){
|
||||
volatile uint32_t* base = (volatile uint32_t*) SIFIVE_TIMECMP_BASE;
|
||||
base[1] = 0xffffffff;
|
||||
base[0] = low;
|
||||
base[1] = high;
|
||||
}
|
||||
|
||||
void halInit(){
|
||||
ns16550a_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
25
src/main/c/emulator/src/hal.h
Normal file
25
src/main/c/emulator/src/hal.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
#ifndef HAL_H
|
||||
#define HAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SBI_SET_TIMER 0
|
||||
#define SBI_CONSOLE_PUTCHAR 1
|
||||
#define SBI_CONSOLE_GETCHAR 2
|
||||
#define SBI_CLEAR_IPI 3
|
||||
#define SBI_SEND_IPI 4
|
||||
#define SBI_REMOTE_FENCE_I 5
|
||||
#define SBI_REMOTE_SFENCE_VMA 6
|
||||
#define SBI_REMOTE_SFENCE_VMA_ASID 7
|
||||
#define SBI_SHUTDOWN 8
|
||||
|
||||
void halInit();
|
||||
void stopSim();
|
||||
void putC(char c);
|
||||
int32_t getC();
|
||||
uint32_t rdtime();
|
||||
uint32_t rdtimeh();
|
||||
void setMachineTimerCmp(uint32_t low, uint32_t high);
|
||||
|
||||
#endif
|
288
src/main/c/emulator/src/main.c
Executable file
288
src/main/c/emulator/src/main.c
Executable file
|
@ -0,0 +1,288 @@
|
|||
#include <stdint.h>
|
||||
#include "riscv.h"
|
||||
#include "config.h"
|
||||
#include "hal.h"
|
||||
|
||||
extern const uint32_t _sp;
|
||||
extern void trapEntry();
|
||||
extern void emulationTrap();
|
||||
|
||||
void putString(char* s){
|
||||
while(*s){
|
||||
putC(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
//Affect mtvec
|
||||
void setup_pmp(void)
|
||||
{
|
||||
// Set up a PMP to permit access to all of memory.
|
||||
// Ignore the illegal-instruction trap if PMPs aren't supported.
|
||||
uintptr_t pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X;
|
||||
asm volatile ("la t0, 1f\n\t"
|
||||
"csrw mtvec, t0\n\t"
|
||||
"csrw pmpaddr0, %1\n\t"
|
||||
"csrw pmpcfg0, %0\n\t"
|
||||
".align 2\n\t"
|
||||
"1:"
|
||||
: : "r" (pmpc), "r" (-1UL) : "t0");
|
||||
}
|
||||
|
||||
void init() {
|
||||
setup_pmp();
|
||||
halInit();
|
||||
putString("*** VexRiscv BIOS ***\n");
|
||||
uint32_t sp = (uint32_t) (&_sp);
|
||||
csr_write(mtvec, trapEntry);
|
||||
csr_write(mscratch, sp -32*4);
|
||||
csr_write(mstatus, 0x0800 | MSTATUS_MPIE);
|
||||
csr_write(mie, 0);
|
||||
csr_write(mepc, OS_CALL);
|
||||
//In future it would probably need to manage missaligned stuff, now it will stop the simulation
|
||||
csr_write(medeleg, MEDELEG_INSTRUCTION_PAGE_FAULT | MEDELEG_LOAD_PAGE_FAULT | MEDELEG_STORE_PAGE_FAULT | MEDELEG_USER_ENVIRONNEMENT_CALL);
|
||||
csr_write(mideleg, MIDELEG_SUPERVISOR_TIMER | MIDELEG_SUPERVISOR_EXTERNAL | MIDELEG_SUPERVISOR_SOFTWARE);
|
||||
csr_write(sbadaddr, 0); //Used to avoid simulation missmatch
|
||||
|
||||
putString("*** Supervisor ***\n");
|
||||
}
|
||||
|
||||
int readRegister(uint32_t id){
|
||||
unsigned int sp = (unsigned int) (&_sp);
|
||||
return ((int*) sp)[id-32];
|
||||
}
|
||||
void writeRegister(uint32_t id, int value){
|
||||
uint32_t sp = (uint32_t) (&_sp);
|
||||
((uint32_t*) sp)[id-32] = value;
|
||||
}
|
||||
|
||||
|
||||
//Currently, this should not happen, unless kernel things are going wrong
|
||||
void redirectTrap(){
|
||||
stopSim();
|
||||
csr_write(sbadaddr, csr_read(mbadaddr));
|
||||
csr_write(sepc, csr_read(mepc));
|
||||
csr_write(scause, csr_read(mcause));
|
||||
csr_write(mepc, csr_read(stvec));
|
||||
}
|
||||
|
||||
void emulationTrapToSupervisorTrap(uint32_t sepc, uint32_t mstatus){
|
||||
csr_write(mtvec, trapEntry);
|
||||
csr_write(sbadaddr, csr_read(mbadaddr));
|
||||
csr_write(scause, csr_read(mcause));
|
||||
csr_write(sepc, sepc);
|
||||
csr_write(mepc, csr_read(stvec));
|
||||
csr_write(mstatus,
|
||||
(mstatus & ~(MSTATUS_SPP | MSTATUS_MPP | MSTATUS_SIE | MSTATUS_SPIE))
|
||||
| ((mstatus >> 3) & MSTATUS_SPP)
|
||||
| (0x0800 | MSTATUS_MPIE)
|
||||
| ((mstatus & MSTATUS_SIE) << 4)
|
||||
);
|
||||
}
|
||||
|
||||
#define max(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
|
||||
|
||||
#define min(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
|
||||
|
||||
|
||||
//Will modify MTVEC
|
||||
int32_t readWord(uint32_t address, int32_t *data){
|
||||
int32_t result, tmp;
|
||||
int32_t failed;
|
||||
__asm__ __volatile__ (
|
||||
" li %[tmp], 0x00020000\n"
|
||||
" csrs mstatus, %[tmp]\n"
|
||||
" la %[tmp], 1f\n"
|
||||
" csrw mtvec, %[tmp]\n"
|
||||
" li %[failed], 1\n"
|
||||
" lw %[result], 0(%[address])\n"
|
||||
" li %[failed], 0\n"
|
||||
"1:\n"
|
||||
" li %[tmp], 0x00020000\n"
|
||||
" csrc mstatus, %[tmp]\n"
|
||||
: [result]"=&r" (result), [failed]"=&r" (failed), [tmp]"=&r" (tmp)
|
||||
: [address]"r" (address)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
*data = result;
|
||||
return failed;
|
||||
}
|
||||
|
||||
//Will modify MTVEC
|
||||
int32_t writeWord(uint32_t address, int32_t data){
|
||||
int32_t result, tmp;
|
||||
int32_t failed;
|
||||
__asm__ __volatile__ (
|
||||
" li %[tmp], 0x00020000\n"
|
||||
" csrs mstatus, %[tmp]\n"
|
||||
" la %[tmp], 1f\n"
|
||||
" csrw mtvec, %[tmp]\n"
|
||||
" li %[failed], 1\n"
|
||||
" sw %[data], 0(%[address])\n"
|
||||
" li %[failed], 0\n"
|
||||
"1:\n"
|
||||
" li %[tmp], 0x00020000\n"
|
||||
" csrc mstatus, %[tmp]\n"
|
||||
: [failed]"=&r" (failed), [tmp]"=&r" (tmp)
|
||||
: [address]"r" (address), [data]"r" (data)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trap(){
|
||||
int32_t cause = csr_read(mcause);
|
||||
if(cause < 0){ //interrupt
|
||||
switch(cause & 0xFF){
|
||||
case CAUSE_MACHINE_TIMER:{
|
||||
csr_set(sip, MIP_STIP);
|
||||
csr_clear(mie, MIE_MTIE);
|
||||
}break;
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
} else { //exception
|
||||
switch(cause){
|
||||
case CAUSE_ILLEGAL_INSTRUCTION:{
|
||||
uint32_t mepc = csr_read(mepc);
|
||||
uint32_t mstatus = csr_read(mstatus);
|
||||
#ifdef SIM
|
||||
uint32_t instruction = csr_read(mbadaddr);
|
||||
#endif
|
||||
#ifdef QEMU
|
||||
uint32_t instruction = 0;
|
||||
uint32_t i;
|
||||
if (mepc & 2) {
|
||||
readWord(mepc - 2, &i);
|
||||
i >>= 16;
|
||||
if (i & 3 == 3) {
|
||||
uint32_t u32Buf;
|
||||
readWord(mepc+2, &u32Buf);
|
||||
i |= u32Buf << 16;
|
||||
}
|
||||
} else {
|
||||
readWord(mepc, &i);
|
||||
}
|
||||
instruction = i;
|
||||
csr_write(mtvec, trapEntry); //Restore mtvec
|
||||
#endif
|
||||
|
||||
uint32_t opcode = instruction & 0x7F;
|
||||
uint32_t funct3 = (instruction >> 12) & 0x7;
|
||||
switch(opcode){
|
||||
case 0x2F: //Atomic
|
||||
switch(funct3){
|
||||
case 0x2:{
|
||||
uint32_t sel = instruction >> 27;
|
||||
uint32_t addr = readRegister((instruction >> 15) & 0x1F);
|
||||
int32_t src = readRegister((instruction >> 20) & 0x1F);
|
||||
uint32_t rd = (instruction >> 7) & 0x1F;
|
||||
int32_t readValue;
|
||||
if(readWord(addr, &readValue)){
|
||||
emulationTrapToSupervisorTrap(mepc, mstatus);
|
||||
return;
|
||||
}
|
||||
int writeValue;
|
||||
switch(sel){
|
||||
case 0x0: writeValue = src + readValue; break;
|
||||
case 0x1: writeValue = src; break;
|
||||
//LR SC done in hardware (cheap), and require to keep track of context switches
|
||||
// case 0x2:{ //LR
|
||||
// }break;
|
||||
// case 0x3:{ //SC
|
||||
// }break;
|
||||
case 0x4: writeValue = src ^ readValue; break;
|
||||
case 0xC: writeValue = src & readValue; break;
|
||||
case 0x8: writeValue = src | readValue; break;
|
||||
case 0x10: writeValue = min(src, readValue); break;
|
||||
case 0x14: writeValue = max(src, readValue); break;
|
||||
case 0x18: writeValue = min((unsigned int)src, (unsigned int)readValue); break;
|
||||
case 0x1C: writeValue = max((unsigned int)src, (unsigned int)readValue); break;
|
||||
default: redirectTrap(); return; break;
|
||||
}
|
||||
if(writeWord(addr, writeValue)){
|
||||
emulationTrapToSupervisorTrap(mepc, mstatus);
|
||||
return;
|
||||
}
|
||||
writeRegister(rd, readValue);
|
||||
csr_write(mepc, mepc + 4);
|
||||
csr_write(mtvec, trapEntry); //Restore mtvec
|
||||
}break;
|
||||
default: redirectTrap(); break;
|
||||
} break;
|
||||
case 0x73:{
|
||||
//CSR
|
||||
uint32_t input = (instruction & 0x4000) ? ((instruction >> 15) & 0x1F) : readRegister((instruction >> 15) & 0x1F);;
|
||||
uint32_t clear, set;
|
||||
uint32_t write;
|
||||
switch (funct3 & 0x3) {
|
||||
case 0: redirectTrap(); break;
|
||||
case 1: clear = ~0; set = input; write = 1; break;
|
||||
case 2: clear = 0; set = input; write = ((instruction >> 15) & 0x1F) != 0; break;
|
||||
case 3: clear = input; set = 0; write = ((instruction >> 15) & 0x1F) != 0; break;
|
||||
}
|
||||
uint32_t csrAddress = instruction >> 20;
|
||||
uint32_t old;
|
||||
switch(csrAddress){
|
||||
case RDCYCLE :
|
||||
case RDINSTRET:
|
||||
case RDTIME : old = rdtime(); break;
|
||||
case RDCYCLEH :
|
||||
case RDINSTRETH:
|
||||
case RDTIMEH : old = rdtimeh(); break;
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
if(write) {
|
||||
uint32_t newValue = (old & ~clear) | set;
|
||||
switch(csrAddress){
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
}
|
||||
|
||||
writeRegister((instruction >> 7) & 0x1F, old);
|
||||
csr_write(mepc, mepc + 4);
|
||||
|
||||
}break;
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
}break;
|
||||
case CAUSE_SCALL:{
|
||||
uint32_t which = readRegister(17);
|
||||
uint32_t a0 = readRegister(10);
|
||||
uint32_t a1 = readRegister(11);
|
||||
uint32_t a2 = readRegister(12);
|
||||
switch(which){
|
||||
case SBI_CONSOLE_PUTCHAR:{
|
||||
putC(a0);
|
||||
csr_write(mepc, csr_read(mepc) + 4);
|
||||
}break;
|
||||
case SBI_CONSOLE_GETCHAR:{
|
||||
writeRegister(10, getC()); //no char
|
||||
csr_write(mepc, csr_read(mepc) + 4);
|
||||
}break;
|
||||
case SBI_SET_TIMER:{
|
||||
setMachineTimerCmp(a0, a1);
|
||||
csr_set(mie, MIE_MTIE);
|
||||
csr_clear(sip, MIP_STIP);
|
||||
csr_write(mepc, csr_read(mepc) + 4);
|
||||
}break;
|
||||
default: stopSim(); break;
|
||||
}
|
||||
}break;
|
||||
default: redirectTrap(); break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
133
src/main/c/emulator/src/riscv.h
Normal file
133
src/main/c/emulator/src/riscv.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
#ifndef RISCV_H
|
||||
#define RISCV_H
|
||||
|
||||
#define CAUSE_ILLEGAL_INSTRUCTION 2
|
||||
#define CAUSE_MACHINE_TIMER 7
|
||||
#define CAUSE_SCALL 9
|
||||
|
||||
#define MEDELEG_INSTRUCTION_PAGE_FAULT (1 << 12)
|
||||
#define MEDELEG_LOAD_PAGE_FAULT (1 << 13)
|
||||
#define MEDELEG_STORE_PAGE_FAULT (1 << 15)
|
||||
#define MEDELEG_USER_ENVIRONNEMENT_CALL (1 << 8)
|
||||
#define MIDELEG_SUPERVISOR_SOFTWARE (1 << 1)
|
||||
#define MIDELEG_SUPERVISOR_TIMER (1 << 5)
|
||||
#define MIDELEG_SUPERVISOR_EXTERNAL (1 << 9)
|
||||
|
||||
#define MIE_MTIE (1 << 7)
|
||||
#define MIP_STIP (1 << 5)
|
||||
|
||||
#define MSTATUS_UIE 0x00000001
|
||||
#define MSTATUS_SIE 0x00000002
|
||||
#define MSTATUS_HIE 0x00000004
|
||||
#define MSTATUS_MIE 0x00000008
|
||||
#define MSTATUS_UPIE 0x00000010
|
||||
#define MSTATUS_SPIE 0x00000020
|
||||
#define MSTATUS_HPIE 0x00000040
|
||||
#define MSTATUS_MPIE 0x00000080
|
||||
#define MSTATUS_SPP 0x00000100
|
||||
#define MSTATUS_HPP 0x00000600
|
||||
#define MSTATUS_MPP 0x00001800
|
||||
#define MSTATUS_FS 0x00006000
|
||||
#define MSTATUS_XS 0x00018000
|
||||
#define MSTATUS_MPRV 0x00020000
|
||||
#define MSTATUS_SUM 0x00040000
|
||||
#define MSTATUS_MXR 0x00080000
|
||||
#define MSTATUS_TVM 0x00100000
|
||||
#define MSTATUS_TW 0x00200000
|
||||
#define MSTATUS_TSR 0x00400000
|
||||
#define MSTATUS32_SD 0x80000000
|
||||
#define MSTATUS_UXL 0x0000000300000000
|
||||
#define MSTATUS_SXL 0x0000000C00000000
|
||||
#define MSTATUS64_SD 0x8000000000000000
|
||||
|
||||
#define SSTATUS_UIE 0x00000001
|
||||
#define SSTATUS_SIE 0x00000002
|
||||
#define SSTATUS_UPIE 0x00000010
|
||||
#define SSTATUS_SPIE 0x00000020
|
||||
#define SSTATUS_SPP 0x00000100
|
||||
#define SSTATUS_FS 0x00006000
|
||||
#define SSTATUS_XS 0x00018000
|
||||
#define SSTATUS_SUM 0x00040000
|
||||
#define SSTATUS_MXR 0x00080000
|
||||
#define SSTATUS32_SD 0x80000000
|
||||
#define SSTATUS_UXL 0x0000000300000000
|
||||
#define SSTATUS64_SD 0x8000000000000000
|
||||
|
||||
|
||||
#define PMP_R 0x01
|
||||
#define PMP_W 0x02
|
||||
#define PMP_X 0x04
|
||||
#define PMP_A 0x18
|
||||
#define PMP_L 0x80
|
||||
#define PMP_SHIFT 2
|
||||
|
||||
#define PMP_TOR 0x08
|
||||
#define PMP_NA4 0x10
|
||||
#define PMP_NAPOT 0x18
|
||||
|
||||
#define RDCYCLE 0xC00 //Read-only cycle Cycle counter for RDCYCLE instruction.
|
||||
#define RDTIME 0xC01 //Read-only time Timer for RDTIME instruction.
|
||||
#define RDINSTRET 0xC02 //Read-only instret Instructions-retired counter for RDINSTRET instruction.
|
||||
#define RDCYCLEH 0xC80 //Read-only cycleh Upper 32 bits of cycle, RV32I only.
|
||||
#define RDTIMEH 0xC81 //Read-only timeh Upper 32 bits of time, RV32I only.
|
||||
#define RDINSTRETH 0xC82 //Read-only instreth Upper 32 bits of instret, RV32I only.
|
||||
|
||||
|
||||
#define csr_swap(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrw %0, " #csr ", %1" \
|
||||
: "=r" (__v) : "rK" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_read(csr) \
|
||||
({ \
|
||||
register unsigned long __v; \
|
||||
__asm__ __volatile__ ("csrr %0, " #csr \
|
||||
: "=r" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_write(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrw " #csr ", %0" \
|
||||
: : "rK" (__v)); \
|
||||
})
|
||||
|
||||
#define csr_read_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrs %0, " #csr ", %1" \
|
||||
: "=r" (__v) : "rK" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_set(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrs " #csr ", %0" \
|
||||
: : "rK" (__v)); \
|
||||
})
|
||||
|
||||
#define csr_read_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrrc %0, " #csr ", %1" \
|
||||
: "=r" (__v) : "rK" (__v)); \
|
||||
__v; \
|
||||
})
|
||||
|
||||
#define csr_clear(csr, val) \
|
||||
({ \
|
||||
unsigned long __v = (unsigned long)(val); \
|
||||
__asm__ __volatile__ ("csrc " #csr ", %0" \
|
||||
: : "rK" (__v)); \
|
||||
})
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
51
src/main/c/emulator/src/start.S
Executable file
51
src/main/c/emulator/src/start.S
Executable file
|
@ -0,0 +1,51 @@
|
|||
.section .init
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
|
||||
#include "config.h"
|
||||
_start:
|
||||
/*#ifdef USE_GP
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
#endif*/
|
||||
la sp, _sp
|
||||
|
||||
|
||||
/* Load data section */
|
||||
la a0, _data_lma
|
||||
la a1, _data
|
||||
la a2, _edata
|
||||
bgeu a1, a2, 2f
|
||||
1:
|
||||
lw t0, (a0)
|
||||
sw t0, (a1)
|
||||
addi a0, a0, 4
|
||||
addi a1, a1, 4
|
||||
bltu a1, a2, 1b
|
||||
2:
|
||||
|
||||
/* Clear bss section */
|
||||
la a0, __bss_start
|
||||
la a1, _end
|
||||
bgeu a0, a1, 2f
|
||||
1:
|
||||
sw zero, (a0)
|
||||
addi a0, a0, 4
|
||||
bltu a0, a1, 1b
|
||||
2:
|
||||
|
||||
call __libc_init_array
|
||||
call init
|
||||
la ra, done
|
||||
li a0, 0
|
||||
li a1, DTB
|
||||
mret
|
||||
done:
|
||||
j done
|
||||
|
||||
|
||||
.globl _init
|
||||
_init:
|
||||
ret
|
71
src/main/c/emulator/src/trap.S
Normal file
71
src/main/c/emulator/src/trap.S
Normal file
|
@ -0,0 +1,71 @@
|
|||
.section .init
|
||||
.globl trapEntry
|
||||
.type trapEntry,@function
|
||||
|
||||
trapEntry:
|
||||
csrrw sp, mscratch, sp
|
||||
sw x1, 1*4(sp)
|
||||
sw x3, 3*4(sp)
|
||||
sw x4, 4*4(sp)
|
||||
sw x5, 5*4(sp)
|
||||
sw x6, 6*4(sp)
|
||||
sw x7, 7*4(sp)
|
||||
sw x8, 8*4(sp)
|
||||
sw x9, 9*4(sp)
|
||||
sw x10, 10*4(sp)
|
||||
sw x11, 11*4(sp)
|
||||
sw x12, 12*4(sp)
|
||||
sw x13, 13*4(sp)
|
||||
sw x14, 14*4(sp)
|
||||
sw x15, 15*4(sp)
|
||||
sw x16, 16*4(sp)
|
||||
sw x17, 17*4(sp)
|
||||
sw x18, 18*4(sp)
|
||||
sw x19, 19*4(sp)
|
||||
sw x20, 20*4(sp)
|
||||
sw x21, 21*4(sp)
|
||||
sw x22, 22*4(sp)
|
||||
sw x23, 23*4(sp)
|
||||
sw x24, 24*4(sp)
|
||||
sw x25, 25*4(sp)
|
||||
sw x26, 26*4(sp)
|
||||
sw x27, 27*4(sp)
|
||||
sw x28, 28*4(sp)
|
||||
sw x29, 29*4(sp)
|
||||
sw x30, 30*4(sp)
|
||||
sw x31, 31*4(sp)
|
||||
call trap
|
||||
lw x1, 1*4(sp)
|
||||
lw x3, 3*4(sp)
|
||||
lw x4, 4*4(sp)
|
||||
lw x5, 5*4(sp)
|
||||
lw x6, 6*4(sp)
|
||||
lw x7, 7*4(sp)
|
||||
lw x8, 8*4(sp)
|
||||
lw x9, 9*4(sp)
|
||||
lw x10, 10*4(sp)
|
||||
lw x11, 11*4(sp)
|
||||
lw x12, 12*4(sp)
|
||||
lw x13, 13*4(sp)
|
||||
lw x14, 14*4(sp)
|
||||
lw x15, 15*4(sp)
|
||||
lw x16, 16*4(sp)
|
||||
lw x17, 17*4(sp)
|
||||
lw x18, 18*4(sp)
|
||||
lw x19, 19*4(sp)
|
||||
lw x20, 20*4(sp)
|
||||
lw x21, 21*4(sp)
|
||||
lw x22, 22*4(sp)
|
||||
lw x23, 23*4(sp)
|
||||
lw x24, 24*4(sp)
|
||||
lw x25, 25*4(sp)
|
||||
lw x26, 26*4(sp)
|
||||
lw x27, 27*4(sp)
|
||||
lw x28, 28*4(sp)
|
||||
lw x29, 29*4(sp)
|
||||
lw x30, 30*4(sp)
|
||||
lw x31, 31*4(sp)
|
||||
csrrw sp, mscratch, sp
|
||||
mret
|
||||
|
||||
|
47
src/main/c/emulator/src/utils.S
Normal file
47
src/main/c/emulator/src/utils.S
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "riscv.h"
|
||||
/*
|
||||
|
||||
.section .init
|
||||
.globl readMemory
|
||||
.type readMemory,@function
|
||||
readWord:
|
||||
csrr a4, mepc
|
||||
li a2, MSTATUS_MPRV
|
||||
csrs mstatus, a2
|
||||
li a3, emulationTrap
|
||||
csrw mepc, a3
|
||||
lw a0, 0(a0)
|
||||
li a3, trapEntry
|
||||
csrw mepc, a3
|
||||
csrc mstatus, a2
|
||||
|
||||
writeWord:
|
||||
csrr a4, mepc
|
||||
li a2, MSTATUS_MPRV
|
||||
csrs mstatus, a2
|
||||
li a3, emulationTrap
|
||||
csrw mepc, a3
|
||||
sw a1, 0(a0)
|
||||
li a3, trapEntry
|
||||
csrw mepc, a3
|
||||
csrc mstatus, a2
|
||||
*/
|
||||
//Redirect trap to supervisor
|
||||
/*
|
||||
.section .init
|
||||
.globl emulationTrap
|
||||
.type emulationTrap,@function
|
||||
emulationTrap:
|
||||
li a0, MSTATUS_MPRV
|
||||
csrc mstatus, a0
|
||||
|
||||
la sp, _sp
|
||||
csrw sepc, a4
|
||||
csrr a0, mcause
|
||||
csrw scause, a0
|
||||
csrr a0, mbadaddr
|
||||
csrw sbadaddr, a0
|
||||
|
||||
call init
|
||||
mret
|
||||
*/
|
|
@ -43,14 +43,30 @@ object IcestormFlow {
|
|||
def apply(workspacePath : String,toplevelPath : String,family : String,device : String, pack : String) : Report = {
|
||||
val projectName = toplevelPath.split("/").last.split("[.]").head
|
||||
|
||||
|
||||
//ifeq ($(NEXTPNR),yes)
|
||||
//%.json: ${VERILOGS}
|
||||
// rm -f ${TOPLEVEL}.v*.bin
|
||||
// cp -f ${ROOT}/hardware/netlist/${TOPLEVEL}.v*.bin . | true
|
||||
// yosys -p 'synth_ice40 -top $(TOPLEVEL) -json $@' $<
|
||||
//
|
||||
//%.asc: $(PIN_DEF) %.json constraint.py
|
||||
// nextpnr-ice40 --$(DEVICE) --json $(TOPLEVEL).json --pcf $(PIN_DEF) --asc $(TOPLEVEL).asc --pre-pack constraint.py $(NEXTPNR_ARG)
|
||||
//else
|
||||
//%.blif: ${VERILOGS}
|
||||
// rm -f ${TOPLEVEL}.v*.bin
|
||||
// cp -f ${ROOT}/hardware/netlist/${TOPLEVEL}.v*.bin . | true
|
||||
// yosys -p 'synth_ice40 -top ${TOPLEVEL} -blif $@' $<
|
||||
//
|
||||
//%.asc: $(PIN_DEF) %.blif
|
||||
// arachne-pnr -d $(subst up,,$(subst hx,,$(subst lp,,$(DEVICE)))) -o $@ -p $^
|
||||
//endif
|
||||
|
||||
val workspacePathFile = new File(workspacePath)
|
||||
FileUtils.deleteDirectory(workspacePathFile)
|
||||
workspacePathFile.mkdir()
|
||||
FileUtils.copyFileToDirectory(new File(toplevelPath), workspacePathFile)
|
||||
doCmd(List("yosys", "-v3", "-p", s"synth_ice40 -top $projectName -blif ${projectName}.blif", s"$projectName.v" ), workspacePath)
|
||||
val arachne = doCmd(List("arachne-pnr", "-d", device.replace("hx","").replace("up",""), "--max-passes", "600", "-P", pack, s"$projectName.blif" ,"-o", s"$projectName.asc"), workspacePath)
|
||||
doCmd(List("yosys", "-v3", "-p", s"synth_ice40 -top $projectName -json ${projectName}.json", s"$projectName.v" ), workspacePath)
|
||||
val arachne = doCmd(List("nextpnr-ice40", s"--$device", "--json", s"${projectName}.json","--asc", s"$projectName.asc"), workspacePath)
|
||||
doCmd(List("icepack", s"$projectName.asc", s"$projectName.bin"), workspacePath)
|
||||
val icetime = doCmd(List("icetime", "-tmd", device, s"${projectName}.asc"), workspacePath)
|
||||
new Report{
|
||||
|
@ -65,7 +81,7 @@ object IcestormFlow {
|
|||
}
|
||||
override def getArea() = {
|
||||
try {
|
||||
intFind.findFirstIn("LCs[^\\n]*\\/".r.findFirstIn(arachne).get).get.toString() + " LC"
|
||||
intFind.findFirstIn("ICESTORM_LC\\:[^\\n]*\\/".r.findFirstIn(arachne).get).get.toString() + " LC"
|
||||
} catch {
|
||||
case e : Throwable => "error"
|
||||
}
|
||||
|
@ -151,7 +167,7 @@ object IcestormFlow {
|
|||
// }
|
||||
SpinalVerilog(StreamFifo(Bits(8 bits), 64))
|
||||
val report = IcestormFlow(
|
||||
workspacePath="/home/spinalvm/tmp",
|
||||
workspacePath="/media/miaou/HD/linux/tmp",
|
||||
toplevelPath="StreamFifo.v",
|
||||
family="iCE40",
|
||||
device="up5k",
|
||||
|
|
|
@ -7,21 +7,21 @@ import spinal.lib._
|
|||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
trait PipelineConfig[T]
|
||||
trait PipelineThing[T]
|
||||
|
||||
trait Pipeline {
|
||||
type T <: Pipeline
|
||||
val plugins = ArrayBuffer[Plugin[T]]()
|
||||
var stages = ArrayBuffer[Stage]()
|
||||
var unremovableStages = mutable.Set[Stage]()
|
||||
val configs = mutable.HashMap[PipelineConfig[_], Any]()
|
||||
val things = mutable.HashMap[PipelineThing[_], Any]()
|
||||
// val services = ArrayBuffer[Any]()
|
||||
|
||||
def indexOf(stage : Stage) = stages.indexOf(stage)
|
||||
|
||||
def service[T](clazz : Class[T]) = {
|
||||
val filtered = plugins.filter(o => clazz.isAssignableFrom(o.getClass))
|
||||
assert(filtered.length == 1)
|
||||
assert(filtered.length == 1, s"??? ${clazz.getName}")
|
||||
filtered.head.asInstanceOf[T]
|
||||
}
|
||||
|
||||
|
@ -37,16 +37,23 @@ trait Pipeline {
|
|||
filtered.head.asInstanceOf[T]
|
||||
}
|
||||
|
||||
def update[T](that : PipelineConfig[T], value : T) : Unit = configs(that) = value
|
||||
def apply[T](that : PipelineConfig[T]) : T = configs(that).asInstanceOf[T]
|
||||
def update[T](that : PipelineThing[T], value : T) : Unit = things(that) = value
|
||||
def apply[T](that : PipelineThing[T]) : T = things(that).asInstanceOf[T]
|
||||
|
||||
def build(): Unit ={
|
||||
plugins.foreach(_.pipeline = this.asInstanceOf[T])
|
||||
plugins.foreach(_.setup(this.asInstanceOf[T]))
|
||||
|
||||
plugins.foreach{ p =>
|
||||
p.parentScope = Component.current.dslBody //Put the given plugin as a child of the current component
|
||||
p.reflectNames()
|
||||
}
|
||||
|
||||
//Build plugins
|
||||
plugins.foreach(_.build(this.asInstanceOf[T]))
|
||||
|
||||
|
||||
|
||||
//Interconnect stages
|
||||
class KeyInfo{
|
||||
var insertStageId = Int.MaxValue
|
||||
|
@ -112,7 +119,7 @@ trait Pipeline {
|
|||
inputDefault := stage.inserts(key)
|
||||
} else {
|
||||
val stageBefore = stages(stageIndex - 1)
|
||||
inputDefault := RegNextWhen(stageBefore.output(key), !stage.arbitration.isStuck).setName(s"${stageBefore.getName()}_to_${stage.getName()}_${key.getName()}")
|
||||
inputDefault := RegNextWhen(stageBefore.output(key), stage.dontSample.getOrElse(key, Nil).foldLeft(!stage.arbitration.isStuck)(_ && !_)).setName(s"${stageBefore.getName()}_to_${stage.getName()}_${key.getName()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,16 @@ object Riscv{
|
|||
def LR = M"00010--00000-----010-----0101111"
|
||||
def SC = M"00011------------010-----0101111"
|
||||
|
||||
def AMOSWAP = M"00001------------010-----0101111"
|
||||
def AMOADD = M"00000------------010-----0101111"
|
||||
def AMOXOR = M"00100------------010-----0101111"
|
||||
def AMOAND = M"01100------------010-----0101111"
|
||||
def AMOOR = M"01000------------010-----0101111"
|
||||
def AMOMIN = M"10000------------010-----0101111"
|
||||
def AMOMAX = M"10100------------010-----0101111"
|
||||
def AMOMINU = M"11000------------010-----0101111"
|
||||
def AMOMAXU = M"11100------------010-----0101111"
|
||||
|
||||
def BEQ (rvc : Boolean) = if(rvc) M"-----------------000-----1100011" else M"-----------------000---0-1100011"
|
||||
def BNE (rvc : Boolean) = if(rvc) M"-----------------001-----1100011" else M"-----------------001---0-1100011"
|
||||
def BLT (rvc : Boolean) = if(rvc) M"-----------------100-----1100011" else M"-----------------100---0-1100011"
|
||||
|
@ -105,6 +115,7 @@ object Riscv{
|
|||
|
||||
def FENCE = M"-----------------000-----0001111"
|
||||
def FENCE_I = M"-----------------001-----0001111"
|
||||
def SFENCE_VMA = M"0001001----------000000001110011"
|
||||
|
||||
object CSR{
|
||||
def MVENDORID = 0xF11 // MRO Vendor ID.
|
||||
|
|
|
@ -33,14 +33,21 @@ case class ExceptionCause() extends Bundle{
|
|||
|
||||
trait ExceptionService{
|
||||
def newExceptionPort(stage : Stage, priority : Int = 0) : Flow[ExceptionCause]
|
||||
def isExceptionPending(stage : Stage) : Bool
|
||||
}
|
||||
|
||||
trait PrivilegeService{
|
||||
def isUser(stage : Stage) : Bool
|
||||
def isUser() : Bool
|
||||
def isSupervisor() : Bool
|
||||
def isMachine() : Bool
|
||||
def forceMachine() : Unit
|
||||
}
|
||||
|
||||
case class PrivilegeServiceDefault() extends PrivilegeService{
|
||||
override def isUser(stage: Stage): Bool = False
|
||||
override def isUser(): Bool = False
|
||||
override def isSupervisor(): Bool = False
|
||||
override def isMachine(): Bool = True
|
||||
override def forceMachine(): Unit = {}
|
||||
}
|
||||
|
||||
trait InterruptionInhibitor{
|
||||
|
@ -51,6 +58,7 @@ trait ExceptionInhibitor{
|
|||
def inhibateException() : Unit
|
||||
}
|
||||
|
||||
|
||||
trait RegFileService{
|
||||
def readStage() : Stage
|
||||
}
|
||||
|
@ -64,19 +72,20 @@ case class MemoryTranslatorCmd() extends Bundle{
|
|||
case class MemoryTranslatorRsp() extends Bundle{
|
||||
val physicalAddress = UInt(32 bits)
|
||||
val isIoAccess = Bool
|
||||
val allowRead, allowWrite, allowExecute, allowUser = Bool
|
||||
val miss = Bool
|
||||
val hit = Bool
|
||||
val allowRead, allowWrite, allowExecute = Bool
|
||||
val exception = Bool
|
||||
val refilling = Bool
|
||||
}
|
||||
|
||||
case class MemoryTranslatorBus() extends Bundle with IMasterSlave{
|
||||
val cmd = MemoryTranslatorCmd()
|
||||
val rsp = MemoryTranslatorRsp()
|
||||
val end = Bool
|
||||
val busy = Bool
|
||||
|
||||
override def asMaster() : Unit = {
|
||||
out(cmd, end)
|
||||
in(rsp)
|
||||
in(rsp, busy)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import spinal.core._
|
|||
import spinal.lib._
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
||||
class Stageable[T <: Data](_dataType : => T) extends HardType[T](_dataType) with Nameable{
|
||||
|
@ -49,7 +50,6 @@ class Stage() extends Area{
|
|||
val haltByOther = False //When settable, stuck the instruction, should only be set by something else than the stucked instruction
|
||||
val removeIt = False //When settable, unschedule the instruction as if it was never executed (no side effect)
|
||||
val flushAll = False //When settable, unschedule instructions in the current stage and all prior ones
|
||||
val redoIt = False //Allow to notify that a given instruction in a pipeline is rescheduled
|
||||
val isValid = Bool //Inform if a instruction is in the current stage
|
||||
val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther)
|
||||
val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else
|
||||
|
@ -68,6 +68,11 @@ class Stage() extends Area{
|
|||
val inputsDefault = mutable.HashMap[Stageable[Data],Data]()
|
||||
val outputsDefault = mutable.HashMap[Stageable[Data],Data]()
|
||||
|
||||
val dontSample = mutable.HashMap[Stageable[_], ArrayBuffer[Bool]]()
|
||||
|
||||
def dontSampleStageable(s : Stageable[_], cond : Bool): Unit ={
|
||||
dontSample.getOrElseUpdate(s, ArrayBuffer[Bool]()) += cond
|
||||
}
|
||||
def inputInit[T <: BaseType](stageable : Stageable[T],initValue : T) =
|
||||
Component.current.addPrePopTask(() => inputsDefault(stageable.asInstanceOf[Stageable[Data]]).asInstanceOf[T].getDrivingReg.init(initValue))
|
||||
}
|
|
@ -56,7 +56,6 @@ object TestsWorkspace {
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = false,
|
||||
twoCycleCache = true
|
||||
|
@ -82,8 +81,7 @@ object TestsWorkspace {
|
|||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
atomicEntriesCount = 2
|
||||
withLrSc = true
|
||||
),
|
||||
// memoryTranslatorPortConfig = null
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -42,6 +42,8 @@ case class VexRiscvConfig(){
|
|||
object REGFILE_WRITE_VALID extends Stageable(Bool)
|
||||
object REGFILE_WRITE_DATA extends Stageable(Bits(32 bits))
|
||||
|
||||
object MPP extends PipelineThing[UInt]
|
||||
object DEBUG_BYPASS_CACHE extends PipelineThing[Bool]
|
||||
|
||||
object SRC1 extends Stageable(Bits(32 bits))
|
||||
object SRC2 extends Stageable(Bits(32 bits))
|
||||
|
@ -51,6 +53,7 @@ case class VexRiscvConfig(){
|
|||
object SRC_LESS extends Stageable(Bool)
|
||||
object SRC_USE_SUB_LESS extends Stageable(Bool)
|
||||
object SRC_LESS_UNSIGNED extends Stageable(Bool)
|
||||
object SRC_ADD_ZERO extends Stageable(Bool)
|
||||
|
||||
|
||||
object HAS_SIDE_EFFECT extends Stageable(Bool)
|
||||
|
@ -71,7 +74,7 @@ case class VexRiscvConfig(){
|
|||
}
|
||||
|
||||
object Src2CtrlEnum extends SpinalEnum(binarySequential){
|
||||
val RS, IMI, IMS, PC = newElement()
|
||||
val RS, IMI, IMS, PC = newElement() //TODO remplacing ZERO could avoid 32 muxes if SRC_ADD can be disabled
|
||||
}
|
||||
object SRC1_CTRL extends Stageable(Src1CtrlEnum())
|
||||
object SRC2_CTRL extends Stageable(Src2CtrlEnum())
|
||||
|
@ -79,7 +82,7 @@ case class VexRiscvConfig(){
|
|||
|
||||
|
||||
|
||||
object RVC_GEN extends PipelineConfig[Boolean]
|
||||
object RVC_GEN extends PipelineThing[Boolean]
|
||||
class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
|
||||
type T = VexRiscv
|
||||
import config._
|
||||
|
@ -96,18 +99,13 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
|
|||
plugins ++= config.plugins
|
||||
|
||||
//regression usage
|
||||
decode.input(config.INSTRUCTION).addAttribute(Verilator.public)
|
||||
decode.input(config.PC).addAttribute(Verilator.public)
|
||||
decode.arbitration.isValid.addAttribute(Verilator.public)
|
||||
decode.arbitration.flushAll.addAttribute(Verilator.public)
|
||||
decode.arbitration.haltItself.addAttribute(Verilator.public)
|
||||
if(withWriteBackStage) {
|
||||
writeBack.input(config.INSTRUCTION) keep() addAttribute (Verilator.public)
|
||||
writeBack.input(config.PC) keep() addAttribute (Verilator.public)
|
||||
writeBack.arbitration.isValid keep() addAttribute (Verilator.public)
|
||||
writeBack.arbitration.isFiring keep() addAttribute (Verilator.public)
|
||||
}
|
||||
decode.arbitration.removeIt.noBackendCombMerge //Verilator perf
|
||||
val lastStageInstruction = CombInit(stages.last.input(config.INSTRUCTION)) keep() addAttribute (Verilator.public)
|
||||
val lastStagePc = CombInit(stages.last.input(config.PC)) keep() addAttribute (Verilator.public)
|
||||
val lastStageIsValid = CombInit(stages.last.arbitration.isValid) keep() addAttribute (Verilator.public)
|
||||
val lastStageIsFiring = CombInit(stages.last.arbitration.isFiring) keep() addAttribute (Verilator.public)
|
||||
|
||||
//Verilator perf
|
||||
decode.arbitration.removeIt.noBackendCombMerge
|
||||
if(withMemoryStage){
|
||||
memory.arbitration.removeIt.noBackendCombMerge
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ object BrieyConfig{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
@ -89,8 +88,7 @@ object BrieyConfig{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -23,12 +23,11 @@ object GenFull extends App{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
),
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
memoryTranslatorPortConfig = MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
|
@ -42,15 +41,13 @@ object GenFull extends App{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
memoryTranslatorPortConfig = MmuPortConfig(
|
||||
portTlbSize = 6
|
||||
)
|
||||
),
|
||||
new MemoryTranslatorPlugin(
|
||||
tlbSize = 32,
|
||||
new MmuPlugin(
|
||||
virtualRange = _(31 downto 28) === 0xC,
|
||||
ioRange = _(31 downto 28) === 0xF
|
||||
),
|
||||
|
|
|
@ -27,7 +27,6 @@ object GenFullNoMmu extends App{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
@ -43,8 +42,7 @@ object GenFullNoMmu extends App{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
)
|
||||
),
|
||||
new StaticMemoryTranslatorPlugin(
|
||||
|
|
|
@ -28,7 +28,6 @@ object GenFullNoMmuMaxPerf extends App{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = false,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
@ -44,8 +43,7 @@ object GenFullNoMmuMaxPerf extends App{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = false
|
||||
catchUnaligned = true
|
||||
)
|
||||
),
|
||||
new StaticMemoryTranslatorPlugin(
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package vexriscv.demo
|
||||
|
||||
import vexriscv.plugin._
|
||||
import vexriscv.ip.{DataCacheConfig, InstructionCacheConfig}
|
||||
import vexriscv.{plugin, VexRiscv, VexRiscvConfig}
|
||||
import spinal.core._
|
||||
|
||||
/**
|
||||
* Created by spinalvm on 15.06.17.
|
||||
*/
|
||||
object GenFullNoMmuNoCacheSimpleMul extends App{
|
||||
def cpu() = new VexRiscv(
|
||||
config = VexRiscvConfig(
|
||||
plugins = List(
|
||||
new IBusSimplePlugin(
|
||||
resetVector = 0x80000000l,
|
||||
cmdForkOnSecondStage = false,
|
||||
cmdForkPersistence = false,
|
||||
prediction = STATIC,
|
||||
catchAccessFault = false,
|
||||
compressedGen = false
|
||||
),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = false,
|
||||
catchAccessFault = false
|
||||
),
|
||||
new DecoderSimplePlugin(
|
||||
catchIllegalInstruction = true
|
||||
),
|
||||
new RegFilePlugin(
|
||||
regFileReadyKind = plugin.SYNC,
|
||||
zeroBoot = false
|
||||
),
|
||||
new IntAluPlugin,
|
||||
new SrcPlugin(
|
||||
separatedAddSub = false,
|
||||
executeInsertion = true
|
||||
),
|
||||
new FullBarrelShifterPlugin,
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = true,
|
||||
bypassMemory = true,
|
||||
bypassWriteBack = true,
|
||||
bypassWriteBackBuffer = true,
|
||||
pessimisticUseSrc = false,
|
||||
pessimisticWriteRegFile = false,
|
||||
pessimisticAddressMatch = false
|
||||
),
|
||||
new MulSimplePlugin,
|
||||
new DivPlugin,
|
||||
new CsrPlugin(CsrPluginConfig.small),
|
||||
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
|
||||
new BranchPlugin(
|
||||
earlyBranch = false,
|
||||
catchAddressMisaligned = true
|
||||
),
|
||||
new YamlPlugin("cpu0.yaml")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
SpinalVerilog(cpu())
|
||||
}
|
61
src/main/scala/vexriscv/demo/GenMicroNoCsr.scala
Normal file
61
src/main/scala/vexriscv/demo/GenMicroNoCsr.scala
Normal file
|
@ -0,0 +1,61 @@
|
|||
package vexriscv.demo
|
||||
|
||||
import vexriscv.plugin._
|
||||
import vexriscv.{plugin, VexRiscv, VexRiscvConfig}
|
||||
import spinal.core._
|
||||
|
||||
/**
|
||||
* Created by spinalvm on 15.06.17.
|
||||
*/
|
||||
object GenMicroNoCsr extends App{
|
||||
def cpu() = new VexRiscv(
|
||||
config = VexRiscvConfig(
|
||||
withMemoryStage = false,
|
||||
withWriteBackStage = false,
|
||||
plugins = List(
|
||||
new IBusSimplePlugin(
|
||||
resetVector = 0x80000000l,
|
||||
cmdForkOnSecondStage = false,
|
||||
cmdForkPersistence = false,
|
||||
prediction = NONE,
|
||||
catchAccessFault = false,
|
||||
compressedGen = false
|
||||
),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = false,
|
||||
catchAccessFault = false,
|
||||
earlyInjection = false
|
||||
),
|
||||
new DecoderSimplePlugin(
|
||||
catchIllegalInstruction = false
|
||||
),
|
||||
new RegFilePlugin(
|
||||
regFileReadyKind = plugin.SYNC,
|
||||
zeroBoot = false,
|
||||
writeRfInMemoryStage = false
|
||||
),
|
||||
new IntAluPlugin,
|
||||
new SrcPlugin(
|
||||
separatedAddSub = false,
|
||||
executeInsertion = false
|
||||
),
|
||||
new LightShifterPlugin,
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = false,
|
||||
bypassMemory = false,
|
||||
bypassWriteBack = false,
|
||||
bypassWriteBackBuffer = false,
|
||||
pessimisticUseSrc = false,
|
||||
pessimisticWriteRegFile = false,
|
||||
pessimisticAddressMatch = false
|
||||
),
|
||||
new BranchPlugin(
|
||||
earlyBranch = true,
|
||||
catchAddressMisaligned = false
|
||||
),
|
||||
new YamlPlugin("cpu0.yaml")
|
||||
)
|
||||
)
|
||||
)
|
||||
SpinalConfig(mergeAsyncProcess = false).generateVerilog(cpu())
|
||||
}
|
|
@ -26,7 +26,6 @@ object GenSmallAndProductiveICache extends App{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = false,
|
||||
catchAccessFault = false,
|
||||
catchMemoryTranslationMiss = false,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = false,
|
||||
twoCycleCache = true
|
||||
|
|
507
src/main/scala/vexriscv/demo/Linux.scala
Normal file
507
src/main/scala/vexriscv/demo/Linux.scala
Normal file
|
@ -0,0 +1,507 @@
|
|||
/*
|
||||
* SpinalHDL
|
||||
* Copyright (c) Dolu, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
|
||||
package vexriscv.demo
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib.eda.bench.{AlteraStdTargets, Bench, Rtl, XilinxStdTargets}
|
||||
import spinal.lib.eda.icestorm.IcestormStdTargets
|
||||
import spinal.lib.master
|
||||
import vexriscv._
|
||||
import vexriscv.ip._
|
||||
import vexriscv.plugin._
|
||||
|
||||
/*
|
||||
prerequired stuff =>
|
||||
- JAVA JDK >= 8
|
||||
- SBT
|
||||
- Verilator
|
||||
|
||||
Setup things =>
|
||||
git clone https://github.com/SpinalHDL/SpinalHDL.git -b dev
|
||||
git clone https://github.com/SpinalHDL/VexRiscv.git -b linux
|
||||
cd VexRiscv
|
||||
|
||||
Run regressions =>
|
||||
sbt "runMain vexriscv.demo.LinuxGen -r"
|
||||
cd src/test/cpp/regression
|
||||
make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes MMU=yes CSR=yes DEBUG_PLUGIN=no COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes REDO=10 TRACE=no COREMARK=yes LINUX_REGRESSION=yes
|
||||
|
||||
Run linux in simulation (Require the machime mode emulator compiled in SIM mode) =>
|
||||
sbt "runMain vexriscv.demo.LinuxGen"
|
||||
cd src/test/cpp/regression
|
||||
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
|
||||
make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes DEBUG_PLUGIN=no COMPRESSED=no LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes EMULATOR=../../../main/c/emulator/build/emulator.bin VMLINUX=$BUILDROOT/output/images/Image DTB=$BUILDROOT/board/spinal/vexriscv_sim/rv32.dtb RAMDISK=$BUILDROOT/output/images/rootfs.cpio WITH_USER_IO=yes TRACE=no FLOW_INFO=no
|
||||
|
||||
Run linux with QEMU (Require the machime mode emulator compiled in QEMU mode)
|
||||
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
|
||||
qemu-system-riscv32 -nographic -machine virt -m 1536M -device loader,file=src/main/c/emulator/build/emulator.bin,addr=0x80000000,cpu-num=0 -device loader,file=$BUILDROOT/board/spinal/vexriscv_sim/rv32.dtb,addr=0xC3000000 -device loader,file=$BUILDROOT/output/images/Image,addr=0xC0000000 -device loader,file=$BUILDROOT/output/images/rootfs.cpio,addr=0xc2000000
|
||||
|
||||
|
||||
Buildroot =>
|
||||
git clone https://github.com/SpinalHDL/buildroot.git -b vexriscv
|
||||
cd buildroot
|
||||
make spinal_vexriscv_sim_defconfig
|
||||
make -j$(nproc)
|
||||
output/host/bin/riscv32-linux-objcopy -O binary output/images/vmlinux output/images/Image
|
||||
|
||||
After changing a kernel config into buildroot =>
|
||||
cd buildroot
|
||||
make spinal_vexriscv_sim_defconfig
|
||||
make linux-dirclean linux-rebuild -j8
|
||||
output/host/bin/riscv32-linux-objcopy -O binary output/images/vmlinux output/images/Image
|
||||
|
||||
Compiling the machine mode emulator (check the config.h file to know the mode) =>
|
||||
cd src/main/c/emulator
|
||||
make clean all
|
||||
|
||||
Changing the emulator mode =>
|
||||
Edit the src/main/c/emulator/src/config.h file, and comment/uncomment the SIM/QEMU flags
|
||||
|
||||
Other commands (Memo):
|
||||
decompile file and split it
|
||||
riscv64-unknown-elf-objdump -S -d vmlinux > vmlinux.asm; split -b 1M vmlinux.asm
|
||||
|
||||
Kernel compilation command =>
|
||||
ARCH=riscv CROSS_COMPILE=riscv32-unknown-linux-gnu- make menuconfig
|
||||
ARCH=riscv CROSS_COMPILE=riscv32-unknown-linux-gnu- make -j`nproc`; riscv32-unknown-linux-gnu-objcopy -O binary vmlinux vmlinux.bin
|
||||
|
||||
Generate a DTB from a DTS =>
|
||||
dtc -O dtb -o rv32.dtb rv32.dts
|
||||
|
||||
https://github.com/riscv/riscv-qemu/wiki#build-and-install
|
||||
|
||||
|
||||
memo :
|
||||
export DATA=/home/miaou/Downloads/Binaries-master
|
||||
cd src/test/cpp/regression
|
||||
rm VexRiscv.v
|
||||
cp $DATA/VexRiscv.v ../../../..
|
||||
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=no LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes EMULATOR=$DATA/emulator.bin VMLINUX=$DATA/vmlinux.bin DTB=$DATA/rv32.dtb RAMDISK=$DATA/rootfs.cpio TRACE=no FLOW_INFO=no
|
||||
|
||||
make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=no SUPERVISOR=yes CSR=yes COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes MMU=yes REDO=1 TRACE=no LINUX_REGRESSION=yes
|
||||
|
||||
qemu-system-riscv32 -nographic -machine virt -m 1536M -device loader,file=$DATA/emulator.bin,addr=0x80000000,cpu-num=0 -device loader,file=$DATA/rv32.dtb,addr=0xC3000000 -device loader,file=$DATA/vmlinux.bin,addr=0xC0000000 -device loader,file=$DATA/rootfs.cpio,addr=0xc2000000
|
||||
|
||||
|
||||
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yess SUPERVISOR=yes CSR=yes COMPRESSED=yes MUL=yes DIV=yes LRSC=yes AMO=yes REDO=1 TRACE=no LINUX_REGRESSION=yes
|
||||
|
||||
program ../../../main/c/emulator/build/emulator.bin 0x80000000 verify
|
||||
soc.loadBin(EMULATOR, 0x80000000);
|
||||
soc.loadBin(VMLINUX, 0xC0000000);
|
||||
soc.loadBin(DTB, 0xC3000000);
|
||||
soc.loadBin(RAMDISK, 0xC2000000);
|
||||
|
||||
export BUILDROOT=/home/miaou/pro/riscv/buildrootSpinal
|
||||
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=no LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes
|
||||
EMULATOR=../../../main/c/emulator/build/emulator.bin
|
||||
VMLINUX=/home/miaou/pro/riscv/buildrootSpinal/output/images/Image
|
||||
DTB=/home/miaou/pro/riscv/buildrootSpinal/board/spinal/vexriscv_sim/rv32.dtb
|
||||
RAMDISK=/home/miaou/pro/riscv/buildrootSpinal/output/images/rootfs.cpio TRACE=no FLOW_INFO=no
|
||||
|
||||
make run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD SUPERVISOR=yes CSR=yes COMPRESSED=no LRSC=yes AMO=yes REDO=0 DHRYSTONE=no LINUX_SOC=yes DEBUG_PLUGIN_EXTERNAL=yes
|
||||
|
||||
rm -rf cpio
|
||||
mkdir cpio
|
||||
cd cpio
|
||||
cpio -idv < ../rootfs.cpio
|
||||
cd ..
|
||||
|
||||
make clean run IBUS=CACHED DBUS=CACHED DEBUG_PLUGIN=STD DHRYSTONE=yes SUPERVISOR=yes MMU=yes CSR=yes COMPRESSED=no MUL=yes DIV=yes LRSC=yes AMO=yes REDO=10 TRACE=no COREMARK=yes LINUX_REGRESSION=yes RUN_HEX=~/pro/riscv/zephyr/samples/synchronization/build/zephyr/zephyr.hex
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
object LinuxGen {
|
||||
def configFull(litex : Boolean, withMmu : Boolean) = {
|
||||
val config = VexRiscvConfig(
|
||||
plugins = List(
|
||||
//Uncomment the whole IBusSimplePlugin and comment IBusCachedPlugin if you want uncached iBus config
|
||||
// new IBusSimplePlugin(
|
||||
// resetVector = 0x80000000l,
|
||||
// cmdForkOnSecondStage = false,
|
||||
// cmdForkPersistence = false,
|
||||
// prediction = DYNAMIC_TARGET,
|
||||
// historyRamSizeLog2 = 10,
|
||||
// catchAccessFault = true,
|
||||
// compressedGen = true,
|
||||
// busLatencyMin = 1,
|
||||
// injectorStage = true,
|
||||
// memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
// portTlbSize = 4
|
||||
// )
|
||||
// ),
|
||||
|
||||
//Uncomment the whole IBusCachedPlugin and comment IBusSimplePlugin if you want cached iBus config
|
||||
new IBusCachedPlugin(
|
||||
resetVector = 0x80000000l,
|
||||
compressedGen = false,
|
||||
prediction = STATIC,
|
||||
injectorStage = false,
|
||||
config = InstructionCacheConfig(
|
||||
cacheSize = 4096*1,
|
||||
bytePerLine = 32,
|
||||
wayCount = 1,
|
||||
addressWidth = 32,
|
||||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = false,
|
||||
twoCycleCache = true
|
||||
// )
|
||||
),
|
||||
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
|
||||
// new DBusSimplePlugin(
|
||||
// catchAddressMisaligned = true,
|
||||
// catchAccessFault = true,
|
||||
// earlyInjection = false,
|
||||
// withLrSc = true,
|
||||
// memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
// portTlbSize = 4
|
||||
// )
|
||||
// ),
|
||||
new DBusCachedPlugin(
|
||||
dBusCmdMasterPipe = true,
|
||||
dBusCmdSlavePipe = true,
|
||||
dBusRspSlavePipe = true,
|
||||
config = new DataCacheConfig(
|
||||
cacheSize = 4096*1,
|
||||
bytePerLine = 32,
|
||||
wayCount = 1,
|
||||
addressWidth = 32,
|
||||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
withLrSc = true,
|
||||
withAmo = true
|
||||
// )
|
||||
),
|
||||
memoryTranslatorPortConfig = withMmu generate MmuPortConfig(
|
||||
portTlbSize = 4
|
||||
)
|
||||
),
|
||||
|
||||
// new MemoryTranslatorPlugin(
|
||||
// tlbSize = 32,
|
||||
// virtualRange = _(31 downto 28) === 0xC,
|
||||
// ioRange = _(31 downto 28) === 0xF
|
||||
// ),
|
||||
|
||||
new DecoderSimplePlugin(
|
||||
catchIllegalInstruction = true
|
||||
),
|
||||
new RegFilePlugin(
|
||||
regFileReadyKind = plugin.SYNC,
|
||||
zeroBoot = true
|
||||
),
|
||||
new IntAluPlugin,
|
||||
new SrcPlugin(
|
||||
separatedAddSub = false
|
||||
),
|
||||
new FullBarrelShifterPlugin(earlyInjection = false),
|
||||
// new LightShifterPlugin,
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = true,
|
||||
bypassMemory = true,
|
||||
bypassWriteBack = true,
|
||||
bypassWriteBackBuffer = true,
|
||||
pessimisticUseSrc = false,
|
||||
pessimisticWriteRegFile = false,
|
||||
pessimisticAddressMatch = false
|
||||
),
|
||||
// new HazardSimplePlugin(false, true, false, true),
|
||||
// new HazardSimplePlugin(false, false, false, false),
|
||||
new MulPlugin,
|
||||
new MulDivIterativePlugin(
|
||||
genMul = false,
|
||||
genDiv = true,
|
||||
mulUnrollFactor = 32,
|
||||
divUnrollFactor = 1
|
||||
),
|
||||
// new DivPlugin,
|
||||
new CsrPlugin(CsrPluginConfig.linuxMinimal(0x80000020l).copy(ebreakGen = false)),
|
||||
// new CsrPlugin(//CsrPluginConfig.all2(0x80000020l).copy(ebreakGen = true)/*
|
||||
// CsrPluginConfig(
|
||||
// catchIllegalAccess = false,
|
||||
// mvendorid = null,
|
||||
// marchid = null,
|
||||
// mimpid = null,
|
||||
// mhartid = null,
|
||||
// misaExtensionsInit = 0,
|
||||
// misaAccess = CsrAccess.READ_ONLY,
|
||||
// mtvecAccess = CsrAccess.WRITE_ONLY,
|
||||
// mtvecInit = 0x80000020l,
|
||||
// mepcAccess = CsrAccess.READ_WRITE,
|
||||
// mscratchGen = true,
|
||||
// mcauseAccess = CsrAccess.READ_ONLY,
|
||||
// mbadaddrAccess = CsrAccess.READ_ONLY,
|
||||
// mcycleAccess = CsrAccess.NONE,
|
||||
// minstretAccess = CsrAccess.NONE,
|
||||
// ecallGen = true,
|
||||
// ebreakGen = true,
|
||||
// wfiGenAsWait = false,
|
||||
// wfiGenAsNop = true,
|
||||
// ucycleAccess = CsrAccess.NONE
|
||||
// )),
|
||||
// new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
|
||||
new BranchPlugin(
|
||||
earlyBranch = false,
|
||||
catchAddressMisaligned = true,
|
||||
fenceiGenAsAJump = false
|
||||
),
|
||||
new YamlPlugin("cpu0.yaml")
|
||||
)
|
||||
)
|
||||
if(withMmu) config.plugins += new MmuPlugin(
|
||||
ioRange = (x => if(litex) x(31 downto 28) === 0xB || x(31 downto 28) === 0xE || x(31 downto 28) === 0xF else x(31 downto 28) === 0xF)
|
||||
) else {
|
||||
config.plugins += new StaticMemoryTranslatorPlugin(
|
||||
ioRange = _(31 downto 28) === 0xF
|
||||
)
|
||||
}
|
||||
config
|
||||
}
|
||||
|
||||
|
||||
|
||||
def main(args: Array[String]) {
|
||||
// import spinal.core.sim._
|
||||
// SimConfig.withConfig(SpinalConfig(mergeAsyncProcess = false, anonymSignalPrefix = "zz_")).allOptimisation.compile(new VexRiscv(configFull)).doSimUntilVoid{ dut =>
|
||||
// dut.clockDomain.forkStimulus(10)
|
||||
// dut.clockDomain.forkSimSpeedPrinter(4)
|
||||
// var iBus : InstructionCacheMemBus = null
|
||||
//
|
||||
// dut.plugins.foreach{
|
||||
// case plugin: IBusCachedPlugin => iBus = plugin.iBus
|
||||
// case _ =>
|
||||
// }
|
||||
// dut.clockDomain.onSamplings{
|
||||
//// iBus.cmd.ready.randomize()
|
||||
// iBus.rsp.data #= 0x13
|
||||
// }
|
||||
// }
|
||||
|
||||
SpinalConfig(mergeAsyncProcess = true, anonymSignalPrefix = "_zz").generateVerilog {
|
||||
|
||||
|
||||
val toplevel = new VexRiscv(configFull(
|
||||
litex = !args.contains("-r"),
|
||||
withMmu = true
|
||||
))
|
||||
// val toplevel = new VexRiscv(configLight)
|
||||
// val toplevel = new VexRiscv(configTest)
|
||||
|
||||
/*toplevel.rework {
|
||||
var iBus : AvalonMM = null
|
||||
for (plugin <- toplevel.config.plugins) plugin match {
|
||||
case plugin: IBusSimplePlugin => {
|
||||
plugin.iBus.asDirectionLess() //Unset IO properties of iBus
|
||||
iBus = master(plugin.iBus.toAvalon())
|
||||
.setName("iBusAvalon")
|
||||
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
|
||||
}
|
||||
case plugin: IBusCachedPlugin => {
|
||||
plugin.iBus.asDirectionLess() //Unset IO properties of iBus
|
||||
iBus = master(plugin.iBus.toAvalon())
|
||||
.setName("iBusAvalon")
|
||||
.addTag(ClockDomainTag(ClockDomain.current)) //Specify a clock domain to the iBus (used by QSysify)
|
||||
}
|
||||
case plugin: DBusSimplePlugin => {
|
||||
plugin.dBus.asDirectionLess()
|
||||
master(plugin.dBus.toAvalon())
|
||||
.setName("dBusAvalon")
|
||||
.addTag(ClockDomainTag(ClockDomain.current))
|
||||
}
|
||||
case plugin: DBusCachedPlugin => {
|
||||
plugin.dBus.asDirectionLess()
|
||||
master(plugin.dBus.toAvalon())
|
||||
.setName("dBusAvalon")
|
||||
.addTag(ClockDomainTag(ClockDomain.current))
|
||||
}
|
||||
case plugin: DebugPlugin => {
|
||||
plugin.io.bus.asDirectionLess()
|
||||
slave(plugin.io.bus.fromAvalon())
|
||||
.setName("debugBusAvalon")
|
||||
.addTag(ClockDomainTag(plugin.debugClockDomain))
|
||||
.parent = null //Avoid the io bundle to be interpreted as a QSys conduit
|
||||
plugin.io.resetOut
|
||||
.addTag(ResetEmitterTag(plugin.debugClockDomain))
|
||||
.parent = null //Avoid the io bundle to be interpreted as a QSys conduit
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
for (plugin <- toplevel.config.plugins) plugin match {
|
||||
case plugin: CsrPlugin => {
|
||||
plugin.externalInterrupt
|
||||
.addTag(InterruptReceiverTag(iBus, ClockDomain.current))
|
||||
plugin.timerInterrupt
|
||||
.addTag(InterruptReceiverTag(iBus, ClockDomain.current))
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}*/
|
||||
// toplevel.writeBack.input(config.PC).addAttribute(Verilator.public)
|
||||
// toplevel.service(classOf[DecoderSimplePlugin]).bench(toplevel)
|
||||
// toplevel.children.find(_.isInstanceOf[DataCache]).get.asInstanceOf[DataCache].io.cpu.execute.addAttribute(Verilator.public)
|
||||
|
||||
|
||||
// toplevel.rework {
|
||||
// for (plugin <- toplevel.config.plugins) plugin match {
|
||||
// case plugin: IBusSimplePlugin => {
|
||||
// plugin.iBus.setAsDirectionLess().unsetName() //Unset IO properties of iBus
|
||||
// val iBus = master(IBusSimpleBus()).setName("iBus")
|
||||
//
|
||||
// iBus.cmd << plugin.iBus.cmd.halfPipe()
|
||||
// iBus.rsp.stage >> plugin.iBus.rsp
|
||||
// }
|
||||
// case plugin: DBusSimplePlugin => {
|
||||
// plugin.dBus.setAsDirectionLess().unsetName()
|
||||
// val dBus = master(DBusSimpleBus()).setName("dBus")
|
||||
// val pending = RegInit(False) setWhen(plugin.dBus.cmd.fire) clearWhen(plugin.dBus.rsp.ready)
|
||||
// dBus.cmd << plugin.dBus.cmd.haltWhen(pending).halfPipe()
|
||||
// plugin.dBus.rsp := RegNext(dBus.rsp)
|
||||
// plugin.dBus.rsp.ready clearWhen(!pending)
|
||||
// }
|
||||
//
|
||||
// case _ =>
|
||||
// }
|
||||
// }
|
||||
|
||||
toplevel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object LinuxSyntesisBench extends App{
|
||||
val withoutMmu = new Rtl {
|
||||
override def getName(): String = "VexRiscv Without Mmu"
|
||||
override def getRtlPath(): String = "VexRiscvWithoutMmu.v"
|
||||
SpinalConfig(inlineRom=true).generateVerilog(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = false)).setDefinitionName(getRtlPath().split("\\.").head))
|
||||
}
|
||||
|
||||
val withMmu = new Rtl {
|
||||
override def getName(): String = "VexRiscv With Mmu"
|
||||
override def getRtlPath(): String = "VexRiscvWithMmu.v"
|
||||
SpinalConfig(inlineRom=true).generateVerilog(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = true)).setDefinitionName(getRtlPath().split("\\.").head))
|
||||
}
|
||||
|
||||
val rtls = List(withoutMmu,withMmu)
|
||||
// val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache)
|
||||
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||
// val rtls = List(fullNoMmu)
|
||||
|
||||
val targets = XilinxStdTargets(
|
||||
vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin"
|
||||
) ++ AlteraStdTargets(
|
||||
quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin",
|
||||
quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin"
|
||||
) //++ IcestormStdTargets().take(1)
|
||||
|
||||
Bench(rtls, targets, "/media/miaou/HD/linux/tmp")
|
||||
}
|
||||
|
||||
object LinuxSim extends App{
|
||||
import spinal.core.sim._
|
||||
|
||||
SimConfig.allOptimisation.compile(new VexRiscv(LinuxGen.configFull(litex = false, withMmu = true))).doSim{dut =>
|
||||
// dut.clockDomain.forkStimulus(10)
|
||||
// dut.clockDomain.forkSimSpeedPrinter()
|
||||
// dut.plugins.foreach{
|
||||
// case p : IBusSimplePlugin => dut.clockDomain.onRisingEdges{
|
||||
// p.iBus.cmd.ready #= ! p.iBus.cmd.ready.toBoolean
|
||||
//// p.iBus.rsp.valid.randomize()
|
||||
//// p.iBus.rsp.inst.randomize()
|
||||
//// p.iBus.rsp.error.randomize()
|
||||
// }
|
||||
// case p : DBusSimplePlugin => dut.clockDomain.onRisingEdges{
|
||||
// p.dBus.cmd.ready #= ! p.dBus.cmd.ready.toBoolean
|
||||
//// p.dBus.cmd.ready.randomize()
|
||||
//// p.dBus.rsp.ready.randomize()
|
||||
//// p.dBus.rsp.data.randomize()
|
||||
//// p.dBus.rsp.error.randomize()
|
||||
// }
|
||||
// case _ =>
|
||||
// }
|
||||
// sleep(10*10000000)
|
||||
|
||||
|
||||
var cycleCounter = 0l
|
||||
var lastTime = System.nanoTime()
|
||||
|
||||
|
||||
|
||||
|
||||
var iBus : IBusSimpleBus = null
|
||||
var dBus : DBusSimpleBus = null
|
||||
dut.plugins.foreach{
|
||||
case p : IBusSimplePlugin =>
|
||||
iBus = p.iBus
|
||||
// p.iBus.rsp.valid.randomize()
|
||||
// p.iBus.rsp.inst.randomize()
|
||||
// p.iBus.rsp.error.randomize()
|
||||
case p : DBusSimplePlugin =>
|
||||
dBus = p.dBus
|
||||
// p.dBus.cmd.ready.randomize()
|
||||
// p.dBus.rsp.ready.randomize()
|
||||
// p.dBus.rsp.data.randomize()
|
||||
// p.dBus.rsp.error.randomize()
|
||||
case _ =>
|
||||
}
|
||||
|
||||
dut.clockDomain.resetSim #= false
|
||||
dut.clockDomain.clockSim #= false
|
||||
sleep(1)
|
||||
dut.clockDomain.resetSim #= true
|
||||
sleep(1)
|
||||
|
||||
def f(): Unit ={
|
||||
cycleCounter += 1
|
||||
|
||||
if((cycleCounter & 8191) == 0){
|
||||
val currentTime = System.nanoTime()
|
||||
val deltaTime = (currentTime - lastTime)*1e-9
|
||||
if(deltaTime > 2.0) {
|
||||
println(f"[Info] Simulation speed : ${cycleCounter / deltaTime * 1e-3}%4.0f kcycles/s")
|
||||
lastTime = currentTime
|
||||
cycleCounter = 0
|
||||
}
|
||||
}
|
||||
dut.clockDomain.clockSim #= false
|
||||
iBus.cmd.ready #= ! iBus.cmd.ready.toBoolean
|
||||
dBus.cmd.ready #= ! dBus.cmd.ready.toBoolean
|
||||
delayed(1)(f2)
|
||||
}
|
||||
def f2(): Unit ={
|
||||
dut.clockDomain.clockSim #= true
|
||||
delayed(1)(f)
|
||||
}
|
||||
|
||||
delayed(1)(f)
|
||||
|
||||
sleep(100000000)
|
||||
}
|
||||
}
|
|
@ -163,3 +163,8 @@ class MuraxApb3Timer extends Component{
|
|||
interruptCtrl.io.inputs(1) := timerB.io.full
|
||||
io.interrupt := interruptCtrl.io.pendings.orR
|
||||
}
|
||||
|
||||
|
||||
object MuraxApb3TimerGen extends App{
|
||||
SpinalVhdl(new MuraxApb3Timer())
|
||||
}
|
|
@ -101,31 +101,26 @@ object VexRiscvSynthesisBench {
|
|||
}
|
||||
|
||||
|
||||
val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||
val linuxBalanced = new Rtl {
|
||||
override def getName(): String = "VexRiscv linux balanced"
|
||||
override def getRtlPath(): String = "VexRiscvLinuxBalanced.v"
|
||||
SpinalConfig(inlineRom = true).generateVerilog(wrap(new VexRiscv(LinuxGen.configFull(false, true))).setDefinitionName(getRtlPath().split("\\.").head))
|
||||
}
|
||||
|
||||
val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full, linuxBalanced)
|
||||
// val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache)
|
||||
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||
// val rtls = List(fullNoMmu)
|
||||
// val rtls = List(smallAndProductive)
|
||||
|
||||
val targets = XilinxStdTargets(
|
||||
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||
vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin"
|
||||
) ++ AlteraStdTargets(
|
||||
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
||||
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
|
||||
quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin",
|
||||
quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin"
|
||||
) ++ IcestormStdTargets().take(1)
|
||||
|
||||
|
||||
// val targets = XilinxStdTargets(
|
||||
// vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||
// )
|
||||
|
||||
// val targets = AlteraStdTargets(
|
||||
// quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
|
||||
// quartusCycloneVPath = null
|
||||
// )
|
||||
|
||||
|
||||
// val targets = IcestormStdTargets()
|
||||
Bench(rtls, targets, "/eda/tmp")
|
||||
Bench(rtls, targets, "/media/miaou/HD/linux/tmp")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,13 +141,13 @@ object BrieySynthesisBench {
|
|||
val rtls = List(briey)
|
||||
|
||||
val targets = XilinxStdTargets(
|
||||
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||
vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin"
|
||||
) ++ AlteraStdTargets(
|
||||
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/",
|
||||
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/"
|
||||
quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin",
|
||||
quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin"
|
||||
)
|
||||
|
||||
Bench(rtls, targets, "/eda/tmp/")
|
||||
Bench(rtls, targets, "/media/miaou/HD/linux/tmp")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,14 +180,13 @@ object MuraxSynthesisBench {
|
|||
val rtls = List(murax, muraxFast)
|
||||
|
||||
val targets = IcestormStdTargets().take(1) ++ XilinxStdTargets(
|
||||
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
|
||||
vivadoArtix7Path = "/media/miaou/HD/linux/Xilinx/Vivado/2018.3/bin"
|
||||
) ++ AlteraStdTargets(
|
||||
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/",
|
||||
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/"
|
||||
quartusCycloneIVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin",
|
||||
quartusCycloneVPath = "/media/miaou/HD/linux/intelFPGA_lite/18.1/quartus/bin"
|
||||
)
|
||||
|
||||
|
||||
Bench(rtls, targets, "/eda/tmp/")
|
||||
Bench(rtls, targets, "/media/miaou/HD/linux/tmp")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ object VexRiscvAvalonForSim{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true
|
||||
)
|
||||
|
@ -67,8 +66,7 @@ object VexRiscvAvalonForSim{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -44,7 +44,6 @@ object VexRiscvAvalonWithIntegratedJtag{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
@ -64,8 +63,7 @@ object VexRiscvAvalonWithIntegratedJtag{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -45,7 +45,6 @@ object VexRiscvAxi4WithIntegratedJtag{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true,
|
||||
twoCycleCache = true
|
||||
|
@ -65,8 +64,7 @@ object VexRiscvAxi4WithIntegratedJtag{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -44,7 +44,6 @@ object VexRiscvCachedWishboneForSim{
|
|||
memDataWidth = 32,
|
||||
catchIllegalAccess = true,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = true,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = true
|
||||
)
|
||||
|
@ -63,8 +62,7 @@ object VexRiscvCachedWishboneForSim{
|
|||
memDataWidth = 32,
|
||||
catchAccessError = true,
|
||||
catchIllegal = true,
|
||||
catchUnaligned = true,
|
||||
catchMemoryTranslationMiss = true
|
||||
catchUnaligned = true
|
||||
),
|
||||
memoryTranslatorPortConfig = null
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
|
|
|
@ -8,24 +8,26 @@ import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
|||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||
import spinal.lib.bus.simple._
|
||||
|
||||
case class DataCacheConfig( cacheSize : Int,
|
||||
bytePerLine : Int,
|
||||
wayCount : Int,
|
||||
addressWidth : Int,
|
||||
cpuDataWidth : Int,
|
||||
memDataWidth : Int,
|
||||
catchAccessError : Boolean,
|
||||
catchIllegal : Boolean,
|
||||
catchUnaligned : Boolean,
|
||||
catchMemoryTranslationMiss : Boolean,
|
||||
clearTagsAfterReset : Boolean = true,
|
||||
waysHitRetime : Boolean = true,
|
||||
tagSizeShift : Int = 0, //Used to force infering ram
|
||||
atomicEntriesCount : Int = 0){
|
||||
|
||||
case class DataCacheConfig(cacheSize : Int,
|
||||
bytePerLine : Int,
|
||||
wayCount : Int,
|
||||
addressWidth : Int,
|
||||
cpuDataWidth : Int,
|
||||
memDataWidth : Int,
|
||||
catchAccessError : Boolean,
|
||||
catchIllegal : Boolean,
|
||||
catchUnaligned : Boolean,
|
||||
earlyWaysHits : Boolean = true,
|
||||
earlyDataMux : Boolean = false,
|
||||
tagSizeShift : Int = 0, //Used to force infering ram
|
||||
withLrSc : Boolean = false,
|
||||
withAmo : Boolean = false){
|
||||
|
||||
assert(!(earlyDataMux && !earlyWaysHits))
|
||||
def burstSize = bytePerLine*8/memDataWidth
|
||||
val burstLength = bytePerLine/(memDataWidth/8)
|
||||
def catchSomething = catchUnaligned || catchMemoryTranslationMiss || catchIllegal || catchAccessError
|
||||
def genAtomic = atomicEntriesCount != 0
|
||||
def catchSomething = catchUnaligned || catchIllegal || catchAccessError
|
||||
|
||||
def getAxi4SharedConfig() = Axi4Config(
|
||||
addressWidth = addressWidth,
|
||||
|
@ -64,121 +66,45 @@ case class DataCacheConfig( cacheSize : Int,
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
object Bypasser{
|
||||
|
||||
//shot readValid path
|
||||
def writeFirstMemWrap[T <: Data](readValid : Bool, readLastAddress : UInt, readLastData : T,writeValid : Bool, writeAddress : UInt, writeData : T) : T = {
|
||||
val writeSample = readValid || (writeValid && writeAddress === readLastAddress)
|
||||
val writeValidReg = RegNextWhen(writeValid,writeSample)
|
||||
val writeAddressReg = RegNextWhen(writeAddress,writeSample)
|
||||
val writeDataReg = RegNextWhen(writeData,writeSample)
|
||||
(writeValidReg && writeAddressReg === readLastAddress) ? writeDataReg | readLastData
|
||||
}
|
||||
|
||||
|
||||
//short readValid path
|
||||
def writeFirstMemWrap(readValid : Bool, readLastAddress : UInt, readLastData : Bits,writeValid : Bool, writeAddress : UInt, writeData : Bits,writeMask : Bits) : Bits = {
|
||||
val writeHit = writeValid && writeAddress === readLastAddress
|
||||
val writeSample = readValid || writeHit
|
||||
val writeValidReg = RegNextWhen(writeValid,writeSample)
|
||||
val writeAddressReg = RegNextWhen(writeAddress,writeSample)
|
||||
val writeDataReg = Reg(writeData)
|
||||
val writeMaskReg = Reg(Bits(widthOf(writeData)/8 bits))
|
||||
val writeDataRegBytes = writeDataReg.subdivideIn(8 bits)
|
||||
val writeDataBytes = writeData.subdivideIn(8 bits)
|
||||
val ret = cloneOf(readLastData)
|
||||
val retBytes = ret.subdivideIn(8 bits)
|
||||
val readLastDataBytes = readLastData.subdivideIn(8 bits)
|
||||
val writeRegHit = writeValidReg && writeAddressReg === readLastAddress
|
||||
for(b <- writeMask.range){
|
||||
when(writeHit && writeMask(b)){
|
||||
writeMaskReg(b) := True
|
||||
}
|
||||
when(readValid) {
|
||||
writeMaskReg(b) := writeMask(b)
|
||||
}
|
||||
when(readValid || (writeHit && writeMask(b))){
|
||||
writeDataRegBytes(b) := writeDataBytes(b)
|
||||
}
|
||||
|
||||
retBytes(b) := (writeRegHit && writeMaskReg(b)) ? writeDataRegBytes(b) | readLastDataBytes(b)
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
//Long sample path
|
||||
// def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,lastAddress : UInt, readData : T, writeValid : Bool, writeAddress : UInt, writeData : T) : (T,T) = {
|
||||
// val hit = writeValid && (sample ? sampleAddress | lastAddress) === writeAddress
|
||||
// val bypass = hit ? writeData | readData
|
||||
// val reg = RegNextWhen(bypass,sample || hit)
|
||||
// (reg,bypass)
|
||||
// }
|
||||
|
||||
//Short sample path
|
||||
def writeFirstRegWrap[T <: Data](sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, sampleData : T, writeValid : Bool, writeAddress : UInt, writeData : T) = {
|
||||
val bypass = (!sample || (writeValid && sampleAddress === writeAddress)) ? writeData | sampleData
|
||||
val regEn = sample || (writeValid && sampleLastAddress === writeAddress)
|
||||
val reg = RegNextWhen(bypass,regEn)
|
||||
reg
|
||||
}
|
||||
|
||||
def writeFirstRegWrap(sample : Bool, sampleAddress : UInt,sampleLastAddress : UInt, sampleData : Bits, writeValid : Bool, writeAddress : UInt, writeData : Bits,writeMask : Bits) = {
|
||||
val byteCount = widthOf(writeMask)
|
||||
val sampleWriteHit = writeValid && sampleAddress === writeAddress
|
||||
val sampleLastHit = writeValid && sampleLastAddress === writeAddress
|
||||
val regBytes = Vec(Bits(8 bits),byteCount)
|
||||
for(b <- writeMask.range){
|
||||
val bypass = Mux(!sample || (sampleWriteHit && writeMask(b)), writeData(b*8, 8 bits), sampleData(b*8, 8 bits))
|
||||
val regEn = sample || (sampleLastHit && writeMask(b))
|
||||
regBytes(b) := RegNextWhen(bypass,regEn)
|
||||
}
|
||||
regBytes.asBits
|
||||
}
|
||||
}
|
||||
|
||||
object DataCacheCpuCmdKind extends SpinalEnum{
|
||||
val MEMORY,MANAGMENT = newElement()
|
||||
}
|
||||
|
||||
object DataCacheCpuExecute{
|
||||
implicit def implArgs(that : DataCacheCpuExecute) = that.args
|
||||
}
|
||||
|
||||
case class DataCacheCpuExecute(p : DataCacheConfig) extends Bundle with IMasterSlave{
|
||||
val isValid = Bool
|
||||
val isStuck = Bool
|
||||
val address = UInt(p.addressWidth bit)
|
||||
// val haltIt = Bool
|
||||
val args = DataCacheCpuExecuteArgs(p)
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid, isStuck, args)
|
||||
out(isValid, args, address)
|
||||
// in(haltIt)
|
||||
}
|
||||
}
|
||||
|
||||
case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
|
||||
val kind = DataCacheCpuCmdKind()
|
||||
val wr = Bool
|
||||
val address = UInt(p.addressWidth bit)
|
||||
val data = Bits(p.cpuDataWidth bit)
|
||||
val size = UInt(2 bits)
|
||||
val forceUncachedAccess = Bool
|
||||
val clean, invalidate, way = Bool
|
||||
val isAtomic = ifGen(p.genAtomic){Bool}
|
||||
// val all = Bool //Address should be zero when "all" is used
|
||||
val isLrsc = p.withLrSc generate Bool()
|
||||
val isAmo = p.withAmo generate Bool()
|
||||
val amoCtrl = p.withAmo generate new Bundle {
|
||||
val swap = Bool()
|
||||
val alu = Bits(3 bits)
|
||||
}
|
||||
}
|
||||
|
||||
case class DataCacheCpuMemory(p : DataCacheConfig) extends Bundle with IMasterSlave{
|
||||
val isValid = Bool
|
||||
val isStuck = Bool
|
||||
val isRemoved = Bool
|
||||
val haltIt = Bool
|
||||
val isWrite = Bool
|
||||
val address = UInt(p.addressWidth bit)
|
||||
val mmuBus = MemoryTranslatorBus()
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid, isStuck, isRemoved)
|
||||
in(haltIt)
|
||||
out(isValid, isStuck, isRemoved, address)
|
||||
in(isWrite)
|
||||
slave(mmuBus)
|
||||
}
|
||||
}
|
||||
|
@ -189,16 +115,18 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
|
|||
val isStuck = Bool
|
||||
val isUser = Bool
|
||||
val haltIt = Bool
|
||||
val isWrite = Bool
|
||||
val data = Bits(p.cpuDataWidth bit)
|
||||
val mmuMiss, illegalAccess, unalignedAccess , accessError = Bool
|
||||
val badAddr = UInt(32 bits)
|
||||
val clearAtomicEntries = ifGen(p.genAtomic) {Bool}
|
||||
val address = UInt(p.addressWidth bit)
|
||||
val mmuException, unalignedAccess , accessError = Bool
|
||||
val clearLrsc = ifGen(p.withLrSc) {Bool}
|
||||
|
||||
// val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid,isStuck,isUser)
|
||||
in(haltIt, data, mmuMiss,illegalAccess , unalignedAccess, accessError, badAddr)
|
||||
outWithNull(clearAtomicEntries)
|
||||
out(isValid,isStuck,isUser, address)
|
||||
in(haltIt, data, mmuException, unalignedAccess, accessError, isWrite)
|
||||
outWithNull(clearLrsc)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,10 +135,15 @@ case class DataCacheCpuBus(p : DataCacheConfig) extends Bundle with IMasterSlave
|
|||
val memory = DataCacheCpuMemory(p)
|
||||
val writeBack = DataCacheCpuWriteBack(p)
|
||||
|
||||
val redo = Bool()
|
||||
val flush = Event
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
master(execute)
|
||||
master(memory)
|
||||
master(writeBack)
|
||||
master(flush)
|
||||
in(redo)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,8 +303,6 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
|
|||
|
||||
class DataCache(p : DataCacheConfig) extends Component{
|
||||
import p._
|
||||
import DataCacheCpuCmdKind._
|
||||
assert(wayCount == 1)
|
||||
assert(cpuDataWidth == memDataWidth)
|
||||
|
||||
val io = new Bundle{
|
||||
|
@ -379,6 +310,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
val mem = master(DataCacheMemBus(p))
|
||||
// val flushDone = out Bool //It pulse at the same time than the manager.request.fire
|
||||
}
|
||||
|
||||
val haltCpu = False
|
||||
val lineWidth = bytePerLine*8
|
||||
val lineCount = cacheSize/bytePerLine
|
||||
|
@ -397,14 +329,13 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
|
||||
class LineInfo() extends Bundle{
|
||||
val used = Bool
|
||||
val dirty = Bool
|
||||
val valid, error = Bool()
|
||||
val address = UInt(tagRange.length bit)
|
||||
}
|
||||
|
||||
val tagsReadCmd = Flow(UInt(log2Up(wayLineCount) bits))
|
||||
val tagsWriteCmd = Flow(new Bundle{
|
||||
// val way = UInt(log2Up(wayCount) bits)
|
||||
val way = Bits(wayCount bits)
|
||||
val address = UInt(log2Up(wayLineCount) bits)
|
||||
val data = new LineInfo()
|
||||
})
|
||||
|
@ -413,13 +344,36 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
val dataReadCmd = Flow(UInt(log2Up(wayWordCount) bits))
|
||||
val dataWriteCmd = Flow(new Bundle{
|
||||
// val way = UInt(log2Up(wayCount) bits)
|
||||
val way = Bits(wayCount bits)
|
||||
val address = UInt(log2Up(wayWordCount) bits)
|
||||
val data = Bits(wordWidth bits)
|
||||
val mask = Bits(wordWidth/8 bits)
|
||||
})
|
||||
|
||||
|
||||
|
||||
val ways = for(i <- 0 until wayCount) yield new Area{
|
||||
val tags = Mem(new LineInfo(), wayLineCount)
|
||||
val data = Mem(Bits(wordWidth bit), wayWordCount)
|
||||
|
||||
//Reads
|
||||
val tagsReadRsp = tags.readSync(tagsReadCmd.payload, tagsReadCmd.valid && !io.cpu.memory.isStuck)
|
||||
val dataReadRsp = data.readSync(dataReadCmd.payload, dataReadCmd.valid && !io.cpu.memory.isStuck)
|
||||
|
||||
//Writes
|
||||
when(tagsWriteCmd.valid && tagsWriteCmd.way(i)){
|
||||
tags(tagsWriteCmd.address) := tagsWriteCmd.data
|
||||
}
|
||||
when(dataWriteCmd.valid && dataWriteCmd.way(i)){
|
||||
data.write(
|
||||
address = dataWriteCmd.address,
|
||||
data = dataWriteCmd.data,
|
||||
mask = dataWriteCmd.mask
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tagsReadCmd.valid := False
|
||||
tagsReadCmd.payload.assignDontCare()
|
||||
dataReadCmd.valid := False
|
||||
|
@ -428,376 +382,270 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
tagsWriteCmd.payload.assignDontCare()
|
||||
dataWriteCmd.valid := False
|
||||
dataWriteCmd.payload.assignDontCare()
|
||||
io.mem.cmd.valid := False
|
||||
io.mem.cmd.payload.assignDontCare()
|
||||
|
||||
|
||||
val way = new Area{
|
||||
val tags = Mem(new LineInfo(),wayLineCount)
|
||||
val data = Mem(Bits(wordWidth bit),wayWordCount)
|
||||
|
||||
when(tagsWriteCmd.valid){
|
||||
tags(tagsWriteCmd.address) := tagsWriteCmd.data
|
||||
}
|
||||
when(dataWriteCmd.valid){
|
||||
data.write(
|
||||
address = dataWriteCmd.address,
|
||||
data = dataWriteCmd.data,
|
||||
mask = dataWriteCmd.mask
|
||||
)
|
||||
}
|
||||
|
||||
val tagReadRspOneAddress = RegNextWhen(tagsReadCmd.payload, tagsReadCmd.valid)
|
||||
val tagReadRspOne = Bypasser.writeFirstMemWrap(
|
||||
readValid = tagsReadCmd.valid,
|
||||
readLastAddress = tagReadRspOneAddress,
|
||||
readLastData = tags.readSync(tagsReadCmd.payload,enable = tagsReadCmd.valid),
|
||||
writeValid = tagsWriteCmd.valid,
|
||||
writeAddress = tagsWriteCmd.address,
|
||||
writeData = tagsWriteCmd.data
|
||||
)
|
||||
|
||||
val dataReadRspOneKeepAddress = False
|
||||
val dataReadRspOneAddress = RegNextWhen(dataReadCmd.payload, dataReadCmd.valid && !dataReadRspOneKeepAddress)
|
||||
val dataReadRspOneWithoutBypass = data.readSync(dataReadCmd.payload,enable = dataReadCmd.valid)
|
||||
val dataReadRspOne = Bypasser.writeFirstMemWrap(
|
||||
readValid = dataReadCmd.valid,
|
||||
readLastAddress = dataReadRspOneAddress,
|
||||
readLastData = dataReadRspOneWithoutBypass,
|
||||
writeValid = dataWriteCmd.valid,
|
||||
writeAddress = dataWriteCmd.address,
|
||||
writeData = dataWriteCmd.data,
|
||||
writeMask = dataWriteCmd.mask
|
||||
)
|
||||
|
||||
val tagReadRspTwoEnable = !io.cpu.writeBack.isStuck
|
||||
val tagReadRspTwoRegIn = (tagsWriteCmd.valid && tagsWriteCmd.address === tagReadRspOneAddress) ? tagsWriteCmd.data | tagReadRspOne
|
||||
val tagReadRspTwo = RegNextWhen(tagReadRspTwoRegIn ,tagReadRspTwoEnable)
|
||||
|
||||
|
||||
val dataReadRspTwoEnable = !io.cpu.writeBack.isStuck
|
||||
val dataReadRspTwo = Bypasser.writeFirstRegWrap(
|
||||
sample = dataReadRspTwoEnable,
|
||||
sampleAddress = dataReadRspOneAddress,
|
||||
sampleLastAddress = RegNextWhen(dataReadRspOneAddress, dataReadRspTwoEnable),
|
||||
sampleData = dataReadRspOne,
|
||||
writeValid = dataWriteCmd.valid,
|
||||
writeAddress = dataWriteCmd.address,
|
||||
writeData = dataWriteCmd.data,
|
||||
writeMask = dataWriteCmd.mask
|
||||
)
|
||||
}
|
||||
|
||||
when(io.cpu.execute.isValid && !io.cpu.execute.isStuck){
|
||||
tagsReadCmd.valid := True
|
||||
when(io.cpu.execute.isValid && !io.cpu.memory.isStuck){
|
||||
tagsReadCmd.valid := True
|
||||
dataReadCmd.valid := True
|
||||
tagsReadCmd.payload := io.cpu.execute.address(lineRange)
|
||||
|
||||
dataReadCmd.valid := True
|
||||
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low) //TODO FMAX maybe critical path could be default
|
||||
dataReadCmd.payload := io.cpu.execute.address(lineRange.high downto wordRange.low)
|
||||
}
|
||||
|
||||
|
||||
val cpuMemoryStageNeedReadData = Bool()
|
||||
|
||||
val victim = new Area{
|
||||
val requestIn = Stream(cloneable(new Bundle{
|
||||
// val way = UInt(log2Up(wayCount) bits)
|
||||
val address = UInt(p.addressWidth bits)
|
||||
}))
|
||||
requestIn.valid := False
|
||||
requestIn.payload.assignDontCare()
|
||||
|
||||
val request = requestIn.halfPipe()
|
||||
request.ready := False
|
||||
|
||||
val buffer = Mem(Bits(p.memDataWidth bits),memTransactionPerLine << tagSizeShift) // WARNING << tagSizeShift could resolve cyclone II issue, //.add(new AttributeString("ramstyle","M4K"))
|
||||
|
||||
//Send line read commands to fill the buffer
|
||||
val readLineCmdCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
|
||||
val dataReadCmdOccure = False
|
||||
val dataReadRestored = RegInit(False)
|
||||
when(request.valid){
|
||||
when(!readLineCmdCounter.msb) {
|
||||
readLineCmdCounter := readLineCmdCounter + 1
|
||||
//dataReadCmd := request.address(lineRange.high downto wordRange.low) Done in the manager
|
||||
dataReadCmdOccure := True
|
||||
dataReadCmd.valid := True
|
||||
dataReadCmd.payload := request.address(lineRange) @@ readLineCmdCounter(readLineCmdCounter.high - 1 downto 0)
|
||||
way.dataReadRspOneKeepAddress := True
|
||||
} otherwise {
|
||||
when(!dataReadRestored && cpuMemoryStageNeedReadData) {
|
||||
dataReadCmd.valid := True
|
||||
dataReadCmd.payload := way.dataReadRspOneAddress //Restore stage one readed value
|
||||
}
|
||||
dataReadRestored := True
|
||||
}
|
||||
}
|
||||
|
||||
dataReadRestored clearWhen(request.ready)
|
||||
io.cpu.memory.haltIt := cpuMemoryStageNeedReadData && request.valid && !dataReadRestored
|
||||
|
||||
//Fill the buffer with line read responses
|
||||
val readLineRspCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
|
||||
when(Delay(dataReadCmdOccure,1, init=False)){
|
||||
buffer(readLineRspCounter.resized) := way.dataReadRspOneWithoutBypass
|
||||
readLineRspCounter := readLineRspCounter + 1
|
||||
}
|
||||
|
||||
//Send buffer read commands
|
||||
val bufferReadCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
|
||||
val bufferReadStream = Stream(buffer.addressType)
|
||||
bufferReadStream.valid := readLineRspCounter > bufferReadCounter
|
||||
bufferReadStream.payload := bufferReadCounter.resized
|
||||
when(bufferReadStream.fire){
|
||||
bufferReadCounter := bufferReadCounter + 1
|
||||
}
|
||||
val bufferReaded = buffer.streamReadSync(bufferReadStream).stage
|
||||
bufferReaded.ready := False
|
||||
|
||||
//Send memory writes from bufffer read responses
|
||||
val bufferReadedCounter = Reg(UInt(log2Up(memTransactionPerLine) bits)) init(0)
|
||||
val memCmdAlreadyUsed = False
|
||||
when(bufferReaded.valid) {
|
||||
io.mem.cmd.valid := True
|
||||
io.mem.cmd.wr := True
|
||||
io.mem.cmd.address := request.address(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
|
||||
io.mem.cmd.length := p.burstLength-1
|
||||
io.mem.cmd.data := bufferReaded.payload
|
||||
io.mem.cmd.mask := (1<<(wordWidth/8))-1
|
||||
io.mem.cmd.last := bufferReadedCounter === bufferReadedCounter.maxValue
|
||||
|
||||
when(!memCmdAlreadyUsed && io.mem.cmd.ready){
|
||||
bufferReaded.ready := True
|
||||
bufferReadedCounter := bufferReadedCounter + 1
|
||||
when(bufferReadedCounter === bufferReadedCounter.maxValue){
|
||||
request.ready := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val counter = Counter(memTransactionPerLine)
|
||||
when(request.ready){
|
||||
readLineCmdCounter.msb := False
|
||||
readLineRspCounter.msb := False
|
||||
bufferReadCounter.msb := False
|
||||
def collisionProcess(readAddress : UInt, readMask : Bits): Bits ={
|
||||
val ret = Bits(wayCount bits)
|
||||
for(i <- 0 until wayCount){
|
||||
ret(i) := dataWriteCmd.valid && dataWriteCmd.way(i) && dataWriteCmd.address === readAddress && (readMask & dataWriteCmd.mask) =/= 0
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
|
||||
val stageA = new Area{
|
||||
val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck)
|
||||
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid && request.kind === MEMORY //TODO filter request kind
|
||||
io.cpu.memory.mmuBus.cmd.virtualAddress := request.address
|
||||
io.cpu.memory.mmuBus.cmd.bypassTranslation := request.way
|
||||
io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved
|
||||
cpuMemoryStageNeedReadData := io.cpu.memory.isValid && request.kind === MEMORY && !request.wr
|
||||
}
|
||||
|
||||
val stageB = new Area {
|
||||
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
|
||||
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck)
|
||||
val waysHit = if(waysHitRetime)
|
||||
RegNextWhen(way.tagReadRspTwoRegIn.used && io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming
|
||||
else
|
||||
way.tagReadRspTwo.used && mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwo.address
|
||||
|
||||
|
||||
//Loader interface
|
||||
val loaderValid = False
|
||||
val loaderReady = False
|
||||
val loadingDone = RegNext(loaderValid && loaderReady) init(False) //one cycle pulse
|
||||
|
||||
//delayedXX are used to relax logic timings in flush and evict modes
|
||||
val delayedIsStuck = RegNext(io.cpu.writeBack.isStuck)
|
||||
val delayedWaysHitValid = RegNext(waysHit)
|
||||
|
||||
val victimNotSent = RegInit(False) clearWhen(victim.requestIn.ready) setWhen(!io.cpu.memory.isStuck)
|
||||
val loadingNotDone = RegInit(False) clearWhen(loaderReady) setWhen(!io.cpu.memory.isStuck)
|
||||
|
||||
val writeMask = request.size.mux (
|
||||
val stage0 = new Area{
|
||||
val mask = io.cpu.execute.size.mux (
|
||||
U(0) -> B"0001",
|
||||
U(1) -> B"0011",
|
||||
default -> B"1111"
|
||||
) |<< mmuRsp.physicalAddress(1 downto 0)
|
||||
) |<< io.cpu.execute.address(1 downto 0)
|
||||
val colisions = collisionProcess(io.cpu.execute.address(lineRange.high downto wordRange.low), mask)
|
||||
}
|
||||
|
||||
val stageA = new Area{
|
||||
def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.memory.isStuck)
|
||||
val request = stagePipe(io.cpu.execute.args)
|
||||
val mask = stagePipe(stage0.mask)
|
||||
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid
|
||||
io.cpu.memory.mmuBus.cmd.virtualAddress := io.cpu.memory.address
|
||||
io.cpu.memory.mmuBus.cmd.bypassTranslation := False
|
||||
io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved
|
||||
io.cpu.memory.isWrite := request.wr
|
||||
|
||||
val wayHits = earlyWaysHits generate ways.map(way => (io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid))
|
||||
val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp))
|
||||
val colisions = stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) //Assume the writeback stage will never be unstall memory acces while memory stage is stalled
|
||||
}
|
||||
|
||||
val stageB = new Area {
|
||||
def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.writeBack.isStuck)
|
||||
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
|
||||
val mmuRspFreeze = False
|
||||
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze)
|
||||
val tagsReadRsp = ways.map(w => stagePipe(w.tagsReadRsp))
|
||||
val dataReadRsp = !earlyDataMux generate ways.map(w => stagePipe(w.dataReadRsp))
|
||||
val waysHits = if(earlyWaysHits) stagePipe(B(stageA.wayHits)) else B(tagsReadRsp.map(tag => mmuRsp.physicalAddress(tagRange) === tag.address && tag.valid).asBits())
|
||||
val waysHit = waysHits.orR
|
||||
val dataMux = if(earlyDataMux) stagePipe(stageA.dataMux) else MuxOH(waysHits, dataReadRsp)
|
||||
val mask = stagePipe(stageA.mask)
|
||||
val colisions = stagePipe(stageA.colisions)
|
||||
|
||||
//Loader interface
|
||||
val loaderValid = False
|
||||
|
||||
|
||||
val hadMemRspErrorReg = RegInit(False)
|
||||
val hadMemRspError = (io.mem.rsp.valid && io.mem.rsp.error) || hadMemRspErrorReg
|
||||
hadMemRspErrorReg := hadMemRspError && io.cpu.writeBack.haltIt
|
||||
|
||||
io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid
|
||||
io.cpu.writeBack.mmuMiss := False
|
||||
io.cpu.writeBack.illegalAccess := False
|
||||
io.cpu.writeBack.unalignedAccess := False
|
||||
io.cpu.writeBack.accessError := (if(catchAccessError) hadMemRspError && !io.cpu.writeBack.haltIt else False)
|
||||
io.cpu.writeBack.badAddr := request.address
|
||||
|
||||
//Evict the cache after reset logics
|
||||
val bootEvicts = if(clearTagsAfterReset) new Area {
|
||||
val flusher = new Area {
|
||||
val valid = RegInit(True)
|
||||
mmuRsp.physicalAddress init (0)
|
||||
when(valid) {
|
||||
tagsWriteCmd.valid := valid
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := False
|
||||
when(mmuRsp.physicalAddress(lineRange) =/= lineCount - 1) {
|
||||
tagsWriteCmd.way.setAll()
|
||||
tagsWriteCmd.data.valid := False
|
||||
io.cpu.writeBack.haltIt := True
|
||||
when(mmuRsp.physicalAddress(lineRange) =/= wayLineCount - 1) {
|
||||
mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
|
||||
io.cpu.writeBack.haltIt := True
|
||||
} otherwise {
|
||||
valid := False
|
||||
}
|
||||
}
|
||||
|
||||
io.cpu.flush.ready := False
|
||||
when(io.cpu.flush.valid && !io.cpu.execute.isValid && !io.cpu.memory.isValid && !io.cpu.writeBack.isValid && !io.cpu.redo){
|
||||
io.cpu.flush.ready := True
|
||||
mmuRsp.physicalAddress.getDrivingReg(lineRange) := 0
|
||||
valid := True
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val atomic = if(genAtomic) new Area{
|
||||
case class AtomicEntry() extends Bundle{
|
||||
val valid = Bool()
|
||||
val size = UInt(2 bits)
|
||||
val address = UInt(addressWidth bits)
|
||||
val lrsc = withLrSc generate new Area{
|
||||
val reserved = RegInit(False)
|
||||
when(io.cpu.writeBack.isValid && !io.cpu.writeBack.isStuck && !io.cpu.redo && request.isLrsc && !request.wr){
|
||||
reserved := True
|
||||
}
|
||||
when(io.cpu.writeBack.clearLrsc){
|
||||
reserved := False
|
||||
}
|
||||
}
|
||||
|
||||
def init: this.type ={
|
||||
valid init(False)
|
||||
this
|
||||
}
|
||||
}
|
||||
val entries = Vec(Reg(AtomicEntry()).init, atomicEntriesCount)
|
||||
val entriesAllocCounter = Counter(atomicEntriesCount)
|
||||
val entriesHit = entries.map(e => e.valid && e.size === request.size && e.address === request.address).orR
|
||||
when(io.cpu.writeBack.isValid && request.isAtomic && !request.wr){
|
||||
entries(entriesAllocCounter).valid := True
|
||||
entries(entriesAllocCounter).size := request.size
|
||||
entries(entriesAllocCounter).address := request.address
|
||||
when(!io.cpu.writeBack.isStuck){
|
||||
entriesAllocCounter.increment()
|
||||
}
|
||||
}
|
||||
when(io.cpu.writeBack.clearAtomicEntries){
|
||||
entries.foreach(_.valid := False)
|
||||
}
|
||||
val requestDataBypass = CombInit(request.data)
|
||||
val isAmo = if(withAmo) request.isAmo else False
|
||||
val amo = withAmo generate new Area{
|
||||
def rf = request.data
|
||||
def mem = dataMux
|
||||
|
||||
when(request.isAtomic && ! entriesHit){
|
||||
writeMask := 0
|
||||
}
|
||||
} else null
|
||||
val compare = request.amoCtrl.alu.msb
|
||||
val unsigned = request.amoCtrl.alu(2 downto 1) === B"11"
|
||||
val addSub = (rf.asSInt + Mux(compare, ~mem, mem).asSInt + Mux(compare, S(1), S(0))).asBits
|
||||
val less = Mux(rf.msb === mem.msb, addSub.msb, Mux(unsigned, mem.msb, rf.msb))
|
||||
val selectRf = request.amoCtrl.swap ? True | (request.amoCtrl.alu.lsb ^ less)
|
||||
|
||||
val result = (request.amoCtrl.alu | (request.amoCtrl.swap ## B"00")).mux(
|
||||
B"000" -> addSub,
|
||||
B"001" -> (rf ^ mem),
|
||||
B"010" -> (rf | mem),
|
||||
B"011" -> (rf & mem),
|
||||
default -> (selectRf ? rf | mem)
|
||||
)
|
||||
val resultRegValid = RegNext(True) clearWhen(!io.cpu.writeBack.isStuck)
|
||||
val resultReg = RegNext(result)
|
||||
}
|
||||
|
||||
|
||||
val memCmdSent = RegInit(False) setWhen (io.mem.cmd.ready) clearWhen (!io.cpu.writeBack.isStuck)
|
||||
io.cpu.redo := False
|
||||
io.cpu.writeBack.accessError := False
|
||||
io.cpu.writeBack.mmuException := io.cpu.writeBack.isValid && (if(catchIllegal) mmuRsp.exception || (!mmuRsp.allowWrite && request.wr) || (!mmuRsp.allowRead && (!request.wr || isAmo)) else False)
|
||||
io.cpu.writeBack.unalignedAccess := io.cpu.writeBack.isValid && (if(catchUnaligned) ((request.size === 2 && mmuRsp.physicalAddress(1 downto 0) =/= 0) || (request.size === 1 && mmuRsp.physicalAddress(0 downto 0) =/= 0)) else False)
|
||||
io.cpu.writeBack.isWrite := request.wr
|
||||
|
||||
io.mem.cmd.valid := False
|
||||
io.mem.cmd.address.assignDontCare()
|
||||
io.mem.cmd.length.assignDontCare()
|
||||
io.mem.cmd.last.assignDontCare()
|
||||
io.mem.cmd.wr := request.wr
|
||||
io.mem.cmd.mask := mask
|
||||
io.mem.cmd.data := requestDataBypass
|
||||
|
||||
when(io.cpu.writeBack.isValid) {
|
||||
if (catchMemoryTranslationMiss) {
|
||||
io.cpu.writeBack.mmuMiss := mmuRsp.miss
|
||||
}
|
||||
switch(request.kind) {
|
||||
is(MANAGMENT) {
|
||||
when(delayedIsStuck && !mmuRsp.miss) {
|
||||
when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) {
|
||||
io.cpu.writeBack.haltIt.clearWhen(!(victim.requestIn.valid && !victim.requestIn.ready))
|
||||
victim.requestIn.valid := request.clean && way.tagReadRspTwo.dirty
|
||||
tagsWriteCmd.valid := victim.requestIn.ready
|
||||
} otherwise{
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
}
|
||||
when(mmuRsp.isIoAccess) {
|
||||
io.cpu.writeBack.haltIt.clearWhen(request.wr ? io.mem.cmd.ready | io.mem.rsp.valid)
|
||||
|
||||
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := !request.invalidate
|
||||
tagsWriteCmd.data.dirty := !request.clean
|
||||
io.mem.cmd.valid := !memCmdSent
|
||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
|
||||
io.mem.cmd.length := 0
|
||||
io.mem.cmd.last := True
|
||||
|
||||
if(withLrSc) when(request.isLrsc && !lrsc.reserved){
|
||||
io.mem.cmd.valid := False
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
is(MEMORY) {
|
||||
val illegal = if(catchIllegal) (request.wr && !mmuRsp.allowWrite) || (!request.wr && !mmuRsp.allowRead) || (io.cpu.writeBack.isUser && !mmuRsp.allowUser) else False
|
||||
val unaligned = if(catchUnaligned) ((request.size === 2 && mmuRsp.physicalAddress(1 downto 0) =/= 0) || (request.size === 1 && mmuRsp.physicalAddress(0 downto 0) =/= 0)) else False
|
||||
io.cpu.writeBack.illegalAccess := illegal
|
||||
io.cpu.writeBack.unalignedAccess := unaligned
|
||||
when((Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) && !illegal && !unaligned) {
|
||||
when(request.forceUncachedAccess || mmuRsp.isIoAccess) {
|
||||
val memCmdSent = RegInit(False)
|
||||
when(!victim.request.valid) {
|
||||
//Avoid mixing memory request while victim is pending
|
||||
io.mem.cmd.wr := request.wr
|
||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
|
||||
io.mem.cmd.mask := writeMask
|
||||
io.mem.cmd.data := request.data
|
||||
io.mem.cmd.length := 0
|
||||
io.mem.cmd.last := True
|
||||
} otherwise {
|
||||
when(waysHit || request.wr && !isAmo) { //Do not require a cache refill ?
|
||||
//Data cache update
|
||||
dataWriteCmd.valid setWhen(request.wr && waysHit)
|
||||
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
|
||||
dataWriteCmd.data := requestDataBypass
|
||||
dataWriteCmd.mask := mask
|
||||
dataWriteCmd.way := waysHits
|
||||
|
||||
when(!memCmdSent) {
|
||||
io.mem.cmd.valid := True
|
||||
memCmdSent setWhen (io.mem.cmd.ready)
|
||||
}
|
||||
//Write through
|
||||
io.mem.cmd.valid setWhen(request.wr)
|
||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
|
||||
io.mem.cmd.length := 0
|
||||
io.mem.cmd.last := True
|
||||
io.cpu.writeBack.haltIt clearWhen(!request.wr || io.mem.cmd.ready)
|
||||
|
||||
io.cpu.writeBack.haltIt.clearWhen(memCmdSent && (io.mem.rsp.fire || request.wr)) //Cut mem.cmd.ready path but insert one cycle stall when write
|
||||
}
|
||||
memCmdSent clearWhen (!io.cpu.writeBack.isStuck)
|
||||
} otherwise {
|
||||
when(waysHit || !loadingNotDone) {
|
||||
io.cpu.writeBack.haltIt := False
|
||||
dataWriteCmd.valid := request.wr
|
||||
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
|
||||
dataWriteCmd.data := request.data
|
||||
dataWriteCmd.mask := writeMask
|
||||
|
||||
tagsWriteCmd.valid := (!loadingNotDone) || request.wr
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := True
|
||||
tagsWriteCmd.data.dirty := request.wr
|
||||
tagsWriteCmd.data.address := mmuRsp.physicalAddress(tagRange)
|
||||
} otherwise {
|
||||
val victimRequired = way.tagReadRspTwo.used && way.tagReadRspTwo.dirty
|
||||
loaderValid := loadingNotDone && !(victimNotSent && victim.request.isStall) //Additional condition used to be sure of that all previous victim are written into the RAM
|
||||
victim.requestIn.valid := victimRequired && victimNotSent
|
||||
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
|
||||
}
|
||||
if(withAmo) when(isAmo){
|
||||
when(!amo.resultRegValid) {
|
||||
io.mem.cmd.valid := False
|
||||
dataWriteCmd.valid := False
|
||||
io.cpu.writeBack.haltIt := True
|
||||
}
|
||||
}
|
||||
|
||||
//On write to read colisions
|
||||
when((!request.wr || isAmo) && (colisions & waysHits) =/= 0){
|
||||
io.cpu.redo := True
|
||||
if(withAmo) io.mem.cmd.valid := False
|
||||
}
|
||||
|
||||
if(withLrSc) when(request.isLrsc && !lrsc.reserved){
|
||||
io.mem.cmd.valid := False
|
||||
dataWriteCmd.valid := False
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
} otherwise { //Do refill
|
||||
//Emit cmd
|
||||
io.mem.cmd.valid setWhen(!memCmdSent)
|
||||
io.mem.cmd.wr := False
|
||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
|
||||
io.mem.cmd.length := p.burstLength-1
|
||||
io.mem.cmd.last := True
|
||||
|
||||
loaderValid setWhen(io.mem.cmd.ready)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(mmuRsp.isIoAccess){
|
||||
io.cpu.writeBack.data := io.mem.rsp.data
|
||||
if(catchAccessError) io.cpu.writeBack.accessError := io.mem.rsp.valid && io.mem.rsp.error
|
||||
} otherwise {
|
||||
io.cpu.writeBack.data := dataMux
|
||||
if(catchAccessError) io.cpu.writeBack.accessError := (waysHits & B(tagsReadRsp.map(_.error))) =/= 0
|
||||
}
|
||||
|
||||
//remove side effects on exceptions
|
||||
when(mmuRsp.refilling || io.cpu.writeBack.accessError || io.cpu.writeBack.mmuException || io.cpu.writeBack.unalignedAccess){
|
||||
io.mem.cmd.valid := False
|
||||
tagsWriteCmd.valid := False
|
||||
dataWriteCmd.valid := False
|
||||
loaderValid := False
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
io.cpu.redo setWhen(io.cpu.writeBack.isValid && mmuRsp.refilling)
|
||||
|
||||
assert(!(io.cpu.writeBack.isValid && !io.cpu.writeBack.haltIt && io.cpu.writeBack.isStuck), "writeBack stuck by another plugin is not allowed")
|
||||
io.cpu.writeBack.data := (request.forceUncachedAccess || mmuRsp.isIoAccess) ? io.mem.rsp.data | way.dataReadRspTwo //not multi ways
|
||||
if(genAtomic){
|
||||
when(request.isAtomic && request.wr){
|
||||
io.cpu.writeBack.data := (!atomic.entriesHit).asBits.resized
|
||||
|
||||
if(withLrSc){
|
||||
when(request.isLrsc && request.wr){
|
||||
io.cpu.writeBack.data := (!lrsc.reserved).asBits.resized
|
||||
}
|
||||
}
|
||||
if(withAmo){
|
||||
when(request.isAmo){
|
||||
requestDataBypass := amo.resultReg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//The whole life of a loading task, the corresponding manager request is present
|
||||
val loader = new Area{
|
||||
val valid = RegNext(stageB.loaderValid) init(False)
|
||||
val valid = RegInit(False) setWhen(stageB.loaderValid)
|
||||
val baseAddress = stageB.mmuRsp.physicalAddress
|
||||
|
||||
val memCmdSent = RegInit(False)
|
||||
when(valid && !memCmdSent) {
|
||||
io.mem.cmd.valid := True
|
||||
io.mem.cmd.wr := False
|
||||
io.mem.cmd.address := baseAddress(tagRange.high downto lineRange.low) @@ U(0,lineRange.low bit)
|
||||
io.mem.cmd.length := p.burstLength-1
|
||||
io.mem.cmd.last := True
|
||||
}
|
||||
|
||||
when(valid && io.mem.cmd.ready){
|
||||
memCmdSent := True
|
||||
}
|
||||
|
||||
when(valid && !memCmdSent) {
|
||||
victim.memCmdAlreadyUsed := True
|
||||
}
|
||||
|
||||
val counter = Counter(memTransactionPerLine)
|
||||
val waysAllocator = Reg(Bits(wayCount bits)) init(1)
|
||||
val error = RegInit(False)
|
||||
|
||||
when(valid && io.mem.rsp.valid){
|
||||
dataWriteCmd.valid := True
|
||||
dataWriteCmd.address := baseAddress(lineRange) @@ counter
|
||||
dataWriteCmd.data := io.mem.rsp.data
|
||||
dataWriteCmd.mask := (1<<(wordWidth/8))-1
|
||||
dataWriteCmd.mask.setAll()
|
||||
dataWriteCmd.way := waysAllocator
|
||||
error := error | io.mem.rsp.error
|
||||
counter.increment()
|
||||
}
|
||||
|
||||
|
||||
when(counter.willOverflow){
|
||||
memCmdSent := False
|
||||
valid := False
|
||||
stageB.loaderReady := True
|
||||
|
||||
//Update tags
|
||||
tagsWriteCmd.valid := True
|
||||
tagsWriteCmd.address := baseAddress(lineRange)
|
||||
tagsWriteCmd.data.valid := True
|
||||
tagsWriteCmd.data.address := baseAddress(tagRange)
|
||||
tagsWriteCmd.data.error := error || io.mem.rsp.error
|
||||
tagsWriteCmd.way := waysAllocator
|
||||
|
||||
waysAllocator := (waysAllocator ## waysAllocator.msb).resized
|
||||
|
||||
error := False
|
||||
}
|
||||
|
||||
io.cpu.redo setWhen(valid)
|
||||
stageB.mmuRspFreeze setWhen(stageB.loaderValid || valid)
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ case class InstructionCacheConfig( cacheSize : Int,
|
|||
memDataWidth : Int,
|
||||
catchIllegalAccess : Boolean,
|
||||
catchAccessFault : Boolean,
|
||||
catchMemoryTranslationMiss : Boolean,
|
||||
asyncTagMemory : Boolean,
|
||||
twoCycleCache : Boolean = true,
|
||||
twoCycleRam : Boolean = false,
|
||||
|
@ -26,7 +25,7 @@ case class InstructionCacheConfig( cacheSize : Int,
|
|||
assert(!(twoCycleRam && !twoCycleCache))
|
||||
|
||||
def burstSize = bytePerLine*8/memDataWidth
|
||||
def catchSomething = catchAccessFault || catchMemoryTranslationMiss || catchIllegalAccess
|
||||
def catchSomething = catchAccessFault || catchIllegalAccess
|
||||
|
||||
def getAxi4Config() = Axi4Config(
|
||||
addressWidth = addressWidth,
|
||||
|
@ -86,7 +85,7 @@ trait InstructionCacheCommons{
|
|||
val pc : UInt
|
||||
val physicalAddress : UInt
|
||||
val data : Bits
|
||||
val cacheMiss, error, mmuMiss, illegalAccess, isUser : Bool
|
||||
val cacheMiss, error, mmuRefilling, mmuException, isUser : Bool
|
||||
}
|
||||
|
||||
case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons {
|
||||
|
@ -99,11 +98,12 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w
|
|||
val dataBypass = Bits(p.cpuDataWidth bits)
|
||||
val mmuBus = MemoryTranslatorBus()
|
||||
val physicalAddress = UInt(p.addressWidth bits)
|
||||
val cacheMiss, error, mmuMiss, illegalAccess,isUser = ifGen(!p.twoCycleCache)(Bool)
|
||||
val cacheMiss, error, mmuRefilling, mmuException, isUser = ifGen(!p.twoCycleCache)(Bool)
|
||||
val haltIt = Bool
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid, isStuck, isRemoved, pc)
|
||||
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss,physicalAddress)
|
||||
inWithNull(error,mmuRefilling,mmuException,data, cacheMiss,physicalAddress, haltIt)
|
||||
outWithNull(isUser, dataBypass, dataBypassValid)
|
||||
slaveWithNull(mmuBus)
|
||||
}
|
||||
|
@ -116,12 +116,12 @@ case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle
|
|||
val pc = UInt(p.addressWidth bits)
|
||||
val physicalAddress = UInt(p.addressWidth bits)
|
||||
val data = Bits(p.cpuDataWidth bits)
|
||||
val cacheMiss, error, mmuMiss, illegalAccess, isUser = ifGen(p.twoCycleCache)(Bool)
|
||||
val cacheMiss, error, mmuRefilling, mmuException, isUser = ifGen(p.twoCycleCache)(Bool)
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
out(isValid, isStuck, pc)
|
||||
outWithNull(isUser)
|
||||
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss, physicalAddress)
|
||||
inWithNull(error, mmuRefilling, mmuException,data, cacheMiss, physicalAddress)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
import p._
|
||||
assert(cpuDataWidth == memDataWidth, "Need testing")
|
||||
val io = new Bundle{
|
||||
val flush = slave(InstructionCacheFlushBus())
|
||||
val flush = in Bool()
|
||||
val cpu = slave(InstructionCacheCpuBus(p))
|
||||
val mem = master(InstructionCacheMemBus(p))
|
||||
}
|
||||
|
@ -291,25 +291,23 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
}
|
||||
})
|
||||
|
||||
io.cpu.prefetch.haltIt := False
|
||||
|
||||
|
||||
|
||||
io.cpu.fetch.haltIt := io.cpu.fetch.mmuBus.busy
|
||||
|
||||
val lineLoader = new Area{
|
||||
val fire = False
|
||||
val valid = RegInit(False) clearWhen(fire)
|
||||
val address = Reg(UInt(addressWidth bits))
|
||||
val hadError = RegInit(False) clearWhen(fire)
|
||||
val flushPending = RegInit(True)
|
||||
|
||||
when(io.cpu.fill.valid){
|
||||
valid := True
|
||||
address := io.cpu.fill.payload
|
||||
}
|
||||
|
||||
io.cpu.prefetch.haltIt setWhen(valid)
|
||||
io.cpu.prefetch.haltIt := valid || flushPending
|
||||
|
||||
val flushCounter = Reg(UInt(log2Up(wayLineCount) + 1 bit)) init(if(preResetFlush) wayLineCount else 0)
|
||||
val flushCounter = Reg(UInt(log2Up(wayLineCount) + 1 bit))
|
||||
when(!flushCounter.msb){
|
||||
io.cpu.prefetch.haltIt := True
|
||||
flushCounter := flushCounter + 1
|
||||
|
@ -317,17 +315,16 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
when(!RegNext(flushCounter.msb)){
|
||||
io.cpu.prefetch.haltIt := True
|
||||
}
|
||||
val flushFromInterface = RegInit(False)
|
||||
io.flush.cmd.ready := !(valid || io.cpu.fetch.isValid) //io.cpu.fetch.isValid will avoid bug on first cycle miss
|
||||
when(io.flush.cmd.valid){
|
||||
|
||||
when(io.flush){
|
||||
io.cpu.prefetch.haltIt := True
|
||||
when(io.flush.cmd.ready){
|
||||
flushCounter := 0
|
||||
flushFromInterface := True
|
||||
}
|
||||
flushPending := True
|
||||
}
|
||||
|
||||
io.flush.rsp := flushCounter.msb.rise && flushFromInterface
|
||||
when(flushPending && !(valid || io.cpu.fetch.isValid) ){
|
||||
flushCounter := 0
|
||||
flushPending := False
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -411,8 +408,8 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
|
||||
io.cpu.fetch.cacheMiss := !hit.valid
|
||||
io.cpu.fetch.error := hit.error
|
||||
io.cpu.fetch.mmuMiss := mmuRsp.miss
|
||||
io.cpu.fetch.illegalAccess := !mmuRsp.allowExecute || (io.cpu.fetch.isUser && !mmuRsp.allowUser)
|
||||
io.cpu.fetch.mmuRefilling := mmuRsp.refilling
|
||||
io.cpu.fetch.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -441,8 +438,8 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
|
||||
io.cpu.decode.cacheMiss := !hit.valid
|
||||
io.cpu.decode.error := hit.error
|
||||
io.cpu.decode.mmuMiss := mmuRsp.miss
|
||||
io.cpu.decode.illegalAccess := !mmuRsp.allowExecute || (io.cpu.decode.isUser && !mmuRsp.allowUser)
|
||||
io.cpu.decode.mmuRefilling := mmuRsp.refilling
|
||||
io.cpu.decode.mmuException := !mmuRsp.refilling && (mmuRsp.exception || !mmuRsp.allowExecute)
|
||||
io.cpu.decode.physicalAddress := mmuRsp.physicalAddress
|
||||
})
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
fenceiGenAsAJump : Boolean = false,
|
||||
fenceiGenAsANop : Boolean = false) extends Plugin[VexRiscv] with PredictionInterface{
|
||||
|
||||
|
||||
def catchAddressMisalignedForReal = catchAddressMisaligned && !pipeline(RVC_GEN)
|
||||
lazy val branchStage = if(earlyBranch) pipeline.execute else pipeline.memory
|
||||
|
||||
|
@ -88,6 +89,8 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
import pipeline.config._
|
||||
import IntAluPlugin._
|
||||
|
||||
assert(earlyBranch || withMemoryStage, "earlyBranch must be true when memory stage is disabled!")
|
||||
|
||||
val bActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
|
@ -265,7 +268,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
default{
|
||||
branch_src1 := input(PC)
|
||||
branch_src2 := ((input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt
|
||||
when(input(PREDICTION_HAD_BRANCHED) && ! missAlignedTarget){
|
||||
when(input(PREDICTION_HAD_BRANCHED)){ //Assume the predictor never predict missaligned stuff, this avoid the need to know if the instruction should branch or not
|
||||
branch_src2 := (if(pipeline(RVC_GEN)) Mux(input(IS_RVC), B(2), B(4)) else B(4)).asUInt.resized
|
||||
}
|
||||
}
|
||||
|
@ -375,4 +378,4 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,10 +51,11 @@ case class CsrPluginConfig(
|
|||
ucycleAccess : CsrAccess,
|
||||
wfiGenAsWait : Boolean,
|
||||
ecallGen : Boolean,
|
||||
mtvecModeGen : Boolean = false,
|
||||
xtvecModeGen : Boolean = false,
|
||||
noCsrAlu : Boolean = false,
|
||||
wfiGenAsNop : Boolean = false,
|
||||
ebreakGen : Boolean = false,
|
||||
userGen : Boolean = false,
|
||||
supervisorGen : Boolean = false,
|
||||
sscratchGen : Boolean = false,
|
||||
stvecAccess : CsrAccess = CsrAccess.NONE,
|
||||
|
@ -70,7 +71,7 @@ case class CsrPluginConfig(
|
|||
deterministicInteruptionEntry : Boolean = false //Only used for simulatation purposes
|
||||
){
|
||||
assert(!ucycleAccess.canWrite)
|
||||
|
||||
def privilegeGen = userGen || supervisorGen
|
||||
def noException = this.copy(ecallGen = false, ebreakGen = false, catchIllegalAccess = false)
|
||||
}
|
||||
|
||||
|
@ -78,26 +79,104 @@ object CsrPluginConfig{
|
|||
def all : CsrPluginConfig = all(0x00000020l)
|
||||
def small : CsrPluginConfig = small(0x00000020l)
|
||||
def smallest : CsrPluginConfig = smallest(0x00000020l)
|
||||
def linuxMinimal(mtVecInit : BigInt) = CsrPluginConfig(
|
||||
catchIllegalAccess = true,
|
||||
mvendorid = 1,
|
||||
marchid = 2,
|
||||
mimpid = 3,
|
||||
mhartid = 0,
|
||||
misaExtensionsInit = 0, //TODO
|
||||
misaAccess = CsrAccess.NONE, //Read required by some regressions
|
||||
mtvecAccess = CsrAccess.WRITE_ONLY, //Read required by some regressions
|
||||
mtvecInit = mtVecInit,
|
||||
mepcAccess = CsrAccess.READ_WRITE,
|
||||
mscratchGen = true,
|
||||
mcauseAccess = CsrAccess.READ_ONLY,
|
||||
mbadaddrAccess = CsrAccess.READ_ONLY,
|
||||
mcycleAccess = CsrAccess.NONE,
|
||||
minstretAccess = CsrAccess.NONE,
|
||||
ucycleAccess = CsrAccess.NONE,
|
||||
wfiGenAsWait = true,
|
||||
ecallGen = true,
|
||||
xtvecModeGen = false,
|
||||
noCsrAlu = false,
|
||||
wfiGenAsNop = false,
|
||||
ebreakGen = true,
|
||||
userGen = true,
|
||||
supervisorGen = true,
|
||||
sscratchGen = true,
|
||||
stvecAccess = CsrAccess.READ_WRITE,
|
||||
sepcAccess = CsrAccess.READ_WRITE,
|
||||
scauseAccess = CsrAccess.READ_WRITE,
|
||||
sbadaddrAccess = CsrAccess.READ_WRITE,
|
||||
scycleAccess = CsrAccess.NONE,
|
||||
sinstretAccess = CsrAccess.NONE,
|
||||
satpAccess = CsrAccess.NONE, //Implemented into the MMU plugin
|
||||
medelegAccess = CsrAccess.WRITE_ONLY,
|
||||
midelegAccess = CsrAccess.WRITE_ONLY,
|
||||
pipelineCsrRead = false,
|
||||
deterministicInteruptionEntry = false
|
||||
)
|
||||
|
||||
|
||||
def linuxFull(mtVecInit : BigInt) = CsrPluginConfig(
|
||||
catchIllegalAccess = true,
|
||||
mvendorid = 1,
|
||||
marchid = 2,
|
||||
mimpid = 3,
|
||||
mhartid = 0,
|
||||
misaExtensionsInit = 0, //TODO
|
||||
misaAccess = CsrAccess.READ_WRITE,
|
||||
mtvecAccess = CsrAccess.READ_WRITE,
|
||||
mtvecInit = mtVecInit,
|
||||
mepcAccess = CsrAccess.READ_WRITE,
|
||||
mscratchGen = true,
|
||||
mcauseAccess = CsrAccess.READ_WRITE,
|
||||
mbadaddrAccess = CsrAccess.READ_WRITE,
|
||||
mcycleAccess = CsrAccess.READ_WRITE,
|
||||
minstretAccess = CsrAccess.READ_WRITE,
|
||||
ucycleAccess = CsrAccess.READ_ONLY,
|
||||
wfiGenAsWait = true,
|
||||
ecallGen = true,
|
||||
xtvecModeGen = false,
|
||||
noCsrAlu = false,
|
||||
wfiGenAsNop = false,
|
||||
ebreakGen = false,
|
||||
userGen = true,
|
||||
supervisorGen = true,
|
||||
sscratchGen = true,
|
||||
stvecAccess = CsrAccess.READ_WRITE,
|
||||
sepcAccess = CsrAccess.READ_WRITE,
|
||||
scauseAccess = CsrAccess.READ_WRITE,
|
||||
sbadaddrAccess = CsrAccess.READ_WRITE,
|
||||
scycleAccess = CsrAccess.READ_WRITE,
|
||||
sinstretAccess = CsrAccess.READ_WRITE,
|
||||
satpAccess = CsrAccess.NONE, //Implemented into the MMU plugin
|
||||
medelegAccess = CsrAccess.READ_WRITE,
|
||||
midelegAccess = CsrAccess.READ_WRITE,
|
||||
pipelineCsrRead = false,
|
||||
deterministicInteruptionEntry = false
|
||||
)
|
||||
|
||||
def all(mtvecInit : BigInt) : CsrPluginConfig = CsrPluginConfig(
|
||||
catchIllegalAccess = true,
|
||||
mvendorid = 11,
|
||||
marchid = 22,
|
||||
mimpid = 33,
|
||||
mhartid = 0,
|
||||
mvendorid = 11,
|
||||
marchid = 22,
|
||||
mimpid = 33,
|
||||
mhartid = 0,
|
||||
misaExtensionsInit = 66,
|
||||
misaAccess = CsrAccess.READ_WRITE,
|
||||
mtvecAccess = CsrAccess.READ_WRITE,
|
||||
mtvecInit = mtvecInit,
|
||||
mepcAccess = CsrAccess.READ_WRITE,
|
||||
mscratchGen = true,
|
||||
mcauseAccess = CsrAccess.READ_WRITE,
|
||||
mbadaddrAccess = CsrAccess.READ_WRITE,
|
||||
mcycleAccess = CsrAccess.READ_WRITE,
|
||||
minstretAccess = CsrAccess.READ_WRITE,
|
||||
ecallGen = true,
|
||||
wfiGenAsWait = true,
|
||||
ucycleAccess = CsrAccess.READ_ONLY
|
||||
misaAccess = CsrAccess.READ_WRITE,
|
||||
mtvecAccess = CsrAccess.READ_WRITE,
|
||||
mtvecInit = mtvecInit,
|
||||
mepcAccess = CsrAccess.READ_WRITE,
|
||||
mscratchGen = true,
|
||||
mcauseAccess = CsrAccess.READ_WRITE,
|
||||
mbadaddrAccess = CsrAccess.READ_WRITE,
|
||||
mcycleAccess = CsrAccess.READ_WRITE,
|
||||
minstretAccess = CsrAccess.READ_WRITE,
|
||||
ecallGen = true,
|
||||
wfiGenAsWait = true,
|
||||
ucycleAccess = CsrAccess.READ_ONLY
|
||||
)
|
||||
|
||||
def all2(mtvecInit : BigInt) : CsrPluginConfig = CsrPluginConfig(
|
||||
|
@ -177,6 +256,7 @@ object CsrPluginConfig{
|
|||
}
|
||||
case class CsrWrite(that : Data, bitOffset : Int)
|
||||
case class CsrRead(that : Data , bitOffset : Int)
|
||||
case class CsrReadToWriteOverride(that : Data, bitOffset : Int) //Used for special cases, as MIP where there shadow stuff
|
||||
case class CsrOnWrite(doThat :() => Unit)
|
||||
case class CsrOnRead(doThat : () => Unit)
|
||||
case class CsrMapping() extends CsrInterface{
|
||||
|
@ -184,6 +264,7 @@ case class CsrMapping() extends CsrInterface{
|
|||
def addMappingAt(address : Int,that : Any) = mapping.getOrElseUpdate(address,new ArrayBuffer[Any]) += that
|
||||
override def r(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrRead(that,bitOffset))
|
||||
override def w(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrWrite(that,bitOffset))
|
||||
override def r2w(csrAddress : Int, bitOffset : Int, that : Data): Unit = addMappingAt(csrAddress, CsrReadToWriteOverride(that,bitOffset))
|
||||
override def onWrite(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrOnWrite(() => body))
|
||||
override def onRead(csrAddress: Int)(body: => Unit): Unit = addMappingAt(csrAddress, CsrOnRead(() => {body}))
|
||||
}
|
||||
|
@ -199,6 +280,8 @@ trait CsrInterface{
|
|||
w(csrAddress,bitOffset,that)
|
||||
}
|
||||
|
||||
def r2w(csrAddress : Int, bitOffset : Int,that : Data): Unit
|
||||
|
||||
def rw(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) rw(csrAddress,that._1, that._2)
|
||||
def w(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) w(csrAddress,that._1, that._2)
|
||||
def r(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) r(csrAddress,that._1, that._2)
|
||||
|
@ -244,9 +327,13 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
interface
|
||||
}
|
||||
|
||||
var exceptionPendings : Vec[Bool] = null
|
||||
override def isExceptionPending(stage : Stage): Bool = exceptionPendings(pipeline.stages.indexOf(stage))
|
||||
|
||||
var jumpInterface : Flow[UInt] = null
|
||||
var timerInterrupt, externalInterrupt : Bool = null
|
||||
var timerInterruptS, externalInterruptS : Bool = null
|
||||
var timerInterrupt, externalInterrupt, softwareInterrupt : Bool = null
|
||||
var externalInterruptS : Bool = null
|
||||
var forceMachineWire : Bool = null
|
||||
var privilege : UInt = null
|
||||
var selfException : Flow[ExceptionCause] = null
|
||||
var contextSwitching : Bool = null
|
||||
|
@ -270,23 +357,20 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
val csrMapping = new CsrMapping()
|
||||
|
||||
//Interruption and exception data model
|
||||
case class Delegator(var enable : Bool, privilege : Int)
|
||||
case class InterruptSpec(var cond : Bool, id : Int, privilege : Int, delegators : List[Delegator])
|
||||
case class ExceptionSpec(id : Int, delegators : List[Delegator])
|
||||
var interruptSpecs = ArrayBuffer[InterruptSpec]()
|
||||
var exceptionSpecs = ArrayBuffer[ExceptionSpec]()
|
||||
|
||||
|
||||
case class InterruptSource(var cond : Bool, id : Int)
|
||||
case class InterruptPrivilege(privilege : Int){
|
||||
var privilegeCond : Bool = null
|
||||
val sources = ArrayBuffer[InterruptSource]()
|
||||
def addInterrupt(cond : Bool, id : Int, privilege : Int, delegators : List[Delegator]): Unit = {
|
||||
interruptSpecs += InterruptSpec(cond, id, privilege, delegators)
|
||||
}
|
||||
|
||||
def getInterruptPrivilege(privilege : Int) = customInterrupts.getOrElseUpdate(privilege, InterruptPrivilege(privilege))
|
||||
var customInterrupts = mutable.LinkedHashMap[Int, InterruptPrivilege]()
|
||||
def addInterrupt(cond : Bool, id : Int, privilege : Int): Unit = {
|
||||
getInterruptPrivilege(privilege).sources += InterruptSource(cond, id)
|
||||
}
|
||||
def createInterrupt(id : Int, privilege : Int) : Bool = { val ret = Bool(); addInterrupt(ret, id, privilege); ret}
|
||||
|
||||
override def r(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r(csrAddress, bitOffset, that)
|
||||
override def w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.w(csrAddress, bitOffset, that)
|
||||
override def r2w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r2w(csrAddress, bitOffset, that)
|
||||
override def onWrite(csrAddress: Int)(body: => Unit): Unit = csrMapping.onWrite(csrAddress)(body)
|
||||
override def onRead(csrAddress: Int)(body: => Unit): Unit = csrMapping.onRead(csrAddress)(body)
|
||||
|
||||
|
@ -336,16 +420,18 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
jumpInterface.valid := False
|
||||
jumpInterface.payload.assignDontCare()
|
||||
|
||||
|
||||
exceptionPendings = Vec(Bool, pipeline.stages.length)
|
||||
timerInterrupt = in Bool() setName("timerInterrupt")
|
||||
externalInterrupt = in Bool() setName("externalInterrupt")
|
||||
softwareInterrupt = in Bool() setName("softwareInterrupt") default(False)
|
||||
if(supervisorGen){
|
||||
timerInterruptS = in Bool() setName("timerInterruptS")
|
||||
// timerInterruptS = in Bool() setName("timerInterruptS")
|
||||
externalInterruptS = in Bool() setName("externalInterruptS")
|
||||
}
|
||||
contextSwitching = Bool().setName("contextSwitching")
|
||||
|
||||
privilege = RegInit(U"11").setName("CsrPlugin_privilege")
|
||||
privilege = UInt(2 bits).setName("CsrPlugin_privilege")
|
||||
forceMachineWire = False
|
||||
|
||||
if(catchIllegalAccess || ecallGen || ebreakGen)
|
||||
selfException = newExceptionPort(pipeline.execute)
|
||||
|
@ -353,16 +439,19 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
allowInterrupts = True
|
||||
allowException = True
|
||||
|
||||
for (privilege <- customInterrupts.values;
|
||||
source <- privilege.sources){
|
||||
source.cond = source.cond.pull()
|
||||
}
|
||||
for (i <- interruptSpecs) i.cond = i.cond.pull()
|
||||
|
||||
|
||||
pipeline.update(MPP, UInt(2 bits))
|
||||
}
|
||||
|
||||
def inhibateInterrupts() : Unit = allowInterrupts := False
|
||||
def inhibateException() : Unit = allowException := False
|
||||
|
||||
def isUser(stage : Stage) : Bool = privilege === 0
|
||||
override def isUser() : Bool = privilege === 0
|
||||
override def isSupervisor(): Bool = privilege === 1
|
||||
override def isMachine(): Bool = privilege === 3
|
||||
override def forceMachine(): Unit = forceMachineWire := True
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
|
@ -382,6 +471,16 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
}
|
||||
|
||||
|
||||
case class Xtvec() extends Bundle {
|
||||
val mode = Bits(2 bits)
|
||||
val base = UInt(xlen-2 bits)
|
||||
}
|
||||
|
||||
val privilegeReg = privilegeGen generate RegInit(U"11")
|
||||
privilege := (if(privilegeGen) privilegeReg else U"11")
|
||||
|
||||
when(forceMachineWire) { privilege := 3 }
|
||||
|
||||
val machineCsr = pipeline plug new Area{
|
||||
//Define CSR registers
|
||||
// Status => MXR, SUM, TVM, TW, TSE ?
|
||||
|
@ -390,11 +489,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val extensions = Reg(Bits(26 bits)) init(misaExtensionsInit) allowUnsetRegToAvoidLatch
|
||||
}
|
||||
|
||||
|
||||
val mtvec = new Area{
|
||||
val mode = Reg(Bits(2 bits)).allowUnsetRegToAvoidLatch
|
||||
val base = Reg(UInt(xlen-2 bits)).allowUnsetRegToAvoidLatch
|
||||
}
|
||||
val mtvec = Reg(Xtvec()).allowUnsetRegToAvoidLatch
|
||||
|
||||
if(mtvecInit != null) mtvec.mode init(mtvecInit & 0x3)
|
||||
if(mtvecInit != null) mtvec.base init(mtvecInit / 4)
|
||||
|
@ -404,9 +499,9 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val MPP = RegInit(U"11")
|
||||
}
|
||||
val mip = new Area{
|
||||
val MEIP = RegNext(externalInterrupt) init(False)
|
||||
val MTIP = RegNext(timerInterrupt) init(False)
|
||||
val MSIP = RegInit(False)
|
||||
val MEIP = RegNext(externalInterrupt)
|
||||
val MTIP = RegNext(timerInterrupt)
|
||||
val MSIP = RegNext(softwareInterrupt)
|
||||
}
|
||||
val mie = new Area{
|
||||
val MEIE, MTIE, MSIE = RegInit(False)
|
||||
|
@ -421,9 +516,13 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val minstret = Reg(UInt(64 bits)) randBoot()
|
||||
|
||||
|
||||
|
||||
val medeleg = Reg(Bits(32 bits)) init(0)
|
||||
val mideleg = Reg(Bits(32 bits)) init(0)
|
||||
val medeleg = supervisorGen generate new Area {
|
||||
val IAM, IAF, II, LAM, LAF, SAM, SAF, EU, ES, IPF, LPF, SPF = RegInit(False)
|
||||
val mapping = mutable.HashMap(0 -> IAM, 1 -> IAF, 2 -> II, 4 -> LAM, 5 -> LAF, 6 -> SAM, 7 -> SAF, 8 -> EU, 9 -> ES, 12 -> IPF, 13 -> LPF, 15 -> SPF)
|
||||
}
|
||||
val mideleg = supervisorGen generate new Area {
|
||||
val ST, SE, SS = RegInit(False)
|
||||
}
|
||||
|
||||
if(mvendorid != null) READ_ONLY(CSR.MVENDORID, U(mvendorid))
|
||||
if(marchid != null) READ_ONLY(CSR.MARCHID , U(marchid ))
|
||||
|
@ -447,12 +546,16 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
minstretAccess(CSR.MINSTRET, minstret(31 downto 0))
|
||||
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
|
||||
|
||||
medelegAccess(CSR.MEDELEG, medeleg)
|
||||
midelegAccess(CSR.MIDELEG, mideleg)
|
||||
if(supervisorGen) {
|
||||
for((id, enable) <- medeleg.mapping) medelegAccess(CSR.MEDELEG, id -> enable)
|
||||
midelegAccess(CSR.MIDELEG, 9 -> mideleg.SE, 5 -> mideleg.ST, 1 -> mideleg.SS)
|
||||
}
|
||||
|
||||
//User CSR
|
||||
ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0))
|
||||
ucycleAccess(CSR.UCYCLEH, mcycle(31 downto 0))
|
||||
ucycleAccess(CSR.UCYCLEH, mcycle(63 downto 32))
|
||||
|
||||
pipeline(MPP) := mstatus.MPP
|
||||
}
|
||||
|
||||
val supervisorCsr = ifGen(supervisorGen) {
|
||||
|
@ -463,14 +566,16 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
}
|
||||
|
||||
val sip = new Area {
|
||||
val SEIP = RegNext(externalInterruptS) init (False)
|
||||
val STIP = RegNext(timerInterruptS) init (False)
|
||||
val SEIP_SOFT = RegInit(False)
|
||||
val SEIP_INPUT = RegNext(externalInterruptS)
|
||||
val SEIP_OR = SEIP_SOFT || SEIP_INPUT
|
||||
val STIP = RegInit(False)
|
||||
val SSIP = RegInit(False)
|
||||
}
|
||||
val sie = new Area {
|
||||
val SEIE, STIE, SSIE = RegInit(False)
|
||||
}
|
||||
val stvec = Reg(UInt(xlen bits)).allowUnsetRegToAvoidLatch
|
||||
val stvec = Reg(Xtvec()).allowUnsetRegToAvoidLatch
|
||||
val sscratch = if (sscratchGen) Reg(Bits(xlen bits)) else null
|
||||
|
||||
val scause = new Area {
|
||||
|
@ -486,15 +591,18 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
}
|
||||
|
||||
//Supervisor CSR
|
||||
WRITE_ONLY(CSR.SSTATUS,8 -> sstatus.SPP, 5 -> sstatus.SPIE, 1 -> sstatus.SIE)
|
||||
for(offset <- List(0, 0x200)) {
|
||||
READ_ONLY(CSR.SSTATUS,8 -> sstatus.SPP, 5 -> sstatus.SPIE, 1 -> sstatus.SIE)
|
||||
for(offset <- List(CSR.MSTATUS, CSR.SSTATUS)) READ_WRITE(offset,8 -> sstatus.SPP, 5 -> sstatus.SPIE, 1 -> sstatus.SIE)
|
||||
for(offset <- List(CSR.MIP, CSR.SIP)) {
|
||||
READ_WRITE(offset, 5 -> sip.STIP, 1 -> sip.SSIP)
|
||||
READ_ONLY(offset, 9 -> sip.SEIP_OR)
|
||||
WRITE_ONLY(offset, 9 -> sip.SEIP_SOFT)
|
||||
r2w(offset, 9, sip.SEIP_SOFT)
|
||||
}
|
||||
READ_ONLY(CSR.SIP, 9 -> sip.SEIP, 5 -> sip.STIP)
|
||||
READ_WRITE(CSR.SIP, 1 -> sip.SSIP)
|
||||
READ_WRITE(CSR.SIE, 9 -> sie.SEIE, 5 -> sie.STIE, 1 -> sie.SSIE)
|
||||
|
||||
stvecAccess(CSR.STVEC, stvec)
|
||||
for(offset <- List(CSR.MIE, CSR.SIE)) READ_WRITE(offset, 9 -> sie.SEIE, 5 -> sie.STIE, 1 -> sie.SSIE)
|
||||
|
||||
|
||||
stvecAccess(CSR.STVEC, 2 -> stvec.base, 0 -> stvec.mode)
|
||||
sepcAccess(CSR.SEPC, sepc)
|
||||
if(sscratchGen) READ_WRITE(CSR.SSCRATCH, sscratch)
|
||||
scauseAccess(CSR.SCAUSE, xlen-1 -> scause.interrupt, 0 -> scause.exceptionCode)
|
||||
|
@ -521,58 +629,16 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
|
||||
if(supervisorGen) {
|
||||
getInterruptPrivilege(1).privilegeCond = sstatus.SIE && privilege <= "01"
|
||||
getInterruptPrivilege(1).sources ++= List(
|
||||
InterruptSource(sip.STIP && sie.STIE, 5),
|
||||
InterruptSource(sip.SSIP && sie.SSIE, 1),
|
||||
InterruptSource(sip.SEIP && sie.SEIE, 9)
|
||||
)
|
||||
addInterrupt(sip.STIP && sie.STIE, id = 5, privilege = 1, delegators = List(Delegator(mideleg.ST, 3)))
|
||||
addInterrupt(sip.SSIP && sie.SSIE, id = 1, privilege = 1, delegators = List(Delegator(mideleg.SS, 3)))
|
||||
addInterrupt(sip.SEIP_OR && sie.SEIE, id = 9, privilege = 1, delegators = List(Delegator(mideleg.SE, 3)))
|
||||
|
||||
for((id, enable) <- medeleg.mapping) exceptionSpecs += ExceptionSpec(id, List(Delegator(enable, 3)))
|
||||
}
|
||||
|
||||
getInterruptPrivilege(3).privilegeCond = mstatus.MIE
|
||||
getInterruptPrivilege(3).sources ++= List(
|
||||
InterruptSource(mip.MTIP && mie.MTIE, 7),
|
||||
InterruptSource(mip.MSIP && mie.MSIE, 3),
|
||||
InterruptSource(mip.MEIP && mie.MEIE, 11)
|
||||
)
|
||||
|
||||
case class DelegatorModel(value : Bits, source : Int, target : Int)
|
||||
// def solveDelegators(delegators : Seq[DelegatorModel], id : Int, lowerBound : Int): UInt = {
|
||||
// val filtredDelegators = delegators.filter(_.target >= lowerBound)
|
||||
// val ret = U(lowerBound, 2 bits)
|
||||
// for(d <- filtredDelegators){
|
||||
// when(!d.value(id)){
|
||||
// ret := d.source
|
||||
// }
|
||||
// }
|
||||
// ret
|
||||
// }
|
||||
|
||||
def solveDelegators(delegators : Seq[DelegatorModel], id : UInt, lowerBound : UInt): UInt = {
|
||||
if(delegators.isEmpty) return U"11"
|
||||
val ret = U(delegators.last.target, 2 bits)
|
||||
for(d <- delegators){
|
||||
when(!d.value(id) || d.target < lowerBound){
|
||||
ret := d.source
|
||||
}
|
||||
}
|
||||
ret
|
||||
// val ret = U"11"
|
||||
// var continue = True
|
||||
// for(d <- delegators){
|
||||
// continue = continue && d.value(id)
|
||||
// when(continue){
|
||||
// ret := d.source
|
||||
// }
|
||||
// }
|
||||
// ret.max(lowerBound)
|
||||
}
|
||||
|
||||
val interruptDelegators = ArrayBuffer[DelegatorModel]()
|
||||
if(midelegAccess.canWrite) interruptDelegators += DelegatorModel(mideleg,3, 1)
|
||||
|
||||
val exceptionDelegators = ArrayBuffer[DelegatorModel]()
|
||||
if(medelegAccess.canWrite) exceptionDelegators += DelegatorModel(medeleg,3, 1)
|
||||
addInterrupt(mip.MTIP && mie.MTIE, id = 7, privilege = 3, delegators = Nil)
|
||||
addInterrupt(mip.MSIP && mie.MSIE, id = 3, privilege = 3, delegators = Nil)
|
||||
addInterrupt(mip.MEIP && mie.MEIE, id = 11, privilege = 3, delegators = Nil)
|
||||
|
||||
|
||||
val mepcCaptureStage = if(exceptionPortsInfos.nonEmpty) lastStage else decode
|
||||
|
@ -584,7 +650,27 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val exceptionValids = Vec(stages.map(s => Bool().setPartialName(s.getName())))
|
||||
val exceptionValidsRegs = Vec(stages.map(s => Reg(Bool).init(False).setPartialName(s.getName()))).allowUnsetRegToAvoidLatch
|
||||
val exceptionContext = Reg(ExceptionCause())
|
||||
val exceptionTargetPrivilege = solveDelegators(exceptionDelegators, exceptionContext.code, privilege)
|
||||
val exceptionTargetPrivilegeUncapped = U"11"
|
||||
|
||||
switch(exceptionContext.code){
|
||||
for(s <- exceptionSpecs){
|
||||
is(s.id){
|
||||
var exceptionPrivilegs = if (supervisorGen) List(1, 3) else List(3)
|
||||
while(exceptionPrivilegs.length != 1){
|
||||
val p = exceptionPrivilegs.head
|
||||
if (exceptionPrivilegs.tail.forall(e => s.delegators.exists(_.privilege == e))) {
|
||||
val delegUpOn = s.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _)
|
||||
val delegDownOff = !s.delegators.filter(_.privilege <= p).map(_.enable).orR
|
||||
when(delegUpOn && delegDownOff) {
|
||||
exceptionTargetPrivilegeUncapped := p
|
||||
}
|
||||
}
|
||||
exceptionPrivilegs = exceptionPrivilegs.tail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val exceptionTargetPrivilege = privilege.max(exceptionTargetPrivilegeUncapped)
|
||||
|
||||
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
|
||||
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority)
|
||||
|
@ -603,7 +689,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
})
|
||||
|
||||
val sortedByStage = groupedByStage.sortWith((a, b) => pipeline.indexOf(a.stage) < pipeline.indexOf(b.stage))
|
||||
sortedByStage.zipWithIndex.foreach(e => e._1.port.setName(e._1.stage.getName() + "_exception_agregat"))
|
||||
// sortedByStage.zipWithIndex.foreach(e => e._1.port.setName(e._1.stage.getName() + "_exception_agregat"))
|
||||
exceptionValids := exceptionValidsRegs
|
||||
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
||||
when(port.valid) {
|
||||
|
@ -624,7 +710,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
else
|
||||
exceptionValidsRegs(stageId) := False
|
||||
}
|
||||
if(stage != stages.last) when(stage.arbitration.isFlushed){
|
||||
when(stage.arbitration.isFlushed){
|
||||
exceptionValids(stageId) := False
|
||||
}
|
||||
}
|
||||
|
@ -632,6 +718,10 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
when(exceptionValidsRegs.orR){
|
||||
fetcher.haltIt()
|
||||
}
|
||||
|
||||
//Avoid the PC register of the last stage to change durring an exception handleing (Used to fill Xepc)
|
||||
stages.last.dontSample.getOrElseUpdate(PC, ArrayBuffer[Bool]()) += exceptionValids.last
|
||||
exceptionPendings := exceptionValidsRegs
|
||||
} else null
|
||||
|
||||
|
||||
|
@ -641,32 +731,27 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
//Process interrupt request, code and privilege
|
||||
val interrupt = False
|
||||
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
|
||||
val interruptDelegatorHit = interruptDelegators.map(d => (d -> False)).toMap
|
||||
for(model <- customInterrupts.values.toSeq.sortBy(_.privilege)){
|
||||
when(model.privilegeCond){
|
||||
when(model.sources.map(_.cond).orR){
|
||||
interrupt := True
|
||||
}
|
||||
for(source <- model.sources){
|
||||
when(source.cond){
|
||||
interruptCode := source.id
|
||||
for(interruptDelegator <- interruptDelegators){
|
||||
interruptDelegatorHit(interruptDelegator) := (if(interruptDelegator.target < model.privilege){
|
||||
False
|
||||
} else {
|
||||
interruptDelegator.value(source.id)
|
||||
})
|
||||
}
|
||||
var interruptPrivilegs = if (supervisorGen) List(1, 3) else List(3)
|
||||
val interruptTargetPrivilege = UInt(2 bits).assignDontCare()
|
||||
val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]()
|
||||
if(supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01")
|
||||
privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11")
|
||||
while(interruptPrivilegs.nonEmpty){
|
||||
val p = interruptPrivilegs.head
|
||||
when(privilegeAllowInterrupts(p)){
|
||||
for(i <- interruptSpecs
|
||||
if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode
|
||||
if interruptPrivilegs.tail.forall(e => i.delegators.exists(_.privilege == e))){ // EX : Supervisor timer need to have machine mode delegator
|
||||
val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _)
|
||||
val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR
|
||||
when(i.cond && delegUpOn && delegDownOff){
|
||||
interrupt := True
|
||||
interruptCode := i.id
|
||||
interruptTargetPrivilege := p
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val interruptTargetPrivilege = U(if(interruptDelegators.isEmpty) 3 else interruptDelegators.last.target, 2 bits)
|
||||
for(interruptDelegator <- interruptDelegators){
|
||||
when(!interruptDelegatorHit(interruptDelegator)){
|
||||
interruptTargetPrivilege := interruptDelegator.source
|
||||
}
|
||||
interruptPrivilegs = interruptPrivilegs.tail
|
||||
}
|
||||
|
||||
interrupt.clearWhen(!allowInterrupts)
|
||||
|
@ -678,8 +763,8 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
//Used to make the pipeline empty softly (for interrupts)
|
||||
val pipelineLiberator = new Area{
|
||||
when(interrupt && decode.arbitration.isValid){
|
||||
decode.arbitration.haltByOther := True
|
||||
when(interrupt){
|
||||
decode.arbitration.haltByOther := decode.arbitration.isValid
|
||||
}
|
||||
|
||||
val done = !stagesFromExecute.map(_.arbitration.isValid).orR && fetcher.pcValid(mepcCaptureStage)
|
||||
|
@ -704,23 +789,21 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
trapCause := exceptionPortCtrl.exceptionContext.code
|
||||
}
|
||||
|
||||
when(exception || interruptJump){
|
||||
switch(privilege){
|
||||
if(supervisorGen) is(1) {
|
||||
sepc := mepcCaptureStage.input(PC)
|
||||
}
|
||||
is(3){
|
||||
mepc := mepcCaptureStage.input(PC)
|
||||
}
|
||||
}
|
||||
val xtvec = Xtvec().assignDontCare()
|
||||
switch(targetPrivilege){
|
||||
if(supervisorGen) is(1) { xtvec := supervisorCsr.stvec }
|
||||
is(3){ xtvec := machineCsr.mtvec }
|
||||
}
|
||||
|
||||
when(hadException || interruptJump){
|
||||
fetcher.haltIt() //Avoid having the fetch confused by the incomming privilege switch
|
||||
|
||||
jumpInterface.valid := True
|
||||
jumpInterface.payload := (if(!mtvecModeGen) mtvec.base @@ "00" else (mtvec.mode === 0 || hadException) ? (mtvec.base @@ "00") | ((mtvec.base + trapCause) @@ "00") )
|
||||
jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") )
|
||||
beforeLastStage.arbitration.flushAll := True
|
||||
|
||||
privilege := targetPrivilege
|
||||
if(privilegeGen) privilegeReg := targetPrivilege
|
||||
|
||||
switch(targetPrivilege){
|
||||
if(supervisorGen) is(1) {
|
||||
sstatus.SIE := False
|
||||
|
@ -728,7 +811,8 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
sstatus.SPP := privilege(0 downto 0)
|
||||
scause.interrupt := !hadException
|
||||
scause.exceptionCode := trapCause
|
||||
if (exceptionPortCtrl != null) {
|
||||
sepc := mepcCaptureStage.input(PC)
|
||||
if (exceptionPortCtrl != null) when(hadException){
|
||||
stval := exceptionPortCtrl.exceptionContext.badAddr
|
||||
}
|
||||
}
|
||||
|
@ -739,33 +823,37 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
mstatus.MPP := privilege
|
||||
mcause.interrupt := !hadException
|
||||
mcause.exceptionCode := trapCause
|
||||
if(exceptionPortCtrl != null) {
|
||||
mepc := mepcCaptureStage.input(PC)
|
||||
if(exceptionPortCtrl != null) when(hadException){
|
||||
mtval := exceptionPortCtrl.exceptionContext.badAddr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lastStage plug new Area{
|
||||
import lastStage._
|
||||
|
||||
//Manage MRET / SRET instructions
|
||||
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
|
||||
jumpInterface.payload := mepc
|
||||
fetcher.haltIt()
|
||||
jumpInterface.valid := True
|
||||
beforeLastStage.arbitration.flushAll := True
|
||||
switch(input(INSTRUCTION)(29 downto 28)){
|
||||
is(3){
|
||||
mstatus.MIE := mstatus.MPIE
|
||||
mstatus.MPP := U"00"
|
||||
mstatus.MIE := mstatus.MPIE
|
||||
mstatus.MPIE := True
|
||||
privilege := mstatus.MPP
|
||||
jumpInterface.payload := mepc
|
||||
if(privilegeGen) privilegeReg := mstatus.MPP
|
||||
}
|
||||
if(supervisorGen) is(1){
|
||||
sstatus.SIE := sstatus.SPIE
|
||||
sstatus.SPP := U"0"
|
||||
sstatus.SIE := sstatus.SPIE
|
||||
sstatus.SPIE := True
|
||||
privilege := U"0" @@ sstatus.SPP
|
||||
jumpInterface.payload := sepc
|
||||
if(privilegeGen) privilegeReg := U"0" @@ sstatus.SPP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -790,14 +878,16 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
execute plug new Area{
|
||||
import execute._
|
||||
//Manage WFI instructions
|
||||
val inWfi = False.addTag(Verilator.public)
|
||||
if(wfiGenAsWait) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.WFI){
|
||||
inWfi := True
|
||||
when(!interrupt){
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decode.arbitration.haltByOther setWhen(stagesFromExecute.dropRight(1).map(s => s.arbitration.isValid && s.input(ENV_CTRL) === EnvCtrlEnum.XRET).asBits.orR)
|
||||
decode.arbitration.haltByOther setWhen(stagesFromExecute.map(s => s.arbitration.isValid && s.input(ENV_CTRL) === EnvCtrlEnum.XRET).asBits.orR)
|
||||
|
||||
execute plug new Area {
|
||||
import execute._
|
||||
|
@ -809,7 +899,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
if(selfException != null) {
|
||||
selfException.valid := False
|
||||
selfException.code.assignDontCare()
|
||||
selfException.badAddr.assignDontCare()
|
||||
selfException.badAddr := input(INSTRUCTION).asUInt
|
||||
if(catchIllegalAccess) when(illegalAccess || illegalInstruction){
|
||||
selfException.valid := True
|
||||
selfException.code := 2
|
||||
|
@ -818,8 +908,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
|
||||
//Manage MRET / SRET instructions
|
||||
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
|
||||
//TODO check MPP value too
|
||||
when(input(INSTRUCTION)(29 downto 28).asUInt =/= privilege) {
|
||||
when(input(INSTRUCTION)(29 downto 28).asUInt > privilege) {
|
||||
illegalInstruction := True
|
||||
}
|
||||
}
|
||||
|
@ -828,7 +917,11 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
//Manage ECALL instructions
|
||||
if(ecallGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.ECALL){
|
||||
selfException.valid := True
|
||||
selfException.code := 11
|
||||
switch(privilege) {
|
||||
is(0) { selfException.code := 8 }
|
||||
if(supervisorGen) is(1) { selfException.code := 9 }
|
||||
default { selfException.code := 11 }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -856,9 +949,11 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
// False -> writeSrc,
|
||||
// True -> Mux(input(INSTRUCTION)(12), ~writeSrc, writeSrc)
|
||||
// )
|
||||
|
||||
val readToWriteData = CombInit(readData)
|
||||
val writeData = if(noCsrAlu) writeSrc else input(INSTRUCTION)(13).mux(
|
||||
False -> writeSrc,
|
||||
True -> Mux(input(INSTRUCTION)(12), readData & ~writeSrc, readData | writeSrc)
|
||||
True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc)
|
||||
)
|
||||
|
||||
|
||||
|
@ -923,6 +1018,17 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
}
|
||||
}
|
||||
|
||||
switch(csrAddress) {
|
||||
for ((address, jobs) <- csrMapping.mapping if jobs.exists(_.isInstanceOf[CsrReadToWriteOverride])) {
|
||||
is(address) {
|
||||
for (element <- jobs) element match {
|
||||
case element: CsrReadToWriteOverride if element.that.getBitsWidth != 0 => readToWriteData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
illegalAccess setWhen(privilege < csrAddress(9 downto 8).asUInt)
|
||||
illegalAccess clearWhen(!arbitration.isValid || !input(IS_CSR))
|
||||
})
|
||||
|
|
|
@ -7,7 +7,7 @@ import spinal.lib._
|
|||
import spinal.lib.bus.amba4.axi.Axi4
|
||||
|
||||
|
||||
class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : Any = null) extends DBusCachedPlugin(config, memoryTranslatorPortConfig){
|
||||
class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : Any = null) extends DBusCachedPlugin(config, memoryTranslatorPortConfig) {
|
||||
var dAxi : Axi4 = null
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -20,18 +20,35 @@ class DAxiCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
|
|||
|
||||
class DBusCachedPlugin(config : DataCacheConfig,
|
||||
memoryTranslatorPortConfig : Any = null,
|
||||
csrInfo : Boolean = false) extends Plugin[VexRiscv]{
|
||||
dBusCmdMasterPipe : Boolean = false,
|
||||
dBusCmdSlavePipe : Boolean = false,
|
||||
dBusRspSlavePipe : Boolean = false,
|
||||
csrInfo : Boolean = false) extends Plugin[VexRiscv] with DBusAccessService {
|
||||
import config._
|
||||
|
||||
assert(isPow2(cacheSize))
|
||||
assert(!(memoryTranslatorPortConfig != null && config.cacheSize/config.wayCount > 4096), "When the D$ is used with MMU, each way can't be bigger than a page (4096 bytes)")
|
||||
|
||||
var dBus : DataCacheMemBus = null
|
||||
var mmuBus : MemoryTranslatorBus = null
|
||||
var exceptionBus : Flow[ExceptionCause] = null
|
||||
var privilegeService : PrivilegeService = null
|
||||
var redoBranch : Flow[UInt] = null
|
||||
|
||||
@dontName var dBusAccess : DBusAccess = null
|
||||
override def newDBusAccess(): DBusAccess = {
|
||||
assert(dBusAccess == null)
|
||||
dBusAccess = DBusAccess()
|
||||
dBusAccess
|
||||
}
|
||||
|
||||
object MEMORY_ENABLE extends Stageable(Bool)
|
||||
object MEMORY_MANAGMENT extends Stageable(Bool)
|
||||
object MEMORY_WR extends Stageable(Bool)
|
||||
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
|
||||
object MEMORY_ATOMIC extends Stageable(Bool)
|
||||
object MEMORY_LRSC extends Stageable(Bool)
|
||||
object MEMORY_AMO extends Stageable(Bool)
|
||||
object IS_DBUS_SHARING extends Stageable(Bool())
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
|
@ -43,23 +60,22 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC_USE_SUB_LESS -> False,
|
||||
MEMORY_ENABLE -> True,
|
||||
RS1_USE -> True
|
||||
) ++ (if (catchUnaligned) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
|
||||
RS1_USE -> True,
|
||||
IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB
|
||||
)
|
||||
|
||||
val loadActions = stdActions ++ List(
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
MEMORY_WR -> False,
|
||||
MEMORY_MANAGMENT -> False
|
||||
MEMORY_WR -> False
|
||||
) ++ (if(catchSomething) List(HAS_SIDE_EFFECT -> True) else Nil)
|
||||
|
||||
val storeActions = stdActions ++ List(
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMS,
|
||||
RS2_USE -> True,
|
||||
MEMORY_WR -> True,
|
||||
MEMORY_MANAGMENT -> False
|
||||
MEMORY_WR -> True
|
||||
)
|
||||
|
||||
decoderService.addDefault(MEMORY_ENABLE, False)
|
||||
|
@ -68,36 +84,66 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
List(SB, SH, SW).map(_ -> storeActions)
|
||||
)
|
||||
|
||||
if(genAtomic){
|
||||
if(withLrSc){
|
||||
List(LB, LH, LW, LBU, LHU, LWU, SB, SH, SW).foreach(e =>
|
||||
decoderService.add(e, Seq(MEMORY_ATOMIC -> False))
|
||||
decoderService.add(e, Seq(MEMORY_LRSC -> False))
|
||||
)
|
||||
decoderService.add(
|
||||
key = LR,
|
||||
values = loadActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
MEMORY_ATOMIC -> True
|
||||
SRC_ADD_ZERO -> True,
|
||||
MEMORY_LRSC -> True
|
||||
)
|
||||
)
|
||||
decoderService.add(
|
||||
key = SC,
|
||||
values = storeActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
SRC_ADD_ZERO -> True,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
MEMORY_ATOMIC -> True
|
||||
MEMORY_LRSC -> True
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if(withAmo){
|
||||
List(LB, LH, LW, LBU, LHU, LWU, SB, SH, SW).foreach(e =>
|
||||
decoderService.add(e, Seq(MEMORY_AMO -> False))
|
||||
)
|
||||
val amoActions = storeActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
SRC_ADD_ZERO -> True,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
MEMORY_AMO -> True
|
||||
)
|
||||
|
||||
for(i <- List(AMOSWAP, AMOADD, AMOXOR, AMOAND, AMOOR, AMOMIN, AMOMAX, AMOMINU, AMOMAXU)){
|
||||
decoderService.add(i, amoActions)
|
||||
}
|
||||
}
|
||||
|
||||
if(withAmo && withLrSc){
|
||||
for(i <- List(AMOSWAP, AMOADD, AMOXOR, AMOAND, AMOOR, AMOMIN, AMOMAX, AMOMINU, AMOMAXU)){
|
||||
decoderService.add(i, List(MEMORY_LRSC -> False))
|
||||
}
|
||||
for(i <- List(LR, SC)){
|
||||
decoderService.add(i, List(MEMORY_AMO -> False))
|
||||
}
|
||||
}
|
||||
|
||||
def MANAGEMENT = M"-------00000-----101-----0001111"
|
||||
decoderService.add(MANAGEMENT, stdActions ++ List(
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
RS2_USE -> True,
|
||||
|
||||
decoderService.addDefault(MEMORY_MANAGMENT, False)
|
||||
decoderService.add(MANAGEMENT, List(
|
||||
MEMORY_MANAGMENT -> True
|
||||
))
|
||||
|
||||
decoderService.add(FENCE, Nil)
|
||||
|
||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig)
|
||||
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.writeBack != null) pipeline.writeBack else pipeline.execute)
|
||||
|
||||
if(catchSomething)
|
||||
exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack)
|
||||
|
@ -105,25 +151,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
if(pipeline.serviceExist(classOf[PrivilegeService]))
|
||||
privilegeService = pipeline.service(classOf[PrivilegeService])
|
||||
|
||||
if(pipeline.serviceExist(classOf[ReportService])){
|
||||
val report = pipeline.service(classOf[ReportService])
|
||||
report.add("dBus" -> {
|
||||
val e = new BusReport()
|
||||
val c = new CacheReport()
|
||||
e.kind = "cached"
|
||||
e.flushInstructions.add(0x13 | (1 << 7)) ////ADDI x1, x0, 0
|
||||
for(idx <- 0 until cacheSize by bytePerLine){
|
||||
e.flushInstructions.add(0x7000500F + (1 << 15)) //Clean invalid data cache way x1
|
||||
e.flushInstructions.add(0x13 + (1 << 7) + (1 << 15) + (bytePerLine << 20)) //ADDI x1, x1, 32
|
||||
}
|
||||
|
||||
e.info = c
|
||||
c.size = cacheSize
|
||||
c.bytePerLine = bytePerLine
|
||||
|
||||
e
|
||||
})
|
||||
}
|
||||
pipeline.update(DEBUG_BYPASS_CACHE, False)
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -133,36 +161,57 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
dBus = master(DataCacheMemBus(this.config)).setName("dBus")
|
||||
|
||||
val cache = new DataCache(this.config)
|
||||
cache.io.mem <> dBus
|
||||
|
||||
//Interconnect the plugin dBus with the cache dBus with some optional pipelining
|
||||
def optionPipe[T](cond : Boolean, on : T)(f : T => T) : T = if(cond) f(on) else on
|
||||
def cmdBuf = optionPipe(dBusCmdSlavePipe, cache.io.mem.cmd)(_.s2mPipe())
|
||||
dBus.cmd << optionPipe(dBusCmdMasterPipe, cmdBuf)(_.m2sPipe())
|
||||
cache.io.mem.rsp << optionPipe(dBusRspSlavePipe,dBus.rsp)(_.m2sPipe())
|
||||
|
||||
decode plug new Area {
|
||||
import decode._
|
||||
|
||||
when(mmuBus.busy && arbitration.isValid && input(MEMORY_ENABLE)) {
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
}
|
||||
|
||||
execute plug new Area {
|
||||
import execute._
|
||||
|
||||
val size = input(INSTRUCTION)(13 downto 12).asUInt
|
||||
cache.io.cpu.execute.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.execute.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.execute.address := input(SRC_ADD).asUInt
|
||||
cache.io.cpu.execute.args.wr := input(MEMORY_WR)
|
||||
cache.io.cpu.execute.args.address := input(SRC_ADD).asUInt
|
||||
cache.io.cpu.execute.args.data := size.mux(
|
||||
U(0) -> input(RS2)( 7 downto 0) ## input(RS2)( 7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0),
|
||||
U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0),
|
||||
default -> input(RS2)(31 downto 0)
|
||||
)
|
||||
cache.io.cpu.execute.args.size := size
|
||||
cache.io.cpu.execute.args.forceUncachedAccess := False
|
||||
cache.io.cpu.execute.args.kind := input(MEMORY_MANAGMENT) ? DataCacheCpuCmdKind.MANAGMENT | DataCacheCpuCmdKind.MEMORY
|
||||
cache.io.cpu.execute.args.clean := input(INSTRUCTION)(28)
|
||||
cache.io.cpu.execute.args.invalidate := input(INSTRUCTION)(29)
|
||||
cache.io.cpu.execute.args.way := input(INSTRUCTION)(30)
|
||||
if(genAtomic) {
|
||||
cache.io.cpu.execute.args.isAtomic := False
|
||||
when(input(MEMORY_ATOMIC)){
|
||||
cache.io.cpu.execute.args.isAtomic := True
|
||||
cache.io.cpu.execute.args.address := input(SRC1).asUInt
|
||||
|
||||
|
||||
cache.io.cpu.flush.valid := arbitration.isValid && input(MEMORY_MANAGMENT)
|
||||
arbitration.haltItself setWhen(cache.io.cpu.flush.isStall)
|
||||
|
||||
if(withLrSc) {
|
||||
cache.io.cpu.execute.args.isLrsc := False
|
||||
when(input(MEMORY_LRSC)){
|
||||
cache.io.cpu.execute.args.isLrsc := True
|
||||
}
|
||||
}
|
||||
|
||||
insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.args.address(1 downto 0)
|
||||
if(withAmo){
|
||||
cache.io.cpu.execute.isAmo := input(MEMORY_AMO)
|
||||
cache.io.cpu.execute.amoCtrl.alu := input(INSTRUCTION)(31 downto 29)
|
||||
cache.io.cpu.execute.amoCtrl.swap := input(INSTRUCTION)(27)
|
||||
}
|
||||
|
||||
insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.address(1 downto 0)
|
||||
|
||||
when(cache.io.cpu.redo && arbitration.isValid && input(MEMORY_ENABLE)){
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
}
|
||||
|
||||
memory plug new Area{
|
||||
|
@ -170,33 +219,52 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.memory.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.memory.isRemoved := arbitration.removeIt
|
||||
arbitration.haltItself setWhen(cache.io.cpu.memory.haltIt)
|
||||
cache.io.cpu.memory.address := U(input(REGFILE_WRITE_DATA))
|
||||
|
||||
cache.io.cpu.memory.mmuBus <> mmuBus
|
||||
arbitration.haltItself setWhen (mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss)
|
||||
cache.io.cpu.memory.mmuBus.rsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite)
|
||||
}
|
||||
|
||||
writeBack plug new Area{
|
||||
import writeBack._
|
||||
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser(writeBack) else False)
|
||||
if(genAtomic) cache.io.cpu.writeBack.clearAtomicEntries := service(classOf[IContextSwitching]).isContextSwitching
|
||||
cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser() else False)
|
||||
cache.io.cpu.writeBack.address := U(input(REGFILE_WRITE_DATA))
|
||||
if(withLrSc) cache.io.cpu.writeBack.clearLrsc := service(classOf[IContextSwitching]).isContextSwitching
|
||||
|
||||
redoBranch.valid := False
|
||||
redoBranch.payload := input(PC)
|
||||
arbitration.flushAll setWhen(redoBranch.valid)
|
||||
|
||||
if(catchSomething) {
|
||||
exceptionBus.valid := cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess
|
||||
exceptionBus.badAddr := cache.io.cpu.writeBack.badAddr
|
||||
exceptionBus.valid := False //cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess
|
||||
exceptionBus.badAddr := U(input(REGFILE_WRITE_DATA))
|
||||
exceptionBus.code.assignDontCare()
|
||||
when(cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.accessError){
|
||||
}
|
||||
|
||||
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE)) {
|
||||
if (catchAccessError) when(cache.io.cpu.writeBack.accessError) {
|
||||
exceptionBus.valid := True
|
||||
exceptionBus.code := (input(MEMORY_WR) ? U(7) | U(5)).resized
|
||||
}
|
||||
when(cache.io.cpu.writeBack.unalignedAccess){
|
||||
|
||||
if (catchUnaligned) when(cache.io.cpu.writeBack.unalignedAccess) {
|
||||
exceptionBus.valid := True
|
||||
exceptionBus.code := (input(MEMORY_WR) ? U(6) | U(4)).resized
|
||||
}
|
||||
when(cache.io.cpu.writeBack.mmuMiss){
|
||||
exceptionBus.code := 13
|
||||
if(catchIllegal) when (cache.io.cpu.writeBack.mmuException) {
|
||||
exceptionBus.valid := True
|
||||
exceptionBus.code := (input(MEMORY_WR) ? U(15) | U(13)).resized
|
||||
}
|
||||
|
||||
when(cache.io.cpu.redo) {
|
||||
redoBranch.valid := True
|
||||
if(catchSomething) exceptionBus.valid := False
|
||||
}
|
||||
}
|
||||
|
||||
arbitration.haltItself.setWhen(cache.io.cpu.writeBack.haltIt)
|
||||
|
||||
val rspShifted = Bits(32 bits)
|
||||
|
@ -218,6 +286,49 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
|||
}
|
||||
}
|
||||
|
||||
//Share access to the dBus (used by self refilled MMU)
|
||||
if(dBusAccess != null) pipeline plug new Area{
|
||||
dBusAccess.cmd.ready := False
|
||||
val forceDatapath = False
|
||||
when(dBusAccess.cmd.valid){
|
||||
decode.arbitration.haltByOther := True
|
||||
val exceptionService = pipeline.service(classOf[ExceptionService])
|
||||
when(!stagesFromExecute.map(s => s.arbitration.isValid || exceptionService.isExceptionPending(s)).orR){
|
||||
when(!cache.io.cpu.redo) {
|
||||
cache.io.cpu.execute.isValid := True
|
||||
dBusAccess.cmd.ready := !execute.arbitration.isStuck
|
||||
}
|
||||
cache.io.cpu.execute.args.wr := dBusAccess.cmd.write
|
||||
cache.io.cpu.execute.args.data := dBusAccess.cmd.data
|
||||
cache.io.cpu.execute.args.size := dBusAccess.cmd.size
|
||||
if(withLrSc) cache.io.cpu.execute.args.isLrsc := False
|
||||
if(withAmo) cache.io.cpu.execute.args.isAmo := False
|
||||
cache.io.cpu.execute.address := dBusAccess.cmd.address //Will only be 12 muxes
|
||||
forceDatapath := True
|
||||
}
|
||||
}
|
||||
execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire
|
||||
|
||||
|
||||
mmuBus.cmd.bypassTranslation setWhen(memory.input(IS_DBUS_SHARING))
|
||||
cache.io.cpu.memory.isValid setWhen(memory.input(IS_DBUS_SHARING))
|
||||
cache.io.cpu.writeBack.isValid setWhen(writeBack.input(IS_DBUS_SHARING))
|
||||
dBusAccess.rsp.valid := writeBack.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt)
|
||||
dBusAccess.rsp.data := cache.io.cpu.writeBack.data
|
||||
dBusAccess.rsp.error := cache.io.cpu.writeBack.unalignedAccess || cache.io.cpu.writeBack.accessError
|
||||
dBusAccess.rsp.redo := cache.io.cpu.redo
|
||||
component.addPrePopTask{() =>
|
||||
when(forceDatapath){
|
||||
execute.output(REGFILE_WRITE_DATA) := dBusAccess.cmd.address.asBits
|
||||
}
|
||||
memory.input(IS_DBUS_SHARING) init(False)
|
||||
writeBack.input(IS_DBUS_SHARING) init(False)
|
||||
when(dBusAccess.rsp.valid){
|
||||
writeBack.input(IS_DBUS_SHARING).getDrivingReg := False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(csrInfo){
|
||||
val csr = service(classOf[CsrPlugin])
|
||||
csr.r(0xCC0, 0 -> U(cacheSize/wayCount), 20 -> U(bytePerLine))
|
||||
|
|
|
@ -9,6 +9,8 @@ import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
|||
import spinal.lib.bus.simple._
|
||||
import vexriscv.ip.DataCacheMemCmd
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
||||
case class DBusSimpleCmd() extends Bundle{
|
||||
val wr = Bool
|
||||
|
@ -63,6 +65,12 @@ object DBusSimpleBus{
|
|||
useBTE = true,
|
||||
useCTI = true
|
||||
)
|
||||
|
||||
def getPipelinedMemoryBusConfig() = PipelinedMemoryBusConfig(
|
||||
addressWidth = 32,
|
||||
dataWidth = 32
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
||||
|
@ -178,7 +186,8 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
|
|||
}
|
||||
|
||||
def toPipelinedMemoryBus() : PipelinedMemoryBus = {
|
||||
val bus = PipelinedMemoryBus(32,32)
|
||||
val pipelinedMemoryBusConfig = DBusSimpleBus.getPipelinedMemoryBusConfig()
|
||||
val bus = PipelinedMemoryBus(pipelinedMemoryBusConfig)
|
||||
bus.cmd.valid := cmd.valid
|
||||
bus.cmd.write := cmd.wr
|
||||
bus.cmd.address := cmd.address.resized
|
||||
|
@ -202,18 +211,34 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
catchAccessFault : Boolean = false,
|
||||
earlyInjection : Boolean = false, /*, idempotentRegions : (UInt) => Bool = (x) => False*/
|
||||
emitCmdInMemoryStage : Boolean = false,
|
||||
onlyLoadWords : Boolean = false) extends Plugin[VexRiscv]{
|
||||
onlyLoadWords : Boolean = false,
|
||||
withLrSc : Boolean = false,
|
||||
memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] with DBusAccessService {
|
||||
|
||||
var dBus : DBusSimpleBus = null
|
||||
assert(!(emitCmdInMemoryStage && earlyInjection))
|
||||
|
||||
object MEMORY_ENABLE extends Stageable(Bool)
|
||||
object MEMORY_READ_DATA extends Stageable(Bits(32 bits))
|
||||
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
|
||||
object ALIGNEMENT_FAULT extends Stageable(Bool)
|
||||
object MMU_FAULT extends Stageable(Bool)
|
||||
object MMU_RSP extends Stageable(MemoryTranslatorRsp())
|
||||
object MEMORY_ATOMIC extends Stageable(Bool)
|
||||
object ATOMIC_HIT extends Stageable(Bool)
|
||||
object MEMORY_STORE extends Stageable(Bool)
|
||||
|
||||
var memoryExceptionPort : Flow[ExceptionCause] = null
|
||||
var rspStage : Stage = null
|
||||
var mmuBus : MemoryTranslatorBus = null
|
||||
var redoBranch : Flow[UInt] = null
|
||||
val catchSomething = catchAccessFault || catchAddressMisaligned || memoryTranslatorPortConfig != null
|
||||
|
||||
@dontName var dBusAccess : DBusAccess = null
|
||||
override def newDBusAccess(): DBusAccess = {
|
||||
assert(dBusAccess == null)
|
||||
dBusAccess = DBusAccess()
|
||||
dBusAccess
|
||||
}
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
|
@ -233,12 +258,14 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> Bool(earlyInjection)
|
||||
BYPASSABLE_MEMORY_STAGE -> Bool(earlyInjection),
|
||||
MEMORY_STORE -> False
|
||||
) ++ (if(catchAccessFault || catchAddressMisaligned) List(HAS_SIDE_EFFECT -> True) else Nil)
|
||||
|
||||
val storeActions = stdActions ++ List(
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMS,
|
||||
RS2_USE -> True
|
||||
RS2_USE -> True,
|
||||
MEMORY_STORE -> True
|
||||
)
|
||||
|
||||
decoderService.addDefault(MEMORY_ENABLE, False)
|
||||
|
@ -248,12 +275,42 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
)
|
||||
|
||||
|
||||
if(withLrSc){
|
||||
List(LB, LH, LW, LBU, LHU, LWU, SB, SH, SW).foreach(e =>
|
||||
decoderService.add(e, Seq(MEMORY_ATOMIC -> False))
|
||||
)
|
||||
decoderService.add(
|
||||
key = LR,
|
||||
values = loadActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
SRC_ADD_ZERO -> True,
|
||||
MEMORY_ATOMIC -> True
|
||||
)
|
||||
)
|
||||
|
||||
decoderService.add(
|
||||
key = SC,
|
||||
values = storeActions.filter(_._1 != SRC2_CTRL) ++ Seq(
|
||||
SRC_ADD_ZERO -> True,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
MEMORY_ATOMIC -> True
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
decoderService.add(FENCE, Nil)
|
||||
|
||||
rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory)
|
||||
if(catchAccessFault || catchAddressMisaligned) {
|
||||
if(catchSomething) {
|
||||
val exceptionService = pipeline.service(classOf[ExceptionService])
|
||||
memoryExceptionPort = exceptionService.newExceptionPort(rspStage)
|
||||
}
|
||||
|
||||
if(memoryTranslatorPortConfig != null) {
|
||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA, memoryTranslatorPortConfig)
|
||||
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.memory != null) pipeline.memory else pipeline.execute)
|
||||
}
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -263,30 +320,40 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
dBus = master(DBusSimpleBus()).setName("dBus")
|
||||
|
||||
|
||||
decode plug new Area {
|
||||
import decode._
|
||||
|
||||
if(mmuBus != null) when(mmuBus.busy && arbitration.isValid && input(MEMORY_ENABLE)) {
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
}
|
||||
|
||||
//Emit dBus.cmd request
|
||||
val cmdSent = if(rspStage == execute) RegInit(False) setWhen(dBus.cmd.fire) clearWhen(!execute.arbitration.isStuck) else False
|
||||
val cmdStage = if(emitCmdInMemoryStage) memory else execute
|
||||
cmdStage plug new Area{
|
||||
import cmdStage._
|
||||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||
|
||||
val cmdSent = if(rspStage == execute) RegInit(False) setWhen(dBus.cmd.fire) clearWhen(!execute.arbitration.isStuck) else False
|
||||
|
||||
insert(ALIGNEMENT_FAULT) := {
|
||||
if (catchAddressMisaligned)
|
||||
(dBus.cmd.size === 2 && dBus.cmd.address(1 downto 0) =/= 0) || (dBus.cmd.size === 1 && dBus.cmd.address(0 downto 0) =/= 0)
|
||||
else
|
||||
False
|
||||
}
|
||||
if (catchAddressMisaligned)
|
||||
insert(ALIGNEMENT_FAULT) := (dBus.cmd.size === 2 && dBus.cmd.address(1 downto 0) =/= 0) || (dBus.cmd.size === 1 && dBus.cmd.address(0 downto 0) =/= 0)
|
||||
else
|
||||
insert(ALIGNEMENT_FAULT) := False
|
||||
|
||||
dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.isFlushed && !input(ALIGNEMENT_FAULT) && !cmdSent
|
||||
dBus.cmd.wr := input(INSTRUCTION)(5)
|
||||
dBus.cmd.address := input(SRC_ADD).asUInt
|
||||
|
||||
val skipCmd = False
|
||||
skipCmd setWhen(input(ALIGNEMENT_FAULT))
|
||||
|
||||
dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.isFlushed && !skipCmd && !cmdSent
|
||||
dBus.cmd.wr := input(MEMORY_STORE)
|
||||
dBus.cmd.size := input(INSTRUCTION)(13 downto 12).asUInt
|
||||
dBus.cmd.payload.data := dBus.cmd.size.mux (
|
||||
U(0) -> input(RS2)(7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0),
|
||||
U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0),
|
||||
default -> input(RS2)(31 downto 0)
|
||||
)
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !input(ALIGNEMENT_FAULT) && !cmdSent){
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !skipCmd && !cmdSent){
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
|
||||
|
@ -298,10 +365,45 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
U(1) -> B"0011",
|
||||
default -> B"1111"
|
||||
) |<< dBus.cmd.address(1 downto 0)
|
||||
|
||||
insert(FORMAL_MEM_ADDR) := dBus.cmd.address & U"xFFFFFFFC"
|
||||
insert(FORMAL_MEM_WMASK) := (dBus.cmd.valid && dBus.cmd.wr) ? formalMask | B"0000"
|
||||
insert(FORMAL_MEM_RMASK) := (dBus.cmd.valid && !dBus.cmd.wr) ? formalMask | B"0000"
|
||||
insert(FORMAL_MEM_WDATA) := dBus.cmd.payload.data
|
||||
|
||||
val mmu = (mmuBus != null) generate new Area {
|
||||
mmuBus.cmd.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
mmuBus.cmd.virtualAddress := input(SRC_ADD).asUInt
|
||||
mmuBus.cmd.bypassTranslation := False
|
||||
mmuBus.end := !arbitration.isStuck || arbitration.isRemoved
|
||||
dBus.cmd.address := mmuBus.rsp.physicalAddress
|
||||
|
||||
//do not emit memory request if MMU refilling
|
||||
insert(MMU_FAULT) := input(MMU_RSP).exception || (!input(MMU_RSP).allowWrite && input(MEMORY_STORE)) || (!input(MMU_RSP).allowRead && !input(MEMORY_STORE))
|
||||
skipCmd.setWhen(input(MMU_FAULT) || input(MMU_RSP).refilling)
|
||||
|
||||
insert(MMU_RSP) := mmuBus.rsp
|
||||
}
|
||||
|
||||
val mmuLess = (mmuBus == null) generate new Area{
|
||||
dBus.cmd.address := input(SRC_ADD).asUInt
|
||||
}
|
||||
|
||||
|
||||
val atomic = withLrSc generate new Area{
|
||||
val reserved = RegInit(False)
|
||||
insert(ATOMIC_HIT) := reserved
|
||||
when(arbitration.isFiring && input(MEMORY_ENABLE) && input(MEMORY_ATOMIC) && !input(MEMORY_STORE)){
|
||||
reserved := True
|
||||
}
|
||||
when(service(classOf[IContextSwitching]).isContextSwitching){
|
||||
reserved := False
|
||||
}
|
||||
|
||||
when(input(MEMORY_STORE) && input(MEMORY_ATOMIC) && !input(ATOMIC_HIT)){
|
||||
skipCmd := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Collect dBus.rsp read responses
|
||||
|
@ -310,28 +412,44 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
|
||||
|
||||
insert(MEMORY_READ_DATA) := dBus.rsp.data
|
||||
arbitration.haltItself setWhen(arbitration.isValid && input(MEMORY_ENABLE) && !input(INSTRUCTION)(5) && !dBus.rsp.ready)
|
||||
|
||||
if(catchAccessFault || catchAddressMisaligned){
|
||||
if(!catchAccessFault){
|
||||
memoryExceptionPort.code := (input(INSTRUCTION)(5) ? U(6) | U(4)).resized
|
||||
memoryExceptionPort.valid := input(ALIGNEMENT_FAULT)
|
||||
} else if(!catchAddressMisaligned){
|
||||
memoryExceptionPort.valid := dBus.rsp.ready && dBus.rsp.error && !input(INSTRUCTION)(5)
|
||||
memoryExceptionPort.code := 5
|
||||
} else {
|
||||
memoryExceptionPort.valid := dBus.rsp.ready && dBus.rsp.error && !input(INSTRUCTION)(5)
|
||||
memoryExceptionPort.code := 5
|
||||
when(input(ALIGNEMENT_FAULT)){
|
||||
memoryExceptionPort.code := (input(INSTRUCTION)(5) ? U(6) | U(4)).resized
|
||||
arbitration.haltItself setWhen(arbitration.isValid && input(MEMORY_ENABLE) && !input(MEMORY_STORE) && (!dBus.rsp.ready || (if(rspStage == execute) !cmdSent else False)))
|
||||
|
||||
if(catchSomething) {
|
||||
memoryExceptionPort.valid := False
|
||||
memoryExceptionPort.code.assignDontCare()
|
||||
memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt
|
||||
|
||||
if(catchAccessFault) when(dBus.rsp.ready && dBus.rsp.error && !input(MEMORY_STORE)) {
|
||||
memoryExceptionPort.valid := True
|
||||
memoryExceptionPort.code := 5
|
||||
}
|
||||
|
||||
if(catchAddressMisaligned) when(input(ALIGNEMENT_FAULT)){
|
||||
memoryExceptionPort.code := (input(MEMORY_STORE) ? U(6) | U(4)).resized
|
||||
memoryExceptionPort.valid := True
|
||||
}
|
||||
|
||||
if(memoryTranslatorPortConfig != null) {
|
||||
redoBranch.valid := False
|
||||
redoBranch.payload := input(PC)
|
||||
|
||||
when(input(MMU_RSP).refilling){
|
||||
redoBranch.valid := True
|
||||
memoryExceptionPort.valid := False
|
||||
} elsewhen(input(MMU_FAULT)) {
|
||||
memoryExceptionPort.valid := True
|
||||
memoryExceptionPort.code := (input(MEMORY_STORE) ? U(15) | U(13)).resized
|
||||
}
|
||||
}
|
||||
when(!(arbitration.isValid && input(MEMORY_ENABLE) && (if(cmdStage == rspStage) !arbitration.isStuckByOthers else True))){
|
||||
memoryExceptionPort.valid := False
|
||||
|
||||
arbitration.flushAll setWhen(redoBranch.valid)
|
||||
}
|
||||
|
||||
when(!(arbitration.isValid && input(MEMORY_ENABLE) && (Bool(cmdStage != rspStage) || !arbitration.isStuckByOthers))){
|
||||
if(catchSomething) memoryExceptionPort.valid := False
|
||||
if(memoryTranslatorPortConfig != null) redoBranch.valid := False
|
||||
}
|
||||
|
||||
memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt //Drived by IntAluPlugin
|
||||
}
|
||||
|
||||
|
||||
|
@ -360,13 +478,58 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE)) {
|
||||
output(REGFILE_WRITE_DATA) := (if(!onlyLoadWords) rspFormated else input(MEMORY_READ_DATA))
|
||||
if(withLrSc){
|
||||
when(input(MEMORY_ATOMIC) && input(MEMORY_STORE)){
|
||||
output(REGFILE_WRITE_DATA) := (!input(ATOMIC_HIT)).asBits.resized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!earlyInjection && !emitCmdInMemoryStage && config.withWriteBackStage)
|
||||
assert(!(arbitration.isValid && input(MEMORY_ENABLE) && !input(INSTRUCTION)(5) && arbitration.isStuck),"DBusSimplePlugin doesn't allow writeback stage stall when read happend")
|
||||
assert(!(arbitration.isValid && input(MEMORY_ENABLE) && !input(MEMORY_STORE) && arbitration.isStuck),"DBusSimplePlugin doesn't allow writeback stage stall when read happend")
|
||||
|
||||
//formal
|
||||
insert(FORMAL_MEM_RDATA) := input(MEMORY_READ_DATA)
|
||||
}
|
||||
|
||||
//Share access to the dBus (used by self refilled MMU)
|
||||
val dBusSharing = (dBusAccess != null) generate new Area{
|
||||
val state = Reg(UInt(2 bits)) init(0)
|
||||
dBusAccess.cmd.ready := False
|
||||
dBusAccess.rsp.valid := False
|
||||
dBusAccess.rsp.data := dBus.rsp.data
|
||||
dBusAccess.rsp.error := dBus.rsp.error
|
||||
dBusAccess.rsp.redo := False
|
||||
|
||||
switch(state){
|
||||
is(0){
|
||||
when(dBusAccess.cmd.valid){
|
||||
decode.arbitration.haltItself := True
|
||||
when(!stages.dropWhile(_ != execute).map(_.arbitration.isValid).orR){
|
||||
state := 1
|
||||
}
|
||||
}
|
||||
}
|
||||
is(1){
|
||||
decode.arbitration.haltItself := True
|
||||
dBus.cmd.valid := True
|
||||
dBus.cmd.address := dBusAccess.cmd.address
|
||||
dBus.cmd.wr := dBusAccess.cmd.write
|
||||
dBus.cmd.data := dBusAccess.cmd.data
|
||||
dBus.cmd.size := dBusAccess.cmd.size
|
||||
when(dBus.cmd.ready){
|
||||
state := (dBusAccess.cmd.write ? U(0) | U(2))
|
||||
dBusAccess.cmd.ready := True
|
||||
}
|
||||
}
|
||||
is(2){
|
||||
decode.arbitration.haltItself := True
|
||||
when(dBus.rsp.ready){
|
||||
dBusAccess.rsp.valid := True
|
||||
state := 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,8 +141,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
|||
val haltIt = RegInit(False)
|
||||
val stepIt = RegInit(False)
|
||||
|
||||
val isPipActive = RegNext(stages.map(_.arbitration.isValid).orR)
|
||||
val isPipBusy = isPipActive || RegNext(isPipActive)
|
||||
val isPipBusy = RegNext(stages.map(_.arbitration.isValid).orR || iBusFetcher.incoming())
|
||||
val godmode = RegInit(False) setWhen(haltIt && !isPipBusy)
|
||||
val haltedByBreak = RegInit(False)
|
||||
|
||||
val hardwareBreakpoints = Vec(Reg(new Bundle{
|
||||
|
@ -176,6 +176,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
|||
resetIt setWhen (io.bus.cmd.data(16)) clearWhen (io.bus.cmd.data(24))
|
||||
haltIt setWhen (io.bus.cmd.data(17)) clearWhen (io.bus.cmd.data(25))
|
||||
haltedByBreak clearWhen (io.bus.cmd.data(25))
|
||||
godmode clearWhen(io.bus.cmd.data(25))
|
||||
}
|
||||
}
|
||||
is(0x1) {
|
||||
|
@ -219,10 +220,6 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
|||
}
|
||||
}
|
||||
|
||||
when(stepIt && Cat(pipeline.stages.map(_.arbitration.redoIt)).asBits.orR) {
|
||||
haltIt := False
|
||||
}
|
||||
|
||||
//Avoid having two C instruction executed in a single step
|
||||
if(pipeline(RVC_GEN)){
|
||||
val cleanStep = RegNext(stepIt && decode.arbitration.isFiring) init(False)
|
||||
|
@ -236,10 +233,17 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
|||
service(classOf[InterruptionInhibitor]).inhibateInterrupts()
|
||||
}
|
||||
}
|
||||
if(serviceExist(classOf[ExceptionInhibitor])) {
|
||||
when(haltIt) {
|
||||
service(classOf[ExceptionInhibitor]).inhibateException()
|
||||
|
||||
when(godmode) {
|
||||
pipeline.plugins.foreach{
|
||||
case p : ExceptionInhibitor => p.inhibateException()
|
||||
case _ =>
|
||||
}
|
||||
pipeline.plugins.foreach{
|
||||
case p : PrivilegeService => p.forceMachine()
|
||||
case _ =>
|
||||
}
|
||||
if(pipeline.things.contains(DEBUG_BYPASS_CACHE)) pipeline(DEBUG_BYPASS_CACHE) := True
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
|
|
@ -66,8 +66,8 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
}
|
||||
}
|
||||
|
||||
val defaults = mutable.HashMap[Stageable[_ <: BaseType], BaseType]()
|
||||
val encodings = mutable.HashMap[MaskedLiteral,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]]()
|
||||
val defaults = mutable.LinkedHashMap[Stageable[_ <: BaseType], BaseType]()
|
||||
val encodings = mutable.LinkedHashMap[MaskedLiteral,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]]()
|
||||
var decodeExceptionPort : Flow[ExceptionCause] = null
|
||||
|
||||
|
||||
|
@ -105,7 +105,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
} else {
|
||||
var offset = 0
|
||||
var defaultValue, defaultCare = BigInt(0)
|
||||
val offsetOf = mutable.HashMap[Stageable[_ <: BaseType], Int]()
|
||||
val offsetOf = mutable.LinkedHashMap[Stageable[_ <: BaseType], Int]()
|
||||
|
||||
//Build defaults value and field offset map
|
||||
stageables.foreach(e => {
|
||||
|
@ -160,7 +160,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
if(catchIllegalInstruction){
|
||||
decodeExceptionPort.valid := arbitration.isValid && input(INSTRUCTION_READY) && !input(LEGAL_INSTRUCTION) // ?? HalitIt to alow decoder stage to wait valid data from 2 stages cache cache ??
|
||||
decodeExceptionPort.code := 2
|
||||
decodeExceptionPort.badAddr.assignDontCare()
|
||||
decodeExceptionPort.badAddr := input(INSTRUCTION).asUInt
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,8 +191,8 @@ object DecodingBench extends App{
|
|||
|
||||
|
||||
object Symplify{
|
||||
val cache = mutable.HashMap[Bits,mutable.HashMap[Masked,Bool]]()
|
||||
def getCache(addr : Bits) = cache.getOrElseUpdate(addr,mutable.HashMap[Masked,Bool]())
|
||||
val cache = mutable.LinkedHashMap[Bits,mutable.LinkedHashMap[Masked,Bool]]()
|
||||
def getCache(addr : Bits) = cache.getOrElseUpdate(addr,mutable.LinkedHashMap[Masked,Bool]())
|
||||
|
||||
//Generate terms logic for the given input
|
||||
def logicOf(input : Bits,terms : Seq[Masked]) = terms.map(t => getCache(input).getOrElseUpdate(t,t === input)).asBits.orR
|
||||
|
|
|
@ -20,7 +20,8 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
val injectorReadyCutGen : Boolean,
|
||||
val prediction : BranchPrediction,
|
||||
val historyRamSizeLog2 : Int,
|
||||
val injectorStage : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{
|
||||
val injectorStage : Boolean,
|
||||
val relaxPredictorAddress : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{
|
||||
var prefetchExceptionPort : Flow[ExceptionCause] = null
|
||||
var decodePrediction : DecodePredictionBus = null
|
||||
var fetchPrediction : FetchPredictionBus = null
|
||||
|
@ -284,7 +285,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
bufferData := input.rsp.inst(31 downto 16)
|
||||
}
|
||||
bufferValid.clearWhen(flush)
|
||||
iBusRsp.readyForError.clearWhen(bufferValid && isRvc)
|
||||
iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending
|
||||
incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3)
|
||||
})
|
||||
|
||||
|
@ -293,19 +294,21 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
val injector = new Area {
|
||||
val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(flush))
|
||||
if (injectorReadyCutGen) {
|
||||
iBusRsp.readyForError.clearWhen(inputBeforeStage.valid)
|
||||
iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe
|
||||
incomingInstruction setWhen (inputBeforeStage.valid)
|
||||
}
|
||||
val decodeInput = (if (injectorStage) {
|
||||
val decodeInput = inputBeforeStage.m2sPipeWithFlush(flush, collapsBubble = false)
|
||||
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst)
|
||||
iBusRsp.readyForError.clearWhen(decodeInput.valid)
|
||||
iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer
|
||||
incomingInstruction setWhen (decodeInput.valid)
|
||||
decodeInput
|
||||
} else {
|
||||
inputBeforeStage
|
||||
})
|
||||
|
||||
if(!decodePcGen) iBusRsp.readyForError.clearWhen(!pcValid(decode)) //Need to wait a valid PC on the decode stage, as it is use to fill CSR xEPC
|
||||
|
||||
|
||||
def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = {
|
||||
stucks.scanLeft(input)((i, stuck) => {
|
||||
|
@ -488,8 +491,17 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
|
||||
decodePrediction.cmd.hadBranch := decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (decode.input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction)
|
||||
|
||||
val noPredictionOnMissaligned = (!pipeline(RVC_GEN)) generate new Area{
|
||||
val missaligned = decode.input(BRANCH_CTRL).mux(
|
||||
BranchCtrlEnum.JAL -> imm.j_sext(1),
|
||||
default -> imm.b_sext(1)
|
||||
)
|
||||
decodePrediction.cmd.hadBranch clearWhen(missaligned)
|
||||
}
|
||||
|
||||
predictionJumpInterface.valid := decodePrediction.cmd.hadBranch && decode.arbitration.isFiring //TODO OH Doublon de priorité
|
||||
predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt
|
||||
if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload)
|
||||
|
||||
// when(predictionJumpInterface.payload((if(pipeline(RVC_GEN)) 0 else 1) downto 0) =/= 0){
|
||||
// decodePrediction.cmd.hadBranch := False
|
||||
|
@ -605,5 +617,10 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
def stageXToIBusRsp[T <: Data](stage : Any, input : T): (T) ={
|
||||
iBusRsp.stages.dropWhile(_ != stage).tail.foldLeft(input)((data,stage) => RegNextWhen(data, stage.output.ready))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -21,6 +21,8 @@ class HaltOnExceptionPlugin() extends Plugin[VexRiscv] with ExceptionService {
|
|||
exceptionPortsInfos += ExceptionPortInfo(interface,stage,priority)
|
||||
interface
|
||||
}
|
||||
override def isExceptionPending(stage : Stage): Bool = False
|
||||
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
|
|
|
@ -34,7 +34,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
config : InstructionCacheConfig,
|
||||
memoryTranslatorPortConfig : Any = null,
|
||||
injectorStage : Boolean = false,
|
||||
withoutInjectorStage : Boolean = false) extends IBusFetcherImpl(
|
||||
withoutInjectorStage : Boolean = false,
|
||||
relaxPredictorAddress : Boolean = true) extends IBusFetcherImpl(
|
||||
resetVector = resetVector,
|
||||
keepPcPlus4 = keepPcPlus4,
|
||||
decodePcGen = compressedGen,
|
||||
|
@ -44,9 +45,14 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
injectorReadyCutGen = false,
|
||||
prediction = prediction,
|
||||
historyRamSizeLog2 = historyRamSizeLog2,
|
||||
injectorStage = (!config.twoCycleCache && !withoutInjectorStage) || injectorStage){
|
||||
injectorStage = (!config.twoCycleCache && !withoutInjectorStage) || injectorStage,
|
||||
relaxPredictorAddress = relaxPredictorAddress){
|
||||
import config._
|
||||
|
||||
assert(isPow2(cacheSize))
|
||||
assert(!(memoryTranslatorPortConfig != null && config.cacheSize/config.wayCount > 4096), "When the I$ is used with MMU, each way can't be bigger than a page (4096 bytes)")
|
||||
|
||||
|
||||
assert(!(withoutInjectorStage && injectorStage))
|
||||
|
||||
var iBus : InstructionCacheMemBus = null
|
||||
|
@ -74,11 +80,9 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
|
||||
super.setup(pipeline)
|
||||
|
||||
def MANAGEMENT = M"-----------------100-----0001111"
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.addDefault(FLUSH_ALL, False)
|
||||
decoderService.add(MANAGEMENT, List(
|
||||
decoderService.add(FENCE_I, List(
|
||||
FLUSH_ALL -> True
|
||||
))
|
||||
|
||||
|
@ -101,7 +105,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
val e = new BusReport()
|
||||
val c = new CacheReport()
|
||||
e.kind = "cached"
|
||||
e.flushInstructions.add(0x400F) //invalid instruction cache
|
||||
e.flushInstructions.add(0x100F) //FENCE.I
|
||||
e.flushInstructions.add(0x13)
|
||||
e.flushInstructions.add(0x13)
|
||||
e.flushInstructions.add(0x13)
|
||||
|
@ -163,8 +167,11 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
cache.io.cpu.fetch.isStuck := !stages(1).input.ready
|
||||
cache.io.cpu.fetch.pc := stages(1).input.payload
|
||||
|
||||
|
||||
stages(1).halt setWhen(cache.io.cpu.fetch.haltIt)
|
||||
|
||||
if (!twoCycleCache) {
|
||||
cache.io.cpu.fetch.isUser := privilegeService.isUser(decode)
|
||||
cache.io.cpu.fetch.isUser := privilegeService.isUser()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,7 +180,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
cache.io.cpu.decode.isValid := stages(2).input.valid && !tightlyCoupledHit
|
||||
cache.io.cpu.decode.isStuck := !stages(2).input.ready
|
||||
cache.io.cpu.decode.pc := stages(2).input.payload
|
||||
cache.io.cpu.decode.isUser := privilegeService.isUser(decode)
|
||||
cache.io.cpu.decode.isUser := privilegeService.isUser()
|
||||
|
||||
if ((!twoCycleRam || wayCount == 1) && !compressedGen && !injectorStage) {
|
||||
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), cache.io.cpu.fetch.data)
|
||||
|
@ -186,34 +193,51 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
val cacheRsp = if (twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch
|
||||
val cacheRspArbitration = stages(if (twoCycleCache) 2 else 1)
|
||||
var issueDetected = False
|
||||
val redoFetch = False //RegNext(False) init(False)
|
||||
when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected) {
|
||||
issueDetected \= True
|
||||
redoFetch := iBusRsp.readyForError
|
||||
}
|
||||
val redoFetch = False
|
||||
|
||||
|
||||
//Refill / redo
|
||||
assert(decodePcGen == compressedGen)
|
||||
cache.io.cpu.fill.valid := redoFetch
|
||||
cache.io.cpu.fill.valid := redoFetch && !cacheRsp.mmuRefilling
|
||||
cache.io.cpu.fill.payload := cacheRsp.physicalAddress
|
||||
redoBranch.valid := redoFetch
|
||||
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
|
||||
|
||||
|
||||
if (catchSomething) {
|
||||
val accessFault = if (catchAccessFault) cacheRsp.error else False
|
||||
val mmuMiss = if (catchMemoryTranslationMiss) cacheRsp.mmuMiss else False
|
||||
val illegalAccess = if (catchIllegalAccess) cacheRsp.illegalAccess else False
|
||||
|
||||
decodeExceptionPort.valid := False
|
||||
decodeExceptionPort.code := mmuMiss ? U(14) | 1
|
||||
decodeExceptionPort.badAddr := cacheRsp.pc
|
||||
when(cacheRsp.isValid && (accessFault || mmuMiss || illegalAccess) && !issueDetected) {
|
||||
issueDetected \= True
|
||||
decodeExceptionPort.valid := iBusRsp.readyForError
|
||||
}
|
||||
decodeExceptionPort.code.assignDontCare()
|
||||
decodeExceptionPort.badAddr := cacheRsp.pc(31 downto 2) @@ "00"
|
||||
}
|
||||
|
||||
when(cacheRsp.isValid && cacheRsp.mmuRefilling && !issueDetected) {
|
||||
issueDetected \= True
|
||||
redoFetch := True
|
||||
}
|
||||
|
||||
if(catchIllegalAccess) when(cacheRsp.isValid && cacheRsp.mmuException && !issueDetected) {
|
||||
issueDetected \= True
|
||||
decodeExceptionPort.valid := iBusRsp.readyForError
|
||||
decodeExceptionPort.code := 12
|
||||
}
|
||||
|
||||
when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected) {
|
||||
issueDetected \= True
|
||||
cache.io.cpu.fill.valid := True
|
||||
redoFetch := True
|
||||
}
|
||||
|
||||
if(catchAccessFault) when(cacheRsp.isValid && cacheRsp.error && !issueDetected) {
|
||||
issueDetected \= True
|
||||
decodeExceptionPort.valid := iBusRsp.readyForError
|
||||
decodeExceptionPort.code := 1
|
||||
}
|
||||
|
||||
redoFetch clearWhen(!iBusRsp.readyForError)
|
||||
cache.io.cpu.fill.valid clearWhen(!iBusRsp.readyForError)
|
||||
if (catchSomething) decodeExceptionPort.valid clearWhen(fetcherHalt)
|
||||
|
||||
redoBranch.valid := redoFetch
|
||||
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
|
||||
|
||||
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
|
||||
iBusRsp.output.valid := cacheRspArbitration.output.valid
|
||||
cacheRspArbitration.output.ready := iBusRsp.output.ready
|
||||
|
@ -223,31 +247,19 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
|
||||
if (mmuBus != null) {
|
||||
cache.io.cpu.fetch.mmuBus <> mmuBus
|
||||
(if (twoCycleCache) stages(1).halt else rsp.iBusRspOutputHalt) setWhen (mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss)
|
||||
} else {
|
||||
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowRead := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.allowUser := True
|
||||
cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False
|
||||
cache.io.cpu.fetch.mmuBus.rsp.miss := False
|
||||
cache.io.cpu.fetch.mmuBus.rsp.hit := False
|
||||
cache.io.cpu.fetch.mmuBus.rsp.exception := False
|
||||
cache.io.cpu.fetch.mmuBus.rsp.refilling := False
|
||||
cache.io.cpu.fetch.mmuBus.busy := False
|
||||
}
|
||||
|
||||
val flushStage = if(memory != null) memory else execute
|
||||
flushStage plug new Area {
|
||||
import flushStage._
|
||||
|
||||
cache.io.flush.cmd.valid := False
|
||||
when(arbitration.isValid && input(FLUSH_ALL)) {
|
||||
cache.io.flush.cmd.valid := True
|
||||
|
||||
when(!cache.io.flush.cmd.ready) {
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
}
|
||||
}
|
||||
val flushStage = decode
|
||||
cache.io.flush := flushStage.arbitration.isValid && flushStage.input(FLUSH_ALL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import spinal.lib.bus.amba4.axi._
|
|||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||
import spinal.lib.bus.simple._
|
||||
import vexriscv.Riscv.{FENCE, FENCE_I}
|
||||
|
||||
|
||||
case class IBusSimpleCmd() extends Bundle{
|
||||
|
@ -59,6 +60,11 @@ object IBusSimpleBus{
|
|||
useBTE = true,
|
||||
useCTI = true
|
||||
)
|
||||
|
||||
def getPipelinedMemoryBusConfig() = PipelinedMemoryBusConfig(
|
||||
addressWidth = 32,
|
||||
dataWidth = 32
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,7 +142,8 @@ case class IBusSimpleBus(interfaceKeepData : Boolean = false) extends Bundle wit
|
|||
}
|
||||
|
||||
def toPipelinedMemoryBus(): PipelinedMemoryBus = {
|
||||
val bus = PipelinedMemoryBus(32,32)
|
||||
val pipelinedMemoryBusConfig = IBusSimpleBus.getPipelinedMemoryBusConfig()
|
||||
val bus = PipelinedMemoryBus(pipelinedMemoryBusConfig)
|
||||
bus.cmd.arbitrationFrom(cmd)
|
||||
bus.cmd.address := cmd.pc.resized
|
||||
bus.cmd.write := False
|
||||
|
@ -166,7 +173,9 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
pendingMax : Int = 7,
|
||||
injectorStage : Boolean = true,
|
||||
rspHoldValue : Boolean = false,
|
||||
singleInstructionPipeline : Boolean = false
|
||||
singleInstructionPipeline : Boolean = false,
|
||||
memoryTranslatorPortConfig : Any = null,
|
||||
relaxPredictorAddress : Boolean = true
|
||||
) extends IBusFetcherImpl(
|
||||
resetVector = resetVector,
|
||||
keepPcPlus4 = keepPcPlus4,
|
||||
|
@ -177,19 +186,31 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
injectorReadyCutGen = false,
|
||||
prediction = prediction,
|
||||
historyRamSizeLog2 = historyRamSizeLog2,
|
||||
injectorStage = injectorStage){
|
||||
injectorStage = injectorStage,
|
||||
relaxPredictorAddress = relaxPredictorAddress){
|
||||
|
||||
var iBus : IBusSimpleBus = null
|
||||
var decodeExceptionPort : Flow[ExceptionCause] = null
|
||||
val catchSomething = memoryTranslatorPortConfig != null || catchAccessFault
|
||||
var mmuBus : MemoryTranslatorBus = null
|
||||
var redoBranch : Flow[UInt] = null
|
||||
|
||||
if(rspHoldValue) assert(busLatencyMin <= 1)
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
super.setup(pipeline)
|
||||
iBus = master(IBusSimpleBus(false)).setName("iBus")
|
||||
|
||||
if(catchAccessFault) {
|
||||
val exceptionService = pipeline.service(classOf[ExceptionService])
|
||||
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.add(FENCE_I, Nil)
|
||||
|
||||
if(catchSomething) {
|
||||
decodeExceptionPort = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.decode,1)
|
||||
}
|
||||
|
||||
if(memoryTranslatorPortConfig != null) {
|
||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_INSTRUCTION, memoryTranslatorPortConfig)
|
||||
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.decode, priority = 1) //Priority 1 will win against branch predictor
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,16 +220,20 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
|
||||
pipeline plug new FetchArea(pipeline) {
|
||||
var cmd = Stream(IBusSimpleCmd())
|
||||
iBus.cmd << (if(cmdForkPersistence && !cmdForkOnSecondStage) cmd.s2mPipe() else cmd)
|
||||
val cmdWithS2mPipe = cmdForkPersistence && (!cmdForkOnSecondStage || mmuBus != null)
|
||||
iBus.cmd << (if(cmdWithS2mPipe) cmd.s2mPipe() else cmd)
|
||||
|
||||
//Avoid sending to many iBus cmd
|
||||
val pendingCmd = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
|
||||
val pendingCmdNext = pendingCmd + cmd.fire.asUInt - iBus.rsp.fire.asUInt
|
||||
pendingCmd := pendingCmdNext
|
||||
|
||||
val cmdFork = if(!cmdForkPersistence || !cmdForkOnSecondStage) new Area {
|
||||
val secondStagePersistence = cmdForkPersistence && cmdForkOnSecondStage && !cmdWithS2mPipe
|
||||
def cmdForkStage = if(!secondStagePersistence) iBusRsp.stages(if(cmdForkOnSecondStage) 1 else 0) else iBusRsp.stages(1)
|
||||
|
||||
val cmdFork = if(!secondStagePersistence) new Area {
|
||||
//This implementation keep the cmd on the bus until it's executed or the the pipeline is flushed
|
||||
def stage = iBusRsp.stages(if(cmdForkOnSecondStage) 1 else 0)
|
||||
def stage = cmdForkStage
|
||||
stage.halt setWhen(stage.input.valid && (!cmd.valid || !cmd.ready))
|
||||
if(singleInstructionPipeline) {
|
||||
cmd.valid := stage.input.valid && pendingCmd =/= pendingMax && !stages.map(_.arbitration.isValid).orR
|
||||
|
@ -217,16 +242,40 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
}else {
|
||||
cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax
|
||||
}
|
||||
cmd.pc := stage.input.payload(31 downto 2) @@ "00"
|
||||
} else new Area{
|
||||
//This implementation keep the cmd on the bus until it's executed, even if the pipeline is flushed
|
||||
def stage = iBusRsp.stages(1)
|
||||
def stage = cmdForkStage
|
||||
val pendingFull = pendingCmd === pendingMax
|
||||
val cmdKeep = RegInit(False) setWhen(cmd.valid) clearWhen(cmd.ready)
|
||||
val cmdFired = RegInit(False) setWhen(cmd.fire) clearWhen(stage.input.ready)
|
||||
stage.halt setWhen(cmd.isStall || (pendingFull && !cmdFired))
|
||||
cmd.valid := (stage.input.valid || cmdKeep) && !pendingFull && !cmdFired
|
||||
cmd.pc := stage.input.payload(31 downto 2) @@ "00"
|
||||
}
|
||||
|
||||
val mmu = (mmuBus != null) generate new Area {
|
||||
mmuBus.cmd.isValid := cmdForkStage.input.valid
|
||||
mmuBus.cmd.virtualAddress := cmdForkStage.input.payload
|
||||
mmuBus.cmd.bypassTranslation := False
|
||||
mmuBus.end := cmdForkStage.output.fire || flush
|
||||
|
||||
cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00"
|
||||
|
||||
//do not emit memory request if MMU miss
|
||||
when(mmuBus.rsp.exception || mmuBus.rsp.refilling){
|
||||
cmdForkStage.halt := False
|
||||
cmd.valid := False
|
||||
}
|
||||
|
||||
when(mmuBus.busy){
|
||||
cmdForkStage.input.valid := False
|
||||
cmdForkStage.input.ready := False
|
||||
}
|
||||
|
||||
val joinCtx = stageXToIBusRsp(cmdForkStage, mmuBus.rsp)
|
||||
}
|
||||
|
||||
val mmuLess = (mmuBus == null) generate new Area{
|
||||
cmd.pc := cmdForkStage.input.payload(31 downto 2) @@ "00"
|
||||
}
|
||||
|
||||
val rspJoin = new Area {
|
||||
|
@ -235,7 +284,7 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
|
||||
discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt
|
||||
when(flush) {
|
||||
if(cmdForkOnSecondStage && cmdForkPersistence)
|
||||
if(secondStagePersistence)
|
||||
discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt
|
||||
else
|
||||
discardCounter := (if(cmdForkOnSecondStage) pendingCmdNext else pendingCmd - iBus.rsp.fire.asUInt)
|
||||
|
@ -261,24 +310,41 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
fetchRsp.rsp.error.clearWhen(!rspBufferOutput.valid) //Avoid interference with instruction injection from the debug plugin
|
||||
|
||||
|
||||
var issueDetected = False
|
||||
val join = Stream(FetchRsp())
|
||||
val exceptionDetected = False
|
||||
val redoRequired = False
|
||||
join.valid := stages.last.output.valid && rspBufferOutput.valid
|
||||
join.payload := fetchRsp
|
||||
stages.last.output.ready := stages.last.output.valid ? join.fire | join.ready
|
||||
rspBufferOutput.ready := join.fire
|
||||
output << join.haltWhen(issueDetected)
|
||||
output << join.haltWhen(exceptionDetected || redoRequired)
|
||||
|
||||
if(catchAccessFault){
|
||||
decodeExceptionPort.valid := False
|
||||
decodeExceptionPort.code := 1
|
||||
decodeExceptionPort.badAddr := join.pc
|
||||
when(join.valid && join.rsp.error && !issueDetected){
|
||||
issueDetected \= True
|
||||
decodeExceptionPort.valid := iBusRsp.readyForError
|
||||
if(memoryTranslatorPortConfig != null){
|
||||
redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling)
|
||||
redoBranch.valid := redoRequired && iBusRsp.readyForError
|
||||
redoBranch.payload := decode.input(PC)
|
||||
decode.arbitration.flushAll setWhen(redoBranch.valid)
|
||||
}
|
||||
|
||||
|
||||
if(catchSomething){
|
||||
decodeExceptionPort.code.assignDontCare()
|
||||
decodeExceptionPort.badAddr := join.pc(31 downto 2) @@ "00"
|
||||
|
||||
if(catchAccessFault) when(join.valid && join.rsp.error){
|
||||
decodeExceptionPort.code := 1
|
||||
exceptionDetected := True
|
||||
}
|
||||
if(memoryTranslatorPortConfig != null) {
|
||||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||
when(stages.last.input.valid && !mmu.joinCtx.refilling && (mmu.joinCtx.exception || !mmu.joinCtx.allowExecute)){
|
||||
decodeExceptionPort.code := 12
|
||||
exceptionDetected := True
|
||||
}
|
||||
}
|
||||
decodeExceptionPort.valid := exceptionDetected && iBusRsp.readyForError && !fetcherHalt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import vexriscv._
|
|||
import spinal.core._
|
||||
object IntAluPlugin{
|
||||
object AluBitwiseCtrlEnum extends SpinalEnum(binarySequential){
|
||||
val XOR, OR, AND, SRC1 = newElement()
|
||||
val XOR, OR, AND = newElement()
|
||||
}
|
||||
object AluCtrlEnum extends SpinalEnum(binarySequential){
|
||||
val ADD_SUB, SLT_SLTU, BITWISE = newElement()
|
||||
|
@ -70,7 +70,7 @@ class IntAluPlugin extends Plugin[VexRiscv]{
|
|||
))
|
||||
|
||||
decoderService.add(List(
|
||||
LUI -> (otherAction ++ List(ALU_CTRL -> AluCtrlEnum.BITWISE, ALU_BITWISE_CTRL -> AluBitwiseCtrlEnum.SRC1, SRC1_CTRL -> Src1CtrlEnum.IMU)),
|
||||
LUI -> (otherAction ++ List(ALU_CTRL -> AluCtrlEnum.ADD_SUB, SRC1_CTRL -> Src1CtrlEnum.IMU, SRC_USE_SUB_LESS -> False, SRC_ADD_ZERO -> True)),
|
||||
AUIPC -> (otherAction ++ List(ALU_CTRL -> AluCtrlEnum.ADD_SUB, SRC_USE_SUB_LESS -> False, SRC1_CTRL -> Src1CtrlEnum.IMU, SRC2_CTRL -> Src2CtrlEnum.PC))
|
||||
))
|
||||
}
|
||||
|
@ -86,8 +86,7 @@ class IntAluPlugin extends Plugin[VexRiscv]{
|
|||
val bitwise = input(ALU_BITWISE_CTRL).mux(
|
||||
AluBitwiseCtrlEnum.AND -> (input(SRC1) & input(SRC2)),
|
||||
AluBitwiseCtrlEnum.OR -> (input(SRC1) | input(SRC2)),
|
||||
AluBitwiseCtrlEnum.XOR -> (input(SRC1) ^ input(SRC2)),
|
||||
AluBitwiseCtrlEnum.SRC1 -> input(SRC1)
|
||||
AluBitwiseCtrlEnum.XOR -> (input(SRC1) ^ input(SRC2))
|
||||
)
|
||||
|
||||
// mux results
|
||||
|
|
|
@ -112,19 +112,20 @@ class MemoryTranslatorPlugin(tlbSize : Int,
|
|||
port.bus.rsp.allowRead := cacheLine.allowRead
|
||||
port.bus.rsp.allowWrite := cacheLine.allowWrite
|
||||
port.bus.rsp.allowExecute := cacheLine.allowExecute
|
||||
port.bus.rsp.allowUser := cacheLine.allowUser
|
||||
port.bus.rsp.hit := cacheHit
|
||||
???
|
||||
// port.bus.rsp.hit := cacheHit
|
||||
// port.stage.arbitration.haltItself setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss)
|
||||
} otherwise {
|
||||
port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress
|
||||
port.bus.rsp.allowRead := True
|
||||
port.bus.rsp.allowWrite := True
|
||||
port.bus.rsp.allowExecute := True
|
||||
port.bus.rsp.allowUser := True
|
||||
port.bus.rsp.hit := True
|
||||
???
|
||||
// port.bus.rsp.hit := True
|
||||
}
|
||||
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
|
||||
port.bus.rsp.miss := sharedMiss
|
||||
???
|
||||
// port.bus.rsp.miss := sharedMiss
|
||||
}
|
||||
}
|
||||
|
||||
|
|
261
src/main/scala/vexriscv/plugin/MmuPlugin.scala
Normal file
261
src/main/scala/vexriscv/plugin/MmuPlugin.scala
Normal file
|
@ -0,0 +1,261 @@
|
|||
package vexriscv.plugin
|
||||
|
||||
import vexriscv.{VexRiscv, _}
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
trait DBusAccessService{
|
||||
def newDBusAccess() : DBusAccess
|
||||
}
|
||||
|
||||
case class DBusAccessCmd() extends Bundle {
|
||||
val address = UInt(32 bits)
|
||||
val size = UInt(2 bits)
|
||||
val write = Bool
|
||||
val data = Bits(32 bits)
|
||||
val writeMask = Bits(4 bits)
|
||||
}
|
||||
|
||||
case class DBusAccessRsp() extends Bundle {
|
||||
val data = Bits(32 bits)
|
||||
val error = Bool()
|
||||
val redo = Bool()
|
||||
}
|
||||
|
||||
case class DBusAccess() extends Bundle {
|
||||
val cmd = Stream(DBusAccessCmd())
|
||||
val rsp = Flow(DBusAccessRsp())
|
||||
}
|
||||
|
||||
|
||||
object MmuPort{
|
||||
val PRIORITY_DATA = 1
|
||||
val PRIORITY_INSTRUCTION = 0
|
||||
}
|
||||
case class MmuPort(bus : MemoryTranslatorBus, priority : Int, args : MmuPortConfig, id : Int/*, exceptionBus: Flow[ExceptionCause]*/)
|
||||
|
||||
case class MmuPortConfig(portTlbSize : Int)
|
||||
|
||||
class MmuPlugin(ioRange : UInt => Bool,
|
||||
virtualRange : UInt => Bool = address => True,
|
||||
// allowUserIo : Boolean = false,
|
||||
enableMmuInMachineMode : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
|
||||
|
||||
var dBusAccess : DBusAccess = null
|
||||
val portsInfo = ArrayBuffer[MmuPort]()
|
||||
|
||||
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
|
||||
val port = MmuPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MmuPortConfig], portsInfo.length)
|
||||
portsInfo += port
|
||||
port.bus
|
||||
}
|
||||
|
||||
object IS_SFENCE_VMA extends Stageable(Bool)
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
import pipeline.config._
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.addDefault(IS_SFENCE_VMA, False)
|
||||
decoderService.add(SFENCE_VMA, List(IS_SFENCE_VMA -> True))
|
||||
|
||||
|
||||
dBusAccess = pipeline.service(classOf[DBusAccessService]).newDBusAccess()
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
import Riscv._
|
||||
val csrService = pipeline.service(classOf[CsrInterface])
|
||||
|
||||
//Sorted by priority
|
||||
val sortedPortsInfo = portsInfo.sortWith((a,b) => a.priority > b.priority)
|
||||
|
||||
case class CacheLine() extends Bundle {
|
||||
val valid, exception, superPage = Bool
|
||||
val virtualAddress = Vec(UInt(10 bits), UInt(10 bits))
|
||||
val physicalAddress = Vec(UInt(10 bits), UInt(10 bits))
|
||||
val allowRead, allowWrite, allowExecute, allowUser = Bool
|
||||
|
||||
def init = {
|
||||
valid init (False)
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
val csr = pipeline plug new Area{
|
||||
val status = new Area{
|
||||
val sum, mxr, mprv = RegInit(False)
|
||||
}
|
||||
val satp = new Area {
|
||||
val mode = RegInit(False)
|
||||
val ppn = Reg(UInt(20 bits))
|
||||
}
|
||||
|
||||
for(offset <- List(CSR.MSTATUS, CSR.SSTATUS)) csrService.rw(offset, 19 -> status.mxr, 18 -> status.sum, 17 -> status.mprv)
|
||||
csrService.rw(CSR.SATP, 31 -> satp.mode, 0 -> satp.ppn)
|
||||
}
|
||||
|
||||
val core = pipeline plug new Area {
|
||||
val ports = for (port <- sortedPortsInfo) yield new Area {
|
||||
val handle = port
|
||||
val id = port.id
|
||||
val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize)
|
||||
val cacheHits = cache.map(line => line.valid && line.virtualAddress(1) === port.bus.cmd.virtualAddress(31 downto 22) && (line.superPage || line.virtualAddress(0) === port.bus.cmd.virtualAddress(21 downto 12)))
|
||||
val cacheHit = cacheHits.asBits.orR
|
||||
val cacheLine = MuxOH(cacheHits, cache)
|
||||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||
val entryToReplace = Counter(port.args.portTlbSize)
|
||||
val requireMmuLockup = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation && csr.satp.mode
|
||||
if(!enableMmuInMachineMode) {
|
||||
requireMmuLockup clearWhen(!csr.status.mprv && privilegeService.isMachine())
|
||||
when(privilegeService.isMachine()) {
|
||||
if (port.priority == MmuPort.PRIORITY_DATA) {
|
||||
requireMmuLockup clearWhen (!csr.status.mprv || pipeline(MPP) === 3)
|
||||
} else {
|
||||
requireMmuLockup := False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(requireMmuLockup) {
|
||||
port.bus.rsp.physicalAddress := cacheLine.physicalAddress(1) @@ (cacheLine.superPage ? port.bus.cmd.virtualAddress(21 downto 12) | cacheLine.physicalAddress(0)) @@ port.bus.cmd.virtualAddress(11 downto 0)
|
||||
port.bus.rsp.allowRead := cacheLine.allowRead || csr.status.mxr && cacheLine.allowExecute
|
||||
port.bus.rsp.allowWrite := cacheLine.allowWrite
|
||||
port.bus.rsp.allowExecute := cacheLine.allowExecute
|
||||
port.bus.rsp.exception := cacheHit && (cacheLine.exception || cacheLine.allowUser && privilegeService.isSupervisor() && !csr.status.sum || !cacheLine.allowUser && privilegeService.isUser())
|
||||
port.bus.rsp.refilling := !cacheHit
|
||||
} otherwise {
|
||||
port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress
|
||||
port.bus.rsp.allowRead := True
|
||||
port.bus.rsp.allowWrite := True
|
||||
port.bus.rsp.allowExecute := True
|
||||
port.bus.rsp.exception := False
|
||||
port.bus.rsp.refilling := False
|
||||
}
|
||||
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
|
||||
|
||||
// Avoid keeping any invalid line in the cache after an exception.
|
||||
// https://github.com/riscv/riscv-linux/blob/8fe28cb58bcb235034b64cbbb7550a8a43fd88be/arch/riscv/include/asm/pgtable.h#L276
|
||||
when(service(classOf[IContextSwitching]).isContextSwitching) {
|
||||
for (line <- cache) {
|
||||
when(line.exception) {
|
||||
line.valid := False
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val shared = new Area {
|
||||
val State = new SpinalEnum{
|
||||
val IDLE, L1_CMD, L1_RSP, L0_CMD, L0_RSP = newElement()
|
||||
}
|
||||
val state = RegInit(State.IDLE)
|
||||
val vpn = Reg(Vec(UInt(10 bits), UInt(10 bits)))
|
||||
val portId = Reg(UInt(log2Up(portsInfo.length) bits))
|
||||
case class PTE() extends Bundle {
|
||||
val V, R, W ,X, U, G, A, D = Bool()
|
||||
val RSW = Bits(2 bits)
|
||||
val PPN0 = UInt(10 bits)
|
||||
val PPN1 = UInt(12 bits)
|
||||
}
|
||||
val dBusRsp = new Area{
|
||||
val pte = PTE()
|
||||
pte.assignFromBits(dBusAccess.rsp.data)
|
||||
val exception = !pte.V || (!pte.R && pte.W) || dBusAccess.rsp.error
|
||||
val leaf = pte.R || pte.X
|
||||
}
|
||||
|
||||
val pteBuffer = RegNextWhen(dBusRsp.pte, dBusAccess.rsp.valid && !dBusAccess.rsp.redo)
|
||||
|
||||
dBusAccess.cmd.valid := False
|
||||
dBusAccess.cmd.write := False
|
||||
dBusAccess.cmd.size := 2
|
||||
dBusAccess.cmd.address.assignDontCare()
|
||||
dBusAccess.cmd.data.assignDontCare()
|
||||
dBusAccess.cmd.writeMask.assignDontCare()
|
||||
switch(state){
|
||||
is(State.IDLE){
|
||||
for(port <- portsInfo.sortBy(_.priority)){
|
||||
when(port.bus.cmd.isValid && port.bus.rsp.refilling){
|
||||
vpn(1) := port.bus.cmd.virtualAddress(31 downto 22)
|
||||
vpn(0) := port.bus.cmd.virtualAddress(21 downto 12)
|
||||
portId := port.id
|
||||
state := State.L1_CMD
|
||||
}
|
||||
}
|
||||
}
|
||||
is(State.L1_CMD){
|
||||
dBusAccess.cmd.valid := True
|
||||
dBusAccess.cmd.address := csr.satp.ppn @@ vpn(1) @@ U"00"
|
||||
when(dBusAccess.cmd.ready){
|
||||
state := State.L1_RSP
|
||||
}
|
||||
}
|
||||
is(State.L1_RSP){
|
||||
when(dBusAccess.rsp.valid){
|
||||
state := State.L0_CMD
|
||||
when(dBusRsp.leaf || dBusRsp.exception){
|
||||
state := State.IDLE
|
||||
}
|
||||
when(dBusAccess.rsp.redo){
|
||||
state := State.L1_CMD
|
||||
}
|
||||
}
|
||||
}
|
||||
is(State.L0_CMD){
|
||||
dBusAccess.cmd.valid := True
|
||||
dBusAccess.cmd.address := pteBuffer.PPN1(9 downto 0) @@ pteBuffer.PPN0 @@ vpn(0) @@ U"00"
|
||||
when(dBusAccess.cmd.ready){
|
||||
state := State.L0_RSP
|
||||
}
|
||||
}
|
||||
is(State.L0_RSP){
|
||||
when(dBusAccess.rsp.valid) {
|
||||
state := State.IDLE
|
||||
when(dBusAccess.rsp.redo){
|
||||
state := State.L0_CMD
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(port <- ports) {
|
||||
port.handle.bus.busy := state =/= State.IDLE && portId === port.id
|
||||
}
|
||||
|
||||
when(dBusAccess.rsp.valid && !dBusAccess.rsp.redo && (dBusRsp.leaf || dBusRsp.exception)){
|
||||
for(port <- ports){
|
||||
when(portId === port.id) {
|
||||
port.entryToReplace.increment()
|
||||
for ((line, lineId) <- port.cache.zipWithIndex) {
|
||||
when(port.entryToReplace === lineId){
|
||||
val superPage = state === State.L1_RSP
|
||||
line.valid := True
|
||||
line.exception := dBusRsp.exception || (superPage && dBusRsp.pte.PPN0 =/= 0)
|
||||
line.virtualAddress := vpn
|
||||
line.physicalAddress := Vec(dBusRsp.pte.PPN0, dBusRsp.pte.PPN1(9 downto 0))
|
||||
line.allowRead := dBusRsp.pte.R
|
||||
line.allowWrite := dBusRsp.pte.W
|
||||
line.allowExecute := dBusRsp.pte.X
|
||||
line.allowUser := dBusRsp.pte.U
|
||||
line.superPage := state === State.L1_RSP
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val fenceStage = stages.last
|
||||
fenceStage plug new Area{
|
||||
import fenceStage._
|
||||
when(arbitration.isValid && input(IS_SFENCE_VMA)){ // || csrService.isWriting(CSR.SATP)
|
||||
for(port <- core.ports; line <- port.cache) line.valid := False //Assume that the instruction already fetched into the pipeline are ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
90
src/main/scala/vexriscv/plugin/MulSimplePlugin.scala
Normal file
90
src/main/scala/vexriscv/plugin/MulSimplePlugin.scala
Normal file
|
@ -0,0 +1,90 @@
|
|||
package vexriscv.plugin
|
||||
import vexriscv._
|
||||
import vexriscv.VexRiscv
|
||||
import spinal.core._
|
||||
|
||||
class MulSimplePlugin extends Plugin[VexRiscv]{
|
||||
object MUL_OPA extends Stageable(SInt(33 bits))
|
||||
object MUL_OPB extends Stageable(SInt(33 bits))
|
||||
object MUL extends Stageable(Bits(64 bits))
|
||||
|
||||
object IS_MUL extends Stageable(Bool)
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
import pipeline.config._
|
||||
|
||||
|
||||
val actions = List[(Stageable[_ <: BaseType],Any)](
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> False,
|
||||
BYPASSABLE_MEMORY_STAGE -> False,
|
||||
RS1_USE -> True,
|
||||
RS2_USE -> True,
|
||||
IS_MUL -> True
|
||||
)
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.addDefault(IS_MUL, False)
|
||||
decoderService.add(List(
|
||||
MULX -> actions
|
||||
))
|
||||
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
|
||||
// Prepare signed inputs for the multiplier in the next stage.
|
||||
// This will map them best to an FPGA DSP.
|
||||
execute plug new Area {
|
||||
import execute._
|
||||
val aSigned,bSigned = Bool
|
||||
val a,b = Bits(32 bit)
|
||||
|
||||
a := input(SRC1)
|
||||
b := input(SRC2)
|
||||
switch(input(INSTRUCTION)(13 downto 12)) {
|
||||
is(B"01") {
|
||||
aSigned := True
|
||||
bSigned := True
|
||||
}
|
||||
is(B"10") {
|
||||
aSigned := True
|
||||
bSigned := False
|
||||
}
|
||||
default {
|
||||
aSigned := False
|
||||
bSigned := False
|
||||
}
|
||||
}
|
||||
|
||||
insert(MUL_OPA) := ((aSigned ? a.msb | False) ## a).asSInt
|
||||
insert(MUL_OPB) := ((bSigned ? b.msb | False) ## b).asSInt
|
||||
}
|
||||
|
||||
memory plug new Area {
|
||||
import memory._
|
||||
|
||||
insert(MUL) := (input(MUL_OPA) * input(MUL_OPB))(63 downto 0).asBits
|
||||
}
|
||||
|
||||
writeBack plug new Area {
|
||||
import writeBack._
|
||||
|
||||
when(arbitration.isValid && input(IS_MUL)){
|
||||
switch(input(INSTRUCTION)(13 downto 12)){
|
||||
is(B"00"){
|
||||
output(REGFILE_WRITE_DATA) := input(MUL)(31 downto 0)
|
||||
}
|
||||
is(B"01",B"10",B"11"){
|
||||
output(REGFILE_WRITE_DATA) := input(MUL)(63 downto 32)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
package vexriscv.plugin
|
||||
|
||||
import vexriscv.{Pipeline, Stage}
|
||||
import spinal.core.Area
|
||||
import spinal.core.{Area, Nameable}
|
||||
|
||||
/**
|
||||
* Created by PIC32F_USER on 03/03/2017.
|
||||
*/
|
||||
trait Plugin[T <: Pipeline] {
|
||||
trait Plugin[T <: Pipeline] extends Nameable{
|
||||
var pipeline : T = null.asInstanceOf[T]
|
||||
def getName() = this.getClass.getSimpleName.replace("$","")
|
||||
setName(this.getClass.getSimpleName.replace("$",""))
|
||||
|
||||
def setup(pipeline: T) : Unit = {}
|
||||
def build(pipeline: T) : Unit
|
||||
|
|
|
@ -91,7 +91,7 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
|||
import writeStage._
|
||||
|
||||
def shadowPrefix(that : Bits) = if(withShadow) global.shadow.write ## that else that
|
||||
val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public)
|
||||
val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public).setName("lastStageRegFileWrite")
|
||||
regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring
|
||||
regFileWrite.address := U(shadowPrefix(output(INSTRUCTION)(rdRange)))
|
||||
regFileWrite.data := output(REGFILE_WRITE_DATA)
|
||||
|
|
|
@ -69,12 +69,14 @@ class FullBarrelShifterPlugin(earlyInjection : Boolean = false) extends Plugin[V
|
|||
val injectionStage = if(earlyInjection) execute else memory
|
||||
injectionStage plug new Area{
|
||||
import injectionStage._
|
||||
switch(input(SHIFT_CTRL)){
|
||||
is(ShiftCtrlEnum.SLL){
|
||||
output(REGFILE_WRITE_DATA) := Reverse(input(SHIFT_RIGHT))
|
||||
}
|
||||
is(ShiftCtrlEnum.SRL,ShiftCtrlEnum.SRA){
|
||||
output(REGFILE_WRITE_DATA) := input(SHIFT_RIGHT)
|
||||
when(arbitration.isValid){
|
||||
switch(input(SHIFT_CTRL)) {
|
||||
is(ShiftCtrlEnum.SLL) {
|
||||
output(REGFILE_WRITE_DATA) := Reverse(input(SHIFT_RIGHT))
|
||||
}
|
||||
is(ShiftCtrlEnum.SRL, ShiftCtrlEnum.SRA) {
|
||||
output(REGFILE_WRITE_DATA) := input(SHIFT_RIGHT)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,24 +107,30 @@ class LightShifterPlugin extends Plugin[VexRiscv]{
|
|||
val immediateActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.IMI,
|
||||
ALU_CTRL -> AluCtrlEnum.BITWISE,
|
||||
ALU_BITWISE_CTRL -> AluBitwiseCtrlEnum.SRC1,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> True,
|
||||
BYPASSABLE_MEMORY_STAGE -> True,
|
||||
RS1_USE -> True
|
||||
RS1_USE -> True,
|
||||
|
||||
//Get SRC1 through the MMU to the RF write path
|
||||
ALU_CTRL -> AluCtrlEnum.ADD_SUB,
|
||||
SRC_USE_SUB_LESS -> False,
|
||||
SRC_ADD_ZERO -> True
|
||||
)
|
||||
|
||||
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC2_CTRL -> Src2CtrlEnum.RS,
|
||||
ALU_CTRL -> AluCtrlEnum.BITWISE,
|
||||
ALU_BITWISE_CTRL -> AluBitwiseCtrlEnum.SRC1,
|
||||
REGFILE_WRITE_VALID -> True,
|
||||
BYPASSABLE_EXECUTE_STAGE -> True,
|
||||
BYPASSABLE_MEMORY_STAGE -> True,
|
||||
RS1_USE -> True,
|
||||
RS2_USE -> True
|
||||
RS2_USE -> True,
|
||||
|
||||
//Get SRC1 through the MMU to the RF write path
|
||||
ALU_CTRL -> AluCtrlEnum.ADD_SUB,
|
||||
SRC_USE_SUB_LESS -> False,
|
||||
SRC_ADD_ZERO -> True
|
||||
)
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
|
@ -156,6 +164,7 @@ class LightShifterPlugin extends Plugin[VexRiscv]{
|
|||
val shiftInput = isActive ? (if(withMemoryStage) memory.input(REGFILE_WRITE_DATA) else shiftReg) | input(SRC1)
|
||||
val done = amplitude(4 downto 1) === 0
|
||||
|
||||
if(withMemoryStage) memory.dontSampleStageable(REGFILE_WRITE_DATA, arbitration.isStuckByOthers)
|
||||
|
||||
when(arbitration.isValid && isShift && input(SRC2)(4 downto 0) =/= 0){
|
||||
output(REGFILE_WRITE_DATA) := input(SHIFT_CTRL).mux(
|
||||
|
|
|
@ -1,13 +1,26 @@
|
|||
package vexriscv.plugin
|
||||
|
||||
import vexriscv.{RVC_GEN, Riscv, VexRiscv}
|
||||
import vexriscv._
|
||||
import spinal.core._
|
||||
|
||||
|
||||
class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean = false, decodeAddSub : Boolean = false) extends Plugin[VexRiscv]{
|
||||
object SRC2_FORCE_ZERO extends Stageable(Bool)
|
||||
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import pipeline.config._
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
decoderService.addDefault(SRC_ADD_ZERO, False) //TODO avoid this default to simplify decoding ?
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
|
||||
decode.insert(SRC2_FORCE_ZERO) := decode.input(SRC_ADD_ZERO) && !decode.input(SRC_USE_SUB_LESS)
|
||||
|
||||
val insertionStage = if(executeInsertion) execute else decode
|
||||
insertionStage plug new Area{
|
||||
import insertionStage._
|
||||
|
@ -33,8 +46,9 @@ class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean =
|
|||
import addSubStage._
|
||||
|
||||
// ADD, SUB
|
||||
val add = (input(SRC1).asUInt + input(SRC2).asUInt).asBits.addAttribute("keep")
|
||||
val sub = (input(SRC1).asUInt - input(SRC2).asUInt).asBits.addAttribute("keep")
|
||||
val add = (U(input(SRC1)) + U(input(SRC2))).asBits.addAttribute("keep")
|
||||
val sub = (U(input(SRC1)) - U(input(SRC2))).asBits.addAttribute("keep")
|
||||
when(input(SRC_ADD_ZERO)){ add := input(SRC1) }
|
||||
|
||||
// SLT, SLTU
|
||||
val less = Mux(input(SRC1).msb === input(SRC2).msb, sub.msb,
|
||||
|
@ -50,7 +64,9 @@ class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean =
|
|||
import addSubStage._
|
||||
|
||||
// ADD, SUB
|
||||
val addSub = (input(SRC1).asSInt + Mux(input(SRC_USE_SUB_LESS), ~input(SRC2), input(SRC2)).asSInt + Mux(input(SRC_USE_SUB_LESS), S(1), S(0))).asBits
|
||||
val addSub = (input(SRC1).asSInt + Mux(input(SRC_USE_SUB_LESS), ~input(SRC2), input(SRC2)).asSInt + Mux(input(SRC_USE_SUB_LESS), S(1, 32 bits), S(0, 32 bits))).asBits
|
||||
when(input(SRC2_FORCE_ZERO)){ addSub := input(SRC1) }
|
||||
|
||||
|
||||
// SLT, SLTU
|
||||
val less = Mux(input(SRC1).msb === input(SRC2).msb, addSub.msb,
|
||||
|
|
|
@ -31,10 +31,10 @@ class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRis
|
|||
port.bus.rsp.allowRead := True
|
||||
port.bus.rsp.allowWrite := True
|
||||
port.bus.rsp.allowExecute := True
|
||||
port.bus.rsp.allowUser := True
|
||||
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
|
||||
port.bus.rsp.miss := False
|
||||
port.bus.rsp.hit := True
|
||||
port.bus.rsp.exception := False
|
||||
port.bus.rsp.refilling := False
|
||||
port.bus.busy := False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
4
src/test/cpp/raw/amo/.gitignore
vendored
Normal file
4
src/test/cpp/raw/amo/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
247
src/test/cpp/raw/amo/build/amo.asm
Normal file
247
src/test/cpp/raw/amo/build/amo.asm
Normal file
|
@ -0,0 +1,247 @@
|
|||
|
||||
build/amo.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .crt_section:
|
||||
|
||||
80000000 <_start>:
|
||||
80000000: 00100e13 li t3,1
|
||||
80000004: 00000097 auipc ra,0x0
|
||||
80000008: 27408093 addi ra,ra,628 # 80000278 <test1_data>
|
||||
8000000c: 02d00113 li sp,45
|
||||
80000010: 0820a1af amoswap.w gp,sp,(ra)
|
||||
80000014: 0000a203 lw tp,0(ra)
|
||||
80000018: 02d00a13 li s4,45
|
||||
8000001c: 224a1663 bne s4,tp,80000248 <fail>
|
||||
80000020: 00b00a13 li s4,11
|
||||
80000024: 223a1263 bne s4,gp,80000248 <fail>
|
||||
|
||||
80000028 <test2>:
|
||||
80000028: 00200e13 li t3,2
|
||||
8000002c: 00000097 auipc ra,0x0
|
||||
80000030: 25008093 addi ra,ra,592 # 8000027c <test2_data>
|
||||
80000034: 03700113 li sp,55
|
||||
80000038: 0820a1af amoswap.w gp,sp,(ra)
|
||||
8000003c: 0000a203 lw tp,0(ra)
|
||||
80000040: 03700a13 li s4,55
|
||||
80000044: 204a1263 bne s4,tp,80000248 <fail>
|
||||
80000048: 01600a13 li s4,22
|
||||
8000004c: 1e3a1e63 bne s4,gp,80000248 <fail>
|
||||
|
||||
80000050 <test3>:
|
||||
80000050: 00300e13 li t3,3
|
||||
80000054: 00000097 auipc ra,0x0
|
||||
80000058: 22c08093 addi ra,ra,556 # 80000280 <test3_data>
|
||||
8000005c: 04200113 li sp,66
|
||||
80000060: 0020a1af amoadd.w gp,sp,(ra)
|
||||
80000064: 0000a203 lw tp,0(ra)
|
||||
80000068: 08b00a13 li s4,139
|
||||
8000006c: 1c4a1e63 bne s4,tp,80000248 <fail>
|
||||
80000070: 04900a13 li s4,73
|
||||
80000074: 1c3a1a63 bne s4,gp,80000248 <fail>
|
||||
|
||||
80000078 <test4>:
|
||||
80000078: 00400e13 li t3,4
|
||||
8000007c: 00000097 auipc ra,0x0
|
||||
80000080: 20808093 addi ra,ra,520 # 80000284 <test4_data>
|
||||
80000084: 05700113 li sp,87
|
||||
80000088: 2020a1af amoxor.w gp,sp,(ra)
|
||||
8000008c: 0000a203 lw tp,0(ra)
|
||||
80000090: 06d00a13 li s4,109
|
||||
80000094: 1a4a1a63 bne s4,tp,80000248 <fail>
|
||||
80000098: 03a00a13 li s4,58
|
||||
8000009c: 1a3a1663 bne s4,gp,80000248 <fail>
|
||||
|
||||
800000a0 <test5>:
|
||||
800000a0: 00500e13 li t3,5
|
||||
800000a4: 00000097 auipc ra,0x0
|
||||
800000a8: 1e408093 addi ra,ra,484 # 80000288 <test5_data>
|
||||
800000ac: 02c00113 li sp,44
|
||||
800000b0: 6020a1af amoand.w gp,sp,(ra)
|
||||
800000b4: 0000a203 lw tp,0(ra)
|
||||
800000b8: 02800a13 li s4,40
|
||||
800000bc: 184a1663 bne s4,tp,80000248 <fail>
|
||||
800000c0: 03800a13 li s4,56
|
||||
800000c4: 183a1263 bne s4,gp,80000248 <fail>
|
||||
|
||||
800000c8 <test6>:
|
||||
800000c8: 00600e13 li t3,6
|
||||
800000cc: 00000097 auipc ra,0x0
|
||||
800000d0: 1c008093 addi ra,ra,448 # 8000028c <test6_data>
|
||||
800000d4: 01800113 li sp,24
|
||||
800000d8: 4020a1af amoor.w gp,sp,(ra)
|
||||
800000dc: 0000a203 lw tp,0(ra)
|
||||
800000e0: 05b00a13 li s4,91
|
||||
800000e4: 164a1263 bne s4,tp,80000248 <fail>
|
||||
800000e8: 04b00a13 li s4,75
|
||||
800000ec: 143a1e63 bne s4,gp,80000248 <fail>
|
||||
|
||||
800000f0 <test7>:
|
||||
800000f0: 00700e13 li t3,7
|
||||
800000f4: 00000097 auipc ra,0x0
|
||||
800000f8: 19c08093 addi ra,ra,412 # 80000290 <test7_data>
|
||||
800000fc: 01800113 li sp,24
|
||||
80000100: 8020a1af amomin.w gp,sp,(ra)
|
||||
80000104: 0000a203 lw tp,0(ra)
|
||||
80000108: 01800a13 li s4,24
|
||||
8000010c: 124a1e63 bne s4,tp,80000248 <fail>
|
||||
80000110: 03800a13 li s4,56
|
||||
80000114: 123a1a63 bne s4,gp,80000248 <fail>
|
||||
|
||||
80000118 <test8>:
|
||||
80000118: 00800e13 li t3,8
|
||||
8000011c: 00000097 auipc ra,0x0
|
||||
80000120: 17808093 addi ra,ra,376 # 80000294 <test8_data>
|
||||
80000124: 05800113 li sp,88
|
||||
80000128: 8020a1af amomin.w gp,sp,(ra)
|
||||
8000012c: 0000a203 lw tp,0(ra)
|
||||
80000130: 05300a13 li s4,83
|
||||
80000134: 104a1a63 bne s4,tp,80000248 <fail>
|
||||
80000138: 05300a13 li s4,83
|
||||
8000013c: 103a1663 bne s4,gp,80000248 <fail>
|
||||
|
||||
80000140 <test9>:
|
||||
80000140: 00900e13 li t3,9
|
||||
80000144: 00000097 auipc ra,0x0
|
||||
80000148: 15408093 addi ra,ra,340 # 80000298 <test9_data>
|
||||
8000014c: fca00113 li sp,-54
|
||||
80000150: 8020a1af amomin.w gp,sp,(ra)
|
||||
80000154: 0000a203 lw tp,0(ra)
|
||||
80000158: fca00a13 li s4,-54
|
||||
8000015c: 0e4a1663 bne s4,tp,80000248 <fail>
|
||||
80000160: 02100a13 li s4,33
|
||||
80000164: 0e3a1263 bne s4,gp,80000248 <fail>
|
||||
|
||||
80000168 <test10>:
|
||||
80000168: 00a00e13 li t3,10
|
||||
8000016c: 00000097 auipc ra,0x0
|
||||
80000170: 13008093 addi ra,ra,304 # 8000029c <test10_data>
|
||||
80000174: 03400113 li sp,52
|
||||
80000178: 8020a1af amomin.w gp,sp,(ra)
|
||||
8000017c: 0000a203 lw tp,0(ra)
|
||||
80000180: fbf00a13 li s4,-65
|
||||
80000184: 0c4a1263 bne s4,tp,80000248 <fail>
|
||||
80000188: fbf00a13 li s4,-65
|
||||
8000018c: 0a3a1e63 bne s4,gp,80000248 <fail>
|
||||
|
||||
80000190 <test11>:
|
||||
80000190: 00b00e13 li t3,11
|
||||
80000194: 00000097 auipc ra,0x0
|
||||
80000198: 10c08093 addi ra,ra,268 # 800002a0 <test11_data>
|
||||
8000019c: fcc00113 li sp,-52
|
||||
800001a0: a020a1af amomax.w gp,sp,(ra)
|
||||
800001a4: 0000a203 lw tp,0(ra)
|
||||
800001a8: fcc00a13 li s4,-52
|
||||
800001ac: 084a1e63 bne s4,tp,80000248 <fail>
|
||||
800001b0: fa900a13 li s4,-87
|
||||
800001b4: 083a1a63 bne s4,gp,80000248 <fail>
|
||||
|
||||
800001b8 <test12>:
|
||||
800001b8: 00c00e13 li t3,12
|
||||
800001bc: 00000097 auipc ra,0x0
|
||||
800001c0: 0e808093 addi ra,ra,232 # 800002a4 <test12_data>
|
||||
800001c4: 03400113 li sp,52
|
||||
800001c8: a020a1af amomax.w gp,sp,(ra)
|
||||
800001cc: 0000a203 lw tp,0(ra)
|
||||
800001d0: 03400a13 li s4,52
|
||||
800001d4: 064a1a63 bne s4,tp,80000248 <fail>
|
||||
800001d8: fc900a13 li s4,-55
|
||||
800001dc: 063a1663 bne s4,gp,80000248 <fail>
|
||||
|
||||
800001e0 <test13>:
|
||||
800001e0: 00d00e13 li t3,13
|
||||
800001e4: 00000097 auipc ra,0x0
|
||||
800001e8: 0c408093 addi ra,ra,196 # 800002a8 <test13_data>
|
||||
800001ec: ffff0137 lui sp,0xffff0
|
||||
800001f0: c020a1af amominu.w gp,sp,(ra)
|
||||
800001f4: 0000a203 lw tp,0(ra)
|
||||
800001f8: ffff0a37 lui s4,0xffff0
|
||||
800001fc: 044a1663 bne s4,tp,80000248 <fail>
|
||||
80000200: ffff0a37 lui s4,0xffff0
|
||||
80000204: 004a0a13 addi s4,s4,4 # ffff0004 <test14_data+0x7ffefd58>
|
||||
80000208: 043a1063 bne s4,gp,80000248 <fail>
|
||||
8000020c: 0480006f j 80000254 <pass>
|
||||
|
||||
80000210 <test14>:
|
||||
80000210: 00e00e13 li t3,14
|
||||
80000214: 00000097 auipc ra,0x0
|
||||
80000218: 09808093 addi ra,ra,152 # 800002ac <test14_data>
|
||||
8000021c: ffff0137 lui sp,0xffff0
|
||||
80000220: 00c10113 addi sp,sp,12 # ffff000c <test14_data+0x7ffefd60>
|
||||
80000224: e020a1af amomaxu.w gp,sp,(ra)
|
||||
80000228: 0000a203 lw tp,0(ra)
|
||||
8000022c: ffff0a37 lui s4,0xffff0
|
||||
80000230: 00ca0a13 addi s4,s4,12 # ffff000c <test14_data+0x7ffefd60>
|
||||
80000234: 004a1a63 bne s4,tp,80000248 <fail>
|
||||
80000238: ffff0a37 lui s4,0xffff0
|
||||
8000023c: 005a0a13 addi s4,s4,5 # ffff0005 <test14_data+0x7ffefd59>
|
||||
80000240: 003a1463 bne s4,gp,80000248 <fail>
|
||||
80000244: 0100006f j 80000254 <pass>
|
||||
|
||||
80000248 <fail>:
|
||||
80000248: f0100137 lui sp,0xf0100
|
||||
8000024c: f2410113 addi sp,sp,-220 # f00fff24 <test14_data+0x700ffc78>
|
||||
80000250: 01c12023 sw t3,0(sp)
|
||||
|
||||
80000254 <pass>:
|
||||
80000254: f0100137 lui sp,0xf0100
|
||||
80000258: f2010113 addi sp,sp,-224 # f00fff20 <test14_data+0x700ffc74>
|
||||
8000025c: 00012023 sw zero,0(sp)
|
||||
80000260: 00000013 nop
|
||||
80000264: 00000013 nop
|
||||
80000268: 00000013 nop
|
||||
8000026c: 00000013 nop
|
||||
80000270: 00000013 nop
|
||||
80000274: 00000013 nop
|
||||
|
||||
80000278 <test1_data>:
|
||||
80000278: 0000000b 0xb
|
||||
|
||||
8000027c <test2_data>:
|
||||
8000027c: 0016 c.slli zero,0x5
|
||||
...
|
||||
|
||||
80000280 <test3_data>:
|
||||
80000280: 0049 c.nop 18
|
||||
...
|
||||
|
||||
80000284 <test4_data>:
|
||||
80000284: 003a c.slli zero,0xe
|
||||
...
|
||||
|
||||
80000288 <test5_data>:
|
||||
80000288: 0038 addi a4,sp,8
|
||||
...
|
||||
|
||||
8000028c <test6_data>:
|
||||
8000028c: 0000004b fnmsub.s ft0,ft0,ft0,ft0,rne
|
||||
|
||||
80000290 <test7_data>:
|
||||
80000290: 0038 addi a4,sp,8
|
||||
...
|
||||
|
||||
80000294 <test8_data>:
|
||||
80000294: 00000053 fadd.s ft0,ft0,ft0,rne
|
||||
|
||||
80000298 <test9_data>:
|
||||
80000298: 0021 c.nop 8
|
||||
...
|
||||
|
||||
8000029c <test10_data>:
|
||||
8000029c: ffffffbf 0xffffffbf
|
||||
|
||||
800002a0 <test11_data>:
|
||||
800002a0: ffa9 bnez a5,800001fa <test13+0x1a>
|
||||
800002a2: ffff 0xffff
|
||||
|
||||
800002a4 <test12_data>:
|
||||
800002a4: ffc9 bnez a5,8000023e <test14+0x2e>
|
||||
800002a6: ffff 0xffff
|
||||
|
||||
800002a8 <test13_data>:
|
||||
800002a8: 0004 0x4
|
||||
800002aa: ffff 0xffff
|
||||
|
||||
800002ac <test14_data>:
|
||||
800002ac: 0005 c.nop 1
|
||||
800002ae: ffff 0xffff
|
45
src/test/cpp/raw/amo/build/amo.hex
Normal file
45
src/test/cpp/raw/amo/build/amo.hex
Normal file
|
@ -0,0 +1,45 @@
|
|||
:0200000480007A
|
||||
:10000000130E100097000000938040271301D002C8
|
||||
:10001000AFA1200803A20000130AD00263164A22EF
|
||||
:10002000130AB00063123A22130E2000970000005A
|
||||
:100030009380002513017003AFA1200803A20000E4
|
||||
:10004000130A700363124A20130A6001631E3A1EEA
|
||||
:10005000130E3000970000009380C022130120048B
|
||||
:10006000AFA1200003A20000130AB008631E4A1CBF
|
||||
:10007000130A9004631A3A1C130E40009700000004
|
||||
:100080009380802013017005AFA1202003A20000FF
|
||||
:10009000130AD006631A4A1A130AA00363163A1AFF
|
||||
:1000A000130E5000970000009380401E1301C00201
|
||||
:1000B000AFA1206003A20000130A800263164A1851
|
||||
:1000C000130A800363123A18130E600097000000B1
|
||||
:1000D0009380001C13018001AFA1204003A2000007
|
||||
:1000E000130AB00563124A16130AB004631E3A14C9
|
||||
:1000F000130E7000970000009380C0191301800157
|
||||
:10010000AFA1208003A20000130A8001631E4A12DF
|
||||
:10011000130A8003631A3A12130E8000970000003E
|
||||
:100120009380801713018005AFA1208003A20000F7
|
||||
:10013000130A3005631A4A10130A300563163A1081
|
||||
:10014000130E900097000000938040151301A0FC4F
|
||||
:10015000AFA1208003A20000130AA0FC63164A0E80
|
||||
:10016000130A100263123A0E130EA000970000004B
|
||||
:100170009380001313014003AFA1208003A200006D
|
||||
:10018000130AF0FB63124A0C130AF0FB631E3A0ACF
|
||||
:10019000130EB000970000009380C0101301C0FC44
|
||||
:1001A000AFA120A003A20000130AC0FC631E4A08EE
|
||||
:1001B000130A90FA631A3A08130EC0009700000061
|
||||
:1001C0009380800E13014003AFA120A003A2000082
|
||||
:1001D000130A4003631A4A06130A90FC63163A0690
|
||||
:1001E000130ED000970000009380400C3701FFFFF2
|
||||
:1001F000AFA120C003A20000370AFFFF63164A0424
|
||||
:10020000370AFFFF130A4A0063103A046F008004A4
|
||||
:10021000130EE00097000000938080093701FFFF74
|
||||
:100220001301C100AFA120E003A20000370AFFFFC5
|
||||
:10023000130ACA00631A4A00370AFFFF130A5A005A
|
||||
:1002400063143A006F000001370110F0130141F20E
|
||||
:100250002320C101370110F0130101F22320010016
|
||||
:100260001300000013000000130000001300000042
|
||||
:1002700013000000130000000B0000001600000037
|
||||
:10028000490000003A000000380000004B00000068
|
||||
:10029000380000005300000021000000BFFFFFFFF6
|
||||
:1002A000A9FFFFFFC9FFFFFF0400FFFF0500FFFFDD
|
||||
:00000001FF
|
5
src/test/cpp/raw/amo/makefile
Normal file
5
src/test/cpp/raw/amo/makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
PROJ_NAME=amo
|
||||
|
||||
ATOMIC=yes
|
||||
|
||||
include ../common/asm.mk
|
174
src/test/cpp/raw/amo/src/crt.S
Normal file
174
src/test/cpp/raw/amo/src/crt.S
Normal file
|
@ -0,0 +1,174 @@
|
|||
.globl _star
|
||||
#define TEST_ID x28
|
||||
|
||||
_start:
|
||||
|
||||
#define assert(reg, value) \
|
||||
li x20, value; \
|
||||
bne x20, reg, fail;
|
||||
|
||||
test1:
|
||||
li TEST_ID, 1
|
||||
la x1, test1_data
|
||||
li x2, 45
|
||||
amoswap.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 45)
|
||||
assert(x3, 11)
|
||||
|
||||
test2:
|
||||
li TEST_ID, 2
|
||||
la x1, test2_data
|
||||
li x2, 55
|
||||
amoswap.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 55)
|
||||
assert(x3, 22)
|
||||
|
||||
|
||||
test3:
|
||||
li TEST_ID,3
|
||||
la x1, test3_data
|
||||
li x2, 66
|
||||
amoadd.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 66+73)
|
||||
assert(x3, 73)
|
||||
|
||||
test4:
|
||||
li TEST_ID,4
|
||||
la x1, test4_data
|
||||
li x2, 87
|
||||
amoxor.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 87^58)
|
||||
assert(x3, 58)
|
||||
|
||||
test5:
|
||||
li TEST_ID,5
|
||||
la x1, test5_data
|
||||
li x2, 44
|
||||
amoand.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 44 & 56)
|
||||
assert(x3, 56)
|
||||
|
||||
test6:
|
||||
li TEST_ID,6
|
||||
la x1, test6_data
|
||||
li x2, 24
|
||||
amoor.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 24 | 75)
|
||||
assert(x3, 75)
|
||||
|
||||
test7:
|
||||
li TEST_ID,7
|
||||
la x1, test7_data
|
||||
li x2, 24
|
||||
amomin.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 24)
|
||||
assert(x3, 56)
|
||||
|
||||
|
||||
test8:
|
||||
li TEST_ID,8
|
||||
la x1, test8_data
|
||||
li x2, 88
|
||||
amomin.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 83)
|
||||
assert(x3, 83)
|
||||
|
||||
test9:
|
||||
li TEST_ID,9
|
||||
la x1, test9_data
|
||||
li x2, -54
|
||||
amomin.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, -54)
|
||||
assert(x3, 33)
|
||||
|
||||
test10:
|
||||
li TEST_ID,10
|
||||
la x1, test10_data
|
||||
li x2, 52
|
||||
amomin.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, -65)
|
||||
assert(x3, -65)
|
||||
|
||||
test11:
|
||||
li TEST_ID,11
|
||||
la x1, test11_data
|
||||
li x2, -52
|
||||
amomax.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, -52)
|
||||
assert(x3, -87)
|
||||
|
||||
test12:
|
||||
li TEST_ID,12
|
||||
la x1, test12_data
|
||||
li x2, 52
|
||||
amomax.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 52)
|
||||
assert(x3, -55)
|
||||
|
||||
|
||||
test13:
|
||||
li TEST_ID,13
|
||||
la x1, test13_data
|
||||
li x2, 0xFFFF0000
|
||||
amominu.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 0xFFFF0000)
|
||||
assert(x3, 0xFFFF0004)
|
||||
|
||||
j pass
|
||||
|
||||
|
||||
test14:
|
||||
li TEST_ID,14
|
||||
la x1, test14_data
|
||||
li x2, 0xFFFF000C
|
||||
amomaxu.w x3,x2,(x1)
|
||||
lw x4, 0(x1)
|
||||
assert(x4, 0xFFFF000C)
|
||||
assert(x3, 0xFFFF0005)
|
||||
|
||||
j pass
|
||||
|
||||
|
||||
fail:
|
||||
li x2, 0xF00FFF24
|
||||
sw TEST_ID, 0(x2)
|
||||
|
||||
pass:
|
||||
li x2, 0xF00FFF20
|
||||
sw x0, 0(x2)
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
|
||||
test1_data: .word 11
|
||||
test2_data: .word 22
|
||||
test3_data: .word 73
|
||||
test4_data: .word 58
|
||||
test5_data: .word 56
|
||||
test6_data: .word 75
|
||||
test7_data: .word 56
|
||||
test8_data: .word 83
|
||||
test9_data: .word 33
|
||||
test10_data: .word -65
|
||||
test11_data: .word -87
|
||||
test12_data: .word -55
|
||||
test13_data: .word 0xFFFF0004
|
||||
test14_data: .word 0xFFFF0005
|
16
src/test/cpp/raw/amo/src/ld
Normal file
16
src/test/cpp/raw/amo/src/ld
Normal file
|
@ -0,0 +1,16 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
MEMORY {
|
||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.crt_section :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*crt.o(.text)
|
||||
} > onChipRam
|
||||
|
||||
}
|
86
src/test/cpp/raw/common/asm.mk
Normal file
86
src/test/cpp/raw/common/asm.mk
Normal file
|
@ -0,0 +1,86 @@
|
|||
|
||||
RISCV_PATH?=/opt/riscv/
|
||||
RISCV_NAME = riscv64-unknown-elf
|
||||
RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy
|
||||
RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump
|
||||
RISCV_CLIB=$(RISCV_PATH)$(RISCV_NAME)/lib/
|
||||
RISCV_CC=$(RISCV_PATH)/bin/$(RISCV_NAME)-gcc
|
||||
LDSCRIPT=src/ld
|
||||
|
||||
MABI=ilp32
|
||||
MARCH := rv32i
|
||||
ifeq ($(MULDIV),yes)
|
||||
MARCH := $(MARCH)m
|
||||
endif
|
||||
ifeq ($(ATOMIC),yes)
|
||||
MARCH := $(MARCH)a
|
||||
endif
|
||||
ifeq ($(COMPRESSED),yes)
|
||||
MARCH := $(MARCH)c
|
||||
endif
|
||||
|
||||
CFLAGS += -march=$(MARCH) -mabi=$(MABI)
|
||||
LDFLAGS += -march=$(MARCH) -mabi=$(MABI)
|
||||
|
||||
|
||||
|
||||
SRCS = $(wildcard src/*.c) \
|
||||
$(wildcard src/*.cpp) \
|
||||
$(wildcard src/*.S)
|
||||
|
||||
|
||||
CFLAGS += -static
|
||||
LDFLAGS += -e_start -T $(LDSCRIPT) -nostartfiles -Wl,-Map,$(OBJDIR)/$(PROJ_NAME).map -Wl,--print-memory-usage
|
||||
OBJDIR = build
|
||||
OBJS := $(SRCS)
|
||||
OBJS := $(OBJS:.c=.o)
|
||||
OBJS := $(OBJS:.cpp=.o)
|
||||
OBJS := $(OBJS:.S=.o)
|
||||
OBJS := $(addprefix $(OBJDIR)/,$(OBJS))
|
||||
|
||||
|
||||
|
||||
all: $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm
|
||||
@echo "done"
|
||||
|
||||
$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR)
|
||||
$(RISCV_CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||
|
||||
%.hex: %.elf
|
||||
$(RISCV_OBJCOPY) -O ihex $^ $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(RISCV_OBJCOPY) -O binary $^ $@
|
||||
|
||||
%.v: %.elf
|
||||
$(RISCV_OBJCOPY) -O verilog $^ $@
|
||||
|
||||
%.asm: %.elf
|
||||
$(RISCV_OBJDUMP) -S -d $^ > $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^
|
||||
|
||||
$(OBJDIR)/%.o: %.S
|
||||
mkdir -p $(dir $@)
|
||||
$(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).elf
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).hex
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).map
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).v
|
||||
rm -f $(OBJDIR)/$(PROJ_NAME).asm
|
||||
find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm
|
||||
|
||||
.SECONDARY: $(OBJS)
|
||||
|
||||
|
4
src/test/cpp/raw/dcache/.gitignore
vendored
Normal file
4
src/test/cpp/raw/dcache/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
78
src/test/cpp/raw/dcache/build/dcache.asm
Normal file
78
src/test/cpp/raw/dcache/build/dcache.asm
Normal file
|
@ -0,0 +1,78 @@
|
|||
|
||||
build/dcache.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .crt_section:
|
||||
|
||||
80000000 <_start>:
|
||||
80000000: 00000097 auipc ra,0x0
|
||||
80000004: 0b408093 addi ra,ra,180 # 800000b4 <fail>
|
||||
|
||||
80000008 <test1>:
|
||||
80000008: 00100e13 li t3,1
|
||||
8000000c: 00100093 li ra,1
|
||||
80000010: 00300113 li sp,3
|
||||
80000014: 00208093 addi ra,ra,2
|
||||
80000018: 08209e63 bne ra,sp,800000b4 <fail>
|
||||
|
||||
8000001c <test2>:
|
||||
8000001c: 00200e13 li t3,2
|
||||
80000020: f56700b7 lui ra,0xf5670
|
||||
80000024: 900ff137 lui sp,0x900ff
|
||||
80000028: 40000313 li t1,1024
|
||||
|
||||
8000002c <test2_repeat>:
|
||||
8000002c: 00100193 li gp,1
|
||||
80000030: 00200293 li t0,2
|
||||
80000034: 006303b3 add t2,t1,t1
|
||||
80000038: 007181b3 add gp,gp,t2
|
||||
8000003c: 007282b3 add t0,t0,t2
|
||||
80000040: 00312023 sw gp,0(sp) # 900ff000 <pass+0x100fef40>
|
||||
80000044: 0000a023 sw zero,0(ra) # f5670000 <pass+0x7566ff40>
|
||||
80000048: 00012203 lw tp,0(sp)
|
||||
8000004c: 06429463 bne t0,tp,800000b4 <fail>
|
||||
80000050: ffc30313 addi t1,t1,-4
|
||||
80000054: 01008093 addi ra,ra,16
|
||||
80000058: 01010113 addi sp,sp,16
|
||||
8000005c: 0000500f 0x500f
|
||||
80000060: fc0316e3 bnez t1,8000002c <test2_repeat>
|
||||
|
||||
80000064 <test3>:
|
||||
80000064: 00300e13 li t3,3
|
||||
80000068: f56700b7 lui ra,0xf5670
|
||||
8000006c: 900ff137 lui sp,0x900ff
|
||||
80000070: 40000313 li t1,1024
|
||||
|
||||
80000074 <test3_repeat>:
|
||||
80000074: 00200193 li gp,2
|
||||
80000078: 00300293 li t0,3
|
||||
8000007c: 006303b3 add t2,t1,t1
|
||||
80000080: 007181b3 add gp,gp,t2
|
||||
80000084: 007282b3 add t0,t0,t2
|
||||
80000088: 00012203 lw tp,0(sp) # 900ff000 <pass+0x100fef40>
|
||||
8000008c: 00312023 sw gp,0(sp)
|
||||
80000090: 0000a023 sw zero,0(ra) # f5670000 <pass+0x7566ff40>
|
||||
80000094: 0000500f 0x500f
|
||||
80000098: 00012203 lw tp,0(sp)
|
||||
8000009c: 00429c63 bne t0,tp,800000b4 <fail>
|
||||
800000a0: ffc30313 addi t1,t1,-4
|
||||
800000a4: 01008093 addi ra,ra,16
|
||||
800000a8: 01010113 addi sp,sp,16
|
||||
800000ac: fc0314e3 bnez t1,80000074 <test3_repeat>
|
||||
800000b0: 0100006f j 800000c0 <pass>
|
||||
|
||||
800000b4 <fail>:
|
||||
800000b4: f0100137 lui sp,0xf0100
|
||||
800000b8: f2410113 addi sp,sp,-220 # f00fff24 <pass+0x700ffe64>
|
||||
800000bc: 01c12023 sw t3,0(sp)
|
||||
|
||||
800000c0 <pass>:
|
||||
800000c0: f0100137 lui sp,0xf0100
|
||||
800000c4: f2010113 addi sp,sp,-224 # f00fff20 <pass+0x700ffe60>
|
||||
800000c8: 00012023 sw zero,0(sp)
|
||||
800000cc: 00000013 nop
|
||||
800000d0: 00000013 nop
|
||||
800000d4: 00000013 nop
|
||||
800000d8: 00000013 nop
|
||||
800000dc: 00000013 nop
|
||||
800000e0: 00000013 nop
|
17
src/test/cpp/raw/dcache/build/dcache.hex
Normal file
17
src/test/cpp/raw/dcache/build/dcache.hex
Normal file
|
@ -0,0 +1,17 @@
|
|||
:0200000480007A
|
||||
:10000000970000009380400B130E10009300100027
|
||||
:100010001301300093802000639E2008130E2000FF
|
||||
:10002000B70067F537F10F901303004093011000FC
|
||||
:1000300093022000B3036300B3817100B3827200A6
|
||||
:100040002320310023A00000032201006394420614
|
||||
:100050001303C3FF93800001130101010F5000003F
|
||||
:10006000E31603FC130E3000B70067F537F10F906D
|
||||
:10007000130300409301200093023000B303630098
|
||||
:10008000B3817100B382720003220100232031008A
|
||||
:1000900023A000000F50000003220100639C4200D7
|
||||
:1000A0001303C3FF9380000113010101E31403FC58
|
||||
:1000B0006F000001370110F0130141F22320C1014C
|
||||
:1000C000370110F0130101F223200100130000009A
|
||||
:1000D00013000000130000001300000013000000D4
|
||||
:0400E0001300000009
|
||||
:00000001FF
|
3
src/test/cpp/raw/dcache/makefile
Normal file
3
src/test/cpp/raw/dcache/makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
PROJ_NAME=dcache
|
||||
|
||||
include ../common/asm.mk
|
75
src/test/cpp/raw/dcache/src/crt.S
Normal file
75
src/test/cpp/raw/dcache/src/crt.S
Normal file
|
@ -0,0 +1,75 @@
|
|||
.globl _star
|
||||
#define TEST_ID x28
|
||||
|
||||
_start:
|
||||
la x1, fail
|
||||
//csrw mtvec, x1
|
||||
|
||||
test1: //Dummy test
|
||||
li TEST_ID, 1
|
||||
li x1, 1
|
||||
li x2, 3
|
||||
addi x1, x1, 2
|
||||
bne x1, x2, fail
|
||||
|
||||
test2: //No invalidate, without load => new one
|
||||
li TEST_ID, 2
|
||||
li x1, 0xF5670000
|
||||
li x2, 0x900FF000
|
||||
li x6, 4096/4
|
||||
test2_repeat:
|
||||
la x3, 1
|
||||
la x5, 2
|
||||
add x7, x6, x6
|
||||
add x3, x3, x7
|
||||
add x5, x5, x7
|
||||
sw x3, 0(x2)
|
||||
sw x0, 0(x1)
|
||||
lw x4, 0(x2)
|
||||
bne x5,x4, fail
|
||||
addi x6, x6, -4
|
||||
addi x1, x1, 16
|
||||
addi x2, x2, 16
|
||||
.word 0x000500F // dcache flush
|
||||
bnez x6, test2_repeat
|
||||
|
||||
test3: //with invalidate, with preload
|
||||
li TEST_ID, 3
|
||||
li x1, 0xF5670000
|
||||
li x2, 0x900FF000
|
||||
li x6, 4096/4
|
||||
test3_repeat:
|
||||
la x3, 2
|
||||
la x5, 3
|
||||
add x7, x6, x6
|
||||
add x3, x3, x7
|
||||
add x5, x5, x7
|
||||
lw x4, 0(x2)
|
||||
sw x3, 0(x2)
|
||||
sw x0, 0(x1)
|
||||
.word 0x000500F // dcache flush
|
||||
lw x4, 0(x2)
|
||||
bne x5,x4, fail
|
||||
addi x6, x6, -4
|
||||
addi x1, x1, 16
|
||||
addi x2, x2, 16
|
||||
bnez x6, test3_repeat
|
||||
|
||||
|
||||
|
||||
j pass
|
||||
|
||||
fail:
|
||||
li x2, 0xF00FFF24
|
||||
sw TEST_ID, 0(x2)
|
||||
|
||||
pass:
|
||||
li x2, 0xF00FFF20
|
||||
sw x0, 0(x2)
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
16
src/test/cpp/raw/dcache/src/ld
Normal file
16
src/test/cpp/raw/dcache/src/ld
Normal file
|
@ -0,0 +1,16 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
MEMORY {
|
||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.crt_section :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*crt.o(.text)
|
||||
} > onChipRam
|
||||
|
||||
}
|
4
src/test/cpp/raw/deleg/.gitignore
vendored
Normal file
4
src/test/cpp/raw/deleg/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
541
src/test/cpp/raw/deleg/build/deleg.asm
Normal file
541
src/test/cpp/raw/deleg/build/deleg.asm
Normal file
|
@ -0,0 +1,541 @@
|
|||
|
||||
build/deleg.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .crt_section:
|
||||
|
||||
80000000 <_start>:
|
||||
80000000: 00100e93 li t4,1
|
||||
80000004: 00000097 auipc ra,0x0
|
||||
80000008: 6fc08093 addi ra,ra,1788 # 80000700 <mtrap>
|
||||
8000000c: 30509073 csrw mtvec,ra
|
||||
80000010: 00000097 auipc ra,0x0
|
||||
80000014: 72808093 addi ra,ra,1832 # 80000738 <strap>
|
||||
80000018: 10509073 csrw stvec,ra
|
||||
8000001c: f00110b7 lui ra,0xf0011
|
||||
80000020: 00000113 li sp,0
|
||||
80000024: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
|
||||
80000028 <test1>:
|
||||
80000028: 00100e13 li t3,1
|
||||
8000002c: 00000f17 auipc t5,0x0
|
||||
80000030: 00cf0f13 addi t5,t5,12 # 80000038 <test2>
|
||||
80000034: 00000073 ecall
|
||||
|
||||
80000038 <test2>:
|
||||
80000038: 00200e13 li t3,2
|
||||
8000003c: 000020b7 lui ra,0x2
|
||||
80000040: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
80000044: 00000113 li sp,0
|
||||
80000048: 3000b073 csrc mstatus,ra
|
||||
8000004c: 30012073 csrs mstatus,sp
|
||||
80000050: 00000097 auipc ra,0x0
|
||||
80000054: 01408093 addi ra,ra,20 # 80000064 <test2+0x2c>
|
||||
80000058: 34109073 csrw mepc,ra
|
||||
8000005c: 30200073 mret
|
||||
80000060: 6880006f j 800006e8 <fail>
|
||||
80000064: 00000f17 auipc t5,0x0
|
||||
80000068: 024f0f13 addi t5,t5,36 # 80000088 <test4>
|
||||
8000006c: 00000073 ecall
|
||||
80000070: 6780006f j 800006e8 <fail>
|
||||
|
||||
80000074 <test3>:
|
||||
80000074: 00300e13 li t3,3
|
||||
80000078: 00000f17 auipc t5,0x0
|
||||
8000007c: 010f0f13 addi t5,t5,16 # 80000088 <test4>
|
||||
80000080: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
80000084: 6640006f j 800006e8 <fail>
|
||||
|
||||
80000088 <test4>:
|
||||
80000088: 00400e13 li t3,4
|
||||
8000008c: 000020b7 lui ra,0x2
|
||||
80000090: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
80000094: 00001137 lui sp,0x1
|
||||
80000098: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800>
|
||||
8000009c: 3000b073 csrc mstatus,ra
|
||||
800000a0: 30012073 csrs mstatus,sp
|
||||
800000a4: 00000097 auipc ra,0x0
|
||||
800000a8: 01408093 addi ra,ra,20 # 800000b8 <test4+0x30>
|
||||
800000ac: 34109073 csrw mepc,ra
|
||||
800000b0: 30200073 mret
|
||||
800000b4: 6340006f j 800006e8 <fail>
|
||||
800000b8: 00000f17 auipc t5,0x0
|
||||
800000bc: 010f0f13 addi t5,t5,16 # 800000c8 <test5>
|
||||
800000c0: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
800000c4: 6240006f j 800006e8 <fail>
|
||||
|
||||
800000c8 <test5>:
|
||||
800000c8: 00500e13 li t3,5
|
||||
800000cc: 000020b7 lui ra,0x2
|
||||
800000d0: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
800000d4: 00000113 li sp,0
|
||||
800000d8: 3000b073 csrc mstatus,ra
|
||||
800000dc: 30012073 csrs mstatus,sp
|
||||
800000e0: 00000097 auipc ra,0x0
|
||||
800000e4: 01408093 addi ra,ra,20 # 800000f4 <test5+0x2c>
|
||||
800000e8: 34109073 csrw mepc,ra
|
||||
800000ec: 30200073 mret
|
||||
800000f0: 5f80006f j 800006e8 <fail>
|
||||
800000f4: 00000f17 auipc t5,0x0
|
||||
800000f8: 010f0f13 addi t5,t5,16 # 80000104 <test6>
|
||||
800000fc: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
80000100: 5e80006f j 800006e8 <fail>
|
||||
|
||||
80000104 <test6>:
|
||||
80000104: 00600e13 li t3,6
|
||||
80000108: 01000093 li ra,16
|
||||
8000010c: 30209073 csrw medeleg,ra
|
||||
|
||||
80000110 <test7>:
|
||||
80000110: 00700e13 li t3,7
|
||||
80000114: 00000f17 auipc t5,0x0
|
||||
80000118: 010f0f13 addi t5,t5,16 # 80000124 <test8>
|
||||
8000011c: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
80000120: 5c80006f j 800006e8 <fail>
|
||||
|
||||
80000124 <test8>:
|
||||
80000124: 00800e13 li t3,8
|
||||
80000128: 00000f17 auipc t5,0x0
|
||||
8000012c: 03cf0f13 addi t5,t5,60 # 80000164 <test9>
|
||||
80000130: 000020b7 lui ra,0x2
|
||||
80000134: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
80000138: 00001137 lui sp,0x1
|
||||
8000013c: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800>
|
||||
80000140: 3000b073 csrc mstatus,ra
|
||||
80000144: 30012073 csrs mstatus,sp
|
||||
80000148: 00000097 auipc ra,0x0
|
||||
8000014c: 01408093 addi ra,ra,20 # 8000015c <test8+0x38>
|
||||
80000150: 34109073 csrw mepc,ra
|
||||
80000154: 30200073 mret
|
||||
80000158: 5900006f j 800006e8 <fail>
|
||||
8000015c: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
80000160: 5880006f j 800006e8 <fail>
|
||||
|
||||
80000164 <test9>:
|
||||
80000164: 00900e13 li t3,9
|
||||
80000168: 00000f17 auipc t5,0x0
|
||||
8000016c: 038f0f13 addi t5,t5,56 # 800001a0 <test10>
|
||||
80000170: 000020b7 lui ra,0x2
|
||||
80000174: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
80000178: 00000113 li sp,0
|
||||
8000017c: 3000b073 csrc mstatus,ra
|
||||
80000180: 30012073 csrs mstatus,sp
|
||||
80000184: 00000097 auipc ra,0x0
|
||||
80000188: 01408093 addi ra,ra,20 # 80000198 <test9+0x34>
|
||||
8000018c: 34109073 csrw mepc,ra
|
||||
80000190: 30200073 mret
|
||||
80000194: 5540006f j 800006e8 <fail>
|
||||
80000198: 00102083 lw ra,1(zero) # 1 <_start-0x7fffffff>
|
||||
8000019c: 54c0006f j 800006e8 <fail>
|
||||
|
||||
800001a0 <test10>:
|
||||
800001a0: 00a00e13 li t3,10
|
||||
800001a4: 00000f17 auipc t5,0x0
|
||||
800001a8: 03cf0f13 addi t5,t5,60 # 800001e0 <test11>
|
||||
800001ac: f00110b7 lui ra,0xf0011
|
||||
800001b0: 00000113 li sp,0
|
||||
800001b4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
800001b8: 00800093 li ra,8
|
||||
800001bc: 30009073 csrw mstatus,ra
|
||||
800001c0: 000010b7 lui ra,0x1
|
||||
800001c4: 80008093 addi ra,ra,-2048 # 800 <_start-0x7ffff800>
|
||||
800001c8: 30409073 csrw mie,ra
|
||||
800001cc: f00110b7 lui ra,0xf0011
|
||||
800001d0: 00100113 li sp,1
|
||||
800001d4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
800001d8: 10500073 wfi
|
||||
800001dc: 50c0006f j 800006e8 <fail>
|
||||
|
||||
800001e0 <test11>:
|
||||
800001e0: 00b00e13 li t3,11
|
||||
800001e4: 00000f17 auipc t5,0x0
|
||||
800001e8: 068f0f13 addi t5,t5,104 # 8000024c <test12>
|
||||
800001ec: f00110b7 lui ra,0xf0011
|
||||
800001f0: 00000113 li sp,0
|
||||
800001f4: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
800001f8: 00800093 li ra,8
|
||||
800001fc: 30009073 csrw mstatus,ra
|
||||
80000200: 000010b7 lui ra,0x1
|
||||
80000204: 80008093 addi ra,ra,-2048 # 800 <_start-0x7ffff800>
|
||||
80000208: 30409073 csrw mie,ra
|
||||
8000020c: 000020b7 lui ra,0x2
|
||||
80000210: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
80000214: 00001137 lui sp,0x1
|
||||
80000218: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800>
|
||||
8000021c: 3000b073 csrc mstatus,ra
|
||||
80000220: 30012073 csrs mstatus,sp
|
||||
80000224: 00000097 auipc ra,0x0
|
||||
80000228: 01408093 addi ra,ra,20 # 80000238 <test11+0x58>
|
||||
8000022c: 34109073 csrw mepc,ra
|
||||
80000230: 30200073 mret
|
||||
80000234: 4b40006f j 800006e8 <fail>
|
||||
80000238: f00110b7 lui ra,0xf0011
|
||||
8000023c: 00100113 li sp,1
|
||||
80000240: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
80000244: 10500073 wfi
|
||||
80000248: 4a00006f j 800006e8 <fail>
|
||||
|
||||
8000024c <test12>:
|
||||
8000024c: 00c00e13 li t3,12
|
||||
80000250: 00000f17 auipc t5,0x0
|
||||
80000254: 064f0f13 addi t5,t5,100 # 800002b4 <test14>
|
||||
80000258: f00110b7 lui ra,0xf0011
|
||||
8000025c: 00000113 li sp,0
|
||||
80000260: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
80000264: 00800093 li ra,8
|
||||
80000268: 30009073 csrw mstatus,ra
|
||||
8000026c: 000010b7 lui ra,0x1
|
||||
80000270: 80008093 addi ra,ra,-2048 # 800 <_start-0x7ffff800>
|
||||
80000274: 30409073 csrw mie,ra
|
||||
80000278: 000020b7 lui ra,0x2
|
||||
8000027c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
80000280: 00000113 li sp,0
|
||||
80000284: 3000b073 csrc mstatus,ra
|
||||
80000288: 30012073 csrs mstatus,sp
|
||||
8000028c: 00000097 auipc ra,0x0
|
||||
80000290: 01408093 addi ra,ra,20 # 800002a0 <test12+0x54>
|
||||
80000294: 34109073 csrw mepc,ra
|
||||
80000298: 30200073 mret
|
||||
8000029c: 44c0006f j 800006e8 <fail>
|
||||
800002a0: f00110b7 lui ra,0xf0011
|
||||
800002a4: 00100113 li sp,1
|
||||
800002a8: 0020a023 sw sp,0(ra) # f0011000 <strap+0x700108c8>
|
||||
800002ac: 10500073 wfi
|
||||
800002b0: 4380006f j 800006e8 <fail>
|
||||
|
||||
800002b4 <test14>:
|
||||
800002b4: 00200093 li ra,2
|
||||
800002b8: 10009073 csrw sstatus,ra
|
||||
800002bc: 00e00e13 li t3,14
|
||||
800002c0: 00000f17 auipc t5,0x0
|
||||
800002c4: 040f0f13 addi t5,t5,64 # 80000300 <test15>
|
||||
800002c8: f00120b7 lui ra,0xf0012
|
||||
800002cc: 00000113 li sp,0
|
||||
800002d0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800002d4: 00200093 li ra,2
|
||||
800002d8: 30009073 csrw mstatus,ra
|
||||
800002dc: 20000093 li ra,512
|
||||
800002e0: 30409073 csrw mie,ra
|
||||
800002e4: 00000e93 li t4,0
|
||||
800002e8: f00120b7 lui ra,0xf0012
|
||||
800002ec: 00100113 li sp,1
|
||||
800002f0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800002f4: 06400093 li ra,100
|
||||
800002f8: fff08093 addi ra,ra,-1
|
||||
800002fc: fe104ee3 bgtz ra,800002f8 <test14+0x44>
|
||||
|
||||
80000300 <test15>:
|
||||
80000300: 00f00e13 li t3,15
|
||||
80000304: 00000f17 auipc t5,0x0
|
||||
80000308: 068f0f13 addi t5,t5,104 # 8000036c <test16>
|
||||
8000030c: f00120b7 lui ra,0xf0012
|
||||
80000310: 00000113 li sp,0
|
||||
80000314: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000318: 00200093 li ra,2
|
||||
8000031c: 30009073 csrw mstatus,ra
|
||||
80000320: 20000093 li ra,512
|
||||
80000324: 30409073 csrw mie,ra
|
||||
80000328: 000020b7 lui ra,0x2
|
||||
8000032c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
80000330: 00001137 lui sp,0x1
|
||||
80000334: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800>
|
||||
80000338: 3000b073 csrc mstatus,ra
|
||||
8000033c: 30012073 csrs mstatus,sp
|
||||
80000340: 00000097 auipc ra,0x0
|
||||
80000344: 01408093 addi ra,ra,20 # 80000354 <test15+0x54>
|
||||
80000348: 34109073 csrw mepc,ra
|
||||
8000034c: 30200073 mret
|
||||
80000350: 3980006f j 800006e8 <fail>
|
||||
80000354: 00100e93 li t4,1
|
||||
80000358: f00120b7 lui ra,0xf0012
|
||||
8000035c: 00100113 li sp,1
|
||||
80000360: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000364: 10500073 wfi
|
||||
80000368: 3800006f j 800006e8 <fail>
|
||||
|
||||
8000036c <test16>:
|
||||
8000036c: 01000e13 li t3,16
|
||||
80000370: 00000f17 auipc t5,0x0
|
||||
80000374: 060f0f13 addi t5,t5,96 # 800003d0 <test17>
|
||||
80000378: f00120b7 lui ra,0xf0012
|
||||
8000037c: 00000113 li sp,0
|
||||
80000380: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000384: 00200093 li ra,2
|
||||
80000388: 30009073 csrw mstatus,ra
|
||||
8000038c: 20000093 li ra,512
|
||||
80000390: 30409073 csrw mie,ra
|
||||
80000394: 000020b7 lui ra,0x2
|
||||
80000398: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
8000039c: 00000113 li sp,0
|
||||
800003a0: 3000b073 csrc mstatus,ra
|
||||
800003a4: 30012073 csrs mstatus,sp
|
||||
800003a8: 00000097 auipc ra,0x0
|
||||
800003ac: 01408093 addi ra,ra,20 # 800003bc <test16+0x50>
|
||||
800003b0: 34109073 csrw mepc,ra
|
||||
800003b4: 30200073 mret
|
||||
800003b8: 3300006f j 800006e8 <fail>
|
||||
800003bc: f00120b7 lui ra,0xf0012
|
||||
800003c0: 00100113 li sp,1
|
||||
800003c4: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800003c8: 10500073 wfi
|
||||
800003cc: 31c0006f j 800006e8 <fail>
|
||||
|
||||
800003d0 <test17>:
|
||||
800003d0: 01100e13 li t3,17
|
||||
800003d4: 20000093 li ra,512
|
||||
800003d8: 30309073 csrw mideleg,ra
|
||||
800003dc: 00000f17 auipc t5,0x0
|
||||
800003e0: 040f0f13 addi t5,t5,64 # 8000041c <test18>
|
||||
800003e4: f00120b7 lui ra,0xf0012
|
||||
800003e8: 00000113 li sp,0
|
||||
800003ec: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800003f0: 00200093 li ra,2
|
||||
800003f4: 30009073 csrw mstatus,ra
|
||||
800003f8: 20000093 li ra,512
|
||||
800003fc: 30409073 csrw mie,ra
|
||||
80000400: 00000e93 li t4,0
|
||||
80000404: f00120b7 lui ra,0xf0012
|
||||
80000408: 00100113 li sp,1
|
||||
8000040c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000410: 06400093 li ra,100
|
||||
80000414: fff08093 addi ra,ra,-1
|
||||
80000418: fe104ee3 bgtz ra,80000414 <test17+0x44>
|
||||
|
||||
8000041c <test18>:
|
||||
8000041c: 01200e13 li t3,18
|
||||
80000420: 00000f17 auipc t5,0x0
|
||||
80000424: 068f0f13 addi t5,t5,104 # 80000488 <test19>
|
||||
80000428: f00120b7 lui ra,0xf0012
|
||||
8000042c: 00000113 li sp,0
|
||||
80000430: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000434: 00200093 li ra,2
|
||||
80000438: 30009073 csrw mstatus,ra
|
||||
8000043c: 20000093 li ra,512
|
||||
80000440: 30409073 csrw mie,ra
|
||||
80000444: 000020b7 lui ra,0x2
|
||||
80000448: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
8000044c: 00001137 lui sp,0x1
|
||||
80000450: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800>
|
||||
80000454: 3000b073 csrc mstatus,ra
|
||||
80000458: 30012073 csrs mstatus,sp
|
||||
8000045c: 00000097 auipc ra,0x0
|
||||
80000460: 01408093 addi ra,ra,20 # 80000470 <test18+0x54>
|
||||
80000464: 34109073 csrw mepc,ra
|
||||
80000468: 30200073 mret
|
||||
8000046c: 27c0006f j 800006e8 <fail>
|
||||
80000470: 00100e93 li t4,1
|
||||
80000474: f00120b7 lui ra,0xf0012
|
||||
80000478: 00100113 li sp,1
|
||||
8000047c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000480: 10500073 wfi
|
||||
80000484: 2640006f j 800006e8 <fail>
|
||||
|
||||
80000488 <test19>:
|
||||
80000488: 01300e13 li t3,19
|
||||
8000048c: 00000f17 auipc t5,0x0
|
||||
80000490: 060f0f13 addi t5,t5,96 # 800004ec <test20>
|
||||
80000494: f00120b7 lui ra,0xf0012
|
||||
80000498: 00000113 li sp,0
|
||||
8000049c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800004a0: 00200093 li ra,2
|
||||
800004a4: 30009073 csrw mstatus,ra
|
||||
800004a8: 20000093 li ra,512
|
||||
800004ac: 30409073 csrw mie,ra
|
||||
800004b0: 000020b7 lui ra,0x2
|
||||
800004b4: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
800004b8: 00000113 li sp,0
|
||||
800004bc: 3000b073 csrc mstatus,ra
|
||||
800004c0: 30012073 csrs mstatus,sp
|
||||
800004c4: 00000097 auipc ra,0x0
|
||||
800004c8: 01408093 addi ra,ra,20 # 800004d8 <test19+0x50>
|
||||
800004cc: 34109073 csrw mepc,ra
|
||||
800004d0: 30200073 mret
|
||||
800004d4: 2140006f j 800006e8 <fail>
|
||||
800004d8: f00120b7 lui ra,0xf0012
|
||||
800004dc: 00100113 li sp,1
|
||||
800004e0: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800004e4: 10500073 wfi
|
||||
800004e8: 2000006f j 800006e8 <fail>
|
||||
|
||||
800004ec <test20>:
|
||||
800004ec: f00120b7 lui ra,0xf0012
|
||||
800004f0: 00000113 li sp,0
|
||||
800004f4: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
800004f8: 01400e13 li t3,20
|
||||
800004fc: 00000f17 auipc t5,0x0
|
||||
80000500: 030f0f13 addi t5,t5,48 # 8000052c <test21>
|
||||
80000504: 00200093 li ra,2
|
||||
80000508: 30009073 csrw mstatus,ra
|
||||
8000050c: 20000093 li ra,512
|
||||
80000510: 30409073 csrw mie,ra
|
||||
80000514: 00000e93 li t4,0
|
||||
80000518: 20000093 li ra,512
|
||||
8000051c: 1440a073 csrs sip,ra
|
||||
80000520: 06400093 li ra,100
|
||||
80000524: fff08093 addi ra,ra,-1
|
||||
80000528: fe104ee3 bgtz ra,80000524 <test20+0x38>
|
||||
|
||||
8000052c <test21>:
|
||||
8000052c: 01500e13 li t3,21
|
||||
80000530: 00000f17 auipc t5,0x0
|
||||
80000534: 060f0f13 addi t5,t5,96 # 80000590 <test22>
|
||||
80000538: 20000093 li ra,512
|
||||
8000053c: 1440b073 csrc sip,ra
|
||||
80000540: 00200093 li ra,2
|
||||
80000544: 30009073 csrw mstatus,ra
|
||||
80000548: 20000093 li ra,512
|
||||
8000054c: 30409073 csrw mie,ra
|
||||
80000550: 000020b7 lui ra,0x2
|
||||
80000554: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
80000558: 00001137 lui sp,0x1
|
||||
8000055c: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800>
|
||||
80000560: 3000b073 csrc mstatus,ra
|
||||
80000564: 30012073 csrs mstatus,sp
|
||||
80000568: 00000097 auipc ra,0x0
|
||||
8000056c: 01408093 addi ra,ra,20 # 8000057c <test21+0x50>
|
||||
80000570: 34109073 csrw mepc,ra
|
||||
80000574: 30200073 mret
|
||||
80000578: 1700006f j 800006e8 <fail>
|
||||
8000057c: 00100e93 li t4,1
|
||||
80000580: 20000093 li ra,512
|
||||
80000584: 1440a073 csrs sip,ra
|
||||
80000588: 10500073 wfi
|
||||
8000058c: 15c0006f j 800006e8 <fail>
|
||||
|
||||
80000590 <test22>:
|
||||
80000590: 01600e13 li t3,22
|
||||
80000594: 00000f17 auipc t5,0x0
|
||||
80000598: 058f0f13 addi t5,t5,88 # 800005ec <test23>
|
||||
8000059c: 20000093 li ra,512
|
||||
800005a0: 1440b073 csrc sip,ra
|
||||
800005a4: 00200093 li ra,2
|
||||
800005a8: 30009073 csrw mstatus,ra
|
||||
800005ac: 20000093 li ra,512
|
||||
800005b0: 30409073 csrw mie,ra
|
||||
800005b4: 20000093 li ra,512
|
||||
800005b8: 1440a073 csrs sip,ra
|
||||
800005bc: 000020b7 lui ra,0x2
|
||||
800005c0: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
800005c4: 00000113 li sp,0
|
||||
800005c8: 3000b073 csrc mstatus,ra
|
||||
800005cc: 30012073 csrs mstatus,sp
|
||||
800005d0: 00000097 auipc ra,0x0
|
||||
800005d4: 01408093 addi ra,ra,20 # 800005e4 <test22+0x54>
|
||||
800005d8: 34109073 csrw mepc,ra
|
||||
800005dc: 30200073 mret
|
||||
800005e0: 1080006f j 800006e8 <fail>
|
||||
800005e4: 10500073 wfi
|
||||
800005e8: 1000006f j 800006e8 <fail>
|
||||
|
||||
800005ec <test23>:
|
||||
800005ec: 01700e13 li t3,23
|
||||
800005f0: 00000e93 li t4,0
|
||||
800005f4: f00120b7 lui ra,0xf0012
|
||||
800005f8: 00000113 li sp,0
|
||||
800005fc: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000600: 20000093 li ra,512
|
||||
80000604: 1440b073 csrc sip,ra
|
||||
80000608: 344021f3 csrr gp,mip
|
||||
8000060c: f00120b7 lui ra,0xf0012
|
||||
80000610: 00100113 li sp,1
|
||||
80000614: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000618: 20000093 li ra,512
|
||||
8000061c: 1440b073 csrc sip,ra
|
||||
80000620: 344021f3 csrr gp,mip
|
||||
80000624: f00120b7 lui ra,0xf0012
|
||||
80000628: 00000113 li sp,0
|
||||
8000062c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000630: 20000093 li ra,512
|
||||
80000634: 1440b073 csrc sip,ra
|
||||
80000638: 344021f3 csrr gp,mip
|
||||
8000063c: f00120b7 lui ra,0xf0012
|
||||
80000640: 00000113 li sp,0
|
||||
80000644: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000648: 20000093 li ra,512
|
||||
8000064c: 1440a073 csrs sip,ra
|
||||
80000650: 344021f3 csrr gp,mip
|
||||
80000654: f00120b7 lui ra,0xf0012
|
||||
80000658: 00100113 li sp,1
|
||||
8000065c: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
80000660: 20000093 li ra,512
|
||||
80000664: 1440a073 csrs sip,ra
|
||||
80000668: 344021f3 csrr gp,mip
|
||||
8000066c: f00120b7 lui ra,0xf0012
|
||||
80000670: 00000113 li sp,0
|
||||
80000674: 0020a023 sw sp,0(ra) # f0012000 <strap+0x700118c8>
|
||||
|
||||
80000678 <test24>:
|
||||
80000678: 01800e13 li t3,24
|
||||
8000067c: 00200093 li ra,2
|
||||
80000680: 3040a073 csrs mie,ra
|
||||
80000684: 3440a073 csrs mip,ra
|
||||
80000688: 3000a073 csrs mstatus,ra
|
||||
8000068c: 00100e93 li t4,1
|
||||
80000690: 00000f17 auipc t5,0x0
|
||||
80000694: 03cf0f13 addi t5,t5,60 # 800006cc <test25>
|
||||
80000698: 000020b7 lui ra,0x2
|
||||
8000069c: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
800006a0: 00001137 lui sp,0x1
|
||||
800006a4: 80010113 addi sp,sp,-2048 # 800 <_start-0x7ffff800>
|
||||
800006a8: 3000b073 csrc mstatus,ra
|
||||
800006ac: 30012073 csrs mstatus,sp
|
||||
800006b0: 00000097 auipc ra,0x0
|
||||
800006b4: 01408093 addi ra,ra,20 # 800006c4 <test24_s>
|
||||
800006b8: 34109073 csrw mepc,ra
|
||||
800006bc: 30200073 mret
|
||||
800006c0: 0280006f j 800006e8 <fail>
|
||||
|
||||
800006c4 <test24_s>:
|
||||
800006c4: 10500073 wfi
|
||||
800006c8: 0200006f j 800006e8 <fail>
|
||||
|
||||
800006cc <test25>:
|
||||
800006cc: 01900e13 li t3,25
|
||||
800006d0: 00000f17 auipc t5,0x0
|
||||
800006d4: 014f0f13 addi t5,t5,20 # 800006e4 <test26>
|
||||
800006d8: 30046073 csrsi mstatus,8
|
||||
800006dc: 10500073 wfi
|
||||
800006e0: 0080006f j 800006e8 <fail>
|
||||
|
||||
800006e4 <test26>:
|
||||
800006e4: 0100006f j 800006f4 <pass>
|
||||
|
||||
800006e8 <fail>:
|
||||
800006e8: f0100137 lui sp,0xf0100
|
||||
800006ec: f2410113 addi sp,sp,-220 # f00fff24 <strap+0x700ff7ec>
|
||||
800006f0: 01c12023 sw t3,0(sp)
|
||||
|
||||
800006f4 <pass>:
|
||||
800006f4: f0100137 lui sp,0xf0100
|
||||
800006f8: f2010113 addi sp,sp,-224 # f00fff20 <strap+0x700ff7e8>
|
||||
800006fc: 00012023 sw zero,0(sp)
|
||||
|
||||
80000700 <mtrap>:
|
||||
80000700: fe0e84e3 beqz t4,800006e8 <fail>
|
||||
80000704: 342020f3 csrr ra,mcause
|
||||
80000708: 341020f3 csrr ra,mepc
|
||||
8000070c: 300020f3 csrr ra,mstatus
|
||||
80000710: 343020f3 csrr ra,mtval
|
||||
80000714: 08000093 li ra,128
|
||||
80000718: 3000b073 csrc mstatus,ra
|
||||
8000071c: 00200093 li ra,2
|
||||
80000720: fc1e8ae3 beq t4,ra,800006f4 <pass>
|
||||
80000724: 000020b7 lui ra,0x2
|
||||
80000728: 80008093 addi ra,ra,-2048 # 1800 <_start-0x7fffe800>
|
||||
8000072c: 3000a073 csrs mstatus,ra
|
||||
80000730: 341f1073 csrw mepc,t5
|
||||
80000734: 30200073 mret
|
||||
|
||||
80000738 <strap>:
|
||||
80000738: fa0e88e3 beqz t4,800006e8 <fail>
|
||||
8000073c: 142020f3 csrr ra,scause
|
||||
80000740: 141020f3 csrr ra,sepc
|
||||
80000744: 100020f3 csrr ra,sstatus
|
||||
80000748: 143020f3 csrr ra,stval
|
||||
8000074c: 00000073 ecall
|
||||
80000750: 00000013 nop
|
||||
80000754: 00000013 nop
|
||||
80000758: 00000013 nop
|
||||
8000075c: 00000013 nop
|
||||
80000760: 00000013 nop
|
||||
80000764: 00000013 nop
|
122
src/test/cpp/raw/deleg/build/deleg.hex
Normal file
122
src/test/cpp/raw/deleg/build/deleg.hex
Normal file
|
@ -0,0 +1,122 @@
|
|||
:0200000480007A
|
||||
:10000000930E1000970000009380C06F73905030E3
|
||||
:10001000970000009380807273905010B71001F029
|
||||
:100020001301000023A02000130E1000170F000082
|
||||
:10003000130FCF0073000000130E2000B720000044
|
||||
:10004000938000801301000073B0003073200130F2
|
||||
:1000500097000000938040017390103473002030AB
|
||||
:100060006F008068170F0000130F4F02730000002D
|
||||
:100070006F008067130E3000170F0000130F0F0181
|
||||
:10008000832010006F004066130E4000B720000070
|
||||
:1000900093800080371100001301018073B000309D
|
||||
:1000A000732001309700000093804001739010345A
|
||||
:1000B000730020306F004063170F0000130F0F0113
|
||||
:1000C000832010006F004062130E5000B720000024
|
||||
:1000D000938000801301000073B000307320013062
|
||||
:1000E000970000009380400173901034730020301B
|
||||
:1000F0006F00805F170F0000130F0F0183201000A7
|
||||
:100100006F00805E130E600093000001739020303A
|
||||
:10011000130E7000170F0000130F0F018320100043
|
||||
:100120006F00805C130E8000170F0000130FCF03C9
|
||||
:10013000B720000093800080371100001301018078
|
||||
:1001400073B00030732001309700000093804001AD
|
||||
:1001500073901034730020306F000059832010001A
|
||||
:100160006F008058130E9000170F0000130F8F03BD
|
||||
:10017000B7200000938000801301000073B00030AE
|
||||
:100180007320013097000000938040017390103479
|
||||
:10019000730020306F004055832010006F00C05462
|
||||
:1001A000130EA000170F0000130FCF03B71001F0BC
|
||||
:1001B0001301000023A02000930080007390003002
|
||||
:1001C000B71000009380008073904030B71001F0AA
|
||||
:1001D0001301100023A02000730050106F00C050C6
|
||||
:1001E000130EB000170F0000130F8F06B71001F0A9
|
||||
:1001F0001301000023A020009300800073900030C2
|
||||
:10020000B71000009380008073904030B72000004A
|
||||
:1002100093800080371100001301018073B000301B
|
||||
:1002200073200130970000009380400173901034D8
|
||||
:10023000730020306F00404BB71001F01301100025
|
||||
:1002400023A02000730050106F00004A130EC0005E
|
||||
:10025000170F0000130F4F06B71001F01301000035
|
||||
:1002600023A020009300800073900030B71000009E
|
||||
:100270009380008073904030B7200000938000800E
|
||||
:100280001301000073B000307320013097000000AC
|
||||
:100290009380400173901034730020306F00C0448D
|
||||
:1002A000B71001F01301100023A0200073005010BC
|
||||
:1002B0006F0080439300200073900010130EE00045
|
||||
:1002C000170F0000130F0F04B72001F013010000F7
|
||||
:1002D00023A02000930020007390003093000020A2
|
||||
:1002E00073904030930E0000B72001F0130110000E
|
||||
:1002F00023A02000930040069380F0FFE34E10FE01
|
||||
:10030000130EF000170F0000130F8F06B72001F037
|
||||
:100310001301000023A02000930020007390003000
|
||||
:100320009300002073904030B7200000938000803D
|
||||
:10033000371100001301018073B0003073200130C9
|
||||
:1003400097000000938040017390103473002030B8
|
||||
:100350006F008039930E1000B72001F013011000D8
|
||||
:1003600023A02000730050106F000038130E00010E
|
||||
:10037000170F0000130F0F06B72001F01301000044
|
||||
:1003800023A02000930020007390003093000020F1
|
||||
:1003900073904030B720000093800080130100006C
|
||||
:1003A00073B000307320013097000000938040014B
|
||||
:1003B00073901034730020306F000033B72001F0C9
|
||||
:1003C0001301100023A02000730050106F00C031F3
|
||||
:1003D000130E10019300002073903030170F0000AF
|
||||
:1003E000130F0F04B72001F01301000023A0200019
|
||||
:1003F00093002000739000309300002073904030F1
|
||||
:10040000930E0000B72001F01301100023A020007C
|
||||
:10041000930040069380F0FFE34E10FE130E200180
|
||||
:10042000170F0000130F8F06B72001F01301000013
|
||||
:1004300023A0200093002000739000309300002040
|
||||
:1004400073904030B7200000938000803711000087
|
||||
:100450001301018073B00030732001309700000059
|
||||
:100460009380400173901034730020306F00C027D8
|
||||
:10047000930E1000B72001F01301100023A02000FC
|
||||
:10048000730050106F004026130E3001170F00004C
|
||||
:10049000130F0F06B72001F01301000023A0200066
|
||||
:1004A0009300200073900030930000207390403040
|
||||
:1004B000B7200000938000801301000073B000306B
|
||||
:1004C0007320013097000000938040017390103436
|
||||
:1004D000730020306F004021B72001F0130110009D
|
||||
:1004E00023A02000730050106F000020B72001F0FF
|
||||
:1004F0001301000023A02000130E4001170F00007D
|
||||
:10050000130F0F039300200073900030930000201E
|
||||
:1005100073904030930E00009300002073A04014AD
|
||||
:10052000930040069380F0FFE34E10FE130E50013F
|
||||
:10053000170F0000130F0F069300002073B0401434
|
||||
:10054000930020007390003093000020739040309F
|
||||
:10055000B720000093800080371100001301018054
|
||||
:1005600073B0003073200130970000009380400189
|
||||
:1005700073901034730020306F000017930E10003A
|
||||
:100580009300002073A04014730050106F00C0153A
|
||||
:10059000130E6001170F0000130F8F05930000204A
|
||||
:1005A00073B040149300200073900030930000203B
|
||||
:1005B000739040309300002073A04014B7200000D7
|
||||
:1005C000938000801301000073B00030732001306D
|
||||
:1005D0009700000093804001739010347300203026
|
||||
:1005E0006F008010730050106F000010130E700128
|
||||
:1005F000930E0000B72001F01301000023A020009B
|
||||
:100600009300002073B04014F3214034B72001F070
|
||||
:100610001301100023A020009300002073B04014A9
|
||||
:10062000F3214034B72001F01301000023A0200083
|
||||
:100630009300002073B04014F3214034B72001F040
|
||||
:100640001301000023A020009300002073A0401499
|
||||
:10065000F3214034B72001F01301100023A0200043
|
||||
:100660009300002073A04014F3214034B72001F020
|
||||
:100670001301000023A02000130E8001930020002E
|
||||
:1006800073A0403073A0403473A00030930E10006C
|
||||
:10069000170F0000130FCF03B720000093800080D6
|
||||
:1006A000371100001301018073B000307320013056
|
||||
:1006B0009700000093804001739010347300203045
|
||||
:1006C0006F008002730050106F000002130E900143
|
||||
:1006D000170F0000130F4F017360043073005010A8
|
||||
:1006E0006F0080006F000001370110F0130141F22C
|
||||
:1006F0002320C101370110F0130101F22320010072
|
||||
:10070000E3840EFEF3202034F3201034F320003075
|
||||
:10071000F32030349300000873B0003093002000C1
|
||||
:10072000E38A1EFCB72000009380008073A0003095
|
||||
:1007300073101F3473002030E3880EFAF320201466
|
||||
:10074000F3201014F3200010F32030147300000085
|
||||
:10075000130000001300000013000000130000004D
|
||||
:0807600013000000130000006B
|
||||
:040000058000000077
|
||||
:00000001FF
|
3
src/test/cpp/raw/deleg/makefile
Normal file
3
src/test/cpp/raw/deleg/makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
PROJ_NAME=deleg
|
||||
|
||||
include ../common/asm.mk
|
382
src/test/cpp/raw/deleg/src/crt.S
Normal file
382
src/test/cpp/raw/deleg/src/crt.S
Normal file
|
@ -0,0 +1,382 @@
|
|||
.globl _start
|
||||
|
||||
#define TEST_ID x28
|
||||
#define TRAP_OK x29
|
||||
#define TRAP_RET x30
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#define externalInterrupt(value) \
|
||||
li x1, 0xF0011000; \
|
||||
li x2, value; \
|
||||
sw x2, 0(x1); \
|
||||
|
||||
#define externalInterruptS(value) \
|
||||
li x1, 0xF0012000; \
|
||||
li x2, value; \
|
||||
sw x2, 0(x1); \
|
||||
|
||||
|
||||
|
||||
#define delay() \
|
||||
li x1, 100; \
|
||||
1: \
|
||||
addi x1, x1, -1; \
|
||||
bgt x1, x0, 1b; \
|
||||
|
||||
|
||||
#define setPriv(value) \
|
||||
li x1, 3 << 11; \
|
||||
li x2, value << 11; \
|
||||
csrc mstatus, x1; \
|
||||
csrs mstatus, x2; \
|
||||
auipc x1, 0; \
|
||||
addi x1, x1, 20; \
|
||||
csrw mepc, x1; \
|
||||
mret; \
|
||||
j fail; \
|
||||
|
||||
|
||||
ROM_SUPER_0:
|
||||
|
||||
_start:
|
||||
li TRAP_OK, 1
|
||||
la x1, mtrap
|
||||
csrw mtvec, x1
|
||||
la x1, strap
|
||||
csrw stvec, x1
|
||||
externalInterrupt(0);
|
||||
|
||||
test1:
|
||||
li TEST_ID, 1
|
||||
la TRAP_RET, test2
|
||||
ecall
|
||||
|
||||
test2: //simple ecall from user to machine
|
||||
li TEST_ID, 2
|
||||
setPriv(0)
|
||||
la TRAP_RET, test4
|
||||
ecall
|
||||
j fail
|
||||
|
||||
test3: //M mialigned load exception without deleg
|
||||
li TEST_ID, 3
|
||||
la TRAP_RET, test4
|
||||
lw x1, 1(x0)
|
||||
j fail
|
||||
test4: //S mialigned load exception without deleg
|
||||
li TEST_ID, 4
|
||||
setPriv(1)
|
||||
la TRAP_RET, test5
|
||||
lw x1, 1(x0)
|
||||
j fail
|
||||
test5: //U mialigned load exception without deleg
|
||||
li TEST_ID, 5
|
||||
setPriv(0)
|
||||
la TRAP_RET, test6
|
||||
lw x1, 1(x0)
|
||||
j fail
|
||||
|
||||
test6: // set medeleg
|
||||
li TEST_ID, 6
|
||||
li x1, 1 << CAUSE_MISALIGNED_LOAD
|
||||
csrw medeleg, x1
|
||||
|
||||
test7: //machine mode exception
|
||||
li TEST_ID, 7
|
||||
la TRAP_RET, test8
|
||||
lw x1, 1(x0)
|
||||
j fail
|
||||
|
||||
test8: //supervisor mode exception
|
||||
li TEST_ID, 8
|
||||
la TRAP_RET, test9
|
||||
setPriv(1)
|
||||
lw x1, 1(x0)
|
||||
j fail
|
||||
|
||||
test9: //user mode exception
|
||||
li TEST_ID, 9
|
||||
la TRAP_RET, test10
|
||||
setPriv(0)
|
||||
lw x1, 1(x0)
|
||||
j fail
|
||||
|
||||
test10: //M external interrupt
|
||||
li TEST_ID, 10
|
||||
la TRAP_RET, test11
|
||||
externalInterrupt(0)
|
||||
li x1, MSTATUS_MIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 11
|
||||
csrw mie, x1
|
||||
externalInterrupt(1)
|
||||
wfi
|
||||
j fail
|
||||
|
||||
test11: //S external interrupt
|
||||
li TEST_ID, 11
|
||||
la TRAP_RET, test12
|
||||
externalInterrupt(0)
|
||||
li x1, MSTATUS_MIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 11
|
||||
csrw mie, x1
|
||||
setPriv(1)
|
||||
externalInterrupt(1)
|
||||
wfi
|
||||
j fail
|
||||
|
||||
test12: //U external interrupt
|
||||
li TEST_ID, 12
|
||||
la TRAP_RET, test14
|
||||
externalInterrupt(0)
|
||||
li x1, MSTATUS_MIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 11
|
||||
csrw mie, x1
|
||||
setPriv(0)
|
||||
externalInterrupt(1)
|
||||
wfi
|
||||
j fail
|
||||
|
||||
|
||||
|
||||
test14: //M external interrupt S
|
||||
li x1, MSTATUS_SIE
|
||||
csrw sstatus, x1
|
||||
|
||||
li TEST_ID, 14
|
||||
la TRAP_RET, test15
|
||||
externalInterruptS(0)
|
||||
li x1, MSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
li TRAP_OK, 0
|
||||
externalInterruptS(1)
|
||||
delay()
|
||||
|
||||
test15: //S external interrupt S
|
||||
li TEST_ID, 15
|
||||
la TRAP_RET, test16
|
||||
externalInterruptS(0)
|
||||
li x1, SSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
setPriv(1)
|
||||
li TRAP_OK, 1
|
||||
externalInterruptS(1)
|
||||
wfi
|
||||
j fail
|
||||
|
||||
test16: //U external interrupt S
|
||||
li TEST_ID, 16
|
||||
la TRAP_RET, test17
|
||||
externalInterruptS(0)
|
||||
li x1, SSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
setPriv(0)
|
||||
externalInterruptS(1)
|
||||
wfi
|
||||
j fail
|
||||
|
||||
|
||||
test17:// set mideleg
|
||||
li TEST_ID, 17
|
||||
li x1, 1 << 9
|
||||
csrw mideleg, x1
|
||||
|
||||
|
||||
la TRAP_RET, test18
|
||||
externalInterruptS(0)
|
||||
li x1, MSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
li TRAP_OK, 0
|
||||
externalInterruptS(1)
|
||||
delay()
|
||||
|
||||
test18: //S external interrupt S with deleg
|
||||
li TEST_ID, 18
|
||||
la TRAP_RET, test19
|
||||
externalInterruptS(0)
|
||||
li x1, SSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
setPriv(1)
|
||||
li TRAP_OK, 1
|
||||
externalInterruptS(1)
|
||||
wfi
|
||||
j fail
|
||||
|
||||
test19: //U external interrupt S with deleg
|
||||
li TEST_ID, 19
|
||||
la TRAP_RET, test20
|
||||
externalInterruptS(0)
|
||||
li x1, SSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
setPriv(0)
|
||||
externalInterruptS(1)
|
||||
wfi
|
||||
j fail
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
test20:// M external interrupt S by software with deleg
|
||||
externalInterruptS(0)
|
||||
li TEST_ID, 20
|
||||
la TRAP_RET, test21
|
||||
li x1, MSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
li TRAP_OK, 0
|
||||
li x1, 1 << 9
|
||||
csrs sip, x1
|
||||
delay()
|
||||
|
||||
test21: //S external interrupt S by software with deleg
|
||||
li TEST_ID, 21
|
||||
la TRAP_RET, test22
|
||||
li x1, 1 << 9
|
||||
csrc sip, x1
|
||||
li x1, SSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
setPriv(1)
|
||||
li TRAP_OK, 1
|
||||
li x1, 1 << 9
|
||||
csrs sip, x1
|
||||
wfi
|
||||
j fail
|
||||
|
||||
test22: //U external interrupt S by software with deleg
|
||||
li TEST_ID, 22
|
||||
la TRAP_RET, test23
|
||||
li x1, 1 << 9
|
||||
csrc sip, x1
|
||||
li x1, SSTATUS_SIE
|
||||
csrw mstatus, x1
|
||||
li x1, 1 << 9
|
||||
csrw mie, x1
|
||||
li x1, 1 << 9
|
||||
csrs sip, x1
|
||||
setPriv(0)
|
||||
wfi
|
||||
j fail
|
||||
|
||||
|
||||
|
||||
test23: //Test software and hardware setting inettrupt
|
||||
li TEST_ID, 23
|
||||
li TRAP_OK, 0
|
||||
externalInterruptS(0)
|
||||
li x1, 1 << 9
|
||||
csrc sip, x1
|
||||
csrr x3, mip
|
||||
|
||||
|
||||
externalInterruptS(1)
|
||||
li x1, 1 << 9
|
||||
csrc sip, x1
|
||||
csrr x3, mip
|
||||
|
||||
|
||||
externalInterruptS(0)
|
||||
li x1, 1 << 9
|
||||
csrc sip, x1
|
||||
csrr x3, mip
|
||||
|
||||
|
||||
externalInterruptS(0)
|
||||
li x1, 1 << 9
|
||||
csrs sip, x1
|
||||
csrr x3, mip
|
||||
|
||||
|
||||
externalInterruptS(1)
|
||||
li x1, 1 << 9
|
||||
csrs sip, x1
|
||||
csrr x3, mip
|
||||
|
||||
externalInterruptS(0)
|
||||
|
||||
test24: //test supervisor software interrupt
|
||||
li TEST_ID, 24
|
||||
li x1, 2
|
||||
csrs mie, x1
|
||||
csrs mip, x1
|
||||
csrs mstatus, x1
|
||||
|
||||
li TRAP_OK, 1
|
||||
la TRAP_RET, test25
|
||||
setPriv(1)
|
||||
test24_s:
|
||||
wfi
|
||||
j fail
|
||||
|
||||
|
||||
test25: //test undelegated supervisor interrupt in machine mode (continue test24)
|
||||
li TEST_ID, 25
|
||||
la TRAP_RET, test26
|
||||
csrsi mstatus, 1 << 3 //mie
|
||||
wfi
|
||||
j fail
|
||||
|
||||
|
||||
test26:
|
||||
|
||||
j pass
|
||||
|
||||
fail:
|
||||
li x2, 0xF00FFF24
|
||||
sw TEST_ID, 0(x2)
|
||||
|
||||
pass:
|
||||
li x2, 0xF00FFF20
|
||||
sw x0, 0(x2)
|
||||
|
||||
|
||||
mtrap:
|
||||
beq TRAP_OK, x0, fail
|
||||
csrr x1, mcause
|
||||
csrr x1, mepc
|
||||
csrr x1, mstatus
|
||||
csrr x1, mbadaddr
|
||||
li x1, MSTATUS_MPIE
|
||||
csrc mstatus, x1
|
||||
li x1, 2
|
||||
beq TRAP_OK, x1, pass
|
||||
li x1, 3 << 11
|
||||
csrs mstatus, x1
|
||||
csrw mepc, TRAP_RET
|
||||
mret
|
||||
|
||||
|
||||
strap:
|
||||
beq TRAP_OK, x0, fail
|
||||
csrr x1, scause
|
||||
csrr x1, sepc
|
||||
csrr x1, sstatus
|
||||
csrr x1, sbadaddr
|
||||
ecall
|
||||
|
||||
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
1471
src/test/cpp/raw/deleg/src/encoding.h
Normal file
1471
src/test/cpp/raw/deleg/src/encoding.h
Normal file
File diff suppressed because it is too large
Load diff
16
src/test/cpp/raw/deleg/src/ld
Normal file
16
src/test/cpp/raw/deleg/src/ld
Normal file
|
@ -0,0 +1,16 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
MEMORY {
|
||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.crt_section :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*crt.o(.text)
|
||||
} > onChipRam
|
||||
|
||||
}
|
4
src/test/cpp/raw/icache/.gitignore
vendored
Normal file
4
src/test/cpp/raw/icache/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
51
src/test/cpp/raw/icache/build/icache.asm
Normal file
51
src/test/cpp/raw/icache/build/icache.asm
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
build/icache.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .crt_section:
|
||||
|
||||
80000000 <_start>:
|
||||
80000000: 00000097 auipc ra,0x0
|
||||
80000004: 04c08093 addi ra,ra,76 # 8000004c <fail>
|
||||
|
||||
80000008 <test1>:
|
||||
80000008: 00100e13 li t3,1
|
||||
8000000c: 00100093 li ra,1
|
||||
80000010: 00300113 li sp,3
|
||||
80000014: 00208093 addi ra,ra,2
|
||||
80000018: 02209a63 bne ra,sp,8000004c <fail>
|
||||
|
||||
8000001c <test2>:
|
||||
8000001c: 00200e13 li t3,2
|
||||
80000020: 01300093 li ra,19
|
||||
80000024: 00000117 auipc sp,0x0
|
||||
80000028: 02010113 addi sp,sp,32 # 80000044 <test2_trigger>
|
||||
8000002c: 0040006f j 80000030 <test2_aligned>
|
||||
|
||||
80000030 <test2_aligned>:
|
||||
80000030: 00112023 sw ra,0(sp)
|
||||
80000034: 0000100f fence.i
|
||||
80000038: 00800a13 li s4,8
|
||||
8000003c: fffa0a13 addi s4,s4,-1
|
||||
80000040: fe0a1ee3 bnez s4,8000003c <test2_aligned+0xc>
|
||||
|
||||
80000044 <test2_trigger>:
|
||||
80000044: 0080006f j 8000004c <fail>
|
||||
80000048: 0100006f j 80000058 <pass>
|
||||
|
||||
8000004c <fail>:
|
||||
8000004c: f0100137 lui sp,0xf0100
|
||||
80000050: f2410113 addi sp,sp,-220 # f00fff24 <pass+0x700ffecc>
|
||||
80000054: 01c12023 sw t3,0(sp)
|
||||
|
||||
80000058 <pass>:
|
||||
80000058: f0100137 lui sp,0xf0100
|
||||
8000005c: f2010113 addi sp,sp,-224 # f00fff20 <pass+0x700ffec8>
|
||||
80000060: 00012023 sw zero,0(sp)
|
||||
80000064: 00000013 nop
|
||||
80000068: 00000013 nop
|
||||
8000006c: 00000013 nop
|
||||
80000070: 00000013 nop
|
||||
80000074: 00000013 nop
|
||||
80000078: 00000013 nop
|
||||
...
|
11
src/test/cpp/raw/icache/build/icache.hex
Normal file
11
src/test/cpp/raw/icache/build/icache.hex
Normal file
|
@ -0,0 +1,11 @@
|
|||
:0200000480007A
|
||||
:10000000970000009380C004130E100093001000AE
|
||||
:100010001301300093802000639A2002130E200009
|
||||
:100020009300300117010000130101026F0040002E
|
||||
:10003000232011000F100000130A8000130AFAFF9A
|
||||
:10004000E31E0AFE6F0080006F000001370110F010
|
||||
:10005000130141F22320C101370110F0130101F215
|
||||
:100060002320010013000000130000001300000013
|
||||
:100070001300000013000000130000000000000047
|
||||
:04008000000000007C
|
||||
:00000001FF
|
3
src/test/cpp/raw/icache/makefile
Normal file
3
src/test/cpp/raw/icache/makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
PROJ_NAME=icache
|
||||
|
||||
include ../common/asm.mk
|
49
src/test/cpp/raw/icache/src/crt.S
Normal file
49
src/test/cpp/raw/icache/src/crt.S
Normal file
|
@ -0,0 +1,49 @@
|
|||
.globl _star
|
||||
#define TEST_ID x28
|
||||
|
||||
#define delay \
|
||||
li x20, 8; \
|
||||
1: addi x20, x20, -1; \
|
||||
bne x20, x0, 1b;
|
||||
|
||||
_start:
|
||||
la x1, fail
|
||||
// csrw mtvec, x1
|
||||
|
||||
test1: //Dummy test
|
||||
li TEST_ID, 1
|
||||
li x1, 1
|
||||
li x2, 3
|
||||
addi x1, x1, 2
|
||||
bne x1, x2, fail
|
||||
|
||||
test2:
|
||||
li TEST_ID, 2
|
||||
li x1, 0x13 //nop
|
||||
la x2, test2_trigger
|
||||
j test2_aligned
|
||||
.align(4)
|
||||
test2_aligned:
|
||||
sw x1, 0(x2)
|
||||
fence.i
|
||||
delay
|
||||
test2_trigger:
|
||||
j fail
|
||||
|
||||
|
||||
j pass
|
||||
|
||||
fail:
|
||||
li x2, 0xF00FFF24
|
||||
sw TEST_ID, 0(x2)
|
||||
|
||||
pass:
|
||||
li x2, 0xF00FFF20
|
||||
sw x0, 0(x2)
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
16
src/test/cpp/raw/icache/src/ld
Normal file
16
src/test/cpp/raw/icache/src/ld
Normal file
|
@ -0,0 +1,16 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
MEMORY {
|
||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.crt_section :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*crt.o(.text)
|
||||
} > onChipRam
|
||||
|
||||
}
|
4
src/test/cpp/raw/lrsc/.gitignore
vendored
Normal file
4
src/test/cpp/raw/lrsc/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
217
src/test/cpp/raw/lrsc/build/lrsc.asm
Normal file
217
src/test/cpp/raw/lrsc/build/lrsc.asm
Normal file
|
@ -0,0 +1,217 @@
|
|||
|
||||
build/lrsc.elf: file format elf32-littleriscv
|
||||
|
||||
|
||||
Disassembly of section .crt_section:
|
||||
|
||||
80000000 <trap_entry-0x20>:
|
||||
80000000: 04c0006f j 8000004c <_start>
|
||||
80000004: 00000013 nop
|
||||
80000008: 00000013 nop
|
||||
8000000c: 00000013 nop
|
||||
80000010: 00000013 nop
|
||||
80000014: 00000013 nop
|
||||
80000018: 00000013 nop
|
||||
8000001c: 00000013 nop
|
||||
|
||||
80000020 <trap_entry>:
|
||||
80000020: 30002ef3 csrr t4,mstatus
|
||||
80000024: 080efe93 andi t4,t4,128
|
||||
80000028: 000e8a63 beqz t4,8000003c <notExternalInterrupt>
|
||||
8000002c: 00002eb7 lui t4,0x2
|
||||
80000030: 800e8e93 addi t4,t4,-2048 # 1800 <trap_entry-0x7fffe820>
|
||||
80000034: 300e9073 csrw mstatus,t4
|
||||
80000038: 30200073 mret
|
||||
|
||||
8000003c <notExternalInterrupt>:
|
||||
8000003c: 34102ef3 csrr t4,mepc
|
||||
80000040: 004e8e93 addi t4,t4,4
|
||||
80000044: 341e9073 csrw mepc,t4
|
||||
80000048: 30200073 mret
|
||||
|
||||
8000004c <_start>:
|
||||
8000004c: 00100e13 li t3,1
|
||||
80000050: 10000537 lui a0,0x10000
|
||||
80000054: 06400593 li a1,100
|
||||
80000058: 06500613 li a2,101
|
||||
8000005c: 06600693 li a3,102
|
||||
80000060: 00d52023 sw a3,0(a0) # 10000000 <trap_entry-0x70000020>
|
||||
80000064: 18b5262f sc.w a2,a1,(a0)
|
||||
80000068: 00100713 li a4,1
|
||||
8000006c: 26e61e63 bne a2,a4,800002e8 <fail>
|
||||
80000070: 00052703 lw a4,0(a0)
|
||||
80000074: 26e69a63 bne a3,a4,800002e8 <fail>
|
||||
80000078: 00200e13 li t3,2
|
||||
8000007c: 10000537 lui a0,0x10000
|
||||
80000080: 00450513 addi a0,a0,4 # 10000004 <trap_entry-0x7000001c>
|
||||
80000084: 06700593 li a1,103
|
||||
80000088: 06800613 li a2,104
|
||||
8000008c: 06900693 li a3,105
|
||||
80000090: 00d52023 sw a3,0(a0)
|
||||
80000094: 18b5262f sc.w a2,a1,(a0)
|
||||
80000098: 00100713 li a4,1
|
||||
8000009c: 24e61663 bne a2,a4,800002e8 <fail>
|
||||
800000a0: 00052703 lw a4,0(a0)
|
||||
800000a4: 24e69263 bne a3,a4,800002e8 <fail>
|
||||
800000a8: 00300e13 li t3,3
|
||||
800000ac: 10000537 lui a0,0x10000
|
||||
800000b0: 00450513 addi a0,a0,4 # 10000004 <trap_entry-0x7000001c>
|
||||
800000b4: 06700593 li a1,103
|
||||
800000b8: 06800613 li a2,104
|
||||
800000bc: 06900693 li a3,105
|
||||
800000c0: 18b5262f sc.w a2,a1,(a0)
|
||||
800000c4: 00100713 li a4,1
|
||||
800000c8: 22e61063 bne a2,a4,800002e8 <fail>
|
||||
800000cc: 00052703 lw a4,0(a0)
|
||||
800000d0: 20e69c63 bne a3,a4,800002e8 <fail>
|
||||
800000d4: 00400e13 li t3,4
|
||||
800000d8: 10000537 lui a0,0x10000
|
||||
800000dc: 00850513 addi a0,a0,8 # 10000008 <trap_entry-0x70000018>
|
||||
800000e0: 06a00593 li a1,106
|
||||
800000e4: 06b00613 li a2,107
|
||||
800000e8: 06c00693 li a3,108
|
||||
800000ec: 00d52023 sw a3,0(a0)
|
||||
800000f0: 100527af lr.w a5,(a0)
|
||||
800000f4: 18b5262f sc.w a2,a1,(a0)
|
||||
800000f8: 1ed79863 bne a5,a3,800002e8 <fail>
|
||||
800000fc: 1e061663 bnez a2,800002e8 <fail>
|
||||
80000100: 00052703 lw a4,0(a0)
|
||||
80000104: 1ee59263 bne a1,a4,800002e8 <fail>
|
||||
80000108: 00500e13 li t3,5
|
||||
8000010c: 10000537 lui a0,0x10000
|
||||
80000110: 00850513 addi a0,a0,8 # 10000008 <trap_entry-0x70000018>
|
||||
80000114: 06d00593 li a1,109
|
||||
80000118: 06e00613 li a2,110
|
||||
8000011c: 06f00693 li a3,111
|
||||
80000120: 00d52023 sw a3,0(a0)
|
||||
80000124: 18b5262f sc.w a2,a1,(a0)
|
||||
80000128: 1c061063 bnez a2,800002e8 <fail>
|
||||
8000012c: 00052703 lw a4,0(a0)
|
||||
80000130: 1ae59c63 bne a1,a4,800002e8 <fail>
|
||||
80000134: 00600e13 li t3,6
|
||||
80000138: 10000537 lui a0,0x10000
|
||||
8000013c: 00c50513 addi a0,a0,12 # 1000000c <trap_entry-0x70000014>
|
||||
80000140: 07000593 li a1,112
|
||||
80000144: 07100613 li a2,113
|
||||
80000148: 07200693 li a3,114
|
||||
8000014c: 10000437 lui s0,0x10000
|
||||
80000150: 01040413 addi s0,s0,16 # 10000010 <trap_entry-0x70000010>
|
||||
80000154: 07300493 li s1,115
|
||||
80000158: 07400913 li s2,116
|
||||
8000015c: 07500993 li s3,117
|
||||
80000160: 00d52023 sw a3,0(a0)
|
||||
80000164: 01342023 sw s3,0(s0)
|
||||
80000168: 100527af lr.w a5,(a0)
|
||||
8000016c: 10042aaf lr.w s5,(s0)
|
||||
80000170: 18b5262f sc.w a2,a1,(a0)
|
||||
80000174: 1894292f sc.w s2,s1,(s0)
|
||||
80000178: 16d79863 bne a5,a3,800002e8 <fail>
|
||||
8000017c: 16061663 bnez a2,800002e8 <fail>
|
||||
80000180: 00052703 lw a4,0(a0)
|
||||
80000184: 16e59263 bne a1,a4,800002e8 <fail>
|
||||
80000188: 173a9063 bne s5,s3,800002e8 <fail>
|
||||
8000018c: 14091e63 bnez s2,800002e8 <fail>
|
||||
80000190: 00042a03 lw s4,0(s0)
|
||||
80000194: 15449a63 bne s1,s4,800002e8 <fail>
|
||||
80000198: 00700e13 li t3,7
|
||||
8000019c: 10000537 lui a0,0x10000
|
||||
800001a0: 01450513 addi a0,a0,20 # 10000014 <trap_entry-0x7000000c>
|
||||
800001a4: 07800593 li a1,120
|
||||
800001a8: 07900613 li a2,121
|
||||
800001ac: 07a00693 li a3,122
|
||||
800001b0: 01000e93 li t4,16
|
||||
|
||||
800001b4 <test7>:
|
||||
800001b4: 00d52023 sw a3,0(a0)
|
||||
800001b8: 100527af lr.w a5,(a0)
|
||||
800001bc: 18b5262f sc.w a2,a1,(a0)
|
||||
800001c0: 12d79463 bne a5,a3,800002e8 <fail>
|
||||
800001c4: 12061263 bnez a2,800002e8 <fail>
|
||||
800001c8: 00052703 lw a4,0(a0)
|
||||
800001cc: 10e59e63 bne a1,a4,800002e8 <fail>
|
||||
800001d0: fffe8e93 addi t4,t4,-1
|
||||
800001d4: 00450513 addi a0,a0,4
|
||||
800001d8: 00358593 addi a1,a1,3
|
||||
800001dc: 00360613 addi a2,a2,3
|
||||
800001e0: 00368693 addi a3,a3,3
|
||||
800001e4: fc0e98e3 bnez t4,800001b4 <test7>
|
||||
800001e8: 00900e13 li t3,9
|
||||
800001ec: 10000537 lui a0,0x10000
|
||||
800001f0: 10050513 addi a0,a0,256 # 10000100 <trap_entry-0x6fffff20>
|
||||
800001f4: 07b00593 li a1,123
|
||||
800001f8: 07c00613 li a2,124
|
||||
800001fc: 07d00693 li a3,125
|
||||
80000200: 00d52023 sw a3,0(a0)
|
||||
80000204: 100527af lr.w a5,(a0)
|
||||
80000208: 00000073 ecall
|
||||
8000020c: 18b5262f sc.w a2,a1,(a0)
|
||||
80000210: 00100713 li a4,1
|
||||
80000214: 0ce61a63 bne a2,a4,800002e8 <fail>
|
||||
80000218: 00052703 lw a4,0(a0)
|
||||
8000021c: 0ce69663 bne a3,a4,800002e8 <fail>
|
||||
80000220: 00b00e13 li t3,11
|
||||
80000224: 10000537 lui a0,0x10000
|
||||
80000228: 30050513 addi a0,a0,768 # 10000300 <trap_entry-0x6ffffd20>
|
||||
8000022c: 08200593 li a1,130
|
||||
80000230: 08300613 li a2,131
|
||||
80000234: 08400693 li a3,132
|
||||
80000238: 00d52023 sw a3,0(a0)
|
||||
8000023c: 00001eb7 lui t4,0x1
|
||||
80000240: 800e8e93 addi t4,t4,-2048 # 800 <trap_entry-0x7ffff820>
|
||||
80000244: 304e9073 csrw mie,t4
|
||||
80000248: 00800e93 li t4,8
|
||||
8000024c: 100527af lr.w a5,(a0)
|
||||
80000250: 300e9073 csrw mstatus,t4
|
||||
80000254: 00000013 nop
|
||||
80000258: 00000013 nop
|
||||
8000025c: 00000013 nop
|
||||
80000260: 00000013 nop
|
||||
80000264: 00000013 nop
|
||||
80000268: 00000013 nop
|
||||
8000026c: 18b5262f sc.w a2,a1,(a0)
|
||||
80000270: 00100713 li a4,1
|
||||
80000274: 06e61a63 bne a2,a4,800002e8 <fail>
|
||||
80000278: 00052703 lw a4,0(a0)
|
||||
8000027c: 06e69663 bne a3,a4,800002e8 <fail>
|
||||
80000280: 00c00e13 li t3,12
|
||||
80000284: 10000537 lui a0,0x10000
|
||||
80000288: 40050513 addi a0,a0,1024 # 10000400 <trap_entry-0x6ffffc20>
|
||||
8000028c: 08c00593 li a1,140
|
||||
80000290: 08d00613 li a2,141
|
||||
80000294: 08e00693 li a3,142
|
||||
80000298: 00d52023 sw a3,0(a0)
|
||||
8000029c: 00001eb7 lui t4,0x1
|
||||
800002a0: 800e8e93 addi t4,t4,-2048 # 800 <trap_entry-0x7ffff820>
|
||||
800002a4: 304e9073 csrw mie,t4
|
||||
800002a8: 00002eb7 lui t4,0x2
|
||||
800002ac: 808e8e93 addi t4,t4,-2040 # 1808 <trap_entry-0x7fffe818>
|
||||
800002b0: 100527af lr.w a5,(a0)
|
||||
800002b4: 300e9073 csrw mstatus,t4
|
||||
800002b8: 00000013 nop
|
||||
800002bc: 00000013 nop
|
||||
800002c0: 00000013 nop
|
||||
800002c4: 00000013 nop
|
||||
800002c8: 00000013 nop
|
||||
800002cc: 00000013 nop
|
||||
800002d0: 18b5262f sc.w a2,a1,(a0)
|
||||
800002d4: 00100713 li a4,1
|
||||
800002d8: 00e61863 bne a2,a4,800002e8 <fail>
|
||||
800002dc: 00052703 lw a4,0(a0)
|
||||
800002e0: 00e69463 bne a3,a4,800002e8 <fail>
|
||||
800002e4: 0100006f j 800002f4 <pass>
|
||||
|
||||
800002e8 <fail>:
|
||||
800002e8: f0100137 lui sp,0xf0100
|
||||
800002ec: f2410113 addi sp,sp,-220 # f00fff24 <pass+0x700ffc30>
|
||||
800002f0: 01c12023 sw t3,0(sp)
|
||||
|
||||
800002f4 <pass>:
|
||||
800002f4: f0100137 lui sp,0xf0100
|
||||
800002f8: f2010113 addi sp,sp,-224 # f00fff20 <pass+0x700ffc2c>
|
||||
800002fc: 00012023 sw zero,0(sp)
|
||||
80000300: 00000013 nop
|
||||
80000304: 00000013 nop
|
||||
80000308: 00000013 nop
|
||||
8000030c: 00000013 nop
|
||||
80000310: 00000013 nop
|
||||
80000314: 00000013 nop
|
53
src/test/cpp/raw/lrsc/build/lrsc.hex
Normal file
53
src/test/cpp/raw/lrsc/build/lrsc.hex
Normal file
|
@ -0,0 +1,53 @@
|
|||
:0200000480007A
|
||||
:100000006F00C00413000000130000001300000084
|
||||
:100010001300000013000000130000001300000094
|
||||
:10002000F32E003093FE0E08638A0E00B72E0000F8
|
||||
:10003000938E0E8073900E3073002030F32E1034A8
|
||||
:10004000938E4E0073901E3473002030130E1000F8
|
||||
:100050003705001093054006130650069306600608
|
||||
:100060002320D5002F26B51813071000631EE6269F
|
||||
:1000700003270500639AE626130E200037050010BB
|
||||
:100080001305450093057006130680069306900637
|
||||
:100090002320D5002F26B518130710006316E62479
|
||||
:1000A000032705006392E624130E30003705001085
|
||||
:1000B0001305450093057006130680069306900607
|
||||
:1000C0002F26B518130710006310E622032705003A
|
||||
:1000D000639CE620130E40003705001013058500D1
|
||||
:1000E0009305A0061306B0069306C0062320D5008C
|
||||
:1000F000AF2705102F26B5186398D71E6316061E66
|
||||
:10010000032705006392E51E130E5000370500100B
|
||||
:10011000130585009305D0061306E0069306F00646
|
||||
:100120002320D5002F26B5186310061C03270500D1
|
||||
:10013000639CE51A130E6000370500101305C50017
|
||||
:1001400093050007130610079306200737040010D5
|
||||
:10015000130404019304300713094007930950075F
|
||||
:100160002320D50023203401AF270510AF2A041027
|
||||
:100170002F26B5182F2994186398D71663160616DC
|
||||
:10018000032705006392E51663903A17631E09146E
|
||||
:10019000032A0400639A4415130E700037050010FB
|
||||
:1001A0001305450193058007130690079306A007E2
|
||||
:1001B000930E00012320D500AF2705102F26B51878
|
||||
:1001C0006394D7126312061203270500639EE5109D
|
||||
:1001D000938EFEFF13054500938535001306360008
|
||||
:1001E00093863600E3980EFC130E9000370500103E
|
||||
:1001F000130505109305B0071306C0079306D00733
|
||||
:100200002320D500AF270510730000002F26B51856
|
||||
:1002100013071000631AE60C032705006396E60C2B
|
||||
:10022000130EB000370500101305053093052008A4
|
||||
:1002300013063008930640082320D500B71E00009F
|
||||
:10024000938E0E8073904E30930E8000AF27051072
|
||||
:1002500073900E3013000000130000001300000024
|
||||
:100260001300000013000000130000002F26B51833
|
||||
:1002700013071000631AE606032705006396E606D7
|
||||
:10028000130EC00037050010130505409305C00884
|
||||
:100290001306D0089306E0082320D500B71E0000FF
|
||||
:1002A000938E0E8073904E30B72E0000938E8E800A
|
||||
:1002B000AF27051073900E301300000013000000EC
|
||||
:1002C00013000000130000001300000013000000E2
|
||||
:1002D0002F26B518130710006318E6000327050042
|
||||
:1002E0006394E6006F000001370110F0130141F242
|
||||
:1002F0002320C101370110F0130101F22320010076
|
||||
:1003000013000000130000001300000013000000A1
|
||||
:080310001300000013000000BF
|
||||
:040000058000004C2B
|
||||
:00000001FF
|
5
src/test/cpp/raw/lrsc/makefile
Normal file
5
src/test/cpp/raw/lrsc/makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
PROJ_NAME=lrsc
|
||||
|
||||
ATOMIC=yes
|
||||
|
||||
include ../common/asm.mk
|
265
src/test/cpp/raw/lrsc/src/crt.S
Normal file
265
src/test/cpp/raw/lrsc/src/crt.S
Normal file
|
@ -0,0 +1,265 @@
|
|||
.globl _start
|
||||
|
||||
|
||||
j _start
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
csrr x29, mstatus
|
||||
and x29, x29, 0x080
|
||||
beqz x29, notExternalInterrupt
|
||||
li x29, 0x1800 //000 disable interrupts
|
||||
csrw mstatus,x29
|
||||
mret
|
||||
|
||||
notExternalInterrupt:
|
||||
csrr x29, mepc
|
||||
addi x29, x29, 4
|
||||
csrw mepc, x29
|
||||
mret
|
||||
|
||||
_start:
|
||||
//Test 1 SC on unreserved area should fail and not write memory
|
||||
li x28, 1
|
||||
li a0, 0x10000000
|
||||
li a1, 100
|
||||
li a2, 101
|
||||
li a3, 102
|
||||
sw a3, 0(a0)
|
||||
sc.w a2, a1, (a0)
|
||||
li a4, 1
|
||||
bne a2, a4, fail
|
||||
lw a4, 0(a0)
|
||||
bne a3, a4, fail
|
||||
|
||||
//Test 2 SC on another unreserved area should fail and not write memory
|
||||
li x28, 2
|
||||
li a0, 0x10000004
|
||||
li a1, 103
|
||||
li a2, 104
|
||||
li a3, 105
|
||||
sw a3, 0(a0)
|
||||
sc.w a2, a1, (a0)
|
||||
li a4, 1
|
||||
bne a2, a4, fail
|
||||
lw a4, 0(a0)
|
||||
bne a3, a4, fail
|
||||
|
||||
|
||||
//Test 3 retrying SC on unreserved area should fail and not write memory
|
||||
li x28, 3
|
||||
li a0, 0x10000004
|
||||
li a1, 103
|
||||
li a2, 104
|
||||
li a3, 105
|
||||
sc.w a2, a1, (a0)
|
||||
li a4, 1
|
||||
bne a2, a4, fail
|
||||
lw a4, 0(a0)
|
||||
bne a3, a4, fail
|
||||
|
||||
|
||||
//Test 4 SC on reserved area should pass and should be written write memory
|
||||
li x28, 4
|
||||
li a0, 0x10000008
|
||||
li a1, 106
|
||||
li a2, 107
|
||||
li a3, 108
|
||||
sw a3, 0(a0)
|
||||
lr.w a5, (a0)
|
||||
sc.w a2, a1, (a0)
|
||||
bne a5, a3, fail
|
||||
bne a2, x0, fail
|
||||
lw a4, 0(a0)
|
||||
bne a1, a4, fail
|
||||
|
||||
|
||||
//Test 5 redo SC on reserved area should pass and should be written write memory
|
||||
li x28, 5
|
||||
li a0, 0x10000008
|
||||
li a1, 109
|
||||
li a2, 110
|
||||
li a3, 111
|
||||
sw a3, 0(a0)
|
||||
sc.w a2, a1, (a0)
|
||||
bne a2, x0, fail
|
||||
lw a4, 0(a0)
|
||||
bne a1, a4, fail
|
||||
|
||||
//Test 6 Allow two entries at the same time
|
||||
li x28, 6
|
||||
li a0, 0x1000000C
|
||||
li a1, 112
|
||||
li a2, 113
|
||||
li a3, 114
|
||||
li s0, 0x10000010
|
||||
li s1, 115
|
||||
li s2, 116
|
||||
li s3, 117
|
||||
|
||||
sw a3, 0(a0)
|
||||
sw s3, 0(s0)
|
||||
lr.w a5, (a0)
|
||||
lr.w s5, (s0)
|
||||
sc.w a2, a1, (a0)
|
||||
sc.w s2, s1, (s0)
|
||||
bne a5, a3, fail
|
||||
bne a2, x0, fail
|
||||
lw a4, 0(a0)
|
||||
bne a1, a4, fail
|
||||
|
||||
bne s5, s3, fail
|
||||
bne s2, x0, fail
|
||||
lw s4, 0(s0)
|
||||
bne s1, s4, fail
|
||||
|
||||
//Test 7 do a lot of allocation to clear the entries
|
||||
li x28, 7
|
||||
li a0, 0x10000014
|
||||
li a1, 120
|
||||
li a2, 121
|
||||
li a3, 122
|
||||
li x29, 16
|
||||
test7:
|
||||
sw a3, 0(a0)
|
||||
lr.w a5, (a0)
|
||||
sc.w a2, a1, (a0)
|
||||
bne a5, a3, fail
|
||||
bne a2, x0, fail
|
||||
lw a4, 0(a0)
|
||||
bne a1, a4, fail
|
||||
add x29, x29, -1
|
||||
add a0, a0, 4
|
||||
add a1, a1, 3
|
||||
add a2, a2, 3
|
||||
add a3, a3, 3
|
||||
bnez x29, test7
|
||||
|
||||
|
||||
//Test 8 SC on discarded entries should fail
|
||||
/* li x28, 8
|
||||
li a0, 0x10000018
|
||||
li a1, 120
|
||||
li a2, 121
|
||||
li a3, 122
|
||||
lw a5, 0(a0)
|
||||
sc.w a2, a1, (a0)
|
||||
li a4, 1
|
||||
bne a2, a4, fail
|
||||
lw a4, 0(a0)
|
||||
bne a5, a4, fail*/
|
||||
|
||||
|
||||
//Test 9 SC should fail after a context switching
|
||||
li x28, 9
|
||||
li a0, 0x10000100
|
||||
li a1, 123
|
||||
li a2, 124
|
||||
li a3, 125
|
||||
sw a3, 0(a0)
|
||||
lr.w a5, (a0)
|
||||
scall
|
||||
sc.w a2, a1, (a0)
|
||||
li a4, 1
|
||||
bne a2, a4, fail
|
||||
lw a4, 0(a0)
|
||||
bne a3, a4, fail
|
||||
|
||||
|
||||
|
||||
//Test 10 SC should fail if the address doesn't match
|
||||
/* li x28, 10
|
||||
li a0, 0x10000200
|
||||
li a6, 0x10000204
|
||||
li a1, 126
|
||||
li a2, 127
|
||||
li a3, 128
|
||||
li a7, 129
|
||||
sw a3, 0(a0)
|
||||
sw a7, 0(a6)
|
||||
lr.w a5, (a6)
|
||||
sc.w a2, a1, (a0)
|
||||
li a4, 1
|
||||
bne a2, a4, fail
|
||||
lw a4, 0(a6)
|
||||
bne a7, a4, fail*/
|
||||
|
||||
|
||||
|
||||
//Test 11 SC should fail after a external interrupt context switching
|
||||
li x28, 11
|
||||
li a0, 0x10000300
|
||||
li a1, 130
|
||||
li a2, 131
|
||||
li a3, 132
|
||||
sw a3, 0(a0)
|
||||
li x29, 0x800 //800 external interrupts
|
||||
csrw mie,x29
|
||||
li x29, 0x008 //008 enable interrupts
|
||||
lr.w a5, (a0)
|
||||
csrw mstatus,x29 //Enable external interrupt (will jump instantly due to testbench setup)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
sc.w a2, a1, (a0)
|
||||
li a4, 1
|
||||
bne a2, a4, fail
|
||||
lw a4, 0(a0)
|
||||
bne a3, a4, fail
|
||||
|
||||
|
||||
//Test 12 SC should fail after a external interrupt context switching (callback on lr)
|
||||
li x28, 12
|
||||
li a0, 0x10000400
|
||||
li a1, 140
|
||||
li a2, 141
|
||||
li a3, 142
|
||||
sw a3, 0(a0)
|
||||
li x29, 0x800 //800 external interrupts
|
||||
csrw mie,x29
|
||||
li x29, 0x1808 //008 enable interrupts
|
||||
lr.w a5, (a0)
|
||||
csrw mstatus,x29 //Enable external interrupt (will jump instantly due to testbench setup)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
sc.w a2, a1, (a0)
|
||||
li a4, 1
|
||||
bne a2, a4, fail
|
||||
lw a4, 0(a0)
|
||||
bne a3, a4, fail
|
||||
|
||||
|
||||
|
||||
j pass
|
||||
|
||||
|
||||
fail: //x28 => error code
|
||||
li x2, 0xF00FFF24
|
||||
sw x28, 0(x2)
|
||||
|
||||
pass:
|
||||
li x2, 0xF00FFF20
|
||||
sw x0, 0(x2)
|
||||
|
||||
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue