1.通用指令Cache MPC
因为访存类指令占据了存储器的接口,阻止了新的指令进入处理器。因此在冯诺依曼体系结构下,单存储器接口会产生冲突问题。
在RIB模式下(精简指令缓冲器),只保存在访存类指令执行时需要从存储器中取出的指令,将其存入Cache中。
通过这种方法,访存类指令执行的开销可以在Cache命中的情况下减少到一个半周期以内。
MPC包含16项,每一项包含两个部分。每一个部分中保存一条指令。还有一个TAG区域保留,作为地址和处理器模式的标识位(KERNEL_MODE或USER_MODE),以及每条指令是否有效的标识位。
MPC是全相联的。TAG区域包含了每一项的处理器模式位KU_MODE以及地址位31~3的区域。每一项需要30位的数据,由于指令受到字长的限制,第1位和第0位都是常数0.
由于每一项保存两个并列的指令,所以第2位作为选择位出现,用来选择使用哪条指令。
每一部分的数据段包含32位的操作码和相关的VALID位,数据段的总长度位66位。VALID位的作用是判断是否命中。
如果整个处理器处在RESET状态或者CCLR信号有效,则所有的VALID位被清空。
基于内部和外部的信号,Cache逻辑判断是否命中,并将有效的操作码送到输出端口MPC_DATA上。
MPC的接口如下:
信号 | 方向 | 说明 |
DATA_IN | 输入 | 要保存指令的操作码和处理器模式 |
CACHE_PC | 输入 | MPC中查找的PC地址,如果命中应等同于相应的TAG区域的值 |
KU_MODE | 输入 | 当前的内核/用户,如果命中应等同于相对应的TAG区域的值 |
MPC_MODE | 输入 |
设定MPC工作模式的处理器引脚:
IC模式 不在BTC中的指令都保存
RIB模式 在请求存储器访问时总线忙的指令,如果不在BTC中,则保存
|
MEM_ACC | 输入 | 存储器接口被MA级占用,RIB模式下关闭 |
FETCH_MODE | 输入 |
设定IF级在两个Cache都未命中的情况下从主存储器中取出指令所用时间的处理器引脚:
串行取值:在下一拍或者以后进行存储器访问,只有在MA级不工作时才能进行。
ID级在下一拍无法工作,必须提前给出控制信号。
并行取值:MA级不工作,存储器访问和Cache访问同时并行进行,如果Cache命中,存储器访问放弃(nMRQ设为无效)
如果Cache也没命中,而MA级正在工作,送一个控制信号到ID级。并行取指模式占用了总线,因此不适合多处理器操作
|
MPC_ACTIVE | 输入 | 处理器引脚激活MPC的使能信号。关闭MPC的信号通过HIT和MPC_ACTIVE的组合实现,即为始终不命中。 |
CCLR,RESET | 输入 | 初始化MPC,其中所有项目无效 |
HIT | 输出 | MPC包含有查询指令 |
MPC_DATA | 输出 | Cache命中后输出操作数 |
MPC替换策略:
在RESET或CLC之后,Cache按顺序送入指令,如果Cache充满后,就用随机替换的方法进行指令的替换。
随即替换相对与LRU替换策略的优点是实现的代价比较小,Cache规模较小时也能保持较高的命中率。
如果处理器工作的状态总不与Cache的替换策略一致,那么LRU将导致FIFO效应,使得Cache每次都需要替换。
2.条件跳转目标Cache
跳转类指令控制程序流,包括条件跳转BCC和非条件跳转CALL。硬件和软件中断以及异常错误也需要程序流的控制操作,但不包括在跳转类指令中。
Cache可以根据程序地址来识别已经在IF级的跳转类指令。Cache把执行过一次的跳转类指令保存在Cache中,根据局部性原理,跳转类指令再次执行的可能性较大。
一条跳转类指令只在ID级发生实质操作,其他流水线由于对跳转类指令不进行任何操作,所以暂停一级。
由于要保持流水线的畅通,尽量使跳转类指令不再在流水线指令流中出现,并且实现跳转地址直接加载。
对于BTC的跳转类指令
由于硬件中断和外部中断超越了处理器的控制而且不可预测。因此,BTC只装载跳转类指令,与中断或异常无关。
当跳转类指令进入流水线IF级,即跳转类指令地址放上地址总线时,IF级开始在Cache中寻找这条指令。
在下一个时钟周期,指令的操作码在ID级进行解码,同时IF装载一条延迟指令进入流水线中。
在IF级,跳转类指令的下一个时钟周期到来之前,跳转目的地址就必须明确,以便提前终止跳转类指令在流水线中的执行。
如果跳转类指令带ANNUL参数,那么如果跳转不执行,延迟指令必须忽略,这可以通过禁止ID级译码操作来实现。
由于后面的EX、MA和WB级对于跳转类指令来说是不需要的。每一个跳转类指令在存储器中必须只有唯一的地址。
最简单的情况是控制转移不依赖于其他更多的信息(CALL),但是对于BCC指令必须对标志位进行比较。
非条件指令CALL,SWI,JMP,RET,RET1和条件转移指令有明显区别。
JMP、RET和RET1不适用于BTC,因为返回地址会动态改变。对于一个条件转移目标Cache,除了BCC指令之外,其他转移指令也要进行检索,包括CALL指令。
BTC引入两种模式BIG_MODE和SMALL_MODE,在BIG_MODE模式下,BCC和CALL指令在BTC保存;在SMALL_MODE模式下,只保存BCC指令。
条件转移目标Cache的工作过程:
根据BTC_MODE,BCC和CALL指令在ID级解码之后保存进BTC中。
包括指令地址,KU_MODE,延迟指令的操作码、跳转目的以及跳转条件都保存在BTC中,对于CALL指令跳转条件总为真。
在每次比较之后,历史位更新。
如果跳转指令地址在ID级进行的Cache索引中,BTC命中,跳转逻辑产生LOCAL_HIT信号。
如果FETCH_MODE选择了进行访问模式,就将正在进行的存储器取值操作放弃,将下一个周期的延迟指令送入ID级中。
如果跳转执行了,PC被置为跳转目的地址。否则PC值自动加2,即指向延迟槽之后的地址
对跳转指令是否跳转的预测执行可以不是最终正确的判断。
万一对于BCC指令,标志位在上一条指令执行后改变了,必须要作出试探性的跳转策略。
跳转预测不总是正确的,因此必须更正。这种情况由流水线控制逻辑来判断,并通过NEW_FLAGS信号指示BTC,BTC根据历史位再次作出跳转与否的决定。
暂时跳转决策的历史位
两位的历史位HIBITS用于试探性的跳转策略。BTC中的每个部分都有其自己的HIBITS位,有4种状态N、N?、T?和T。
N表示预测跳转不执行,T表示预测跳转执行。N?和T?表示不是非常确定的预测。
如果没有有效的标志位,暂时跳转的决定就要根据历史位HIBITS做出。根据最终跳转的决定,HIBITS位再更新。
如果NEW_FLASH有效,跳转在N和N?状态不执行,而在T和T?状态下执行。
如果发生跳转错误,则在下一个流水线级更正。这时标志位已经有效,因为前一条指令在EX级中执行,标志位在时钟周期末计算出来。
如果发生跳转决策错误,已经装载的指令就必须放弃。即放弃在下一个时钟周期由IF级进入ID级的指令的执行。因此ID级在下一个时钟周期被禁止。
对于带ANNUL参数的错误执行的跳转指令,在ID级中的延迟指令也要被禁止。因此在下一个时钟周期EX级也要被禁止。
无论跳转与否,必须将相应的WORK信号置位,同时PC值置位何时的值。
只有最终正确的跳转决定作出后才对HIBITS更新。对HIBITS更新的功能对于预测的准确率非常重要。
更新逻辑改变HIBITS的状态,状态途中的n和t分别表示最终决定跳转或不跳转。
要改变HIBITS的状态至少要重复2次。
BTC的替换策略
与MPC相同,BTC在RESET或CLC指令之后按顺序进行填充。其后其内容随机进行替换。
在每一次命中之后,HIBITS更新。每一次未命中,跳转类指令就被保存在Cache中,同时HIBITS根据跳转情况初始化成N?或者T?。
对于CALL指令,HIBITS设定为T状态。新指令只有进入ID级后才能保存到BTC中,因为在ID级才能译码并确认是BCC指令或者CALL指令。
中断发生之后,BTC被清空。BTC不能包含错误信息,因此在更换程序后必须清除。
BTC算法
如上图所示,BTC算法将任务分为两个部分,一方面是BTC_CHECK用于试探性的跳转决策和校正。
另一方面,BTC_HIT用于统计命中率,BTC_STORE在未命中的情况下,保存新的指令到BTC中。
BTC_STORE如上文提到的,采用按序装入、随即替换的方式进行。
BTC_HIT的整体流程如下图所示
BTC_HIT信号提供所需的数据,并改变PC的值。无论在标志位有效或试探性的跳转预测进行时都要考虑这一位。
如果跳转决定时基于HI_BITS作出的,处理器必须标记下来,以便在下一个时钟周期通过BTC_CHECK检查并校正。
这样,三种情况:"跳转","不跳转无ANNUL参数","不跳转带ANNUL参数"就区别出来了。
BTC的输出就根据相应的情况配置,程序计数器PC和指令寄存器IR设置相应的值,如果需要禁止流水线级。
BTC_CHECK整体流程如下:
BTC_CHECK决定是否用试探性的方式决定跳转。如果跳转,对跳转的正确性在标识位有效后立即进行检测。
如果需要校正,则与BTC_HIT一样,分为"跳转",“不跳转带ANNUL参数“,“不跳转不带ANNUL参数”三种情况,并且对三种情况进行相应的修改操作。
其中"OLD_"表示信号属于之前的时钟周期。
条件转移目标Cache的结构如下:
BTC包含一个全相联的TAG存储器、一个数据存储器和跳转逻辑。
Cache有16项,每一项包含它的TAG区域和数据区域相应的信息。TAG包括所保存指令的地址和KU_MODE模式信息,数据区包括有效位,跳转目的,延迟指令、条件码CC,HIBITS位和指示ANNUL的指示位。
BTC一行的存储格式如下:
BTC接口如下:
信号 | 方向 | 说明 |
DATA_IN | 输入 | 保存在BTC中的数据,处理器模式、ANNUL位、条件码、跳转目标和延迟指令 |
CACHE_PC | 输入 | 查找BTC的指令地址,如果命中,应与TAG相应区域相同 |
KU_MODE | 输入 | 当前的内核/用户模式,如果命中,应与TAG相应区域相同 |
BTC_MODE | 输入 |
处理器引脚设定BTC工作模式:
BIG_MODE 保存BCC和CALL指令
SMALL_MODE 保存BCC指令
|
CALL,BCC,TAKES | 输入 | 通过该信号,ID级报告正在进行跳转类指令译码,如果是条件跳转,BTC被告知跳转是否执行 |
NEW_FLAGS | 输入 | 下一周期指令将影响标志位 |
BTC_ACTIVE | 输入 | 处理器引脚,用以激活整个BTC,BTC的无效是通过HIT和BTC_ACTIVE信号组合实现的,即总不命中 |
CCLR,RESET | 输入 | 初始化BTC,其中的所有项目无效 |
BTC_TAKEN | 输出 | 暂时或最终跳转决定 |
BTC_PC | 输出 | Cache命中后PC的地址 |
HIT | 输出 | BTC包含所查找的指令 |
BTC_DATA | 输出 | Cache命中后的延迟指令 |
流水线中MPC和BTC的协同:
对于BTC和MPC共有三种状态:禁止状态、命中和未命中状态。
MPC和BTC的替换策略禁止在两个Cache中同时命中同一地址的指令,所以规定BTC命中权的优先级高于MPC命中权。
指令寄存器的来源:
BTC状态 | MPC状态 | 指令来源 |
未命中/关闭 | 未命中/关闭 | 存储器 |
未命中/关闭 | 命中 | MPC |
命中 | 未命中/关闭 | BTC |
命中 | 命中 | BTC |
Cache模式和指令存储
MPC模式 | BTC模式 | 访存类指令 | 条件转移类指令 | CALL | 其他指令 |
关闭 | 关闭 | X | X | X | X |
关闭 | SMALL_MODE | X | BTC | X | X |
关闭 | BIG_MODE | X | BTC | BTC | X |
IC_MODE | 关闭 | MPC | MPC | MPC | MPC |
IC_MODE | SMALL_MODE | MPC | BTC | MPC | MPC |
IC_MODE | BIG_MODE | MPC | BTC | BTC | MPC |
RIB_MODE | 关闭 | MPC | X | X | X |
RIB_MODE | SMALL_MODE | MPC | BTC | X | X |
RIB_MODE | BIG_MODE | MPC | BTC | BTC | X |
3.寄存器堆
寄存器堆REG包含32位40字的RAM存储器,多选器和其他的逻辑单元。
寄存器堆用作处理器的通用寄存器,寄存器堆的结构如下图:
寄存器堆的接口:
信号 | 方向 | 说明 |
ADDR_A
ADDR_B
ADDR_D
C5_DEST
C5_BUS
REG_RnW
|
输入
输入
输入
输入
输入
输入
|
第一个ALU操作数地址
第二个ALU操作数地址
要保存的数据地址
WB写回的结果地址
WB写回的结果
端口P2的读写选择
|
DATA_A
DATA_B
DATA_D
|
输出
输出
输出
|
第一个ALU操作数
第二个ALU操作数
要保存的数据
|
寄存器堆在ID级进行操作数的读取。在WB级将运算结果写入到寄存器堆中。
处理器的定时逻辑和ID以及WB的访问逻辑决定了寄存器堆的控制逻辑。当流水线满载运行时,每个时钟对寄存器堆进行4次访问,3次读操作以及1次写操作。
定义一个双端口的寄存器堆,一个只读端口P1和一个只写端口P2。两个端口都有地址输入端ADDR_P1和ADDR_P2。
P1口有数据输出口DATA_P1,P2有双端口数据接口DATA_P2。信号REG_RnW指示P2口在前半周期是写口,后半周期是读口。
寄存器堆的访问时间必须小于半个时钟周期的长度,大约20ns。这样将4个访问分别放在2个端口来完成。
在前半个周期,写回级连接C5_BUS总线,通过P2口进行写操作,同时ID级从P1口读出要保存的数据并放在D_BUS总线上。
在后半个周期,ID级从P1传送前一个操作数到A_BUS上,传送LP2第二个操作数到B_BUS上。
寄存器堆的实现方案使得流水线达到平衡。两个访问需要40ns的时间。相当于ALU的运算时间。ID级和EX级的关键路径达到基本相同的长度。
RISC处理器的一个特性是寄存器R0中总保存常数0。在40个通用寄存器的阵列中。每一个只有32个寄存器对用户是可见的,余下的8个作为寄存器28~31的第二套重叠寄存器。
在中断发生时,有一套重叠的寄存器根据中断登记掩蔽了相应地址的寄存器。