GithubHelp home page GithubHelp logo

spinalhdl / vexriscv Goto Github PK

View Code? Open in Web Editor NEW
2.3K 98.0 380.0 12.98 MB

A FPGA friendly 32 bit RISC-V CPU implementation

License: MIT License

Scala 26.91% C++ 4.69% Makefile 0.87% Assembly 62.02% Verilog 0.26% Python 0.13% Shell 0.08% C 3.82% Tcl 1.21% Java 0.01%
riscv soc cpu spinalhdl vhdl verilog fpga softcore

vexriscv's Introduction

Index

Description

This repository hosts a RISC-V implementation written in SpinalHDL. Here are some specs :

  • RV32I[M][A][F[D]][C] instruction set
  • 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, does not use any vendor specific IP block / primitive
  • AXI4, Avalon, wishbone ready
  • Optional MUL/DIV extensions
  • Optional F32/F64 FPU (require data cache for now)
  • Optional instruction and data caches
  • Optional hardware refilled MMU
  • Optional debug extension allowing Eclipse debugging via a GDB >> openOCD >> JTAG connection
  • Optional interrupts and exception handling with Machine, [Supervisor] and [User] modes as defined in the RISC-V Privileged ISA Specification v1.10.
  • Two implementations of shift instructions: single cycle (full barrel shifter) and shiftNumber cycles
  • Each stage can have optional bypass or interlock hazard logic
  • Linux compatible (SoC : https://github.com/enjoy-digital/linux-on-litex-vexriscv)
  • Zephyr compatible
  • FreeRTOS port
  • Support tightly coupled memory on I$ D$ (see GenFullWithTcm / GenFullWithTcmIntegrated)

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:

  • There are very few fixed things. Nearly everything is plugin based. The PC manager is a plugin, the register file is a plugin, the hazard controller is a plugin, ...
  • There is an automatic a tool which allows plugins to insert data in the pipeline at a given stage, and allows other plugins to read it in another stage through automatic pipelining.
  • There is a service system which provides a very dynamic framework. For instance, a plugin could provide an exception service which can then be used by other plugins to emit exceptions from the pipeline.

There is a gitter channel for all questions about VexRiscv :
Gitter

For commercial support, please contact [email protected].

Area usage and maximal frequency

The following numbers were obtained by synthesizing the CPU as toplevel on the fastest speed grade without any specific synthesis options to save area or to get better maximal frequency (neutral).
The clock constraint is set to an unattainable value, which tends to increase the design area.
The dhrystone benchmark was compiled with the -O3 -fno-inline option.
All the cached configurations have some cache trashing during the dhrystone benchmark except the VexRiscv full max perf one. This, of course, reduces the performance. It is possible to produce dhrystone binaries which fit inside a 4KB I$ and 4KB D$ (I already had this case once) but currently it isn't the case.
The CPU configurations used below can be found in the src/scala/vexriscv/demo directory.

VexRiscv small (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) ->
    Artix 7     -> 243 Mhz 504 LUT 505 FF 
    Cyclone V   -> 174 Mhz 352 ALMs
    Cyclone IV  -> 179 Mhz 731 LUT 494 FF 
    iCE40       -> 92 Mhz 1130 LC

VexRiscv small (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) ->
    Artix 7     -> 240 Mhz 556 LUT 566 FF 
    Cyclone V   -> 194 Mhz 394 ALMs
    Cyclone IV  -> 174 Mhz 831 LUT 555 FF 
    iCE40       -> 85 Mhz 1292 LC

VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz)  ->
    Artix 7     -> 232 Mhz 816 LUT 534 FF 
    Cyclone V   -> 155 Mhz 492 ALMs
    Cyclone IV  -> 155 Mhz 1,111 LUT 530 FF 
    iCE40       -> 63 Mhz 1596 LC

VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$)  ->
    Artix 7     -> 220 Mhz 730 LUT 570 FF 
    Cyclone V   -> 142 Mhz 501 ALMs
    Cyclone IV  -> 150 Mhz 1,139 LUT 536 FF 
    iCE40       -> 66 Mhz 1680 LC

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     -> 216 Mhz 1418 LUT 949 FF 
    Cyclone V   -> 133 Mhz 933 ALMs
    Cyclone IV  -> 143 Mhz 2,076 LUT 972 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     -> 199 Mhz 1840 LUT 1158 FF 
    Cyclone V   -> 141 Mhz 1,166 ALMs
    Cyclone IV  -> 131 Mhz 2,407 LUT 1,067 FF 

