Remove the Ibex example system (#272)

This commit is contained in:
Mike Thompson 2024-05-28 18:23:18 +00:00 committed by GitHub
parent 7f3bb9fcb2
commit 42f76f433c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 14 additions and 3903 deletions

View file

@ -3,16 +3,20 @@
Examples
========
To make use of Ibex it has to be integrated as described in :ref:`core-integration`.
To make use of CVE2 please review the :ref:`core-integration` section of this document.
The CVE2 is simple enough to integrate into your own platform.
To get you started, we suggest a couple of very useful open-source platforms.
FPGA
----
Ibex Minimal System
-------------------
A minimal example for the `Arty A7 <https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start>`_ FPGA Development board is provided.
In this example Ibex is directly linked to a SRAM memory instance.
Four LEDs from the board are connected to the data bus and are updated each time when a word is written.
The memory is separated into a instruction and data section.
The instructions memory is initialized at synthesis time by reading the output from the software build.
The software writes to the data section the complementary lower for bits of a word every second resulting in blinking LEDs.
A minimal example for the `Arty A7 <https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start>`_ FPGA Development board developed for Ibex should be portable to the CVE2 without significant effort.
If you are interested in using the Ibex minimal example, it can be found `here <https://github.com/lowRISC/ibex/tree/master/examples/simple_system>`_.
X-HEEP
------
The CV32E20 (a specific configuration of the CVE2) has been integrated into the `X-HEEP <https://github.com/esl-epfl/x-heep/tree/main>`_ (eXtendable Heterogeneous Energy-Efficient Platform).
X-HEEP is a RISC-V microcontroller implemented in SystemVerilog that can be configured to integrate a number of CORE-V processors.
X-HEEP provides a simple customizable MCU to get you up and running quickly.
Find the description of how to build and program the Arty board in ``examples/fpga/artya7/README.md``.

View file

@ -1,95 +0,0 @@
# Ibex RISC-V Core SoC Example
Please see [examples](https://ibex-core.readthedocs.io/en/latest/02_user/examples.html "Ibex User Manual") for a description of this example.
## Requirements
### Tools
- RV32 compiler
- srecord
- `fusesoc` and its dependencies
- Xilinx Vivado
### Hardware
- Either a Digilent Arty A7-35 oder A7-100 board
## Build
The easiest way to build and execute this example is to call the following make goals from the root directory.
Use the following for the Arty A7-35
```
make build-arty-35 program-arty
```
and for the Arty A7-100
```
make build-arty-100 program-arty
```
### Software
First the software must be built. Go into `examples/sw/led` and call:
```
make CC=/path/to/RISC-V-compiler
```
The setting of `CC` is only required if `riscv32-unknown-elf-gcc` is not available through the `PATH` environment variable.
The path to the RV32 compiler `/path/to/RISC-V-compiler` depends on the environment.
For example, it can be for example `/opt/riscv/bin/riscv-none-embed-gcc` if the whole path is required or simply the name of the executable if it is available through the `PATH` environment variable.
This should produce a `led.vmem` file which is used in the synthesis to update the SRAM storage.
### Hardware
Run either of the following commands at the top level to build the respective hardware.
Both variants of the Arty A7 are supported and can be selected via the `--parts` parameter.
```
fusesoc --cores-root=. run --target=synth --setup --build lowrisc:cve2:top_artya7 --part xc7a35ticsg324-1L
```
```
fusesoc --cores-root=. run --target=synth --setup --build lowrisc:cve2:top_artya7 --part xc7a100tcsg324-1
```
This will create a directory `build` which contains the output files, including
the bitstream.
Initial memory parameter `SRAMInitFile` can be given to FuseSoc to specify which .vmem file to load the design with.
Example use case includes loading `coremark.vmem` which can be used for performance/power analysis.
Please see [CoreMark README](https://github.com/lowRISC/ibex/blob/master/examples/sw/benchmarks/README.md) for compiling CoreMark.
```
fusesoc --cores-root=. run --target=synth --setup --build lowrisc:cve2:top_artya7 --part xc7a100tcsg324-1 --SRAMInitFile=examples/sw/benchmarks/coremark/coremark.vmem
```
#### Power Analysis Using Vivado
Setting `FPGAPowerAnalysis` parameter to 1 allows user to run a power analysis using Vivado.
It uses a post-implementation functional simulation on Vivado to log switching activity.
This switching activity is then used to generate a detailed power report.
In order to use it with CoreMark run the command below
```
fusesoc --cores-root=. run --target=synth --setup --build lowrisc:cve2:top_artya7 --part xc7a100tcsg324-1 --SRAMInitFile=examples/sw/benchmarks/coremark/coremark.vmem --FPGAPowerAnalysis=1
```
## Program
After the board is connected to the computer it can be programmed with:
```
fusesoc --cores-root=. run --target=synth --run lowrisc:cve2:top_artya7
```
LED1/LED3 and LED0/LED2 should alternately be on after the FPGA programming is finished.

View file

@ -1,217 +0,0 @@
## Based on https://github.com/Digilent/digilent-xdc/blob/master/Arty-A7-100-Master.xdc
## This file is a general .xdc for the Arty A7-100 Rev. D
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
## Clock signal
set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { IO_CLK }]; #IO_L12P_T1_MRCC_35 Sch=gclk[100]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { IO_CLK }];
## Switches
#set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L12N_T1_MRCC_16 Sch=sw[0]
#set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L13P_T2_MRCC_16 Sch=sw[1]
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]
## RGB LEDs
#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { led0_b }]; #IO_L18N_T2_35 Sch=led0_b
#set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { led0_g }]; #IO_L19N_T3_VREF_35 Sch=led0_g
#set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { led0_r }]; #IO_L19P_T3_35 Sch=led0_r
#set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { led1_b }]; #IO_L20P_T3_35 Sch=led1_b
#set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { led1_g }]; #IO_L21P_T3_DQS_35 Sch=led1_g
#set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { led1_r }]; #IO_L20N_T3_35 Sch=led1_r
#set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { led2_b }]; #IO_L21N_T3_DQS_35 Sch=led2_b
#set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { led2_g }]; #IO_L22N_T3_35 Sch=led2_g
#set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { led2_r }]; #IO_L22P_T3_35 Sch=led2_r
#set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { led3_b }]; #IO_L23P_T3_35 Sch=led3_b
#set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { led3_g }]; #IO_L24P_T3_35 Sch=led3_g
#set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { led3_r }]; #IO_L23N_T3_35 Sch=led3_r
## LEDs
set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { LED[0] }]; #IO_L24N_T3_35 Sch=led[4]
set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { LED[1] }]; #IO_25_35 Sch=led[5]
set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { LED[2] }]; #IO_L24P_T3_A01_D17_14 Sch=led[6]
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { LED[3] }]; #IO_L24N_T3_A00_D16_14 Sch=led[7]
## Buttons
#set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L6N_T0_VREF_16 Sch=btn[0]
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]
## Pmod Header JA
#set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_0_15 Sch=ja[1]
#set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L4P_T0_15 Sch=ja[2]
#set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L4N_T0_15 Sch=ja[3]
#set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L6P_T0_15 Sch=ja[4]
#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L6N_T0_VREF_15 Sch=ja[7]
#set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L10P_T1_AD11P_15 Sch=ja[8]
#set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L10N_T1_AD11N_15 Sch=ja[9]
#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_25_15 Sch=ja[10]
## Pmod Header JB
#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L11P_T1_SRCC_15 Sch=jb_p[1]
#set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L11N_T1_SRCC_15 Sch=jb_n[1]
#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L12P_T1_MRCC_15 Sch=jb_p[2]
#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L12N_T1_MRCC_15 Sch=jb_n[2]
#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L23P_T3_FOE_B_15 Sch=jb_p[3]
#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L23N_T3_FWE_B_15 Sch=jb_n[3]
#set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L24P_T3_RS1_15 Sch=jb_p[4]
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L24N_T3_RS0_15 Sch=jb_n[4]
## Pmod Header JC
#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { jc[0] }]; #IO_L20P_T3_A08_D24_14 Sch=jc_p[1]
#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { jc[1] }]; #IO_L20N_T3_A07_D23_14 Sch=jc_n[1]
#set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { jc[2] }]; #IO_L21P_T3_DQS_14 Sch=jc_p[2]
#set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { jc[3] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=jc_n[2]
#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { jc[4] }]; #IO_L22P_T3_A05_D21_14 Sch=jc_p[3]
#set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { jc[5] }]; #IO_L22N_T3_A04_D20_14 Sch=jc_n[3]
#set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { jc[6] }]; #IO_L23P_T3_A03_D19_14 Sch=jc_p[4]
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L23N_T3_A02_D18_14 Sch=jc_n[4]
## Pmod Header JD
#set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L11N_T1_SRCC_35 Sch=jd[1]
#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L12N_T1_MRCC_35 Sch=jd[2]
#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L13P_T2_MRCC_35 Sch=jd[3]
#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L13N_T2_MRCC_35 Sch=jd[4]
#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L14P_T2_SRCC_35 Sch=jd[7]
#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L14N_T2_SRCC_35 Sch=jd[8]
#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15P_T2_DQS_35 Sch=jd[9]
#set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L15N_T2_DQS_35 Sch=jd[10]
## USB-UART Interface
#set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L19N_T3_VREF_16 Sch=uart_rxd_out
#set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L14N_T2_SRCC_16 Sch=uart_txd_in
## ChipKit Outer Digital Header
#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { ck_io0 }]; #IO_L16P_T2_CSI_B_14 Sch=ck_io[0]
#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { ck_io1 }]; #IO_L18P_T2_A12_D28_14 Sch=ck_io[1]
#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { ck_io2 }]; #IO_L8N_T1_D12_14 Sch=ck_io[2]
#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { ck_io3 }]; #IO_L19P_T3_A10_D26_14 Sch=ck_io[3]
#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { ck_io4 }]; #IO_L5P_T0_D06_14 Sch=ck_io[4]
#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { ck_io5 }]; #IO_L14P_T2_SRCC_14 Sch=ck_io[5]
#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { ck_io6 }]; #IO_L14N_T2_SRCC_14 Sch=ck_io[6]
#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { ck_io7 }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=ck_io[7]
#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { ck_io8 }]; #IO_L11P_T1_SRCC_14 Sch=ck_io[8]
#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { ck_io9 }]; #IO_L10P_T1_D14_14 Sch=ck_io[9]
#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { ck_io10 }]; #IO_L18N_T2_A11_D27_14 Sch=ck_io[10]
#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { ck_io11 }]; #IO_L17N_T2_A13_D29_14 Sch=ck_io[11]
#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { ck_io12 }]; #IO_L12N_T1_MRCC_14 Sch=ck_io[12]
#set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { ck_io13 }]; #IO_L12P_T1_MRCC_14 Sch=ck_io[13]
## ChipKit Inner Digital Header
#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { ck_io26 }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=ck_io[26]
#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { ck_io27 }]; #IO_L16N_T2_A15_D31_14 Sch=ck_io[27]
#set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { ck_io28 }]; #IO_L6N_T0_D08_VREF_14 Sch=ck_io[28]
#set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { ck_io29 }]; #IO_25_14 Sch=ck_io[29]
#set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { ck_io30 }]; #IO_0_14 Sch=ck_io[30]
#set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { ck_io31 }]; #IO_L5N_T0_D07_14 Sch=ck_io[31]
#set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { ck_io32 }]; #IO_L13N_T2_MRCC_14 Sch=ck_io[32]
#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ck_io33 }]; #IO_L13P_T2_MRCC_14 Sch=ck_io[33]
#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { ck_io34 }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=ck_io[34]
#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { ck_io35 }]; #IO_L11N_T1_SRCC_14 Sch=ck_io[35]
#set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { ck_io36 }]; #IO_L8P_T1_D11_14 Sch=ck_io[36]
#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { ck_io37 }]; #IO_L17P_T2_A14_D30_14 Sch=ck_io[37]
#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { ck_io38 }]; #IO_L7N_T1_D10_14 Sch=ck_io[38]
#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { ck_io39 }]; #IO_L7P_T1_D09_14 Sch=ck_io[39]
#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { ck_io40 }]; #IO_L9N_T1_DQS_D13_14 Sch=ck_io[40]
#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { ck_io41 }]; #IO_L9P_T1_DQS_14 Sch=ck_io[41]
## ChipKit Outer Analog Header - as Single-Ended Analog Inputs
## NOTE: These ports can be used as single-ended analog inputs with voltages from 0-3.3V (ChipKit analog pins A0-A5) or as digital I/O.
## WARNING: Do not use both sets of constraints at the same time!
## NOTE: The following constraints should be used with the XADC IP core when using these ports as analog inputs.
#set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { vaux4_n }]; #IO_L1N_T0_AD4N_35 Sch=ck_an_n[0] ChipKit pin=A0
#set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { vaux4_p }]; #IO_L1P_T0_AD4P_35 Sch=ck_an_p[0] ChipKit pin=A0
#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { vaux5_n }]; #IO_L3N_T0_DQS_AD5N_35 Sch=ck_an_n[1] ChipKit pin=A1
#set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { vaux5_p }]; #IO_L3P_T0_DQS_AD5P_35 Sch=ck_an_p[1] ChipKit pin=A1
#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { vaux6_n }]; #IO_L7N_T1_AD6N_35 Sch=ck_an_n[2] ChipKit pin=A2
#set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { vaux6_p }]; #IO_L7P_T1_AD6P_35 Sch=ck_an_p[2] ChipKit pin=A2
#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { vaux7_n }]; #IO_L9N_T1_DQS_AD7N_35 Sch=ck_an_n[3] ChipKit pin=A3
#set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { vaux7_p }]; #IO_L9P_T1_DQS_AD7P_35 Sch=ck_an_p[3] ChipKit pin=A3
#set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { vaux15_n }]; #IO_L10N_T1_AD15N_35 Sch=ck_an_n[4] ChipKit pin=A4
#set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { vaux15_p }]; #IO_L10P_T1_AD15P_35 Sch=ck_an_p[4] ChipKit pin=A4
#set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { vaux0_n }]; #IO_L1N_T0_AD0N_15 Sch=ck_an_n[5] ChipKit pin=A5
#set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { vaux0_p }]; #IO_L1P_T0_AD0P_15 Sch=ck_an_p[5] ChipKit pin=A5
## ChipKit Outer Analog Header - as Digital I/O
## NOTE: The following constraints should be used when using these ports as digital I/O.
#set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { ck_a0 }]; #IO_0_35 Sch=ck_a[0]
#set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { ck_a1 }]; #IO_L4P_T0_35 Sch=ck_a[1]
#set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { ck_a2 }]; #IO_L4N_T0_35 Sch=ck_a[2]
#set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { ck_a3 }]; #IO_L6P_T0_35 Sch=ck_a[3]
#set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { ck_a4 }]; #IO_L6N_T0_VREF_35 Sch=ck_a[4]
#set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { ck_a5 }]; #IO_L11P_T1_SRCC_35 Sch=ck_a[5]
## ChipKit Inner Analog Header - as Differential Analog Inputs
## NOTE: These ports can be used as differential analog inputs with voltages from 0-1.0V (ChipKit analog pins A6-A11) or as digital I/O.
## WARNING: Do not use both sets of constraints at the same time!
## NOTE: The following constraints should be used with the XADC core when using these ports as analog inputs.
#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { vaux12_p }]; #IO_L2P_T0_AD12P_35 Sch=ad_p[12] ChipKit pin=A6
#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { vaux12_n }]; #IO_L2N_T0_AD12N_35 Sch=ad_n[12] ChipKit pin=A7
#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { vaux13_p }]; #IO_L5P_T0_AD13P_35 Sch=ad_p[13] ChipKit pin=A8
#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { vaux13_n }]; #IO_L5N_T0_AD13N_35 Sch=ad_n[13] ChipKit pin=A9
#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { vaux14_p }]; #IO_L8P_T1_AD14P_35 Sch=ad_p[14] ChipKit pin=A10
#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { vaux14_n }]; #IO_L8N_T1_AD14N_35 Sch=ad_n[14] ChipKit pin=A11
## ChipKit Inner Analog Header - as Digital I/O
## NOTE: The following constraints should be used when using the inner analog header ports as digital I/O.
#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { ck_a6 }]; #IO_L2P_T0_AD12P_35 Sch=ad_p[12]
#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { ck_a7 }]; #IO_L2N_T0_AD12N_35 Sch=ad_n[12]
#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { ck_a8 }]; #IO_L5P_T0_AD13P_35 Sch=ad_p[13]
#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { ck_a9 }]; #IO_L5N_T0_AD13N_35 Sch=ad_n[13]
#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { ck_a10 }]; #IO_L8P_T1_AD14P_35 Sch=ad_p[14]
#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { ck_a11 }]; #IO_L8N_T1_AD14N_35 Sch=ad_n[14]
## ChipKit SPI
#set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { ck_miso }]; #IO_L17N_T2_35 Sch=ck_miso
#set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { ck_mosi }]; #IO_L17P_T2_35 Sch=ck_mosi
#set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { ck_sck }]; #IO_L18P_T2_35 Sch=ck_sck
#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { ck_ss }]; #IO_L16N_T2_35 Sch=ck_ss
## ChipKit I2C
#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { ck_scl }]; #IO_L4P_T0_D04_14 Sch=ck_scl
#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { ck_sda }]; #IO_L4N_T0_D05_14 Sch=ck_sda
#set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { scl_pup }]; #IO_L9N_T1_DQS_AD3N_15 Sch=scl_pup
#set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports { sda_pup }]; #IO_L9P_T1_DQS_AD3P_15 Sch=sda_pup
## Misc. ChipKit Ports
#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { ck_ioa }]; #IO_L10N_T1_D15_14 Sch=ck_ioa
set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { IO_RST_N }]; #IO_L16P_T2_35 Sch=ck_rst
## SMSC Ethernet PHY
#set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { eth_col }]; #IO_L16N_T2_A27_15 Sch=eth_col
#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { eth_crs }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=eth_crs
#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { eth_mdc }]; #IO_L14N_T2_SRCC_15 Sch=eth_mdc
#set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { eth_mdio }]; #IO_L17P_T2_A26_15 Sch=eth_mdio
#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { eth_ref_clk }]; #IO_L22P_T3_A17_15 Sch=eth_ref_clk
#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { eth_rstn }]; #IO_L20P_T3_A20_15 Sch=eth_rstn
#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_clk }]; #IO_L14P_T2_SRCC_15 Sch=eth_rx_clk
#set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_dv }]; #IO_L13N_T2_MRCC_15 Sch=eth_rx_dv
#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[0] }]; #IO_L21N_T3_DQS_A18_15 Sch=eth_rxd[0]
#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[1] }]; #IO_L16P_T2_A28_15 Sch=eth_rxd[1]
#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[2] }]; #IO_L21P_T3_DQS_15 Sch=eth_rxd[2]
#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[3] }]; #IO_L18N_T2_A23_15 Sch=eth_rxd[3]
#set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxerr }]; #IO_L20N_T3_A19_15 Sch=eth_rxerr
#set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_clk }]; #IO_L13P_T2_MRCC_15 Sch=eth_tx_clk
#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_en }]; #IO_L19N_T3_A21_VREF_15 Sch=eth_tx_en
#set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[0] }]; #IO_L15P_T2_DQS_15 Sch=eth_txd[0]
#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[1] }]; #IO_L19P_T3_A22_15 Sch=eth_txd[1]
#set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[2] }]; #IO_L17N_T2_A25_15 Sch=eth_txd[2]
#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[3] }]; #IO_L18P_T2_A24_15 Sch=eth_txd[3]
## Quad SPI Flash
#set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { qspi_cs }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_cs
#set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0]
#set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1]
#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2]
#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3]
## Power Measurements
#set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports { vsnsvu_n }]; #IO_L7N_T1_AD2N_15 Sch=ad_n[2]
#set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports { vsnsvu_p }]; #IO_L7P_T1_AD2P_15 Sch=ad_p[2]
#set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { vsns5v0_n }]; #IO_L3N_T0_DQS_AD1N_15 Sch=ad_n[1]
#set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { vsns5v0_p }]; #IO_L3P_T0_DQS_AD1P_15 Sch=ad_p[1]
#set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { isns5v0_n }]; #IO_L5N_T0_AD9N_15 Sch=ad_n[9]
#set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { isns5v0_p }]; #IO_L5P_T0_AD9P_15 Sch=ad_p[9]
#set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_n }]; #IO_L8N_T1_AD10N_15 Sch=ad_n[10]
#set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_p }]; #IO_L8P_T1_AD10P_15 Sch=ad_p[10]

