RISCV的一个核心子集
存储器访问指令: load doubleword - ld store doubleword - sd
算术逻辑指令: add sub and or
条件分支指令: branch if equal - beq
这个子集没有包含所有的定点指令,也没有包含任何浮点指令。但这个子集说明了建立数据通路和设计控制定点关键原理。
在完成指令系统实现的过程中,我们将认识到指令体系结构将从多方面影响指令系统的实现,以及各种策略会怎样影响计算机的时钟频率和CPI每条指令的时钟周期数。
概述
实现每条指令的前两个步骤时相同的:
1 程序计算器PC发送指到指令所在的存储单元,并从中取出指令。
2 根据指令的某些字段选择要读取的一个或两个寄存器。对于ld指令,只需要读取一个寄存器,但大多数其他指令需要读取两个寄存器。
这两个步骤之后,完成指令所需的剩余操作取决于指令类别。对于上述三类指令,剩余操作基本相同。
RISCV指令系统的简单性和规整性使不同类的指令具有类似的执行过程,简化了实现。
例如,在读取寄存器后都是用算式逻辑单元ALU。存储器访问指令用ALU计算地址,算术逻辑指令用ALU来执行运算,而条件分支指令用ALU进行比较。
但经过ALU之后,各类指令所需操作不同。存储器访问指令需要访问存储器以读取数据或存储数据,算术逻辑指令或载入指令需要将来自ALU或存储器的数据写回寄存器。 而条件分支指令需要根据比较结果更改下一条指令的地址,否则,下一条指令的地址会通过PC加4来获得。
所有的指令都始于用程序计数器获得指令在指令存储器中的地址。取出指令后,指令的对应字段指定要使用的寄存器操作数。寄存器操作数一被取出,即可用于计算存储器地址ld sd,计算算术运算进行,分支判断。
如果是算术逻辑指令,ALU结果必须写回寄存器。如果是存取指令,ALU结果将作为存储器地址以存储来自寄存器的值,或将存储器数据加载到寄存器中。
ALU结果或访问存储器的结果将写回到寄存器堆。分支指令需要根据ALU输出来确定下一条指令的地址,这个地址可能来自计算PC和分支偏移量相加的加法器,也可能来自计算当前PC加4的加法器。
一些功能单元的控制依赖于当前执行的指令类型。例如,数据存储器必须在指令是load时被读,store时被写。寄存器堆只能是load或算术逻辑指令时被写。但是ALU的控制不依赖指令类型。 与多路选择器类似,ALU的控制线也根据指令的某些字段来设置,进而控制ALU做哪种运算。
逻辑设计一般方法
包括两种不同类型的逻辑单元:
处理数据值的单元和存储状态的单元
处理数据值的单元是组合逻辑,它们的输出依赖于当前输入。给定相同的输入,组合逻辑单元总是产生相同的输出。组合逻辑单元没有内部存储功能。
状态单元,有存储功能。这是因为关机后重启计算机,通过恢复状态单元的原值,计算机可继续运行,就像没有断电一样。如指令存储器,数据存储器和寄存器都是状态单元。
一个状态单元至少有两个输入一个输出,必须的输入是写入状态单元的数据值和决定何时写入数据值的时钟信号。状态单元的输出提供了在前一个时钟周期写入单元的数据值。例如 逻辑上最简单的一种状态单元是D触发器。
除了D触发器,RISCV还使用了存储器和寄存器。
包含状态单元的逻辑部件称为时序的。输出取决于输入和内部状态。 例如,寄存器的功能单元取决于提供的寄存器号和之前写入寄存器的内容。
时钟同步方法
规定信号可以读出和写入的时间。
采用边沿触发的时钟,即存储在时序逻辑单元种的所有值仅在时钟边沿更新。如果状态单元不是在每个时钟边沿都更新,需要加入一个写控制信号。