VexRiscv full max perf (HZ*IPC) -> (RV32IM, 1.38 DMIPS/Mhz 2.57 Coremark/Mhz, 8KB-I$,8KB-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     -> 200 Mhz 1935 LUT 1216 FF 
    Cyclone V   -> 130 Mhz 1,166 ALMs
    Cyclone IV  -> 126 Mhz 2,484 LUT 1,120 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     -> 151 Mhz 2021 LUT 1541 FF 
    Cyclone V   -> 124 Mhz 1,368 ALMs
    Cyclone IV -> 128 Mhz 2,826 LUT 1,474 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     -> 180 Mhz 2883 LUT 2130 FF 
    Cyclone V   -> 131 Mhz 1,764 ALMs
    Cyclone IV  -> 121 Mhz 3,608 LUT 2,082 FF 

The following configuration results in 1.44 DMIPS/MHz:

  • 5 stage: F -> D -> E -> M -> WB
  • single cycle ADD/SUB/Bitwise/Shift ALU
  • branch/jump done in the E stage
  • memory load values are bypassed in the WB stage (late result)
  • 33 cycle division with bypassing in the M stage (late result)
  • single cycle multiplication with bypassing in the WB stage (late result)
  • dynamic branch prediction done in the F stage with a direct mapped target buffer cache (no penalties on correct predictions)

Note that, recently, the capability to remove the Fetch/Memory/WriteBack stage was added to reduce the area of the CPU, which ends up with a smaller CPU and a better DMIPS/Mhz for the small configurations.

Dependencies

On Ubuntu 14:

# JAVA JDK 8
sudo add-apt-repository -y ppa:openjdk-r/ppa
sudo apt-get update
sudo apt-get install openjdk-8-jdk -y
sudo update-alternatives --config java
sudo update-alternatives --config javac

# Install SBT - https://www.scala-sbt.org/
echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list
echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list
curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add
sudo apt-get update
sudo apt-get install sbt

# Verilator (for sim only, really needs 3.9+, in general apt-get will give you 3.8)
sudo apt-get install git make autoconf g++ flex bison
git clone http://git.veripool.org/git/verilator   # Only first time
unsetenv VERILATOR_ROOT  # For csh; ignore error if on bash
unset VERILATOR_ROOT  # For bash
cd verilator
git pull        # Make sure we're up-to-date
git checkout v4.216
autoconf        # Create ./configure script
./configure
make
sudo make install

CPU generation

We now have twenty-two CPU configurations in this directory. Look at the files called Gen*.scala. Here is the full configuration, and the smallest configuration.

To generate the corresponding RTL as a VexRiscv.v file, run the following commands in the root directory of this repository:

sbt "runMain vexriscv.demo.GenFull"

or

sbt "runMain vexriscv.demo.GenSmallest"

NOTES:

  • It could take time the first time you run it.
  • The VexRiscv project may need an unreleased master-head of the SpinalHDL repo. If it fails to compile, just get the SpinalHDL repository and do a "sbt clean compile publishLocal" in it as described in the dependencies chapter.

Regression tests

Build Status

To run tests (need java, scala, verilator), just do :

export VEXRISCV_REGRESSION_SEED=42
export VEXRISCV_REGRESSION_TEST_ID=
sbt "testOnly vexriscv.TestIndividualFeatures"

This will generate random VexRiscv configuration and test them with:

You can rerun some specific test by setting VEXRISCV_REGRESSION_TEST_ID by their id. For instance, if you want to rerun :

  • test_id_5_test_IBus_CachedS1024W1BPL32Relaxvexriscv.plugin.DYNAMIC_DBus_CachedS8192W2BPL16_MulDiv_MulDivFpga_Shift_FullLate_Branch_Late_Hazard_BypassAll_RegFile_SyncDR_Src__Csr_AllNoException_Decoder__Debug_None_DBus_NoMmu
  • test_id_9_test_IBus_Simple1S2InjStagevexriscv.plugin.STATIC_DBus_SimpleLate_MulDiv_MulDivFpgaSimple_Shift_FullEarly_Branch_Late_Hazard_Interlock_RegFile_AsyncER_Src_AddSubExecute_Csr_None_Decoder__Debug_None_DBus_NoMmu

then :

export VEXRISCV_REGRESSION_TEST_ID=5,9

Also there is a few environnement variable that you can use to modulate the random generation :

Parameters range description
VEXRISCV_REGRESSION_SEED Int Seed used to generate the random configurations
VEXRISCV_REGRESSION_TEST_ID [Int[,\Int]*] Random configuration that should be keeped and tested
VEXRISCV_REGRESSION_CONFIG_COUNT Int Number of random configurations
VEXRISCV_REGRESSION_CONFIG_RVC_RATE 0.0-1.0 Chance to generate a RVC config
VEXRISCV_REGRESSION_CONFIG_LINUX_RATE 0.0-1.0 Chance to generate a linux ready config
VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE 0.0-1.0 Chance to generate a machine mode OS ready config
VEXRISCV_REGRESSION_LINUX_REGRESSION yes/no Enable the linux test
VEXRISCV_REGRESSION_COREMARK yes/no Enable the Coremark test
VEXRISCV_REGRESSION_ZEPHYR_COUNT Int Number of zephyr tests to run on capable configs
VEXRISCV_REGRESSION_CONFIG_DEMW_RATE 0.0-1.0 Chance to generate a config with writeback stage
VEXRISCV_REGRESSION_CONFIG_DEM_RATE 0.0-1.0 Chance to generate a config with memory stage

Basic Verilator simulation

To run basic simulation with stdout and no tracing, loading a binary directly is supported with the RUN_HEX variable of src/test/cpp/regression/makefile. This has a significant performance advantage over using GDB over OpenOCD with JTAG over TCP. VCD tracing is supported with the makefile variable TRACE.

Interactive debug of the simulated CPU via GDB OpenOCD and Verilator

To use this, you just need to use the same command as with running tests, but adding DEBUG_PLUGIN_EXTERNAL=yes in the make arguments. This works for the GenFull configuration, but not for GenSmallest, as this configuration has no debug module.

Then, you can use the OpenOCD RISC-V tool to create a GDB server connected to the target (the simulated CPU), as follows:

#In the VexRiscv repository, to run the simulation on which one OpenOCD can connect itself =>
sbt "runMain vexriscv.demo.GenFull"
cd src/test/cpp/regression
make run DEBUG_PLUGIN_EXTERNAL=yes

#In the openocd git, after building it =>
src/openocd -c "set VEXRISCV_YAML PATH_TO_THE_GENERATED_CPU0_YAML_FILE" -f tcl/target/vexriscv_sim.cfg

#Run a GDB session with an elf RISCV executable (GenFull CPU)
YourRiscvToolsPath/bin/riscv32-unknown-elf-gdb VexRiscvRepo/src/test/resources/elf/uart.elf
target remote localhost:3333
monitor reset halt
load
continue

# Now it should print messages in the Verilator simulation of the CPU

Using Eclipse to run and debug the software

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 contains the makefile, then select "Cross GCC" (not "RISC-V Cross GCC")

To create a new debug configuration:

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.

wget http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/helios/SR2/eclipse-cpp-helios-SR2-linux-gtk-x86_64.tar.gz
tar -xvzf download.php?file=%2Ftechnology%2Fepp%2Fdownloads%2Frelease%2Fhelios%2FSR2%2Feclipse-cpp-helios-SR2-linux-gtk-x86_64.tar.gz
cd eclipse
./eclipse -application org.eclipse.equinox.p2.director -repository http://opensource.zylin.com/zylincdt -installIU com.zylin.cdt.feature.feature.group/

See https://drive.google.com/drive/folders/1NseNHH05B6lmIXqQFVwK8xRjWE4ydeG-?usp=sharing to import a makefile project and create a debug configuration.

Note that sometimes Eclipse needs to be restarted in order to be able to place new breakpoints.

If you want to get more information about how all this JTAG / GDB stuff work, you can find great blog about it here :

https://tomverbeure.github.io/2021/07/18/VexRiscv-OpenOCD-and-Traps.html

Briey SoC

As a demonstration, a SoC named Briey is implemented in src/main/scala/vexriscv/demo/Briey.scala. This SoC is very similar to the Pinsec SoC:

Briey SoC

To generate the Briey SoC Hardware:

sbt "runMain vexriscv.demo.Briey"

To run the verilator simulation of the Briey SoC, which can then be connected to OpenOCD/GDB, first get these dependencies:

sudo apt-get install build-essential xorg-dev libudev-dev libgl1-mesa-dev libglu1-mesa-dev libasound2-dev libpulse-dev libopenal-dev libogg-dev libvorbis-dev libaudiofile-dev libpng12-dev libfreetype6-dev libusb-dev libdbus-1-dev zlib1g-dev libdirectfb-dev libsdl2-dev

Then go in src/test/cpp/briey and run the simulation with (UART TX is printed in the terminal, VGA is displayed in a GUI):

make clean run

To connect OpenOCD (https://github.com/SpinalHDL/openocd_riscv) to the simulation :

src/openocd -f tcl/interface/jtag_tcp.cfg -c "set BRIEY_CPU0_YAML /home/spinalvm/Spinal/VexRiscv/cpu0.yaml" -f tcl/target/briey.cfg

To connect OpenOCD to Altera FPGAs (Intel VJTAG) see here: https://github.com/SpinalHDL/VexRiscv/tree/master/doc/vjtag

You can find multiple software examples and demos here: https://github.com/SpinalHDL/VexRiscvSocSoftware/tree/master/projects/briey

You can find some FPGA projects which instantiate the Briey SoC here (DE1-SoC, DE0-Nano): https://drive.google.com/drive/folders/0B-CqLXDTaMbKZGdJZlZ5THAxRTQ?usp=sharing

Here are some measurements of Briey SoC timings and area:

Artix 7     -> 181 Mhz 3220 LUT 3181 FF 
Cyclone V   -> 142 Mhz 2,222 ALMs
Cyclone IV  -> 130 Mhz 4,538 LUT 3,211 FF 

Murax SoC

Murax is a very light SoC (it fits in an ICE40 FPGA) which can work without any external components:

  • VexRiscv RV32I[M]
  • JTAG debugger (Eclipse/GDB/openocd ready)
  • 8 kB of on-chip ram
  • Interrupt support
  • APB bus for peripherals
  • 32 GPIO pin
  • one 16 bits prescaler, two 16 bits timers
  • one UART with tx/rx fifo

Depending on the CPU configuration, on the ICE40-hx8k FPGA with icestorm for synthesis, the full SoC has the following area/performance:

  • RV32I interlocked stages => 51 Mhz, 2387 LC 0.45 DMIPS/Mhz
  • RV32I bypassed stages => 45 Mhz, 2718 LC 0.65 DMIPS/Mhz

Its implementation can be found here: src/main/scala/vexriscv/demo/Murax.scala.

To generate the Murax SoC Hardware:

# To generate the SoC without any content in the ram
sbt "runMain vexriscv.demo.Murax"

# To generate the SoC with a demo program already in ram
sbt "runMain vexriscv.demo.MuraxWithRamInit"

The demo program included by default with MuraxWithRamInit will blink the LEDs and echo characters received on the UART back to the user. To see this when running the Verilator sim, type some text and press enter.

Then go in src/test/cpp/murax and run the simulation with:

make clean run

To connect OpenOCD (https://github.com/SpinalHDL/openocd_riscv) to the simulation:

src/openocd -f tcl/interface/jtag_tcp.cfg -c "set MURAX_CPU0_YAML /home/spinalvm/Spinal/VexRiscv/cpu0.yaml" -f tcl/target/murax.cfg

You can find multiple software examples and demos here: https://github.com/SpinalHDL/VexRiscvSocSoftware/tree/master/projects/murax

Here are some timing and area measurements of the Murax SoC:

Murax interlocked stages (0.45 DMIPS/Mhz, 8 bits GPIO) ->
    Artix 7     -> 216 Mhz 1109 LUT 1201 FF 
    Cyclone V   -> 182 Mhz 725 ALMs
    Cyclone IV  -> 147 Mhz 1,551 LUT 1,223 FF 
    iCE40       ->  64 Mhz 2422 LC (nextpnr)

MuraxFast bypassed stages (0.65 DMIPS/Mhz, 8 bits GPIO) ->
    Artix 7     -> 224 Mhz 1278 LUT 1300 FF 
    Cyclone V   -> 173 Mhz 867 ALMs
    Cyclone IV  -> 143 Mhz 1,755 LUT 1,258 FF 
    iCE40       ->  66 Mhz 2799 LC (nextpnr)

Some scripts to generate the SoC and call the icestorm toolchain can be found here: scripts/Murax/

A top level simulation testbench with the same features + a GUI are implemented with SpinalSim. You can find it in src/test/scala/vexriscv/MuraxSim.scala.

To run it :

# This will generate the Murax RTL + run its testbench. You need Verilator 3.9xx installated.
sbt "test:runMain vexriscv.MuraxSim"

Build all above with mill

Mill is a simple tool to build Scala/Java, also fits in off-line environment very well.

Github url is here: https://github.com/com-lihaoyi/mill

Document is here: https://mill-build.com/mill/Intro_to_Mill.html

Download executable mill:

curl --fail -L -o mill https://github.com/com-lihaoyi/mill/releases/download/0.11.6/0.11.6-assembly
chmod +x mill

Using mill to generate the corresponding RTL as a VexRiscv.v file, run the following commands in the root directory of this repository:

./mill VexRiscv.runMain vexriscv.demo.GenFull

or

./mill VexRiscv.runMain vexriscv.demo.GenSmallest

Using mill to run tests (need java, scala, verilator), do :

export VEXRISCV_REGRESSION_SEED=42
export VEXRISCV_REGRESSION_TEST_ID=
./mill VexRiscv.test.testOnly vexriscv.TestIndividualFeatures

Using mill to generate the Briey SoC Hardware:

./mill VexRiscv.runMain vexriscv.demo.Briey

Using mill to generate the Murax SoC Hardware:

# To generate the SoC without any content in the ram
./mill VexRiscv.runMain vexriscv.demo.Murax

# To generate the SoC with a demo program already in ram
./mill VexRiscv.runMain vexriscv.demo.MuraxWithRamInit

# This will generate the Murax RTL + run its testbench. You need Verilator 3.9xx installated.
./mill VexRiscv.test.runMain vexriscv.MuraxSim

Mill's IDE supports:

# Build Server Protocol (BSP)
./mill mill.bsp.BSP/install

# IntelliJ IDEA Support
./mill mill.idea.GenIdea/idea

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 applications (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:

The VexRiscvSocSoftware makefiles are expecting to find this prebuild version in /opt/riscv/contentOfThisPreBuild

version=riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14
wget -O riscv64-unknown-elf-gcc.tar.gz riscv https://static.dev.sifive.com/dev-tools/$version.tar.gz
tar -xzvf riscv64-unknown-elf-gcc.tar.gz
sudo mv $version /opt/riscv
echo 'export PATH=/opt/riscv/bin:$PATH' >> ~/.bashrc

If you want to compile the rv32i and rv32im GCC toolchain from source code and install them in /opt/, do the following (will take one hour):

# Be carefull, sometime the git clone has issue to successfully clone riscv-gnu-toolchain.
sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev -y

git clone --recursive https://github.com/riscv/riscv-gnu-toolchain riscv-gnu-toolchain
cd riscv-gnu-toolchain

echo "Starting RISC-V Toolchain build process"

ARCH=rv32im
rmdir -rf $ARCH
mkdir $ARCH; cd $ARCH
../configure  --prefix=/opt/$ARCH --with-arch=$ARCH --with-abi=ilp32
sudo make -j4
cd ..


ARCH=rv32i
rmdir -rf $ARCH
mkdir $ARCH; cd $ARCH
../configure  --prefix=/opt/$ARCH --with-arch=$ARCH --with-abi=ilp32
sudo make -j4
cd ..

echo -e "\\nRISC-V Toolchain installation completed!"

CPU parametrization and instantiation example

You can find many examples of different configurations in the https://github.com/SpinalHDL/VexRiscv/tree/master/src/main/scala/vexriscv/demo folder.

Here is one such example:

import vexriscv._
import vexriscv.plugin._

//Instanciate one VexRiscv
val cpu = new VexRiscv(
  //Provide a configuration instance
  config = VexRiscvConfig(
    //Provide a list of plugins which will futher add their logic into the CPU
    plugins = List(
      new IBusSimplePlugin(
        resetVector = 0x00000000l,
        cmdForkOnSecondStage = true,
        cmdForkPersistence  = true
      ),
      new DBusSimplePlugin(
        catchAddressMisaligned = false,
        catchAccessFault = false
      ),
      new DecoderSimplePlugin(
        catchIllegalInstruction = false
      ),
      new RegFilePlugin(
        regFileReadyKind = Plugin.SYNC,
        zeroBoot = true
      ),
      new IntAluPlugin,
      new SrcPlugin(
        separatedAddSub = false,
        executeInsertion = false
      ),
      new LightShifterPlugin,
      new HazardSimplePlugin(
        bypassExecute           = false,
        bypassMemory            = false,
        bypassWriteBack         = false,
        bypassWriteBackBuffer   = false
      ),
      new BranchPlugin(
        earlyBranch = false,
        catchAddressMisaligned = false
      ),
      new YamlPlugin("cpu0.yaml")
    )
  )
)

Add a custom instruction to the CPU via the plugin system

Here is an example of a simple plugin which adds a simple SIMD_ADD instruction:

import spinal.core._
import vexriscv.plugin.Plugin
import vexriscv.{Stageable, DecoderService, VexRiscv}

//This plugin example will add a new instruction named SIMD_ADD which does the following:
//
//RD : Regfile Destination, RS : Regfile Source
//RD( 7 downto  0) = RS1( 7 downto  0) + RS2( 7 downto  0)
//RD(16 downto  8) = RS1(16 downto  8) + RS2(16 downto  8)
//RD(23 downto 16) = RS1(23 downto 16) + RS2(23 downto 16)
//RD(31 downto 24) = RS1(31 downto 24) + RS2(31 downto 24)
//
//Instruction encoding :
//0000011----------000-----0110011
//       |RS2||RS1|   |RD |
//
//Note :  RS1, RS2, RD positions follow the RISC-V spec and are common for all instruction of the ISA

class SimdAddPlugin extends Plugin[VexRiscv]{
  //Define the concept of IS_SIMD_ADD signals, which specify if the current instruction is destined for this plugin
  object IS_SIMD_ADD extends Stageable(Bool)

  //Callback to setup the plugin and ask for different services
  override def setup(pipeline: VexRiscv): Unit = {
    import pipeline.config._

    //Retrieve the DecoderService instance
    val decoderService = pipeline.service(classOf[DecoderService])

    //Specify the IS_SIMD_ADD default value when instructions are decoded
    decoderService.addDefault(IS_SIMD_ADD, False)

    //Specify the instruction decoding which should be applied when the instruction matches the 'key' parttern
    decoderService.add(
      //Bit pattern of the new SIMD_ADD instruction
      key = M"0000011----------000-----0110011",

      //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
        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 uses the RS1 value
        RS2_USE                  -> True  //Same as above but for RS2.
      )
    )
  }

  override def build(pipeline: VexRiscv): Unit = {
    import pipeline._
    import pipeline.config._

    //Add a new scope on the execute stage (used to give a name to signals)
    execute plug new Area {
      //Define some signals used internally by the plugin
      val rs1 = execute.input(RS1).asUInt
      //32 bits UInt value of the regfile[RS1]
      val rs2 = execute.input(RS2).asUInt
      val rd = UInt(32 bits)

      //Do some computations
      rd(7 downto 0) := rs1(7 downto 0) + rs2(7 downto 0)
      rd(16 downto 8) := rs1(16 downto 8) + rs2(16 downto 8)
      rd(23 downto 16) := rs1(23 downto 16) + rs2(23 downto 16)
      rd(31 downto 24) := rs1(31 downto 24) + rs2(31 downto 24)

      //When the instruction is a SIMD_ADD, write the result into the register file data path.
      when(execute.input(IS_SIMD_ADD)) {
        execute.output(REGFILE_WRITE_DATA) := rd.asBits
      }
    }
  }
}

If you want to add this plugin to a given CPU, you just need to add it to its parameterized plugin list.

This example is a very simple one, but each plugin can really have access to the whole CPU:

  • Halt a given stage of the CPU
  • Unschedule instructions
  • Emit an exception
  • Introduce a new instruction decoding specification
  • Ask to jump the PC somewhere
  • Read signals published by other plugins
  • Override published signals values
  • Provide an alternative implementation
  • ...

As a demonstration, this SimdAddPlugin was integrated in the src/main/scala/vexriscv/demo/GenCustomSimdAdd.scala CPU configuration and is self-tested by the src/test/cpp/custom/simd_add application by running the following commands:

# Generate the CPU
sbt "runMain vexriscv.demo.GenCustomSimdAdd"

cd src/test/cpp/regression/

# Optionally add TRACE=yes if you want to get the VCD waveform from the simulation.
# Also you have to know that, by default, the testbench introduce instruction/data bus stall.
# Note the CUSTOM_SIMD_ADD flag is set to yes.
make clean run IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no DHRYSTONE=no REDO=2 CUSTOM_SIMD_ADD=yes

To retrieve the plugin related signals in your waveform viewer, just filter with simd.

Adding a new CSR via the plugin system

Here are two examples about how to add a custom CSR to the CPU via the plugin system: https://github.com/SpinalHDL/VexRiscv/blob/master/src/main/scala/vexriscv/demo/CustomCsrDemoPlugin.scala

The first one (CustomCsrDemoPlugin) adds an instruction counter and a clock cycle counter into the CSR mapping (and also do tricky stuff as a demonstration).

The second one (CustomCsrDemoGpioPlugin) creates a GPIO peripheral directly mapped into the CSR.

CPU clock and resets

Without the debug plugin, the CPU will have a standard clk input and a reset input. But with the debug plugin the situation is the following:

  • clk: as before, the clock which drives the whole CPU design, including the debug logic
  • reset: reset all the CPU states except the debug logic
  • debugReset: reset the debug logic of the CPU
  • debug_resetOut: a CPU output signal which allows the JTAG to reset the CPU + the memory interconnect + the peripherals

So here is the reset interconnect, in case you use the debug plugin:

                                VexRiscv
                            +------------------+
                            |                  |
toplevelReset >----+--------> debugReset       |
                   |        |                  |
                   |  +-----< debug_resetOut   |
                   |  |     |                  |
                   +--or>-+-> reset            |
                          | |                  |
                          | +------------------+
                          |
                          +-> Interconnect / Peripherals

VexRiscv Architecture

VexRiscv is implemented via a 5 stage in-order pipeline on which many optional and complementary plugins add functionalities to provide a functional RISC-V CPU. This approach is completely unconventional and only possible through meta hardware description languages (SpinalHDL, in the current case) but has proven its advantages via the VexRiscv implementation:

  • You can swap/turn on/turn off parts of the CPU directly via the plugin system
  • You can add new functionalities/instructions without having to modify any of the sources of the CPU
  • It allows the CPU configuration to cover a very large spectrum of implementations without cooking spaghetti code
  • It allows your codebase to truly produce a parametrized CPU design

If you generate the CPU without any plugin, it will only contain the definition of the 5 pipeline stages and their basic arbitration, but nothing else, and everything else, including the program counter is added into the CPU via plugins.

FPU

Features :

  • Support IEEE 754 float and optionaly double
  • Implement Subnormal (few cycles lost in case of subnormal load/store)
  • Implement exceptions flags
  • The FPU can be shared between multiple CPU
  • Can be integrated inside or outside the CPU via the FpuPlugin
  • Fully pipelined, can produce one result per cycle for most operations (add,sub, mul, fma, load, store), as long there is no inter-dependancies
  • Implement multiplication using multiple sub multiplication operations in parallel ("FPGA friendly")
  • Division done with radix 4 (2 bits per cycle)
  • Square root done with radix 2 (1 bit per cycle)
  • Currently only compatible with the DBusCachedPlugin for load and store
  • 64 bits Load and store can be done in one cycle via the DBusCachedPlugin (even if VexRiscv is RV32)

Accuracy, roundings (RNE, RTZ, RDN, RUP, RMM) and compliance:

  • Fully implemented excepted in the cases specified bellow
  • In FMA, the result of the multiplication is rounded before the addition (keep mantissa width + 2 bits)
  • A very special corner case of underflow flag do not follow IEEE 754 (rounding from subnormal to normal number)
  • Very specific, but SGNJ instruction will not mutate the value from/to F32/F64 (no NaN-boxing mutation)

There is a diagram of the FPU design and its CPU integration :

fpuDesign

The FPU can be parametrized with FpuParameter data structure :

Parameters type description
withDouble Boolean Enable 64 bits floating point (32 bits always enabled)
asyncRegFile Boolean Implement the register file using combinatorial reads (instead of syncronous reads)
mulWidthA Boolean Specify the width of the left operand of multiplication blocks
mulWidthB Boolean Same than above but the the right operand

Synthesis results of the FPU itself, without the CPU integration, on the fast speed grade :

Fpu 32 bits ->
  Artix 7 relaxed -> 135 Mhz 1786 LUT 1778 FF 
  Artix 7 FMax    -> 205 Mhz 2101 LUT 1778 FF 
Fpu 64/32 bits ->
  Artix 7 relaxed -> 101 Mhz 3336 LUT 3033 FF 
  Artix 7 FMax    -> 165 Mhz 3728 LUT 3175 FF 

Note that if you want to debug FPU code via the openocd_riscv.vexriscv target, you need to use the GDB from :

https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-20171231-x86_64-linux-centos6.tar.gz

More recent versions of gdb will not detect the FPU. Also, the openocd_riscv.vexriscv can't read CSR/FPU registers, so to have visibility on the floating points values, you need to compile your code in -O0, which will force values to be stored in memory (and so, be visible)

Plugins

This chapter describes the currently implemented plugins.

IBusSimplePlugin

This plugin implements the CPU frontend (instruction fetch) via a very simple and neutral memory interface going outside the CPU.

Parameters type description
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:

case class IBusSimpleCmd() extends Bundle{
  val pc = UInt(32 bits)
}

case class IBusSimpleRsp() extends Bundle with IMasterSlave{
  val error = Bool
  val inst  = Bits(32 bits)

  override def asMaster(): Unit = {
    out(error,inst)
  }
}

case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMasterSlave{
  var cmd = Stream(IBusSimpleCmd())
  var rsp = Flow(IBusSimpleRsp())

  override def asMaster(): Unit = {
    master(cmd)
    slave(rsp)
  }
}

Important : check out the cmdForkPersistence parameter, because if it is not set, it can break the iBus compatibility with your memory system (unless you externaly add some buffers).

Setting cmdForkPersistence and cmdForkOnSecondStage improves iBus cmd timings.

The iBusSimplePlugin includes bridges to convert from the IBusSimpleBus to AXI4, Avalon, and Wishbone interfaces.

This plugin implements a jump interface that allows all other plugins to issue a jump:

trait JumpService{
  def createJumpInterface(stage : Stage) : Flow[UInt]
}

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

Simple and light multi-way instruction cache.

Parameters type description
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 an asynchronous manner.

The memory bus is defined as :

case class InstructionCacheMemCmd(p : InstructionCacheConfig) extends Bundle{
  val address = UInt(p.addressWidth bit)
  val size = UInt(log2Up(log2Up(p.bytePerLine) + 1) bits)
}

case class InstructionCacheMemRsp(p : InstructionCacheConfig) extends Bundle{
  val data = Bits(p.memDataWidth bit)
  val error = Bool
}

case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle with IMasterSlave{
  val cmd = Stream (InstructionCacheMemCmd(p))
  val rsp = Flow (InstructionCacheMemRsp(p))

  override def asMaster(): Unit = {
    master(cmd)
    slave(rsp)
  }
}

The address is in byte and aligned to the bytePerLine config, the size will always be equal to log2(bytePerLine).

Note that the cmd stream transaction need to be consumed before starting to send back some rsp transactions (1 cycle minimal latency)

Some documentation about Stream here :

https://spinalhdl.github.io/SpinalDoc-RTD/master/SpinalHDL/Libraries/stream.html?highlight=stream

Flow are the same as Stream but without ready signal.

DecoderSimplePlugin

This plugin provides instruction decoding capabilities to other 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 to stall the pipeline until the hazard is gone. Each plugin that implements an instruction provides this kind of information to the DecoderSimplePlugin plugin.

Parameters type description
catchIllegalInstruction Boolean When true, instructions that don't match a decoding specification will generate a trap exception

Here is a usage example:

    //Specify the instruction decoding which should be applied when the instruction matches the 'key' pattern
    decoderService.add(
      //Bit pattern of the new instruction
      key = M"0000011----------000-----0110011",

      //Decoding specification when the 'key' pattern is recognized in the instruction
      List(
        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 uses the RS1 value
        RS2_USE                  -> True  //Same than above but for RS2.
      )
    )
  }

This plugin operates in the Decode stage.

RegFilePlugin

This plugin implements the register file.

Parameters type description
regFileReadyKind RegFileReadKind Can be set to ASYNC or SYNC. Specifies the kind of memory read used to implement the register file. ASYNC means zero cycle latency memory read, while SYNC means one cycle latency memory read which can be mapped into standard FPGA memory blocks
zeroBoot Boolean Load all registers with zeroes at the beginning of the simulation to keep everything deterministic in logs/traces

This register file use a don't care read-during-write policy, so the bypassing/hazard plugin should take care of this.

If you get a Missing inserts : INSTRUCTION_ANTICIPATE error, that's because the RegFilePlugin is configured to use SYNC memory read ports to access the register file, but the IBus plugin configuration can't provide the instruction's register file read address one cycle before the decode stage. To workaround that you can :

  • Configure the RegFilePlugin to implement the register file read in a asyncronus manner (ASYNC), if your target device support such things
  • If you use the IBusSimplePlugin, you need to enable the injectorStage configuration
  • If you use the IBusCachedPlugin, you can either enable the injectorStage, or set twoCycleCache + twoCycleRam to false.

HazardSimplePlugin

This plugin checks the pipeline instruction dependencies and, if necessary or possible, will stop the instruction in the decoding stage or bypass the instruction results from the later stages of the decode stage.

Since the register file is implemented with a don't care read-during-write policy, this plugin also manages these kind of hazards.

Parameters type description
bypassExecute Boolean Enable the bypassing of instruction results coming from the Execute stage
bypassMemory Boolean Enable the bypassing of instruction results coming from the Memory stage
bypassWriteBack Boolean Enable the bypassing of instruction results coming from the WriteBack stage
bypassWriteBackBuffer Boolean Enable the bypassing of the previous cycle register file written value

SrcPlugin

This plugin muxes different input values to produce SRC1/SRC2/SRC_ADD/SRC_SUB/SRC_LESS values which are common values used by many plugins in the execute stage (ALU/Branch/Load/Store).

Parameters type description
separatedAddSub RegFileReadKind By default SRC_ADD/SRC_SUB are generated from a single controllable adder/substractor, but if this is set to true, it use separate adder/substractors
executeInsertion Boolean By default SRC1/SRC2 are generated in the Decode stage, but if this parameter is true, it is done in the Execute stage (It will relax the bypassing network)

Except for SRC1/SRC2, this plugin does everything at the begining of Execute stage.

IntAluPlugin

This plugin implements all ADD/SUB/SLT/SLTU/XOR/OR/AND/LUI/AUIPC instructions in the execute stage by using the SrcPlugin outputs. It is a really simple plugin.

The result is injected into the pipeline directly at the end of the execute stage.

LightShifterPlugin

Implements SLL/SRL/SRA instructions by using an iterative shifter register, while using one cycle per bit shift.

The result is injected into the pipeline directly at the end of the execute stage.

FullBarrelShifterPlugin

Implements SLL/SRL/SRA instructions by using a full barrel shifter, so it executes all shifts in a single cycle.

Parameters type description
earlyInjection Boolean By default the result of the shift is injected into the pipeline in the Memory stage to relax timings, but if this option is true it will be done in the Execute stage

BranchPlugin

This plugin implements all branch/jump instructions (JAL/JALR/BEQ/BNE/BLT/BGE/BLTU/BGEU) with primitives used by the cpu frontend plugins to implement branch prediction. The prediction implementation is set in the frontend plugins (IBusX).

Parameters type description
earlyBranch Boolean By default the branch is done in the Memory stage to relax timings, but if this option is set it's done in the Execute stage
catchAddressMisaligned Boolean If a jump/branch is done in an unaligned PC address, it will fire an trap exception

Each miss predicted jumps will produce between 2 and 4 cycles penalty depending the earlyBranch and the PcManagerSimplePlugin.relaxedPcCalculation configurations

Prediction NONE

No prediction: each PC change due to a jump/branch will produce a penalty.

Prediction STATIC

In the decode stage, a conditional branch pointing backwards or a JAL is branched speculatively. If the speculation is right, the branch penalty is reduced to a single cycle, otherwise the standard penalty is applied.

Prediction DYNAMIC

Same as the STATIC prediction, except that to do the prediction, it uses a direct mapped 2 bit history cache (BHT) which remembers if the branch is more likely to be taken or not.

Prediction DYNAMIC_TARGET

This predictor uses a direct mapped branch target buffer (BTB) in the Fetch stage which stores the PC of the instruction, the target PC of the instruction and a 2 bit history to remember if the branch is more likely to be taken or not. This is actually the most efficient branch predictor implemented on VexRiscv, because when the branch prediction is right, it produces no branch penalty. The downside is that this predictor has a long combinatorial path coming from the prediction cache read port to the programm counter, passing through the jump interface.

DBusSimplePlugin

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
catchAddressMisaligned Boolean If a memory access is done to an unaligned memory address, it will fire a trap exception
catchAccessFault Boolean If a memory read returns an error, it will fire a trap exception
earlyInjection Boolean By default, the memory read values are injected into the pipeline in the WriteBack stage to relax the timings. If this parameter is true, it's done in the Memory stage

Here is the DBusSimpleBus

case class DBusSimpleCmd() extends Bundle{
  val wr = Bool
  val address = UInt(32 bits)
  val data = Bits(32 bit)
  val size = UInt(2 bit)
}

case class DBusSimpleRsp() extends Bundle with IMasterSlave{
  val ready = Bool
  val error = Bool
  val data = Bits(32 bit)

  override def asMaster(): Unit = {
    out(ready,error,data)
  }
}


case class DBusSimpleBus() extends Bundle with IMasterSlave{
  val cmd = Stream(DBusSimpleCmd())
  val rsp = DBusSimpleRsp()

  override def asMaster(): Unit = {
    master(cmd)
    slave(rsp)
  }
}

Note that there are bridges available that can convert this interface into AXI4 and Avalon.

There is at least one cycle latency between a cmd and the corresponding rsp. The rsp.ready flag should be false after a read cmd until the rsp is present.

DBusCachedPlugin

Multi way cache implementation with writh-through and allocate on read strategy. (Documentation is WIP)

You can invalidate the whole cache via the 0x500F instruction, and you can invalidate a address range (single line size) via the instruction 0x500F | RS1 << 15 where RS1 should not be X0 and point to one byte of the desired address to invalidate.

The memory bus is defined as :

case class DataCacheMemCmd(p : DataCacheConfig) extends Bundle{
  val wr = Bool
  val uncached = Bool
  val address = UInt(p.addressWidth bit)
  val data = Bits(p.cpuDataWidth bits)
  val mask = Bits(p.cpuDataWidth/8 bits)
  val size   = UInt(p.sizeWidth bits) //... 1 => 2 bytes ... 2 => 4 bytes ...
  val exclusive = p.withExclusive generate Bool()
  val last = Bool
}
case class DataCacheMemRsp(p : DataCacheConfig) extends Bundle{
  val aggregated = UInt(p.aggregationWidth bits)
  val last = Bool()
  val data = Bits(p.memDataWidth bit)
  val error = Bool
  val exclusive = p.withExclusive generate Bool()
}
case class DataCacheInv(p : DataCacheConfig) extends Bundle{
  val enable = Bool()
  val address = UInt(p.addressWidth bit)
}
case class DataCacheAck(p : DataCacheConfig) extends Bundle{
  val hit = Bool()
}

case class DataCacheSync(p : DataCacheConfig) extends Bundle{
  val aggregated = UInt(p.aggregationWidth bits)
}

case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave{
  val cmd = Stream (DataCacheMemCmd(p))
  val rsp = Flow (DataCacheMemRsp(p))

  val inv = p.withInvalidate generate Stream(Fragment(DataCacheInv(p)))
  val ack = p.withInvalidate generate Stream(Fragment(DataCacheAck(p)))
  val sync = p.withInvalidate generate Stream(DataCacheSync(p))

  override def asMaster(): Unit = {
    master(cmd)
    slave(rsp)

    if(p.withInvalidate) {
      slave(inv)
      master(ack)
      slave(sync)
    }
  }
}

If you don't use memory coherency you can ignore the inv/ack/sync streams, also write cmd should not generate any rsp transaction.

As the cache is write through, there is no write burst but only individual write transactions.

The address is in byte and aligned to the bytePerLine config, the size will is encoded as log2(number of bytes in the burst). last should be set only on the last transaction of a burst.

Note that the cmd stream transaction need to be consumed before starting to send back some rsp transactions (1 cycle minimal latency)

Some documentation about Stream here :

https://spinalhdl.github.io/SpinalDoc-RTD/master/SpinalHDL/Libraries/stream.html?highlight=stream

Flow are the same as Stream but without ready signal.

MulPlugin

Implements the multiplication instruction from the RISC-V M extension. Its implementation was done in a FPGA friendly way by using 4 17*17 bit multiplications. The processing is fully pipelined between the Execute/Memory/Writeback stage. The results of the instructions are always inserted in the WriteBack stage.

DivPlugin

Implements the division/modulo instruction from the RISC-V M extension. It is done in a simple iterative way which always takes 34 cycles. The result is inserted into the Memory stage.

This plugin is now based on MulDivIterativePlugin.

MulDivIterativePlugin

This plugin implements the multiplication, division and modulo of the RISC-V M extension in an iterative way, which is friendly for small FPGAs that don't have DSP blocks.

This plugin is able to unroll the iterative calculation process to reduce the number of cycles used to execute mul/div instructions.

Parameters type description
genMul Boolean Enables multiplication support. Can be set to false if you want to use the MulPlugin instead
genDiv Boolean Enables division support
mulUnrollFactor Int Number of combinatorial stages used to speed up the multiplication, should be > 0
divUnrollFactor Int Number of combinatorial stages used to speed up the division, should be > 0

The number of cycles used to execute a multiplication is '32/mulUnrollFactor' The number of cycles used to execute a division is '32/divUnrollFactor + 1'

Both mul/div are processed in the memory stage (late result).

CsrPlugin

Implements most of the Machine mode and a few of the User mode registers, as specified in the RISC-V priviledged spec. The access mode of most of the CSR is parameterizable to reduce the area usage of unneeded features.

(CsrAccess can be NONE/READ_ONLY/WRITE_ONLY/READ_WRITE)

Parameters type description
catchIllegalAccess Boolean
mvendorid BigInt
marchid BigInt
mimpid BigInt
mhartid BigInt
misaExtensionsInit Int
misaAccess CsrAccess
mtvecAccess CsrAccess
mtvecInit BigInt
mepcAccess CsrAccess
mscratchGen Boolean
mcauseAccess CsrAccess
mbadaddrAccess CsrAccess
mcycleAccess CsrAccess
minstretAccess CsrAccess
ucycleAccess CsrAccess
wfiGen Boolean
ecallGen Boolean

If an interrupt occurs, before jumping to mtvec, the plugin will stop the Prefetch stage and wait for all the instructions in the later pipeline stages to complete their execution.

If an exception occur, the plugin will kill the corresponding instruction, flush all previous instructions, and wait until the previously killed instructions reach the WriteBack stage before jumping to mtvec.

StaticMemoryTranslatorPlugin

Static memory translator plugin which allows to specify which range of the memory addresses is I/O mapped and shouldn't be cached.

Parameters type description
ioRange UInt => Bool Function reference which eat an address and return true if the address should be uncached. ex : ioRange= _(31 downto 28) === 0xF => all 0xFXXXXXXX will be uncached

MmuPlugin

Hardware refilled MMU implementation. Allows other 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.

PmpPlugin

This is a physical memory protection (PMP) plugin which conforms to the v1.12 RISC-V privilege specification, without ePMP (Smepmp) extension support. PMP is configured by writing two special CSRs: pmpcfg# and pmpaddr#. The former contains the permissions and addressing modes for four protection regions, and the latter contains the encoded start address for a single region. Since the actual region bounds must be computed from the values written to these registers, writing them takes a few CPU cylces. This delay is necessary in order to centralize all of the decoding logic into a single component. Otherwise, it would have to be duplicated for each region, even though the decoding operation happens only when PMP is reprogrammed (e.g., on some context switches).

PmpPluginNapot

The PmpPluginNapot is a specialized PMP implementation, providing only the NAPOT (naturally-aligned poser-of-2 regions) addressing mode. It requires fewer resources and has a less significant timing impact compared to the full PmpPlugin.

DebugPlugin

This plugin implements enough CPU debug features to allow comfortable GDB/Eclipse debugging. To access those debug features, it provides a simple memory bus interface. The JTAG interface is provided by another bridge, which makes it possible to efficiently connect multiple CPUs to the same JTAG.

Parameters type description
debugClockDomain ClockDomain As the debug unit is able to reset the CPU itself, it should use another clock domain to avoid killing itself (only the reset wire should differ)

The internals of the debug plugin are done in a manner which reduces the area usage and the FMax impact of this plugin.

Here is the simple bus to access it, the rsp comes one cycle after the request:

case class DebugExtensionCmd() extends Bundle{
  val wr = Bool
  val address = UInt(8 bit)
  val data = Bits(32 bit)
}
case class DebugExtensionRsp() extends Bundle{
  val data = Bits(32 bit)
}

case class DebugExtensionBus() extends Bundle with IMasterSlave{
  val cmd = Stream(DebugExtensionCmd())
  val rsp = DebugExtensionRsp()

  override def asMaster(): Unit = {
    master(cmd)
    in(rsp)
  }
}

Here is the register mapping:

Read address 0x00 ->
  bit 0  : resetIt
  bit 1  : haltIt
  bit 2  : isPipBusy
  bit 3  : haltedByBreak
  bit 4  : stepIt
Write address 0x00 ->
  bit 4  : stepIt
  bit 16 : set resetIt
  bit 17 : set haltIt
  bit 24 : clear resetIt
  bit 25 : clear haltIt and haltedByBreak

Read Address 0x04 ->
  bits (31 downto 0) : Last value written into the register file
Write Address 0x04 ->
  bits (31 downto 0) : Instruction that should be pushed into the CPU pipeline for debug purposes

The OpenOCD port is here: https://github.com/SpinalHDL/openocd_riscv

EmbeddedRiscvJtag

VexRiscv also support the official RISC-V debug specification (Thanks Efinix for the funding !).

To enable it, you need to add the EmbeddedRiscvJtag to the plugin list :

new EmbeddedRiscvJtag(
  p = DebugTransportModuleParameter(
    addressWidth = 7,
    version      = 1,
    idle         = 7
  ),
  withTunneling = false,
  withTap = true
)

And turn on the withPrivilegedDebug option in the CsrPlugin config.

Here is an example of openocd tcl script to connect :

# ADD HERE YOUR JTAG ADAPTER SETTINGS

set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10002FFF

set _TARGETNAME $_CHIPNAME.cpu

target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME

init
halt

A full example can be found in GenFullWithOfficialRiscvDebug.scala

YamlPlugin

This plugin offers a service to other plugins to generate a useful Yaml file describing the CPU configuration. It contains, for instance, the sequence of instructions required to flush the data cache (information used by openocd).

FpuPlugin

Allow the integration of a internal or a external FPU into VexRiscv (See the FPU chapter)

Parameters type description
externalFpu Boolean When false the FPU is instanciated in Vex, else the plugin has a port interface to which you can connect an external FPU
p FpuParameter Parameter with which the connected FPU will be created

AesPlugin

This plugin allow to accelerate AES encryption/decryption by using an internal ROM to solve SBOX and permutations, allowing in practice to execute one AES round in about 21 cycles.

For more documentation, check src/main/scala/vexriscv/plugin/AesPlugin.scala, a software C driver can be found here : https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/software/standalone/driver/aes_custom.h

It was also ported on libressl via the following patch : https://github.com/SpinalHDL/buildroot-spinal-saxon/blob/main/patches/libressl/0000-vexriscv-aes.patch

Speed up of 4 was observed in libressl running in linux. SpinalHDL/SaxonSoc#53 (comment)

vexriscv's People

Contributors

andreaswallner avatar banahogg avatar buncram avatar bunnie avatar chiangkd avatar dnltz avatar dolu1990 avatar japm48 avatar kaofishy avatar lindemer avatar lschuermann avatar marekpikula avatar martijnbastiaan avatar mateusz-holenko avatar mithro avatar mmicko avatar occheung avatar oscarshiang avatar pradeep2004 avatar pythonlinks avatar rdolbeau avatar robindust-ce avatar rpls avatar saahm avatar sebastien-riou avatar snoopy87 avatar tcal-x avatar tomverbeure avatar xobs avatar zeldin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vexriscv's Issues

Construct Plugin-wrapped objects using Factories OR Parameterize

More of a feature request for a frustrating modification, than an issue

I'm trying to add a toAxi4() method to DBusSimpleBus (because AXI Shared isn't part of the AXI spec), so I've created a subclass DBusSimpleAxiBus that implements the toAxi4 method.

It's fairly easy to use DBusSimpleBus as a parent for a new class, DBusSimpleAxiBus - but it's non trivial to use DBusSimpleAxiBus in a plugin without copy-pasting much of the code in the build method of DBusSimplePlugin. This is because DBusSimpleBus is directly created by DBusSimpleAxiPlugin instead of using a parameter or a factory

There are two factory solutions I can think of:

  1. Parameterize DBusSimplePlugin with the class of the bus it wraps - and make that class provide a factory method / instantiate the parameterization directly

And the less clean, but easier way
2. Add a factory method to DBusSimplePlugin that subclasses can override.

With either 1 or 2 extending DBusSimpleBus and DBusSimplePlugin becomes simple. Instead of calling the constructor directly - DBusSimplePlugin can call the factory and my extension takes a handful of lines that reuses all of the code you've written (hooray OOP!), or use the parameterized constructor directly

Anyhow, option 2 is shown below. I provide a dBusFactory method in DBusSimplePlugin, and override it in DBusSimpleAxi4Bus

I think option 1 is better in the long run - because it could eliminate the need of calling toAxi4Shared, toAvalon,

class DBusSimplePlugin(catchAddressMisaligned : Boolean, catchAccessFault : Boolean, earlyInjection : Boolean = false) extends Plugin[VexRiscv]{

  var dBus  : DBusSimpleBus = null

 def dBusFactory(): DBusSimpleBus = { // New factory method
    return master(DBusSimpleBus()).setName("dBus")
  }
  override def build(pipeline: VexRiscv): Unit = {
    import pipeline._
    import pipeline.config._

    dBus = dBusFactory() // New factory method call

    // Remaining build() code not shown...

  }
}

class DBusSimpleAxi4Bus() extends DBusSimpleBus() {
  def toAxi4(stageCmd : Boolean = true): Axi4 = {
    // Not shown...
  }
}

class DBusSimpleAxi4Plugin(catchAddressMisaligned : Boolean, catchAccessFault : Boolean, earlyInjection : Boolean = false) extends DBusSimplePlugin(catchAddressMisaligned, catchAccessFault, earlyInjection) {
                                                                                                                                                                                                 
  override def dBusFactory(): DBusSimpleBus = {
    return master(new DBusSimpleAxi4Bus()).setName("dBus")
  }
}


What this means is that I can extend your codebase without forking it and modifying it to add a toAxi4 method in DBusSimpleBus. Ditto for DBusCached

Murax debug on FPGA

I had some success using Debug with verilator, now I switched to FPGA (iCE40-HX8K) and a JLink JTAG probe. I am using the project iCE40-hx8k_breakout_board.
What works:

  • The code execution in general, without connection to debug I mean.
  • The JTAG connection seems fine, the target is found everytime, I can read/write registers and run from the first instruction to the first breakpoint (which I can place anywhere in the code).

What does not work:

  • I cannot step (just trying intruction level for now). when I try to instruction step from the first instruction, instead of jumping to 0x800000b0 I land at 0xb0. If I set a break point at 0x800000b0 and just run then I stop there. Then if I instruction step I land at 0xb4 instead of 0x800000b4... It seems the instruction step is discarding some most significant bits.
  • I cannot run to a second breakpoint

What I tried:

  • removing all break points -> the first instruction step still lands at 0xb0
  • reduce JTAG frequency to 400kHz -> same behavior
  • openocd debug message does not contain obvious error message

openocd_riscv is up-to-date, Murax is from yesterday, I just changed the RAM size to 8k (it is 4k in the object "MuraxWithRamInit").

One detail about the wiring: I connected only TMS,TDI,TDO,TCK,GND and VREF. I did not connect TRST to anything, should it be ?

log of openocd for the trial "reset, run with break at , instruction step"

user@lafite:~/Downloads/openocd_riscv$ src/openocd -d -f tcl/interface/jlink.cfg -c "set MURAX_CPU0_YAML /home/user/Downloads/VexRiscv/cpu0.yaml" -f tcl/target/murax.cfg
Open On-Chip Debugger 0.10.0+dev-01202-gced8dcd (2019-02-25-22:00)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
User : 13 5 command.c:544 command_print(): debug_level: 3
Debug: 14 5 options.c:184 add_default_dirs(): bindir=/usr/local/bin
Debug: 15 5 options.c:185 add_default_dirs(): pkgdatadir=/usr/local/share/openocd
Debug: 16 5 options.c:186 add_default_dirs(): exepath=/home/user/Downloads/openocd_riscv/src
Debug: 17 5 options.c:187 add_default_dirs(): bin2data=../share/openocd
Debug: 18 5 configuration.c:42 add_script_search_dir(): adding /home/user/.openocd
Debug: 19 5 configuration.c:42 add_script_search_dir(): adding /home/user/Downloads/openocd_riscv/src/../share/openocd/site
Debug: 20 5 configuration.c:42 add_script_search_dir(): adding /home/user/Downloads/openocd_riscv/src/../share/openocd/scripts
Debug: 21 5 configuration.c:97 find_file(): found tcl/interface/jlink.cfg
Debug: 22 5 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_interface jlink
Debug: 23 5 command.c:143 script_debug(): command - interface ocd_interface jlink
Debug: 25 5 command.c:323 command_new(): BUG: command 'jlink' does not have the '.usage' field filled out
Debug: 26 5 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 27 5 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 28 5 command.c:323 command_new(): BUG: command 'jlink freemem' does not have the '.usage' field filled out
Debug: 29 5 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 30 5 command.c:323 command_new(): BUG: command 'jlink hwstatus' does not have the '.usage' field filled out
Debug: 31 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 32 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 33 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 34 6 command.c:323 command_new(): BUG: command 'jlink config' does not have the '.usage' field filled out
Debug: 35 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 36 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 37 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 38 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 39 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 40 6 command.c:323 command_new(): BUG: command 'config reset' does not have the '.usage' field filled out
Debug: 41 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 42 6 command.c:323 command_new(): BUG: command 'config write' does not have the '.usage' field filled out
Debug: 43 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 44 6 command.c:323 command_new(): BUG: command 'jlink emucom' does not have the '.usage' field filled out
Debug: 45 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 46 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
Debug: 47 6 command.c:364 register_command_handler(): registering 'ocd_jlink'...
User : 48 6 command.c:693 command_run_line(): /home/user/Downloads/VexRiscv/cpu0.yamlUser : 49 6 command.c:695 command_run_line(): 
Debug: 50 6 configuration.c:97 find_file(): found tcl/target/murax.cfg
Debug: 51 6 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_adapter_khz 400
Debug: 52 6 command.c:143 script_debug(): command - adapter_khz ocd_adapter_khz 400
Debug: 54 6 core.c:1645 jtag_config_khz(): handle jtag khz
Debug: 55 6 core.c:1612 adapter_khz_to_speed(): convert khz to interface specific speed value
Debug: 56 6 core.c:1612 adapter_khz_to_speed(): convert khz to interface specific speed value
User : 57 6 command.c:544 command_print(): adapter speed: 400 kHz
Debug: 58 6 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_adapter_nsrst_delay 260
Debug: 59 6 command.c:143 script_debug(): command - adapter_nsrst_delay ocd_adapter_nsrst_delay 260
User : 61 6 command.c:544 command_print(): adapter_nsrst_delay: 260
Debug: 62 6 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_transport select
Debug: 63 6 command.c:143 script_debug(): command - ocd_transport ocd_transport select
Info : 64 6 transport.c:286 jim_transport_select(): auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Debug: 65 6 command.c:364 register_command_handler(): registering 'ocd_jtag_flush_queue_sleep'...
Debug: 66 7 command.c:364 register_command_handler(): registering 'ocd_jtag_rclk'...
Debug: 67 7 command.c:364 register_command_handler(): registering 'ocd_jtag_ntrst_delay'...
Debug: 68 7 command.c:364 register_command_handler(): registering 'ocd_jtag_ntrst_assert_width'...
Debug: 69 7 command.c:364 register_command_handler(): registering 'ocd_scan_chain'...
Debug: 70 7 command.c:364 register_command_handler(): registering 'ocd_jtag_reset'...
Debug: 71 7 command.c:364 register_command_handler(): registering 'ocd_runtest'...
Debug: 72 7 command.c:364 register_command_handler(): registering 'ocd_irscan'...
Debug: 73 7 command.c:364 register_command_handler(): registering 'ocd_verify_ircapture'...
Debug: 74 7 command.c:364 register_command_handler(): registering 'ocd_verify_jtag'...
Debug: 75 7 command.c:364 register_command_handler(): registering 'ocd_tms_sequence'...
Debug: 76 7 command.c:364 register_command_handler(): registering 'ocd_wait_srst_deassert'...
Debug: 77 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 78 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 79 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 80 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 81 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 82 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 83 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 84 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 85 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 86 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 87 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 88 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 89 7 command.c:364 register_command_handler(): registering 'ocd_jtag'...
Debug: 90 7 command.c:364 register_command_handler(): registering 'ocd_svf'...
Debug: 91 7 command.c:364 register_command_handler(): registering 'ocd_xsvf'...
Debug: 92 7 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_transport select
Debug: 93 7 command.c:143 script_debug(): command - ocd_transport ocd_transport select
Debug: 94 7 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_jtag_ntrst_delay 250
Debug: 95 7 command.c:143 script_debug(): command - jtag_ntrst_delay ocd_jtag_ntrst_delay 250
User : 97 7 command.c:544 command_print(): jtag_ntrst_delay: 250
Debug: 98 8 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_jtag newtap fpga_spinal bridge -expected-id 0x10001fff -irlen 4 -ircapture 0x1 -irmask 0xF
Debug: 99 8 command.c:143 script_debug(): command - ocd_jtag ocd_jtag newtap fpga_spinal bridge -expected-id 0x10001fff -irlen 4 -ircapture 0x1 -irmask 0xF
Debug: 100 8 tcl.c:550 jim_newtap_cmd(): Creating New Tap, Chip: fpga_spinal, Tap: bridge, Dotted: fpga_spinal.bridge, 8 params
Debug: 101 8 tcl.c:574 jim_newtap_cmd(): Processing option: -expected-id
Debug: 102 8 tcl.c:574 jim_newtap_cmd(): Processing option: -irlen
Debug: 103 8 tcl.c:574 jim_newtap_cmd(): Processing option: -ircapture
Debug: 104 8 tcl.c:574 jim_newtap_cmd(): Processing option: -irmask
Debug: 105 8 core.c:1304 jtag_tap_init(): Created Tap: fpga_spinal.bridge @ abs position 0, irlen 4, capture: 0x1 mask: 0xf
Debug: 106 8 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_target create fpga_spinal.cpu0 vexriscv -endian little -chain-position fpga_spinal.bridge -coreid 0 -dbgbase 0xF00F0000
Debug: 107 8 command.c:143 script_debug(): command - ocd_target ocd_target create fpga_spinal.cpu0 vexriscv -endian little -chain-position fpga_spinal.bridge -coreid 0 -dbgbase 0xF00F0000
Debug: 108 8 target.c:1931 target_free_all_working_areas_restore(): freeing all working areas
Debug: 109 8 vexriscv.c:176 vexriscv_target_create(): vexriscv_target_create

Debug: 110 8 command.c:364 register_command_handler(): registering 'ocd_vexriscv'...
Debug: 111 8 command.c:364 register_command_handler(): registering 'ocd_vexriscv'...
Debug: 112 8 command.c:364 register_command_handler(): registering 'ocd_vexriscv'...
Debug: 113 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 114 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 115 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 116 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 117 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 118 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 119 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 120 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 121 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 122 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 123 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 124 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 125 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 126 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 127 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 128 8 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 129 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 130 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 131 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 132 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 133 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 134 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 135 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 136 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 137 9 command.c:364 register_command_handler(): registering 'ocd_fpga_spinal.cpu0'...
Debug: 138 9 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_vexriscv readWaitCycles 12
Debug: 139 9 command.c:143 script_debug(): command - ocd_vexriscv ocd_vexriscv readWaitCycles 12
Debug: 141 9 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_vexriscv cpuConfigFile /home/user/Downloads/VexRiscv/cpu0.yaml
Debug: 142 9 command.c:143 script_debug(): command - ocd_vexriscv ocd_vexriscv cpuConfigFile /home/user/Downloads/VexRiscv/cpu0.yaml
Debug: 144 9 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_poll_period 50
Debug: 145 9 command.c:143 script_debug(): command - poll_period ocd_poll_period 50
Info : 147 9 server.c:761 handle_poll_period_command(): set servers polling period to 50ms
Debug: 148 9 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_init
Debug: 149 9 command.c:143 script_debug(): command - init ocd_init
Debug: 151 9 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_target init
Debug: 152 9 command.c:143 script_debug(): command - ocd_target ocd_target init
Debug: 154 9 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_target names
Debug: 155 9 command.c:143 script_debug(): command - ocd_target ocd_target names
Debug: 156 9 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 cget -event gdb-flash-erase-start
Debug: 157 10 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 cget -event gdb-flash-erase-start
Debug: 158 10 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 configure -event gdb-flash-erase-start reset init
Debug: 159 10 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 configure -event gdb-flash-erase-start reset init
Debug: 160 10 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 cget -event gdb-flash-write-end
Debug: 161 10 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 cget -event gdb-flash-write-end
Debug: 162 10 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 configure -event gdb-flash-write-end reset halt
Debug: 163 10 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 configure -event gdb-flash-write-end reset halt
Debug: 164 10 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 cget -event gdb-attach
Debug: 165 10 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 cget -event gdb-attach
Debug: 166 10 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 configure -event gdb-attach halt
Debug: 167 10 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 configure -event gdb-attach halt
Debug: 168 10 target.c:1395 handle_target_init_command(): Initializing targets...
Debug: 169 10 vexriscv.c:511 vexriscv_init_target(): vexriscv_init_target

Debug: 170 10 vexriscv.c:512 vexriscv_init_target(): vexriscv_init_target
Debug: 171 10 vexriscv.c:322 vexriscv_build_reg_cache(): -
Debug: 172 11 command.c:364 register_command_handler(): registering 'ocd_target_request'...
Debug: 173 11 command.c:364 register_command_handler(): registering 'ocd_trace'...
Debug: 174 11 command.c:364 register_command_handler(): registering 'ocd_trace'...
Debug: 175 11 command.c:364 register_command_handler(): registering 'ocd_fast_load_image'...
Debug: 176 12 command.c:364 register_command_handler(): registering 'ocd_fast_load'...
Debug: 177 12 command.c:364 register_command_handler(): registering 'ocd_profile'...
Debug: 178 12 command.c:364 register_command_handler(): registering 'ocd_virt2phys'...
Debug: 179 12 command.c:364 register_command_handler(): registering 'ocd_reg'...
Debug: 180 12 command.c:364 register_command_handler(): registering 'ocd_poll'...
Debug: 181 12 command.c:364 register_command_handler(): registering 'ocd_wait_halt'...
Debug: 182 12 command.c:364 register_command_handler(): registering 'ocd_halt'...
Debug: 183 12 command.c:364 register_command_handler(): registering 'ocd_resume'...
Debug: 184 12 command.c:364 register_command_handler(): registering 'ocd_reset'...
Debug: 185 12 command.c:364 register_command_handler(): registering 'ocd_soft_reset_halt'...
Debug: 186 12 command.c:364 register_command_handler(): registering 'ocd_step'...
Debug: 187 12 command.c:364 register_command_handler(): registering 'ocd_mdd'...
Debug: 188 12 command.c:364 register_command_handler(): registering 'ocd_mdw'...
Debug: 189 12 command.c:364 register_command_handler(): registering 'ocd_mdh'...
Debug: 190 12 command.c:364 register_command_handler(): registering 'ocd_mdb'...
Debug: 191 12 command.c:364 register_command_handler(): registering 'ocd_mwd'...
Debug: 192 12 command.c:364 register_command_handler(): registering 'ocd_mww'...
Debug: 193 12 command.c:364 register_command_handler(): registering 'ocd_mwh'...
Debug: 194 12 command.c:364 register_command_handler(): registering 'ocd_mwb'...
Debug: 195 12 command.c:364 register_command_handler(): registering 'ocd_bp'...
Debug: 196 12 command.c:364 register_command_handler(): registering 'ocd_rbp'...
Debug: 197 12 command.c:364 register_command_handler(): registering 'ocd_wp'...
Debug: 198 12 command.c:364 register_command_handler(): registering 'ocd_rwp'...
Debug: 199 12 command.c:364 register_command_handler(): registering 'ocd_load_image'...
Debug: 200 12 command.c:364 register_command_handler(): registering 'ocd_dump_image'...
Debug: 201 12 command.c:364 register_command_handler(): registering 'ocd_verify_image_checksum'...
Debug: 202 12 command.c:364 register_command_handler(): registering 'ocd_verify_image'...
Debug: 203 12 command.c:364 register_command_handler(): registering 'ocd_test_image'...
Debug: 204 12 command.c:364 register_command_handler(): registering 'ocd_reset_nag'...
Debug: 205 12 command.c:364 register_command_handler(): registering 'ocd_ps'...
Debug: 206 12 command.c:364 register_command_handler(): registering 'ocd_test_mem_access'...
Debug: 207 12 jlink.c:553 jlink_init(): Using libjaylink 0.2.0-git-8645845 (compiled with 0.2.0-git-8645845).
Debug: 208 23 jlink.c:532 jaylink_log_handler(): Found device (VID:PID = 1366:0101, bus:address = 001:020).
Debug: 209 24 jlink.c:532 jaylink_log_handler(): Device: USB address = 0.
Debug: 210 24 jlink.c:532 jaylink_log_handler(): Device: Serial number = 269401883.
Debug: 211 24 jlink.c:532 jaylink_log_handler(): Allocating new device instance.
Debug: 212 24 jlink.c:532 jaylink_log_handler(): Found 1 USB device(s).
Debug: 213 24 jlink.c:532 jaylink_log_handler(): Trying to open device (bus:address = 001:020).
Debug: 214 24 jlink.c:532 jaylink_log_handler(): Using endpoint 81 (IN) and 01 (OUT).
Debug: 215 24 jlink.c:532 jaylink_log_handler(): Device opened successfully.
Info : 223 25 jlink.c:670 jlink_init(): J-Link V9 compiled Apr 20 2018 16:47:26
Info : 236 25 jlink.c:711 jlink_init(): Hardware version: 9.40
Info : 245 25 jlink.c:753 jlink_init(): VTarget = 3.293 V
Debug: 251 26 jlink.c:532 jaylink_log_handler(): Last read operation left 16 bytes in the buffer.
Debug: 261 26 jlink.c:905 jlink_reset(): TRST: 0, SRST: 0.
Debug: 281 30 core.c:1612 adapter_khz_to_speed(): convert khz to interface specific speed value
Debug: 282 30 core.c:1615 adapter_khz_to_speed(): have interface set up
Debug: 289 30 core.c:1612 adapter_khz_to_speed(): convert khz to interface specific speed value
Debug: 290 30 core.c:1615 adapter_khz_to_speed(): have interface set up
Info : 291 30 core.c:1394 adapter_init(): clock speed 400 kHz
Debug: 292 30 openocd.c:142 handle_init_command(): Debug Adapter init complete
Debug: 293 30 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_transport init
Debug: 294 30 command.c:143 script_debug(): command - ocd_transport ocd_transport init
Debug: 296 30 transport.c:239 handle_transport_init(): handle_transport_init
Debug: 297 30 jlink.c:905 jlink_reset(): TRST: 0, SRST: 0.
Debug: 302 31 core.c:729 jtag_add_reset(): SRST line released
Debug: 303 31 core.c:753 jtag_add_reset(): TRST line released
Debug: 304 31 core.c:327 jtag_call_event_callbacks(): jtag event: TAP reset
Debug: 306 550 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_jtag arp_init
Debug: 307 550 command.c:143 script_debug(): command - ocd_jtag ocd_jtag arp_init
Debug: 308 550 core.c:1407 jtag_init_inner(): Init JTAG chain
Debug: 309 550 core.c:327 jtag_call_event_callbacks(): jtag event: TAP reset
Debug: 319 551 core.c:1060 jtag_examine_chain(): DR scan interrogation for IDCODE/BYPASS
Debug: 320 551 core.c:327 jtag_call_event_callbacks(): jtag event: TAP reset
Debug: 330 553 jep106.c:33 jep106_manufacturer(): BUG: Caller passed out-of-range JEP106 ID!
Info : 331 553 core.c:959 jtag_examine_chain_display(): JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (<invalid>), part: 0x0001, ver: 0x1)
Debug: 332 553 core.c:1190 jtag_validate_ircapture(): IR capture validation scan
Debug: 342 554 core.c:1248 jtag_validate_ircapture(): fpga_spinal.bridge: IR capture 0x01
Debug: 343 554 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_dap init
Debug: 344 554 command.c:143 script_debug(): command - ocd_dap ocd_dap init
Debug: 346 554 arm_dap.c:105 dap_init_all(): Initializing all DAPs ...
Debug: 347 554 openocd.c:159 handle_init_command(): Examining targets...
Debug: 348 554 target.c:1581 target_call_event_callbacks(): target event 17 (examine-start)
Debug: 349 554 vexriscv.c:1510 vexriscv_examine(): vexriscv_examine
Debug: 350 554 vexriscv.c:820 vexriscv_assert_reset(): vexriscv_assert_reset

