L6b:微码处理器架构

微码 ROM 大小计算与单总线数据通路设计,取指-译码-执行的微指令流程举例

这部分的ppt和 L6a singlecycle 中的内容有很大的重合度,相同的地方就不再讲述,主要针对额外的微码设计部分进行讲解。

微码处理器架构

微码处理器的核心架构可以理解为:处理器内部不是直接用硬连线控制逻辑执行一条机器指令,而是用一段固定存在 ROM 里的“微程序”逐步控制数据通路完成这条指令。

img

  1. Main Memory:主存储器 保存的是用户程序,也就是普通机器指令,课件中称为“宏指令”,例如 x86、RISC-V 指令。 比如一条 lwaddjal 都是宏指令。
  2. Datapath:数据通路 真正执行数据操作的部分,包括 PC、寄存器堆、ALU、内存接口等。 它负责完成寄存器读写、ALU计算、访存、更新PC等实际动作。
  3. Microcode ROM:微码ROM 保存固定的微码指令,也就是更底层的控制步骤。 一条宏指令不会一次完成,而是被拆成多条微指令执行。

Microcode ROM 大小计算

ROM 地址位数:μaddress=μPC+opcode+1+1|\mu address| = |\mu PC| + |opcode| + 1 + 1,后面两个“1”是指分支预测结果和存储器是否忙。

ROM 每行数据位数:data=μPC+controlsignals|data| = |\mu PC| + |control signals|

img

单总线Microcoded RISC-V ROM大小

指令获取序列包含3个常用步骤,大约12个指令组,每组约5步(1步调度),一共是 3+12*5 = 63 步,因此μPC\mu PC

需要用6位来表示,操作码(opcode)有5位,大约18个控制信号(control signal)。

因此data=μPC+controlsignals=6+18=24|data| = |\mu PC| + |control signals| = 6 + 18 = 24

μaddress=μPC+opcode+1+1=6+5+2=13|\mu address| = |\mu PC| + |opcode| + 1 + 1 = 6 + 5 + 2 = 13ROM=2μaddress×data=213×24=196608bits=24KiBROM = 2^{|\mu address|} × |data| = 2^{13} × 24 = 196608 bits = 24 KiB

微码RISC-V单总线数据通路

整个数据通路内部主要靠一条总线传数据,所以一次只能完成比较简单的寄存器传输操作,比如下面这三种操作:

text
//写入寄存器传输的微指令:
MA := PC             
B := Reg[rs2]
Reg[rd] := A + B

MA := PC 意思是把 PC 的值送到总线上,再加载到 Memory Address Register,也就是内存地址寄存器 MA 中。

B := Reg[rs2]意思是从寄存器堆中读出 rs2,送到总线上,再加载到 B 寄存器。

Reg[rd] := A + B意思是 ALU 对 A 和 B 做加法,然后把结果写回 rd 寄存器。

img

提醒

在单总线数据通路中,PC被当作 Register RAM 中的特殊寄存器来存放,上图设计中PC寄存器是作为 Register RAM 额外的第32号寄存器

32(PC)输入信号表示存放PC的寄存器编号32,这个信号一般会固定为100000,表示选择第32号寄存器,可以进行后续的读/写操作

纯ROM的内容

img

案例解释

对于fetch0: MA, A := PC -> fetch1微指令的数据通路解释

该指令表示把 PC 的值同时送入 MA 和 A,然后进入 fetch1。

  1. RegSel 选择 PC

图中 Register RAM 里面既有普通寄存器,也有 PC。PC 通常被看成一个特殊寄存器,比如地址编号为 32。

所以控制信号设置为:RegSel = PC,表示从寄存器堆中选中 PC。

  1. RegEn 打开寄存器输出

让 PC 的值从 Register RAM 输出到单总线:Bus := PC

  1. MALd = 1

允许 Memory Address Register (MA) 从总线加载 PC:MA := PC。这一步是为了告诉主存“我要访问 PC 指向的地址”。

  1. ALd = 1

ALU 前面的 A 寄存器也从总线加载 PC 的值:A := PC

这一步的目的:先把旧 PC 保存到 ALU 的 A 输入端,后面用来计算PC + 4PC+offset

注意,A := PCMA:= PC这两个动作可以在同一个周期完成,因为它们都是从总线上读PC,不冲突。

对于fetch1: Busy=1 -> fetch1的理解

如果 Main Memory 还没有准备好数据,即输入busy=1,就不要进入下一步,继续等待。

对于fetch0:IR := Mem -> fetch2的理解

Main Memory 准备好数据,先Bus := Mem[PC],然后IR := Bus,把PC地址的指令传给了指令寄存器IR,然后进入fetch2。

后续微指令

后续就根据opcode等指令格式和操作要求,依次完成相应寄存器操作,比如图中给出的ADD指令的取指后续微指令执行流程:fetch2->ALU0->ALU1->ALU2

微码程序草图

微码就像处理器内部执行机器指令的小程序,每条机器指令对应一段微码流程。

img

img

公共的取指令流程

MA, A := PC

PC := A + 4

wait for memory

IR := Mem

dispatch on opcode

含义:先用 PC 作为地址去主存取指令,同时把 PC 保存到 A 中。然后 PC 加 4,准备指向下一条指令。等内存返回指令后,把指令放入 IR,也就是指令寄存器。最后根据 opcode 分发到不同指令的微码入口。

ALU 类微指令

A := Reg[rs1]

B := Reg[rs2]

