Part A(第一部分):addi

实验5是项目3A的先决条件,强烈建议学习第16-19讲、讨论9和作业4。

在此部分中,您将设计一个可以执行addi指令的骨架CPU。

任务1:算术逻辑单元(ALU)

填写alu.circ中的ALU,使其能够执行所需的算术计算。参见课程笔记中的表1,该表描述了ALU的输入/输出信号。

任务:实现课程笔记中的表2,该表定义了项目特定的ALU操作及对应的ALUSel值。add已经为您实现。您可以且鼓励使用Logisim内置组件来实现算术操作。

未使用的值:Part A的ALU测试仅使用表2中定义操作的ALUSel值,因此您的设计暂时不需要担心未使用的值。

测试

运行test_alu单元测试。按照测试与调试部分中的调试单元测试示例操作。

test_alu测试模块包含以下测试电路:

  • alu-add
  • alu-all
  • alu-logic
  • alu-mult
  • alu-shift
  • alu-slt-sub-bsel

任务2:寄存器文件(RegFile)

填写regfile.circ,使其包含32个可以写入和读取的寄存器。参见课程笔记状态元素部分中表1中RegFile的输入/输出信号。

额外的输出信号regfile电路的输出中包含8个常量输出寄存器,用于测试和调试目的。确保将这8个输出引脚连接到对应的寄存器:

  • ra (x1)
  • sp (x2)
  • t0 (x5)
  • t1 (x6)
  • t2 (x7)
  • s0 (x8)
  • s1 (x9)
  • a0 (x10)

提醒:

  • x0寄存器应始终包含0值,即使有指令尝试写入它。
  • 善用复制粘贴!最好先完整制作一个寄存器,然后将其用作其他寄存器的模板,以避免重复工作。您可以在Logisim中使用Ctrl/Cmd + D复制选定的组件或组件组。
  • 内置寄存器上的Enable引脚可能会派上用场。

测试与调试

test_regfile测试模块包含以下测试电路:

  • regfile-more-regs
  • regfile-read-only
  • regfile-read-write
  • regfile-x0

任务3:立即数生成器

填写imm-gen.circ中的立即数生成器(不是cpu.circ中的imm_gen子电路)。参见课程笔记中立即数生成器的输入/输出信号。

在Part A的其余部分中,我们将创建刚好足以执行addi指令的CPU。在Part B中,您将重新审视这些电路并扩展它们以支持更多指令。

Part A(第一部分):您的任务是为addi指令生成立即数。您现在可以忽略其他立即数类型,即可以忽略ImmSel

Part B(第二部分):为所有相关指令生成立即数。

测试与调试

您必须先完成下一个任务才能调试此任务!

任务4:数据通路

cpu.circ中填写数据通路,使其包含一个可以执行addi指令的单周期(非流水线)处理器的数据通路。

在此任务中,您可以保持处理器的大多数输入和输出不变,因为addi指令不需要它们。几个值得注意的组件:

  • 常量寄存器输出(参见RegFile任务)
  • 程序计数器和指令(见下文)
  • 内存,参见课程笔记。Part A不需要。

我们知道从头开始构建数据通路可能令人生畏,因此本节的其余部分提供了创建处理器的更详细指导。

回顾执行指令的五个阶段:

  1. 取指(IF)
  2. 译码(ID)
  3. 执行(EX)
  4. 访存(MEM)
  5. 写回(WB)

任务4.1:取指

我们已经提供了程序计数器的简单实现。它是一个32位寄存器,每个时钟周期递增4。ProgramCounter连接到IMEM(指令内存),Instruction从IMEM返回。

此子任务无需实现任何内容!

任务4.2:译码

在此步骤中,我们需要分解Instruction输入并将各个位发送到正确的子电路。

addi是什么类型的指令?指令中有哪些不同的字段,每个字段对应哪些位?

addi是I型指令。字段为:

  • imm [31-20]
  • rs1 [19-15]
  • funct3 [14-12]
  • rd [11-7]
  • opcode [6-0]
在Logisim中,您会使用什么工具来分出不同的位组?

使用分线器从指令中提取5个字段。

哪些字段应该连接到寄存器文件?它们应该连接到寄存器文件的哪些输入?

您从指令中分出的rs1位应连接到寄存器文件的ReadIndex1。 您从指令中分出的rd位应连接到寄存器文件的WriteIndex。 I型指令没有rs2,所以我们现在可以忽略rs2。 记得将时钟连接到寄存器文件!

什么需要连接到立即数生成器?

Instruction连接到立即数生成器。您在上一个任务中制作的立即数生成器应该接收指令并为您输出正确的立即数。

任务4.3:执行

在此步骤中,我们将使用译码后的指令字段来计算实际指令。

addi指令应该向ALU输入哪两个数据值(AB)?

输入A应为寄存器文件的ReadData1

输入B应为立即数生成器的立即数。

指令应该向ALU输入什么ALUSel值?

ALUSel选择ALU将执行哪种计算。由于我们现在只关心实现addi,我们可以硬编码ALU始终选择add操作(ALUSel = 0b0000)。

任务4.4:访存

addi指令不使用内存,因此此子任务无需实现任何内容!

访存阶段是使用存储指令写入内存和使用加载指令读取内存的阶段。因为addi指令不使用内存,我们在Part A中不需要担心它。请忽略DMEM并保持其I/O引脚未驱动。

任务4.5:写回

在此步骤中,我们将把addi指令的结果写回寄存器。

addi指令正在写入什么数据,以及指令将此数据写入哪里?

addi取加法计算的结果(来自ALU输出)并将其写入寄存器rd

ALUResult连接到寄存器文件的WriteData

由于addi指令总是写入寄存器,您现在可以将RegWEn硬连线为1,使寄存器写入始终启用。

测试与调试

运行test_addi集成测试。按照测试与调试部分中的调试集成测试示例操作。

test_addi测试模块包含以下测试电路:

  • addi-basic
  • addi-negative
  • addi-positive

提交与评分

将您的仓库提交到Gradescope上的Project 3A作业。Part A的自动评分器测试与您本地运行的测试相同。Part A占项目3总成绩的20%。

  • ALU (7分)
  • RegFile (8分)
  • addi (5)

总计:20分