owned this note
owned this note
Published
Linked with GitHub
# Asssigment3: SoftCPU
###### tags: `computer-arch-HW`
## Requirements1
### Enviroment setting
1. install [srv32 - RISCV RV32IM Soft CPU](https://hackmd.io/@sysprog/S1Udn1Xtt) and [riscv-gnu-toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain).
2. add the path in .bashrc file
#### .bashrc
```bash=
# riscv path
export PATH="/home/wei/.local/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/10.2.0-1.2.1/.content/bin":$PATH
```
### Create the folder for our code file and edit the Makefile
```bash=
cd ~/srv32/sw
mkdir Add_Binary # as same as Add_Binary.c
cd ~/Desktop
git clone https://github.com/AirysTW/Add-Binary-Leetcode-67-.git
cp ./Add-Binary-Leetcode-67-/Add_Binary.c ~/srv32/sw/Add_Binary/
cd ~/srv32/sw/Add_Binary
cp ../hello/Makefile ./
vim Makefile
```
#### Makefile
```cmake=
include ../common/Makefile.common
EXE = .elf
SRC = Add_Binary.c
CFLAGS += -L../common
LDFLAGS += -T ../common/default.ld
TARGET = Add_Binary
OUTPUT = $(TARGET)$(EXE)
ASM_COM = compile_with_asm
C_COM = compile_with_c
ONLY_ASM_COM = only_asm_compile
.PHONY: all clean
all: $(TARGET)
$(C_COM): $(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
$(ONLY_ASM_COM): $(SRC)
$(CC) $(CFLAGS) -S $(SRC) $(LDFLAGS)
$(ASM_COM): $(SRC)
$(CC) $(CFLAGS) -o $(OUTPUT) $(TARGET).s $(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
$(RM) *.s
```
### Compile the Add_Binary and use rtl & rvsim to simulate
```bash=
cd ~/srv32
make Add_Binary
```
Terminal output
```objectivec=
make[1]: Entering directory '/home/wei/srv32/sw'
make -C common
make[2]: Entering directory '/home/wei/srv32/sw/common'
make[2]: Nothing to be done for 'all'.
make[2]: Leaving directory '/home/wei/srv32/sw/common'
make[2]: Entering directory '/home/wei/srv32/sw/Add_Binary'
riscv-none-embed-gcc -O3 -Wall -march=rv32im -mabi=ilp32 -nostartfiles -nostdlib -L../common -o Add_Binary.elf Add_Binary.c -lc -lm -lgcc -lsys -T ../common/default.ld
Add_Binary.c: In function 'addBinary':
Add_Binary.c:52:26: warning: '%d' directive writing between 1 and 10 bytes into a region of size 8 [-Wformat-overflow=]
52 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~
Add_Binary.c:52:25: note: directive argument in the range [-536870960, 536871118]
52 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~~~~~
Add_Binary.c:52:13: note: 'sprintf' output 2 or more bytes (assuming 11) into a destination of size 8
52 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
riscv-none-embed-objcopy -j .text -O binary Add_Binary.elf imem.bin
riscv-none-embed-objcopy -j .data -O binary Add_Binary.elf dmem.bin
riscv-none-embed-objcopy -O binary Add_Binary.elf memory.bin
riscv-none-embed-objdump -d Add_Binary.elf > Add_Binary.dis
riscv-none-embed-readelf -a Add_Binary.elf > Add_Binary.symbol
make[2]: Leaving directory '/home/wei/srv32/sw/Add_Binary'
make[1]: Leaving directory '/home/wei/srv32/sw'
make[1]: Entering directory '/home/wei/srv32/sim'
a : 1010
b : 1011
add two binary : 10101
Excuting 6078 instructions, 7828 cycles, 1.287 CPI
Program terminate
- ../rtl/../testbench/testbench.v:418: Verilog $finish
Simulation statistics
=====================
Simulation time : 0.053 s
Simulation cycles: 7839
Simulation speed : 0.147906 MHz
make[1]: Leaving directory '/home/wei/srv32/sim'
make[1]: Entering directory '/home/wei/srv32/tools'
./rvsim --memsize 128 -l trace.log ../sw/Add_Binary/Add_Binary.elf
a : 1010
b : 1011
add two binary : 10101
Excuting 6078 instructions, 7828 cycles, 1.288 CPI
Program terminate
Simulation statistics
=====================
Simulation time : 0.002 s
Simulation cycles: 7828
Simulation speed : 3.358 MHz
make[1]: Leaving directory '/home/wei/srv32/tools'
Compare the trace between RTL and ISS simulator
=== Simulation passed ===
```
## Requirements2
```bash=
cd ~/srv32/sim/
ls
```
Then you could find out the wave.fst file.
### SRV32 Architecture

Because srv32 is a three-stage cpu, then we focus on the **PC inst branch** of **IF/ID** **EX** **WB**.
And add **stall** signal source to observe when stall strategy happening to avoid data hazard.
### find the wave.fst file
### open the GTKwave

#### Here we choose below signal source

#### Only in the beginning stall had happened
you could see the stall signal active in the beginning. And keep about 9 clock time along.

## Requirements3
### Original code
```c=
char* addBinary(char a[], char b[]) // two string as input
{
char* ans=(char*)malloc(8); // final answer
strcpy(ans,""); // ans string initialize
char aa[8], bb[8]; // argument two local string
strcpy(aa,a); // two string initialize
strcpy(bb,b);
int num_a=strlen(a),num_b=strlen(b),num=max(num_a,num_b),carry=0; // find max size of strings
if(num_a>num_b) // let shorter string as long as longer one (zero padding)
{
for(int i=0;i<num_a-num_b;i++)
{
char tmp[8]; // tmp string to save the current string
strcpy(tmp,bb); // initialize the tmp string
sprintf(bb,"%d%s",0,tmp); // zero padding
}
}else if(num_a<num_b) // same concept about privious one
{ // , but we don't care the equal situation
for(int i=0;i<num_b-num_a;i++) // ,because that is not necessary
{
char tmp[8];
strcpy(tmp,aa);
sprintf(aa,"%d%s",0,tmp);
}
}
for(int i=num-1;i>=0;i--) // add two binary string
{
int sum; // sum of the current number and carry number
char tmp[8]; // tmp srting
strcpy(tmp,ans); // initialize
sum=(aa[i]-'0')+(bb[i]-'0')+carry; // sum string a,b number and carry number
sprintf(ans,"%d%s",sum%2,tmp); // save the residual
carry=sum/2; // save carry
if(carry!=0 && i-1<0) // if the current i is final one
{ // ,save the carry as the first member of ans
strcpy(tmp,ans);
sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
}
}
return ans;
};
```
#### Performance
1. RTL:
instructions: 10613
cycles: 13527
CPI: 1.274
2. rvsim:
instructions: 10613
cycles: 13527
CPI: 1.275
```bash=
make[1]: Entering directory '/home/wei/srv32/sw'
make -C common
make[2]: Entering directory '/home/wei/srv32/sw/common'
make[2]: Nothing to be done for 'all'.
make[2]: Leaving directory '/home/wei/srv32/sw/common'
make[2]: Entering directory '/home/wei/srv32/sw/Add_Binary'
riscv-none-embed-gcc -O3 -Wall -march=rv32im -mabi=ilp32 -nostartfiles -nostdlib -L../common -o Add_Binary.elf Add_Binary.c -lc -lm -lgcc -lsys -T ../common/default.ld
Add_Binary.c: In function 'addBinary':
Add_Binary.c:81:26: warning: '%d' directive writing between 1 and 10 bytes into a region of size 8 [-Wformat-overflow=]
81 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~
Add_Binary.c:81:25: note: directive argument in the range [-536870960, 536871118]
81 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~~~~~
Add_Binary.c:81:13: note: 'sprintf' output 2 or more bytes (assuming 11) into a destination of size 8
81 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
riscv-none-embed-objcopy -j .text -O binary Add_Binary.elf imem.bin
riscv-none-embed-objcopy -j .data -O binary Add_Binary.elf dmem.bin
riscv-none-embed-objcopy -O binary Add_Binary.elf memory.bin
riscv-none-embed-objdump -d Add_Binary.elf > Add_Binary.dis
riscv-none-embed-readelf -a Add_Binary.elf > Add_Binary.symbol
make[2]: Leaving directory '/home/wei/srv32/sw/Add_Binary'
make[1]: Leaving directory '/home/wei/srv32/sw'
make[1]: Entering directory '/home/wei/srv32/sim'
a : 1000000
b : 1
add two binary : 1000001
Excuting 10613 instructions, 13527 cycles, 1.274 CPI
Program terminate
- ../rtl/../testbench/testbench.v:418: Verilog $finish
Simulation statistics
=====================
Simulation time : 0.085 s
Simulation cycles: 13538
Simulation speed : 0.159271 MHz
make[1]: Leaving directory '/home/wei/srv32/sim'
make[1]: Entering directory '/home/wei/srv32/tools'
./rvsim --memsize 128 -l trace.log ../sw/Add_Binary/Add_Binary.elf
a : 1000000
b : 1
add two binary : 1000001
Excuting 10613 instructions, 13527 cycles, 1.275 CPI
Program terminate
Simulation statistics
=====================
Simulation time : 0.004 s
Simulation cycles: 13527
Simulation speed : 3.426 MHz
make[1]: Leaving directory '/home/wei/srv32/tools'
Compare the trace between RTL and ISS simulator
=== Simulation passed ===
```
### Optimize code
```c=
char* addBinary(char a[], char b[]) // two string as input
{
char* ans=(char*)malloc(8); // final answer
strcpy(ans,""); // ans string initialize
char aa[8], bb[8]; // argument two local string
strcpy(aa,a); // two string initialize
strcpy(bb,b);
int num_a=strlen(a),num_b=strlen(b),num=max(num_a,num_b),carry=0; // find max size of strings
if(num_a>num_b) // let shorter string as long as longer one (zero padding)
{
for(int i=0;i<(num_a-num_b)/2;i++)
{
char tmp[8]; // tmp string to save the current string
strcpy(tmp,bb); // initialize the tmp string
sprintf(bb,"%s%s","00",tmp); // zero padding
}
if ((num_a-num_b)%2 !=0)
{
char tmp[8]; // tmp string to save the current string
strcpy(tmp,bb); // initialize the tmp string
sprintf(bb,"%d%s",0,tmp); // zero padding
}
}else if(num_a<num_b) // same concept about privious one
{ // , but we don't care the equal situation
for(int i=0;i<(num_b-num_a)/2;i++) // ,because that is not necessary
{
char tmp[8];
strcpy(tmp,aa);
sprintf(aa,"%s%s","00",tmp);
}
if ((num_b-num_a)%2 !=0)
{
char tmp[8];
strcpy(tmp,aa); // initialize the tmp string
sprintf(aa,"%d%s",0,tmp); // zero padding
}
}
for(int i=num-1;i>=0;i--) // add two binary string
{
int sum; // sum of the current number and carry number
char tmp[8]; // tmp srting
strcpy(tmp,ans); // initialize
sum=(aa[i]-'0')+(bb[i]-'0')+carry; // sum string a,b number and carry number
sprintf(ans,"%d%s",sum%2,tmp); // save the residual
carry=sum/2; // save carry
if(carry!=0 && i-1<0) // if the current i is final one
{ // ,save the carry as the first member of ans
strcpy(tmp,ans);
sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
}
}
return ans;
};
```
#### Performance
1. RTL:
instructions: 8969
cycles: 11451
CPI: 1.276
2. rvsim:
instructions: 8969
cycles: 11451
CPI: 1.277
```bash=
make[1]: Entering directory '/home/wei/srv32/sw'
make -C common
make[2]: Entering directory '/home/wei/srv32/sw/common'
make[2]: Nothing to be done for 'all'.
make[2]: Leaving directory '/home/wei/srv32/sw/common'
make[2]: Entering directory '/home/wei/srv32/sw/Add_Binary_opt'
riscv-none-embed-gcc -O3 -Wall -march=rv32im -mabi=ilp32 -nostartfiles -nostdlib -L../common -o Add_Binary_opt.elf Add_Binary_opt.c -lc -lm -lgcc -lsys -T ../common/default.ld
Add_Binary_opt.c: In function 'addBinary':
Add_Binary_opt.c:64:26: warning: '%d' directive writing between 1 and 10 bytes into a region of size 8 [-Wformat-overflow=]
64 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~
Add_Binary_opt.c:64:25: note: directive argument in the range [-536870960, 536871118]
64 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~~~~~
Add_Binary_opt.c:64:13: note: 'sprintf' output 2 or more bytes (assuming 11) into a destination of size 8
64 | sprintf(ans,"%d%s",carry,tmp); // save the carry to the ans string
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
riscv-none-embed-objcopy -j .text -O binary Add_Binary_opt.elf imem.bin
riscv-none-embed-objcopy -j .data -O binary Add_Binary_opt.elf dmem.bin
riscv-none-embed-objcopy -O binary Add_Binary_opt.elf memory.bin
riscv-none-embed-objdump -d Add_Binary_opt.elf > Add_Binary_opt.dis
riscv-none-embed-readelf -a Add_Binary_opt.elf > Add_Binary_opt.symbol
make[2]: Leaving directory '/home/wei/srv32/sw/Add_Binary_opt'
make[1]: Leaving directory '/home/wei/srv32/sw'
make[1]: Entering directory '/home/wei/srv32/sim'
a : 1000000
b : 1
add two binary : 1000001
Excuting 8969 instructions, 11451 cycles, 1.276 CPI
Program terminate
- ../rtl/../testbench/testbench.v:418: Verilog $finish
Simulation statistics
=====================
Simulation time : 0.072 s
Simulation cycles: 11462
Simulation speed : 0.159194 MHz
make[1]: Leaving directory '/home/wei/srv32/sim'
make[1]: Entering directory '/home/wei/srv32/tools'
./rvsim --memsize 128 -l trace.log ../sw/Add_Binary_opt/Add_Binary_opt.elf
a : 1000000
b : 1
add two binary : 1000001
Excuting 8969 instructions, 11451 cycles, 1.277 CPI
Program terminate
Simulation statistics
=====================
Simulation time : 0.003 s
Simulation cycles: 11451
Simulation speed : 3.481 MHz
make[1]: Leaving directory '/home/wei/srv32/tools'
Compare the trace between RTL and ISS simulator
=== Simulation passed ===
```