contributed by < qwe661234
>
This problem is based on LeetCode 203. Given the head of a linked list and an integer variable val
, remove all the nodes of the linked list that has Node.val == val
, and return the new head.
register s0
represent the origin heap limit address, registera0
represent the new heap limit address. We want to allocate 8 bytes for ListNode, 4 bytes for node->value
and 4 bytes for node->next
, so we add register s0
with 8 and store the result in register a0
. Then we use brk
systemcall to set new heap limit address to address stored in register a0
.
It is more convient to use sbrk
systemcall to implement malloc, but Ripes only support brk
systemcall.
First, we store list head address and return address in stack and load array in data section.
Two instruction sw ra, 0(sp)
and sw s0, 4(sp)
store return address and the address of list head (0x0fff0000
) in stack.
This label is for head == NULL
, because head is NULL when i = 0
. Instruction sw s1, 0(s0)
store arr[0] to node->val
, instruction sw x0, 4(s0)
set node->next
to NULL and instuction mv t2, s0
record previous node.
Instruction addi t1, t1, 4
means i++.
Only one instruction in this label loop
is different from label create
, sw s0, 4(t2)
, this instruction store node
to previous_node->next
.
Instruction beq t2, s0
is to check if node->val == target
.
Instruction beq t1, s1
is to check if current_node == head
.
This label is to deal with remove node from list. Register t1
store current node address and register t3
store previous node address.
This label is to deal with remove head from list. Register t1
store current node address, instruction lw t1, 4(t1)
means we load head->next
and instruction mv s1, t1
means we store head->next
to head
.
This function is for testing results automatically, we load answers which we has defined and value store in list node, then we assert whether these two values are equal or not.
The original linked list is 1->2->6->3->4->5->6
. After removing target elements in linked list, the linked list would be 1->2->3->4->5
.
If we create list reversely(from last node to first node), we can just store current_node
to pervious_node->next
, instead of set current_node->next = NULL
. Also, we don't need to care about this creating is for head or node. Therefore, we can save instruction sw x0, 4(s0) # node->next = NULL
and merge label create
to label loop
. But, we should reverse the arrange of array in data section, because you create list reversely.
Instruction pipeline
is a technique for implementing instruction-level parallelism within a single processor. We partition an instruction to five stages.
Stage | Full name |
---|---|
IF | Instruciton Fetch |
ID | Instruction decode & read register |
EX | Execution or Address Calculation |
MEM | Data memory access (load data from memory) |
WB | write back (write data back to register) |
Also, we have four pipeline register
to store the data of pervious stage. Next stage would load data from pipeline register
and store new data to next pipeline register
.
We take instruction lw t0, 4(t1)
as example
In this stage, load the instruction which address is PC, and store PC + 4 to IF/ID pipeline register.
In this stage, decode the instruction loaded from IF/ID pipeline register. the instruction is lw t0, 4(t1)
, so R1
is register t1
(x6) , R2
in this instruction is useless, imm
is 4 and register t0
(x5) would store in ID/EX pipeline register.
Reg 1 means the address store in register t1
(x6), here is 0x00000020.
In this stage, we pass immediate and the address store in register t1
(x6) to ALU, ALU will execute add operation to calculate right memory address that we want to access value.
Here is 0x00000020 + 4 (immediate) = 0x00000024.
In this stage, we will access data store in memory address that ALU calculate in previous stage.
In last stage, we will write data which we access in pervious stage back to the target register.
We can notice the below image, red line represent the target register number, and blue line represent the value that access from memory.
The pipeline design might encounter three types of hazard
A required resource is busy, and instruction need to wait until the resource is ready.
An instruction depends on completion of data access by a previous instruction.
There are two scenarioes for data hazard
There is an example of RAW, before the first instruction add s0, t0, t1
write back data to registerx8
, the second instruction sub t2, s0, t3
has read data from register x8
.
In this Image, Ripe
use forwarding to avoid data hazard.
There is an example of RAW, before the first instruction lw s0, 20(t1)
access memory and write back data to registers0
, the second instruction sub t2, s0, t3
has read data from register s0
.
In this Image, Ripe
use stall and forwarding to avoid data hazard.
there are three solution for data hazard:
Branch determines flow of control, and fetching next instruction depends on branch outcome.
Result of branch is known at the EX stage.