Debug: 369 555 vexriscv.c:835 vexriscv_assert_reset(): vexriscv_assert_reset
Debug: 370 555 vexriscv.c:842 vexriscv_deassert_reset(): vexriscv_deassert_reset

Debug: 389 557 vexriscv.c:851 vexriscv_deassert_reset(): vexriscv_deassert_reset
Debug: 399 558 vexriscv.c:1533 vexriscv_examine(): Target is halted
Debug: 400 558 target.c:1581 target_call_event_callbacks(): target event 18 (examine-end)
Debug: 401 558 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_flash init
Debug: 402 558 command.c:143 script_debug(): command - ocd_flash ocd_flash init
Debug: 413 559 tcl.c:1224 handle_flash_init_command(): Initializing flash devices...
Debug: 414 559 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_mflash init
Debug: 415 559 command.c:143 script_debug(): command - ocd_mflash ocd_mflash init
Debug: 426 560 mflash.c:1377 handle_mflash_init_command(): Initializing mflash devices...
Debug: 427 560 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_nand init
Debug: 428 560 command.c:143 script_debug(): command - ocd_nand ocd_nand init
Debug: 439 561 tcl.c:497 handle_nand_init_command(): Initializing NAND devices...
Debug: 440 561 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_pld init
Debug: 441 561 command.c:143 script_debug(): command - ocd_pld ocd_pld init
Debug: 452 562 pld.c:205 handle_pld_init_command(): Initializing PLDs...
Debug: 453 562 gdb_server.c:3393 gdb_target_start(): starting gdb server for fpga_spinal.cpu0 on 3333
Info : 454 562 server.c:311 add_service(): Listening on port 3333 for gdb connections
Debug: 455 562 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_soft_reset_halt
Debug: 456 562 command.c:143 script_debug(): command - soft_reset_halt ocd_soft_reset_halt
User : 467 563 target.c:3044 handle_soft_reset_halt_command(): requesting target halt and executing a soft reset
Debug: 468 563 vexriscv.c:1557 vexriscv_soft_reset_halt(): -
Info : 496 565 server.c:311 add_service(): Listening on port 6666 for tcl connections
Info : 497 565 server.c:311 add_service(): Listening on port 4444 for telnet connections
Debug: 498 565 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_init
Debug: 499 565 command.c:143 script_debug(): command - init ocd_init
Info : 1131 7559 server.c:100 add_connection(): accepting 'gdb' connection on tcp/3333
Debug: 1132 7559 breakpoints.c:354 breakpoint_clear_target_internal(): Delete all breakpoints for target: fpga_spinal.cpu0
Debug: 1133 7559 breakpoints.c:494 watchpoint_clear_target(): Delete all watchpoints for target: fpga_spinal.cpu0
Debug: 1134 7559 target.c:1581 target_call_event_callbacks(): target event 19 (gdb-attach)
Debug: 1135 7559 target.c:4535 target_handle_event(): target(0): fpga_spinal.cpu0 (vexriscv) event: 19 (gdb-attach) action: halt
Debug: 1136 7559 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_halt
Debug: 1137 7560 command.c:143 script_debug(): command - halt ocd_halt
Debug: 1148 7560 target.c:3018 handle_halt_command(): -
Debug: 1149 7560 vexriscv.c:729 vexriscv_halt(): target->state: halted
Debug: 1168 7562 gdb_server.c:1014 gdb_new_connection(): New GDB Connection: 1, Target fpga_spinal.cpu0, state: halted
Debug: 1169 7562 gdb_server.c:3160 gdb_input_inner(): received packet: 'qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+'
Debug: 1170 7562 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 0

