Exercise: OpenRISC Programming - Integrated Systems Laboratory

Exercise: OpenRISC Programming
Increasing efficiency of the OpenRISC core with
simple instruction extensions
23.03.2015
Michael Gautschi
Antonio Pullini
Integrated Systems Laboratory
Integrated Systems Laboratory
Introduction
• All exercises will be performed on the following configuration:
– 4 OpenRISC or10n cores
• With private instruction cache (I$)
– 8 banks of shared level 1 memory (TCDM)
– Large L2 memory for instructions and data
– Since the focus of this exercise is on the core, only one core is used and
the others are put to sleep.
or10n
processor cores
Not used / sleeping
23.03.2015
2
Integrated Systems Laboratory
Exercise Overview
1. Introduction example
–
Compile & execute Helloworld on the Instruction Set Simulator (ISS)
2. Simulator Basics
–
Analyze ISS output and debug
3. Benchmarking
–
Analyze performance improvements of the new instructions using the simulator
4. RTL simulations and benchmarking
–
Compare to simulator
5. Unaligned memory accesses
–
Program a simple stencil and show the benefit of unaligned memory accesses
6. Auto vectorization
–
Analyze the improvements of vector operations on a matrix addition
7. Interrupts and events
–
23.03.2015
Compare interrupts and event response times
3
Integrated Systems Laboratory
Getting Started – 1/2
• Copy data from master account:
$ mkdir 2_OpenRISC
$ cp /home/soc_master/2_OpenRISC/openrisc.tar.gz 2_OpenRISC/.
$ tar –xzf OpenRISC.tar.gz
2_OpenRISC directory
• Source the instruction set simulator
$ source /home/soc_master/germain/pulp-sdk2014.1-ub14.10_2/env/setup.sh
• We will be working in the software (sw) and
build directories
– sw-dir:
• contains application sourcecode
– build-dir:
• Holds compiler and simulator output here
• Simulator and RTL-simulations will be run here
– sim-dir:
• Contains precompiled code for RTL-simulation
23.03.2015
4
Integrated Systems Laboratory
Getting Started – 2/2
• We will be working on the scratch because we are going to
generate some data 
1.
Create a build directory and set up the compiler
•
2.
Start the compiler in a new shell:
•
•
3.
$ mkdir /scratch/soc_xx/build_id
$ or1k –v1.7.3 xterm
$ tcsh
(switch to cshell)
Configure the build directory in the new shell
•
•
•
•
•
$ cd /scratch/soc_xx/build_id
$ cp /home/soc_xx/2_OpenRISC/build/configure_template.tcl
/scratch/soc_xx/build_id/configure.tcl
In the configure script: Set the path to your exercise folder:
OPENRISC_DIR=“/home/soc_xx/2_OpenRISC”
$ ./configure.tcl
You have successfully set up the build directory!
– Lets get started with exercise 1!
23.03.2015
5
Integrated Systems Laboratory
Exercise 1 – Introduction
a)
The build directory is created, the compiler is configured, and the
simulator is set up. We are ready to start with a simple helloworld
application.
b) Compile Helloworld.c
• Helloworld.c is located in sw/apps/sequential_tests/helloworld/.
• To compile the application enter the build folder and run the makefile
$ cd build
$ make helloworld
$ make helloworld.read
$ make helloworld.slm.cmd
c)
: to generate an executable for the simulator
: to generate the assemebly
: to generate input data for RTL simulations
Run Helloworld.c
• The simulator is called “pulp-run” and can be started like this:
$ pulp-run --load-binary=./apps/sequential_tests/helloworld/helloworld:0xf
• Console should output “helloworld”
• Output is also written to the file: stdout/stdout_pe0
23.03.2015
6
Integrated Systems Laboratory
Exercise 2 – Simulator basics 1/4

Simulator commands to run an application



Enter debug mode



Run an application:
$ pulp-run --load-binary=./applicationName:0xf
Get assembly traces:
$ pulp-run --load-binary=./applicationName:0xf --iis-trace
Force entering the debugger in the beginning:
$ pulp-run --load-binary=./applicationName:0xf --pdb-break
press “Ctrl+C” during execution
Check current status of core:
(Cmd) state

: bootaddress = 0x1c000000
Breakpoints and inspection of memory (in debug mode)

Set a breakpoint on memory access:
(Cmd) bkp address region rw

Display all breakpoints:

Remove a breakpoint:

