|
将出一个系列小脚丫的文章,会在小脚丫上运行Mico8微处理器器软核,并添加一些外设;后续会在其上移植Opencore8051。敬请期待~
1. LatticeMico8介绍
Mico8是由Lattice开发等为其FPGA和CPLD产品提供的8位微处理器软核,可用于通信,消费电子,计算机,医疗、工业和自动化等市场。其最小配置少于250个LUT,并仍能保大部分特性。
主要特性介绍:
- 8位数据宽度/18位指令宽度
- 可配置指令存储(PROM)
- 可通过WISHBONE接口连接片内或外部存储
- 能够容纳256,512……4K指令
- Scratchpad存储和外设空间(互相独立)
- 可通过WISHBONE接口连接片内或外部存储
- 通过使用页寻址支持可支持最多4GB
- 支持最小2个时钟周期的指令执行周期
- 可配置为16/32个通用寄存器
- 可配置函数调用栈(Call stack)大小
2. Mico8软核分析
2.1 寄存器设置
Mico8的指令宽度是18位,使得它可操作最多达32个达通用寄存器;从其寻址模式及寄存器设置来看,更接近ARM等RISC架构。 其page寄存器的设置比较有特点,R13、R14、R15可用作页指针寄存器(Page-pointer,PP),从而使最大寻址范围达4GB;当然,很多情况下并不需要这么大空间,mico8的存储模式支持小、中、大模式,分别支持256,65536以及4GB四种地址范围模式。 Mico8仅有3个控制和状态寄存器(CSR):IP,IM,IE。都是和中断相关的,分别是中断挂起寄存器,中断掩码寄存器和全局中断使能寄存器。注意,Mico8仅支持最多8个外部中断——容易理解,位宽决定的。
竟然没有暴露PC,运算状态标志位如(溢出,进位,ZERO等)……
2.2 存储架构
下面我们看下其存储架构,Mico8可支持3种不同且相互独立的存储区域:外设,PROM以及Scratchpad。由于它们是相互独立的,其地址范围可以相互重叠。而且每种存储都有自己独立的IO接口和指令集支持——这点很粗暴。
2.2.1 PROM空间
PROM空间:存储程序代码。该空间通过一个高速总线连接到取指引擎(instruction fetch engine),只需要1个时钟周期即可完成取指。当通过8位宽度WISHBONE总线连接到片外存储时候,取指引擎会通过三次读取操作获取执行码(3*8 = 24 > 8,有些浪费~),此时的延迟取决于WISHBONE总线延迟和外部存储的延迟。显然,Mico8的指令设计更适合于片内ROM。 片外PROM的设置另一个好处是可以直接通过Mico8指令进行写入操作(只要执行序列符合ROM写入规则即可)。
比如,我们只要写好SPI Flash的驱动连接取指引擎,我们就可以扩大PROM空间,并可以直接对其编程——实现在线升级等。
Scratchpad空间
Scratchpad空间被设计用于程序读写以及用户自定义数据,实际上就是RAM了。其空间排布从低地址到高地依次是:4字节保留空间(中断专用),程序数据,用户数据。
实际看来,Scratchpad的实现和PROM一样,支持的特性也一样;只不过是通过规范告诉我们一个是用于RAM一个用于ROM,并分别通过不同的指令进行访问——便于编译器的实现,确实很简单、很粗暴。
2.2.2外设(I/O)空间
除了其空间必须是在core的外部,其余设计和PROM、Scratchpad一样。
2.2.3 存储访问模型
Mico8的指令可直接访问256个存储位置,因为其通用寄存器都是8位宽度;当超过256时,需要通过分页来进行大范围访问: file:///Users/rock/Documents/md_docs/mem_mode.png
2.3 中断架构
Mico8支持最多8个可屏蔽中断,其中断至支持电平触发,低电平有效的中断模式(仍然突出简单二字)。中断寄存器及状态支持如寄存器设置一节所述。 当中断发生时的行为:
- 将要执行的下一条指令会被放入调用栈(Call stack);
- 运算标志(进位和Zero)也被放入调用栈;
- Mico8从中断向量开始执行(地址0);
- 执行完毕后,指令iret会弹出调用栈并继续执行
Scratchpad的前4个字节供中断使用。只有一个中断向量!用户需要去查询IP寄存器来得到究竟是哪个中断发生(粗暴!)显然它也不支持嵌套中断。
2.4 调用栈(call stack)
中断一节我们提到调用栈,Mico8实现了一个硬件调用栈用于处理过程调用(函数调用,对应于指令call)。栈的深度决定了函数嵌套调用的深度,Mico8支持8,16,32三种调用深度(简陋~)
3.指令集分析及编程模型
了解了处理器架构,就基本上可以知道它支持哪些指令了。不过我们还是分析一下,加深对其架构的理解。
3.1 指令格式
###### Register-Register Format ###### 17 13 12 8 7 3 210 +--------+-----------+------------+---+ | Opcode | Rd | Rb |000|+--------+-----------+------------+---+ ###### Register-Immediate Format ###### 17 13 12 8 7 0 +--------+-----------+----------------+ | Opcode | Rd | Constant | +--------+-----------+----------------+###### Immediate Format ###### 17 12 11 0 +---------+---------------------------+ | Opcode | Signed Immediate | +---------+---------------------------+注意到立即数模式种,opcode是6bit,且其操作数是有符号数。
3.2 指令分类
指令:
- 运算:ADD, ADDC, ADDI, ADDIC; CMP, CMPI; SUB, SUBC, SUBI, SUBIC;
- 逻辑:AND, ANDI, OR, ORI,ROL, ROLC, ROR, RORC, XOR, XORI
- 标志位操作:CLRC, CLRI, CLRZ, SETC, SETI, SETZ, TEST, TESTI
- 跳转: B, BC, BNC, BZ
- 调用:CALL, CALLC, CALLNC, CALLNZ,CALLZ, IRET(回复标识位,中断用), RET
- 外设操作:EXPORT, EXPORTI, IMPORT, IMPORTI
- Scratchpad操作:LSP, LSPI, SSP, SSPI
- 寄存器操作:RCSR, WCSR, MOV, MOVI
- 其它: NOP
几种模式:
- 后缀C/I:分别时带进位操作,立即数操作,以及组合。
- 存储的读取时标准的load-store模式,(以及大量设置通用寄存器),明显RISC架构的味道。
注意到没有对PROM区域的操作?实际上指令完全是被动执行,不能通过对PC赋值的形式实现程序流控制。简单,够用~
3.3 编程模型
数据表示:char-8bit,short-16bit,int-16bit, long-32bit, pointer-取决于存储模式设置,浮点-32位。
Mico8同样有类似于ARM的ATPCS规则,规定了函数调用时输入,输出参数传递的规则。
栈帧: 程序运行时,每个函数调用都会有其运行时的栈帧。其增长方向向下,SP永远指向最后一个
Mico8只能有一个中断处理函数,且必须命名为__IRQ:
<div><pre>__attribute ((interrupt)) __IRQ (void) { /* user interrupt code, should check IP to get which interrupt happened. */}关于Scratchpad和外设区域: Mico8编译器默认所有的存储器读取都编译成scratchpad区域的存取(即指令LSP, LSPI, SSP, SSPI),如果用户要操作外设区域的话,用户需要显式的使用该指令。 显然,用户要么用内联汇编,要么直接用汇编(或者用其编译器指定的一些内置函数,如void __builtin_export (char value, size_t address))
其实本部分时和编译器相关,而和硬件无关的;只不过是告诉用户如果使用汇编和C交互时候,需要遵循的编译器规则。
3. 在小脚丫上运行Mico8软核
[未完待续]
|
|