
学计算机组成原理的人大多有同一种体验前面学数据表示、运算器、存储系统都还觉得能跟上一到控制器这一章就开始发懵。尤其是“微程序设计”这几个字出现之后微指令、微操作、控制存储器、微地址、微程序入口……一堆“微”字辈概念砸过来整个人仿佛从宏观世界瞬间掉进了微观世界。这篇笔记就是我啃这块“硬骨头”时的完整整理把概念之间的逻辑关系、容易混淆的考点、常见计算题套路一起梳理清楚希望能帮你少走弯路。这篇内容适合正在学计算机组成原理的本科生、准备考研的读者也适合想重新理解CPU控制器的自学者。我不会只堆概念会把“为什么这样设计”也讲透因为考试和实际理解卡住的往往就是那个“为什么”。1. 为什么微程序设计是计组里的“硬骨头”——先搞懂控制器到底在干什么1.1 指令周期、机器周期、时钟周期和微操作这四个概念的关系这一章之所以难是因为概念分层太多。很多人一上来就背微指令格式但连控制器到底要干什么都没搞清楚。CPU执行一条指令不是一蹴而就的。机器指令只是程序员看到的样子硬件要真正完成它得把它拆成一连串最基本的动作。这些动作就是“微操作”。一条加法指令底层至少要经历“取指令→译码→取操作数→执行→写回结果”几个阶段。这里要先理顺时序体系指令周期执行一条指令所需的总时间。机器周期CPU周期把一个指令周期划分为若干段通常以访问一次存储器的时间为基准。时钟周期机器周期再细化成最基本的时钟节拍。微操作在一个时钟周期内各功能部件完成的原子级别动作。打个比方指令周期像是“做一道菜”的总时间机器周期像是“洗菜”“切菜”“炒菜”这样的阶段时钟周期是每个具体动作的一拍微操作就是“手起刀落”那一下。控制器这一章的职责就是决定每一拍让哪些部件做什么动作、按什么顺序做。1.2 微程序设计的本质把“连线”变成“存储的程序”控制器有两种经典的实现路线硬布线控制器和微程序控制器。硬布线控制器的思路是用逻辑门电路把“当前状态→下一状态→控制信号”的关系直接搭出来相当于用硬件连线固化了所有控制逻辑。微程序设计则换了一种思路把一条机器指令的执行过程写成一段“小程序”这段程序由一系列更底层的“微指令”组成存放在一个专门的只读存储器中这个存储器就是控制存储器CM。执行机器指令的时候控制器按顺序读出这些微指令每条微指令各个字段的编码经过译码后发出对应的控制信号。换句话说硬布线是“用电路决定行为”微程序是“用存储的程序决定行为”。为什么微程序设计思想能站住脚因为它把控制器的设计从“画逻辑电路图”变成了“编写微指令序列”设计周期大大缩短修改功能只需要改控制存储器里的内容不需要重新设计电路。CISC时代指令复杂、数量多微程序几乎是必然选择。学这一章的人最容易犯的一个错误是分不清“程序”和“微程序”、“指令”和“微指令”。记住一句话程序由机器指令组成运行在主存中微程序由微指令组成固化在控制存储器中。一条机器指令对应一段微程序一段微程序由若干条微指令组成。2. 微指令的三种编码方式——直接控制、字段直接编码、字段间接编码怎么选2.1 直接控制编码最直观但代价最高先看最简单的直接控制编码。微指令的操作控制字段中每个二进制位直接对应一个微操作控制信号。某一位为1就发出对应的控制信号为0就不发。这种方式的优点是简单、速度快不需要额外的译码电路信号从微指令寄存器输出后可以直接接到各功能部件。缺点也极其明显如果CPU需要100个微操作控制信号操作控制字段就得有100位微指令字长非常长控制存储器的容量也会被撑大。假设控制存储器有512个存储单元每条微指令100位操作控制字段加上8位下地址字段微指令字长就是108位控制存储器容量就是512×108位。这个数字作为教科书例题没问题但实际工程中成本偏高。直接控制编码通常不会单独出现在实际产品中但它作为理解起点非常合适因为你能一眼看清楚“微指令字长”这个概念是怎么来的。2.2 字段直接编码在速度和容量之间找平衡为了解决直接控制编码字长过长的痛点出现了字段直接编码。思路是把若干“互斥”的微操作放在同一组组内用二进制编码表示具体执行哪一个操作然后通过译码器把编码还原成控制信号。这里有个关键概念必须搞清楚什么是互斥的微操作互斥就是不能在同一时刻发生的操作。比如ALU的加法操作和减法操作互斥因为一个时刻ALU只能做一种运算总线向寄存器A写数据和向寄存器B写数据的操作也可能互斥取决于数据通路结构。而相容的微操作则可以在同一拍并行执行比如“PC内容送地址寄存器”和“程序计数器加1”在很多数据通路设计中可以同时完成。分组的原则很简单把互斥的微操作放在同一组里编码。假设一组有n个互斥微操作留一个编码表示“本组不发出任何操作”那么这一组需要 m 位编码满足 2^m ≥ n1取最小值。为什么是 n1 而不是 n因为必须留出一种状态表示“本组无操作”否则译码器输出的每个状态都会对应某个控制信号你就没法表达“这一拍不需要这组操作”的情况。举个例子某数据通路中有一组5个相斥的微操作那么需要的位数是满足2^m≥6的m即m3。很多人会算成2^m≥5取m3结论碰巧一致但思路是错的。如果这组有7个相斥微操作8个状态刚好够用3位可以如果变成8个相斥微操作需要满足2^m≥9就得4位了。这种边界情况考试特别喜欢出。操作控制字段被分成若干组之后每组独立编码各组之间是并行译码的。这样一条微指令仍然可以同时发出多组控制信号保留了并行控制能力同时字长比直接控制缩短了很多。2.3 字段间接编码进一步压缩但引入了依赖字段间接编码是在字段直接编码基础上再进一步。它的特点是一个字段的编码含义要依赖另一个字段的编码来解释。举个例子A字段的某些取值可以决定B字段是“操作类型字段”还是“源操作数选择字段”。这样做的收益是字长更短代价是译码逻辑更复杂、控制信号产生的延迟更大因为要先等另一个字段的译码结果。这个方案在考研题里一般不会深入考但理解它的思路有意思它本质上是用“上下文”来复用编码空间跟操作系统的指令编码优化思路很像。三种编码方式的取舍可以直接看这个对比编码方式微指令字长译码速度硬件复杂度灵活性直接控制最长最快无需译码低低字段直接编码中等中等一级译码中中字段间接编码最短较慢二级译码高高实际设计中字段直接编码是主流因为它兼顾了字长、速度和设计复杂度。3. 微地址的形成逻辑——琢磨透下地址字段就掌握了一半3.1 微指令格式的两条路线水平型和垂直型微指令格式大体分成两派水平型和垂直型。这个划分依据主要是微指令中并行控制能力的强弱。水平型微指令的特点是操作控制字段的每一个二进制位或每一个字段直接控制数据通路中的一个或一组操作并行控制能力强。一条水平型微指令可以同时指定多个微操作比如同时完成“ALU加法”“结果送寄存器”“程序计数器加1”三个动作。水平型微指令字长通常很长几十位甚至上百位但执行速度快控制信号的利用率高。垂直型微指令则更像机器指令。它有类似操作码和地址码的结构每条微指令一般只定义一到两个微操作需要经过译码后产生控制信号字长短并行度低程序的条数会比水平型多执行速度也慢一些。用交通工具类比水平型像一辆满载货物的卡车一趟能拉很多货效率高但车身大垂直型像小轿车灵活轻便但一趟拉不了多少东西。考试里比较两者时容易漏掉“执行速度”这个维度。水平型因为并行度高同样功能需要的微指令条数更少总执行时间更短垂直型虽然每条指令简单但条数多总时间更长。3.2 下一条微指令的地址怎么确定三种典型方式微程序是按顺序执行的但也会有跳转所以必须有一套机制决定下一条要执行的微指令在控制存储器中的地址。主要有三种方式。第一种是计数器方式。硬件里设置一个微地址寄存器μPC执行完一条微指令后自动加1指向下一条微指令。这种方式类似普通程序中的PC顺序执行效率很高。遇到跳转时由跳转逻辑把目标地址装入μPC。第二种是下地址字段方式也叫断定方式。每条微指令顺序控制字段里自带一个“下地址字段”直接指明下一条微指令的地址。这种方式在执行顺序路径时可以直接跳转不需要让μPC逐个递增灵活性更强。代价是每条微指令都要多占一些位来存放下地址。第三种是多路转移方式。这是下地址字段的扩展根据测试条件比如运算结果符号、进位标志、中断请求等从多个候选地址中选一个作为下一条微指令地址。条件成立跳到分支A条件不成立跳到分支B。微程序里实现if-else逻辑就得靠它。3.3 取指微程序的入口地址怎么来微程序控制器执行一条机器指令时不是从上电复位后就随便跑而是要找到当前机器指令对应的微程序入口。通常设计是这样的复位后微地址寄存器先被置为取指微程序的入口地址取指部分对所有机器指令是公共的执行完取指微程序后指令已经被取到指令寄存器IR中。此时指令的操作码送到微地址形成电路通过一个地址映射机制可以用PLA、ROM或者译码器实现转换成该指令对应的微程序入口地址送到微地址寄存器然后开始执行该指令的执行阶段微程序。执行完后通常又回到取指微程序的入口开始取下一条指令。这个过程实际上包含了一个“间接寻址”的思路机器指令的操作码不直接是控制存储器的地址而是需要经过映射。如果操作码很规整映射电路就是简单的译码器如果设计比较复杂就得用一张表来查。理解了这个过程《计算机组成原理》里的“微程序入口地址形成”题目就没什么难度了。常见的陷阱是有些同学会混淆“指令操作码”和“微指令操作控制字段”。前者是机器指令的一部分告诉CPU执行什么操作后者是微指令的一部分控制具体微操作信号。4. 微程序控制器与硬布线控制器——两种路线的取舍与RISC/CISC的关联4.1 两种控制器的结构对比学这一章时很多人会觉得微程序控制器是“先进”的硬布线是“落后”的这是误解。从结构上看两者的核心差异在于控制信号的产生方式。硬布线控制器没有控制存储器它的控制逻辑由组合逻辑电路实现输入是指令操作码、状态标志、时序信号输出就是各部件控制信号。一旦设计完成想要修改控制逻辑就要重新设计电路板。微程序控制器的核心部件是控制存储器、微指令寄存器、微地址寄存器和地址译码电路。设计人员通过修改控制存储器内容来改变控制逻辑相当于用“软件”的方式实现“硬件”的控制功能。对比维度硬布线控制器微程序控制器控制信号产生方式组合逻辑电路微指令译码设计/修改灵活性差改逻辑需改电路好改控制存储器内容即可执行速度快慢需要取微指令和译码设计周期长适合指令系统固定短适合指令复杂多变典型应用RISC处理器、流水线处理器CISC处理器4.2 为什么RISC又绕回了硬布线早期CISC处理器因为指令系统复杂用微程序控制器可以大大降低设计难度。每一条指令都有一段对应的微程序增加指令只增加微程序不需要改电路。但微程序控制有个绕不开的毛病每条机器指令执行前都要先到控制存储器里去读微指令相当于“解释执行”了一层速度比直接用硬件连线慢一拍。对于追求极致性能的处理器来说这一拍不能接受。RISC处理器选择的路线是精简指令系统指令格式规整、种类少、寻址方式简单这样一来控制器逻辑就不那么复杂硬布线设计可行而且速度快。这也是为什么现代高性能处理器普遍都是流水线硬布线控制设计甚至很多CISC处理器内部也会先把复杂指令翻译成类RISC微操作再用硬布线执行。学习这一节时可以用一个现实中的类比来帮助理解硬布线像是量身定制的专用工具效率高但是改了需求就得重新做工具微程序像是用操作手册指导通用设备工作灵活性高但每执行一步都要先读一下手册速度上吃亏。5. 一条加法指令的微程序拆解——把抽象的流程落到具体微指令上5.1 指令格式与取指阶段的微操作拆分光讲概念容易飘我把一个简化模型机里的ADD指令执行过程完整拆一遍你就明白微程序到底是怎么设计出来的。假设这个模型机有一条双操作数指令ADD R1, R2含义是将寄存器R1和R2的内容相加结果存回R1。简化数据通路如下程序计数器PC地址寄存器MAR数据寄存器MDR指令寄存器IR通用寄存器组R0~R3ALU累加器或者专用暂存器。取指阶段要完成三件事把PC中的指令地址送到MAR从主存读出指令送到MDR再转入IRPC加1为取下一条指令做准备。用微操作序列表示取指阶段可以拆成以下几条微指令微指令1PC → MAR即把PC内容经总线送入MAR同时可让PC加1。如果硬件允许PC输出到总线的同时自增那么这两个微操作是相容的可以放在同一条微指令里。微指令2发出读主存命令M[MAR] → MDR等待存储器完成读操作。微指令3MDR → IR把读出的指令送入指令寄存器。这三条微指令构成取指微程序。注意每个阶段用了几拍很多题目会问“取指周期包含几个机器周期/时钟周期”答案取决于数据通路设计。5.2 执行阶段从R1R2到结果写回执行阶段同样需要拆成微操作序列。ADD R1, R2至少需要把R1的值送ALU的A输入端把R2的值送ALU的B输入端ALU执行加法把ALU输出写回R1。对应微指令可以这样设计微指令1R1 → ALU_AR2 → ALU_B。如果数据通路允许这两个操作可以并行执行相容。微指令2ALU_ADD并让结果送入暂存器或直接进入数据总线。这条微指令里还可以包含其他相容操作比如为下一步写回做准备。微指令3ALU_OUT → R1把结果写到目标寄存器。可以看到设计微程序的核心就是判断哪些微操作可以合并到同一条微指令。合并得越激进微指令条数越少但硬件要支持这些操作的并行执行合并得保守硬件简单了但微程序变长速度变慢。5.3 相容性判断是设计微程序的基本功判断两个微操作是相容还是相斥不能靠背要看数据通路图。两个微操作如果同时作用到同一个功能部件且目标冲突就是相斥的如果操作对象不同、资源不冲突就是相容的。举几个例子“R1送ALU输入端”和“R2送ALU另一个输入端”相容因为两个输入端口互不冲突。“ALU执行加法”和“ALU执行减法”相斥因为ALU一个时刻只能做一种运算。“PC送MAR”和“PC加1”在大多数设计中相容因为一个走总线一个在PC内部完成。“主存写”和“寄存器组写”通常相容因为它们写入的对象不同。考试时遇到这类题先画出数据通路再逐对判断资源冲突。不要凭感觉要按“部件是否冲突”这个标准来推。6. 期末和考研常见的坑——微程序设计章节的典型丢分点6.1 微指令字长的计算陷阱微指令字长的计算是高频考点但错误率极高。一个典型的题目某机采用微程序控制方式操作控制字段采用字段直接编码。已知有8个互斥的微操作分在同一组那么这一组至少需要多少位错误答案是3位因为很多人直接取⌈log2 8⌉3。正确答案是4位因为8个互斥微操作加上“不操作”这一状态共需要9个状态满足2^m≥9的最小m是4。这类题的关键就一句话算编码位数永远要加1个“无操作状态”。如果题目用了“某组有n个互斥的微命令”这种表述默认要表示不操作的状态除非题目明确说不需要。另一种陷阱是题目给出多个互斥组各组微命令的数量不同有的组还需要留出不操作编码。计算总字长时要把每组位数分别算出来再加总不能把各组数量直接相加取对数。6.2 控制存储器容量怎么算控制存储器容量等于微指令总条数乘以微指令字长。微指令总条数怎么确定一个较笨但稳妥的方法是看微程序控制器的微程序包含多少条微指令。题目通常会以表格或流程图的形式给出取指微程序、各指令执行微程序的条数把所有条数加起来就是控制存储器的总单元数假设微程序连续存放。微指令字长则是操作控制字段位数加顺序控制字段位数。顺序控制字段里如果包含下地址字段还要看地址字段本身需要多少位这取决于控制存储器的总单元数。比如总单元数是256下地址字段至少需要8位。这里容易出现循环计算下地址字段的位数决定了控制存储器容量而容量又决定了下地址字段位数。解决办法是先根据操作控制字段和微程序条数估算再看地址范围是否够用。举一个完整的小例子某微程序控制器共有微指令40条操作控制字段采用字段直接编码分4组每组互斥微操作数分别为5、7、8、3。计算每组需要的位数第一组516个状态需3位。第二组718个状态需3位。第三组819个状态需4位。第四组314个状态需2位。操作控制字段合计334212位。顺序控制字段包括下地址字段至少需要⌈log2 40⌉6位如果还要表示测试条件和分支信息再增加位。因此微指令字长为12618位控制存储器容量为40×18位。6.3 我的几个学习建议学完这一章我自己的感受是别急着背结论先理解微程序控制器的工作流程能画出从“取指”到“执行”的状态流转图概念就清楚了一大半。第一个建议是把“指令”和“微指令”这两个词用英文区分开指令是instruction微指令是microinstruction。做题时看到“指令”和“微指令”混在一起先停下来把对象搞清楚很多错误其实是审题问题。第二个建议是遇到微观操作的相容性判断千万用数据通路图推不要靠生活经验。考试时如果条件不足默认按教材常见的单总线数据通路模型来判断。第三个建议是把微程序控制器和硬布线控制器的对比当作“体系结构”层面的问题来看不要只当两个知识点背。理解了CISC和RISC的取舍你才能理解为什么现代处理器内部采用了混合方式。这也是为什么很多教材把微程序设计和指令系统设计放在同一章的原因。我在实际复习时发现把这一章和前面的“指令系统”“数据通路”串起来效果特别好。先自己画一个简单数据通路再为ADD R1, R2设计微程序最后算字长和容量一套流程下来考试涉及的主要题型基本都覆盖了。你遇到的具体困惑大概率也出不了这几个范围。这篇笔记写到最后我最想强调的还是那个习惯每个公式和每个结论都回去找到它在数据通路上的实际含义比死记硬背可靠得多。