Merge branch 'master' of https://github.com/lcbcFoo/riscv-leon into release

This commit is contained in:
lcbcFoo 2018-03-10 19:46:26 -03:00
commit 5d4d83b0cd
2 changed files with 103 additions and 14 deletions

View file

@ -24,14 +24,14 @@ Also, we wanted to show to the hardware developers community that it is possible
---
## <a name="repo-map"></a> Repository Map
The directories `bin`, `boards` and `software` where simply copied from GRLIB and contain scripts, templates and small programs used by GRLIB. The directory `doc` constains the documentation from GRLIB (may be updated with ReonV specific documentation on future). Directory `designs` contains all scripts and configuration designs for each specific FPGA board supported by Leon3 (and by ReonV). Directory `lib` constains the source code of the processor and of all peripherals or IP cores provided by GRLIB, the 7-stage integer pipeline changed to RISC-V is at `lib/gaisler/leon3v3/iu4.vhd`. Lastly, `riscv` contains scripts and configuration files to run a test example on ReonV (check [Running an Example[(#running) section).
The directories `bin`, `boards` and `software` where simply copied from GRLIB and contain scripts, templates and small programs used by GRLIB. The directory `doc` constains the documentation from GRLIB (may be updated with ReonV specific documentation on future). Directory `designs` contains all scripts and configuration designs for each specific FPGA board supported by Leon3 (and by ReonV). Directory `lib` constains the source code of the processor and of all peripherals or IP cores provided by GRLIB, the 7-stage integer pipeline changed to RISC-V is at `lib/gaisler/leon3v3/iu3.vhd`. Lastly, `riscv` contains scripts and configuration files to run a test example on ReonV (check [Running an Example](#running) section).
---
## <a name="install"></a> Installation
### <a name="install-reonv"></a> ReonV
As already explained, ReonV is a modified version of the Leon3 processor, which is part of GRLIB, that means you can clone this repository and follow the detailed instructions provided in the GRLIB User Manual (it can be found at doc/grlib.pdf or [here](http://www.gaisler.com/products/grlib/grlib.pdf)) depending on the tools you want to use for synthesis or simulation or even on which FPGA you are goind to run.
As already explained, ReonV is a modified version of the Leon3 processor, which is part of GRLIB, that means you can clone this repository and follow the detailed instructions provided in the GRLIB User Manual (it can be found at `doc/grlib.pdf` or [here](http://www.gaisler.com/products/grlib/grlib.pdf)) depending on the tools you want to use for synthesis or simulation or even on which FPGA you are going to run.
### <a name="rv-toolchain"></a> RISC-V Toolchain
Needed to compile a program targeting RISC-V architecture, its repository can be found [here](https://github.com/riscv/riscv-gnu-toolchain)
It is needed to compile a program targeting RISC-V architecture, its repository can be found [here](https://github.com/riscv/riscv-gnu-toolchain). Follow the instructions provided there and make sure to compile it for RV32I only! You can make this by replacing the line `./configure --prefix=/the/path/you/chose` explained on their README to `./configure --with-arch=rv32i --with-abi=ilp32 --prefix=/the/path/you/chose`.
### <a name="install-grmon"></a> GRMON2
GRMON2 is the Leon3 debugging tool provided by [Cobham Gaisler AB](http://www.gaisler.com/). It communicates with the Debugging Unit of the processor and allows to easily execute programs and debug the processor. GRMON has evaluation and professional versions, you can find the download links and its manual [here](http://www.gaisler.com/index.php/downloads/debug-tools).

View file

@ -6,17 +6,13 @@ changing a few commands to the ones your board requires.
---
## Overview
* ReonV currentily implements RV32I without privilegied instructions, so it is important to use a compiler to this ISA (follow instructions on the main README).
* We will use GRMON2 to load, run and debug the program, since the processor DSU was not changed and it communicates with GRMON. However, GRMON2 was not designed for RISC-V and we have to change the assembly and binary to workaround this problem (more information on issue [GRMON2 and RISCV](https://github.com/lcbcFoo/ReonV/issues/5)
* The scrips for running on nexys4ddr are at `designs/leon3-digilent-nexys4ddr`. If you are running on other board, you must use its own design directory.
* We will use GRMON2 to load, run and debug the program, since the processor DSU was not changed and it communicates with GRMON. However, GRMON2 was not designed for RISC-V and we have to take some workarounds to run a RISC-V program using it (more information on issue [GRMON2 and RISCV](https://github.com/lcbcFoo/ReonV/issues/5))
* The design directory for this board is `designs/leon3-digilent-nexys4ddr`. If you are running on other board, you must use its own design directory.
## Compiling the program
We have files `main.c`, `main.s`, `main.S` and `main.bin`. `main.c` contains our simple example, `main.s` was generated after running `make main.s`, `main.S` is the modified assembly we are going to assemble and finally `main.bin` is the binary generated after assembling `main.S` and extracting .text section, it is the binary we are going to run. The process of compilation is:
Currently, we have a simple `crt0.S` to initialize stack and other registers. Also, we have some minimal posix functions needed for benchmarks implemented on `posix.c`. These file are linked to the main.c program by the linker script, allowing us to use some commom functions from glibc. However, we do not have complete support for glibc at this moment. The linker script also sets the beginning of `.text` to position 0x40001000 (a workaround needed to run via GRMON2). To compile a program `main.c` on the `riscv` directory run:
```
make main.s
# Modify main.s to main.S. We need to set stack point, change `call` commands to `jal`,
# since after we remove .text section the calculation for `call` will be wrong.
# Put an instruction EBREAK to stop the program.
make main.bin # This will assemble main.S and extract .text section
make main.out
```
---
@ -43,9 +39,102 @@ grmon -digilent -u
```
## Running the program
GRMON2 has many features, but some as still restricted because of our RISC-V ISA. To load and our program use:
GRMON2 has many features, but some are still restricted because of our RISC-V ISA. To load and run our program use:
```
bload ../../riscv/main.bin 0x40000000 # Load on memory position 0x40000000
bload ../../riscv/main.out 0x40000000 # Load on memory position 0x40000000
ep 0x40001000 # Set entry point to position 0x40001000
run
```
You can `reset` the processor, see the registers with `reg`, set a breakpoint with `bp <address>`, run step by step with `step` and disassemble memory with `disassemble <memory address>`
Our sample program allocates 2 arrays of size 8 on heap, calculates the first 8 fibonacci numbers and places them on array 1, writes this array into output section of memory with `write`, then reads the results written there using `lseek` and `read` into array2. Finally, it compares both arrays and writes `0xAAAAAAAA` if they are equal or `0xBBBBBBBB` if not.
After the `run` command, you can check registers with `reg` and `reg w7` (explanation at [GRMON2 and RISCV](https://github.com/lcbcFoo/ReonV/issues/5)). Then check the results with `disassemble 0x44000000` and verify heap with `disassemble 0x43000000`. Below is the entire described process to run our example on GRMON2 with #commentaries added.
```
grmon2> bload ../../riscv/main.out # Load program
40000000 Binary data 11.2kB / 11.2kB [===============>] 100%
Total size: 11.23kB (505.32kbit/s)
Entry point 0x40000000
Image /home/foo/IC/riscv-leon/repo/riscv/main.out loaded
grmon2> ep 0x40001000 # Set entry point
Cpu 0 entry point: 0x40001000
grmon2> run # Run
Stopped (tt = 0x00, )
0x400010b8: 73001000 call 0x0C0050B8 # This represents an ebreak instruction which stops execution
grmon2> reg # The first 3 colluns represents registers 8-31 (8 is OUTS 0, 16 is LOCALS 0, 24 is INS 0)
INS LOCALS OUTS GLOBALS
0: 00000000 00000000 43FFFFF0 00000000
1: 00000000 00000000 00000000 00000000
2: 00000000 00000000 00000000 00000000
3: 00000000 00000000 43FFFFC8 00000000
4: 00000000 00000000 00000004 00000000
5: 00000000 00000000 44000020 00000000
6: 00000000 00000000 44000024 00000000
7: 00000000 00000000 00000000 00000000
psr: F35000E0 wim: 00000002 tbr: 40001000 y: 00000000
pc: 400010B8 call 0x0C0050B8
npc: 400010BC sethi %hi(0x0), %o1
grmon2> reg w7 # The LOCALS colluns shows our registers 0-7 (LOCALS 0 is our 0)
INS LOCALS OUTS GLOBALS
0: 43FFFFF0 00000000 00000000 00000000
1: 00000000 4000108C 00000000 00000000
2: 00000000 43FFFFD0 00000000 00000000
3: 43FFFFC8 00000000 00000000 00000000
4: 00000004 00000000 00000000 00000000
5: 44000020 00000000 00000000 00000000
6: 44000024 00000000 00000000 00000000
7: 00000000 00000000 00000000 00000000
grmon2> disassemble 0x43000000 # Disassemble our heap
# The translation made by GRMON2 is based on SPARC, ignore it
0x43000000: 01000000 nop # Here starts array1
0x43000004: 01000000 nop
0x43000008: 02000000 unimp
0x4300000c: 03000000 sethi %hi(0x0), %g1
0x43000010: 05000000 sethi %hi(0x0), %g2
0x43000014: 08000000 unimp
0x43000018: 0d000000 sethi %hi(0x0), %g6
0x4300001c: 15000000 sethi %hi(0x0), %o2 # Here it ends, the results of fib(i) are correct
0x43000020: 01000000 nop # Here starts array2
0x43000024: 01000000 nop
0x43000028: 02000000 unimp
0x4300002c: 03000000 sethi %hi(0x0), %g1
0x43000030: 05000000 sethi %hi(0x0), %g2
0x43000034: 08000000 unimp
0x43000038: 0d000000 sethi %hi(0x0), %g6
0x4300003c: 15000000 sethi %hi(0x0), %o2 # Here it ends. Array2 was copied with success
grmon2> disassemble 0x44000000 # Disassemble our output section
# The translation made by GRMON2 is based on SPARC, ignore it
0x44000000: 01000000 nop # Here starts the array1 written to output
0x44000004: 01000000 nop
0x44000008: 02000000 unimp
0x4400000c: 03000000 sethi %hi(0x0), %g1
0x44000010: 05000000 sethi %hi(0x0), %g2
0x44000014: 08000000 unimp
0x44000018: 0d000000 sethi %hi(0x0), %g6
0x4400001c: 15000000 sethi %hi(0x0), %o2 # And here it ends
0x44000020: bbbbaaaa unknown opcode: 0xBBBBAAAA # This is our compare value, the result is correct!
0x44000024: 37000000 sethi %hi(0x0), %i3 # Below here is just junk on memory, ignore it
0x44000028: 59000000 call 0xA8000028
0x4400002c: 90000000 add 0, %o0
0x44000030: e9000000 ld [0], %f20
0x44000034: 79010000 call 0x28040034
0x44000038: 62020000 call 0xCC080038
0x4400003c: db030000 ld [%o4], %f13
```
## Important information (READ IT)
* As described in the [GRMON2 and RISCV](https://github.com/lcbcFoo/ReonV/issues/5) issue, GRMON2 assumes processor is using big endian, therefore it shows bytes of a word backwards, for example:
Number 974169 in RISC-V convention is `0x 00 0E DD 59`, GRMON2 shows it as `0x 59 DD 0E 00`
This is an inconvenience that must be kept in mind when reading values from memory while using GRMON2 (especially if you use `dump` and try to compare with other results!).
* There is no console yet, you can check the results of your program with the simple `write`, `read` and `lseek` functions implemented at `posix.c`. They use memory section `0x44000000 - 0x450000000` as an output section, allowing you to `dump` this region with GRMON2 and compare result with another environment if you wish.
* The default value for stack is `0x43FFFFF0` and `0x43000000` for the heap.
* Some commands of GRMON2 are `reg` and `reg w7` to see registers, set a breakpoint with `bp <address>`, run step by step with `step`, disassemble memory with `disassemble <memory address>` and a lot of others commands described on GRMON2´s [manual](http://www.gaisler.com/doc/grmon2.pdf).