Inspect memory:
: address = 32 bit memory address;
: default region = 0x4 (1 word)
: rw = read or write access (default rw)
(Cmd) bkp_list
23.03.2015
(Cmd) bkp_dis ID
: ID shown in bkp_list
(Cmd) mem_dump address size
: 32bit addresses
: default size = 0x4 (1 word)
7
Integrated Systems Laboratory
Exercise 2 – Simulator basics 2/4
• Analyze the rijendael application (aes en/decryption)
–
Generate the assembly:
$ make rijndael.read
–
Have a look at the assembly file rijndael.read
•
function header
PC
The most important functions are:
–
–
–
main
encrypt
decrypt
compute_aes
encfile
decfile
Instruction in big and little endian format
Disassembled instructions
Absolute and relative
jump/branch targets
23.03.2015
8
Integrated Systems Laboratory
Exercise 2 – Simulator basics 3/4
•
Simulator traces:
Latency of the instruction
New register values, effective addresses
Disassembled instructions
•
To trace an application:
–
–
Run the application with the option --iss-trace
Four traces are generated, one for each core
•
–
23.03.2015
PC
we are actually using a four-core configuration of which three cores are
sleeping
trace_cluster0_core0.log shows the interesting traces!
9
Integrated Systems Laboratory
Exercise 2 – Simulator basics 4/4
•
23.03.2015
Tasks:
–
Run the rijndael application with traces and make use of the debugger
and breakpoints
–
Which instructions take more than one cycle to execute?
–
Why are some load/store instructions (l.lwz, l.sw) taking more than one
cycle?
–
Do you see an example of a data hazard?
–
How many times is address 0x1c008000 read?
–
What is the encryption key?
10
Integrated Systems Laboratory
Exercise 3 – Benchmarking 1/5
•
Intro:
The timer can be used to count execution time (in cycles)
Check matrixMul.c for example
Include <timer.h> and use the functions:
–
–
–
reset_timer()
stop_timer()
•
•
•
start_timer()
get_time()
Hardware loops
–
–
To run the application with different hardware loop settings, the compiler needs to be reconfigured
There are two options:
1.
2.
Create a new build folder with a new configure.tcl script
Modify current folder and modify the configuration script: configure.tcl
–
To support different numbers of hardware loops, add the following to TARGET_C_FLAGS in configure.tcl:
remove the option -mno-hwlp to enable hwlps
-mmax-hwloops=<number_of_hwlp>
: number_of_hwlp [0,4]
–
Reconfigure build folder:
$ ./configure.tcl
•
The compiler will generate the following hwloop instructions to produce efficient loops:
- lp.start
- lp.count
- lp.setup
23.03.2015
- lp.end
- lp.counti
- lp.setupi
11
Integrated Systems Laboratory
Exercise 3 – Benchmarking 2/5
Tasks:
•
–
–
–
–
Check if hardware loops are generated (in the matrixMul.read file)
How many instructions are actually saved? Compare the
matrixMul.read with and w/o hwloops.
Estimate the speedup with 1,2,4 hardware loops
Do your measurements match your estimations?
•
Why is the benefit of the first one higher?
Execution time: (# cycles/ % improvement)
Baseline
Hardware loop (1 register set)
2 register sets
3 register sets
4 register sets
23.03.2015
12
Integrated Systems Laboratory
Exercise 3 – Benchmarking 3/5
• Pre/post increment immediate:
Old MAC:
– Activated by default!
– Deactivate with –mno-idxls
• Pre/post increment register:
– From a hardware perspective, what is the
drawback of this instruction?
– Deactivate with –mno-rrls
• Multiply-accumulate instruction:
– Old architecture:
New MAC:
• Accumulation register stored in a special
register which is not in the register file
• Accumulation result can be accessed in
two cycles
– New architecture:
• Accumulates directly on the register file
• Enable new MAC with -mmac3
23.03.2015
13
Integrated Systems Laboratory
Exercise 3 – Benchmarking 4/5
• Vector Instructions:
– Add, sub, mul, mac, comparisons are all supported in vector mode
– In parallel one can compute:
• One word
• Two halfwords, or
• Four bytes
– Enable the vector extensions with the compiler option:
•
•
–mlv32
-munaligned-ls
for vector generation
for unaligned memory accesses
– Check in the .read me if vector code is generated. Vector instructions have the
format:
• lv.{mul,mac,sub,add,…}
• Tasks:
– Run the matrixMul application with the different compiler options
– Summarize your results in the first column on the next page
23.03.2015
14
Integrated Systems Laboratory
Exercise 3 – Benchmarking 5/5
Execution time: (# cycles/ % improvement)
Simulator:
RTL-SIM:
Baseline
Hardware-loop
Pre/post incr. imm.
Pre/post incr. reg
mac
Vector
Unaligned access
• Can you explain your results?
• Are the results you obtained optimal?
• What can be done better?
– Try to improve the matrix multiplication such that vectors are used more
efficiently
23.03.2015
15
Integrated Systems Laboratory
Exercise 4 – RTL Simulation 1/2
• The simulator is not 100% accurate because:
•
•
•
•
It is still under development
Not all components are modeled (no caches/memory contentions/
simplified DMA)
But a lot faster than RTL simulation
Start RTL simulations with the Makefile in your build folders:
–
$ make testName_vsim
• Rerun the matrixMul in the RTL simulation and complete the table
– If you have a build folder for each configuration, you can run the
simulations in parallel (each RTL-sim will take ~5min)
– Are you able to reproduce the previously obtained results? Do you
observe any differences?
– Do you have an explanation?
23.03.2015
16
Integrated Systems Laboratory
Exercise 4 – RTL Simulation 2/2
• In matrixMul.c the function
computeGold() which is actually
computing the multiplication is
called two times with the same
inputs and outputs!
Code snipped of matrixMul.c:
• Why do you think this is the case?
– Compare the execution time of
the first iteration between the
RTL-simulation and the simulator!
– What do you observe?
23.03.2015
17
Integrated Systems Laboratory
Exercise 5 – Unaligned Memory Access
•
Unaligned memory access
– If data is not aligned, for example when
computing the stencil over an image, a lot of
memory accesses and shifting is required.
– If data can be accessed in an unaligned
fashion, the shifting is not required anymore.
– The or10n core supports unaligned accesses
in two consecutive cycles!
•
Pixel = 1 char
Tasks:
– Complete the stencil template program
(sw/apps/sequential_tests/stencil/stencil.c)
which computes four stencils in parallel over
a 32x32 pixel image
– Do you observe a speedup with unaligned
memory access enabled?
– Compare to a vector only implementation
23.03.2015
Image – 1 stencil
4 parallel stencils computed with
vectorial unit
18
Integrated Systems Laboratory
Exercise 6 – Auto Vectorization
•
•
•
In the matrixMul example, the automatic vector support did not bring the desired speedup
If the matrices are accessed in a more regular fashion, this is expected to change!
Run the matrixAdd{8,16,32} applications in RTL simulation and measure the speedup.
–
–
–
•
matrixAdd8 is based on characters
matrixAdd16 on short integers
matrixAdd32 on integers
Run the motion_detection application and compare first the execution time of the baseline and
the optimized architecture without vector support.
–
And then add first unaligned memory access, and then vector instructions
Execution time: (# cycles/ % improvement)
matrixAdd32
matrixAdd16
matrixAdd8
motion_detection
Baseline
Without vector
Unaligned access
With vector
23.03.2015
19
Integrated Systems Laboratory
Exercise 7 – Interrupts & Events 1/2
•
Core 3 is used to model an external interface in the following
•
Receiving and processing of data is completed as follows:
1.
2.
3.
4.
5.
23.03.2015
Core 0 configures its interrupt or event mask before completing other tasks/going to sleep
Core 3 generates data and sends/places it in a buffer (here in L2 memory)
Core 3 sends commands to global event unit, to generate an event for core 0
Core 0 receives an interrupt/ wakes up and processes the data in L2 memory
Continue from beginning
20
Integrated Systems Laboratory
Exercise 7 – Interrupts & Events 2/2
•
Task 1: Interrupts
–
–
Check out the interrupt/event template: sw/apps/sequential_tests/event_interrupt.c
Define an interrupt handler
•
–
–
–
•
Initialize interrupts
Add interrupt handler on interrupt GP0 (see sw/libs/sys_lib/src/int.c)
Set interrupt mask (1= interrupt is not masked)
Task 2: Events
–
In the function wait_and_proc_data():
•
•
•
Copy data from receive_buffer to your memory (received_data)
go to sleep, wait for event
When an event is received: copy data from receive_buffer to your memory (received data)
Task 3: Comparison
–
Compare the two solutions:
•
•
Execution time
Measure the time required to process one package in modelsim
$ make event_interrupt_vsim_debug
•
Hints to measure time:
–
–
•
23.03.2015
Events: observe the clock of core 0
Interrupts: observe the state of exception routine (exc_running_p)
What are the benefits of using events?
21
Integrated Systems Laboratory
Questions & Answers
•
You have successfully completed the exercise
•
If you are interested in a mini-project we can offer you:
– Implementing and optimizing of a benchmark, using the multicore pulp
environment
• See last exercise about the pulp architecture
– Compare simulator and RTL simulations and come up with examples how to
improve it
– Add performance counters on RTL level
– Compare OR10N core to a state-of-the art micro-controller with DSP
functionalities like the ARM Cortex M4
– Add a small unit which observes the stack pointer, and issues an exception if a
stack overflow has been detected
– We are open to your own ideas!
23.03.2015
22