Debug: 1171 7563 gdb_server.c:3160 gdb_input_inner(): received packet: 'vMustReplyEmpty'
Debug: 1172 7563 gdb_server.c:3160 gdb_input_inner(): received packet: 'QStartNoAckMode'
Debug: 1173 7563 gdb_server.c:639 gdb_get_packet_inner(): Received first acknowledgment after entering noack mode. Ignoring it.
Debug: 1174 7563 gdb_server.c:3160 gdb_input_inner(): received packet: 'Hg0'
Debug: 1175 7563 gdb_server.c:3160 gdb_input_inner(): received packet: 'qTStatus'
Debug: 1176 7563 gdb_server.c:3160 gdb_input_inner(): received packet: '?'
Debug: 1177 7564 gdb_server.c:3160 gdb_input_inner(): received packet: 'qXfer:threads:read::0,fff'
Debug: 1178 7564 gdb_server.c:3160 gdb_input_inner(): received packet: 'Hc-1'
Debug: 1179 7564 gdb_server.c:3160 gdb_input_inner(): received packet: 'qC'
Debug: 1180 7564 gdb_server.c:3160 gdb_input_inner(): received packet: 'qAttached'
Debug: 1181 7565 gdb_server.c:3160 gdb_input_inner(): received packet: 'qOffsets'
Debug: 1182 7565 gdb_server.c:3160 gdb_input_inner(): received packet: 'g'
Debug: 1183 7565 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 1

Debug: 1184 7566 gdb_server.c:3160 gdb_input_inner(): received packet: 'p20'
Debug: 1185 7566 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 0

Debug: 1195 7567 gdb_server.c:3160 gdb_input_inner(): received packet: 'qXfer:threads:read::0,fff'
Debug: 1196 7568 gdb_server.c:3160 gdb_input_inner(): received packet: 'qSymbol::'
Debug: 1215 7859 gdb_server.c:3160 gdb_input_inner(): received packet: 'qRcmd,72657365742068616c74'
Debug: 1225 7860 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_reset halt
Debug: 1226 7860 command.c:143 script_debug(): command - reset ocd_reset halt
Debug: 1237 7861 target.c:1599 target_call_reset_callbacks(): target reset 2 (halt)
Debug: 1238 7862 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_target names
Debug: 1239 7862 command.c:143 script_debug(): command - ocd_target ocd_target names
Debug: 1240 7862 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 invoke-event reset-start
Debug: 1241 7862 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 invoke-event reset-start
Debug: 1242 7862 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_transport select
Debug: 1243 7862 command.c:143 script_debug(): command - ocd_transport ocd_transport select
Debug: 1244 7862 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_jtag arp_init-reset
Debug: 1245 7862 command.c:143 script_debug(): command - ocd_jtag ocd_jtag arp_init-reset
Debug: 1246 7862 core.c:1521 jtag_init_reset(): Initializing with hard TRST+SRST reset
Debug: 1247 7862 core.c:742 jtag_add_reset(): JTAG reset with TLR instead of TRST
Debug: 1248 7862 core.c:327 jtag_call_event_callbacks(): jtag event: TAP reset
Debug: 1258 7863 core.c:1407 jtag_init_inner(): Init JTAG chain
Debug: 1259 7863 core.c:327 jtag_call_event_callbacks(): jtag event: TAP reset
Debug: 1269 7863 core.c:1060 jtag_examine_chain(): DR scan interrogation for IDCODE/BYPASS
Debug: 1270 7863 core.c:327 jtag_call_event_callbacks(): jtag event: TAP reset
Debug: 1280 7865 jep106.c:33 jep106_manufacturer(): BUG: Caller passed out-of-range JEP106 ID!
Info : 1281 7865 core.c:959 jtag_examine_chain_display(): JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (<invalid>), part: 0x0001, ver: 0x1)
Debug: 1282 7865 core.c:1190 jtag_validate_ircapture(): IR capture validation scan
Debug: 1292 7866 core.c:1248 jtag_validate_ircapture(): fpga_spinal.bridge: IR capture 0x01
Debug: 1293 7866 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_transport select
Debug: 1294 7866 command.c:143 script_debug(): command - ocd_transport ocd_transport select
Debug: 1295 7866 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 cget -chain-position
Debug: 1296 7866 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 cget -chain-position
Debug: 1297 7866 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_jtag tapisenabled fpga_spinal.bridge
Debug: 1298 7866 command.c:143 script_debug(): command - ocd_jtag ocd_jtag tapisenabled fpga_spinal.bridge
Debug: 1299 7866 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 invoke-event examine-start
Debug: 1300 7866 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 invoke-event examine-start
Debug: 1301 7866 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 arp_examine allow-defer
Debug: 1302 7866 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 arp_examine allow-defer
Debug: 1303 7866 vexriscv.c:1510 vexriscv_examine(): vexriscv_examine
Debug: 1304 7866 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 invoke-event examine-end
Debug: 1305 7867 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 invoke-event examine-end
Debug: 1306 7867 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 invoke-event reset-assert-pre
Debug: 1307 7867 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 invoke-event reset-assert-pre
Debug: 1308 7867 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_transport select
Debug: 1309 7867 command.c:143 script_debug(): command - ocd_transport ocd_transport select
Debug: 1310 7867 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 cget -chain-position
Debug: 1311 7867 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 cget -chain-position
Debug: 1312 7867 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_jtag tapisenabled fpga_spinal.bridge
Debug: 1313 7867 command.c:143 script_debug(): command - ocd_jtag ocd_jtag tapisenabled fpga_spinal.bridge
Debug: 1314 7867 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 arp_reset assert 1
Debug: 1315 7867 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 arp_reset assert 1
Debug: 1316 7867 target.c:1931 target_free_all_working_areas_restore(): freeing all working areas
Debug: 1317 7867 vexriscv.c:820 vexriscv_assert_reset(): vexriscv_assert_reset

