mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-22 21:17:59 -04:00
Remove the Ibex example system (#272)
This commit is contained in:
parent
7f3bb9fcb2
commit
42f76f433c
38 changed files with 14 additions and 3903 deletions
|
@ -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``.
|
||||
|
|
|
@ -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.
|
|
@ -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]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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]
|
||||
}
|
Binary file not shown.
|
@ -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
|
|
@ -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 |
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
|
@ -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();
|
||||
};
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
waive --rule=macro-name-style --location="cve2_simple_system.sv" --regex="RegFile"
|
|
@ -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"
|
|
@ -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
|
|
@ -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[@]}"
|
6
examples/sw/.gitignore
vendored
6
examples/sw/.gitignore
vendored
|
@ -1,6 +0,0 @@
|
|||
*.o
|
||||
*.bin
|
||||
*.dis
|
||||
*.elf
|
||||
*.vmem
|
||||
*.d
|
|
@ -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.
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 ]
|
||||
}
|
||||
}
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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++;
|
||||
}
|
|
@ -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
|
|
@ -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__
|
|
@ -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
|
|
@ -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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue