# Lab1: R32I Simulator
<contributed by:`xl86305955`>
###### tags:`Computer Architecture`, `RISC-V`
## Requirements
1. Following the instructions of [Lab1: R32I Simulator](/@sysprog/H1TpVYMdB), you shall write RISC-V assembly programs (R32I ISA) such as calculating Fibonacci numbers and output to the console with system calls.
* Don't implement the same subject as others do. Your program shall be different.
* You have to ensure the program functioned with [Ripes](https://github.com/mortbopet/Ripes) simulator.
2. You have to explain how each instruction works along with [Ripes](https://github.com/mortbopet/Ripes) simulator.
* Explain your program with the visualization for multiplexer input selection, register write/enable signals and more. You have to illustrate each stage such as IF, ID, IE, MEM, and WB. In addition, you should discuss the steps of memory updates accordingly.
3. Write down your thoughts and progress in [HackMD notes](https://hackmd.io/s/features).
* [Example page](https://hackmd.io/@kksweet8845/2019q3homworkquiz2): Do not modify this note.
* Insert your HackMD notes and RISC-V assembly programs in the following table.
## Development Environment
* Tools
* Using [Ripes](https://github.com/mortbopet/Ripes) as a RISC-V simulator
## Implementing 9*9 multiplication table using RISC-V
### 9*9 multiplication table implementing in psuedo code
My thought is very simple, just translated the high-level language into RISC-V assembly language.
```clike
for i from 1 to 9
for j from 1 to 9
print i * j = product
print '\n'
```
### Instruction and Pipeline explanation
The RISC-V source code:
```l=
.data
mul: .string "*"
spa: .string " "
row: .string "\n"
equ: .string "="
.text
main:
addi s0, zero, 1 # i = 1
loop1: #for i loop
slti t0, s0, 10 #if(i<10)
beq t0, zero, exit #if(i>=10) go exit
addi s1, zero, 1 #else set j=1
loop2: #for j loop
slti t0, s1, 10 #if(j<10)
beq t0, zero, label #if(j>=10) go label
mv t0, s0 # i
mv t1, s1 # j
mul t2, t0, t1 # i*j
mv a1, t0 #else printf i
li a0, 1
ecall
la a1, mul #printf *
li a0, 4
ecall
mv a1, t1 #printf j
li a0, 1
ecall
la a1, equ #printf =
li a0, 4
ecall
mv a1, t2 #printf i*j
li a0, 1
ecall
la a1, spa #printf " "
li a0, 4
ecall
addi s1, s1, 1 #j++
j loop2
label:
la a1, row #printf \n
li a0, 4
ecall
addi s0, s0, 1 #i++
j loop1
exit: #exit
li a0, 10
ecall
```
As you can see, the output is showed in `Application Output` like `1*1 = 1 1*2 = 2` ..., and so on

:::danger
The changing line operation `\n` don't operate as expected.I can't find the syntax corresponding to this operation in RISC-V
:::
The five stage pipeline diagram will represent the circumstance of `i = 1`.The similar instruction will be repeat ten times until `j = 9`,and the tenth times will jump out the loop and do the another block which is the same as the block below.


After seeing the source code and five stage pipeline diagram, we can strat to discuss about the dataflow in this source code now
Briefly descibe about which `five stage` represented:
* IF (Instuction Fetch): Get the next instruction address which is going to execute in CPU from `PC` (programming counter)
* ID (Instruction Decode): Decode the instruction, determine what format is it and what registers to read
* MEM (Memory): Some instruction may need memory access, like load world, store world
* WB (Write Back): Write back to registers
The assembled code:
```=
addi x8 x0 1
slti x5 x8 10
beq x5 x0 144
addi x9 x0 1
slti x5 x9 10
beq x5 x0 108
addi x5 x8 0
addi x6 x9 0
mul x7 x5 x6
addi x11 x5 0
addi x10 x0 1
ecall
auipc x11 65536
addi x11 x11 -48
addi x10 x0 4
ecall
addi x11 x6 0
addi x10 x0 1
ecall
auipc x11 65536
addi x11 x11 -64
addi x10 x0 4
ecall
addi x11 x7 0
addi x10 x0 1
ecall
auipc x11 65536
addi x11 x11 -100
addi x10 x0 4
ecall
addi x9 x9 1
jal x0 16
auipc x11 65536
addi x11 x11 -120
addi x10 x0 4
ecall
addi x8 x8 1
jal x0 4
addi x10 x0 10
ecall
```
The first instuction set the value of `i` to 1
```=
addi x8 x0 1
```
These two instructions determined the branch should or should not taken by the value of `i`
```=
slti x5 x8 10
beq x5 x0 144
```
The branch taken or not is based on the value in`x5` and determined in `ID` stage.The value in `x5` register was calculated in EXE stage. This would cause the `control hazard`.
The solution of the control hazard is flushed the instuctions, setting the control signal to `NOP` instruction, waiting the `slti` instruction arrive in `WB` stage, so the `beq` instruction can get the right value.

Then goto loop2, setting up the value of `j` and determine the branch taken or not.Because of the `slti` and `beq` instruction,the control hazard would arise again.
```=
addi x9 x0 1
slti x5 x9 10
beq x5 x0 108
```
Now we enter the loop of `j`. Fisrt of all, we move the value of `i`, `j` to `x5`, `x6` registers respectively, calculate the value of `i*j` and save the result to `x7` register
```=
addi x5 x8 0
addi x6 x9 0
mul x7 x5 x6
```
We want to print out the result. The `ecall` instruction can do so. The `ecall` instuction represented `system call` in RISC-V. For example:
```=
la a1, mul // load the * symbol address which defined in .data
li a0, 4 // 4 is represented the system call service code to print the string
ecall // system call, set the mode bit to kernel mode
```

We can print the result `i*j = product` by the following instructions.
```=
addi x11 x5 0
addi x10 x0 1
ecall
auipc x11 65536
addi x11 x11 -48
addi x10 x0 4
ecall
addi x11 x6 0
addi x10 x0 1
ecall
auipc x11 65536
addi x11 x11 -64
addi x10 x0 4
ecall
addi x11 x7 0
addi x10 x0 1
ecall
auipc x11 65536
addi x11 x11 -100
addi x10 x0 4
ecall
```
The `ecall` will cause the pipeline stall for two clocks, until it get the system call information from the forward instructions.

Finished the first iteration of `j`, the value of `j` add one, and jump to loop2
```=
addi x9 x9 1
jal x0 16
```
After serveral loops, we can get the result.