lab1-运算

无情的执行指令的机器

经过 lab0,大家已经对 liemu 模拟器的主要流程有了一定的了解。而模拟器就是用代码模拟了实际中 CPU 的执行过程。只不过在模拟器中,这些控制逻辑都是用 C++ 代码实现的,而在实际中,这些逻辑是由硬件电路实现的。

芯片设计是十分复杂的事情,著名的一生一芯就是教大家造芯片的,liemu 模仿的 nemu 也是它的学习内容之一。

但是,如果只关注 CPU 的执行过程,会发现 CPU 十分纯粹。正如蒋炎岩老师经常说的一样:CPU 是一个无情的执行指令的机器。

CPU在上电以后只有这3件事:

  1. pc 所存储的地址处取一条指令;

  2. 执行这条指令;

  3. 更新 pc 的值。

这就是 CPU 纯粹的工作,可以在 liemu 的代码中找到对应的实现。

CPU 是这样的,ram、cache、流水线等部件只要执行具体的任务就可以,可是 CPU 要考虑的事情就很多了。

一条指令从被读取到被执行

指令的生成liemu 中运行的 RISC-V 指令由交叉编译器生成,liemu/inst/demo 中的 Makefile 已经配置好了编译指令的命令,只需要在 liemu/inst/demo 中运行 make 即可生成指令,其中的 demo.s 是指令的源文件,在其中编写 RISC-V 汇编代码,make 之后可以在 out.inst 中看到生成的机器指令。

指令的存储: 不同于 nemu 可以读取 elf 文件。本项目生成的指令直接以十六进制文本的形式存储在 liemu/inst/*.inst 文件中,可以在 liemu/Makefile 中设置具体要模拟执行哪个文件中的指令。

指令的加载liemu 开始运行时,会读取 liemu/inst/*.inst 中的指令,存储在对应的内存位置中。

指令的解析:实际中,CPU 是实时取指令、解析指令、执行指令的,但是 liemuls 功能需要提前展示所有指令的信息,所以在实际执行指令前,所有指令就已经被解析了。提前解析指令时,将指令的汇编形式存储下来,就可以在 ls 时展示出来。而指令的执行过程,则是以统一的 lambda 的形式存储下来。

指令的执行: 在 CPU 真的开始执行某条指令时,已经不需要再次解析了,之前的解析结果可以直接用指令的地址获取到,直接获取之前解析到的函数对象,然后执行即可。不过,为了访问内存过程的完整性,还是进行了取指令操作和解析指令操作。

乘除法指令

RISC-V 的乘除法指令拓展叫做 RV32M, 其中包含了乘法指令 mul 、除法指令 div、求余指令 rem,以及对应的无符号版本 divuremu。对于乘法,两个32 位数相乘的结果是一个 64 位数,而 mul 只能获取结果的低 32 位。因此还有对应的获取高位结果的指令:mulhmulhsumulhu

在 lab1 中,只需要实现 muldivrem 这三个指令即可。

  • mul rd, rs1, rs2 : 将 rs1rs2 相乘(定点补码的布斯乘法)的结果存入 rd 中, 忽略算术溢出。

  • div rd, rs1, rs2 : 将 rs1 除以 rs2 (定点补码的布斯除法)的结果存入 rd 中,结果向零舍入。

  • rem rd, rs1, rs2 : 将 rs1 除以 rs2 (定点补码的布斯除法) 的余数存入 rd 中,结果的符号与 rs1 相同。

RTFSC

本次实验的所有代码修改应该都在 src/Inst.hpp 中,具体的实现内容分别在 3 个函数中,请你自己找到这 3 个函数,并完成其中的内容。

定点补码布斯乘法

定点补码布斯除法

任务

  • 完成 muldivrem 指令的实现。

  • 不得直接使用 C++ 的乘除法运算符,需要自己基于位运算实现乘法和除法的算法。

  • 如果你觉得用传统的方法操作每一位太麻烦,不妨考虑使用 C++ 的 std::bitset 类型,它可以将一个整数转换为二进制表示,方便进行位运算。使用方法请 STFW 或者 ATFAI。

验证正确性

insts/ 目录下新建文本文件 lab1.inst,将以下指令写入文件中:

之后打开 Makefile 文件,将其中的 INST_NAME 的值改为 lab1

然后在 liemu 目录下运行 make run,输入 si 114 执行完所有指令查看输出结果,如果输出结果如下,说明你的实现的计算结果是正确的。

提交

将你的整个 src 目录提交,提交文件为一个压缩包,命名为 lab1.tar.gz,压缩包以附件的形式发送到指定的邮箱,其中邮件主题为 lab1-学号-姓名,例如 lab1-920106114514-丁真

具体来说,在收到 lab1.tar.gz 之后,将其解压缩,期望会得到一个名为 lab1 的目录,目录下有 src 目录。

最后更新于