Debug: 1336 7868 vexriscv.c:835 vexriscv_assert_reset(): vexriscv_assert_reset
Debug: 1337 7868 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 invoke-event reset-assert-post
Debug: 1338 7868 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 invoke-event reset-assert-post
Debug: 1339 7869 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 invoke-event reset-deassert-pre
Debug: 1340 7869 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 invoke-event reset-deassert-pre
Debug: 1341 7869 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_transport select
Debug: 1342 7869 command.c:143 script_debug(): command - ocd_transport ocd_transport select
Debug: 1343 7869 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 cget -chain-position
Debug: 1344 7869 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 cget -chain-position
Debug: 1345 7869 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_jtag tapisenabled fpga_spinal.bridge
Debug: 1346 7869 command.c:143 script_debug(): command - ocd_jtag ocd_jtag tapisenabled fpga_spinal.bridge
Debug: 1347 7869 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 arp_reset deassert 1
Debug: 1348 7869 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 arp_reset deassert 1
Debug: 1349 7869 target.c:1931 target_free_all_working_areas_restore(): freeing all working areas
Debug: 1350 7869 vexriscv.c:842 vexriscv_deassert_reset(): vexriscv_deassert_reset

Debug: 1369 7870 vexriscv.c:851 vexriscv_deassert_reset(): vexriscv_deassert_reset
Debug: 1370 7870 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 invoke-event reset-deassert-post
Debug: 1371 7871 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 invoke-event reset-deassert-post
Debug: 1372 7871 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_transport select
Debug: 1373 7871 command.c:143 script_debug(): command - ocd_transport ocd_transport select
Debug: 1374 7871 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 cget -chain-position
Debug: 1375 7871 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 cget -chain-position
Debug: 1376 7871 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_jtag tapisenabled fpga_spinal.bridge
Debug: 1377 7871 command.c:143 script_debug(): command - ocd_jtag ocd_jtag tapisenabled fpga_spinal.bridge
Debug: 1378 7871 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 was_examined
Debug: 1379 7871 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 was_examined
Debug: 1380 7871 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 arp_waitstate halted 1000
Debug: 1381 7871 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 arp_waitstate halted 1000
Debug: 1391 7872 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 curstate
Debug: 1392 7872 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 curstate
Debug: 1393 7872 command.c:143 script_debug(): command - ocd_command ocd_command type ocd_fpga_spinal.cpu0 invoke-event reset-end
Debug: 1394 7872 command.c:143 script_debug(): command - ocd_fpga_spinal.cpu0 ocd_fpga_spinal.cpu0 invoke-event reset-end
Debug: 1413 7961 gdb_server.c:3158 gdb_input_inner(): received packet: 'X80000000,0:<binary-data>'
Debug: 1414 7961 gdb_server.c:3158 gdb_input_inner(): received packet: 'X80000000,12c:<binary-data>'
Debug: 1415 7961 gdb_server.c:1584 gdb_write_memory_binary_packet(): addr: 0x80000000, len: 0x0000012c
Debug: 1416 7961 target.c:2138 target_write_buffer(): writing buffer of 300 byte at 0x80000000
Debug: 1417 7961 vexriscv.c:1146 vexriscv_write_memory(): SAVED : 18

Debug: 1420 7962 jlink.c:532 jaylink_log_handler(): Adjusted buffer size to 4096 bytes.
Debug: 1439 8016 gdb_server.c:3158 gdb_input_inner(): received packet: 'X8000012c,b4c:<binary-data>'
Debug: 1440 8017 gdb_server.c:1584 gdb_write_memory_binary_packet(): addr: 0x8000012c, len: 0x00000b4c
Debug: 1441 8017 target.c:2138 target_write_buffer(): writing buffer of 2892 byte at 0x8000012c
Debug: 1442 8019 vexriscv.c:1146 vexriscv_write_memory(): SAVED : 29d

Debug: 1541 8421 gdb_server.c:3158 gdb_input_inner(): received packet: 'X80000c78,1d8:<binary-data>'
Debug: 1542 8421 gdb_server.c:1584 gdb_write_memory_binary_packet(): addr: 0x80000c78, len: 0x000001d8
Debug: 1543 8421 target.c:2138 target_write_buffer(): writing buffer of 472 byte at 0x80000c78
Debug: 1544 8421 vexriscv.c:1146 vexriscv_write_memory(): SAVED : 34

Debug: 1566 8503 gdb_server.c:3158 gdb_input_inner(): received packet: 'X80000e50,1f0:<binary-data>'
Debug: 1567 8503 gdb_server.c:1584 gdb_write_memory_binary_packet(): addr: 0x80000e50, len: 0x000001f0
Debug: 1568 8503 target.c:2138 target_write_buffer(): writing buffer of 496 byte at 0x80000e50
Debug: 1569 8503 vexriscv.c:1146 vexriscv_write_memory(): SAVED : 75

Debug: 1590 8573 gdb_server.c:3158 gdb_input_inner(): received packet: 'X80001040,8:<binary-data>'
Debug: 1591 8573 gdb_server.c:1584 gdb_write_memory_binary_packet(): addr: 0x80001040, len: 0x00000008
Debug: 1592 8573 target.c:2138 target_write_buffer(): writing buffer of 8 byte at 0x80001040
Debug: 1602 8576 gdb_server.c:3160 gdb_input_inner(): received packet: 'P20=00000080'
Debug: 1603 8576 gdb_server.c:1349 gdb_set_register_packet(): -
Debug: 1604 8576 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 0

Debug: 1614 8667 gdb_server.c:3160 gdb_input_inner(): received packet: 'qXfer:threads:read::0,fff'
Debug: 1615 8688 gdb_server.c:3160 gdb_input_inner(): received packet: 'p342'
Debug: 1616 8688 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 0

Debug: 1626 8690 gdb_server.c:3160 gdb_input_inner(): received packet: 'm800005b8,4'
Debug: 1627 8690 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x00000000800005b8, len: 0x00000004
Debug: 1628 8690 target.c:2200 target_read_buffer(): reading buffer of 4 byte at 0x800005b8
Debug: 1638 8701 gdb_server.c:3160 gdb_input_inner(): received packet: 'm80000124,4'
Debug: 1639 8701 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000080000124, len: 0x00000004
Debug: 1640 8701 target.c:2200 target_read_buffer(): reading buffer of 4 byte at 0x80000124
Debug: 1650 8707 gdb_server.c:3160 gdb_input_inner(): received packet: 'm80000464,4'
Debug: 1651 8707 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000080000464, len: 0x00000004
Debug: 1652 8707 target.c:2200 target_read_buffer(): reading buffer of 4 byte at 0x80000464
Debug: 1662 8711 gdb_server.c:3160 gdb_input_inner(): received packet: 'm80000ccc,4'
Debug: 1663 8711 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000080000ccc, len: 0x00000004
Debug: 1664 8711 target.c:2200 target_read_buffer(): reading buffer of 4 byte at 0x80000ccc
Debug: 1674 8714 gdb_server.c:3160 gdb_input_inner(): received packet: 'm800000b0,4'
Debug: 1675 8714 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x00000000800000b0, len: 0x00000004
Debug: 1676 8714 target.c:2200 target_read_buffer(): reading buffer of 4 byte at 0x800000b0
Debug: 1695 8832 gdb_server.c:3160 gdb_input_inner(): received packet: 'm80000000,40'
Debug: 1696 8832 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000080000000, len: 0x00000040
Debug: 1697 8832 target.c:2200 target_read_buffer(): reading buffer of 64 byte at 0x80000000
Debug: 1707 8852 gdb_server.c:3160 gdb_input_inner(): received packet: 'm80000040,40'
Debug: 1708 8852 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000080000040, len: 0x00000040
Debug: 1709 8852 target.c:2200 target_read_buffer(): reading buffer of 64 byte at 0x80000040
Debug: 2295 15306 gdb_server.c:3160 gdb_input_inner(): received packet: 'Z0,800000b0,4'
Debug: 2296 15306 gdb_server.c:1643 gdb_breakpoint_watchpoint_packet(): -
Debug: 2297 15306 vexriscv.c:1278 vexriscv_add_breakpoint(): Adding breakpoint: addr 0x800000b0, len 4, type 1, set: 0, id: 0
Debug: 2334 15312 breakpoints.c:104 breakpoint_add_internal(): added software breakpoint at 0x800000b0 of length 0x00000004, (BPID: 0)
Debug: 2335 15312 gdb_server.c:3160 gdb_input_inner(): received packet: 'vCont?'
Debug: 2336 15312 gdb_server.c:3160 gdb_input_inner(): received packet: 'vCont;c'
Debug: 2337 15312 gdb_server.c:2729 gdb_handle_vcont_packet(): target fpga_spinal.cpu0 continue
Debug: 2338 15312 target.c:1581 target_call_event_callbacks(): target event 3 (resume-start)
Debug: 2339 15312 vexriscv.c:1422 vexriscv_resume_or_step(): Addr: 0x0, stepping: no, handle breakpoints no

Debug: 2340 15312 target.c:1931 target_free_all_working_areas_restore(): freeing all working areas
Debug: 2341 15312 vexriscv.c:685 vexriscv_restore_context(): -
Debug: 2360 15314 target.c:1581 target_call_event_callbacks(): target event 2 (resumed)
Debug: 2361 15314 vexriscv.c:1479 vexriscv_resume_or_step(): Target resumed at 0x80000000
Debug: 2362 15314 target.c:1581 target_call_event_callbacks(): target event 4 (resume-end)
Debug: 2363 15314 target.c:1581 target_call_event_callbacks(): target event 5 (gdb-start)
Debug: 2373 15415 vexriscv.c:710 vexriscv_debug_entry(): -
Debug: 2383 15416 vexriscv.c:636 vexriscv_save_context(): -
Debug: 2403 15440 target.c:1581 target_call_event_callbacks(): target event 0 (gdb-halt)
Debug: 2404 15441 target.c:1581 target_call_event_callbacks(): target event 1 (halted)
Debug: 2405 15441 target.c:1581 target_call_event_callbacks(): target event 6 (gdb-end)
Debug: 2406 15441 gdb_server.c:3160 gdb_input_inner(): received packet: 'p20'
Debug: 2407 15441 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 0

Debug: 2408 15441 gdb_server.c:3160 gdb_input_inner(): received packet: 'qXfer:threads:read::0,fff'
Debug: 2409 15442 gdb_server.c:3160 gdb_input_inner(): received packet: 'z0,800000b0,4'
Debug: 2410 15442 gdb_server.c:1643 gdb_breakpoint_watchpoint_packet(): -
Debug: 2411 15442 vexriscv.c:1358 vexriscv_remove_breakpoint(): Removing breakpoint: addr 0x800000b0, len 4, type 1, set: 0, id: 0
Debug: 2430 15445 breakpoints.c:307 breakpoint_free(): free BPID: 0 --> 0
Debug: 2431 15447 gdb_server.c:3160 gdb_input_inner(): received packet: 'qXfer:threads:read::0,fff'
Debug: 2432 15447 gdb_server.c:3160 gdb_input_inner(): received packet: 'g'
Debug: 2433 15447 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 1

Debug: 2434 15511 gdb_server.c:3160 gdb_input_inner(): received packet: 'm80000080,40'
Debug: 2435 15511 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000080000080, len: 0x00000040
Debug: 2436 15511 target.c:2200 target_read_buffer(): reading buffer of 64 byte at 0x80000080
Debug: 2455 15532 gdb_server.c:3160 gdb_input_inner(): received packet: 'm800000c0,40'
Debug: 2456 15532 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x00000000800000c0, len: 0x00000040
Debug: 2457 15532 target.c:2200 target_read_buffer(): reading buffer of 64 byte at 0x800000c0
Debug: 2467 15554 gdb_server.c:3160 gdb_input_inner(): received packet: 'm80000100,40'
Debug: 2468 15554 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000080000100, len: 0x00000040
Debug: 2469 15554 target.c:2200 target_read_buffer(): reading buffer of 64 byte at 0x80000100
Debug: 2821 19511 gdb_server.c:3160 gdb_input_inner(): received packet: 'vCont;s:0;c:0'
Debug: 2822 19511 gdb_server.c:2812 gdb_handle_vcont_packet(): request to step current core only
Debug: 2823 19511 gdb_server.c:2820 gdb_handle_vcont_packet(): target fpga_spinal.cpu0 single-step thread 0
Debug: 2824 19511 target.c:1581 target_call_event_callbacks(): target event 5 (gdb-start)
Debug: 2825 19511 vexriscv.c:1422 vexriscv_resume_or_step(): Addr: 0x0, stepping: yes, handle breakpoints no

Debug: 2826 19511 target.c:1931 target_free_all_working_areas_restore(): freeing all working areas
Debug: 2827 19511 vexriscv.c:685 vexriscv_restore_context(): -
Debug: 2846 19514 target.c:1581 target_call_event_callbacks(): target event 2 (resumed)
Debug: 2847 19514 vexriscv.c:1479 vexriscv_resume_or_step(): Target resumed at 0x800000b0
Debug: 2857 19514 vexriscv.c:710 vexriscv_debug_entry(): -
Debug: 2867 19515 vexriscv.c:636 vexriscv_save_context(): -
Debug: 2886 19539 target.c:1581 target_call_event_callbacks(): target event 0 (gdb-halt)
Debug: 2887 19539 target.c:1581 target_call_event_callbacks(): target event 1 (halted)
Debug: 2888 19539 target.c:1581 target_call_event_callbacks(): target event 6 (gdb-end)
Debug: 2898 19540 gdb_server.c:3160 gdb_input_inner(): received packet: 'p20'
Debug: 2899 19540 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 0

Debug: 2909 19541 gdb_server.c:3160 gdb_input_inner(): received packet: 'g'
Debug: 2910 19541 vexriscv.c:1249 vexriscv_get_gdb_reg_list(): vexriscv_get_gdb_reg_list 1

Debug: 2911 19541 gdb_server.c:3160 gdb_input_inner(): received packet: 'qXfer:threads:read::0,fff'
Debug: 2912 19541 gdb_server.c:3160 gdb_input_inner(): received packet: 'qXfer:threads:read::0,fff'
Debug: 2913 19593 gdb_server.c:3160 gdb_input_inner(): received packet: 'm80,40'
Debug: 2914 19593 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000000000080, len: 0x00000040
Debug: 2915 19593 target.c:2200 target_read_buffer(): reading buffer of 64 byte at 0x00000080
Debug: 2925 19610 gdb_server.c:3160 gdb_input_inner(): received packet: 'mc0,40'
Debug: 2926 19610 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x00000000000000c0, len: 0x00000040
Debug: 2927 19610 target.c:2200 target_read_buffer(): reading buffer of 64 byte at 0x000000c0
Debug: 2937 19626 gdb_server.c:3160 gdb_input_inner(): received packet: 'm100,40'
Debug: 2938 19626 gdb_server.c:1444 gdb_read_memory_packet(): addr: 0x0000000000000100, len: 0x00000040
Debug: 2939 19626 target.c:2200 target_read_buffer(): reading buffer of 64 byte at 0x00000100

GDB not working with FPGA

Hello all,
I'm having a little problem with the FPGA implementation to test functionality on sillicon and the compilation is completely fine but when it comes to interfacing with the board.
The OpenOCD can connect, I'm using the command:

openocd -f tcl/interface/altera-usb-blaster.cfg -c "set BRIEY_CPU0_YAML /home/aaron/VexRiscv/cpu0.yaml" -f tcl/target/briey.cfg

However, when then trying to connect to the GDB with:

target remote localhost:3333

It times out, am I missing something? I'm using the DE0-nano development board.

Briey simulation regression

Hi,

I am working on porting Briey soc to Xilinx fpga board and have issue with sdram so I use simulator to extract reference waveform.
I noticed a regression in briey soc simulation with d957934

When using simulator it's no longer possible to load/execute code in sdram. Internal ram load/exec is fine.
Tested with latest SpinalHDL, VexRiscSoftware (uart example) and gcc 6.1.0 (self build rv32i toolchain).

Does it use physical address or virtual address?

We are looking for a microcontroller that uses physical address access, so we can reduce some implementation complexity. I am wondering whether the generic VexRiscv core uses physical address or virtual address?

What is the difference between iCE40HX8K-EVB and iCE40-hx8k_breakout_board

My board says;

iCE40-HX8K Breakout Board
Rev A P/N: ICE40HX8K-B-EVN

Not sure which one that is... However iCE40HX8K-EVB uses iceprogduino while iCE40-hx8k_breakout_board uses iceprog which works with my board.

If this is all correct, once you run iceprog what is suppose to happen?

I'll try and send an updated README once I have this all figured out...

Processor not writing to data memory

Hello everyone. I seem to have encountered a bug when I try to use the VexRiscv processor in a Vivado block design. The benchmarks dhrystone and towers from https://github.com/riscv/riscv-tests/tree/master/benchmarks work fine, however when I try to run the multiply benchmark, the processor only reads from the data memory and never writes. This gets even weirder because the addresses that it reads, are the addresses that it shall write to. The dBusAxi is connected to an AXI Bram controller IP which is connected to a block memory generator with 32KiB of memory. I attached the data that I gathered with an ILA core and the assembler generated by the RISC-V GCC. Please let me know if you need any more info.

Cheers!
multiply_vexriscv.zip
multiply_vexriscv.txt

Edit: I should also mention that I use commit 6402255 and the VexRiscvAxi4WithIntegratedJtag configuration because it does not work for me in newer versions.

GenFullNoMmuNoCache throws exception with fence.i and fence

I generated a Vex core with the GenFullNoMmuNoCache option. I am trying to compile this program:

https://github.com/gcc-mirror/gcc/blob/master/gcc/testsuite/gcc.c-torture/execute/931002-1.c

which generates a fence.i before the call to t1(). When the core hits this, it jumps to the trap location with CsrPlugin_mcause_exceptionCode = 2

How can I reconfigure vex to treat fence.i and fence as nop. Or alternatively is there a gcc compiler flag to prevent it from use fence.i instructions. Thanks.

VexRiscv configuration doesn't trap on misaligned branch

When I run the riscv-formal testsuite, the branch instructions are all failing.

Branches to locations for which bit [1] is set are expected to result in a trap, but they don't trap on the VexRiscv.

Repro instructions:

