文章目录
1. Part A - Math Operations by RISC-V
1.1 Absolute Value 绝对值
- 对于非负数不需要进行取反:修改执行和分支跳转的判断条件
MemCheck:存储计算结果s0到a0中时,地址偏移量(imm)应该为 0 而非 4
1.2 ReLU
整数数组在内存中是连续内存地址存储的
ReLU ( x ) = { x , if x > 0 0 , if x ≤ 0 \text{ReLU}(x) = \begin{cases} x, & \text{if } x > 0 \\ 0, & \text{if } x \leq 0 \end{cases} ReLU(x)={x,0,if x>0if x≤0
- 处理指针地址和整数值是不同逻辑
- 处理异常报错返回
# 地址
mv t0 a0
# 整数
mv t1, a1
# 立即数
li t2, 1
# 异常返回(函数无返回值)
li a0, 36
j exit
1.3 Argmax
- 遍历数组,得到最大值的首次位置下标
1.4 Dot Production 点乘
- 从元素个数为单位的 步幅 转化到地址指针的移动量,需要 ∗ 4 b y t e s *4\ bytes ∗4 bytes (此处元素为整数类型)
1.5 Loss Function 损失函数
对现有函数编写单元测试模块
- 注意边界条件和对应输出的 Error Code
- 尽量写全各种各种边界条件 Corner Case
2. Part B - Matrix Multiplication
神经网络中的计算、训练等过程,都与矩阵乘法密切相关
2.1 Matmul 矩阵乘法
三层循环分支嵌套
- 外层:遍历左边矩阵
m0的行,遍历 index 为i - 内层:遍历右边矩阵
m1的列,遍历 index 为j - 元素乘积操作层:对具体的
m0[i][k]和m1[j][k]相乘,遍历 index 为k
- 在每一个
i和j的条件下,所有k的元素乘积加总,得到结果矩阵d[i][j]的值 - RISC-V 指令
ret,实际上上是jarl x0, 0(ra)的简写 —— 通过读取ra寄存器中的值来确定返回的目标地址,并将这个地址加载到PC中,从而实现返回操作
2.2 从文件读取矩阵到内存中
- 在函数中,只要没有保存在栈空间中的寄存器,都有可能因作为 caller 调用其他函数,而改变调用前所有寄存器中的状态/值
2.3 从内存中存储到文件
- 凡是需要利用
sp栈空间缓存的关键数据,都需要开辟新的临时空间,防止覆盖已有栈内存以及获得 正确的sp指针
2.4 Neural Network
s1(char**)的 array- 读取这种地址指针中的多个参数/元素? —— 地址指针 + 偏移量
lw a0, 4(s1) - 在栈空间的寄存器中存储此类地址指针
- 首先需要
malloc序列大小的存储空间,得到指向该地址的ptr - 将这个
ptr存储到寄存器中,从而得到s1(int**)等指向序列地址的寄存器
- 首先需要
- 读取这种地址指针中的多个参数/元素? —— 地址指针 + 偏移量
- 有很多个需要变量需要作为 saved registers,超过 11 个怎么办? —— 直接使用
sp指向栈空间存储- 先开辟出 64 个字节的空间
- 将所有 saved registers (
s0-s11)分配从12(sp)到60(sp)的空间 - 然后将需要存储的其他变量,通过
sw t0, 4(sp)等形式,直接写入栈空间
Important Bug
Venus ran into a simulator error! You are attempting to edit the text of the program though the program is set to immutable at address 0x00000000!
在这一 project 中,出现这个问题的主要原因是,将新的值复制到栈上的寄存器中的写法存在问题
- 错误写法:
sw a0, 0(s11)- 将
s11中的值作为基准地址(加上偏移量 0) - 向该值所对应的地址写入
a0 - 因为
s11在栈空间中被分配内存后,并未对值进行初始化等操作,默认为0,因此 将这个默认值作为地址,就产生了向不可写入地址进行写操作的报错
- 将
- 正确写法:
mv s11, a0- 将
a0中的值,直接存储到寄存器s11中 - 不涉及任何指针、地址等操作
- 寄存器
s11中存储的值即为所需要的int,而非int*(需要根据这一指针找到相应地址中真正的值)
- 将

被折叠的 条评论
为什么被折叠?



