owned this note
owned this note
Published
Linked with GitHub
# Lab3
## Generate the files
I pick the c code in Assignment 1. and transform into test.c . test.c is the target c file. I modify the Makefile to generate corresbonding .efl file to simulate. The Makefile and test.c are put in a folder called test.
### Makefile
```
include ../common/Makefile.common
EXE = .elf
SRC = test.c
CFLAGS += -L../common
LDFLAGS += -T ../common/default.ld
TARGET = test
OUTPUT = $(TARGET)$(EXE)
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) -o $(OUTPUT) $(SRC) $(LDFLAGS)
$(OBJCOPY) -j .text -O binary $(OUTPUT) imem.bin
$(OBJCOPY) -j .data -O binary $(OUTPUT) dmem.bin
$(OBJCOPY) -O binary $(OUTPUT) memory.bin
$(OBJDUMP) -d $(OUTPUT) > $(TARGET).dis
$(READELF) -a $(OUTPUT) > $(TARGET).symbol
clean:
$(RM) *.o $(OUTPUT) $(TARGET).dis $(TARGET).symbol [id]mem.bin memory.bin
```
we just execute the following command in srv32-devel:
```
make test
```
The .elf file and other output will be generated
## Output
with printf()
```
5 4 3 2 4
Excuting 3746 instructions, 4774 cycles, 1.274 CPI
Program terminate
- ../rtl/../testbench/testbench.v:418: Verilog $finish
Simulation statistics
=====================
Simulation time : 0.079 s
Simulation cycles: 4785
Simulation speed : 0.0605696 MHz
make[1]: Leaving directory '/home/korin/srv32-devel/sim'
make[1]: Entering directory '/home/korin/srv32-devel/tools'
./rvsim --memsize 128 -l trace.log ../sw/test/test.elf
5 4 3 2 4
Excuting 3746 instructions, 4774 cycles, 1.274 CPI
Program terminate
Simulation statistics
=====================
Simulation time : 0.006 s
Simulation cycles: 4774
Simulation speed : 0.764 MHz
make[1]: Leaving directory '/home/korin/srv32-devel/tools'
Compare the trace between RTL and ISS simulator
=== Simulation passed ===
```
Without printf()
```
Excuting 73 instructions, 89 cycles, 1.219 CPI
Program terminate
- ../rtl/../testbench/testbench.v:418: Verilog $finish
Simulation statistics
=====================
Simulation time : 0.019 s
Simulation cycles: 100
Simulation speed : 0.00526316 MHz
make[1]: Leaving directory '/home/korin/srv32-devel/sim'
make[1]: Entering directory '/home/korin/srv32-devel/tools'
./rvsim --memsize 128 -l trace.log ../sw/test/test.elf
Excuting 73 instructions, 89 cycles, 1.219 CPI
Program terminate
Simulation statistics
=====================
Simulation time : 0.000 s
Simulation cycles: 89
Simulation speed : 1.047 MHz
make[1]: Leaving directory '/home/korin/srv32-devel/tools'
Compare the trace between RTL and ISS simulator
=== Simulation passed ===
```
As we can compare the output between the code with printf() and without printf(), the gap of the number of executed instructions is large.
### A part of Assembly code
Execute the following command and get the assembly code.
```
riscv-none-embed-objdump -d test.elf
```
```
test.elf: file format elf32-littleriscv
Disassembly of section .text:
00000000 <_start>:
0: 00000297 auipc t0,0x0
4: 08028293 addi t0,t0,128 # 80 <trap_handler>
8: 30529073 csrw mtvec,t0
c: 3050e073 csrsi mtvec,1
10: 00020297 auipc t0,0x20
14: 00028293 mv t0,t0
18: 00020317 auipc t1,0x20
1c: ffc30313 addi t1,t1,-4 # 20014 <_bss_end>
00000020 <_bss_clear>:
20: 0002a023 sw zero,0(t0) # 20010 <heap_ptr>
24: 00428293 addi t0,t0,4
28: fe62ece3 bltu t0,t1,20 <_bss_clear>
2c: 00040117 auipc sp,0x40
30: fd410113 addi sp,sp,-44 # 40000 <_stack>
34: 008000ef jal ra,3c <main>
38: 3580006f j 390 <exit>
0000003c <main>:
3c: 00500613 li a2,5
40: 00200793 li a5,2
44: 00300713 li a4,3
48: 00400593 li a1,4
4c: 00f5a6b3 slt a3,a1,a5
50: fff68693 addi a3,a3,-1
54: 00d7f7b3 and a5,a5,a3
58: fff60613 addi a2,a2,-1
5c: 00060e63 beqz a2,78 <main+0x3c>
60: 00178793 addi a5,a5,1
64: 00170713 addi a4,a4,1
68: 00e5a6b3 slt a3,a1,a4
6c: fff68693 addi a3,a3,-1
70: 00d77733 and a4,a4,a3
74: fd9ff06f j 4c <main+0x10>
78: 00000513 li a0,0
7c: 00008067 ret
```
```
00000390 <exit>:
390: 0ff57793 andi a5,a0,255
394: 90000737 lui a4,0x90000
398: 02f70623 sb a5,44(a4) # 9000002c <_stack+0x8ffc002c>
39c: 0000006f j 39c <exit+0xc>
```
### Branch instruction
In address ```0x5c```, there is an bracnh instruction ```beqz a2,78```. When the condition is true, the next instrution address is `0x78`, which is ```li a0,0```.


* ```ex_inst``` is the instruction executed in EX stage.
* ```ex_pc``` is the address of the instruction in EX stage.
* ```fetch_pc```is the address of next instruction
As the EX stage excute ```beqz```, which address is ```0x5c``` and decoded as ```00060E63```, the address of the address is update into ```00000078``` in next cycle, and executed later.
Since srv32 is a 3-stage RISC-V processor, the program will jump to the destination instruction after 3 cycle.
The instrutions at address ```0x60``` ```0x64``` will be stalled.
|Instruction|1|2|3|4|5|6|7|
|:-:|-|-|:-:|:-:|:-:|:-:|-|
|beqz a2,78|IF/ID|EX|WB||||
|addi a5,a5,1||IF/ID|NOP|NOP||
|addi a4,a4,1|||IF/ID|NOP|NOP|
|li a0,0||||IF/ID|EX|WB|
## Execution
By comparing the instruction dumped by compiler and the instructions in GTKwave. Most of the instructions are not executed.
By running the folowing command:
```
riscv-none-embed-size test.elf
```
Get the total size of the code.
```
text data bss dec hex filename
1036 16 4 1056 420 test.elf
```
As we can see that the number is over 1000. However, in the simulator, we only execute 73 instructions in 89 cycles. In fact, the assembly code I put here are the parts which are executed in waveform.
The program begin in start and execute through ```<_bss_clear>``` until the instruction```jal ra,3c ```, which jump to the ```<main>```.
Since there is a branch instruction ```beqz``` and jump instruction ```j```in the main, this part will be executed five times, which is the length of the array in c code, and branch to the end of ```<main>``` by ```beqz```. Then, return back to instruction ```j 390 <exit>```. Finally, the processor execute ```<exit>``` in address ```390``` and terminated.