Reg[rd] := ALUOp(A,B)

goto instruction fetch

上述是普通 R 型指令的流程,实现一些运算操作,例如 addsubandor

ALUI 类微指令

A := Reg[rs1]

B := ImmI

Reg[rd] := ALUOp(A,B)

goto instruction fetch

ALUI 类指令和 ALU 类指令类似,只是第二个操作数不是 rs2,而是立即数。

LW 微指令

A := Reg[rs1]

B := ImmI

MA := A + B

wait for memory

Reg[rd] := Mem

goto instruction fetch

含义:先读出基地址寄存器 rs1,再取立即数偏移 ImmI,然后用 ALU 计算访存地址

JAL 指令

A := PC 这一条是我添加的,不然A := A - 4有点莫名其妙,大家也可以查一下。

Reg[rd] := A

A := A - 4

B := ImmJ

PC := A + B

goto instruction fetch

含义:在取指阶段,PC 已经被加了 4,所以 A 里面保存的是返回地址,也就是 PC + 4

因此,Reg[rd] := A,就是把返回地址写入 rd。然后A := A - 4是恢复原来的 PC。

最后PC := A + B,也就是PC = 原PC + JAL立即数

Branch 指令

A := Reg[rs1]

B := Reg[rs2]

if (!ALUOp(A,B)) goto instruction fetch

A := PC

A := A - 4

B := ImmB

PC := A + B

goto instruction fetch

含义:先比较两个寄存器。如果分支条件不成立,就直接去取下一条指令。如果条件成立,就计算分支目标地址。

这里同样要 A := A - 4,因为 PC 已经在取指阶段加过 4,所以要先恢复原 PC,再加上分支偏移量。

减少控制代码存储空间

减少ROM高度(地址位宽):使用外部逻辑来合并输入信号;通过分组操作码来减少状态数量

减少ROM宽度(数据位宽):限制μPC编码(下一步,调度,等待内存,…);编码控制信号(垂直微编码、纳型编码)

单总线RISC-V微码引擎

单总线控制逻辑设计

img

µPC跳跃类型

next,下一步:表示执行下一条微指令,也就是µPC := µPC + 1

spin,自旋:表示等待内存。如果内存还忙,就停在当前微指令;如果内存准备好,再继续。

fetch,读取:表示跳回取指令流程,开始下一条宏指令。

dispatch,指令分发:表示根据 opcode 跳转到对应指令组的入口,例如 ALU、LW、Branch。

ftrue / ffalse:表示根据条件判断结果跳转,主要用于分支指令。

已编码的ROM内容

与前面纯ROM的内容相比,下面已编码的ROM内容用更紧凑的编码方式存储微码,减少 ROM 的浪费。

此时的ROM的Address只剩下µPC,Data中包括Control LinesNext µPC

img

其中 Branch2ffalse 表示:如果分支条件为假,就直接回到取指阶段;如果条件为真,就继续执行后面的分支目标地址计算。

复杂指令的实现

下面是以存储器-存储器加法为例,演示微码执行流程。

先读第一个内存操作数到 A,再读第二个内存操作数到 B,然后 ALU 相加,最后把结果写回内存。

img

通过上述流程可以显示出微码的一个重要优势:实现复杂指令很方便。通常不需要修改数据通路,只需要增加一段微码即可实现

水平vs垂直µ码

水平微码

水平微码的特点是:

  • 微指令很
  • 每条微指令可以同时控制多个硬件动作
  • 执行步骤,但是编码稀疏,占用 ROM 位数多

例如一条水平微指令可能同时控制寄存器选择、ALU操作、写回、地址加载等多个信号。

优点是速度较快,因为一步能做很多事。缺点是每条微指令很长,ROM 宽度大。

垂直微码

垂直微码的特点是:

  • 微指令较窄
  • 控制信号经过编码
  • 通常一条微指令只做一个较简单的数据通路操作
  • 执行步骤更多,但是更节省 ROM 空间

优点是 ROM 更小。缺点是执行同一条宏指令可能需要更多微步骤。

纳码

纳码可以理解为一种两级微码结构

普通微码中有很多重复的控制信号模式,比如:ALU0: A ← Reg[rs1]ALUI0: A ← Reg[rs1],虽然属于不同指令,但控制信号模式可能完全一样。如果每次都在微码 ROM 里存完整控制信号,就会浪费空间。

纳码工作构成

µcode ROM 负责流程控制和给出 nanoaddress;nanoinstruction ROM 负责输出真正的控制信号。

img

微码 ROM:决定下一步去哪、使用哪种控制模式 纳指令 ROM:保存具体控制信号模板

这样重复的控制信号模式只需要在纳指令 ROM 中存一份,不用在每条微码里重复存。

案例

Motorola 68000 的例子:

17位 µcode,其中可以包含10位µ跳转或者9位纳指令指针 纳指令宽 68位,解码后可产生 196个控制信号

可写控制存储 | Writable Control Store

六七十年代半导体 ROM/RAM 变得可用,控制存储不一定非要用老式只读结构,于是出现了基于RAM的可写控制存储(WCS) (应用案例:B1700, QMachine, Intel i432,…)

可写控制存储(WCS)可以理解为把原来存在 ROM 里的微码,改成存在高速 RAM 里。这样微码不再是出厂后完全固定的,而是可以被加载、修改、更新。

img

其他剩余部分和L6a singlecycle章节的内容完全重合,不再赘述。

L6a:单周期处理器设计
L7:流水线处理器

评论区