1 引言
随着集成电路设计和工艺技术的发展,嵌入式系统(SOC)已经在PDA、机顶盒、手机等信息终端中被广泛应用。他不仅减小了电路尺寸,而且具有成本低廉,可靠性高,功耗低等优点。可以说嵌入式系统是未来集成电路发展的方向。而作为嵌入式系统核心的微处理器,是SOC不可或缺的“心脏”,微处理器的性能直接影响整个SOC的性能。
为了提高CPU的效率和指令执行的并行性,现代微处理器已经广泛采用流水线设计,对于一些较高性能的CPU更是采用了多发射的超流水技术等,所以,CPU流水线的设计,将成为决定其性能的关键。
2 处理器体系结构
我们所设计的处理器是基于MIPS指令集的64位RISC结构,执行32位定长的MIPS指令,具有五级流水线。中央处理单元有32个通用寄存器和3个特殊功能寄存器:PC,HI,LO。其中PC是程序计数器,HI和LO用于64位乘除法运算。系统协处理器CP0的32个CP0寄存器和TLB提供内存管理和流水线中的异常处理功能。此外,处理器还提供了16k的指令Cache和8k数据Cach e。
图1所示为处理器的系统结构框图,图中清楚地表明了各个模块间的控制关系(实线表示)和在流水线控制下的数据流向(空心线表示),流水线每一级之间由级间寄存器暂存对应指令的控制信号和数据。
3 流水线结构
根据图1可以看出,将指令执行通道分成了5个单元,通道中流水线的每个单元之间使用级间寄存器来存放相应的控制信号和数据。对应的流水线结构分别为:取指(Ifet ch)、译码(Dec)、执行(Exec)、存储器操作(Mem)和写回寄存器(WB)。如图2所示,指令在流水线上顺序执行,但是同周期有五条指令相交迭。所以采用流水线结构大大提高了指令的并行性,CPI近似等于1。
4 流水线控制的设计
由于采用了五级流水线设计,需要一个核心的流水线控制模块对这个流水线上的各个单元进行控制,以确保流水线正确高效地运行。值得注意的是,指令在流水线上的处理并不是简单地如图2所示的一个流畅序列,而是会出现很多因素破坏指令流水的平衡性,这些因素有:
(1)由于流水线上的2个执行单元同时使用同一硬件资源而产生冒险。
(2)部分指令在1个周期不能完成相应流水阶段的操作,如乘法指令在Exec级在ALU运算需要多个周期。
(3)指令运算的结果在Exec级得到,WB级才写回寄存器堆,而后续指令在结果写回前需要使用结果。
(4)Branch指令、跳转指令和ERET等指令导致流水线上程序流的改变。
(5)在流水线的执行过程中随时都可能有异常发生。
流水线控制就是解决以上问题,控制流水通道中的指令执行过程,在各种情况下能够保证程序的指令流有序、无误地执行。他主要包括以下各个单元,图3给出了流水线控制部分的总体结构。
4.1 异常处理单元
异常是指令运行过程中发生的不可预测的中断,需要预先定义的异常处理程序来解决。他可能发生在流水线的Mem,Exec和Dec级,Mem级的异常优先级最高,后面依次为Exec级和D ec级。异常发生后,流水线中导致异常的指令以及后续指令都要被中止,异常处理程序调入流水线中执行。
异常处理单元收集各个异常信号并对其进行单周期监测,确保异常的及时响应,若多个异常同时发生需要判断异常的优先级,并处理处于最高优先级的异常。此时异常处理单元通过互锁单元使流水线暂停2个周期,将异常信息存入CP0寄存器,保存EPC,并由流水线冲刷单元终止流水线上的无效指令。流水线调入异常处理向量,重新开始执行指令。如图4所示为异常处理的流程,硬件处理部分由异常处理单元控制完成,软件部分为异常服务程序的执行过程。
4.2 互锁处理模块
互锁的发生主要有以下几种情况,一是由于流水线中的2个处理模块同时使用同一资源产生冒险,此时等待资源的流水级以及前面的流水级都要等待;二是由于在某一流水级的操作需要多个时钟周期,整个流水线上的各个流水级等待多周期操作的完成。当互锁发生后,互锁处理模块暂停流水线直到互锁解决。如果从不同流水级同时发出暂停流水线的请求,也要判断暂停流水线请求的优先级。
互锁单元收集互锁信号,并响应最高优先级的互锁信号。在判断互锁类型后,向相应的执行单元发出Stall(流水线停止)信号,该信号必须为整数个时钟周期。
4.3 优先级判别模块
对于特定的异常或互锁,都对应于流水线的某一级。在流水线指令交迭执行的过程中异常和互锁也会同时发生。优先级判别模块根据异常处理单元和互锁处理单元送来的异常与互锁的请求信号来判断是由异常处理模块来终止流水线上执行的指令还是由互锁单元将流水线暂停。
异常处于较高优先级时,产生异常的指令及其后续指令都要终止在流水线上的操作,所以未发生的互锁将被清除。互锁处于较高优先级时,异常信号保持,直到流水线上无较高优先级的互锁信号时流水线响应异常。
4.4 流水线冲刷
在流水线运行的过程中,由于程序执行的不确定性,会出现异常或者是跳转、子程序或异常处理程序返回的情况,导致顺序执行的指令发生变化。但是,由于采取了流水线设计,在指令顺序发生变化时需要舍弃已经进入流水线的部分指令,从其他指令地址重新装载指令。
流水线为了冲刷相应的指令,对指令缓存,Dec,Exec和Mem级的控制信号加入了多路选择器,通过流水线冲刷单元发出的选择信号来选通控制信号,正常情况下选通控制信号来完成对各级操作的控制,如果要冲刷某一级流水线上的指令(如Exec级),则相应的flushExe c信号选择“0”来执行空操作,被冲刷的流水级可以看作执行了一条NOP指令。
4.5 数据旁路
通过对流水线结构的分析发现,对于一条执行结果要写回寄存器的指令,在Exec级计算出的数据要在WB级才写回寄存器堆,后面的指令如果需要该结果,就需要等待直到数据写回才继续流水线执行。如图2中的第一条sub指令将$1和$3相减的结果保存到$2寄存器,结果在C3周期得到,C5周期写回寄存器,而后续的and和or指令分别在C4、C5使用$2的值就会产生错误的结果。而add和sw在C6和C7使用$2寄存器的值就会得到希望的结果。为了保证指令在流水线上正确高效地执行,我们在流水线控制中增加了数据旁路,在数据写回寄存器堆前将得出的结果从流水级间的暂存寄存器中调到Exec级使用。判断是否从旁路中选择的条件为:
图5是增加了数据旁路结构的流水线通道示意图。表示了图2中指令流在C4周期流水线的状态。
4.6 数据冒险监测
数据旁路避免了流水线通过Stall来解决数据冒险的问题,提高了指令的执行效率。但是当load指令后面的一条指令试图读取寄存器与load指令要写的寄存器相同时,load的数据在Me m级从存储器读入,而Exec的指令必须要Stall一个周期才能通过数据旁路从Mem/WB寄存器得到数据。如:
当load指令进入Exec级,and指令进入Dec级,此时判断到load指令装载的目的寄存器与and指令的源寄存器相同,就会出现数据冒险,此时HDUStall信号使and指令等待一周期,loa d指令在Mem级得到数据后通过数据旁路机制解决数据冒险。
数据冒险监测单元也对于CP0寄存器的冒险进行了检测并控制流水线采取相应的避免机制。
5 指令调试
作为对整个流水线的控制,必须在流水通道内运行各种指令流,分析流水线的控制信号能否对这些指令流在流水线上的执行进行精确控制。对整个处理器进行了虚拟仿真和FPGA验证,在仿真平台和FPGA验证板上运行了各种可能的指令流,分析了流水线控制信号的变化,确保了这个处理器的中心控制模块对指令流水线的正确控制,并达到了较高的运行效率。图6是采用虚拟仿真平台对发生itlb_miss exception的仿真波形。
五级流水线控制单元大大提高了处理器的执行效率,达到了64位处理器的高性能设计,处理器的速度达到了120 MHz,有较强的DSP数据处理能力,并且可以运行WinCE,Linux等嵌入式操作系统。