特权系统的支持
本节将会详细介绍流水线中对特权指令、中断异常的支持。
1 控制状态寄存器
-
CSR写指令对指令流的影响:
处理器可以对控制状态寄存器(CSR)进行读写。值得注意的是,除了读写,在触发异常、触发中断时CSR的值也会发生改变,这意味着控制状态寄存器的值变化可能会影响指令流(例如在写入CRMD寄存器后立刻执行特权不合法的特权指令)。考虑到CSR读写指令执行频率并不高,因此对CSR写指令采用执行后冲刷流水线的思路来实现。
-
CSR写指令的写入时机:
对CSR进行重命名的代价是比较大的,在没有重命名的情况下,写回段不能直接对CSR进行写入,而是应当在提交指令后再进行写入。为优化地址转换的时序,当CSR被写入时,处理器会多阻塞一个周期,用以将CSR信息锁存一个周期后送入TLB。
-
ROB对CSR写指令的支持:
CSR写指令由乘除模块进行处理,这个模块是顺序发射的,因此处理器在ROB中维护了一个缓冲区,CSR写地址、写数据等信息都会在执行阶段写入这个缓冲区,提交时由这个缓存对CSR发起写操作。
由于CSR写指令一定会冲刷全部流水线,故在冲刷流水线前,缓冲区仅仅会记录最旧的CSR写请求,后续写请求将会被缓冲区无视
2 异常处理
龙芯架构32位精简版指令集规定了若干异常,根据触发地点不同可以分为:
- 前端:PIF,PPI,ADEF,SYS,BRK,INE,IPE,TLBR
- 后端:PIL,PIS,PME,PPI,ADEM,ALE,TLBR
注意到,后端的异常只会在访存流水线中产生,因此可以采用如下方法进行处理:
- 在译码阶段之前产生的所有异常,都会将产生异常的指令替换为一条
mul $r0, $r0, $r0
指令,并在重命名阶段将异常写入重排序缓存 - 在译码阶段产生的异常,直接将其目标队列序号设置为乘除法队列,并将运算设置为乘法,并在重命名阶段将异常写入重排序缓存
- 由于只有加载和存储指令可能在后端触发异常,而能够在后端触发异常的加载和存储指令在前端一定没有触发异常(否则就将被替换为
mul $r0, $r0, $r0
并送入乘除法队列)。因此,访存流水线会在写回段将后端产生的异常写入重排序缓存。并将这条指令附带的全部写入控制信号设置为无效。
3 中断处理
ESTAT寄存器在每个周期都会对中断源进行采样,一旦侦测到存在异常信号,就会立刻保存到ROB的缓冲区里,当下一条指令提交时,这条指令会被打上中断标记,并触发这个中断。
4 访存单元控制指令
4.1 TLB读写与查找
TLB相关指令都由乘除法流水线进行处理。
- TLBRD:执行阶段读出对应的TLB表项,写入ROB的缓冲区中,提交时同步到CSR中
- TLBWR/TLBFILL:提交阶段将CSR中的值写入TLB中,TLBFILL使用了计数器的低4位进行随机化处理
- TLBSRCH:执行阶段查找TLB,找到命中的表项索引,写入ROB的缓冲区中,提交时同步到CSR中
- INVTLB:执行阶段将操作数写入ROB的缓冲区中,提交时对TLB进行处理
4.2 Cache操作
CACOP指令涉及地址转换,因此需要送入访存流水线。CACOP必须保证:在执行之前所有的Store操作都已经完成,因此,CACOP会滞留在发射队列中,直到这条指令被确认为最旧的指令才会发射。
对于DCache而言,CACOP可以视为一次普通的无效果访存,而对于ICache而言,这条指令打断了正常取指的节奏,因此当CACOP提交后,流水线依然需要冲刷一次来恢复到正常的取指节奏。