OpenRISC—OR1200各子模块总览
上一篇《OpenRISC—OR1200编译链环境》中对OpenRISC 1000架构有过简单介绍,从本节开始,后续将更详细介绍OR1200软核。
1. OR1200框架
OR1200是一个采用Harvard结构的32位RISC处理器,其基于OpenRISC1000架构,具有五级流水线、支持MMU、Cache及基本的DSP功能。
OR1200总体框图如下:
OR1200具有32个通用寄存器,没有影子寄存器,所以不支持上下文快速切换。默认配置中有8KB的直接映射数据缓存、8KB直接映射指令缓存,缓存块大小为16字节。默认配置中数据MMU含有64项的直接映射快表(DTLB:Data Translation Lookaside Buffers);指令MMU含有64项的直接映射快表(ITLB:Instruction Translation Lookaside Buffers )。
OR1200采用wishbone B3版本的总线接口,支持电源管理、计时器、调试和外部中断。需要注意,虽然OR1200的代码中包含FPU,但这里FPU实际并不是OR1200的一部分,而是一个独立的项目,所以本书不对FPU的实现代码进行分析。
2.OR1200基础
2.1 寻址方式
OpenRISC 1000 寻址模式有寄存器间接寻址、PC相对寻址。
(1)寄存器间接寻址
这种寻址模式主要是加载/存储指令使用,它将一个16位的立即数做符号扩展,然后与指定的通用寄存器的值相加,从而得到有效地址。
(2) PC相对寻址
这种寻址模式主要是转移指令使用,在转移指令中有一个26位立即数,将其符号扩展,然后与程序计数寄存器(PC)的值相加,从而得到有效地址。
2.2 位和字节次序
OR1200默认采用MSB(Most Significant Byte)字节序或称“大端字节序”(big endian byte),但如果使用了字节重排序硬件,它也支持LSB(Least Significant Byte)字节序或称“小端字节序”。重排序使用位SR[LFE]激活。
2.3 寄存器集
RISC有一个特点:大量使用寄存器。这是因为寄存器的存取可以在一个时钟周期内完成,同时简化了寻址方式。OR1200的指令中除加载/存储指令外,都是使用寄存器或立即数作为操作数的。
OR1200中的寄存器分为两类,通用寄存器(GPR:General Purpose Register)和特殊寄存器(SPR:Special Purpose Register)。
2.3.1 通用寄存器(GPR)
32个通用寄存器被标识为R0~R31,并且在32位处理器中是32位线宽。它们存储浮点数据、向量或内存指针,GPR可被ORBIS、ORVDX和ORFPX指令作为源和目的地寄存器访问。
其中,R0一般用作常量0。
2.3.2 特殊寄存器(SPR)
所有单元的特殊寄存器被分为32组,每组中的寄存器使用不同的寄存器地址(编号)来区分,一个组中可以放有几个不同单元或处理器的寄存器。特殊寄存器分组如下表:
组号 | 特殊寄存器组功能描述 |
0 | 系统控制与状态寄存器 |
1 | 数据MMU(Data MMU)有关寄存器 |
2 | 指令MMU(Instruction MMU)有关寄存器 |
3 | 数据缓存(Data Cache)有关寄存器 |
4 | 指令缓存(Instruction Cache)有关寄存器 |
5 | 乘累加(MAC)有关寄存器 |
6 | 调试单元(Debug Unit)有关寄存器 |
7 | 性能计数单元(Performance Counters Unit)有关寄存器 |
8 | 电源管理(Power Management)有关寄存器 |
9 | 可编程中断控制器(Programmable Interrupt Controller)有关寄存器 |
10 | 计时器单元(Tick Timer)有关寄存器 |
11 | 浮点单元 |
12~23 | 保留 |
24~31 | 用户单元 |
OpenRISC 1000架构处理器需要至少使用第0组特殊寄存器,其它寄存器可选;并且只有单元存在时,单元相应的特殊寄存器组才存在。第0组特殊寄存器表,如下:
组号 | 寄存器编号 | 寄存器名 | 用户模式 | 超级监管者模式 | 描述 |
0 | 0 | VR | - | R | 版本寄存器 |
0 | 1 | UPR | - | R | 单元出现寄存器 |
0 | 2 | CPUCFGR | - | R | CPU配置寄存器 |
0 | 3 | DMMUCFGR | - | R | 数据MMU配置寄存器 |
0 | 4 | IMMUCFGR | - | R | 指令MMU配置寄存器 |
0 | 5 | DCCFGR | - | R | 数据Cache配置寄存器 |
0 | 6 | ICCFGR | - | R | 指令Cache配置寄存器 |
0 | 7 | DCFGR | - | R | 调试配置寄存器 |
0 | 8 | PCCFGR | - | R | 执行计数配置寄存器 |
0 | 16 | NPC | - | R | PC映射到SPR空间(下一个PC) |
0 | 17 | SR | - | R/W | 超级监管者寄存器 |
0 | 18 | PPC | - | R/W | PC映射SPR空间(之前PC) |
0 | 20 | EPCSR | R* | R/W | FP控制状态寄存器 |
0 | 32~47 | EPCR0~EPCR15 | - | R/W | 异常PC寄存器 |
0 | 48~63 | EEAR0~EEAR15 | - | R/W | 异常EA寄存器 |
0 | 64~79 | ESR~ESR15 | - | R/W | 异常SR寄存器 |
0 | 1024~1535 | GPR0~GPR511 | - | R/W | GPR映射到SPR空间寄存器 |
2.4 指令集
OpenRISC 1000架构指令集中的指令分为3种:基本指令集、向量/DSP扩展指令和浮点扩展指令,其指令助记符分别为以“l.”、“lv.”和“lf.”开始。
OR1200主要实现了OpenRISC1000架构中基本指令集(ORBIS32/64)中的一部分,而非全部。共有76条指令,本书分为6类,分别是:数据处理类指令(含算术、逻辑、移位、比较、数据传送等)、特殊寄存器访问类指令、转移类指令、异常处理指令、乘法除法类指令和加载存储类指令。
2.4.1 数据处理类指令
数据处理类指令包含算术、逻辑、移位、比较、数据传送等指令。如:加法指令l.add、减法指令l.sub;逻辑指令,如:寄存器相与指令l.and、寄存器相或指令l.or;移位指令,如:带立即数循环右移指令l.rori、逻辑左移指令l.sll;比较指令,如:比较寄存器是否相等指令l.sfeq;数据传送指令,如:l.movhi,表示将16位立即数左移16位,然后存储到目的寄存器。
2.4.2 特殊寄存器访问类指令
特殊寄存器访问类型有两个:特殊寄存器读指令l.mfspr、特殊寄存器写指令l.mtspr。
2.4.3 转移类指令
转移类指令包括条件转移、无条件转移和绝对转移、相对转移等指令。
2.4.4 异常处理类指令
包括系统调用l.sys、自陷l.trap和异常返回l.rfe等指令。
2.4.5 乘法、除法类指令
乘法、除法类指令包括乘法指令、乘累加指令和除法指令等。
2.4.6 加载存储类指令
包括加载指令、存储指令。加载指令,如:加载一个字到寄存器的指令l.lwz;存储指令,如:存储一个字到指定地址的指令l.sw。
2.5 异常模型
在指令的执行过程中由于外部信号、错误或指令本身的一些原因会导致处理器进入异常处理过程。异常处理过程偏离了原程序的执行流程,OR1200将跳转到一个指令的地址,从那里读取指令,开始异常处理,这个指定的地址称为异常处理例程入口地址。
OR1200异常类型及对应处理例程的入口地址,如下:
异常类型 | 处理例程地址 | 引起异常的条件 |
复位(Reset) | 0x100 | 由软件或硬件复位引起 |
总线错误(Bus Error) | 0x200 | 访问非法物理地址 |
数据页失效(Data Page Fault) | 0x300 | 加载存储类指令访问数据页时违反了页保护策略 |
指令页失效(Instruction Page Fault) | 0x400 | 取指操作访问指令页时违反页保护策略 |
计时器中断(Tick Timer) | 0x500 | 计时器满足一定条件时会声明中断 |
对齐异常(Alignment) | 0x600 | 加载存储指令访问未对齐的地址 |
无效指令(Illegal Instruction) | 0x700 | 指令不是OR1200支持的指令 |
外部中断(External Interrupt) | 0x800 | 外部中断发生 |
数据TLB失靶(DTLB Miss) | 0x900 | 在DTLB中没有发现匹配项 |
指令TLB失靶(ITLB Miss) | 0xA00 | 在ITLB中没有发现匹配项 |
溢出(Range) | 0xB00 | 如果SR[OVE]为1,那么算术操作引起的SR[OV]等于1,会导致溢出异常 |
系统调用(System Call) | 0xC00 | 使用指令l.sys |
浮点(Floating Point) | 0xD00 | 浮点运算引起 |
自陷(Trap) | 0xE00 | 使用指令l.trap |
保留(Reserved) | 0xF00-0x1F00 |
3. OR1200模块功能
3.1 OR1200_TOP内部各模块
3.1.1 OR1200_TOP各子模块
3.1.2 OR1200_TOP各子模块功能
模块名 | 全称 | 功能 | 对应verilog文件 |
CPU | 处理器单元 | 执行运算、控制 | or1200_cpu.v |
IMMU | 指令MMU | 对指令地址进行翻译 | or1200_immu_top.v or1200_immu_tlb.v |
DMMU | 数据MMU | 对加载/存储指令中要读写的数据地址进行翻译 | or1200_dmmu_top.v or1200_dmmu_tlb.v |
QMEM | 快速存储器 | 内部的一个小存储器,类似SRAM,可以快速访问,因此适宜放一些经常使用的代码 |
or1200_qmem_top.v |
ICache | 指令缓存 | 缓存处理器取到的指令,以便下一次可以快速访问 | or1200_ic_top.v or1200_ic_fsm.v or1200_ic_ram.v or1200_ic_tag.v |
DCache | 数据缓存 | 缓存处理器读写的数据,以便下一次可以快速访问 | or1200_dc_top.v or1200_dc_fsm.v or1200_dc_ram.v or1200_dc_tag.v |
SB | 存储缓冲区 | CPU与外部存储器之间的速率不一致时,SB起缓冲作用 | or1200_sb.v or1200_sb_fifo.v |
WB_BIU | wishbone总线接口单元 | OR1200可以挂接在wishbone总线,符合wishbone B3版标准 | or1200_wb_biu.v |
PIC | 可编程中断控制器 | OR1200最多支持32个外部中断 | or1200_pic.v |
PM | 电源管理 | OR1200支持多种节电模式 | or1200_pm.v |
TT | 计时器单元 | 用于对时钟计数,当达到一个预设值时会引发中断 | or1200_tt.v |
DU | 调试单元 | 辅助调试系统 | or1200_du.v |
上述模块中IMMU、DMMU、ICache、DCache、QMEM、SB、PIC、PM、DU和TT都是可选项。
3.2 CPU子模块
3.2.1 CPU模块内部各子模块
从图中我们发现CPU中的核心模块是CTRL,实际上通过后面对具体指令处理过程分析可知所有的指令都需要在该模块中译码、分析,然后输出控制信号给其他模块进行计算,流水线也是在该模块中实现的。
3.2.2 CPU模块内部各子模块功能
模块名 | 全称 | 作用 | verilog文件 |
CTRL | 控制单元 | 指令译码,生成其余模块的控制信号 | or1200_ctrl.v |
ALU | 算术逻辑单元 | 完成整数运算、移位、比较、逻辑、数据传送等运算 | or1200_alu.v |
RF | 寄存器文件 | 通用寄存器r0~r31对应该模块,实现对r0~r31的读写 | or1200_rf.v |
MULT_MAC | 乘累加单元 | 完成乘法、除法、乘累加运算 | or1200_mult_mac.v |
SPRS | 特殊寄存器集 | 控制对特殊寄存器的读写,其中也实现部分特殊寄存器,如SR | or1200_sprs.v |
EXCEPT | 异常控制单元 | 对异常情况进行处理,引导CPU跳转到异常处理例程入口地址 | or1200_except.v |
CFGR | 配置寄存器集 | 该模块实现了第0组特殊寄存器中的一些只读寄存器 | or1200_cfgr.v |
FREEZE | CPU暂停单元 | 控制CPU的运行与暂停 | or1200_freeze.v |
GENPC | PC计算单元 | 依据指令执行或异常情况计算PC值 | or1200_genpc.v |
IF | 取指预取单元 | 取到的指令首先送到IF模块,在其中判断是否需要暂存指令,还是直接送往CTRL进入流水线 |
or1200_if.v |
LSU | 加载存储单元 | 加载存储类指令使用本模块读写外部存储器 | or1200_lsu.v |
OPERAND_MUX | 操作数复用单元 | 依据指令从多个输入中选择其中两个,作为操作数a、b,送到各个计算模块 | or1200_operandmuxes.v |
WB_MUX | 回写控制单元 | 用于从多个计算模块中选择一个计算结果作为要写入目的寄存器的数据 |
or1200_wbmux.v |
参考来源:
[1] 《步步惊芯—软核处理器内部设计分析》 雷思磊 电子工业出版社
[2] 《开源软核处理器OpenRisc的SOPC设计》 徐敏、孙恺等 北京航空航天出版社
下一篇:《OpenRISC—OR1200总线标准Wishbone》