# Lab1:RV32I Simulator
###### tags: `RISC-V` `2022 Computer Architecture`
## Length of last word ([leetcode 58](https://leetcode.com/problems/length-of-last-word/))
### describe:
Given a string s consisting of words and spaces, return the length of the last word in the string.
A word is a maximal substring consisting of non-space characters only.
Example :
```
Input: s = " fly me to the moon "
Output: 4
Explanation: The last word is "moon" with length 4.
```
Constraints :
```
* 1 <= s.length <= 10^4
* s consists of only English letters and spaces ' '.
* There will be at least one word in s.
```
## C code
```c
#include <stdio.h>
#include <string.h>
int lengthOfLastWord(char *s){
int j = strlen(s)-1;
int length = 0;
s = s+j;
while(*s == ' '){
s--;
}
while(*s != ' '){
s--;
length++;
}
printf("length of last word is %d.", length);
}
int main(){
char *str = "I am a student ";
lengthOfLastWord(str);
return 0;
}
```
:::warning
:warning: Instead of comparing a byte at one time, can you use efficient word-by-word comparisons?
:notes: jserv
:::
:::info
hello prof. jserv , sorry that I can't understand the warning. Do you mean that I shouldn't use the char to calculate the length of the word?
:::
:::danger
Where is your RISC-V Assembly listing?
:notes: jserv
:::
:::info
I already done, but I am still working on the part of checking my data automatically.
:::
## Assembly code ver1
```risc=
.data
str1: .string "Hello World"
str2: .string "I am a student "
str3: .string " abc "
str: .string "length of last word is "
space: .string " "
.text
# s1 = str1 address
# s2 = space
# s3 = length
main:
#function:lengthOfLastWord(char * s)
la s1, str1
lb s2, space
add s3, x0, x0 #initialize length
#find the position of the last letter is not space
jal ra, strlen #strlen()
#print result
la a0, str1
addi a7, x0, 4
ecall
li a0, 13 #CR
li a7, 11
ecall
la a0, str #length of last word is
addi a7, x0, 4
ecall
add a0, s3, x0 #length
li a7, 1
ecall
li a7, 10 #end
ecall
strlen:
addi s1, s1, 1 #find the last position of the string
lb t0, 0(s1)
bne t0, x0, strlen
addi s1, s1, -1
lb t0, 0(s1)
bne t0, s2, loop2
loop1: #my first while
addi s1, s1, -1 #s--
lb t0, 0(s1) #t0=s[i], i=length(s)-1
beq t0, s2, loop1 #while(char[i]==" ")
loop2: #my second while
addi s1, s1, -1 #s--
lb t0, 0(s1) #t0=s[i], i=last word
addi s3, s3, 1 #length++
bne t0, s2, loop2 #while(char[i]!=" ")
ret
```
### code explain
I use two loop to calculate the length of last word.
#### loop1:
if the last part of the string has space, I decrease the position until I find the position which isn't a space.
Then I branch to loop2
#### loop2:
I start to count the length of the word, once I decrease the position, I increase the length, until I encounter a space. If I meet the space, I return the value of length.
### Pseudo Instruction
```
00000000 <main>:
0: 10000497 auipc x9 0x10000
4: 02448493 addi x9 x9 36
8: 10000917 auipc x18 0x10000
c: 03790903 lb x18 55 x18
10: 000009b3 add x19 x0 x0
14: 044000ef jal x1 68 <strlen>
18: 10000517 auipc x10 0x10000
1c: 00c50513 addi x10 x10 12
20: 00400893 addi x17 x0 4
24: 00000073 ecall
28: 00d00513 addi x10 x0 13
2c: 00b00893 addi x17 x0 11
30: 00000073 ecall
34: 10000517 auipc x10 0x10000
38: fd850513 addi x10 x10 -40
3c: 00400893 addi x17 x0 4
40: 00000073 ecall
44: 00098533 add x10 x19 x0
48: 00100893 addi x17 x0 1
4c: 00000073 ecall
50: 00a00893 addi x17 x0 10
54: 00000073 ecall
00000058 <strlen>:
58: 00148493 addi x9 x9 1
5c: 00048283 lb x5 0 x9
60: fe029ce3 bne x5 x0 -8 <strlen>
64: fff48493 addi x9 x9 -1
68: 00048283 lb x5 0 x9
6c: 00148493 addi x9 x9 1
70: 01229863 bne x5 x18 16 <loop2>
00000074 <loop1>:
74: fff48493 addi x9 x9 -1
78: 00048283 lb x5 0 x9
7c: ff228ce3 beq x5 x18 -8 <loop1>
00000080 <loop2>:
80: fff48493 addi x9 x9 -1
84: 00048283 lb x5 0 x9
88: 00198993 addi x19 x19 1
8c: ff229ae3 bne x5 x18 -12 <loop2>
90: 00008067 jalr x0 x1 0
```
## Assembly code ver2
```RISC
.data
str1: .string "Hello World"
str2: .string "i am a student "
str3: .string "a"
str: .string "length of last word is "
space: .string " "
.text
# s1 = str1 address
# s2 = space
# s3 = length
# s4 = filter
main:
#function:lengthOfLastWord(char * s)
la s1, str3
lb s2, space
addi s3, x0, 1 #initialize length = 1
#find the position of the last letter is not space
jal ra, strlen #strlen()
#print result
la a0, str3
addi a7, x0, 4
ecall
li a0, 13 #CR
li a7, 11
ecall
la a0, str #length of last word is
addi a7, x0, 4
ecall
add a0, s3, x0 #length
li a7, 1
ecall
li a7, 10 #end
ecall
strlen:
addi s1, s1, 1 #find the last position of the string
addi s4, s4, 1
lb t0, 0(s1)
bne t0, x0, strlen
loop1:
addi s1, s1, -1 #s--
addi s4, s4, -1 #the last position is not space
lb t0, 0(s1) #t0=s[i]
lb t1, 0(s1)
beq t0, s2, loop1 #while(char[i]==" ")
la s1, str1
loop2:
beq s4, x0, return #if encounter the last position, return
addi s4, s4, -1
addi s1, s1, 1 #s++
lb t0, 0(s1) #t0=s[i]
addi s3, s3, 1 #length++
bne t0, s2, loop2
addi s3, x0, 0 #if encounter a space, length = 0
j loop2
return:
ret
```
### code explain
If the last position has space, I recognized the last position which is not space.Then I start to count the length, if I encounter a space, I reset the length. When I reach the last position which is not space, I return the length.
#### loop1
starting from last position, decrease until I find the position which is not space.
#### loop2
starting from head of the string, continuously adding the value of length. If I meet a space, reset the value of length.
If I reach the position I got from loop1, return length value.
### Pseudo Instruction
```
00000000 <main>:
0: 10000497 auipc x9 0x10000
4: 01d48493 addi x9 x9 29
8: 10000917 auipc x18 0x10000
c: 02f90903 lb x18 47 x18
10: 00100993 addi x19 x0 1
14: 044000ef jal x1 68 <strlen>
18: 10000517 auipc x10 0x10000
1c: 00550513 addi x10 x10 5
20: 00400893 addi x17 x0 4
24: 00000073 ecall
28: 00d00513 addi x10 x0 13
2c: 00b00893 addi x17 x0 11
30: 00000073 ecall
34: 10000517 auipc x10 0x10000
38: feb50513 addi x10 x10 -21
3c: 00400893 addi x17 x0 4
40: 00000073 ecall
44: 00098533 add x10 x19 x0
48: 00100893 addi x17 x0 1
4c: 00000073 ecall
50: 00a00893 addi x17 x0 10
54: 00000073 ecall
00000058 <strlen>:
58: 00148493 addi x9 x9 1
5c: 001a0a13 addi x20 x20 1
60: 00048283 lb x5 0 x9
64: fe029ae3 bne x5 x0 -12 <strlen>
00000068 <loop1>:
68: fff48493 addi x9 x9 -1
6c: fffa0a13 addi x20 x20 -1
70: 00048283 lb x5 0 x9
74: 00048303 lb x6 0 x9
78: ff2288e3 beq x5 x18 -16 <loop1>
7c: 10000497 auipc x9 0x10000
80: f8448493 addi x9 x9 -124
00000084 <loop2>:
84: 020a0063 beq x20 x0 32 <return>
88: fffa0a13 addi x20 x20 -1
8c: 00148493 addi x9 x9 1
90: 00048283 lb x5 0 x9
94: 00198993 addi x19 x19 1
98: ff2296e3 bne x5 x18 -20 <loop2>
9c: 00000993 addi x19 x0 0
a0: fe5ff06f jal x0 -28 <loop2>
000000a4 <return>:
a4: 00008067 jalr x0 x1 0
```
## Ripes
### 5 stage pipeline
#### overview
1. IF (Instruction Fetch): Read an instruction from memory.
2. ID (Instruction Decode): Read source operands from the register file.
3. EX (Execute Stage): Perform ALU operation.
4. MEM (Memory Access): Access data memory.
5. WB (Register Write Back): Update register file.

whole block diagram of Ripes RISC-V simulator

#### IF
Read an instruction from memory
* Use the program counter (PC) to index into the IMemory
* Compute NPC by incrementing current PC
Update pipeline registers
* Write the instruction into the pipeline registers

#### ID
Generate control signals for the opcode bits
Read source operands from the register file.
* Use the specifiers for indexing RF
Update pipeline registers
* Send the operand and immediate values to next stage
* Pass control signals and NPC to next stage

#### ES
Perform ALU operation.
* Compute the result of ALU
* Compute branch target

#### MEM
Access data memory.
* Load/store address: ALU outcome
* Control signals determine read or write access
Update pipeline registers
* ALU results from execute
* Loaded data from D-Memory
* Destination register

#### WB
Update register file.
## Reference
[2022 Computer Architecture](http://wiki.csie.ncku.edu.tw/arch/schedule)
[PIPELINING: 5-STAGE PIPELINE Mahdi Nazm Bojnordi](http://www.cs.utah.edu/~bojnordi/classes/6810/f19/slides/05-pipelining.pdf)
[The RISC-V Instruction Set Manual Volume I: Unprivileged ISA](https://riscv.org/wp-content/uploads/2019/06/riscv-spec.pdf)