--- a/src/main/scala/vexriscv/demo/GenFullNoMmuNoDbgNoCache.scala
+++ b/src/main/scala/vexriscv/demo/GenFullNoMmuNoDbgNoCache.scala
@@ -12,6 +12,8 @@ object GenFullNoMmuNoDbgNoCache extends App{
   def cpu() = new VexRiscv(
     config = VexRiscvConfig(
       plugins = List(
+        new FormalPlugin,
+        new HaltOnExceptionPlugin,
         new PcManagerSimplePlugin(
           resetVector = 0x00000000l,
           relaxedPcCalculation = false
@@ -52,7 +54,7 @@ object GenFullNoMmuNoDbgNoCache extends App{
         //new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
         new BranchPlugin(
           earlyBranch = false,
-          catchAddressMisaligned = false,
+          catchAddressMisaligned = true,
           prediction = STATIC
         ),
         new YamlPlugin("cpu0.yaml")

In checks.cfg, change the insn depth from 20 to 14 to get an acceptable runtime.

python3 ../../checks/genchecks.py
cd ./checks
sby -f insn_beq_ch0.sby
  • Observe the following result:
SBY 23:19:55 [insn_beq_ch0] engine_0: ##   0:00:02  Checking assumptions in step 14..
SBY 23:19:56 [insn_beq_ch0] engine_0: ##   0:00:03  Checking assertions in step 14..
SBY 23:19:59 [insn_beq_ch0] engine_0: ##   0:00:07  BMC failed!
SBY 23:19:59 [insn_beq_ch0] engine_0: ##   0:00:07  Assert failed in rvfi_testbench: rvfi_testbench.sv:17|rvfi_insn_check.sv:137
SBY 23:19:59 [insn_beq_ch0] engine_0: ##   0:00:07  Writing trace to VCD file: engine_0/trace.vcd
SBY 23:20:01 [insn_beq_ch0] engine_0: ##   0:00:09  Writing trace to Verilog testbench: engine_0/trace_tb.v
SBY 23:20:01 [insn_beq_ch0] engine_0: ##   0:00:09  Vlog top module 'wrapper.uut' not found: no cell 'wrapper' in module 'rvfi_testbench'
SBY 23:20:01 [insn_beq_ch0] engine_0: ##   0:00:09  Writing trace to constraints file: engine_0/trace.smtc
SBY 23:20:01 [insn_beq_ch0] engine_0: ##   0:00:09  Status: FAILED (!)
SBY 23:20:01 [insn_beq_ch0] engine_0: finished (returncode=1)
SBY 23:20:01 [insn_beq_ch0] engine_0: Status returned by engine: FAIL

The failure is because the CPU doesn't assert trap when it jumps to an address that has bit [1] set.

A more complete archive is here: fail.tar.gz

sbt "run-main vexriscv.demo.MuraxWithRamInit" does nothing?

Running sbt "run-main vexriscv.demo.MuraxWithRamInit" produces the following output;

[info] Loading project definition from github/SpinalHDL/VexRiscv/project
[info] Set current project to VexRiscv (in build file:github/SpinalHDL/VexRiscv/)
[info] Running vexriscv.demo.MuraxWithRamInit 
[info] [Runtime] SpinalHDL v1.1.5    git head : 0310b2489a097f2b9de5535e02192d9ddd2764ae
[info] [Runtime] JVM max memory : 15567.3MiB
[info] [Runtime] Current date : 2018.07.20 18:00:23
[info] [Progress] at 0.000 : Elaborate components
[info] [Progress] at 0.792 : Checks and transforms
[info] [Progress] at 1.069 : Generate Verilog
[info] [Progress] at 1.073 :           emit BufferCC
[info] [Progress] at 1.093 :         emit BufferCC_1
[info] [Progress] at 1.093 :         emit UartCtrlTx
[info] [Progress] at 1.103 :         emit UartCtrlRx
[info] [Progress] at 1.110 :       emit FlowCCByToggle
[info] [Progress] at 1.112 :       emit UartCtrl
[info] [Progress] at 1.114 :       emit StreamFifo
[info] [Warning] memReadSync with dontCare is as readFirst into Verilog Mem.readSync(x)
[info] [Progress] at 1.121 :       emit StreamFifo_1
[info] [Warning] memReadSync with dontCare is as readFirst into Verilog Mem.readSync(x)
[info] [Progress] at 1.126 :       emit Prescaler
[info] [Progress] at 1.126 :       emit Timer
[info] [Progress] at 1.127 :       emit Timer_1
[info] [Progress] at 1.129 :       emit InterruptCtrl
[info] [Progress] at 1.129 :     emit BufferCC_2
[info] [Progress] at 1.130 :     emit MuraxMasterArbiter
[info] [Progress] at 1.132 :     emit VexRiscv
[info] [Warning] memReadSync with dontCare is as readFirst into Verilog Mem.readSync(x)
[info] [Warning] memReadSync with dontCare is as readFirst into Verilog Mem.readSync(x)
[info] [Progress] at 1.181 :     emit JtagBridge
[info] [Progress] at 1.185 :     emit SystemDebugger
[info] [Progress] at 1.187 :     emit MuraxSimpleBusRam
[info] [Progress] at 1.226 :     emit MuraxSimpleBusToApbBridge
[info] [Progress] at 1.227 :     emit Apb3Gpio
[info] [Progress] at 1.228 :     emit Apb3UartCtrl
[info] [Progress] at 1.232 :     emit MuraxApb3Timer
[info] [Progress] at 1.235 :     emit Apb3Decoder
[info] [Progress] at 1.236 :     emit Apb3Router
[info] [Progress] at 1.238 :   emit Murax
[info] [Warning] 52 signals were pruned. You can call printPruned on the backend report to get more informations.
[info] [Info] Number of registers : 1395
[info] [Done] at 1.246
[success] Total time: 2 s, completed Jul 20, 2018 6:00:24 PM

But it was my understanding that I should

Will blink led and echo UART RX to UART TX (in the verilator sim, type some text and press enter to send UART frames to the Murax RX pin).

Interactive debug of the simulated CPU

Hello
I have a question to ask,I am testing the Interactive debug of the simulated CPU .but failed.
log information is at fllowing

sbt "run-main vexriscv.demo.GenFull"
cd src/test/cpp/regression
make run DEBUG_PLUGIN_EXTERNAL=yes

peter@ubuntu:~/workspace/VexRiscv/src/test/cpp/regression$ make run DEBUG_PLUGIN_EXTERNAL=yes

verilator -cc ../../../../VexRiscv.v -O3 -CFLAGS -std=c++11 -LDFLAGS -pthread -CFLAGS -DIBUS_CACHED -CFLAGS -DDBUS_CACHED -CFLAGS -DREDO=10 -CFLAGS -pthread -CFLAGS -DTHREAD_COUNT=4 -CFLAGS -DDHRYSTONE -CFLAGS -DCSR -CFLAGS -DISA_TEST -CFLAGS -DMMU -CFLAGS -DMUL -CFLAGS -DDIV -CFLAGS -DDEBUG_PLUGIN -CFLAGS -DDEBUG_PLUGIN_STD -CFLAGS -DDEBUG_PLUGIN_EXTERNAL -CFLAGS -DTRACE_START=0 --gdbbt -Wno-UNOPTFLAT -Wno-WIDTH --x-assign unique --exe main.cpp
No stack.
make -j -C obj_dir/ -f VVexRiscv.mk VVexRiscv
make[1]: Entering directory '/home/peter/workspace/VexRiscv/src/test/cpp/regression/obj_dir'
g++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -Wno-char-subscripts -Wno-parentheses-equality -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -DCSR -DDBUS_CACHED -DDEBUG_PLUGIN -DDEBUG_PLUGIN_EXTERNAL -DDEBUG_PLUGIN_STD -DDHRYSTONE -DDIV -DIBUS_CACHED -DISA_TEST -DMMU -DMUL -DREDO=10 -DTHREAD_COUNT=4 -DTRACE_START=0 -pthread -std=c++11 -c -o main.o ../main.cpp
/usr/bin/perl /usr/local/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include VVexRiscv.cpp VVexRiscv_VexRiscv.cpp > VVexRiscv__ALLcls.cpp
/usr/bin/perl /usr/local/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include VVexRiscv__Dpi.cpp VVexRiscv__Syms.cpp > VVexRiscv__ALLsup.cpp
g++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -Wno-char-subscripts -Wno-parentheses-equality -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -DCSR -DDBUS_CACHED -DDEBUG_PLUGIN -DDEBUG_PLUGIN_EXTERNAL -DDEBUG_PLUGIN_STD -DDHRYSTONE -DDIV -DIBUS_CACHED -DISA_TEST -DMMU -DMUL -DREDO=10 -DTHREAD_COUNT=4 -DTRACE_START=0 -pthread -std=c++11 -c -o VVexRiscv__ALLsup.o VVexRiscv__ALLsup.cpp
g++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -Wno-char-subscripts -Wno-parentheses-equality -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -DCSR -DDBUS_CACHED -DDEBUG_PLUGIN -DDEBUG_PLUGIN_EXTERNAL -DDEBUG_PLUGIN_STD -DDHRYSTONE -DDIV -DIBUS_CACHED -DISA_TEST -DMMU -DMUL -DREDO=10 -DTHREAD_COUNT=4 -DTRACE_START=0 -pthread -std=c++11 -c -o VVexRiscv__ALLcls.o VVexRiscv__ALLcls.cpp
Archiving VVexRiscv__ALL.a ...
ar r VVexRiscv__ALL.a VVexRiscv__ALLcls.o VVexRiscv__ALLsup.o
ranlib VVexRiscv__ALL.a
g++ main.o verilated.o verilated_dpi.o VVexRiscv__ALL.a -pthread -o VVexRiscv -lm -lstdc++ 2>&1 | c++filt
make[1]: Leaving directory '/home/peter/workspace/VexRiscv/src/test/cpp/regression/obj_dir'
./obj_dir/VVexRiscv
BOOT

#Then I did the following
src/openocd -c 'set VEXRISCV_YAML ../VexRiscv/cpu0.yaml' -f tcl/target/vexriscv_sim.cfg

peter@ubuntu:~/workspace/openocd_riscv$ src/openocd -c "set VEXRISCV_YAML ../VexRiscv/cpu0.yaml" -f tcl/target/vexriscv_sim.cfg

Open On-Chip Debugger 0.10.0+dev-00293-ga3421ba (2018-01-10-11:44)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
../VexRiscv/cpu0.yaml
Info : only one transport option; autoselect 'jtag'
adapter speed: 4000 kHz
adapter_nsrst_delay: 260
jtag_ntrst_delay: 250
Info : set servers polling period to 50ms
Info : clock speed 4000 kHz
Info : TAP fpga_spinal.bridge does not have IDCODE
Info : TAP auto0.tap does not have IDCODE
Info : TAP auto1.tap does not have IDCODE
Info : TAP auto2.tap does not have IDCODE
Info : TAP auto3.tap does not have IDCODE
Info : TAP auto4.tap does not have IDCODE
Info : TAP auto5.tap does not have IDCODE
Info : TAP auto6.tap does not have IDCODE
Info : TAP auto7.tap does not have IDCODE
Info : TAP auto8.tap does not have IDCODE
Info : TAP auto9.tap does not have IDCODE
Info : TAP auto10.tap does not have IDCODE
Info : TAP auto11.tap does not have IDCODE
Info : TAP auto12.tap does not have IDCODE
Info : TAP auto13.tap does not have IDCODE
Info : TAP auto14.tap does not have IDCODE
Info : TAP auto15.tap does not have IDCODE
Info : TAP auto16.tap does not have IDCODE
Info : TAP auto17.tap does not have IDCODE
Info : TAP auto18.tap does not have IDCODE
Info : TAP auto19.tap does not have IDCODE
Warn : Unexpected idcode after end of chain: 21 0xfffff800
Error: double-check your JTAG setup (interface, speed, ...)
Error: Trying to use configured scan chain anyway...
Error: fpga_spinal.bridge: IR capture error; saw 0x0f not 0x01
Warn : Bypassing JTAG setup events due to errors
requesting target halt and executing a soft reset

#Then VexRiscv log show CONNECTED

......
make[1]: Leaving directory '/home/peter/workspace/VexRiscv/src/test/cpp/regression/obj_dir'
./obj_dir/VVexRiscv
BOOT
CONNECTED

What should I do?

Can VexRISCV based SoC be made to fit on an iCE40 1k?

So, this is a pretty big challenge I think....

The iCE40 1K has the following resources;

  • 1280 Logic Cells
  • 64kbits Embedded RAM bits
  • 1 PLL

However, there might be hope, your stats seem to indicate the following;

VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) ->
  iCE40      -> 81 Mhz 1130 LC

VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) ->
  iCE40      -> 71 Mhz 1278 LC

But that is obviously only the CPU.

The SoC seems to use about double the LC;

Murax interlocked stages (0.45 DMIPS/Mhz) ->
  ICE40-HX   ->  51 Mhz 2402 LC (icestorm)

MuraxFast bypassed stages (0.65 DMIPS/Mhz) ->
  ICE40-HX   ->  50 Mhz, 2787 LC  (icestorm)

Thoughts?

Can't access the code memory when a breakpoint is set on it

Greetings!
I am basing my cybersecurity research on VexRiscV and need to build a firmware that can hash parts of itself. I noticed that the hash algorithm failed when a certain point in the code was reached and I noticed that this point had the same address as the breakpoint I had set for debugging. I've stripped away the hash code and tried this on a completely unmodified branch of VexRiscV (Murax, simulation only):

// Here we copy program code with a breakpoint
// into another part of the RAM.
uint8_t * ram_ptr = (uint8_t*) (0x80000450);
uint8_t arr [32] = {0}; 
for (int i = 0; i < 32; i++){
	arr[i] = ram_ptr[i];
}

I noticed that the word at the address where the breakpoint was set (0x80000454) was not copied correctly. Instead of the expected piece of RISC-V assembly, I got those four bytes: 0x73, 0x0, 0x10, 0x0. I've attached the full demo if you want to check this for yourself.
ram_err_demo.tar.gz

The steps I executed:

  • Built Murax using sbt
  • Started Verilator
  • Started gdb and connected to the remote target
  • Did monitor reset halt and load
  • Set a breakpoint at main.c:46 and continued
  • Printed arr

This is a pretty special use case but for me it is crucial that I can access the code memory and hash it without that glitch. Do you have any idea what could cause this? I will look into the debugging plugin myself and try to determine the reason but if you know it from the top of your head it would be a great help. If I can find a solution, I will inform you and create a pull request.

FPGA Flow

HI, Can you add FPGA flow for all these cores.

Problems when writing to memory

Hello, I have a little problem while using your processor and maybe you can point me into the right direction.
So consider the following setup: I use a PYNQ-Z1 board with a xc7z020clg400-1 FPGA from Xilinx. On this I have an instance of your VexRiscv, built with the AXI and JTAG extension (from your demo folder). The iBusAxi is connected to a AXI BRAM Controller which is connected to a Block Memory Generator with 16KiB memory. The dBusAxi is connected to a separate controller and a separate BRAM, therefore instruction and data memory are separated. The data memory is mapped to address 0x4000. So what I basically want to achieve, is to write the integer 0xDEADBEEF to the address 0x4000 (first position in data memory). I wrote a C program for that and compiled it with the riscv32-unknown-elf-gcc with march=rv32im and mabi=ilp32. The code is then turned into binary format by invoking riscv32-unknown-elf-objcopy -O binary [...]. The relevant assembler code looks like this:
`
lui a5,0x4

   10068:	fef42623          	sw	a5,-20(s0)

   1006c:	fec42783          	lw	a5,-20(s0)

   10070:	deadc737          	lui	a4,0xdeadc

   10074:	eef70713          	addi	a4,a4,-273 # deadbeef <__global_pointer$+0xdeaca573>

   10078:	00e7a023          	sw	a4,0(a5) # 4000 <_start-0xc054>

`
Now what happens is, that the processor writes to 0x4000 in the memory, but unfortunately it writes the bytes 0xFFFFFEEF. It would be nice if you could provide any idea what could be going wrong.
Cheers!

Unresolved dependency on eclipse plugin

When building I am getting error:

sbt run
...
[error] sbt.librarymanagement.ResolveException: unresolved dependency: com.typesafe.sbteclipse#sbteclipse-plugin;4.0.0: not found
...

Commenting out eclipse from build.sbt and plugins.sbt seems to fix it for me but I wonder what would be the correct way:

diff --git a/build.sbt b/build.sbt
index 038d4ca..69558d9 100644
--- a/build.sbt
+++ b/build.sbt
@@ -6,10 +6,10 @@ version := "1.0"
 
 scalaVersion := "2.11.8"
 
-EclipseKeys.withSource := true
+//EclipseKeys.withSource := true
 
 libraryDependencies ++= Seq(
   "com.github.spinalhdl" % "spinalhdl-core_2.11" % "0.10.15",

diff --git a/project/plugins.sbt b/project/plugins.sbt
index ef6ceea..e348df3 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,2 +1,2 @@
-addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")
+//addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")

Provide MMU / MemoryTranslatorPlugin example

VexRiscv implements a simple MMU. This MMU is effective, but nonstandard, and requires extended instructions to do refilling.

Would it be possible to give a simple example of how to use it? For example, how would mappings be added and removed in order to create a simple context switch for a protected memory operating system?

Source for muraxDemo.hex

Where is the source and makefile for https://github.com/SpinalHDL/VexRiscv/blob/master/src/main/ressource/hex/muraxDemo.hex?

https://github.com/SpinalHDL/VexRiscv/blob/master/src/main/c/murax/xipBootloader/demo.S looks as if it is doing something similar but does not copy the UART RX to TX, its makefile produces an elf file, but no hex file, and its elf file, demo.elf, is much small that muraxDemo.elf.

Apologies if I am missing something obvious - I have only just started looking at SpinalHDL.

Setup instructions: unable to build SpinalHDL

xobs@Pazuzu:/mnt/c/Users/smcro/Documents/Code/fpga/SpinalHDL$ sbt clean compile publish-local
Copying runtime jar.
Getting org.scala-sbt sbt 0.13.16  (this may take some time)...

:: problems summary ::
:::: WARNINGS
                module not found: org.scala-sbt#sbt;0.13.16

        ==== local: tried

          /home/xobs/.ivy2/local/org.scala-sbt/sbt/0.13.16/ivys/ivy.xml

          -- artifact org.scala-sbt#sbt;0.13.16!sbt.jar:

          /home/xobs/.ivy2/local/org.scala-sbt/sbt/0.13.16/jars/sbt.jar

        ==== local-preloaded-ivy: tried

          file:////home/xobs/.sbt/preloaded/org.scala-sbt/sbt/0.13.16/ivys/ivy.xml

        ==== local-preloaded: tried

          file:////home/xobs/.sbt/preloaded/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.pom

          -- artifact org.scala-sbt#sbt;0.13.16!sbt.jar:

          file:////home/xobs/.sbt/preloaded/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.jar

        ==== Maven Central: tried

          https://repo1.maven.org/maven2/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.pom

          -- artifact org.scala-sbt#sbt;0.13.16!sbt.jar:

          https://repo1.maven.org/maven2/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.jar

        ==== sbt-maven-releases: tried

          https://repo.scala-sbt.org/scalasbt/maven-releases/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.pom

          -- artifact org.scala-sbt#sbt;0.13.16!sbt.jar:

          https://repo.scala-sbt.org/scalasbt/maven-releases/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.jar

        ==== sbt-maven-snapshots: tried

          https://repo.scala-sbt.org/scalasbt/maven-snapshots/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.pom

          -- artifact org.scala-sbt#sbt;0.13.16!sbt.jar:

          https://repo.scala-sbt.org/scalasbt/maven-snapshots/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.jar

        ==== typesafe-ivy-releases: tried

          https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt/0.13.16/ivys/ivy.xml

        ==== sbt-ivy-snapshots: tried

          https://repo.scala-sbt.org/scalasbt/ivy-snapshots/org.scala-sbt/sbt/0.13.16/ivys/ivy.xml

                ::::::::::::::::::::::::::::::::::::::::::::::

                ::          UNRESOLVED DEPENDENCIES         ::

                ::::::::::::::::::::::::::::::::::::::::::::::

                :: org.scala-sbt#sbt;0.13.16: not found

                ::::::::::::::::::::::::::::::::::::::::::::::


:::: ERRORS
        Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo1.maven.org/maven2/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.pom

        Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo1.maven.org/maven2/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.jar

        Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo.scala-sbt.org/scalasbt/maven-releases/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.pom

        Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo.scala-sbt.org/scalasbt/maven-releases/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.jar

        Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo.scala-sbt.org/scalasbt/maven-snapshots/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.pom

        Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo.scala-sbt.org/scalasbt/maven-snapshots/org/scala-sbt/sbt/0.13.16/sbt-0.13.16.jar

        Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt/0.13.16/ivys/ivy.xml

        Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo.scala-sbt.org/scalasbt/ivy-snapshots/org.scala-sbt/sbt/0.13.16/ivys/ivy.xml


:: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS
unresolved dependency: org.scala-sbt#sbt;0.13.16: not found
Error during sbt execution: Error retrieving required libraries
  (see /home/xobs/.sbt/boot/update.log for complete log)
Error: Could not retrieve sbt 0.13.16
xobs@Pazuzu:/mnt/c/Users/smcro/Documents/Code/fpga/SpinalHDL$

Installing scala with sudo apt-get install scala does not solve the issue.

48/64 bit instructions

Awesome project!
I am trying to add custom SIMD instructions.
Is it possible to add 48 / 64 bit instructions?
Can iBus_rsp_inst bus be extended to 64 / 128?

The smallest verilog simulation does not commit SW before RET. Anything wrong?

The disassembled code is as follows:
0xbfc80268: 0007a703 lw a4,0(a5)
0xbfc8026c: 00071863 bnez a4,16 # 0xbfc8027c
0xbfc80270: 800007b7 lui a5,-2147483648
0xbfc80274: 00a7a823 sw a0,16(a5)
0xbfc80278: 00008067 ret
0xbfc8027c: 0007a683 lw a3,0(a5)
0xbfc80280: 00100713 addi a4,zero,1
0xbfc80284: 00e69863 bne a3,a4,16 # 0xbfc80294

The SW at 0xBFC80274 is just not output.
The core connection is like a puzzle: the dbus_ready and rsp_valid makes me frustrated. So this is my connection:
wire [31:0] w_instr_addr;
wire [31:0] w_instr_data;
wire w_instr_ready;

wire	[31:0]	w_data_addr;
wire	[31:0]	w_data_rdata;
wire			w_data_rd;
wire	[31:0]	w_data_wdata;
reg	[3:0]		w_data_wr;
wire			w_data_ready;

wire	[31:0]	w_data_addr_pre;
wire			w_data_wr_pre;
wire	[1:0]		w_rv32_cpu_wrsize;		//	0:byte, 1:word, 2:dword

wire			w_ibus_cmd_valid, w_dbus_cmd_valid;

generate
	if(SOC_SIMULATION == "FALSE") begin: Gen_SOC
		VexRiscvSmallestNoCsrSynp rv32_cpu (
			.iBus_cmd_valid			(w_ibus_cmd_valid),
			.iBus_cmd_ready			(w_instr_ready),
			.iBus_cmd_payload_pc		(w_instr_addr),
			.iBus_rsp_valid			(0),
			.iBus_rsp_payload_error		(0),
			.iBus_rsp_payload_inst		(w_instr_data),
			.dBus_cmd_valid			(w_dbus_cmd_valid),
			.dBus_cmd_ready			(w_data_ready || (|w_data_wr) || (~w_dbus_cmd_valid)),
			.dBus_cmd_payload_wr		(w_data_wr_pre),
			.dBus_cmd_payload_address	(w_data_addr_pre),
			.dBus_cmd_payload_data		(w_data_wdata),
			.dBus_cmd_payload_size		(w_rv32_cpu_wrsize),
			.dBus_rsp_ready			(0),
			.dBus_rsp_error			(0),
			.dBus_rsp_data			(w_data_rdata),
			.clk					(clk_i),
			.reset				(r_soc_rst[0])
		);
		assign w_data_addr = {w_data_addr_pre[31:2], 2'b0};
	end else begin: Gen_Sim
		
	end
endgenerate
always @(*) begin
	if(w_rv32_cpu_wrsize == 2'b10)
		w_data_wr <= {4{w_data_wr_pre}};
	else if(w_rv32_cpu_wrsize == 2'b01) begin
		w_data_wr[1:0] <= (w_data_addr_pre[1] == 0) ? {2{w_data_wr_pre}} : 2'b00;
		w_data_wr[3:2] <= (w_data_addr_pre[1] == 1) ? {2{w_data_wr_pre}} : 2'b00;
	end else begin
		w_data_wr[0] <= (w_data_addr_pre[1:0] == 2'b00) && w_data_wr_pre;
		w_data_wr[1] <= (w_data_addr_pre[1:0] == 2'b01) && w_data_wr_pre;
		w_data_wr[2] <= (w_data_addr_pre[1:0] == 2'b10) && w_data_wr_pre;
		w_data_wr[3] <= (w_data_addr_pre[1:0] == 2'b11) && w_data_wr_pre;
	end
end

I just got stuck here. Thanks for any suggestions.

Incorrect path to examples

Aloha!

In README.md, under section CPU Generation (https://github.com/SpinalHDL/VexRiscv#cpu-generation) it states that:

You can find two example CPU instances in:

src/main/scala/vexriscv/GenFull.scala
src/main/scala/vexriscv/GenSmallest.scala

I guess they have moved. The correct path seems to be "src/main/scala/vexriscv/demo/"
And it contains many more examples than the two mentioned.

Two lint issues with the vexriscv.demo.GenFull configuration

Aloha!

I generated Verilog for the vexriscv.demo.GenFull configuration. I then used the verilator linter to check the code. There were two warnings:

%Warning-WIDTH: VexRiscv.v:2565: Operator ASSIGNW expects 30 bits on the Assign RHS, but Assign RHS's SHIFTR generates 32 bits.
%Warning-WIDTH: VexRiscv.v:4422: Operator ASSIGNW expects 30 bits on the Assign RHS, but Assign RHS's SHIFTR generates 32 bits.

Line 2656 is:
assign zz_331 = (IBusCachedPlugin_iBusRsp_stages_0_input_payload >>> 2);

And line 4422 is:
assign zz_164 = (IBusCachedPlugin_fetchPc_output_payload >>> 2);

So both seems to be related to the instruction cache bus.

Is this a known issue?

Looking at the code it seems

RV32E support

After a discussion with @Dolu1990 , it was revealed that 50% of the gate count of a minimal VexRiscv is the register file, which is 32x32-bits. That's many registers.

The RV32E version of the specification cuts the number of registers down to 16, which should shrink the number of gates required by ~25%.

How much work is required to add support for RV32E?

No trap generated for `divu` on core without divide

On a VexRiscv core without a Multiply or Divide stage, the core will execute a divu instruction. It does... something. I'm not sure what.

The VexRiscv source file is at https://github.com/xobs/VexRiscv-verilog/blob/riscv-contest-20190315/src/main/scala/vexriscv/GenCoreDefault.scala. This particular core was instantiated with the following command:

run-main vexriscv.GenCoreDefault --iCacheSize 1024 --dCacheSize 0 --mulDiv false --singleCycleMulDiv false --outputFile 2-stage-1024-cache --pipelining false --memoryStage false --writeBackStage false

As you can see, mulDiv is false, which causes no divider to be added.

Here is the result of running that instruction on an FPGA:

(gdb) disassemble $pc-4,$pc+8
Dump of assembler code from 0x20040530 to 0x2004053c:
   0x20040530 <gc_init+8>:      li      a2,65
=> 0x20040534 <gc_init+12>:     divu    a4,a4,a2
   0x20040538 <gc_init+16>:     addi    sp,sp,-16
End of assembler dump.
(gdb) p/x $a2
$5 = 0x41
(gdb) p/x $a4
$6 = 0xfffc
(gdb) stepi
0x20040538      122         MP_STATE_MEM(gc_alloc_table_byte_len) = total_byte_len / (1 + BITS_PER_BYTE / 2 * BYTES_PER_BLOCK);(gdb) disassemble $pc-4,$pc+8
Dump of assembler code from 0x20040534 to 0x20040540:
   0x20040534 <gc_init+12>:     divu    a4,a4,a2
=> 0x20040538 <gc_init+16>:     addi    sp,sp,-16
   0x2004053c <gc_init+20>:     sw      s0,8(sp)
End of assembler dump.
(gdb) p/x $a2
$7 = 0x41
(gdb) p/x $a4
$8 = 0x7ffe
(gdb)

As you can see, it tries to execute $a4 = $a4 / $a2, but rather than raising an exception it's done something strange and gotten 0x7ffe as the result.

Add iCE40 stats to "Area usage and maximal frequency" section?

VexRiscv looks pretty awesome!

The Area usage and maximal frequency section is really useful for seeing how the parametrization works.

It also looks like Murax SoC supports the iCE40 FPGA.

Would it be possible to add the iCE40 info to the Area usage and maximal frequency section too?

It looks like you already have some details in the Murax SoC section;

Murax interlocked stages (0.45 DMIPS/Mhz) ->
  Artix 7    -> 305 Mhz 1004 LUT 1297 FF 
  Cyclone V  -> 160 Mhz 744 ALMs
  Cyclone IV -> 148 Mhz 1,522 LUT 1,255 FF 
  ICE40-HX   ->  51 Mhz 2402 LC (icestorm)

MuraxFast bypassed stages (0.65 DMIPS/Mhz) ->
  Artix 7    -> 312 Mhz 1240 LUT 1330 FF 
  Cyclone V  -> 159 Mhz 884 ALMs
  Cyclone IV -> 142 Mhz 1,755 LUT 1,289 FF 
  ICE40-HX   ->  50 Mhz, 2787 LC  (icestorm)

I'm very interested in know how big VexRiscv smallest is on the iCE40. It would also be interested to know the biggest configuration of VexRiscv that will fit on the various iCE40 parts.

Thanks!

Setup instructions: Cannot install key

The setup instructions say to do:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823

However, this does not actually work:

xobs@Pazuzu:~$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
Executing: /tmp/apt-key-gpghome.QoPbFivw9k/gpg.1.sh --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
gpg: connecting dirmngr at '/tmp/apt-key-gpghome.QoPbFivw9k/S.dirmngr' failed: IPC connect call failed
gpg: keyserver receive failed: No dirmngr
xobs@Pazuzu:~$

This prevents the support packages from getting installed further on.

Briey DE0 Nano SoC, not enough I/O pin locations

Hi,

I intend to test some of the softwares provided for Briey on the DE0 Nano SoC. I first ran the TCL scripts as explained by the readme in the devkits folder, but now when running the fitter on Quartus I get the following logs :

Info: *******************************************************************
Info: Running Quartus Prime Fitter
Info: Version 18.0.0 Build 614 04/24/2018 SJ Lite Edition
Info: Processing started: Tue May 29 11:31:26 2018
Info: Command: quartus_fit --read_settings_files=on --write_settings_files=off DE0_NANO -c DE0_NANO
Info: qfit2_default_script.tcl version: #1
Info: Project = DE0_NANO
Info: Revision = DE0_NANO
Warning (18236): Number of processors has not been specified which may cause overloading on shared machines. Set the global assignment NUM_PARALLEL_PROCESSORS in your QSF to an appropriate value for best performance.
Info (20030): Parallel compilation is enabled and will use 8 of the 8 processors detected
Info (119006): Selected device 5CSEMA4U23C6 for design "DE0_NANO"
Info (21077): Low junction temperature is 0 degrees C
Info (21077): High junction temperature is 85 degrees C
Warning: RST port on the PLL is not properly connected on instance pll0:pll0_inst|altpll:altpll_component|pll0_altpll:auto_generated|generic_pll2. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock.
Info: Must be connected
Warning (21300): LOCKED port on the PLL is not properly connected on instance "pll0:pll0_inst|altpll:altpll_component|pll0_altpll:auto_generated|generic_pll1". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready.
Info (171003): Fitter is performing an Auto Fit compilation, which may decrease Fitter effort to reduce compilation time
Warning (292013): Feature LogicLock is only available with a valid subscription license. You can purchase a software subscription to gain full access to this feature.
Warning (15714): Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details
Info (176045): Design uses memory blocks. Violating setup or hold times of memory block address registers for either read or write operations could cause memory contents to be corrupted. Make sure that all memory block address registers meet the setup and hold time requirements.
Critical Warning (169085): No exact pin location assignment(s) for 138 pins of 154 total pins. For the list of pins please refer to the I/O Assignment Warnings table in the fitter report.
Error (179000): Design requires 154 user-specified I/O pins -- too many to fit in the 145 user I/O pin locations available in the selected device
Info (179001): Current design requires 154 user-specified I/O pins -- 154 normal user-specified I/O pins and 0 programming pins that have been constrained to use dual-purpose I/O pin locations
Info (179002): Targeted device has 145 I/O pin locations available for user I/O -- 117 general-purpose I/O pins and 28 dual-purpose I/O pins
Error (12289): An error occurred while applying the periphery constraints. Review the offending constraints and rerun the Fitter.
Info (11798): Fitter preparation operations ending: elapsed time is 00:00:10
Warning (171167): Found invalid Fitter assignments. See the Ignored Assignments panel in the Fitter Compilation Report for more information.
Warning (169064): Following 82 pins have no output enable or a GND or VCC output enable - later changes to this connectivity may change fitting results
Warning (169069): Following 90 pins have nothing, GND, or VCC driving datain port -- changes to this connectivity may change fitting results
Error (11802): Can't fit design in device. Modify your design to reduce resources, or choose a larger device. The Intel FPGA Knowledge Database contains many articles with specific details on how to resolve this error. Visit the Knowledge Database at https://www.altera.com/support/support-resources/knowledge-base/search.html and search for this specific error message number.
Error: Quartus Prime Fitter was unsuccessful. 3 errors, 9 warnings
Error: Peak virtual memory: 1226 megabytes
Error: Processing ended: Tue May 29 11:31:48 2018
Error: Elapsed time: 00:00:22
Error: Total CPU time (on all processors): 00:00:21

I'm not really used to Quartus and I don't see how I could solve these I/O issue. Moreover when looking to the Compilation Report it states 154/314 for Total Pins and the right device is selected.

CPU Generation Documentation in README

In the CPU Generation section of the README.md file, the sbt "run-main vexriscv.demo.GenFull" command should be run in the VexRiscv directory, but that fact is not reflected in the README. I think it would add clarification to say in the README that the command should be run in the root of the VexRiscv directory.

SEGV in regression test: Too many open files

Hi,

If I try and run the regression tests by 'cd src/test/cpp/regression' and then 'make clean run', I get the following output:

[snip]
SUCCESS I-BGE-01
SUCCESS I-BGE-01
SUCCESS I-BGE-01
SUCCESS I-BGE-01
SUCCESS I-BGE-01
SUCCESS I-BGEU-01
SUCCESS I-BGEU-01
SUCCESS I-BGEU-01
SUCCESS I-BGEU-01
make: *** [makefile:175: run] Segmentation fault

If I turn on debug in the makefile, recompile and then do 'gdb ./obj_dir/VVexRiscv', I get the following output:

SUCCESS I-BGEU-01
SUCCESS I-BGEU-01

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7ad4db1 in fseek () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) where
#0  0x00007ffff7ad4db1 in fseek () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x0000555555565c8c in Compliance::pass (this=0x7fffffef4470) at ../main.cpp:2155
#2  0x0000555555562c8c in Workspace::dBusAccess (this=0x7fffffef4470, addr=4027580192, wr=true, size=2, mask=15, data=0x55555577c73c, error=0x555555a4c25c) at ../main.cpp:842
#3  0x0000555555565ac2 in Compliance::dBusAccess (this=0x7fffffef4470, addr=4027580192, wr=true, size=2, mask=15, data=0x55555577c73c, error=0x555555a4c25c)
    at ../main.cpp:2139
#4  0x00005555555645af in DBusCached::preCycle (this=0x555555a4c250) at ../main.cpp:1568
#5  0x0000555555563c52 in Workspace::run (this=0x7fffffef4470, timeout=5000) at ../main.cpp:1077
#6  0x000055555555a232 in main (argc=1, argv=0x7fffffffe0a8, env=0x7fffffffe0b8) at ../main.cpp:2648
(gdb) up
#1  0x0000555555565c8c in Compliance::pass (this=0x7fffffef4470) at ../main.cpp:2155
2155            fseek(refFile, 0, SEEK_END);
(gdb) p ref
ref        refFile    refIndex   refSize    refwrap.h  
(gdb) p refFile 
$1 = (FILE *) 0x0
(gdb) l
2150
2151
2152
2153            virtual void pass(){
2154                    FILE *refFile = fopen((string("../../resources/ref/") + name + ".reference_output").c_str(), "r");
2155            fseek(refFile, 0, SEEK_END);
2156            uint32_t refSize = ftell(refFile);
2157            fseek(refFile, 0, SEEK_SET);
2158            char* ref = new char[refSize];
2159            fread(ref, 1, refSize, refFile);
(gdb) p name
$2 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, 
    _M_p = 0x7ffffff04cf0 "I-BGEU-01"}, _M_string_length = 9, {_M_local_buf = "I-BGEU-01\000\000\000\000\000\000", _M_allocated_capacity = 3471524643809144137}}
(gdb) 

So its failing to open the file '../../resources/ref/I-BGEU-01.reference_output' which is odd as it exists. If I now tweak main.cpp to be:

[snip]
       virtual void pass(){
                FILE *refFile = fopen((string("../../resources/ref/") + name + ".reference_output").c_str(), "r");
                if (refFile == NULL) { perror("oh dear"); }
        fseek(refFile, 0, SEEK_END);
        uint32_t refSize = ftell(refFile);
        fseek(refFile, 0, SEEK_SET);
[snip]

I now get the output:

[snip]
SUCCESS I-BGE-01
SUCCESS I-BGE-01
SUCCESS I-BGE-01
SUCCESS I-BGE-01
SUCCESS I-BGE-01
SUCCESS I-BGEU-01
SUCCESS I-BGEU-01
SUCCESS I-BGEU-01
SUCCESS I-BGEU-01
oh dear: Too many open files
make: *** [makefile:175: run] Segmentation fault

This is with Verilator 4.006 2018-10-27 and gcc version 8.2.0

Thanks,

Matt

ps. I just noticed at the top of the output from make, I get '/bin/sh: 1: dplus: not found', what is 'dplus'? Its not on the list of requirements, I can't find anything obvious in debian packages nor can I find an obvious package on the internet. What have I missed?

Linux on VexRiscv

My intention with creating this issue is collecting/sharing information and gauging interest about running Linux on VecRiscv. From what I know, VexRiscv is still missing functionality, and it won't work out of the box.

A big problem is the MMU. Ideally, "someone" will hopefully write patches to add no-MMU support to Linux/RISC-V, but currently, a MMU is required. It appears VexRiscv has a partial MMU implementation using a software-filled TLB. There needs to be machine mode to walk the page tables and fill the TLBs, and I didn't find a reference implementation of that.

Another issue are atomics. Linux requires them currently. There seems to be partial support present in VexRiscv (a subset or so). Another possibility is patching the kernel not to use atomics if built without SMP support. There's also the question how much atomics support userspace typically requires.

Without doubt there are more issues that I don't know about.

Antmicro apparently made a Linux port: https://github.com/antmicro/litex-rv32-linux-system https://github.com/antmicro/litex-linux-riscv
I didn't know about this before and haven't managed to build the whole thing yet.
Unfortunately, their Linux kernel repository does not include the git history. Here's a diff against the apparent base: https://0x0.st/z-li.diff

Please post any other information you know.

Failed to compile regression tests

Hello,

I have some problems to compile regression tests:

$ sbt "run-main vexriscv.demo.GenFull"
[warn] Executing in batch mode.
[warn]   For better performance, hit [ENTER] to switch to interactive mode, or
[warn]   consider launching sbt without any commands, or explicitly passing 'shell'
[info] Loading project definition from VexRiscv/project
[info] Set current project to VexRiscv (in build file:VexRiscv/)
[info] Running vexriscv.demo.GenFull 
[Runtime] SpinalHDL v0.10.15    git head : 7e6b26ca08f52c6959f931ef9e993590e23625e2
[Runtime] JVM max memory : 981.5MiB
[Runtime] Current date : 2017.08.05 09:21:22
[Progress] at 0.000 : Start elaboration
[Progress] at 0.841 : Start analysis and transform
[Progress] at 0.862 : Get names from reflection
[Progress] at 0.872 : Transform connections
[Progress] at 0.931 : Infer nodes's bit width
[Progress] at 1.040 : Check combinatorial loops
[Progress] at 1.075 : Check cross clock domains
[Progress] at 1.137 : Simplify graph's nodes
[Progress] at 1.166 : Check that there is no incomplete assignment
[Progress] at 1.180 : Collect signals not used in the graph
[Warning] 32 signals were pruned. You can call printPruned on the backend report to get more informations.
[Progress] at 1.191 : Finalise
[Info] Graph has 6170 nodes
[Progress] at 1.225 : Write Verilog
[Progress] at 1.229 :       emit UnsignedDivider
[Progress] at 1.252 :     emit InstructionCache
[Warning] memReadSync with dontCare is as readFirst into Verilog ways_0_tags_port1
[Warning] memReadSync with dontCare is as readFirst into Verilog ways_0_datas_port1
[Progress] at 1.265 :     emit DataCache
[Warning] memReadSync with dontCare is as readFirst into Verilog way_tags_port2
[Warning] memReadSync with dontCare is as readFirst into Verilog way_data_port1
[Warning] memReadSync with dontCare is as readFirst into Verilog victim_buffer_port2
[Progress] at 1.306 :     emit MixedDivider
[Progress] at 1.309 :   emit VexRiscv
[Warning] memReadSync with dontCare is as readFirst into Verilog MemoryTranslatorPlugin_shared_cache_port0
[Warning] memReadSync with dontCare is as readFirst into Verilog RegFilePlugin_regFile_port0
[Warning] memReadSync with dontCare is as readFirst into Verilog RegFilePlugin_regFile_port1
[Warning] memReadSync with dontCare is as readFirst into Verilog branchCache_port1
[Done] at 1.361
[success] Total time: 2 s, completed 5-Aug-2017 9:21:23 AM
$ verilator --version
Verilator 3.874 2015-06-06 rev verilator_3_872-20-g0d43051
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ cd src/test/cpp/regression/
$ make clean run
rm -rf obj_dir
verilator -cc  ../../../../VexRiscv.v  -O3 -CFLAGS -std=c++11 -LDFLAGS -pthread  -CFLAGS -DIBUS_CACHED -CFLAGS -DDBUS_CACHED -CFLAGS -DREDO=10 -CFLAGS -pthread -CFLAGS -DTHREAD_COUNT=4 -CFLAGS -DDHRYSTONE -CFLAGS -DCSR -CFLAGS -DISA_TEST -CFLAGS -DMMU -CFLAGS -DMUL -CFLAGS -DDIV -CFLAGS -DDEBUG_PLUGIN -CFLAGS -DDEBUG_PLUGIN_STD -CFLAGS -DTRACE_START=0 --gdbbt  -Wno-WIDTH --x-assign unique --exe main.cpp
No stack.
make  -j  -C obj_dir/ -f VVexRiscv.mk VVexRiscv
make[1]: Entering directory 'obj_dir'
g++  -I.  -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -Wno-char-subscripts -Wno-parentheses-equality -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable     -DCSR -DDBUS_CACHED -DDEBUG_PLUGIN -DDEBUG_PLUGIN_STD -DDHRYSTONE -DDIV -DIBUS_CACHED -DISA_TEST -DMMU -DMUL -DREDO=10 -DTHREAD_COUNT=4 -DTRACE_START=0 -pthread -std=c++11   -c -o main.o ../main.cpp
g++  -I.  -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -Wno-char-subscripts -Wno-parentheses-equality -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable     -DCSR -DDBUS_CACHED -DDEBUG_PLUGIN -DDEBUG_PLUGIN_STD -DDHRYSTONE -DDIV -DIBUS_CACHED -DISA_TEST -DMMU -DMUL -DREDO=10 -DTHREAD_COUNT=4 -DTRACE_START=0 -pthread -std=c++11   -c -o verilated.o /usr/share/verilator/include/verilated.cpp
g++  -I.  -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -Wno-char-subscripts -Wno-parentheses-equality -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable     -DCSR -DDBUS_CACHED -DDEBUG_PLUGIN -DDEBUG_PLUGIN_STD -DDHRYSTONE -DDIV -DIBUS_CACHED -DISA_TEST -DMMU -DMUL -DREDO=10 -DTHREAD_COUNT=4 -DTRACE_START=0 -pthread -std=c++11   -c -o verilated_dpi.o /usr/share/verilator/include/verilated_dpi.cpp
/usr/bin/perl /usr/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include VVexRiscv.cpp VVexRiscv_VexRiscv.cpp > VVexRiscv__ALLcls.cpp
/usr/bin/perl /usr/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include VVexRiscv__Dpi.cpp VVexRiscv__Syms.cpp > VVexRiscv__ALLsup.cpp
g++  -I.  -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -Wno-char-subscripts -Wno-parentheses-equality -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable     -DCSR -DDBUS_CACHED -DDEBUG_PLUGIN -DDEBUG_PLUGIN_STD -DDHRYSTONE -DDIV -DIBUS_CACHED -DISA_TEST -DMMU -DMUL -DREDO=10 -DTHREAD_COUNT=4 -DTRACE_START=0 -pthread -std=c++11   -c -o VVexRiscv__ALLcls.o VVexRiscv__ALLcls.cpp
g++  -I.  -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -Wno-char-subscripts -Wno-parentheses-equality -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable     -DCSR -DDBUS_CACHED -DDEBUG_PLUGIN -DDEBUG_PLUGIN_STD -DDHRYSTONE -DDIV -DIBUS_CACHED -DISA_TEST -DMMU -DMUL -DREDO=10 -DTHREAD_COUNT=4 -DTRACE_START=0 -pthread -std=c++11   -c -o VVexRiscv__ALLsup.o VVexRiscv__ALLsup.cpp
../main.cpp: In member function ‘Workspace* Workspace::run(uint64_t)’:
../main.cpp:369:25: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
   if(bootPc != -1) top->VexRiscv->prefetch_PcManagerSimplePlugin_pcReg = bootPc;
                         ^
../main.cpp:413:13: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
     if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address 
             ^
../main.cpp:413:79: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
     if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address 
                                                                               ^
../main.cpp:418:42: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
        " PC " << hex << setw(8) <<  top->VexRiscv->writeBack_PC << " : reg[" << dec << setw(2) << (uint32_t)top->VexRiscv->writeBack_RegFileP
                                          ^
../main.cpp:418:114: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
        " PC " << hex << setw(8) <<  top->VexRiscv->writeBack_PC << " : reg[" << dec << setw(2) << (uint32_t)top->VexRiscv->writeBack_RegFileP
                                                                                                                  ^
../main.cpp:418:213: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
 c << setw(2) << (uint32_t)top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address << "] = " << hex << setw(8) << top->VexRiscv->w
                                                                                                                                   ^
../main.cpp:424:14: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
      if(top->VexRiscv->decode_arbitration_isValid && !top->VexRiscv->decode_arbitration_haltItself){
              ^
../main.cpp:424:60: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
      if(top->VexRiscv->decode_arbitration_isValid && !top->VexRiscv->decode_arbitration_haltItself){
                                                            ^
../main.cpp:427:23: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
       iBusAccess(top->VexRiscv->decode_PC, &expectedData, &dummy);
                       ^
../main.cpp:428:21: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
       assertEq(top->VexRiscv->decode_INSTRUCTION,expectedData);
                     ^
../main.cpp:134:28: note: in definition of macro ‘assertEq’
 #define assertEq(x,ref) if(x != ref) {\
                            ^
../main.cpp:428:21: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
       assertEq(top->VexRiscv->decode_INSTRUCTION,expectedData);
                     ^
../main.cpp:135:62: note: in definition of macro ‘assertEq’
  printf("\n*** %s is %d but should be %d ***\n\n",TEXTIFY(x),x,ref);\
                                                              ^
../main.cpp: In member function ‘virtual void TestA::checks()’:
../main.cpp:1240:11: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
   if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address !=
           ^
../main.cpp:1240:77: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
   if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address !=
                                                                             ^
../main.cpp:1241:18: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
    assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address, regFileWriteRefArray[regFileWriteRefIndex][0]);
                  ^
../main.cpp:134:28: note: in definition of macro ‘assertEq’
 #define assertEq(x,ref) if(x != ref) {\
                            ^
../main.cpp:1241:18: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
    assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address, regFileWriteRefArray[regFileWriteRefIndex][0]);
                  ^
../main.cpp:135:62: note: in definition of macro ‘assertEq’
  printf("\n*** %s is %d but should be %d ***\n\n",TEXTIFY(x),x,ref);\
                                                              ^
../main.cpp:1242:18: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
    assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data, regFileWriteRefArray[regFileWriteRefIndex][1]);
                  ^
../main.cpp:134:28: note: in definition of macro ‘assertEq’
 #define assertEq(x,ref) if(x != ref) {\
                            ^
../main.cpp:1242:18: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
    assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data, regFileWriteRefArray[regFileWriteRefIndex][1]);
                  ^
../main.cpp:135:62: note: in definition of macro ‘assertEq’
  printf("\n*** %s is %d but should be %d ***\n\n",TEXTIFY(x),x,ref);\
                                                              ^
../main.cpp: In member function ‘virtual void TestX28::checks()’:
../main.cpp:1266:11: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
   if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address ==
           ^
../main.cpp:1266:77: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
   if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address ==
                                                                             ^
../main.cpp:1267:18: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
    assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data, ref[refIndex]);
                  ^
../main.cpp:134:28: note: in definition of macro ‘assertEq’
 #define assertEq(x,ref) if(x != ref) {\
                            ^
../main.cpp:1267:18: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
    assertEq(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data, ref[refIndex]);
                  ^
../main.cpp:135:62: note: in definition of macro ‘assertEq’
  printf("\n*** %s is %d but should be %d ***\n\n",TEXTIFY(x),x,ref);\
                                                              ^
../main.cpp: In member function ‘virtual void RiscvTest::checks()’:
../main.cpp:1294:11: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
   if(top->VexRiscv->writeBack_INSTRUCTION == 0x00000073){
           ^
../main.cpp:1297:20: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
    iBusAccess(top->VexRiscv->writeBack_PC, &instruction, &error);
                    ^
../main.cpp:1299:26: error: ‘class VVexRiscv’ has no member named ‘VexRiscv’
     uint32_t code = top->VexRiscv->RegFilePlugin_regFile[28];
                          ^
      Archiving VVexRiscv__ALL.a ...
ar r VVexRiscv__ALL.a VVexRiscv__ALLcls.o VVexRiscv__ALLsup.o
ar: creating VVexRiscv__ALL.a
ranlib VVexRiscv__ALL.a
At global scope:
cc1plus: warning: unrecognized command line option ‘-Wno-parentheses-equality’
VVexRiscv.mk:81: recipe for target 'main.o' failed
make[1]: *** [main.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make[1]: Leaving directory 'obj_dir'
makefile:95: recipe for target 'compile' failed
make: *** [compile] Error 2

Am I missing something?
Thanks,

Roman

Add support for using the DSP blocks on the iCE40UP5K?

The iCE40UP5K has DSP tiles which are described as "DSP blocks with multiply and accumulate functions". They are 16 x 16 Multiply & 32 bit Accumulator Blocks which can be chained together to be a 32x32 multiply block. It would be awesome if the VexRISCV could use these DSP blocks for better performance.

One issue is that Yosys can't infer the ice40 DSP blocks at the moment, so they will have to be manually instantiated.

File name <> Module name inconsistent

File name: GenSmallAndPerformant.scala
Module name: GenSmallAndProductive

Same thing for: GenSmallAndProductiveWithICache

Which is the right name: *performant or *productive?

Once I know, I'll submit a patch.

Tom

AXI Bridge

Hello, I am new to SpinalHDL but found a liking in your VexRiscv. Since I need an AXI interface to access my memory, it would be nice to just use the core and the AXI bridge that was mentioned in your README, so I can convert your simple bus to AXI. Could you provide me with any info on how to achieve this or where I could learn how to achieve this?
Have a nice day!

VexRiscV fails to meet timing as soon as you connect it to IBus/DBus memory

image

This on Lattice ecp5 @ 125MHz
Worst path info:

      Requested Period:                      7.264
    - Setup time:                            1.777
    + Clock delay at ending point:           0.000 (ideal)
    = Required time:                         5.487

    - Propagation time:                      6.769
    - Clock delay at starting point:         0.000 (ideal)
    = Slack (critical) :                     -1.282

    Number of logic level(s):                10
    Starting point:                          VexRiscv._zz_237[2] / Q
    Ending point:                            mem.mem0_1_mem0_0_0 / ADA1
    The start point is clocked by            q_engine|clk [rising] on pin CK
    The end   point is clocked by            q_engine|clk [rising] on pin CLKA

Instance / Net                                           Pin      Pin               Arrival     No. of    
Name                                        Type         Name     Dir     Delay     Time        Fan Out(s)
----------------------------------------------------------------------------------------------------------
VexRiscv._zz_237[2]                         FD1S3AX      Q        Out     0.930     0.930       -         
_zz_237[2]                                  Net          -        -       -         -           14        
VexRiscv.un3__zz_408                        ORCALUT4     A        In      0.000     0.930       -         
VexRiscv.un3__zz_408                        ORCALUT4     Z        Out     0.754     1.685       -         
un3__zz_408                                 Net          -        -       -         -           43        
VexRiscv._zz_159_f0                         ORCALUT4     D        In      0.000     1.685       -         
VexRiscv._zz_159_f0                         ORCALUT4     Z        Out     0.608     2.293       -         
_zz_159                                     Net          -        -       -         -           3         
VexRiscv.decode_arbitration_haltItself9     ORCALUT4     B        In      0.000     2.293       -         
VexRiscv.decode_arbitration_haltItself9     ORCALUT4     Z        Out     0.608     2.901       -         
decode_arbitration_haltItself9              Net          -        -       -         -           3         
VexRiscv._zz_99_1_a0_4_2_sx                 ORCALUT4     C        In      0.000     2.901       -         
VexRiscv._zz_99_1_a0_4_2_sx                 ORCALUT4     Z        Out     0.523     3.424       -         
_zz_99_1_a0_4_2_sx                          Net          -        -       -         -           1         
VexRiscv._zz_99_1_a0_4_2                    ORCALUT4     A        In      0.000     3.424       -         
VexRiscv._zz_99_1_a0_4_2                    ORCALUT4     Z        Out     0.523     3.947       -         
_zz_99_1_a0_4_2                             Net          -        -       -         -           1         
VexRiscv._zz_99_1_a0_4_2_RNIU39D2           ORCALUT4     D        In      0.000     3.947       -         
VexRiscv._zz_99_1_a0_4_2_RNIU39D2           ORCALUT4     Z        Out     0.523     4.470       -         
_zz_1_0                                     Net          -        -       -         -           1         
VexRiscv._zz_99_1_a1_RNIEP4H3               ORCALUT4     B        In      0.000     4.470       -         
VexRiscv._zz_99_1_a1_RNIEP4H3               ORCALUT4     Z        Out     0.523     4.993       -         
_zz_sx                                      Net          -        -       -         -           1         
VexRiscv._zz_99_1_a1_RNIUEUP6               ORCALUT4     C        In      0.000     4.993       -         
VexRiscv._zz_99_1_a1_RNIUEUP6               ORCALUT4     Z        Out     0.743     5.736       -         
_zz_99                                      Net          -        -       -         -           34        
VexRiscv.iBus_cmd_payload_pc_m2[2]          ORCALUT4     A        In      0.000     5.736       -         
VexRiscv.iBus_cmd_payload_pc_m2[2]          ORCALUT4     Z        Out     0.523     6.259       -         
iBus_cmd_payload_pc_m2[2]                   Net          -        -       -         -           1         
VexRiscv.iBus_cmd_payload_pc[2]             PFUMX        BLUT     In      0.000     6.259       -         
VexRiscv.iBus_cmd_payload_pc[2]             PFUMX        Z        Out     0.509     6.769       -         
iBus_cmd_payload_pc[2]                      Net          -        -       -         -           18        
mem.mem0_1_mem0_0_0                         DP16KD       ADA1     In      0.000     6.769       -         
==========================================================================================================```

Correct spelling?

Aloha!

Noticed that the name of a directory in VexRiscv/src/main is "ressource". Is that a spelling error?

JTAG/Reset Lock Up (Avalon)

So I've been banging my head on the desk trying to understand the debug/jtag. I think the problem is related to reset.

For reference, this is my qsys diagram:

qsys

monitor reset halt -> locks up
monitor reset resume -> locks up
monitor halt -> works
monitor resume -> works

This is what halt/resume cycles look like:

image

And now monitor reset run/halt

image

Thoughts?

OCD config:

#-----------------------------------------
# JTAG Adapter
#
interface ftdi
ftdi_vid_pid 0x0403 0x6014
#ftdi_layout_init 0x0c08 0x0f1b
ftdi_layout_init 0xfff8 0xfffb
ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100
ftdi_layout_signal nSRST -data 0x0200 -oe 0x0200
transport select jtag

#-----------------------------------------
# Target
#
set  _ENDIAN little
set _TAP_TYPE 1234
set _CPUTAPID 0x10001FFF

adapter_khz 4000
# have tried 25,100,1000 too
adapter_nsrst_delay 260
jtag_ntrst_delay 250

set _CHIPNAME fpga_spinal
jtag newtap $_CHIPNAME bridge -expected-id $_CPUTAPID -irlen 4 -ircapture 0x1 -irmask 0xF

target create $_CHIPNAME.cpu0 vexriscv -endian $_ENDIAN -chain-position $_CHIPNAME.bridge -coreid 0 -dbgbase 0xF00F0000
vexriscv readWaitCycles 12
vexriscv cpuConfigFile ../cpu0.yaml

poll_period 50

init
#echo "Halting processor"
soft_reset_halt

GDB:

target remote localhost:3333
set arch riscv:rv32
monitor reset halt
load
continue

Xilinx Vivado inferring block ram on register file

Not really sure if this is a bug but I've noticed that by default, Vivado infers the CPU register file as a block ram. On one hand it saves LUTs when you have free block rams but it complicates timing a bit. Is this an intentional part of the design?

Create wiki

This is the first RISCV core I've been able to get up and running without breaking my head. Much appreciation for the SpinalHDL team for the making this work with Qsys and Avalon. :) (Although SpinalHDL itself puzzling still.)

Where should notes and documentation go? (Is there a wiki?) There's a lot of little things I had to figure out. It would be nice to make it easy to post the notes. One example, for Quartus, is the memory initialization files. Quartus memory initialization files are interpreted with the wrong endianess. Another configuration option is required to support intel hex as well. (Or maybe there's a simpler approach to making programming files?)

Objcopy can produce compatible output using this...

$(RISCV_OBJCOPY) --strip-debug --remove-section=.comment --remove-section=.note --strip-unneeded -O ihex --reverse-bytes=4 $^ $@

I'm not sure where to put these nuggets of information.

QSys interprets clock and reset as conduits

Hi,

After compiling the VexRiscvAvalonForSim example, I imported the TCL component into Quartus but trying to instantiate it inside Platform Designer I receive the following errors:

Error: unsaved.VexRiscv_0: VexRiscv_0.debug_resetOut has an associatedClock of "clk" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.timerInterrupt has an associatedReset of "reset" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.timerInterrupt has an associatedClock of "clk" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.externalInterrupt has an associatedReset of "reset" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.externalInterrupt has an associatedClock of "clk" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.iBusAvalon has an associatedReset of "reset" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.iBusAvalon has an associatedClock of "clk" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.dBusAvalon has an associatedReset of "reset" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.dBusAvalon has an associatedClock of "clk" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.debugBusAvalon has an associatedReset of "debugReset" with incompatible type "conduit"
Error: unsaved.VexRiscv_0: VexRiscv_0.debugBusAvalon has an associatedClock of "clk" with incompatible type "conduit"

This happens with VexRiscvAvalanWithIntegratedJtag as well. I am using Quartus II 18.0 .

Tony

SIMD

Hi!

I've started to think about a MAC module, mainly for audio processing.

I'd like to multiply a 64-bit register location (8guard,32signal,24overflow) by a 32bit coefficient and store the product in a 88bit accumulator register 32,32,24.

Then ultimately 16-way SIMD. Does this feasible?

Mul/Div don't work if withWriteBackStage or withMemoryStage is false

The MulPlugin, DivPlugin, and MulDivIterativePlugin all require that withWriteBackStage = true and withMemoryStage = true. This can make it difficult to shrink the core, especially since the MulPlugin ought to be inferred to a DSP block.

Is it difficult to adapt plugins to work with shorter pipelines?

Can the Briey SoC run on a iCE40-HX8K-CT256?

The README seems to suggest that the Murax SoC is the only one that can be run on an iCE40 FPGA.

But I was a bit confused by the 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

I think I am mistunderstanding these numbers, because the iCE40-HX8K chip has 7,680 LUTs, which is greater than 3227, 2,207, and 4,594.

I'm new to FPGAs, so sorry for the question. But how many LUTs does the Briey SoC require? And what do those "area" numbers mean?

(I've just bought a iCE40-HX8K breakout board. But I might also get a Artix 7 (or Zynq 7020) board to play with VexRiscv.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.