View file

@ -1,145 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
module top_artya7 (
input IO_CLK,
input IO_RST_N,
output [3:0] LED
);
parameter int FPGAPowerAnalysis = 0;
// Choose 64kb memory for normal builds and 256kb for FPGAPowerAnalysis builds. The latter will
// not fit in the Arty A7-35 Board FPGA.
parameter int MEM_SIZE = FPGAPowerAnalysis == 0 ? 64 * 1024 : 256 * 1024;
parameter logic [31:0] MEM_START = 32'h00000000;
parameter logic [31:0] MEM_MASK = MEM_SIZE-1;
parameter SRAMInitFile = "";
logic clk_sys, rst_sys_n;
// Instruction connection to SRAM
logic instr_req;
logic instr_gnt;
logic instr_rvalid;
logic [31:0] instr_addr;
logic [31:0] instr_rdata;
// Data connection to SRAM
logic data_req;
logic data_gnt;
logic data_rvalid;
logic data_we;
logic [3:0] data_be;
logic [31:0] data_addr;
logic [31:0] data_wdata;
logic [31:0] data_rdata;
cve2_top #(
.RegFile(cve2_pkg::RegFileFPGA),
.DmHaltAddr(32'h00000000),
.DmExceptionAddr(32'h00000000)
) u_top (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
.test_en_i ('b0),
.scan_rst_ni (1'b1),
.ram_cfg_i ('b0),
.hart_id_i (32'b0),
// First instruction executed is at 0x0 + 0x80
.boot_addr_i (32'h00000000),
.instr_req_o (instr_req),
.instr_gnt_i (instr_gnt),
.instr_rvalid_i (instr_rvalid),
.instr_addr_o (instr_addr),
.instr_rdata_i (instr_rdata),
.instr_rdata_intg_i ('0),
.instr_err_i ('b0),
.data_req_o (data_req),
.data_gnt_i (data_gnt),
.data_rvalid_i (data_rvalid),
.data_we_o (data_we),
.data_be_o (data_be),
.data_addr_o (data_addr),
.data_wdata_o (data_wdata),
.data_wdata_intg_o (),
.data_rdata_i (data_rdata),
.data_rdata_intg_i ('0),
.data_err_i ('b0),
.irq_software_i (1'b0),
.irq_timer_i (1'b0),
.irq_external_i (1'b0),
.irq_fast_i (15'b0),
.irq_nm_i (1'b0),
.debug_req_i ('b0),
.crash_dump_o (),
.fetch_enable_i ('b1),
.alert_minor_o (),
.alert_major_internal_o(),
.alert_major_bus_o (),
.core_sleep_o ()
);
// SRAM block for instruction and data storage
ram_2p #(
.Depth(MEM_SIZE / 4),
.MemInitFile(SRAMInitFile)
) u_ram (
.clk_i (clk_sys),
.rst_ni(rst_sys_n),
.a_req_i (data_req),
.a_we_i (data_we),
.a_be_i (data_be),
.a_addr_i (data_addr),
.a_wdata_i (data_wdata),
.a_rvalid_o(data_rvalid),
.a_rdata_o (data_rdata),
.b_req_i (instr_req),
.b_we_i (1'b0),
.b_be_i (4'b0),
.b_addr_i (instr_addr),
.b_wdata_i (32'b0),
.b_rvalid_o(instr_rvalid),
.b_rdata_o (instr_rdata)
);
assign instr_gnt = instr_req;
assign data_gnt = data_req;
// Connect the LED output to the lower four bits of the most significant
// byte
logic [3:0] leds;
always_ff @(posedge clk_sys or negedge rst_sys_n) begin
if (!rst_sys_n) begin
leds <= 4'b0;
end else begin
if (data_req && data_we) begin
for (int i = 0; i < 4; i = i + 1) begin
if (data_be[i] == 1'b1) begin
leds <= data_wdata[i*8 +: 4];
end
end
end
end
end
assign LED = leds;
// Clock and reset
clkgen_xil7series
clkgen(
.IO_CLK,
.IO_RST_N,
.clk_sys,
.rst_sys_n
);
endmodule

View file

@ -1,64 +0,0 @@
CAPI=2:
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:cve2:top_artya7:0.1"
description: "Ibex example toplevel for Arty A7 boards (both, -35 and -100)"
filesets:
files_rtl_artya7:
depend:
- lowrisc:cve2:cve2_top
- lowrisc:cve2:fpga_xilinx_shared
files:
- rtl/top_artya7.sv
file_type: systemVerilogSource
files_constraints:
files:
- data/pins_artya7.xdc
file_type: xdc
files_tcl:
files:
- util/vivado_setup_hooks.tcl : { file_type: tclSource }
- util/vivado_hook_write_bitstream_pre.tcl : { file_type: user, copyto: vivado_hook_write_bitstream_pre.tcl }
parameters:
# XXX: This parameter needs to be absolute, or relative to the *.runs/synth_1
# directory. It's best to pass it as absolute path when invoking fusesoc, e.g.
# --SRAMInitFile=$PWD/sw/led/led.vmem
# XXX: The VMEM file should be added to the sources of the Vivado project to
# make the Vivado dependency tracking work. However this requires changes to
# fusesoc first.
SRAMInitFile:
datatype: str
description: SRAM initialization file in vmem hex format
default: "../../../../../examples/sw/led/led.vmem"
paramtype: vlogparam
# For value definition, please see ip/prim/rtl/prim_pkg.sv
PRIM_DEFAULT_IMPL:
datatype: str
paramtype: vlogdefine
description: Primitives implementation to use, e.g. "prim_pkg::ImplGeneric".
FPGAPowerAnalysis:
datatype: int
paramtype: vlogparam
description: Enables custom power analysis scripts for Vivado.
targets:
synth:
default_tool: vivado
filesets:
- files_rtl_artya7
- files_constraints
- files_tcl
toplevel: top_artya7
parameters:
- SRAMInitFile
- PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx
- FPGAPowerAnalysis
tools:
vivado:
part: "xc7a100tcsg324-1" # Default to Arty A7-100

View file

@ -1,24 +0,0 @@
open_project ../../lowrisc_cve2_top_artya7_0.1.xpr
set saif_name "detailed_power.saif"
open_run impl_1
# Runs a post implementation functional simulation with the memory initialized with SRAMInitFile.
# Feeds clock (100mhz) and reset switch and records switching activity for 3ms.
set_property top top_artya7 [current_fileset sim_1]
launch_simulation -mode post-implementation -type functional
open_saif "$saif_name"
log_saif [get_objects -r *]
add_force {/top_artya7/IO_CLK} -radix bin {1 0ns} {0 5ns} -repeat_every 10ns
add_force {/top_artya7/IO_RST_N} -radix bin {1 0ns}
run 3ms
close_saif
# Reporting power using .saif generated above
open_run impl_1
set_operating_conditions -process maximum
read_saif "../../lowrisc_cve2_top_artya7_0.1.sim/sim_1/impl/func/xsim/$saif_name"
read_saif "../../lowrisc_cve2_top_artya7_0.1.sim/sim_1/impl/func/xsim/$saif_name" -strip_path top_artya7
set_units -power uW
report_power -name {detailed_power_report} -verbose -file post_implementation_power_result.log -hierarchical_depth 20

View file

@ -1,14 +0,0 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
# Setup hook scripts, to be called at various stages during the build process
# See Xilinx UG 894 ("Using Tcl Scripting") for documentation.
# fusesoc-generated workroot containing the Vivado project file
set workroot [pwd]
set vlogparam_list [get_property generic [get_filesets sources_1]]
set FPGAPowerAnalysis [regexp {FPGAPowerAnalysis} $vlogparam_list]
if {$FPGAPowerAnalysis == 1} {
set_property STEPS.WRITE_BITSTREAM.TCL.PRE "${workroot}/vivado_hook_write_bitstream_pre.tcl" [get_runs impl_1]
}

View file

@ -1,283 +0,0 @@
// Copyright 2023 Intrinsix Corp.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// ============================================================================
//
// Description : OBI to AHB-Lite Master Adaptor
// This adapter accepts OBI v1.5.0 transfers and translates them into
// AHB-lite (ARM IHI 0033C) transfers.
module obi2ahbm_adapter (
// Clock and reset
input hclk_i, // (I) AHB clock
input hresetn_i, // (I) AHB reset, active LOW
// AHB master interface
output logic [31:0] haddr_o, // (O) 32-bit AHB system address bus
output logic [2:0] hburst_o, // (O) Burst type
output logic hmastlock_o, // (O) Sequence lock
output logic [3:0] hprot_o, // (O) Protection control
output logic [2:0] hsize_o, // (O) Transfer size
output logic [1:0] htrans_o, // (O) Transfer type
output logic [31:0] hwdata_o, // (O) 32-bit AHB write data bus
output logic hwrite_o, // (O) Transfer direction
input logic [31:0] hrdata_i, // (I) 32-bit AHB read data bus
input logic hready_i, // (I) Status of transfer
input logic hresp_i, // (I) Transfer response
// Data interface from core
input logic data_req_i, // (I) Request ready
output logic data_gnt_o, // (O) The other side accepted the request
output logic data_rvalid_o, // (O) Read data valid when high
input logic data_we_i, // (I) Write enable (active HIGH)
input logic [3:0] data_be_i, // (I) Byte enable
input logic [31:0] data_addr_i, // (I) Address
input logic [31:0] data_wdata_i, // (I) Write data
output logic [31:0] data_rdata_o, // (O) Read data
output logic data_err_o, // (O) Error
input logic pending_dbus_xfer_i, // (I) Asserted if data bus is busy from other transactions
// Miscellaneous
input logic priv_mode_i // (I) Privilege mode (from core. 1=machine mode, 0=user mode)
);
// ********** //
// Parameters //
// ********** //
parameter HPROT_NONCACHEABLE = 1'b0;
parameter HPROT_NONBUFFERABLE = 1'b0;
parameter HPROT_DATAACCESS = 1'b1;
parameter MACHINE_MODE = 1'b1;
parameter HBURST_SINGLE = 3'b000;
parameter TIE_LO = 1'b0;
parameter AHB_FSM_WAIT = 2'b00;
parameter AHB_FSM_DATA = 2'b10;
// ********** //
// Wires/Regs //
// ********** //
logic [1:0] ahb_fsm_reg;
logic [1:0] ahb_fsm_reg_nxt;
logic [31:0] haddr_m_reg;
logic [3:0] hprot_m_reg;
logic [2:0] hsize_m_reg;
logic hwrite_m_reg;
logic data_err_o_nxt;
logic [31:0] data_rdata_o_reg;
logic [31:0] hwdata_m_nxt;
logic prev_data_gnt_o;
// ********************** //
// Continuous assignments //
// ********************** //
// These signals are unused, so OK that they are tied to a constant
// lint_checking TIELOG off
// Only single bursts are supported
assign hburst_o = HBURST_SINGLE;
// hmastlock_o is not used, so it is tied low
assign hmastlock_o = TIE_LO;
// lint_checking TIELOG on
// A grant should only happen on a request, and if the AHB side is ready
// to respond. Don't initiate an AHB xfer if the data bus is busy from
// other pending xfers
assign data_gnt_o = hready_i && data_req_i && !pending_dbus_xfer_i;
// The valid signal should only assert when transitioning to the DATA state
assign data_rvalid_o = ahb_fsm_reg == AHB_FSM_DATA ? hready_i : 1'b0;
// ************* //
// Clocked Logic //
// ************* //
always @ (posedge hclk_i or negedge hresetn_i) begin
if (!hresetn_i) begin
data_err_o <= 1'b0;
data_rdata_o_reg <= 32'h00000000;
haddr_m_reg <= 32'h00000000;
hprot_m_reg <= {HPROT_NONCACHEABLE, HPROT_NONBUFFERABLE, MACHINE_MODE, HPROT_DATAACCESS};
hsize_m_reg <= 3'b000;
// Write data needs to come one cycle after per AHB protocol
hwdata_o <= 32'h00000000;
hwrite_m_reg <= 1'b0;
ahb_fsm_reg <= AHB_FSM_WAIT;
prev_data_gnt_o <= 1'b0;
end
else begin
data_err_o <= data_err_o_nxt;
data_rdata_o_reg <= data_rdata_o;
haddr_m_reg <= haddr_o;
hprot_m_reg <= hprot_o;
hsize_m_reg <= hsize_o;
hwdata_o <= hwdata_m_nxt;
hwrite_m_reg <= hwrite_o;
ahb_fsm_reg <= ahb_fsm_reg_nxt;
if (!data_rvalid_o) begin
prev_data_gnt_o <= data_gnt_o | prev_data_gnt_o;
end else begin
prev_data_gnt_o <= data_gnt_o;
end
end
end
// ******************* //
// Combinational Logic //
// ******************* //
// Signal that the current request errored out and the read is invalid if
// an AHB error response is received
assign data_err_o_nxt = hresp_i;
//AHB Logic
always_comb begin
hprot_o = hprot_m_reg;
haddr_o = haddr_m_reg;
hwrite_o = hwrite_m_reg;
// lint_checking TIELOG off
// If htrans_m is not driven to non-seq while data_gnt_o is set
// then it should be idle and set to (2'b00)
htrans_o = 2'b00;
// lint_checking TIELOG on
hwdata_m_nxt = hwdata_o;
hsize_o = hsize_m_reg;
unique case (ahb_fsm_reg)
AHB_FSM_WAIT: begin
// Idles until data_gnt_o is received
// Once data_gnt_o is received, this is the address phase of AHB
// and all ahb signals are fed through from the core
if (data_gnt_o) begin
// lint_checking TIELOG off
// Non-bufferable, non-cacheable data accesses are supported. The
// privilege bit, hprot_o[1], is driven by the privilege mode
// that the core is currently in (1 for machine, 0 for user)
hprot_o = {HPROT_NONCACHEABLE, HPROT_NONBUFFERABLE, priv_mode_i, HPROT_DATAACCESS};
// lint_checking TIELOG on
// The address, transfer request, and write enable can be fed
// through from the core to the corresponding AHB signals. For
// htrans_o, if data_gnt_o is given, the ahb is in address phase,
// and the transaction is non-sequential (1'b10).
haddr_o = data_addr_i;
hwrite_o = data_we_i;
// lint_checking TIELOG off
htrans_o = 2'b10;
// lint_checking TIELOG on
// Write data needs to be in data phase (After data_gnt_o is de-asserted)
// So the data fromthe core is registered to save it for completing the transaction
hwdata_m_nxt = data_wdata_i;
// lint_checking TIELOG off
// Only word (32-bit), half-word (16-bit), or byte (8-bit)
// aligned transfers are supported. Invalid responses default to
hsize_o[2] = TIE_LO;
// lint_checking TIELOG on
hsize_o[1] = &data_be_i;
hsize_o[0] = (data_be_i[3] & data_be_i[2]) ^ (data_be_i[1] & data_be_i[0]);
end
end
AHB_FSM_DATA: begin
// DATA phase
// read data is fed through from the core
data_rdata_o = hrdata_i;
// If data_gnt_o is also given during the data phase, then it is also
// the subsequent address phase, so the necessary signals get
// passed through from the core
if (data_gnt_o) begin
// lint_checking TIELOG off
// Non-bufferable, non-cacheable data accesses are supported. The
// privilege bit, hprot_o[1], is driven by the privilege mode
// that the core is currently in (1 for machine, 0 for user)
hprot_o = {HPROT_NONCACHEABLE, HPROT_NONBUFFERABLE, priv_mode_i, HPROT_DATAACCESS};
// lint_checking TIELOG on
// The address, transfer request, and write enable can be fed
// through from the core to the corresponding AHB signals. For
// htrans_o, if data_gnt_o is given, the ahb is in address phase,
// and the transaction is non-sequential (1'b10).
haddr_o = data_addr_i;
hwrite_o = data_we_i;
// lint_checking TIELOG off
htrans_o = 2'b10;
// lint_checking TIELOG on
// Write data needs to be in data phase (After data_gnt_o is de-asserted)
// So the data fromthe core is registered to save it for completing the transaction
hwdata_m_nxt = data_wdata_i;
// lint_checking TIELOG off
// Only word (32-bit), half-word (16-bit), or byte (8-bit)
// aligned transfers are supported. Invalid responses default to
hsize_o[2] = TIE_LO;
// lint_checking TIELOG on
hsize_o[1] = &data_be_i;
hsize_o[0] = (data_be_i[3] & data_be_i[2]) ^ (data_be_i[1] & data_be_i[0]);
end
end
default: begin
hprot_o = {HPROT_NONCACHEABLE, HPROT_NONBUFFERABLE, priv_mode_i, HPROT_DATAACCESS};
haddr_o = data_addr_i;
hwrite_o = data_we_i;
htrans_o = 2'b00;
hsize_o = {TIE_LO,TIE_LO,TIE_LO};
end
endcase
end
//FSM
always_comb begin
ahb_fsm_reg_nxt = ahb_fsm_reg;
unique case (ahb_fsm_reg)
// IDLE/ADDRESS phase
// Waits until "ADDRESS Phase" occurs during data_gnt_o
AHB_FSM_WAIT: begin
if (data_gnt_o) begin
ahb_fsm_reg_nxt = AHB_FSM_DATA;
end
end
// DATA/ADDRESS phase
// DATA phase for alread started transaction.
// If data_gnt_o it is also the ADDRESS phase for the next set of data so it stays
// in the data phase on the next cycle
AHB_FSM_DATA: begin
if (data_rvalid_o) begin
if (data_gnt_o) begin
ahb_fsm_reg_nxt = AHB_FSM_DATA;
end else begin
ahb_fsm_reg_nxt = AHB_FSM_WAIT;
end
end
end
default: begin
ahb_fsm_reg_nxt = ahb_fsm_reg;
end
endcase
end
// lint_checking TRNMBT on
// lint_checking HASUPC on
endmodule : obi2ahbm_adapter

View file

@ -1,146 +0,0 @@
# Ibex Simple System
Simple System gives you an Ibex based system simulated by Verilator that can
run stand-alone binaries. It contains:
* An Ibex Core
* A single memory for instructions and data
* A basic peripheral to write ASCII output to a file and halt simulation from software
* A basic timer peripheral capable of generating interrupts based on the RISC-V Machine Timer Registers (see RISC-V Privileged Specification, version 1.11, Section 3.1.10)
* A software framework to build programs for it
## Prerequisites
* [Verilator](https://www.veripool.org/wiki/verilator)
Note Linux package managers may have Verilator but often a very old version
that is not suitable. It is recommended Verilator is built from source.
* The Python dependencies of this repository.
Install them with `pip3 install -U -r python-requirements.txt` from the
repository root.
* RISC-V Compiler Toolchain - lowRISC provides a pre-built GCC based toolchain
<https://github.com/lowRISC/lowrisc-toolchains/releases>
* libelf and its development libraries.
On Debian/Ubuntu, install it by running `apt-get install libelf-dev`.
* srecord.
On Debian/Ubuntu, install it by running `apt-get install srecord`.
(Optional, needed for generating a vmem file)
## Building Simulation
The Simple System simulator binary can be built via FuseSoC. From the Ibex
repository root run:
```
fusesoc --cores-root=. run --target=sim --setup --build lowrisc:cve2:cve2_simple_system --RV32E=0 --RV32M=cve2_pkg::RV32MFast
```
## Building Software
Simple System related software can be found in `examples/sw/simple_system`.
To build the hello world example, from the Ibex reposistory root run:
```
make -C examples/sw/simple_system/hello_test
```
The compiled program is available at
`examples/sw/simple_system/hello_test/hello_test.elf`. The same directory also
contains a Verilog memory file (vmem file) to be used with some simulators.
To build new software make a copy of the `hello_test` directory named as desired.
Look inside the Makefile for further instructions.
If using a toolchain other than the lowRISC pre-built one
`examples/sw/simple_system/common/common.mk` may need altering to point to the
correct compiler binaries.
## Running the Simulator
Having built the simulator and software, from the Ibex repository root run:
```
./build/lowrisc_cve2_cve2_simple_system_0/sim-verilator/Vcve2_simple_system [-t] --meminit=ram,<sw_elf_file>
```
`<sw_elf_file>` should be a path to an ELF file (or alternatively a vmem file)
built as described above. Use
`./examples/sw/simple_system/hello_test/hello_test.elf` to run the `hello_test`
binary.
Pass `-t` to get an FST trace of execution that can be viewed with
[GTKWave](http://gtkwave.sourceforge.net/). If using the `hello_test`
binary the simulator will halt itself, outputting some simulation
statistics:
```
Simulation statistics
=====================
Executed cycles: 633
Wallclock time: 0.013 s
Simulation speed: 48692.3 cycles/s (48.6923 kHz)
Performance Counters
====================
Cycles: 483
NONE: 0
Instructions Retired: 266
LSU Busy: 59
Fetch Wait: 16
Loads: 21
Stores: 38
Jumps: 46
Conditional Branches: 53
Taken Conditional Branches: 48
Compressed Instructions: 182
```
The simulator produces several output files
* `cve2_simple_system.log` - The ASCII output written via the output peripheral
* `cve2_simple_system_pcount.csv` - A CSV of the performance counters
* `trace_core_00000000.log` - An instruction trace of execution
## Simulating with Synopsys VCS
Similar to the Verilator flow the Simple System simulator binary can be built using:
```
fusesoc --cores-root=. run --target=sim --tool=vcs --setup --build lowrisc:cve2:cve2_simple_system --RV32E=0 --RV32M=cve2_pkg::RV32MFast --SRAMInitFile=`<sw_vmem_file>`
```
`<sw_vmem_file>` should be a path to a vmem file built as described above, use
`./examples/sw/simple_system/hello_test/hello_test.vmem` to run the `hello_test`
binary.
To run the simulator:
```
./build/lowrisc_cve2_cve2_simple_system_0/sim-vcs/lowrisc_cve2_cve2_simple_system_0
```
Pass `-gui` to use the DVE GUI.
## Simulating with Riviera-PRO
To build and run Simple System run:
```
fusesoc --cores-root=. run --target=sim --tool=rivierapro lowrisc:cve2:cve2_simple_system --RV32E=0 --RV32M=cve2_pkg::RV32MFast --SRAMInitFile=\"$(readlink -f <sw_vmem_file>)\"
```
`<sw_vmem_file>` should be a path to a vmem file built as described above, use
`./examples/sw/simple_system/hello_test/hello_test.vmem` to run the `hello_test`
binary.
## System Memory Map
| Address | Description |
|---------------------|--------------------------------------------------------------------------------------------------------|
| 0x20000 | ASCII Out, write ASCII characters here that will get output to the log file |
| 0x20008 | Simulator Halt, write 1 here to halt the simulation |
| 0x30000 | RISC-V timer `mtime` register |
| 0x30004 | RISC-V timer `mtimeh` register |
| 0x30008 | RISC-V timer `mtimecmp` register |
| 0x3000C | RISC-V timer `mtimecmph` register |
| 0x100000 0x1FFFFF | 1 MB memory for instruction and data. Execution starts at 0x100080, exception handler base is 0x100000 |

View file

@ -1,108 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include <cassert>
#include <fstream>
#include <iostream>
#include "Vcve2_simple_system__Syms.h"
#include "cve2_pcounts.h"
#include "cve2_simple_system.h"
#include "verilated_toplevel.h"
#include "verilator_memutil.h"
#include "verilator_sim_ctrl.h"
SimpleSystem::SimpleSystem(const char *ram_hier_path, int ram_size_words)
: _ram(ram_hier_path, ram_size_words, 4) {}
int SimpleSystem::Main(int argc, char **argv) {
bool exit_app;
int ret_code = Setup(argc, argv, exit_app);
if (exit_app) {
return ret_code;
}
Run();
if (!Finish()) {
return 1;
}
return 0;
}
std::string SimpleSystem::GetIsaString() const {
const Vcve2_simple_system &top = _top;
assert(top.cve2_simple_system);
std::string base = top.cve2_simple_system->RV32E ? "rv32e" : "rv32i";
std::string extensions = "c";
if (top.cve2_simple_system->RV32M)
extensions += "m";
// See the equivalent get_isa_string() function in core_cve2_base_test.sv for
// an explanation of the different ISA strings
switch (top.cve2_simple_system->RV32B) {
case 0: // RV32BNone
break;
case 1: // RV32BBalanced
extensions += "_Zba_Zbb_Zbs_Xbitmanip";
break;
case 2: // RV32BOTEarlGrey
case 3: // RV32BFull
extensions += "_Zba_Zbb_Zbc_Zbs_Xbitmanip";
break;
}
return base + extensions;
}
int SimpleSystem::Setup(int argc, char **argv, bool &exit_app) {
VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
simctrl.SetTop(&_top, &_top.IO_CLK, &_top.IO_RST_N,
VerilatorSimCtrlFlags::ResetPolarityNegative);
_memutil.RegisterMemoryArea("ram", 0x0, &_ram);
simctrl.RegisterExtension(&_memutil);
exit_app = false;
return simctrl.ParseCommandArgs(argc, argv, exit_app);
}
void SimpleSystem::Run() {
VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
std::cout << "Simulation of Ibex" << std::endl
<< "==================" << std::endl
<< std::endl;
simctrl.RunSimulation();
}
bool SimpleSystem::Finish() {
VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance();
if (!simctrl.WasSimulationSuccessful()) {
return false;
}
// Set the scope to the root scope, the cve2_pcount_string function otherwise
// doesn't know the scope itself. Could be moved to cve2_pcount_string, but
// would require a way to set the scope name from here, similar to MemUtil.
svSetScope(svGetScopeFromName("TOP.cve2_simple_system"));
std::cout << "\nPerformance Counters" << std::endl
<< "====================" << std::endl;
std::cout << cve2_pcount_string(false);
std::ofstream pcount_csv("cve2_simple_system_pcount.csv");
pcount_csv << cve2_pcount_string(true);
return true;
}

View file

@ -1,142 +0,0 @@
CAPI=2:
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:cve2:cve2_simple_system"
description: "Generic simple system for running binaries on ibex using verilator"
filesets:
files_simple_system:
depend:
- lowrisc:cve2:cve2_simple_system_core
files:
- cve2_simple_system_main.cc
file_type: cppSource
parameters:
RV32E:
datatype: int
paramtype: vlogparam
default: 0
description: "Enable the E ISA extension (reduced register set) [0/1]"
RV32M:
datatype: str
default: cve2_pkg::RV32MFast
paramtype: vlogdefine
description: "RV32M implementation parameter enum. See the cve2_pkg::rv32m_e enum in cve2_pkg.sv for permitted values."
RV32B:
datatype: str
default: cve2_pkg::RV32BNone
paramtype: vlogdefine
description: "Bitmanip implementation parameter enum. See the cve2_pkg::rv32b_e enum in cve2_pkg.sv for permitted values."
RegFile:
datatype: str
default: cve2_pkg::RegFileFF
paramtype: vlogdefine
description: "Register file implementation parameter enum. See the cve2_pkg::regfile_e enum in cve2_pkg.sv for permitted values."
ICache:
datatype: int
default: 0
paramtype: vlogparam
description: "Enable instruction cache"
ICacheECC:
datatype: int
default: 0
paramtype: vlogparam
description: "Enable ECC protection in instruction cache"
SRAMInitFile:
datatype: str
paramtype: vlogparam
description: "Path to a vmem file to initialize the RAM with"
SecureIbex:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables security hardening features (EXPERIMENTAL) [0/1]"
ICacheScramble:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]"
PMPEnable:
datatype: int
default: 0
paramtype: vlogparam
description: "Enable PMP"
PMPGranularity:
datatype: int
default: 0
paramtype: vlogparam
description: "Granularity of NAPOT range, 0 = 4 byte, 1 = byte, 2 = 16 byte, 3 = 32 byte etc"
PMPNumRegions:
datatype: int
default: 4
paramtype: vlogparam
description: "Number of PMP regions"
targets:
default: &default_target
filesets:
- files_simple_system
toplevel: cve2_simple_system
parameters:
- RV32E
- RV32M
- RV32B
- RegFile
- ICache
- ICacheScramble
- ICacheECC
- SecureIbex
- PMPEnable
- PMPGranularity
- PMPNumRegions
- SRAMInitFile
lint:
<<: *default_target
default_tool: verilator
tools:
verilator:
mode: lint-only
verilator_options:
- "-Wall"
# RAM primitives wider than 64bit (required for ECC) fail to build in
# Verilator without increasing the unroll count (see Verilator#1266)
- "--unroll-count 72"
sim:
<<: *default_target
default_tool: verilator
tools:
vcs:
vcs_options:
- '-xlrm uniq_prior_final'
- '-debug_access+r'
verilator:
mode: cc
verilator_options:
# Disabling tracing reduces compile times but doesn't have a
# huge influence on runtime performance.
- '--trace'
- '--trace-fst' # this requires -DVM_TRACE_FMT_FST in CFLAGS below!
- '--trace-structs'
- '--trace-params'
- '--trace-max-array 1024'
- '-CFLAGS "-std=c++11 -Wall -DVM_TRACE_FMT_FST -DTOPLEVEL_NAME=cve2_simple_system -g"'
- '-LDFLAGS "-pthread -lutil -lelf"'
- "-Wall"
- "-Wwarn-IMPERFECTSCH"
# RAM primitives wider than 64bit (required for ECC) fail to build in
# Verilator without increasing the unroll count (see Verilator#1266)
- "--unroll-count 72"

View file

@ -1,26 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "verilated_toplevel.h"
#include "verilator_memutil.h"
class SimpleSystem {
public:
SimpleSystem(const char *ram_hier_path, int ram_size_words);
virtual ~SimpleSystem() {}
virtual int Main(int argc, char **argv);
// Return an ISA string, as understood by Spike, for the system being
// simulated.
std::string GetIsaString() const;
protected:
cve2_simple_system _top;
VerilatorMemUtil _memutil;
MemArea _ram;
virtual int Setup(int argc, char **argv, bool &exit_app);
virtual void Run();
virtual bool Finish();
};

View file

@ -1,35 +0,0 @@
CAPI=2:
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:cve2:cve2_simple_system_core"
description: "Generic simple system for running binaries on ibex using verilator"
filesets:
files_sim:
depend:
- lowrisc:cve2:cve2_top_tracing
- lowrisc:cve2:sim_shared
files:
- rtl/cve2_simple_system.sv
file_type: systemVerilogSource
files_verilator:
depend:
- lowrisc:dv_verilator:memutil_verilator
- lowrisc:dv_verilator:simutil_verilator
- lowrisc:dv_verilator:cve2_pcounts
files:
- cve2_simple_system.cc: { file_type: cppSource }
- cve2_simple_system.h: { file_type: cppSource, is_include_file: true}
- lint/verilator_waiver.vlt: {file_type: vlt}
files_lint_verible:
files:
- lint/verible_waiver.vbw: {file_type: veribleLintWaiver}
targets:
default:
filesets:
- tool_veriblelint ? (files_lint_verible)
- files_sim
- tool_verilator ? (files_verilator)

View file

@ -1,13 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "cve2_simple_system.h"
int main(int argc, char **argv) {
SimpleSystem simple_system(
"TOP.cve2_simple_system.u_ram.u_ram.gen_generic.u_impl_generic",
1024 * 1024);
return simple_system.Main(argc, argv);
}

View file

@ -1 +0,0 @@
waive --rule=macro-name-style --location="cve2_simple_system.sv" --regex="RegFile"

View file

@ -1,40 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Lint waivers for processing simple_system RTL with Verilator
//
// This should be used for rules applying to things like testbench
// top-levels. For rules that apply to the actual design (files in the
// 'rtl' directory), see verilator_waiver_rtl.vlt in the same
// directory.
//
// See https://www.veripool.org/projects/verilator/wiki/Manual-verilator#CONFIGURATION-FILES
// for documentation.
//
// Important: This file must included *before* any other Verilog file is read.
// Otherwise, only global waivers are applied, but not file-specific waivers.
`verilator_config
// We have some boolean top-level parameters in e.g. simple_system.sv.
// When building with fusesoc, these get set with defines like
// -GRV32E=1 (rather than -GRV32E=1'b1), leading to warnings like:
//
// Operator VAR '<varname>' expects 1 bits on the Initial value, but
// Initial value's CONST '32'h1' generates 32 bits.
//
// This signoff rule ignores errors like this. Note that it only
// matches when you set a 1-bit value to a literal 1, so it won't hide
// silly mistakes like setting it to 2.
//
lint_off -rule WIDTH -file "*/rtl/cve2_simple_system.sv"
-match "*expects 1 bits*Initial value's CONST '32'h1'*"
// This isn't a waiver, as such, but rather tells Verilator to expose
// the given parameters' values to C++. This allows cosim to figure
// out what flavour of core it is running, which allows us to call
// Spike with the right ISA.
public -module "cve2_simple_system" -var "RV32E"
public -module "cve2_simple_system" -var "RV32M"
public -module "cve2_simple_system" -var "RV32B"

View file

@ -1,295 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// VCS does not support overriding enum and string parameters via command line. Instead, a `define
// is used that can be set from the command line. If no value has been specified, this gives a
// default. Other simulators don't take the detour via `define and can override the corresponding
// parameters directly.
`ifndef RV32M
`define RV32M cve2_pkg::RV32MFast
`endif
`ifndef RV32B
`define RV32B cve2_pkg::RV32BNone
`endif
`ifndef RegFile
`define RegFile cve2_pkg::RegFileFF
`endif
/**
* Ibex simple system
*
* This is a basic system consisting of an ibex, a 1 MB sram for instruction/data
* and a small memory mapped control module for outputting ASCII text and
* controlling/halting the simulation from the software running on the ibex.
*
* It is designed to be used with verilator but should work with other
* simulators, a small amount of work may be required to support the
* simulator_ctrl module.
*/
module cve2_simple_system (
input IO_CLK,
input IO_RST_N
);
parameter bit SecureIbex = 1'b0;
parameter bit ICacheScramble = 1'b0;
parameter bit PMPEnable = 1'b0;
parameter int unsigned PMPGranularity = 0;
parameter int unsigned PMPNumRegions = 4;
parameter bit RV32E = 1'b0;
parameter cve2_pkg::rv32m_e RV32M = `RV32M;
parameter cve2_pkg::rv32b_e RV32B = `RV32B;
parameter cve2_pkg::regfile_e RegFile = `RegFile;
parameter bit ICache = 1'b0;
parameter bit ICacheECC = 1'b0;
parameter SRAMInitFile = "";
logic clk_sys = 1'b0, rst_sys_n;
typedef enum logic {
CoreD
} bus_host_e;
typedef enum logic[1:0] {
Ram,
SimCtrl,
Timer
} bus_device_e;
localparam int NrDevices = 3;
localparam int NrHosts = 1;
// interrupts
logic timer_irq;
// host and device signals
logic host_req [NrHosts];
logic host_gnt [NrHosts];
logic [31:0] host_addr [NrHosts];
logic host_we [NrHosts];
logic [ 3:0] host_be [NrHosts];
logic [31:0] host_wdata [NrHosts];
logic host_rvalid [NrHosts];
logic [31:0] host_rdata [NrHosts];
logic host_err [NrHosts];
// devices (slaves)
logic device_req [NrDevices];
logic [31:0] device_addr [NrDevices];
logic device_we [NrDevices];
logic [ 3:0] device_be [NrDevices];
logic [31:0] device_wdata [NrDevices];
logic device_rvalid [NrDevices];
logic [31:0] device_rdata [NrDevices];
logic device_err [NrDevices];
// Device address mapping
logic [31:0] cfg_device_addr_base [NrDevices];
logic [31:0] cfg_device_addr_mask [NrDevices];
assign cfg_device_addr_base[Ram] = 32'h100000;
assign cfg_device_addr_mask[Ram] = ~32'hFFFFF; // 1 MB
assign cfg_device_addr_base[SimCtrl] = 32'h20000;
assign cfg_device_addr_mask[SimCtrl] = ~32'h3FF; // 1 kB
assign cfg_device_addr_base[Timer] = 32'h30000;
assign cfg_device_addr_mask[Timer] = ~32'h3FF; // 1 kB
// Instruction fetch signals
logic instr_req;
logic instr_gnt;
logic instr_rvalid;
logic [31:0] instr_addr;
logic [31:0] instr_rdata;
logic instr_err;
assign instr_gnt = instr_req;
assign instr_err = '0;
`ifdef VERILATOR
assign clk_sys = IO_CLK;
assign rst_sys_n = IO_RST_N;
`else
initial begin
rst_sys_n = 1'b0;
#8
rst_sys_n = 1'b1;
end
always begin
#1 clk_sys = 1'b0;
#1 clk_sys = 1'b1;
end
`endif
// Tie-off unused error signals
assign device_err[Ram] = 1'b0;
assign device_err[SimCtrl] = 1'b0;
bus #(
.NrDevices ( NrDevices ),
.NrHosts ( NrHosts ),
.DataWidth ( 32 ),
.AddressWidth ( 32 )
) u_bus (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
.host_req_i (host_req ),
.host_gnt_o (host_gnt ),
.host_addr_i (host_addr ),
.host_we_i (host_we ),
.host_be_i (host_be ),
.host_wdata_i (host_wdata ),
.host_rvalid_o (host_rvalid ),
.host_rdata_o (host_rdata ),
.host_err_o (host_err ),
.device_req_o (device_req ),
.device_addr_o (device_addr ),
.device_we_o (device_we ),
.device_be_o (device_be ),
.device_wdata_o (device_wdata ),
.device_rvalid_i (device_rvalid),
.device_rdata_i (device_rdata ),
.device_err_i (device_err ),
.cfg_device_addr_base,
.cfg_device_addr_mask
);
cve2_top_tracing #(
.SecureIbex ( SecureIbex ),
.ICacheScramble ( ICacheScramble ),
.PMPEnable ( PMPEnable ),
.PMPGranularity ( PMPGranularity ),
.PMPNumRegions ( PMPNumRegions ),
.MHPMCounterNum ( 29 ),
.RV32E ( RV32E ),
.RV32M ( RV32M ),
.RV32B ( RV32B ),
.RegFile ( RegFile ),
.ICache ( ICache ),
.ICacheECC ( ICacheECC ),
.DmHaltAddr ( 32'h00100000 ),
.DmExceptionAddr ( 32'h00100000 )
) u_top (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
.test_en_i ('b0),
.scan_rst_ni (1'b1),
.ram_cfg_i ('b0),
.hart_id_i (32'b0),
// First instruction executed is at 0x0 + 0x80
.boot_addr_i (32'h00100000),
.instr_req_o (instr_req),
.instr_gnt_i (instr_gnt),
.instr_rvalid_i (instr_rvalid),
.instr_addr_o (instr_addr),
.instr_rdata_i (instr_rdata),
.instr_rdata_intg_i ('0),
.instr_err_i (instr_err),
.data_req_o (host_req[CoreD]),
.data_gnt_i (host_gnt[CoreD]),
.data_rvalid_i (host_rvalid[CoreD]),
.data_we_o (host_we[CoreD]),
.data_be_o (host_be[CoreD]),
.data_addr_o (host_addr[CoreD]),
.data_wdata_o (host_wdata[CoreD]),
.data_wdata_intg_o (),
.data_rdata_i (host_rdata[CoreD]),
.data_rdata_intg_i ('0),
.data_err_i (host_err[CoreD]),
.irq_software_i (1'b0),
.irq_timer_i (timer_irq),
.irq_external_i (1'b0),
.irq_fast_i (15'b0),
.irq_nm_i (1'b0),
.scramble_key_valid_i ('0),
.scramble_key_i ('0),
.scramble_nonce_i ('0),
.scramble_req_o (),
.debug_req_i ('b0),
.crash_dump_o (),
.double_fault_seen_o (),
.fetch_enable_i (cve2_pkg::FetchEnableOn),
.alert_minor_o (),
.alert_major_internal_o (),
.alert_major_bus_o (),
.core_sleep_o ()
);
// SRAM block for instruction and data storage
ram_2p #(
.Depth(1024*1024/4),
.MemInitFile(SRAMInitFile)
) u_ram (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
.a_req_i (device_req[Ram]),
.a_we_i (device_we[Ram]),
.a_be_i (device_be[Ram]),
.a_addr_i (device_addr[Ram]),
.a_wdata_i (device_wdata[Ram]),
.a_rvalid_o (device_rvalid[Ram]),
.a_rdata_o (device_rdata[Ram]),
.b_req_i (instr_req),
.b_we_i (1'b0),
.b_be_i (4'b0),
.b_addr_i (instr_addr),
.b_wdata_i (32'b0),
.b_rvalid_o (instr_rvalid),
.b_rdata_o (instr_rdata)
);
simulator_ctrl #(
.LogName("cve2_simple_system.log")
) u_simulator_ctrl (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
.req_i (device_req[SimCtrl]),
.we_i (device_we[SimCtrl]),
.be_i (device_be[SimCtrl]),
.addr_i (device_addr[SimCtrl]),
.wdata_i (device_wdata[SimCtrl]),
.rvalid_o (device_rvalid[SimCtrl]),
.rdata_o (device_rdata[SimCtrl])
);
timer #(
.DataWidth (32),
.AddressWidth (32)
) u_timer (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
.timer_req_i (device_req[Timer]),
.timer_we_i (device_we[Timer]),
.timer_be_i (device_be[Timer]),
.timer_addr_i (device_addr[Timer]),
.timer_wdata_i (device_wdata[Timer]),
.timer_rvalid_o (device_rvalid[Timer]),
.timer_rdata_o (device_rdata[Timer]),
.timer_err_o (device_err[Timer]),
.timer_intr_o (timer_irq)
);
export "DPI-C" function mhpmcounter_get;
function automatic longint unsigned mhpmcounter_get(int index);
return u_top.u_cve2_top.u_cve2_core.cs_registers_i.mhpmcounter[index];
endfunction
endmodule

View file

@ -1,108 +0,0 @@
#!/bin/bash
set -u
set -e
# This is a simple bash script to allow you to run a binary compiled
# for the simple_system environment using Spike.
#
error() {
echo >&2 "$@"
exit 1
}
usage () {
echo >&2 "Usage: spike-simple-system [-h] [-v] [-n] [--] [options] <elf>"
echo >&2
echo >&2 " Where <elf> is the path to an ELF binary that was"
echo >&2 " compiled for the simple_system environment. Any arguments "
echo >&2 " in <options> will be passed to Spike after those to set up "
echo >&2 " the environment for simple_system tests."
echo >&2
echo >&2 " If the -v argument is passed, the Spike command will be "
echo >&2 " echoed to stderr before it runs. If the -n argument is passed "
echo >&2 " (which implies -v), we don't actually run the command."
echo >&2
echo >&2 " This will write the Spike instruction log to stderr."
exit $1
}
declare -a opts
opts=()
verbose=0
dryrun=0
at_start=1
# We can be rather lazy when building our command line here, and don't
# need to distinguish between [options] and <elf>, since they end up
# appended to the Spike command line in the same order.
while [ $# != 0 ]; do
if [ $at_start = 1 ]; then
case "$1" in
--help|-h)
usage 0
;;
--verbose|-v)
verbose=1
;;
--dry-run|-n)
dryrun=1
verbose=1
;;
--)
at_start=0
;;
*)
at_start=0
opts=("$1")
;;
esac
else
opts+=("$1")
fi
shift
done
# If opts is empty, that's definitely an error (since the <elf>
# parameter was compulsory). Moan here.
if [ ${#opts[*]} = 0 ]; then
usage 1
fi
# Time to figure out how to call the Spike binary. If the user has set
# SPIKE_PATH, we should obey that. Otherwise, we'll just assume that
# they've got their PATH set up sensibly.
if [ x"$SPIKE_PATH" = x ]; then
spike='spike'
else
spike="$SPIKE_PATH/spike"
fi
# Here are the Spike options you need to run in a simple_system world.
declare -a ss_opts
ss_opts=(--isa=rv32imc
--log-commits
-l
-m0x10000:0x30000,0x100000:0x100000)
cmd=("$spike" "${ss_opts[@]}" "${opts[@]}")
if [ $verbose = 1 ]; then
# Echo the command that we're going to run in the same style as
# 'set -x' would.
echo >&2 + "${cmd[@]}"
fi
if [ $dryrun = 1 ]; then
exit 0
fi
exec "${cmd[@]}"

View file

@ -1,6 +0,0 @@
*.o
*.bin
*.dis
*.elf
*.vmem
*.d

View file

@ -1,117 +0,0 @@
# Benchmarks
This directory contains benchmarks that can be run on ibex simple system.
Benchmarks may rely on code external to this directory (e.g. it may be found in
`vendor/`) see the specific benchmark information below for details on how to
build and run each benchmark and where benchmark code is located.
## Building Simulation
All of these benchmarks run on Simple System. A verilator simulation suitable
for running them can be built with:
```
fusesoc --cores-root=. run --target=sim --setup --build lowrisc:cve2:cve2_simple_system --RV32E=0 --RV32M=cve2_pkg::RV32MFast
```
See examples/simple_system/README.md for full details.
## CoreMark
CoreMark (https://www.eembc.org/coremark/ https://github.com/eembc/coremark) is
an industry standard benchmark with results available for a wide variety of
systems.
The CoreMark source is vendored into the Ibex repository at
`vendor/eembc_coremark`. Support structure and a makefile to build CoreMark for
running on simple system is found in `examples/sw/benchmarks/coremark`.
To build CoreMark:
```
make -C ./examples/sw/benchmarks/coremark/
```
To run CoreMark (after building a suitable simulator binary, see above):
```
build/lowrisc_cve2_cve2_simple_system_0/sim-verilator/Vcve2_simple_system --meminit=ram,examples/sw/benchmarks/coremark/coremark.elf
```
The simulator outputs the performance counter values observed for the benchmark
(the counts do not include anything from pre or post benchmark loops).
CoreMark should output (to `cve2_simple_system.log`) something like the
following:
```
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 4244465
Total time (secs): 8
Iterations/Sec : 1
Iterations : 10
Compiler version : GCC
Compiler flags :
Memory location :
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0xfcaf
Correct operation validated. See README.md for run and reporting rules.
```
### Choice of ISA string
Different ISAs (to choose different RISC-V ISA extensions) can be selected by
passing the desired ISA string into `RV_ISA` when invoking make.
```
make -C ./examples/sw/benchmarks/coremark clean
make -C ./examples/sw/benchmarks/coremark RV_ISA=rv32imc
```
This will build CoreMark using the 'C' extension (compressed instructions).
When changing `RV_ISA`, you must clean out any old build with `make clean` and
rebuild.
The following ISA strings give the best performance for the Ibex configurations
listed in the README:
| Config | Best ISA |
|----------------------|----------|
| "small" | rv32im |
| "maxperf" | rv32im |
| "maxperf-pmp-bmfull" | rv32imcb |
### CoreMark score
A CoreMark score is given as the number of iterations executed per second. The
CoreMark binary is hard-coded to execute 10 iterations (see
`examples/sw/benchmarks/coremark/Makefile` if you wish to alter this). To obtain
a useful CoreMark score from the simulation you need to choose a clock speed the
Ibex implementation you are interested in would run at, e.g. 100 MHz, taking
the above example:
* 10 iterations take 4244465 clock cycles
* So at 100 MHz Ibex would execute (100 * 10^6) / (4244465 / 10) = 235.6
Iterations in 1 second.
* CoreMark (at 100 MHz) is 235.6
CoreMark/MHz is often used instead of a raw CoreMark score. The example above
gives a CoreMark/MHz of 2.36 (235.6 / 100 rounded to 2 decimal places).
To directly produce CoreMark/MHz from the number of iterations (I) and total
ticks (T) use the follow formula:
```
CoreMark/MHz = (10 ^ 6) * I / T
```
Note that `core_main.c` from CoreMark has had a minor modification to prevent it
from reporting an error if it executes for less than 10 seconds. This violates
the run reporting rules (though does not effect benchmark execution). It is
trivial to restore `core_main.c` to the version supplied by EEMBC in the
CoreMark repository if an official result is desired.

View file

@ -1,19 +0,0 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# Build coremark benchmark for Ibex Simple System
COREMARK_DIR = ../../../../vendor/eembc_coremark
export PORT_DIR = $(CURDIR)/ibex
export ITERATIONS = 10
export OPATH = $(CURDIR)/
# Export OPATH above doesn't seem to work so need to explicitly give it on the
# make command line
all:
$(MAKE) -C $(COREMARK_DIR)
clean:
$(MAKE) -C $(COREMARK_DIR) clean

View file

@ -1,189 +0,0 @@
// Copyright lowRISC contributors.
// Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
// Original Author: Shay Gal-on
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "core_portme.h"
#include "coremark.h"
#include "simple_system_common.h"
#if VALIDATION_RUN
volatile ee_s32 seed1_volatile = 0x3415;
volatile ee_s32 seed2_volatile = 0x3415;
volatile ee_s32 seed3_volatile = 0x66;
#endif
#if PERFORMANCE_RUN
volatile ee_s32 seed1_volatile = 0x0;
volatile ee_s32 seed2_volatile = 0x0;
volatile ee_s32 seed3_volatile = 0x66;
#endif
#if PROFILE_RUN
volatile ee_s32 seed1_volatile = 0x8;
volatile ee_s32 seed2_volatile = 0x8;
volatile ee_s32 seed3_volatile = 0x8;
#endif
volatile ee_s32 seed4_volatile = ITERATIONS;
volatile ee_s32 seed5_volatile = 0;
/* Porting : Timing functions
How to capture time and convert to seconds must be ported to whatever is
supported by the platform. e.g. Read value from on board RTC, read value from
cpu clock cycles performance counter etc. Sample implementation for standard
time.h and windows.h definitions included.
*/
CORETIMETYPE barebones_clock() {
ee_u32 result;
PCOUNT_READ(mcycle, result);
return result;
}
/* Define : TIMER_RES_DIVIDER
Divider to trade off timer resolution and total time that can be
measured.
Use lower values to increase resolution, but make sure that overflow
does not occur. If there are issues with the return value overflowing,
increase this value.
*/
#define GETMYTIME(_t) (*_t = barebones_clock())
#define MYTIMEDIFF(fin, ini) ((fin) - (ini))
#define TIMER_RES_DIVIDER 1
#define SAMPLE_TIME_IMPLEMENTATION 1
#define CLOCKS_PER_SEC 500000
#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
void pcount_read(uint32_t pcount_out[]) {
PCOUNT_READ(minstret, pcount_out[0]);
PCOUNT_READ(mhpmcounter3, pcount_out[1]);
PCOUNT_READ(mhpmcounter4, pcount_out[2]);
PCOUNT_READ(mhpmcounter5, pcount_out[3]);
PCOUNT_READ(mhpmcounter6, pcount_out[4]);
PCOUNT_READ(mhpmcounter7, pcount_out[5]);
PCOUNT_READ(mhpmcounter8, pcount_out[6]);
PCOUNT_READ(mhpmcounter9, pcount_out[7]);
PCOUNT_READ(mhpmcounter10, pcount_out[8]);
PCOUNT_READ(mhpmcounter11, pcount_out[9]);
PCOUNT_READ(mhpmcounter12, pcount_out[10]);
}
const char *pcount_names[] = {"Instructions Retired",
"LSU Busy",
"IFetch wait",
"Loads",
"Stores",
"Jumps",
"Branches",
"Taken Branches",
"Compressed Instructions",
"Multiply Wait",
"Divide Wait"};
const uint32_t pcount_num = sizeof(pcount_names) / sizeof(char *);
void dump_pcounts() {
uint32_t pcounts[pcount_num];
pcount_read(pcounts);
ee_printf(
"Performance Counters\n"
"--------------------\n");
for (uint32_t i = 0; i < pcount_num; ++i) {
ee_printf("%s: %u\n", pcount_names[i], pcounts[i]);
}
ee_printf("\n");
}
/** Define Host specific (POSIX), or target specific global time variables. */
static CORETIMETYPE start_time_val, stop_time_val;
/* Function : start_time
This function will be called right before starting the timed portion of
the benchmark.
Implementation may be capturing a system timer (as implemented in the
example code) or zeroing some system parameters - e.g. setting the cpu clocks
cycles to 0.
*/
void start_time(void) {
pcount_enable(0);
pcount_reset();
pcount_enable(1);
GETMYTIME(&start_time_val);
}
/* Function : stop_time
This function will be called right after ending the timed portion of the
benchmark.
Implementation may be capturing a system timer (as implemented in the
example code) or other system parameters - e.g. reading the current value of
cpu cycles counter.
*/
void stop_time(void) {
GETMYTIME(&stop_time_val);
pcount_enable(0);
}
/* Function : get_time
Return an abstract "ticks" number that signifies time on the system.
Actual value returned may be cpu cycles, milliseconds or any other
value, as long as it can be converted to seconds by <time_in_secs>. This
methodology is taken to accomodate any hardware or simulated platform. The
sample implementation returns millisecs by default, and the resolution is
controlled by <TIMER_RES_DIVIDER>
*/
CORE_TICKS get_time(void) {
CORE_TICKS elapsed = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
return elapsed;
}
/* Function : time_in_secs
Convert the value returned by get_time to seconds.
The <secs_ret> type is used to accomodate systems with no support for
floating point. Default implementation implemented by the EE_TICKS_PER_SEC
macro above.
*/
secs_ret time_in_secs(CORE_TICKS ticks) {
secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
return retval;
}
ee_u32 default_num_contexts = 1;
/* Function : portable_init
Target specific initialization code
Test for some common mistakes.
*/
void portable_init(core_portable *p, int *argc, char *argv[]) {
ee_printf("Ibex CoreMark platform init...\n");
if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
ee_printf(
"ERROR! Please define ee_ptr_int to a type that holds a pointer!\n");
}
if (sizeof(ee_u32) != 4) {
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
}
p->portable_id = 1;
}
/* Function : portable_fini
Target specific final code
*/
void portable_fini(core_portable *p) {
#ifndef SUPPRESS_PCOUNT_DUMP
dump_pcounts();
#endif
CORE_TICKS elapsed = get_time();
float coremark_mhz;
coremark_mhz = (1000000.0f * (float)ITERATIONS) / elapsed;
ee_printf("CoreMark / MHz: %f\n", coremark_mhz);
p->portable_id = 0;
}

View file

@ -1,201 +0,0 @@
// Copyright lowRISC contributors.
// Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
// Original Author: Shay Gal-on
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
/* Topic : Description
This file contains configuration constants required to execute on
different platforms
*/
#ifndef CORE_PORTME_H
#define CORE_PORTME_H
#include <sys/types.h>
extern unsigned int _stack_start;
/************************/
/* Data types and settings */
/************************/
/* Configuration : HAS_FLOAT
Define to 1 if the platform supports floating point.
*/
#ifndef HAS_FLOAT
#define HAS_FLOAT 1
#endif
/* Configuration : HAS_TIME_H
Define to 1 if platform has the time.h header file,
and implementation of functions thereof.
*/
#ifndef HAS_TIME_H
#define HAS_TIME_H 0
#endif
/* Configuration : USE_CLOCK
Define to 1 if platform has the time.h header file,
and implementation of functions thereof.
*/
#ifndef USE_CLOCK
#define USE_CLOCK 0
#endif
/* Configuration : HAS_STDIO
Define to 1 if the platform has stdio.h.
*/
#ifndef HAS_STDIO
#define HAS_STDIO 0
#endif
/* Configuration : HAS_PRINTF
Define to 1 if the platform has stdio.h and implements the printf
function.
*/
#ifndef HAS_PRINTF
#define HAS_PRINTF 0
#endif
/* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
Initialize these strings per platform
*/
#ifndef COMPILER_VERSION
#ifdef __GNUC__
#define COMPILER_VERSION "GCC"
#else
#define COMPILER_VERSION "unknown"
#endif
#endif
#ifndef COMPILER_FLAGS
#define COMPILER_FLAGS "" /* "Please put compiler flags here (e.g. -o3)" */
#endif
#ifndef MEM_LOCATION
#define MEM_LOCATION "STACK"
#endif
/* Data Types :
To avoid compiler issues, define the data types that need to be used for
8b, 16b and 32b in <core_portme.h>.
*Imprtant* :
ee_ptr_int needs to be the data type used to hold pointers, otherwise
CoreMark may fail!!!
*/
typedef signed short ee_s16;
typedef unsigned short ee_u16;
typedef signed int ee_s32;
typedef double ee_f32;
typedef unsigned char ee_u8;
typedef unsigned int ee_u32;
typedef ee_u32 ee_ptr_int;
typedef size_t ee_size_t;
#define NULL ((void *)0)
/* align_mem :
This macro is used to align an offset to point to a 32b value. It is
used in the Matrix algorithm to initialize the input memory blocks.
*/
#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3))
/* Configuration : CORE_TICKS
Define type of return from the timing functions.
*/
#define CORETIMETYPE ee_u32
typedef ee_u32 CORE_TICKS;
/* Configuration : SEED_METHOD
Defines method to get seed values that cannot be computed at compile
time.
Valid values :
SEED_ARG - from command line.
SEED_FUNC - from a system function.
SEED_VOLATILE - from volatile variables.
*/
#ifndef SEED_METHOD
#define SEED_METHOD SEED_VOLATILE
#endif
/* Configuration : MEM_METHOD
Defines method to get a block of memry.
Valid values :
MEM_MALLOC - for platforms that implement malloc and have malloc.h.
MEM_STATIC - to use a static memory array.
MEM_STACK - to allocate the data block on the stack (NYI).
*/
#ifndef MEM_METHOD
#define MEM_METHOD MEM_STACK
#endif
/* Configuration : MULTITHREAD
Define for parallel execution
Valid values :
1 - only one context (default).
N>1 - will execute N copies in parallel.
Note :
If this flag is defined to more then 1, an implementation for launching
parallel contexts must be defined.
Two sample implementations are provided. Use <USE_PTHREAD> or <USE_FORK>
to enable them.
It is valid to have a different implementation of <core_start_parallel>
and <core_end_parallel> in <core_portme.c>, to fit a particular architecture.
*/
#ifndef MULTITHREAD
#define MULTITHREAD 1
#define USE_PTHREAD 0
#define USE_FORK 0
#define USE_SOCKET 0
#endif
/* Configuration : MAIN_HAS_NOARGC
Needed if platform does not support getting arguments to main.
Valid values :
0 - argc/argv to main is supported
1 - argc/argv to main is not supported
Note :
This flag only matters if MULTITHREAD has been defined to a value
greater then 1.
*/
#ifndef MAIN_HAS_NOARGC
#define MAIN_HAS_NOARGC 0
#endif
/* Configuration : MAIN_HAS_NORETURN
Needed if platform does not support returning a value from main.
Valid values :
0 - main returns an int, and return value will be 0.
1 - platform does not support returning a value from main
*/
#ifndef MAIN_HAS_NORETURN
#define MAIN_HAS_NORETURN 0
#endif
/* Variable : default_num_contexts
Not used for this simple port, must cintain the value 1.
*/
extern ee_u32 default_num_contexts;
typedef struct CORE_PORTABLE_S { ee_u8 portable_id; } core_portable;
/* target specific init/fini */
void portable_init(core_portable *p, int *argc, char *argv[]);
void portable_fini(core_portable *p);
#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && \
!defined(VALIDATION_RUN)
#if (TOTAL_DATA_SIZE == 1200)
#define PROFILE_RUN 1
#elif (TOTAL_DATA_SIZE == 2000)
#define PERFORMANCE_RUN 1
#else
#define VALIDATION_RUN 1
#endif
#endif
int ee_printf(const char *fmt, ...);
#endif /* CORE_PORTME_H */

View file

@ -1,100 +0,0 @@
# Copyright lowRISC contributors.
# Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
# Original Author: Shay Gal-on
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
RV_ISA = rv32im
SUPPRESS_PCOUNT_DUMP = 0
OUTFILES = $(OPATH)coremark.dis $(OPATH)coremark.map $(OPATH)coremark.vmem
NAME = coremark
PORT_CLEAN := $(OUTFILES)
SIMPLE_SYSTEM_COMMON = ../../examples/sw/simple_system/common
EXT_SRCS = $(wildcard $(SIMPLE_SYSTEM_COMMON)/*.c)
CRT0 = $(SIMPLE_SYSTEM_COMMON)/crt0.S
LINKER_SCRIPT = $(SIMPLE_SYSTEM_COMMON)/link.ld
# Flag : OUTFLAG
# Use this flag to define how to to get an executable (e.g -o)
OUTFLAG = -o
# Flag : CC
# Use this flag to define compiler to use
CC = riscv32-unknown-elf-gcc
# Flag : LD
# Use this flag to define compiler to use
LD = riscv32-unknown-elf-ld
# Flag : AS
# Use this flag to define compiler to use
AS = riscv32-unknown-elf-as
# Flag : CFLAGS
# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
PORT_CFLAGS = -g -march=$(RV_ISA) -mabi=ilp32 -static -mcmodel=medlow -mtune=sifive-3-series \
-O3 -falign-functions=16 -funroll-all-loops \
-finline-functions -falign-jumps=4 \
-nostdlib -nostartfiles -ffreestanding -mstrict-align \
-DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 \
-DPERFORMANCE_RUN=1
ifeq ($(SUPPRESS_PCOUNT_DUMP),1)
PORT_CFLAGS += -DSUPPRESS_PCOUNT_DUMP
endif
FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
CFLAGS += $(PORT_CFLAGS) $(XCFLAGS) -I$(SIMPLE_SYSTEM_COMMON) -I$(PORT_DIR) -I.
#Flag : LFLAGS_END
# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
# Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
#SEPARATE_COMPILE=1
# Flag : SEPARATE_COMPILE
# You must also define below how to create an object file, and how to link.
OBJOUT = -o
LFLAGS =
ASFLAGS =
OFLAG = -o
COUT = -c
LFLAGS_END = -T $(LINKER_SCRIPT) -Xlinker -Map=$(OPATH)coremark.map -lm -lgcc
# Flag : PORT_SRCS
# Port specific source files can be added here
# You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler!
PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c ./barebones/cvt.c $(CRT0) $(EXT_SRCS)
vpath %.c $(PORT_DIR)
vpath %.s $(PORT_DIR)
# Flag : LOAD
# For a simple port, we assume self hosted compile and run, no load needed.
# Flag : RUN
# For a simple port, we assume self hosted compile and run, simple invocation of the executable
LOAD = echo "Please set LOAD to the process of loading the executable to the flash"
RUN = echo "Please set LOAD to the process of running the executable (e.g. via jtag, or board reset)"
OEXT = .o
EXE = .elf
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.c
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
$(OPATH)%$(OEXT) : %.c
$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
$(OPATH)$(PORT_DIR)/%$(OEXT) : %.s
$(AS) $(ASFLAGS) $< $(OBJOUT) $@
# Target : port_pre% and port_post%
# For the purpose of this simple port, no pre or post steps needed.
.PHONY : port_clean port_prebuild port_postbuild port_prerun port_postrun port_preload port_postload
port_postbuild:
riscv32-unknown-elf-objdump -SD $(OPATH)coremark.elf > $(OPATH)coremark.dis
riscv32-unknown-elf-objcopy -O binary $(OPATH)coremark.elf $(OPATH)coremark.bin
srec_cat $(OPATH)coremark.bin -binary -offset 0x0000 -byte-swap 4 -o $(OPATH)coremark.vmem -vmem
# FLAG : OPATH
# Path to the output folder. Default - current folder.
MKDIR = mkdir -p

View file

@ -1,579 +0,0 @@
// Copyright lowRISC contributors.
// Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
// Original Author: Shay Gal-on
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include <coremark.h>
#include <stdarg.h>
#include "simple_system_common.h"
#define ZEROPAD (1 << 0) /* Pad with zero */
#define SIGN (1 << 1) /* Unsigned/signed long */
#define PLUS (1 << 2) /* Show plus */
#define SPACE (1 << 3) /* Spacer */
#define LEFT (1 << 4) /* Left justified */
#define HEX_PREP (1 << 5) /* 0x */
#define UPPERCASE (1 << 6) /* 'ABCDEF' */
#define is_digit(c) ((c) >= '0' && (c) <= '9')
static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static ee_size_t strnlen(const char *s, ee_size_t count);
static ee_size_t strnlen(const char *s, ee_size_t count) {
const char *sc;
for (sc = s; *sc != '\0' && count--; ++sc)
;
return sc - s;
}
static int skip_atoi(const char **s) {
int i = 0;
while (is_digit(**s))
i = i * 10 + *((*s)++) - '0';
return i;
}
static char *number(char *str, long num, int base, int size, int precision,
int type) {
char c, sign, tmp[66];
char *dig = digits;
int i;
if (type & UPPERCASE)
dig = upper_digits;
if (type & LEFT)
type &= ~ZEROPAD;
if (base < 2 || base > 36)
return 0;
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN) {
if (num < 0) {
sign = '-';
num = -num;
size--;
} else if (type & PLUS) {
sign = '+';
size--;
} else if (type & SPACE) {
sign = ' ';
size--;
}
}
if (type & HEX_PREP) {
if (base == 16)
size -= 2;
else if (base == 8)
size--;
}
i = 0;
if (num == 0)
tmp[i++] = '0';
else {
while (num != 0) {
tmp[i++] = dig[((unsigned long)num) % (unsigned)base];
num = ((unsigned long)num) / (unsigned)base;
}
}
if (i > precision)
precision = i;
size -= precision;
if (!(type & (ZEROPAD | LEFT)))
while (size-- > 0)
*str++ = ' ';
if (sign)
*str++ = sign;
if (type & HEX_PREP) {
if (base == 8)
*str++ = '0';
else if (base == 16) {
*str++ = '0';
*str++ = digits[33];
}
}
if (!(type & LEFT))
while (size-- > 0)
*str++ = c;
while (i < precision--)
*str++ = '0';
while (i-- > 0)
*str++ = tmp[i];
while (size-- > 0)
*str++ = ' ';
return str;
}
static char *eaddr(char *str, unsigned char *addr, int size, int precision,
int type) {
char tmp[24];
char *dig = digits;
int i, len;
if (type & UPPERCASE)
dig = upper_digits;
len = 0;
for (i = 0; i < 6; i++) {
if (i != 0)
tmp[len++] = ':';
tmp[len++] = dig[addr[i] >> 4];
tmp[len++] = dig[addr[i] & 0x0F];
}
if (!(type & LEFT))
while (len < size--)
*str++ = ' ';
for (i = 0; i < len; ++i)
*str++ = tmp[i];
while (len < size--)
*str++ = ' ';
return str;
}
static char *iaddr(char *str, unsigned char *addr, int size, int precision,
int type) {
char tmp[24];
int i, n, len;
len = 0;
for (i = 0; i < 4; i++) {
if (i != 0)
tmp[len++] = '.';
n = addr[i];
if (n == 0)
tmp[len++] = digits[0];
else {
if (n >= 100) {
tmp[len++] = digits[n / 100];
n = n % 100;
tmp[len++] = digits[n / 10];
n = n % 10;
} else if (n >= 10) {
tmp[len++] = digits[n / 10];
n = n % 10;
}
tmp[len++] = digits[n];
}
}
if (!(type & LEFT))
while (len < size--)
*str++ = ' ';
for (i = 0; i < len; ++i)
*str++ = tmp[i];
while (len < size--)
*str++ = ' ';
return str;
}
#if HAS_FLOAT
char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
static void ee_bufcpy(char *d, char *s, int count);
void ee_bufcpy(char *pd, char *ps, int count) {
char *pe = ps + count;
while (ps != pe)
*pd++ = *ps++;
}
static void parse_float(double value, char *buffer, char fmt, int precision) {
int decpt, sign, exp, pos;
char *digits = NULL;
char cvtbuf[80];
int capexp = 0;
int magnitude;
if (fmt == 'G' || fmt == 'E') {
capexp = 1;
fmt += 'a' - 'A';
}
if (fmt == 'g') {
digits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
magnitude = decpt - 1;
if (magnitude < -4 || magnitude > precision - 1) {
fmt = 'e';
precision -= 1;
} else {
fmt = 'f';
precision -= decpt;
}
}
if (fmt == 'e') {
digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
if (sign)
*buffer++ = '-';
*buffer++ = *digits;
if (precision > 0)
*buffer++ = '.';
ee_bufcpy(buffer, digits + 1, precision);
buffer += precision;
*buffer++ = capexp ? 'E' : 'e';
if (decpt == 0) {
if (value == 0.0)
exp = 0;
else
exp = -1;
} else
exp = decpt - 1;
if (exp < 0) {
*buffer++ = '-';
exp = -exp;
} else
*buffer++ = '+';
buffer[2] = (exp % 10) + '0';
exp = exp / 10;
buffer[1] = (exp % 10) + '0';
exp = exp / 10;
buffer[0] = (exp % 10) + '0';
buffer += 3;
} else if (fmt == 'f') {
digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
if (sign)
*buffer++ = '-';
if (*digits) {
if (decpt <= 0) {
*buffer++ = '0';
*buffer++ = '.';
for (pos = 0; pos < -decpt; pos++)
*buffer++ = '0';
while (*digits)
*buffer++ = *digits++;
} else {
pos = 0;
while (*digits) {
if (pos++ == decpt)
*buffer++ = '.';
*buffer++ = *digits++;
}
}
} else {
*buffer++ = '0';
if (precision > 0) {
*buffer++ = '.';
for (pos = 0; pos < precision; pos++)
*buffer++ = '0';
}
}
}
*buffer = '\0';
}
static void decimal_point(char *buffer) {
while (*buffer) {
if (*buffer == '.')
return;
if (*buffer == 'e' || *buffer == 'E')
break;
buffer++;
}
if (*buffer) {
int n = strnlen(buffer, 256);
while (n > 0) {
buffer[n + 1] = buffer[n];
n--;
}
*buffer = '.';
} else {
*buffer++ = '.';
*buffer = '\0';
}
}
static void cropzeros(char *buffer) {
char *stop;
while (*buffer && *buffer != '.')
buffer++;
if (*buffer++) {
while (*buffer && *buffer != 'e' && *buffer != 'E')
buffer++;
stop = buffer--;
while (*buffer == '0')
buffer--;
if (*buffer == '.')
buffer--;
while (buffer != stop)
*++buffer = 0;
}
}
static char *flt(char *str, double num, int size, int precision, char fmt,
int flags) {
char tmp[80];
char c, sign;
int n, i;
// Left align means no zero padding
if (flags & LEFT)
flags &= ~ZEROPAD;
// Determine padding and sign char
c = (flags & ZEROPAD) ? '0' : ' ';
sign = 0;
if (flags & SIGN) {
if (num < 0.0) {
sign = '-';
num = -num;
size--;
} else if (flags & PLUS) {
sign = '+';
size--;
} else if (flags & SPACE) {
sign = ' ';
size--;
}
}
// Compute the precision value
if (precision < 0)
precision = 6; // Default precision: 6
// Convert floating point number to text
parse_float(num, tmp, fmt, precision);
if ((flags & HEX_PREP) && precision == 0)
decimal_point(tmp);
if (fmt == 'g' && !(flags & HEX_PREP))
cropzeros(tmp);
n = strnlen(tmp, 256);
// Output number with alignment and padding
size -= n;
if (!(flags & (ZEROPAD | LEFT)))
while (size-- > 0)
*str++ = ' ';
if (sign)
*str++ = sign;
if (!(flags & LEFT))
while (size-- > 0)
*str++ = c;
for (i = 0; i < n; i++)
*str++ = tmp[i];
while (size-- > 0)
*str++ = ' ';
return str;
}
#endif
static int ee_vsprintf(char *buf, const char *fmt, va_list args) {
int len;
unsigned long num;
int i, base;
char *str;
char *s;
int flags; // Flags to number()
int field_width; // Width of output field
int precision; // Min. # of digits for integers; max number of chars for from
// string
int qualifier; // 'h', 'l', or 'L' for integer fields
for (str = buf; *fmt; fmt++) {
if (*fmt != '%') {
*str++ = *fmt;
continue;
}
// Process flags
flags = 0;
repeat:
fmt++; // This also skips first '%'
switch (*fmt) {
case '-':
flags |= LEFT;
goto repeat;
case '+':
flags |= PLUS;
goto repeat;
case ' ':
flags |= SPACE;
goto repeat;
case '#':
flags |= HEX_PREP;
goto repeat;
case '0':
flags |= ZEROPAD;
goto repeat;
}
// Get field width
field_width = -1;
if (is_digit(*fmt))
field_width = skip_atoi(&fmt);
else if (*fmt == '*') {
fmt++;
field_width = va_arg(args, int);
if (field_width < 0) {
field_width = -field_width;
flags |= LEFT;
}
}
// Get the precision
precision = -1;
if (*fmt == '.') {
++fmt;
if (is_digit(*fmt))
precision = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
precision = va_arg(args, int);
}
if (precision < 0)
precision = 0;
}
// Get the conversion qualifier
qualifier = -1;
if (*fmt == 'l' || *fmt == 'L') {
qualifier = *fmt;
fmt++;
}
// Default base
base = 10;
switch (*fmt) {
case 'c':
if (!(flags & LEFT))
while (--field_width > 0)
*str++ = ' ';
*str++ = (unsigned char)va_arg(args, int);
while (--field_width > 0)
*str++ = ' ';
continue;
case 's':
s = va_arg(args, char *);
if (!s)
s = "<NULL>";
len = strnlen(s, precision);
if (!(flags & LEFT))
while (len < field_width--)
*str++ = ' ';
for (i = 0; i < len; ++i)
*str++ = *s++;
while (len < field_width--)
*str++ = ' ';
continue;
case 'p':
if (field_width == -1) {
field_width = 2 * sizeof(void *);
flags |= ZEROPAD;
}
str = number(str, (unsigned long)va_arg(args, void *), 16, field_width,
precision, flags);
continue;
case 'A':
flags |= UPPERCASE;
case 'a':
if (qualifier == 'l')
str = eaddr(str, va_arg(args, unsigned char *), field_width,
precision, flags);
else
str = iaddr(str, va_arg(args, unsigned char *), field_width,
precision, flags);
continue;
// Integer number formats - set up the flags and "break"
case 'o':
base = 8;
break;
case 'X':
flags |= UPPERCASE;
case 'x':
base = 16;
break;
case 'd':
case 'i':
flags |= SIGN;
case 'u':
break;
#if HAS_FLOAT
case 'f':
str = flt(str, va_arg(args, double), field_width, precision, *fmt,
flags | SIGN);
continue;
#endif
default:
if (*fmt != '%')
*str++ = '%';
if (*fmt)
*str++ = *fmt;
else
--fmt;
continue;
}
if (qualifier == 'l')
num = va_arg(args, unsigned long);
else if (flags & SIGN)
num = va_arg(args, int);
else
num = va_arg(args, unsigned int);
str = number(str, num, base, field_width, precision, flags);
}
*str = '\0';
return str - buf;
}
int ee_printf(const char *fmt, ...) {
char buf[256], *p;
va_list args;
int n = 0;
va_start(args, fmt);
ee_vsprintf(buf, fmt, args);
va_end(args);
p = buf;
while (*p) {
putchar(*p);
n++;
p++;
}
return n;
}

View file

@ -1,60 +0,0 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# Generate a baremetal application
PROGRAM ?= led
PROGRAM_CFLAGS = -Wall -g -Os
ARCH = rv32imc
# ARCH = rv32im # to disable compressed instructions
SRCS = $(PROGRAM).c
CC = riscv32-unknown-elf-gcc
CROSS_COMPILE = $(patsubst %-gcc,%-,$(CC))
OBJCOPY ?= $(CROSS_COMPILE)objcopy
OBJDUMP ?= $(CROSS_COMPILE)objdump
LINKER_SCRIPT ?= link.ld
CRT ?= crt0.S
CFLAGS ?= -march=$(ARCH) -mabi=ilp32 -static -mcmodel=medany \
-fvisibility=hidden -nostdlib -nostartfiles $(PROGRAM_CFLAGS)
OBJS := ${SRCS:.c=.o} ${CRT:.S=.o}
DEPS = $(OBJS:%.o=%.d)
OUTFILES = $(PROGRAM).elf $(PROGRAM).vmem $(PROGRAM).bin $(PROGRAM).dis
all: $(OUTFILES)
$(PROGRAM).elf: $(OBJS) $(LINKER_SCRIPT)
$(CC) $(CFLAGS) -T $(LINKER_SCRIPT) $(OBJS) -o $@ $(LIBS)
%.dis: %.elf
$(OBJDUMP) -SD $^ > $@
# Note: this target requires the srecord package to be installed.
# XXX: This could be replaced by objcopy once
# https://sourceware.org/bugzilla/show_bug.cgi?id=19921
# is widely available.
# XXX: Currently the start address 0x00000000 is hardcoded. It could/should be
# read from the elf file, but is lost in the bin file.
# Switching to objcopy will resolve that as well.
%.vmem: %.bin
srec_cat $^ -binary -offset 0x0000 -byte-swap 4 -o $@ -vmem
%.bin: %.elf
$(OBJCOPY) -O binary $^ $@
%.o: %.c
$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
%.o: %.S
$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
clean:
$(RM) -f *.o *.d
distclean: clean
$(RM) -f $(OUTFILES)

View file

@ -1,89 +0,0 @@
.section .text
default_exc_handler:
jal x0, default_exc_handler
reset_handler:
/* set all registers to zero */
mv x1, x0
mv x2, x1
mv x3, x1
mv x4, x1
mv x5, x1
mv x6, x1
mv x7, x1
mv x8, x1
mv x9, x1
mv x10, x1
mv x11, x1
mv x12, x1
mv x13, x1
mv x14, x1
mv x15, x1
mv x16, x1
mv x17, x1
mv x18, x1
mv x19, x1
mv x20, x1
mv x21, x1
mv x22, x1
mv x23, x1
mv x24, x1
mv x25, x1
mv x26, x1
mv x27, x1
mv x28, x1
mv x29, x1
mv x30, x1
mv x31, x1
/* stack initilization */
la x2, _stack_start
_start:
.global _start
/* clear BSS */
la x26, _bss_start
la x27, _bss_end
bge x26, x27, zero_loop_end
zero_loop:
sw x0, 0(x26)
addi x26, x26, 4
ble x26, x27, zero_loop
zero_loop_end:
main_entry:
/* jump to main program entry point (argc = argv = 0) */
addi x10, x0, 0
addi x11, x0, 0
jal x1, main
/* =================================================== [ exceptions ] === */
/* This section has to be down here, since we have to disable rvc for it */
.section .vectors, "ax"
.option norvc;
// external interrupts are handled by the same callback
// until compiler supports IRQ routines
.org 0x00
.rept 31
nop
.endr
jal x0, default_exc_handler
// reset vector
.org 0x80
jal x0, reset_handler
// illegal instruction exception
.org 0x84
jal x0, default_exc_handler
// ecall handler
.org 0x88
jal x0, default_exc_handler

View file

@ -1,47 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include <stdint.h>
#define CLK_FIXED_FREQ_HZ (50ULL * 1000 * 1000)
/**
* Delay loop executing within 8 cycles on ibex
*/
static void delay_loop_cve2(unsigned long loops) {
int out; /* only to notify compiler of modifications to |loops| */
asm volatile(
"1: nop \n" // 1 cycle
" nop \n" // 1 cycle
" nop \n" // 1 cycle
" nop \n" // 1 cycle
" addi %1, %1, -1 \n" // 1 cycle
" bnez %1, 1b \n" // 3 cycles
: "=&r" (out)
: "0" (loops)
);
}
static int usleep_cve2(unsigned long usec) {
unsigned long usec_cycles;
usec_cycles = CLK_FIXED_FREQ_HZ * usec / 1000 / 1000 / 8;
delay_loop_cve2(usec_cycles);
return 0;
}
static int usleep(unsigned long usec) {
return usleep_cve2(usec);
}
int main(int argc, char **argv) {
// The lowest four bits of the highest byte written to the memory region named
// "stack" are connected to the LEDs of the board.
volatile uint8_t *var = (volatile uint8_t *) 0x0000c010;
*var = 0x0a;
while (1) {
usleep(1000 * 1000); // 1000 ms
*var = ~(*var);
}
}

View file

@ -1,105 +0,0 @@
OUTPUT_ARCH(riscv)
/* required to correctly link newlib */
GROUP( -lc -lgloss -lgcc -lsupc++ )
SEARCH_DIR(.)
__DYNAMIC = 0;
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0xC000 /* 48 kB */
stack : ORIGIN = 0x0000C000, LENGTH = 0x4000 /* 16 kB */
}
/* Stack information variables */
_min_stack = 0x2000; /* 8K - minimum stack space to reserve */
_stack_len = LENGTH(stack);
_stack_start = ORIGIN(stack) + LENGTH(stack);
/* We have to align each sector to word boundaries as our current s19->slm
* conversion scripts are not able to handle non-word aligned sections. */
SECTIONS
{
.vectors :
{
. = ALIGN(4);
KEEP(*(.vectors))
} > rom
.text : {
. = ALIGN(4);
_stext = .;
*(.text)
*(.text.*)
_etext = .;
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
*(.lit)
*(.shdata)
. = ALIGN(4);
_endtext = .;
} > rom
.rodata : {
. = ALIGN(4);
*(.rodata);
*(.rodata.*)
} > rom
.shbss :
{
. = ALIGN(4);
*(.shbss)
} > rom
.data : {
. = ALIGN(4);
sdata = .;
_sdata = .;
*(.data);
*(.data.*)
edata = .;
_edata = .;
} > rom
.bss :
{
. = ALIGN(4);
_bss_start = .;
*(.bss)
*(.bss.*)
*(.sbss)
*(.sbss.*)
*(COMMON)
_bss_end = .;
} > rom
/* ensure there is enough room for stack */
.stack (NOLOAD): {
. = ALIGN(4);
. = . + _min_stack ;
. = ALIGN(4);
stack = . ;
_stack = . ;
} > stack
.stab 0 (NOLOAD) :
{
[ .stab ]
}
.stabstr 0 (NOLOAD) :
{
[ .stabstr ]
}
}

View file

@ -1,75 +0,0 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
COMMON_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
COMMON_SRCS = $(wildcard $(COMMON_DIR)/*.c)
INCS := -I$(COMMON_DIR)
# ARCH = rv32im # to disable compressed instructions
ARCH ?= rv32imc
ifdef PROGRAM
PROGRAM_C := $(PROGRAM).c
endif
SRCS = $(COMMON_SRCS) $(PROGRAM_C) $(EXTRA_SRCS)
C_SRCS = $(filter %.c, $(SRCS))
ASM_SRCS = $(filter %.S, $(SRCS))
CC = riscv32-unknown-elf-gcc
CROSS_COMPILE = $(patsubst %-gcc,%-,$(CC))
OBJCOPY ?= $(CROSS_COMPILE)objcopy
OBJDUMP ?= $(CROSS_COMPILE)objdump
LINKER_SCRIPT ?= $(COMMON_DIR)/link.ld
CRT ?= $(COMMON_DIR)/crt0.S
CFLAGS ?= -march=$(ARCH) -mabi=ilp32 -static -mcmodel=medany -Wall -g -Os\
-fvisibility=hidden -nostdlib -nostartfiles -ffreestanding $(PROGRAM_CFLAGS)
OBJS := ${C_SRCS:.c=.o} ${ASM_SRCS:.S=.o} ${CRT:.S=.o}
DEPS = $(OBJS:%.o=%.d)
ifdef PROGRAM
OUTFILES := $(PROGRAM).elf $(PROGRAM).vmem $(PROGRAM).bin
else
OUTFILES := $(OBJS)
endif
all: $(OUTFILES)
ifdef PROGRAM
$(PROGRAM).elf: $(OBJS) $(LINKER_SCRIPT)
$(CC) $(CFLAGS) -T $(LINKER_SCRIPT) $(OBJS) -o $@ $(LIBS)
.PHONY: disassemble
disassemble: $(PROGRAM).dis
endif
%.dis: %.elf
$(OBJDUMP) -fhSD $^ > $@
# Note: this target requires the srecord package to be installed.
# XXX: This could be replaced by objcopy once
# https://sourceware.org/bugzilla/show_bug.cgi?id=19921
# is widely available.
%.vmem: %.bin
srec_cat $^ -binary -offset 0x0000 -byte-swap 4 -o $@ -vmem
%.bin: %.elf
$(OBJCOPY) -O binary $^ $@
%.o: %.c
$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
%.o: %.S
$(CC) $(CFLAGS) -MMD -c $(INCS) -o $@ $<
clean:
$(RM) -f $(OBJS) $(DEPS)
distclean: clean
$(RM) -f $(OUTFILES)

View file

@ -1,102 +0,0 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#include "simple_system_regs.h"
.section .text
default_exc_handler:
jal x0, simple_exc_handler
timer_handler:
jal x0, simple_timer_handler
reset_handler:
/* set all registers to zero */
mv x1, x0
mv x2, x1
mv x3, x1
mv x4, x1
mv x5, x1
mv x6, x1
mv x7, x1
mv x8, x1
mv x9, x1
mv x10, x1
mv x11, x1
mv x12, x1
mv x13, x1
mv x14, x1
mv x15, x1
mv x16, x1
mv x17, x1
mv x18, x1
mv x19, x1
mv x20, x1
mv x21, x1
mv x22, x1
mv x23, x1
mv x24, x1
mv x25, x1
mv x26, x1
mv x27, x1
mv x28, x1
mv x29, x1
mv x30, x1
mv x31, x1
/* stack initilization */
la x2, _stack_start
_start:
.global _start
/* clear BSS */
la x26, _bss_start
la x27, _bss_end
bge x26, x27, zero_loop_end
zero_loop:
sw x0, 0(x26)
addi x26, x26, 4
ble x26, x27, zero_loop
zero_loop_end:
main_entry:
/* jump to main program entry point (argc = argv = 0) */
addi x10, x0, 0
addi x11, x0, 0
jal x1, main
/* Halt simulation */
li x5, SIM_CTRL_BASE + SIM_CTRL_CTRL
li x6, 1
sw x6, 0(x5)
/* If execution ends up here just put the core to sleep */
sleep_loop:
wfi
j sleep_loop
/* =================================================== [ exceptions ] === */
/* This section has to be down here, since we have to disable rvc for it */
.section .vectors, "ax"
.option norvc;
// All unimplemented interrupts/exceptions go to the default_exc_handler.
.org 0x00
.rept 7
jal x0, default_exc_handler
.endr
jal x0, timer_handler
.rept 23
jal x0, default_exc_handler
.endr
// reset vector
.org 0x80
jal x0, reset_handler

View file

@ -1,90 +0,0 @@
/* Copyright lowRISC contributors.
Licensed under the Apache License, Version 2.0, see LICENSE for details.
SPDX-License-Identifier: Apache-2.0 */
OUTPUT_ARCH(riscv)
MEMORY
{
/* Change this if you'd like different sizes. Arty A7-100(35) has a maximum of 607.5KB(225KB)
BRAM space. Configuration below is for maximum BRAM capacity with Artya A7-35 while letting
CoreMark run (.vmem of 152.8KB).
*/
ram : ORIGIN = 0x00100000, LENGTH = 0x30000 /* 192 kB */
stack : ORIGIN = 0x00130000, LENGTH = 0x8000 /* 32 kB */
}
/* Stack information variables */
_min_stack = 0x2000; /* 8K - minimum stack space to reserve */
_stack_len = LENGTH(stack);
_stack_start = ORIGIN(stack) + LENGTH(stack);
_entry_point = _vectors_start + 0x80;
ENTRY(_entry_point)
/* The tohost address is used by Spike for a magic "stop me now" message. This
is set to equal SIM_CTRL_CTRL (see simple_system_regs.h), which has that
effect in simple_system simulations. Note that it must be 8-byte aligned.
We don't read data back from Spike, so fromhost is set to some dummy value:
we place it just above the top of the stack.
*/
tohost = 0x20008;
fromhost = _stack_start + 0x10;
SECTIONS
{
.vectors :
{
. = ALIGN(4);
_vectors_start = .;
KEEP(*(.vectors))
_vectors_end = .;
} > ram
.text : {
. = ALIGN(4);
*(.text)
*(.text.*)
} > ram
.rodata : {
. = ALIGN(4);
/* Small RO data before large RO data */
*(.srodata)
*(.srodata.*)
*(.rodata);
*(.rodata.*)
} > ram
.data : {
. = ALIGN(4);
/* Small data before large data */
*(.sdata)
*(.sdata.*)
*(.data);
*(.data.*)
} > ram
.bss :
{
. = ALIGN(4);
_bss_start = .;
/* Small BSS before large BSS */
*(.sbss)
*(.sbss.*)
*(.bss)
*(.bss.*)
*(COMMON)
_bss_end = .;
} > ram
/* ensure there is enough room for stack */
.stack (NOLOAD): {
. = ALIGN(4);
. = . + _min_stack ;
. = ALIGN(4);
stack = . ;
_stack = . ;
} > stack
}

View file

@ -1,197 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "simple_system_common.h"
int putchar(int c) {
DEV_WRITE(SIM_CTRL_BASE + SIM_CTRL_OUT, (unsigned char)c);
return c;
}
int puts(const char *str) {
while (*str) {
putchar(*str++);
}
return 0;
}
void puthex(uint32_t h) {
int cur_digit;
// Iterate through h taking top 4 bits each time and outputting ASCII of hex
// digit for those 4 bits
for (int i = 0; i < 8; i++) {
cur_digit = h >> 28;
if (cur_digit < 10)
putchar('0' + cur_digit);
else
putchar('A' - 10 + cur_digit);
h <<= 4;
}
}
void sim_halt() { DEV_WRITE(SIM_CTRL_BASE + SIM_CTRL_CTRL, 1); }
void pcount_reset() {
asm volatile(
"csrw minstret, x0\n"
"csrw mcycle, x0\n"
"csrw mhpmcounter3, x0\n"
"csrw mhpmcounter4, x0\n"
"csrw mhpmcounter5, x0\n"
"csrw mhpmcounter6, x0\n"
"csrw mhpmcounter7, x0\n"
"csrw mhpmcounter8, x0\n"
"csrw mhpmcounter9, x0\n"
"csrw mhpmcounter10, x0\n"
"csrw mhpmcounter11, x0\n"
"csrw mhpmcounter12, x0\n"
"csrw mhpmcounter13, x0\n"
"csrw mhpmcounter14, x0\n"
"csrw mhpmcounter15, x0\n"
"csrw mhpmcounter16, x0\n"
"csrw mhpmcounter17, x0\n"
"csrw mhpmcounter18, x0\n"
"csrw mhpmcounter19, x0\n"
"csrw mhpmcounter20, x0\n"
"csrw mhpmcounter21, x0\n"
"csrw mhpmcounter22, x0\n"
"csrw mhpmcounter23, x0\n"
"csrw mhpmcounter24, x0\n"
"csrw mhpmcounter25, x0\n"
"csrw mhpmcounter26, x0\n"
"csrw mhpmcounter27, x0\n"
"csrw mhpmcounter28, x0\n"
"csrw mhpmcounter29, x0\n"
"csrw mhpmcounter30, x0\n"
"csrw mhpmcounter31, x0\n"
"csrw minstreth, x0\n"
"csrw mcycleh, x0\n"
"csrw mhpmcounter3h, x0\n"
"csrw mhpmcounter4h, x0\n"
"csrw mhpmcounter5h, x0\n"
"csrw mhpmcounter6h, x0\n"
"csrw mhpmcounter7h, x0\n"
"csrw mhpmcounter8h, x0\n"
"csrw mhpmcounter9h, x0\n"
"csrw mhpmcounter10h, x0\n"
"csrw mhpmcounter11h, x0\n"
"csrw mhpmcounter12h, x0\n"
"csrw mhpmcounter13h, x0\n"
"csrw mhpmcounter14h, x0\n"
"csrw mhpmcounter15h, x0\n"
"csrw mhpmcounter16h, x0\n"
"csrw mhpmcounter17h, x0\n"
"csrw mhpmcounter18h, x0\n"
"csrw mhpmcounter19h, x0\n"
"csrw mhpmcounter20h, x0\n"
"csrw mhpmcounter21h, x0\n"
"csrw mhpmcounter22h, x0\n"
"csrw mhpmcounter23h, x0\n"
"csrw mhpmcounter24h, x0\n"
"csrw mhpmcounter25h, x0\n"
"csrw mhpmcounter26h, x0\n"
"csrw mhpmcounter27h, x0\n"
"csrw mhpmcounter28h, x0\n"
"csrw mhpmcounter29h, x0\n"
"csrw mhpmcounter30h, x0\n"
"csrw mhpmcounter31h, x0\n");
}
void pcount_enable(int enable) {
// Note cycle is disabled with everything else
unsigned int inhibit_val = enable ? 0x0 : 0xFFFFFFFF;
// CSR 0x320 was called `mucounteren` in the privileged spec v1.9.1, it was
// then dropped in v1.10, and then re-added in v1.11 with the name
// `mcountinhibit`. Unfortunately, the version of binutils we use only allows
// the old name, and LLVM only supports the new name (though this is changed
// on trunk to support both), so we use the numeric value here for maximum
// compatibility.
asm volatile("csrw 0x320, %0\n" : : "r"(inhibit_val));
}
unsigned int get_mepc() {
uint32_t result;
__asm__ volatile("csrr %0, mepc;" : "=r"(result));
return result;
}
unsigned int get_mcause() {
uint32_t result;
__asm__ volatile("csrr %0, mcause;" : "=r"(result));
return result;
}
unsigned int get_mtval() {
uint32_t result;
__asm__ volatile("csrr %0, mtval;" : "=r"(result));
return result;
}
void simple_exc_handler(void) {
puts("EXCEPTION!!!\n");
puts("============\n");
puts("MEPC: 0x");
puthex(get_mepc());
puts("\nMCAUSE: 0x");
puthex(get_mcause());
puts("\nMTVAL: 0x");
puthex(get_mtval());
putchar('\n');
sim_halt();
while(1);
}
volatile uint64_t time_elapsed;
uint64_t time_increment;
inline static void increment_timecmp(uint64_t time_base) {
uint64_t current_time = timer_read();
current_time += time_base;
timecmp_update(current_time);
}
void timer_enable(uint64_t time_base) {
time_elapsed = 0;
time_increment = time_base;
// Set timer values
increment_timecmp(time_base);
// enable timer interrupt
asm volatile("csrs mie, %0\n" : : "r"(0x80));
// enable global interrupt
asm volatile("csrs mstatus, %0\n" : : "r"(0x8));
}
void timer_disable(void) { asm volatile("csrc mie, %0\n" : : "r"(0x80)); }
uint64_t timer_read(void) {
uint32_t current_timeh;
uint32_t current_time;
// check if time overflowed while reading and try again
do {
current_timeh = DEV_READ(TIMER_BASE + TIMER_MTIMEH, 0);
current_time = DEV_READ(TIMER_BASE + TIMER_MTIME, 0);
} while (current_timeh != DEV_READ(TIMER_BASE + TIMER_MTIMEH, 0));
uint64_t final_time = ((uint64_t)current_timeh << 32) | current_time;
return final_time;
}
void timecmp_update(uint64_t new_time) {
DEV_WRITE(TIMER_BASE + TIMER_MTIMECMP, -1);
DEV_WRITE(TIMER_BASE + TIMER_MTIMECMPH, new_time >> 32);
DEV_WRITE(TIMER_BASE + TIMER_MTIMECMP, new_time);
}
uint64_t get_elapsed_time(void) { return time_elapsed; }
void simple_timer_handler(void) __attribute__((interrupt));
void simple_timer_handler(void) {
increment_timecmp(time_increment);
time_elapsed++;
}

View file

@ -1,88 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef SIMPLE_SYSTEM_COMMON_H__
#include <stdint.h>
#include "simple_system_regs.h"
#define DEV_WRITE(addr, val) (*((volatile uint32_t *)(addr)) = val)
#define DEV_READ(addr, val) (*((volatile uint32_t *)(addr)))
#define PCOUNT_READ(name, dst) asm volatile("csrr %0, " #name ";" : "=r"(dst))
/**
* Writes character to simulator out log. Signature matches c stdlib function
* of the same name.
*
* @param c Character to output
* @returns Character output (never fails so no EOF ever returned)
*/
int putchar(int c);
/**
* Writes string to simulator out log. Signature matches c stdlib function of
* the same name.
*
* @param str String to output
* @returns 0 always (never fails so no error)
*/
int puts(const char *str);
/**
* Writes ASCII hex representation of number to simulator out log.
*
* @param h Number to output in hex
*/
void puthex(uint32_t h);
/**
* Immediately halts the simulation
*/
void sim_halt();
/**
* Enables/disables performance counters. This effects mcycle and minstret as
* well as the mhpmcounterN counters.
*
* @param enable if non-zero enables, otherwise disables
*/
void pcount_enable(int enable);
/**
* Resets all performance counters. This effects mcycle and minstret as well
* as the mhpmcounterN counters.
*/
void pcount_reset();
/**
* Enables timer interrupt
*
* @param time_base Number of time ticks to count before interrupt
*/
void timer_enable(uint64_t time_base);
/**
* Returns current mtime value
*/
uint64_t timer_read(void);
/**
* Set a new timer value
*
* @param new_time New value for time
*/
void timecmp_update(uint64_t new_time);
/**
* Disables timer interrupt
*/
void timer_disable(void);
/**
* Returns current global time value
*/
uint64_t get_elapsed_time(void);
#endif

View file

@ -1,18 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef SIMPLE_SYSTEM_REGS_H__
#define SIMPLE_SYSTEM_REGS_H__
#define SIM_CTRL_BASE 0x20000
#define SIM_CTRL_OUT 0x0
#define SIM_CTRL_CTRL 0x8
#define TIMER_BASE 0x30000
#define TIMER_MTIME 0x0
#define TIMER_MTIMEH 0x4
#define TIMER_MTIMECMP 0x8
#define TIMER_MTIMECMPH 0xC
#endif // SIMPLE_SYSTEM_REGS_H__

View file

@ -1,14 +0,0 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# Generate a baremetal application
# Name of the program $(PROGRAM).c will be added as a source file
PROGRAM = hello_test
PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
# Any extra source files to include in the build. Use the upper case .S
# extension for assembly files
EXTRA_SRCS :=
include ${PROGRAM_DIR}/../common/common.mk

View file

@ -1,41 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "simple_system_common.h"
int main(int argc, char **argv) {
pcount_enable(0);
pcount_reset();
pcount_enable(1);
puts("Hello simple system\n");
puthex(0xDEADBEEF);
putchar('\n');
puthex(0xBAADF00D);
putchar('\n');
pcount_enable(0);
// Enable periodic timer interrupt
// (the actual timebase is a bit meaningless in simulation)
timer_enable(2000);
uint64_t last_elapsed_time = get_elapsed_time();
while (last_elapsed_time <= 4) {
uint64_t cur_time = get_elapsed_time();
if (cur_time != last_elapsed_time) {
last_elapsed_time = cur_time;
if (last_elapsed_time & 1) {
puts("Tick!\n");
} else {
puts("Tock!\n");
}
}
asm volatile("wfi");
}
return 0;
}