├── .github └── ISSUE_TEMPLATE │ └── ---------.md ├── .gitignore ├── 1-单周期、多周期和流水线处理器.md ├── 2-浅析计组课设中制作的CPU.md ├── 3-什么是五级流水、数据前推、流水线暂停.md ├── 4-一个静态五级流水MIPS的最基本架构.md ├── 5-第一条指令 ORI 的实现.md ├── 6-流水线冲突.md ├── 7-数据相关的解决办法介绍.md ├── 8-ORI 的数据相关.md ├── 9-1-ORI 指令数据相关的解决办法 1 - 数据前推.md ├── 9-2-ORI 指令数据相关的解决办法 2 - 流水线暂停.md ├── LICENSE ├── README.md ├── chapter09_指令流水线.ppt └── pic ├── 1 └── 1.jpg ├── 2 └── 1.jpg ├── 3 └── 1.png ├── 4 └── 1.jpg ├── 5 ├── 1.jpg ├── 10.jpg ├── 11.jpg ├── 12.jpg ├── 13.jpg ├── 14.jpg ├── 15.jpg ├── 16.jpg ├── 17.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 6.jpg ├── 7.jpg ├── 8.jpg └── 9.jpg ├── 6 └── 1.jpg ├── 7 ├── 1.jpg └── 2.jpg ├── 8 └── 1.jpg └── 9 ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 6.jpg └── 7.jpg /.github/ISSUE_TEMPLATE/---------.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 内容更改或新增请求 3 | about: 发现了问题还是有新点子?提出来吧! 4 | title: "[Features]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **你的新点子是否关乎到一个文档中存在的问题呢?请描述一下吧!** 11 | 请简明扼要地描述你的想法,比如:“在看到xxx的时候,我觉得xxx不妥,因为......”。 12 | 13 | **讲一讲你期望的结果** 14 | 请简明扼要地描述你期望的结果,比如:“对于刚刚说到的问题,可以这样描述......,这样会让同学们更......”。 15 | 16 | **附件** 17 | 如果有任何截图或者演示能让大家更容易地理解你的想法的话,还请发上来哦! 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | *.zip -------------------------------------------------------------------------------- /1-单周期、多周期和流水线处理器.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 1.单周期、多周期和流水线处理器 6 | 7 | 首先,我们大家都知道“时钟”(CLK)这个概念,在数字电路中,时钟是整个电路最重要的信号,整个系统内大部分器件的动作都是在时钟的跳变沿上进行 8 | 9 | ![clk](./pic/1/1.jpg) 10 | 11 | ## 为什么CPU需要时钟才能工作? 12 | 13 | ### 最简单的例子 14 | 15 | 想象一个大型的交响乐乐团: 16 | 17 | - 每个乐手都是一个外设; 18 | 19 | - 乐团的指挥家就是一个CPU; 20 | 21 | 于是我们知道,外设根据CPU的指挥进行工作,就如乐手根据指挥家的手势进行演奏一样。 22 | 23 | 但是现在出现了问题:指挥家让右手边的乐团演奏这一段音乐,虽然乐手们大家都知道整个曲子的谱调是什么样,知道最后演奏出来的音乐听起来是什么样,但是对于每一位乐手来说,他都会质疑:我应该演奏多快?我应该怎么和其他乐手合作演奏出来这一首宏伟的乐曲,而不是最终演奏出了杂乱无章的噪声呢? 24 | 25 | 于是,音乐的节拍解决了这个问题。指挥家根据节拍来即兴指挥乐团,而乐手们又跟着同一个节拍演奏自己不同的乐谱,从而构成了这样一曲有序动听的交响乐。 26 | 27 | 就和每张乐谱都有自己的节拍一样,CPU以及外设也都有自己的节拍:CLK(时钟信号),它们统一在同一个时钟信号下的上升沿或者下降沿进行自己的工作,这样才不会因为每个器件速度的不同而打破了“和谐”。 28 | 29 | ### 详细的解释 30 | 31 | 1. 大家一起协调工作 32 | 33 | 无固定频率的CPU和周边工作单元协同工作时,因为大家步调不一致,沟通起来效率会打折扣(通才采用应答的模式来进行速度匹配,类似于TCP)。 34 | 35 | 有的器件它的工作速度可能非常快(比如说一个单纯的PC,最简单的情况下它只会对上一个上升沿或下降沿到来时自己的值+4),同时,有的器件它工作的速度可能会非常慢(比如说FPU在计算一个极其复杂的浮点数除法时,再如DIV模块进行32位除法的时候一般需要32个周期),当然所有器件都不能想当然地进行工作,所以需要一个时钟信号让大家同步起来,一起协调地完成每个工作; 36 | 37 | 2. “同步地”工作 38 | 39 | 例如CPU从寄存器中读取一个32位的数据,此时要求32位数据同时读入而不能有先后顺序,于是就需要有同一个时钟信号,让部件在同一个上升沿(或下降沿)去读取出这样一个数据。 40 | 41 | ## 单周期处理器 42 | 43 | 单周期CPU在一个时钟周期内完成所有的工作。例如指令取出,得到结果等,它们全部都在一个时钟周期内完成。 44 | 45 | **缺点**:在单周期CPU中,时钟周期就是指令周期,因此每个指令周期都是固定的时长;而由于不同的指令执行的快慢是不同的,导致指令周期必须取决于执行时间最长的指令,因此在执行较简单的指令时会浪费时间,处理器的主频也难以提高。 46 | 47 | ## 多周期处理器 48 | 49 | 多周期CPU将整个CPU的执行过程分成几个阶段,每个阶段用一个时钟去完成。在多周期CPU中,一个指令周期可以由数个时钟周期组成,不同的指令可以占用不同的时钟周期数,从而提高了时间片的利用率,不仅能提高CPU主频,还为组成指令流水线提供了基础。 50 | 51 | 然而,多周期的CPU中,器件的工作方式还是“等待”,即必须等待当前指令全部执行完毕后,才会继续执行下一条指令。 52 | 53 | **缺点**:多周期CPU执行过程中,同一时间片内只有一个部件是繁忙的,其余部件都处于空闲状态;尽管提高了主频,但时间利用率依旧不高。 54 | 55 | ## 流水线处理器 56 | 57 | 我们利用各阶段电路间可并行执行的特点,让各个阶段的执行在时间上重叠起来,这种技术就是流水线技术。 58 | 59 | 就如工厂里面组装电脑一样: 60 | 61 | ### 横向来看 62 | 63 | 想象你现在只是一个CPU,你通过传送带被送到了主板组装工人那儿开始组装,然后传送带又把你送到了散热器工人那儿;然后组装外壳……最后完成了所有的组装,你现在是一台成熟的电脑了! 64 | 65 | ### 纵向来看 66 | 67 | 负责组装主板的工人,在第一台电脑通过传送带送来的时候快速地进行了主板的组装,然后电脑通过传送带从这儿离开,到了下一个工人那儿被装上散热器;第二台电脑通过传送带送来的时候,这位工人又快速地进行了主板的组装,电脑离开;第三台电脑过来了、第三台电脑离开了;第四台电脑过来了、第四台电脑离开了…… 68 | 69 | ### 优点 70 | 71 | 每个部件(工人)不间断地自己完成自己的工作。 72 | 73 | 给CPU贴标签的工人不用在贴完上一个CPU后干瞪眼,等待装外壳的工人龟速装完外壳才能贴下一个CPU,然后送到主板工人那儿组装。 74 | 75 | (说实在的,其实就是资本主义市场,一直压榨工人,让他们不能休息(滑稽)) -------------------------------------------------------------------------------- /2-浅析计组课设中制作的CPU.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 2-浅析计组课设中制作的CPU 6 | 7 | 大家是否还记得这一张图: 8 | 9 | ![1](./pic/2/1.jpg) 10 | 11 | 这是一个典型的单周期MIPS CPU架构: 12 | 13 | 1. PC生成下一个指令的地址; 14 | 2. 译码模块译码,CU通过译码模块翻译出来的操作码控制寄存器堆(Register File)的相应读写; 15 | 3. CU将控制信号传给ALU控制器,然后ALU控制器控制ALU进行相应的运算; 16 | 4. 最后ALU的结果需要写回给寄存器堆或者内存,CU仍然需要发出控制信号控制RegFile等器件的行为; 17 | 18 | 这幅图与我们当时设计的CPU还是**有所区别**的: 19 | 20 | 1. 我们采用状态机完成CPU; 21 | 2. 完成指令不止一个时钟周期; 22 | 3. 图里面多了很多寄存器。 23 | 24 | 于是: 25 | 26 | - 由于有寄存器,每一个上升沿或下降沿会进行一次数据锁存; 27 | - 通过状态机和控制器,控制整个处理过程的状态,每个周期只做一个过程(比如取值或者译码过程); 28 | - 在本质上其实是**多周期处理器**。 29 | 30 | ## 单周期处理器设计步骤 31 | 32 | 1. 分析指令系统,得出数据通路; 33 | 2. 为数据通路选择合适的器件; 34 | 3. 连接组件建立数据通路; 35 | 4. 分析每条指令的实现,确定控制信号; 36 | 5. 集成控制信号,形成完整的控制逻辑。 37 | -------------------------------------------------------------------------------- /3-什么是五级流水、数据前推、流水线暂停.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 3-什么是五级流水、数据前推、流水线暂停 6 | 7 | 请看图: 8 | 9 | ![1](./pic/3/1.png) 10 | 11 | ## 五级流水线的五个阶段 12 | 13 | 1. Instruction Fetch - IF:取指阶段; 14 | 2. Instruction Decode - ID:译码阶段; 15 | 3. Execute - EX:执行阶段; 16 | 4. Memory Access - MEM:访存阶段; 17 | 5. Writeback - WB:写回阶段。 18 | 19 | ## 用比喻详解五级流水、数据前推、流水线暂停 20 | 21 | ![2](./pic/3/1.png) 22 | 23 | 工厂有五个工人,他们是A B C D E,他们每个人都只负责自己的工作: 24 | 25 | 1. A负责的工作名称叫”取指“; 26 | 2. B负责的工作名称叫“译码”; 27 | 3. C负责的工作名称叫“执行”; 28 | 4. D负责的工作名称叫“访存”; 29 | 5. E负责的工作名称叫“写回”; 30 | 31 | 他们每个工人都不去管别人的工作是什么样子的; 32 | 33 | 工厂有个时钟喇叭,以每秒一次的频率大声“嘀嘀嘀”,当时钟喇叭发出声音的时候: 34 | 35 | 1. 传送带向前移动一个工人的位置; 36 | 2. ABCDE同时开始做自己的工作; 37 | 38 | 现在你是一个未加工产品,你被送上了传送带。 39 | 40 | ### 五级流水横向来看 41 | 42 | 1. 你听到了一声洪亮的“嘀”声,你被传送带往前送了一格到达了A工人,他在下一个“嘀”来临之前把你“取指”了; 43 | 2. 你又听到了一声“嘀”,你被传送带往前送到了B工人,他在下一个“嘀”来临之前把你“译码”了; 44 | 3. 以此类推,最后,E工人完成了对你的“写回”,下一个“嘀”来临的时候,你变成了一个成熟的自己! 45 | 46 | ### 五级流水纵向来看 47 | 48 | 1. 你是工人C,你只负责把产品“执行”; 49 | 2. 第一个声音发出,传送带向前推进一格,但是此时传送带在你这儿的位置上并没有东西; 50 | 3. 第二个声音发出,传送带向前推进一格,你看到B正在对一个东西“译码”,但是此时传送带在你这儿的位置上仍然没有东西; 51 | 4. 第三个声音发出,传送带向前推进一格,你传送带有东西了!你在下一个声音到来之前对这个东西完成了“执行”工序; 52 | 5. 第四个声音发出,传送带向前推进一格,你处理的东西到了D那儿,但是你现在又拿到了从B那儿送过来的东西,你又开始加工; 53 | 6. 第五个声音发出、第六个声音发出……声音源源不断地发出,一个一个没有被加工的东西到了你这儿,你在下一个声音发出之前完成了对它们的加工…… 54 | 7. 第n个声音发出,你在下一个声音发出之前完成了“执行工序,第n+1个声音发出,没有东西再来了,你的东西送到了D那儿; 55 | 8. 第n+2个声音发出,这个东西送到了E那儿; 56 | 9. 最后一个声音发出,这个东西从E那儿被送出去。你们五个人完成了所有产品的加工! 57 | 58 | ### 五级流水整体来看 59 | 60 | ![2](./pic/3/1.png) 61 | 62 | 1. 在第一个声音发出的时候,整个工厂只有A在做工序; 63 | 2. 到了第4个声音发出的时候,整个工厂已经有4个人在同时工作了!其中 64 | 65 | - A在对第四个产品进行工序,这个产品刚刚来到A这儿; 66 | 67 | - B在对第三个产品进行工序,这个产品已经被A处理完了,现在在B这儿等待处理; 68 | 69 | - C在对第二个产品进行工序,这个产品已经被A B都处理完了,现在在C这儿; 70 | 71 | - D在对第一个产品进行工序,这个产品已经被A B C都处理了!现在在D这儿。 72 | 3. 放眼望去,整个工厂里面每个人都在有条不紊的做自己的工作! 73 | 74 | > 动态流程可以查看项目中的PPT部分,里面有动画帮助理解 75 | 76 | ### 流水线暂停 77 | 78 | 想象你还是工人C,你负责”执行“工序,但是现在出现了一个大问题: 79 | 80 | - 这个东西太复杂了!你在下一个声音发出之前根本做不完! 81 | - 你不能把你没做完的东西让传送带送给D加工!这个产品不合格! 82 | 83 | 这可怎么办呢? 84 | 85 | 于是,你大喊一声:做不完了,sad!包工头听见了你的喊声,急忙把传送带关掉了! 86 | 87 | 此时: 88 | 89 | 1. 下一个声音发出的时候,传送带不会向前推进一格了; 90 | 2. 下一个声音发出的时候,你仍然在努力解决当前的工序问题; 91 | 3. 下一个声音发出的时候,虽然其他四个工人都做好了自己的工作,但是因为传送带没有动,所以他们手里都还留着上一个声音发出的时候正在处理的东西; 92 | 4. 几个声音过去了,你还在努力解决当前问题,大家急切的眼神让你充满了决心; 93 | 5. 第32个声音过去了,你终于解决了这个问题!你大喊一声:我完事了,happy!包工头长舒一口气,开启了传送带; 94 | 6. 第33个声音到来了,传送带向前推进了一格,D开始处理从你这儿传送过去的东西,你开始处理从B那儿传送过来的东西,一切都是这样和谐; 95 | 7. 第n个声音到来的时候,你发现又是一个难题!这时你又大喊一声:做不完了! 96 | 8. 包工头暂停了流水线,大家开始看你表演长达32个周期的”执行“工序…… 97 | 98 | ### 数据前推 99 | 100 | 想象你还是工人C,你负责”执行“工序,你们的工厂生产很多东西,甚至能直接把生产出来的东西拿来自己使用!但是现在又出现了一个大问题: 101 | 102 | - 你现在正在处理一个螺丝刀,下一个声音发出了,传送带把螺丝刀送给了D继续加工,但是B突然非常激动地给你说,这个产品很特殊,他需要一个螺丝刀才能完成对现在这个产品的工序,不然下一个声音到来的时候,这个东西到你这儿就不是一个合格的产品! 103 | - 你也非常激动,但是虽然在你加工过后,螺丝刀直接能用了,而且D E工人只对这个螺丝刀包装一下对外出售,但是你至少也得等到E工人最后包装完成过后,B工人才能拿到螺丝刀啊!这样一来,这个产品就一直被错误地加工下去,最后甚至会影响到整个流水线的产品质量!除非流水线暂停! 104 | 105 | 但是聪明的你突然想到了办法,于是悄悄对B说: 106 | 107 | **”我把螺丝刀加工完后直接分你一个,你保持低调,不要声张!“** 108 | 109 | 于是: 110 | 111 | 1. 你和B达成了协议,暗中交易;而且你可以光速克隆一个一模一样的螺丝刀,除了你和B,谁都不知道! 112 | 2. 在第一个声音发出的时候,B悄悄给你说:”我需要螺丝刀!“ 113 | 3. 下一个声音发出之前,你在对螺丝刀完成工序的同时光速克隆了一个一模一样的螺丝刀,然后给了B;B在下一个声音发出之前用你赞助的螺丝刀完成了工序,这使你充满了决心! 114 | 4. 下一个声音发出来了!你们两个若无其事地继续进行着各自的工作; 115 | 5. 第n个声音发出来了,B又突然悄悄给你说:”我需要螺丝刀!“ 116 | 6. 你们两个又开始了交易…… 117 | -------------------------------------------------------------------------------- /4-一个静态五级流水MIPS的最基本架构.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 4-一个静态五级流水MIPS的最基本架构 6 | 7 | ![1](./pic/4/1.jpg) 8 | 9 | ## 流水线寄存器 10 | 11 | 流水线寄存器在五级流水架构图中,视觉上位于每个阶段的交界处,用来锁存此阶段得出的结果,并在下一个阶段到来的时候将此结果送给下一个模块进行处理; 12 | 13 | ### 用处 14 | 15 | 因为所有部件都是连接在一起的,如果没有流水线寄存器的话,一个时钟信号到来之后,IF阶段处理的结果马上反馈到了ID阶段,同时如果ID在这个周期内得出了结果,就会马上反馈到EX阶段,以此类推;如果一个周期时间非常长的话,一条指令将在一个周期内得出结果,于是本质上这个变成了单周期处理器,就不存在流水线这一个说法了。 16 | 17 | 流水线寄存器就像一个“镜像”,它保持前一段的数据,以便给后一段使用;同时又像一个“门神”,它不让那些处理速度过快的阶段超越整体设计速度。 18 | 19 | 总的来说,流水线寄存器将每个段进行**隔离**,让每个部件互不干扰地进行工作。 20 | 21 | ## 取指阶段 22 | 23 | - PC模块:给出指令地址,其中实现指令指针寄存器PC,该寄存器的值就是指令地址; 24 | - IF/ID模块:实现取指与译码阶段之间的流水线寄存器,将取指阶段的结果在下一个时钟上升沿传递到译码阶段。 25 | 26 | ## 译码阶段 27 | 28 | - ID模块:对指令进行译码,译码结果包括运算类型、运算所需的源操作数、要写入的目的寄存器地址等等; 29 | - RegFile模块:实现了32个32位通用整数寄存器,可以同时进行两个寄存器的读操作和一个寄存器的写操作; 30 | - ID/EX模块:实现译码与执行阶段的流水线寄存器,将译码阶段的结果在下一个时钟周期传递到执行阶段。 31 | 32 | ## 执行阶段 33 | 34 | - EX模块:根据译码阶段的结果进行指定的运算,给出运算结果; 35 | - EX/MEM模块:执行阶段与访存阶段的流水线寄存器,将执行阶段的结果在下一个时钟周期传递到访存阶段。 36 | 37 | ## 访存阶段 38 | 39 | - 由于本讲义只会讲解ORI指令的实现,所以此阶段在本讲义中留空,感兴趣的同学自行学习; 40 | 41 | ## 写回阶段 42 | 43 | - 由于本讲义只会讲解ORI指令的实现,所以此阶段在本讲义中留空,感兴趣的同学自行学习; 44 | 45 | ## 一个独立的模块 46 | 47 | 有一个CTRL模块,用于控制流水线暂停以及清空,不便于归入流水线中的某一个阶段。 48 | 49 | 此外,一个具有完整功能的MIPS处理器还有其他很多部分,这里不加过多的叙述,感兴趣的同学可以自行深入学习。 -------------------------------------------------------------------------------- /5-第一条指令 ORI 的实现.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 5-第一条指令 ORI 的实现 6 | 7 | 此章节会完全参考 《自己动手写CPU》中 OpenMIPS 处理器的实现方法给大家讲解 ORI 的实现,但是又在内容上有所优化。 8 | 9 | 从此节开始到结束,**将是本讲义的重点部分**,前面所有部分可以说是一种铺垫,希望大家通过后面部分的学习能够掌握讲义所提供给大家的一个思维方式来解决实验中遇到的难题。 10 | 11 | 当然这个讲义提供的是一种最基本的思维方式,为的是让大家能够更好的理解各个指令五级流水的实现,其他更有效更快速的思维方式大家可以在课余时间自行学习。 12 | 13 | ## 前言 14 | 15 | 摘自《自己动手写CPU》 16 | 17 | ![1](./pic/5/1.jpg) 18 | 19 | ## 补充内容:MIPS指令集格式 20 | 21 | 在MIPS架构中,指令被分为三种类型:R型、I型和J型。三种类型的指令的最高6位均为6位的opcode码。从25位往下, 22 | 23 | - R型指令用连续三个5位二进制码来表示三个寄存器的地址,然后用一个5位二进制码来表示移位的位数(如果未使用移位操作,则全为0),最后为6位的function码(它与opcode码共同决定R型指令的具体操作方式); 24 | 25 | - **I型指令则用连续两个5位二进制码来表示两个寄存器的地址,然后是一个16位二进制码来表示的一个立即数二进制码;** 26 | 27 | - J型指令用26位二进制码来表示跳转目标的指令地址(实际的指令地址应为32位,其中最低两位为00,高四位由PC当前地址决定)。 28 | 29 | 三种类型的指令图示如下: 30 | 31 | ![17](./pic/5/17.jpg) 32 | 33 | 参考资料:[MIPS架构——维基百科](https://zh.wikipedia.org/w/index.php?title=MIPS%E6%9E%B6%E6%A7%8B&wteswitched=1#MIPS%E6%8C%87%E4%BB%A4%E6%A0%BC%E5%BC%8F) 34 | 35 | 36 | 37 | ## ORI 指令说明 38 | 39 | ![2](./pic/5/2.jpg) 40 | 41 | ### 16位立即数扩展 42 | 43 | ![3](./pic/5/3.jpg) 44 | 45 | - 符号扩展:按照最高位扩展; 46 | - 无符号扩展:将扩展后的32位数据的高16位全置为0; 47 | 48 | # 原始的数据流图 49 | 50 | ![4](./pic/5/4.jpg) 51 | 52 | - IF:取出指令存储器中的指令,与此同时PC值递增得到下一条指令的地址,准备取下一条指令; 53 | - ID:对指令进行译码,根据译码结果从RegFile中取出源操作数,其中ORI还需要立即数扩展; 54 | - EX:根据译码阶段送入的源操作数、操作码进行运算。对于ORI指令而言,就是进行逻辑“或”运算,运算结果传递到访存阶段; 55 | - MEM:对于ORI指令,访存阶段没有任何操作,直接把结果传递到下一个阶段; 56 | - WB:把运算结果保存到目的寄存器。 57 | 58 | ## OpenMIPS 五级流水线结构图 59 | 60 | ![5](./pic/5/5.jpg) 61 | 62 | # 取指阶段的实现 63 | 64 | 取指阶段取出指令存储器中的指令,同时PC值递增。准备下一条指令; 65 | 66 | 包括PC和IF/ID两个模块 67 | 68 | ## PC模块 69 | 70 | PC模块的作用是给出指令地址,接口如图所示: 71 | 72 | ![6](./pic/5/6.jpg) 73 | 74 | PC代码讲解: 75 | 76 | ```verilog 77 | `include "defines.v" 78 | 79 | module pc_reg( 80 | 81 | input wire clk, 82 | input wire rst, 83 | 84 | output reg[`InstAddrBus] pc, 85 | output reg ce 86 | 87 | ); 88 | 89 | // 指令存储器禁用的时候 PC值需要归零 90 | always @ (posedge clk) begin 91 | if (ce == `ChipDisable) begin 92 | pc <= 32'h00000000; 93 | end else begin 94 | pc <= pc + 4'h4; 95 | end 96 | end 97 | 98 | // 复位的时候需要禁用指令存储器 99 | always @ (posedge clk) begin 100 | if (rst == `RstEnable) begin 101 | ce <= `ChipDisable; 102 | end else begin 103 | ce <= `ChipEnable; 104 | end 105 | end 106 | 107 | endmodule 108 | ``` 109 | 110 | ## IF/ID模块 111 | 112 | IF/ID模块的作用是暂时保存取指阶段所得的指令,以及对应的指令地址,并在下一个CLK传递到译码阶段,接口如图所示: 113 | 114 | ![7](./pic/5/7.jpg) 115 | 116 | (5、6:传递给译码阶段的……) 117 | 118 | ```verilog 119 | module if_id( 120 | 121 | input wire clk, 122 | input wire rst, 123 | 124 | 125 | input wire[`InstAddrBus] if_pc, 126 | input wire[`InstBus] if_inst, 127 | output reg[`InstAddrBus] id_pc, 128 | output reg[`InstBus] id_inst 129 | 130 | ); 131 | 132 | // 如果复位的话,传递给下一个阶段的数据要清零 133 | always @ (posedge clk) begin 134 | if (rst == `RstEnable) begin 135 | id_pc <= `ZeroWord; 136 | id_inst <= `ZeroWord; 137 | end else begin 138 | id_pc <= if_pc; 139 | id_inst <= if_inst; 140 | end 141 | end 142 | 143 | endmodule 144 | ``` 145 | 146 | # 译码阶段的实现 147 | 148 | 此时,我们的ORI指令已经进入了译码阶段,在这个阶段,CPU需要对这个指令进行译码,即给出需要进行的运算类型、参与运算的操作数。 149 | 150 | ## RegFile模块 151 | 152 | 这是寄存器堆模块,实现了32个32位通用寄存器,可以同时进行两个寄存器的读操作和一个寄存器的写操作。接口如图: 153 | 154 | ![8](./pic/5/8.jpg) 155 | 156 | ![9](./pic/5/9.jpg) 157 | 158 | 代码如下: 159 | 160 | ```verilog 161 | `include "defines.v" 162 | 163 | module regfile( 164 | 165 | input wire clk, 166 | input wire rst, 167 | 168 | // 写端口 169 | input wire we, 170 | input wire[`RegAddrBus] waddr, 171 | input wire[`RegBus] wdata, 172 | 173 | // 读端口 1 174 | input wire re1, 175 | input wire[`RegAddrBus] raddr1, 176 | output reg[`RegBus] rdata1, 177 | 178 | // 读端口 2 179 | input wire re2, 180 | input wire[`RegAddrBus] raddr2, 181 | output reg[`RegBus] rdata2 182 | 183 | ); 184 | 185 | // 定义32个32位寄存器 186 | reg[`RegBus] regs[0:`RegNum-1]; 187 | 188 | // 写操作 189 | always @ (posedge clk) begin 190 | if (rst == `RstDisable) begin 191 | // 如果 写使能 而且 我们没有向0号寄存器写入东西的时候,我们才向寄存器里面写入 192 | // 因为 0 号寄存器只读而且永远读出 32'h0 193 | if((we == `WriteEnable) && (waddr != `RegNumLog2'h0)) begin 194 | regs[waddr] <= wdata; 195 | end 196 | end 197 | end 198 | 199 | // 读端口1 的读操作 200 | always @ (*) begin 201 | // 如果重置则读出 32'h0 202 | if(rst == `RstEnable) begin 203 | rdata1 <= `ZeroWord; 204 | // 如果读0号寄存器,也只读出0 205 | end else if(raddr1 == `RegNumLog2'h0) begin 206 | rdata1 <= `ZeroWord; 207 | // 当读地址与写地址相同,且写使能,且端口1读使能,则要把写入的数据直接读出来 208 | // 数据前推的实现,后面会提及 209 | end else if((raddr1 == waddr) && (we == `WriteEnable) 210 | && (re1 == `ReadEnable)) begin // 注意此部分!理解! 211 | rdata1 <= wdata; 212 | // 否则读取相应寄存器单元 213 | end else if(re1 == `ReadEnable) begin 214 | rdata1 <= regs[raddr1]; 215 | // 如果第一个读端口不能使用时,输出0 216 | end else begin 217 | rdata1 <= `ZeroWord; 218 | end 219 | end 220 | 221 | // 读端口2 的读操作 222 | // 和读端口1 类似 223 | always @ (*) begin 224 | if(rst == `RstEnable) begin 225 | rdata2 <= `ZeroWord; 226 | end else if(raddr2 == `RegNumLog2'h0) begin 227 | rdata2 <= `ZeroWord; 228 | end else if((raddr2 == waddr) && (we == `WriteEnable) 229 | && (re2 == `ReadEnable)) begin // 注意此部分!理解! 230 | rdata2 <= wdata; 231 | end else if(re2 == `ReadEnable) begin 232 | rdata2 <= regs[raddr2]; 233 | end else begin 234 | rdata2 <= `ZeroWord; 235 | end 236 | end 237 | 238 | endmodule 239 | ``` 240 | 241 | 有一点需要注意:读寄存器是组合逻辑电路 242 | 243 | ``` 244 | always @ (*) 245 | ``` 246 | 247 | 因为一旦输入的要读取的寄存器地址发生了变化,必须要立刻给出新地址对应的寄存器的值,这样可以保证在译码阶段读取得到要读取的寄存器的值;**但是写操作是时序逻辑电路**,写操作发生在时钟信号的上升沿。 248 | 249 | ``` 250 | always @ (posedge clk) 251 | ``` 252 | 253 | ## ID模块 254 | 255 | ID模块进行译码,得到最终运算的类型、子类型、源操作数等等,接口如图: 256 | 257 | ![10](./pic/5/10.jpg) 258 | 259 | ![11](./pic/5/11.jpg) 260 | 261 | 代码如下: 262 | 263 | ```verilog 264 | `include "defines.v" 265 | 266 | module id( 267 | 268 | input wire rst, 269 | input wire[`InstAddrBus] pc_i, 270 | input wire[`InstBus] inst_i, 271 | 272 | // 读取的REGFILE的值 273 | input wire[`RegBus] reg1_data_i, 274 | input wire[`RegBus] reg2_data_i, 275 | 276 | // 输出到REGFILE的信息,包括读端口1和2的读使能信号以及读地址信号 277 | output reg reg1_read_o, 278 | output reg reg2_read_o, 279 | output reg[`RegAddrBus] reg1_addr_o, 280 | output reg[`RegAddrBus] reg2_addr_o, 281 | 282 | // 送到EX阶段的信息 283 | output reg[`AluOpBus] aluop_o, // ALU操作码 284 | output reg[`AluSelBus] alusel_o, // ALU子操作码 285 | output reg[`RegBus] reg1_o, // 源操作数 1 286 | output reg[`RegBus] reg2_o, // 源操作数 2 287 | output reg[`RegAddrBus] wd_o, // 要写入的寄存器的地址 288 | output reg wreg_o // 写使能信号 289 | ); 290 | 291 | // 取得指令的指令码、功能码等; 292 | wire[5:0] op = inst_i[31:26]; //对于ORI指令只需要判断 26-31bit 的值即可判断 293 | wire[4:0] op2 = inst_i[10:6]; 294 | wire[5:0] op3 = inst_i[5:0]; 295 | wire[4:0] op4 = inst_i[20:16]; 296 | // 保存指令执行需要的立即数 297 | reg[`RegBus] imm; 298 | // 指令是否有效 299 | reg instvalid; 300 | 301 | 302 | // 译码阶段,组合逻辑 303 | // 如果重置则进行以下操作 304 | always @ (*) begin 305 | if (rst == `RstEnable) begin 306 | aluop_o <= `EXE_NOP_OP; 307 | alusel_o <= `EXE_RES_NOP; 308 | wd_o <= `NOPRegAddr; 309 | wreg_o <= `WriteDisable; 310 | instvalid <= `InstValid; 311 | reg1_read_o <= 1'b0; 312 | reg2_read_o <= 1'b0; 313 | reg1_addr_o <= `NOPRegAddr; 314 | reg2_addr_o <= `NOPRegAddr; 315 | imm <= 32'h0; 316 | // 如果不重置则进行以下操作 317 | end else begin 318 | // 这里其实是default里面的值 319 | // 我们先看下面的case 320 | aluop_o <= `EXE_NOP_OP; 321 | alusel_o <= `EXE_RES_NOP; 322 | wd_o <= inst_i[15:11]; 323 | wreg_o <= `WriteDisable; 324 | instvalid <= `InstInvalid; 325 | reg1_read_o <= 1'b0; 326 | reg2_read_o <= 1'b0; 327 | reg1_addr_o <= inst_i[25:21]; 328 | reg2_addr_o <= inst_i[20:16]; 329 | imm <= `ZeroWord; 330 | case (op) 331 | `EXE_ORI: 332 | begin 333 | wreg_o <= `WriteEnable; // 写使能 334 | aluop_o <= `EXE_OR_OP; 335 | alusel_o <= `EXE_RES_LOGIC; 336 | reg1_read_o <= 1'b1; // 读 rs 337 | reg2_read_o <= 1'b0; // 不读 rt 338 | imm <= {16'h0, inst_i[15:0]}; // 立即数无符号扩展 339 | wd_o <= inst_i[20:16]; // 写寄存器地址位 rt 340 | instvalid <= `InstValid; 341 | end 342 | default: 343 | // 在上面已经给出 344 | begin 345 | end 346 | endcase 347 | end 348 | end 349 | 350 | 351 | // 确定运算的操作数1 352 | always @ (*) begin 353 | if(rst == `RstEnable) begin 354 | reg1_o <= `ZeroWord; 355 | end else if(reg1_read_o == 1'b1) begin 356 | reg1_o <= reg1_data_i; 357 | // 若没有 读使能,则把立即数作为数据输出为 操作数1 358 | end else if(reg1_read_o == 1'b0) begin 359 | reg1_o <= imm; 360 | end else begin 361 | reg1_o <= `ZeroWord; 362 | end 363 | end 364 | 365 | // 确定运算的操作数2 366 | always @ (*) begin 367 | if(rst == `RstEnable) begin 368 | reg2_o <= `ZeroWord; 369 | end else if(reg2_read_o == 1'b1) begin 370 | reg2_o <= reg2_data_i; 371 | // 若没有 读使能,则把立即数作为数据输出为 操作数1 372 | end else if(reg2_read_o == 1'b0) begin 373 | reg2_o <= imm; 374 | end else begin 375 | reg2_o <= `ZeroWord; 376 | end 377 | end 378 | 379 | endmodule 380 | ``` 381 | 382 | ## ID/EX模块 383 | 384 | ID模块的输出连接到ID/EX模块,后者将译码阶段取得的运算类型、源操作数、要写的目的寄存器地址等结果,在下一个时钟传递到执行阶段,接口如图所示: 385 | 386 | ![12](./pic/5/12.jpg) 387 | 388 | 代码如下: 389 | 390 | ```verilog 391 | `include "defines.v" 392 | 393 | module id_ex( 394 | 395 | input wire clk, 396 | input wire rst, 397 | 398 | 399 | // 从ID阶段传递过来的信息 400 | input wire[`AluOpBus] id_aluop, 401 | input wire[`AluSelBus] id_alusel, 402 | input wire[`RegBus] id_reg1, 403 | input wire[`RegBus] id_reg2, 404 | input wire[`RegAddrBus] id_wd, 405 | input wire id_wreg, 406 | 407 | // 需要传递到EX阶段的信息 408 | output reg[`AluOpBus] ex_aluop, 409 | output reg[`AluSelBus] ex_alusel, 410 | output reg[`RegBus] ex_reg1, 411 | output reg[`RegBus] ex_reg2, 412 | output reg[`RegAddrBus] ex_wd, 413 | output reg ex_wreg 414 | 415 | ); 416 | 417 | // 如果重置的话,进行以下操作清空信息 418 | always @ (posedge clk) begin 419 | if (rst == `RstEnable) begin 420 | ex_aluop <= `EXE_NOP_OP; 421 | ex_alusel <= `EXE_RES_NOP; 422 | ex_reg1 <= `ZeroWord; 423 | ex_reg2 <= `ZeroWord; 424 | ex_wd <= `NOPRegAddr; 425 | ex_wreg <= `WriteDisable; 426 | // 如果不重置的话,把ID阶段的结果送到EX阶段 427 | end else begin 428 | ex_aluop <= id_aluop; 429 | ex_alusel <= id_alusel; 430 | ex_reg1 <= id_reg1; 431 | ex_reg2 <= id_reg2; 432 | ex_wd <= id_wd; 433 | ex_wreg <= id_wreg; 434 | end 435 | end 436 | 437 | endmodule 438 | ``` 439 | 440 | # 执行阶段的实现 441 | 442 | 现在,指令已经进入了执行阶段了,在这个阶段,CPU将根据译码结果对源操作数等进行指定的运算并给出结果。 443 | 444 | ## EX模块 445 | 446 | EX模块接收ID阶段翻译的信号来决定如何进行操作,接口如图所示: 447 | 448 | ![13](./pic/5/13.jpg) 449 | 450 | 代码如下: 451 | 452 | ```verilog 453 | `include "defines.v" 454 | 455 | module ex( 456 | 457 | input wire rst, 458 | 459 | // 从译码阶段送过来的信息 460 | input wire[`AluOpBus] aluop_i, 461 | input wire[`AluSelBus] alusel_i, 462 | input wire[`RegBus] reg1_i, 463 | input wire[`RegBus] reg2_i, 464 | input wire[`RegAddrBus] wd_i, 465 | input wire wreg_i, 466 | 467 | // 执行的结果 468 | output reg[`RegAddrBus] wd_o, 469 | output reg wreg_o, 470 | output reg[`RegBus] wdata_o 471 | 472 | ); 473 | 474 | // 保存逻辑运算的结果 475 | reg[`RegBus] logicout; 476 | 477 | // 组合逻辑:根据运算子类型进行运算,此处只有“或运算” 478 | always @ (*) begin 479 | if(rst == `RstEnable) begin 480 | logicout <= `ZeroWord; 481 | end else begin 482 | case (aluop_i) 483 | `EXE_OR_OP: begin 484 | logicout <= reg1_i | reg2_i; 485 | end 486 | default: begin 487 | logicout <= `ZeroWord; 488 | end 489 | endcase 490 | end //if 491 | end //always 492 | 493 | 494 | // 组合逻辑: 根据主运算类型选择一个选择一个运算结果最为最终结果输出 495 | always @ (*) begin 496 | // 需要写入的寄存器的地址 497 | wd_o <= wd_i; 498 | // 寄存器写使能 499 | wreg_o <= wreg_i; 500 | // 根据主运算类型选择一个选择一个运算结果最为最终结果输出 501 | case ( alusel_i ) 502 | `EXE_RES_LOGIC: begin 503 | wdata_o <= logicout; 504 | end 505 | default: begin 506 | wdata_o <= `ZeroWord; 507 | end 508 | endcase 509 | end 510 | 511 | endmodule 512 | ``` 513 | 514 | 注意:EX模块中全是组合逻辑电路,因为他们需要实时拿出运算结果! 515 | 516 | ## EX/MEM模块 517 | 518 | EX模块的输出连接到EX/MEM模块,后者的作用是将执行阶段的结果在下一个时钟周期传递到访存阶段,接口如图所示: 519 | 520 | ![14](./pic/5/14.jpg) 521 | 522 | 代码如下: 523 | 524 | ```verilog 525 | `include "defines.v" 526 | 527 | module ex_mem( 528 | 529 | input wire clk, 530 | input wire rst, 531 | 532 | 533 | // 来自执行阶段的信息 534 | input wire[`RegAddrBus] ex_wd, 535 | input wire ex_wreg, 536 | input wire[`RegBus] ex_wdata, 537 | 538 | // 送到访存阶段的信息 539 | output reg[`RegAddrBus] mem_wd, 540 | output reg mem_wreg, 541 | output reg[`RegBus] mem_wdata 542 | 543 | 544 | ); 545 | 546 | 547 | // 时序逻辑 548 | always @ (posedge clk) begin 549 | // 如果重置的话,清除信息 550 | if(rst == `RstEnable) begin 551 | mem_wd <= `NOPRegAddr; 552 | mem_wreg <= `WriteDisable; 553 | mem_wdata <= `ZeroWord; 554 | // 不重置的话,把信息传递到MEM阶段 555 | end else begin 556 | mem_wd <= ex_wd; 557 | mem_wreg <= ex_wreg; 558 | mem_wdata <= ex_wdata; 559 | end //if 560 | end //always 561 | 562 | 563 | endmodule 564 | ``` 565 | 566 | # 访存阶段的实现 567 | 568 | 访存阶段,ORI指令不需要做任何事,所以只是简单地将执行阶段的结果传递给写回阶段即可。 569 | 570 | ## MEM模块 571 | 572 | 代码如下: 573 | 574 | ```verilog 575 | `include "defines.v" 576 | 577 | module mem( 578 | 579 | input wire rst, 580 | 581 | // 来自执行阶段的消息 582 | input wire[`RegAddrBus] wd_i, 583 | input wire wreg_i, 584 | input wire[`RegBus] wdata_i, 585 | 586 | // 访存阶段的结果 587 | output reg[`RegAddrBus] wd_o, 588 | output reg wreg_o, 589 | output reg[`RegBus] wdata_o 590 | 591 | ); 592 | 593 | // 如果重置则清除结果 594 | always @ (*) begin 595 | if(rst == `RstEnable) begin 596 | wd_o <= `NOPRegAddr; 597 | wreg_o <= `WriteDisable; 598 | wdata_o <= `ZeroWord; 599 | // 否则因为ORI在此阶段不需要做任何事情,所以直接送给下个阶段(WB) 600 | end else begin 601 | wd_o <= wd_i; 602 | wreg_o <= wreg_i; 603 | wdata_o <= wdata_i; 604 | end //if 605 | end //always 606 | 607 | 608 | endmodule 609 | ``` 610 | 611 | ## MEM/WB模块 612 | 613 | 代码如下: 614 | 615 | ```verilog 616 | `include "defines.v" 617 | 618 | module mem_wb( 619 | 620 | input wire clk, 621 | input wire rst, 622 | 623 | 624 | // 来自访存阶段的信息 625 | input wire[`RegAddrBus] mem_wd, 626 | input wire mem_wreg, 627 | input wire[`RegBus] mem_wdata, 628 | 629 | // 需要传递给写回阶段的信息 630 | output reg[`RegAddrBus] wb_wd, 631 | output reg wb_wreg, 632 | output reg[`RegBus] wb_wdata 633 | 634 | ); 635 | 636 | 637 | // 如果重置的话,清除信息,否则传递给写回阶段 638 | always @ (posedge clk) begin 639 | if(rst == `RstEnable) begin 640 | wb_wd <= `NOPRegAddr; 641 | wb_wreg <= `WriteDisable; 642 | wb_wdata <= `ZeroWord; 643 | end else begin 644 | wb_wd <= mem_wd; 645 | wb_wreg <= mem_wreg; 646 | wb_wdata <= mem_wdata; 647 | end //if 648 | end //always 649 | 650 | 651 | endmodule 652 | ``` 653 | 654 | # 写回阶段的实现 655 | 656 | 经过上面的层层传递,ORI指令的运算结果已经到达了写回阶段了。 657 | 658 | 这个阶段实际上是在RegFile模块中实现的,请看这张图: 659 | 660 | ![4-2](./pic/5/4.jpg) 661 | 662 | MEM/WB的输出直接连接到RegFile模块,此时会将指令的运算结果写入目的寄存器,具体代码参考“译码阶段的实现” 663 | 664 | # 顶层模块的实现 665 | 666 | 顶层模块就是将上面实现的流水线各个阶段的模块进行实例化、连接,如图所示: 667 | 668 | ![5-2](./pic/5/5.jpg) 669 | 670 | 接口如图所示: 671 | 672 | ![15](./pic/5/15.jpg) 673 | 674 | 代码如下: 675 | 676 | ```verilog 677 | `include "defines.v" 678 | 679 | module openmips( 680 | 681 | input wire clk, 682 | input wire rst, 683 | 684 | 685 | input wire[`RegBus] rom_data_i, 686 | output wire[`RegBus] rom_addr_o, 687 | output wire rom_ce_o 688 | 689 | ); 690 | 691 | // IF/ID模块的输出,连接到ID模块的输入 692 | wire[`InstAddrBus] pc; 693 | wire[`InstAddrBus] id_pc_i; 694 | wire[`InstBus] id_inst_i; 695 | 696 | // ID模块输出,连接到ID/EX模块的输入 697 | wire[`AluOpBus] id_aluop_o; 698 | wire[`AluSelBus] id_alusel_o; 699 | wire[`RegBus] id_reg1_o; 700 | wire[`RegBus] id_reg2_o; 701 | wire id_wreg_o; 702 | wire[`RegAddrBus] id_wd_o; 703 | 704 | // ID/EX模块输出,连接到EX模块的输入 705 | wire[`AluOpBus] ex_aluop_i; 706 | wire[`AluSelBus] ex_alusel_i; 707 | wire[`RegBus] ex_reg1_i; 708 | wire[`RegBus] ex_reg2_i; 709 | wire ex_wreg_i; 710 | wire[`RegAddrBus] ex_wd_i; 711 | 712 | // EX模块的输出,连接到EX/MEM模块的输入 713 | wire ex_wreg_o; 714 | wire[`RegAddrBus] ex_wd_o; 715 | wire[`RegBus] ex_wdata_o; 716 | 717 | // EX/MEM模块的输出,连接到MEM模块的输入 718 | wire mem_wreg_i; 719 | wire[`RegAddrBus] mem_wd_i; 720 | wire[`RegBus] mem_wdata_i; 721 | 722 | // MEM模块的输出,连接到MEM/WB模块的输入 723 | wire mem_wreg_o; 724 | wire[`RegAddrBus] mem_wd_o; 725 | wire[`RegBus] mem_wdata_o; 726 | 727 | // MEM/WB模块的输出,连接到WB模块的输入 728 | wire wb_wreg_i; 729 | wire[`RegAddrBus] wb_wd_i; 730 | wire[`RegBus] wb_wdata_i; 731 | 732 | // WB模块的输出,连接到ID阶段RegFile模块的输入 733 | wire reg1_read; 734 | wire reg2_read; 735 | wire[`RegBus] reg1_data; 736 | wire[`RegBus] reg2_data; 737 | wire[`RegAddrBus] reg1_addr; 738 | wire[`RegAddrBus] reg2_addr; 739 | 740 | // PC_REG 的实例化 741 | pc_reg pc_reg0( 742 | .clk(clk), 743 | .rst(rst), 744 | .pc(pc), 745 | .ce(rom_ce_o) 746 | 747 | ); 748 | 749 | assign rom_addr_o = pc; 750 | 751 | // IF/ID模块的实例化 752 | if_id if_id0( 753 | .clk(clk), 754 | .rst(rst), 755 | .if_pc(pc), 756 | .if_inst(rom_data_i), 757 | .id_pc(id_pc_i), 758 | .id_inst(id_inst_i) 759 | ); 760 | 761 | // ID模块实例化 762 | id id0( 763 | .rst(rst), 764 | .pc_i(id_pc_i), 765 | .inst_i(id_inst_i), 766 | 767 | .reg1_data_i(reg1_data), 768 | .reg2_data_i(reg2_data), 769 | 770 | // 来自REGFILE的数据输入 771 | .reg1_read_o(reg1_read), 772 | .reg2_read_o(reg2_read), 773 | 774 | .reg1_addr_o(reg1_addr), 775 | .reg2_addr_o(reg2_addr), 776 | 777 | // 送到ID/EX模块的数据 778 | .aluop_o(id_aluop_o), 779 | .alusel_o(id_alusel_o), 780 | .reg1_o(id_reg1_o), 781 | .reg2_o(id_reg2_o), 782 | .wd_o(id_wd_o), 783 | .wreg_o(id_wreg_o) 784 | ); 785 | 786 | //ͨ RegFile模块的实例化 787 | regfile regfile1( 788 | .clk (clk), 789 | .rst (rst), 790 | .we (wb_wreg_i), 791 | .waddr (wb_wd_i), 792 | .wdata (wb_wdata_i), 793 | .re1 (reg1_read), 794 | .raddr1 (reg1_addr), 795 | .rdata1 (reg1_data), 796 | .re2 (reg2_read), 797 | .raddr2 (reg2_addr), 798 | .rdata2 (reg2_data) 799 | ); 800 | 801 | // ID/EX模块的实例化 802 | id_ex id_ex0( 803 | .clk(clk), 804 | .rst(rst), 805 | 806 | // 来自ID阶段的数据 807 | .id_aluop(id_aluop_o), 808 | .id_alusel(id_alusel_o), 809 | .id_reg1(id_reg1_o), 810 | .id_reg2(id_reg2_o), 811 | .id_wd(id_wd_o), 812 | .id_wreg(id_wreg_o), 813 | 814 | // 要送到EX阶段的数据 815 | .ex_aluop(ex_aluop_i), 816 | .ex_alusel(ex_alusel_i), 817 | .ex_reg1(ex_reg1_i), 818 | .ex_reg2(ex_reg2_i), 819 | .ex_wd(ex_wd_i), 820 | .ex_wreg(ex_wreg_i) 821 | ); 822 | 823 | // EX模块的实例化 824 | ex ex0( 825 | .rst(rst), 826 | 827 | // 来自ID/EX的数据 828 | .aluop_i(ex_aluop_i), 829 | .alusel_i(ex_alusel_i), 830 | .reg1_i(ex_reg1_i), 831 | .reg2_i(ex_reg2_i), 832 | .wd_i(ex_wd_i), 833 | .wreg_i(ex_wreg_i), 834 | 835 | // EX阶段的结果,输出到EX/MEM的数据 836 | .wd_o(ex_wd_o), 837 | .wreg_o(ex_wreg_o), 838 | .wdata_o(ex_wdata_o) 839 | 840 | ); 841 | 842 | // EX/MEM的实例化 843 | ex_mem ex_mem0( 844 | .clk(clk), 845 | .rst(rst), 846 | 847 | // 来自EX模块的数据 848 | .ex_wd(ex_wd_o), 849 | .ex_wreg(ex_wreg_o), 850 | .ex_wdata(ex_wdata_o), 851 | 852 | 853 | // 将要送到MEM阶段的数据 854 | .mem_wd(mem_wd_i), 855 | .mem_wreg(mem_wreg_i), 856 | .mem_wdata(mem_wdata_i) 857 | 858 | 859 | ); 860 | 861 | // MEM模块的实例化 862 | mem mem0( 863 | .rst(rst), 864 | 865 | // 来自EX/MEM模块的数据 866 | .wd_i(mem_wd_i), 867 | .wreg_i(mem_wreg_i), 868 | .wdata_i(mem_wdata_i), 869 | 870 | // 要送到MEM/WB模块的数据 871 | .wd_o(mem_wd_o), 872 | .wreg_o(mem_wreg_o), 873 | .wdata_o(mem_wdata_o) 874 | ); 875 | 876 | // MEM/WB 模块的实例化 877 | mem_wb mem_wb0( 878 | .clk(clk), 879 | .rst(rst), 880 | 881 | // 来自MEM的数据 882 | .mem_wd(mem_wd_o), 883 | .mem_wreg(mem_wreg_o), 884 | .mem_wdata(mem_wdata_o), 885 | 886 | // 将要送到RegFile的数据 887 | .wb_wd(wb_wd_i), 888 | .wb_wreg(wb_wreg_i), 889 | .wb_wdata(wb_wdata_i) 890 | 891 | ); 892 | 893 | endmodule 894 | ``` 895 | 896 | # 利用Vivado行为仿真 897 | 898 | VIVADO行为仿真方法以及testbench编写本讲义不做讲解,请自行学习,但是在这儿提供一下思路: 899 | 900 | 1. 在testbench中创建一个顶层MIPS实例; 901 | 2. 给出时钟信号输入以及指令输入; 902 | 3. 在每个周期给出不同的测试指令(**不能有数据相关!因为至此我们还没有开始实现数据相关!**); 903 | 4. 查看仿真波形,检查结果是否正确; 904 | 905 | ## 测试程序示例 906 | 907 | 这是一段测试程序,如图所示: 908 | 909 | ![16](./pic/5/16.jpg) 910 | 911 | 给出它的机器码: 912 | 913 | ``` 914 | 34011100 915 | 34020020 916 | 3403ff00 917 | 3404ffff 918 | ``` 919 | 920 | 为了使流水线情况更加直观,建议先一条指令一条指令查看仿真波形,熟悉之后最后再把四条指令全部发出查看结果是否正确。 921 | 922 | # 回顾原始的数据流图 923 | 924 | ![4-3](./pic/5/4.jpg) 925 | 926 | 请以上面给出的一段测试程序为例,看看这四条指令在五级流水线中是如何流动的。 -------------------------------------------------------------------------------- /6-流水线冲突.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 6-流水线冲突 6 | 7 | 流水线中经常会有一些“相关”的问题发生,它使得指令序列中下一条指令没有办法按照设计的时钟周期执行,这些“相关”会降低流水线的性能,他们被称为流水线中的冒险(Hazard,书上译作冲突)。 8 | 9 | 流水线中冲突分为三种 10 | 11 | 1. 结构冲突; 12 | 2. 数据冲突; 13 | 3. 控制冲突。 14 | 15 | ## 结构冲突 16 | 17 | 指的是在指令的执行过程中,由于硬件资源满足不了指令执行的要求发生硬件资源冲突而产生的冲突。 18 | 19 | 比如指令和数据都共享一个存储器,在某个时钟周期的时候: 20 | 21 | - 流水线要完成某条指令中,对存储器中数据的访问操作; 22 | - 流水线同时还要完成下一条指令的取指操作。 23 | 24 | 这样就发生了存储器访问冲突,产生了结构冲突。 25 | 26 | ## 控制冲突 27 | 28 | 指的是流水线中的分支指令或者其他需要改写PC的指令造成的冲突。 29 | 30 | ## 数据冲突 31 | 32 | **很常见的一种冲突类型**,指的是流水线中在执行的几条指令里面,有一条或者多条指令依赖于前面指令的执行结果。 33 | 34 | 数据冲突分为三种: 35 | 36 | 1. RAW:写后读数据,即后面的指令必须在前面的指令写之后读取数据,才能有正确结果; 37 | 38 | 2. WAR:读后写数据,即后面的指令必须在前面的指令读之后写入数据,才能有正确结果; 39 | 40 | 3. WAW:写后写数据,即后面的指令必须在前面的指令写之后写入数据,才能有正确结果; 41 | 42 | ### 对于本文档实现的简单CPU 43 | 44 | 从ORI指令的实现过程可以知道: 45 | 46 | - ORI只有在流水线WB阶段才会写回寄存器,因此不存在WAW冲突; 47 | 48 | 而对于五级流水线的MIPS CPU来说: 49 | 50 | - 因为只能在ID阶段读寄存器,WB阶段写寄存器,所以不存在WAR冲突 51 | 52 | 这样一看,问题简单了许多。 -------------------------------------------------------------------------------- /7-数据相关的解决办法介绍.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | # 7-数据相关的解决办法介绍 4 | 5 | 对于数据相关,通常来说有三种解决方式: 6 | 7 | 1. 插入暂停周期(流水线暂停); 8 | 2. 数据前推(Forwarding,书上译作定向技术); 9 | 3. 编译器调度。 10 | 11 | 在这个讲义中我们只讲前两种方法。 12 | 13 | ## 流水线暂停 14 | 15 | 视觉上来说,在检测到相关问题时,在流水线中插入一些暂停周期,效果如图所示: 16 | 17 | ![1](./pic/7/1.jpg) 18 | 19 | ### 实现原理 20 | 21 | 从字面上理解来说,就是将流水线暂停,等待上一条指令得出结果(或者解决冲突)过后,流水线才会继续流动。 22 | 23 | 如第3节提到的一样,一个工人大喊“做不完了!”,然后包工头将停止传送带的运行。 24 | 25 | 这之间有两个细节: 26 | 27 | - 工人向包工头发出信号请求流水线暂停 28 | - 包工头收到信号后决定暂不暂停,并且如果暂停的话就发“停止”信号给传送带,让其停止运动 29 | 30 | 流水线暂停就是通过类似“请求暂停-开始暂停”的方式实现。具体实现之后会讲到。 31 | 32 | ### 额外 33 | 34 | 需要注意的是,流水线暂停不止可以解决相关问题。 35 | 36 | 在进行一个非常复杂的运算的时候(比如说OpenMIPS实现的除法在EX阶段需要32个时钟周期才能得出结果),它可以阻塞流水线的流动以确保结果正确。 37 | 38 | 虽然本质上还是解决的相关问题,但是流水线暂停还起着控制流水线流动的关键作用。 39 | 40 | ### 缺点 41 | 42 | 流水线暂停为流水线增加了很多空白周期,以至于每个器件不能最高效率发挥自己的能力,导致处理器性能下降。 43 | 44 | 但是值得注意的是,有的场合(比如和Load指令的数据相关)又必须请求流水线暂停,这些情况此讲义不做讲解。 45 | 46 | ## 数据前推 47 | 48 | 要避免流水线暂停导致的性能下降问题,我们就要寻求一个全新的解决方案。 49 | 50 | 大家回想一下第三节中所讲的内容就知道,视觉上来说,数据前推就如同“走后门”: 51 | 52 | ![2](./pic/7/2.jpg) 53 | 54 | ### 实现原理 55 | 56 | 数据前推将计算结果从其产生的地方直接送到其他指令需要的地方(甚至可以是所有功能单元处)以避免流水线暂停。 57 | 58 | ### 额外 59 | 60 | 需要注意的是,这个方法有一个前提: 61 | 62 | - 新的寄存器值可以在执行阶段计算出来。 63 | 64 | 如果是加载指令,那么就**不满足**这个前提,因为: 65 | 66 | - 加载指令在访存阶段才能获得最终结果。 67 | 68 | 这是一种load相关,需要进行流水线暂停。 -------------------------------------------------------------------------------- /8-ORI 的数据相关.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | # 8-ORI 的数据相关 4 | 5 | 首先,我们对ORI指令进行分析,看看它到底属于哪一种数据相关类型、为什么属于这一种数据相关类型 6 | 7 | ## ORI的数据相关解析 8 | 9 | 比如 10 | 11 | ``` 12 | ORI $1, $0, 0x1100 13 | ORI $2, $1, 0x0020 14 | ``` 15 | 16 | ![1](./pic/6/1.jpg) 17 | 18 | - 第一条ORI指令将运算结果写回寄存器1; 19 | - 第二条ORI指令需要读出寄存器1的数据拿来和立即数进行运算; 20 | - 在编程的时候,我们期望的是将第一条指令的运算结果用于第二条指令。 21 | 22 | 但是当第二条指令进行到 ID 阶段的时候: 23 | 24 | - 第一条指令还处于执行阶段; 25 | - 第一条指令要在写回阶段才会把最新的值提交到RegFile。 26 | 27 | 在这种情况下,如果第二条ORI指令继续执行的话,就会得出错误的结果,**就和之前在“3-什么是五级流水、数据前推、流水线暂停”中提到的一样**,工人B需要用C加工的螺丝刀加工目前这个产品,但是这个螺丝刀只能在E加工完成后才能用得到,此时如果继续加工的话,B工人加工出来的产品将不是合格的。 28 | 29 | 这是一个典型的RAW相关,即后面的指令必须在前一个指令写之后进行读操作,出来的结果才是正确的。 30 | 31 | ## 具体的ORI数据相关 32 | 33 | 对于 ORI 指令本身来说,它的RAW数据相关也有三种情况,而为了让大家更好的理解这三种情况,在此我们先将其归为一种单纯的情况来理解: 34 | 35 | - ORI在WB阶段最后的时钟上升沿才能把运算结果写入寄存器(参考第5节中的RegFile实现); 36 | 37 | - 在最坏的情况下,每条ORI指令之间都存在数据相关; 38 | 39 | 于是在最坏的情况下,以第一条出现的ORI指令来说,从ID阶段开始,它的EX/MEM/WB每一个阶段都有一个处于ID阶段的ORI需要对他的数据进行访问。 40 | 41 | ![1](./pic/8/1.jpg) -------------------------------------------------------------------------------- /9-1-ORI 指令数据相关的解决办法 1 - 数据前推.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 9-1-ORI 指令数据相关的解决办法 1 - 数据前推 6 | 7 | ![1](./pic/9/1.jpg) 8 | 9 | 在上一节我们说到,ORI指令也有三种数据相关的情况: 10 | 11 | 1. 相邻两条ORI指令数据相关; 12 | 2. 相隔一条ORI指令数据相关; 13 | 3. 相隔两条ORI指令数据相关。 14 | 15 | 我们再对比上面那张图看一下,其实它们也就是: 16 | 17 | 1. 位于后面的ORI指令在 ID 阶段请求读取,但是前面的ORI指令还处于 EX 阶段; 18 | 2. 位于后面的ORI指令在 ID 阶段请求读取,但是前面的ORI指令还处于 MEM 阶段; 19 | 3. 位于后面的ORI指令在 ID 阶段请求读取,但是前面的ORI指令还处于 WB 阶段(WB阶段的最后一个时钟上升沿才能把最新数值写入进RegFile)。 20 | 21 | 我们先看最简单的一种情况 22 | 23 | ## 相隔两条ORI指令数据相关 24 | 25 | 即位于后面的ORI指令在 ID 阶段请求读取,但是前面的ORI指令还处于 WB 阶段。 26 | 27 | **注意:WB阶段的最后一个时钟上升沿才能把最新数值写入进RegFile。** 28 | 29 | ![2](./pic/9/2.jpg) 30 | 31 | 我们分析一下,在这种情况下: 32 | 33 | - 时钟上升沿信号到来,指令1和指令4分别同时进入了WB和ID阶段 34 | 35 | - 此时的数据相关问题是: 36 | 37 | - 指令1的运算结果存储到了寄存器1中 38 | - 指令4从寄存器1中取出指令1的运算结果 39 | - 但是指令1此时还没有把结果写回寄存器1中 40 | 41 | - 指令1和指令4**访问的都是同一个寄存器** 42 | 43 | - 指令1完成了EX阶段到达了WB阶段,此时已经给出了**“写寄存器”信号**和需要写入的寄存器的**地址信号** 44 | 45 | 46 | 47 | ### 解决办法 48 | 49 | 这种情况,我们只需要在寄存器堆 RegFile 模块上动手脚就行了。 50 | 51 | 我们看看第5小节中提到的: 52 | 53 | ```verilog 54 | // 来自第5小结中,RegFile的代码 55 | // --------------------------- 56 | 57 | // 读端口1 的读操作 58 | always @ (*) begin 59 | // 如果重置则读出 32'h0 60 | if(rst == `RstEnable) begin 61 | rdata1 <= `ZeroWord; 62 | // 如果读0号寄存器,也只读出0 63 | end else if(raddr1 == `RegNumLog2'h0) begin 64 | rdata1 <= `ZeroWord; 65 | // 当读地址与写地址相同,且写使能,且端口1读使能,则要把写入的数据直接读出来 66 | // 数据前推的实现,后面会提及 67 | end else if((raddr1 == waddr) && (we == `WriteEnable) 68 | && (re1 == `ReadEnable)) begin 69 | rdata1 <= wdata; 70 | // 否则读取相应寄存器单元 71 | end else if(re1 == `ReadEnable) begin 72 | rdata1 <= regs[raddr1]; 73 | // 如果第一个读端口不能使用时,输出0 74 | end else begin 75 | rdata1 <= `ZeroWord; 76 | end 77 | end 78 | ``` 79 | 80 | 注意有一段代码: 81 | 82 | ```verilog 83 | // 当读地址与写地址相同,且写使能,且端口1读使能,则要把写入的数据直接读出来 84 | // 数据前推的实现,后面会提及 85 | end else if((raddr1 == waddr) && (we == `WriteEnable) 86 | && (re1 == `ReadEnable)) begin 87 | rdata1 <= wdata; 88 | // 否则读取相应寄存器单元 89 | end 90 | ``` 91 | 92 | 这段代码说的是,如果在一个时刻(注意,RegFile模块的读逻辑是组合逻辑)**写地址**和**读地址**是一模一样的话,那么RegFile读出来的数据就是要写入的数据。 93 | 94 | 我们深入理解一下: 95 | 96 | ![2-2](./pic/9/2.jpg) 97 | 98 | 1. 指令1现在位于WB阶段,**写使能信号**以及**写地址**已经给出,等待下一个时钟上升沿的到来以写入RegFile(RegFile的写入逻辑是时序逻辑) 99 | 2. 指令4现在位于ID阶段,**读使能信号**以及**读地址**已经给出,RegFile实时根据读地址读出相应寄存器中的数据 100 | 3. 指令1写地址指向 1号寄存器 101 | 4. 指令4读地址指向 1号寄存器 102 | 5. 指令1要把运算结果写入 1号寄存器 103 | 6. 指令4要从 1号寄存器 读指令1的执行结果,用于自己的计算 104 | 105 | 于是我们就增加刚刚的判断: 106 | 107 | ```verilog 108 | // 当读地址与写地址相同,且写使能,且端口1读使能,则要把写入的数据直接读出来 109 | // 数据前推的实现,后面会提及 110 | end else if((raddr1 == waddr) && (we == `WriteEnable) 111 | && (re1 == `ReadEnable)) begin 112 | rdata1 <= wdata; 113 | end 114 | ``` 115 | 116 | 意思就是,(在**相隔两条ORI指令数据相关**这种情况下)后面的指令的ID阶段需要用到前面的指令的运行结果的话(此时前面的指令运行结果已经出来了,但是还没有写回寄存器),我们不需要等前一条指令先写回,而是直接从前一条指令那儿**把数据”通过后门“拿过来用**,以此来避免流水线暂停。 117 | 118 | 这样,在下一个时钟周期到来的时候,指令1完成了它的任务,而指令4也正确地进入了EX阶段继续它的任务。 119 | 120 | 这种情况在所有的三种情况中是最特殊的,因为发生数据相关的时候,两条指令都在请求寄存器操作,所以我们不需要添加额外的线路,接下来我们讨论更一般的情况。 121 | 122 | ## 相邻两条以及相隔一条ORI指令数据相关 123 | 124 | ![3](./pic/9/3.jpg) 125 | 126 | 和相隔两条指令的情况很类似: 127 | 128 | - 指令2在ID阶段的时候请求指令1的执行结果,但是指令1位于EX阶段 129 | - 指令3在ID阶段的时候请求指令1的执行结果,但是指令1位于MEM阶段 130 | 131 | ### 解决办法 132 | 133 | 我们把剩下的两种情况合并到一起写。 134 | 135 | **首先大家必须记得在第7节中我们已经提到的一点:** 136 | 137 | > ### 额外 138 | > 139 | > 需要注意的是,这个方法有一个前提: 140 | > 141 | > - 新的寄存器值可以在执行阶段计算出来。 142 | > 143 | 144 | 和前面一样,我们只需要一个”后门“把数据直接送给请求数据的指令即可,就和上面的图一样: 145 | 146 | ![3-2](./pic/9/3.jpg) 147 | 148 | - EX阶段的数据前推到ID阶段 149 | - MEM阶段的数据前推到ID阶段 150 | 151 | ### 开始修改 152 | 153 | 为了实现这两个情况的数据前推,我们需要对之前已经写好的ORI原始结构进行修改。 154 | 155 | ![4](./pic/9/4.jpg) 156 | 157 | - 把EX阶段的数据前推到ID阶段,需要在ID模块上新增接口 158 | - 把MEM阶段的数据前推到ID阶段,需要在ID模块上新增接口 159 | 160 | ![5](./pic/9/5.jpg) 161 | 162 | 修改过后的ID模块会根据送入的信息进行综合判断,给出最后需要参与运算的操作数。 163 | 164 | 修改过后的ID模块如下(注意,**相隔两条ORI指令数据相关**修改的是RegFile模块): 165 | 166 | ```verilog 167 | `include "defines.v" 168 | 169 | module id( 170 | 171 | input wire rst, 172 | input wire[`InstAddrBus] pc_i, 173 | input wire[`InstBus] inst_i, 174 | 175 | // EX阶段推过来的数据 176 | input wire ex_wreg_i, 177 | input wire[`RegBus] ex_wdata_i, 178 | input wire[`RegAddrBus] ex_wd_i, 179 | 180 | // MEM阶段推过来的数据 181 | input wire mem_wreg_i, 182 | input wire[`RegBus] mem_wdata_i, 183 | input wire[`RegAddrBus] mem_wd_i, 184 | 185 | // 从RegFile中获取的数据 186 | input wire[`RegBus] reg1_data_i, 187 | input wire[`RegBus] reg2_data_i, 188 | 189 | 190 | output reg reg1_read_o, 191 | output reg reg2_read_o, 192 | output reg[`RegAddrBus] reg1_addr_o, 193 | output reg[`RegAddrBus] reg2_addr_o, 194 | 195 | 196 | output reg[`AluOpBus] aluop_o, 197 | output reg[`AluSelBus] alusel_o, 198 | output reg[`RegBus] reg1_o, 199 | output reg[`RegBus] reg2_o, 200 | output reg[`RegAddrBus] wd_o, 201 | output reg wreg_o 202 | ); 203 | 204 | wire[5:0] op = inst_i[31:26]; 205 | wire[4:0] op2 = inst_i[10:6]; 206 | wire[5:0] op3 = inst_i[5:0]; 207 | wire[4:0] op4 = inst_i[20:16]; 208 | reg[`RegBus] imm; 209 | reg instvalid; 210 | 211 | always @ (*) begin 212 | if (rst == `RstEnable) begin 213 | aluop_o <= `EXE_NOP_OP; 214 | alusel_o <= `EXE_RES_NOP; 215 | wd_o <= `NOPRegAddr; 216 | wreg_o <= `WriteDisable; 217 | instvalid <= `InstValid; 218 | reg1_read_o <= 1'b0; 219 | reg2_read_o <= 1'b0; 220 | reg1_addr_o <= `NOPRegAddr; 221 | reg2_addr_o <= `NOPRegAddr; 222 | imm <= 32'h0; 223 | end else begin 224 | aluop_o <= `EXE_NOP_OP; 225 | alusel_o <= `EXE_RES_NOP; 226 | wd_o <= inst_i[15:11]; 227 | wreg_o <= `WriteDisable; 228 | instvalid <= `InstInvalid; 229 | reg1_read_o <= 1'b0; 230 | reg2_read_o <= 1'b0; 231 | reg1_addr_o <= inst_i[25:21]; 232 | reg2_addr_o <= inst_i[20:16]; 233 | imm <= `ZeroWord; 234 | case (op) 235 | `EXE_ORI: begin //ORIָ 236 | wreg_o <= `WriteEnable; 237 | aluop_o <= `EXE_OR_OP; 238 | alusel_o <= `EXE_RES_LOGIC; 239 | reg1_read_o <= 1'b1; 240 | reg2_read_o <= 1'b0; 241 | imm <= {16'h0, inst_i[15:0]}; 242 | wd_o <= inst_i[20:16]; 243 | instvalid <= `InstValid; 244 | end 245 | default: begin 246 | end 247 | endcase //case op 248 | end //if 249 | end //always 250 | 251 | // 读端口1 252 | // 对ID/EX模块输出的数据在之前的基础上增加了两种情况: 253 | always @ (*) begin 254 | if(rst == `RstEnable) begin 255 | reg1_o <= `ZeroWord; 256 | // 如果(前面的指令)EX阶段要写入的寄存器的地址 == (后面的指令)ID阶段要读取的寄存器的地址 257 | end else if((reg1_read_o == 1'b1) && (ex_wreg_i == 1'b1) 258 | && (ex_wd_i == reg1_addr_o)) begin 259 | reg1_o <= ex_wdata_i; 260 | // 如果(前面的指令)MEM阶段要写入的寄存器的地址 == (后面的指令)ID阶段要读取的寄存器的地址 261 | end else if((reg1_read_o == 1'b1) && (mem_wreg_i == 1'b1) 262 | && (mem_wd_i == reg1_addr_o)) begin 263 | reg1_o <= mem_wdata_i; 264 | end else if(reg1_read_o == 1'b1) begin 265 | reg1_o <= reg1_data_i; 266 | end else if(reg1_read_o == 1'b0) begin 267 | reg1_o <= imm; 268 | end else begin 269 | reg1_o <= `ZeroWord; 270 | end 271 | end 272 | 273 | // 读端口2 的逻辑和上面 读端口1 的逻辑类似 274 | always @ (*) begin 275 | if(rst == `RstEnable) begin 276 | reg2_o <= `ZeroWord; 277 | end else if((reg2_read_o == 1'b1) && (ex_wreg_i == 1'b1) 278 | && (ex_wd_i == reg2_addr_o)) begin 279 | reg2_o <= ex_wdata_i; 280 | end else if((reg2_read_o == 1'b1) && (mem_wreg_i == 1'b1) 281 | && (mem_wd_i == reg2_addr_o)) begin 282 | reg2_o <= mem_wdata_i; 283 | end else if(reg2_read_o == 1'b1) begin 284 | reg2_o <= reg2_data_i; 285 | end else if(reg2_read_o == 1'b0) begin 286 | reg2_o <= imm; 287 | end else begin 288 | reg2_o <= `ZeroWord; 289 | end 290 | end 291 | 292 | endmodule 293 | ``` 294 | 295 | 至此,我们已经用**数据前推**解决了ORI的数据相关问题! 296 | 297 | # 验证 298 | 299 | 我们用这个程序进行验证: 300 | 301 | ```assembly 302 | .org 0x0 303 | .global _start 304 | .set noat 305 | _start: 306 | ori $1,$0,0x1100 # $1 = $0 | 0x1100 = 0x1100 307 | ori $1,$1,0x0020 # $1 = $1 | 0x0020 = 0x1120 308 | ori $1,$1,0x4400 # $1 = $1 | 0x4400 = 0x5520 309 | ori $1,$1,0x0044 # $1 = $1 | 0x0044 = 0x5564 310 | ``` 311 | 312 | 机器码为: 313 | 314 | ``` 315 | 34011100 316 | 34210020 317 | 34214400 318 | 34210044 319 | ``` 320 | 321 | 我们在仿真的时候只需要关注 寄存器1 的值即可 322 | 323 | # 回顾 324 | 325 | ## 原始的ORI结构图 326 | 327 | ![c5-1](./pic/5/5.jpg) 328 | 329 | ## 增加了数据前推的ORI的结构图 330 | 331 | ![4-sad](./pic/9/4.jpg) 332 | 333 | ## 提示 334 | 335 | 可以发现,EX阶段和MEM阶段都各自多了三条数据通路,分别把自己的数据前推到了ID阶段。 -------------------------------------------------------------------------------- /9-2-ORI 指令数据相关的解决办法 2 - 流水线暂停.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 9-2-ORI 指令数据相关的解决办法 2 - 流水线暂停 6 | 7 | ## 注意事项 8 | 9 | 流水线暂停位于《自己动手写CPU》第七章,里面已经实现了很多东西,所以这篇文档的代码和之前的不兼容,于是只截取重点部分给大家讲解。 10 | 11 | 不过因为大家学习本文档的初衷是理解五级流水如何实现,所以代码并不重要,重要的是理解思维。 12 | 13 | ## 简介 14 | 15 | ![intro](./pic/7/1.jpg) 16 | 17 | 18 | 19 | 前面说过,视觉上来说,流水线暂停其实是在检测到流水线相关问题时,在流水线中插入一些暂停周期,等待前面的指令完全执行完毕后再恢复流水线。 20 | 21 | 对于相邻两条ORI产生数据相关时: 22 | 23 | - 前一条指令在WB阶段的最后一个时钟周期把数据写入RegFile 24 | - 后一条指令在ID阶段请求一个正确的值 25 | 26 | 所以理论上,我们要**插入三个暂停周期,即将第二条指令的ID阶段推迟到第一条指令的WB阶段后**,但是在此之前,我们已经在RegFile里面实现了数据前推: 27 | 28 | ```verilog 29 | // 当读地址与写地址相同,且写使能,且端口1读使能,则要把写入的数据直接读出来 30 | // 数据前推的实现,后面会提及 31 | end else if((raddr1 == waddr) && (we == `WriteEnable) 32 | && (re1 == `ReadEnable)) begin 33 | rdata1 <= wdata; 34 | // 否则读取相应寄存器单元 35 | end 36 | ``` 37 | 38 | 所以我们只需要**插入两个暂停周期,将第二条指令的ID阶段推迟到第一条指令的WB阶段**,其实这是一个“带数据前推的流水线暂停”。 39 | 40 | ## 实现 41 | 42 | 一种直观的实现方式是: 43 | 44 | - 保持PC的值不变 45 | - 保持流水线各个阶段的寄存器不变 46 | 47 | 我们采用一个改进的暂停方式: 48 | 49 | - 保持PC的值不变 50 | - 保持流水线第n阶段以及之前的各个阶段的寄存器不变 51 | - 第n阶段后面的指令继续运行 52 | 53 | 比如EX阶段请求暂停,则保持IF/ID/EX阶段的流水线寄存器的值不变,而处于MEM/WB阶段的指令继续执行。 54 | 55 | 为此我们要新增一个模块,这个模块不属于流水线的任何一个阶段。 56 | 57 | ### 新增CTRL模块 58 | 59 | ![6](./pic/9/6.jpg) 60 | 61 | CTRL模块的输入来自于ID、EX模块的请求暂停信号 stallreq。CTRL模块会对暂停请求信号进行判断,然后输出流水线暂停信号stall。看图可知stall输出到PC、IF/ID、ID/EX、EX/MEM、MEM/WB等模块,从而控制PC值以及各个阶段的流水线寄存器。 62 | 63 | ### CTRL模块的实现 64 | 65 | CTRL模块的接口如图所示: 66 | 67 | ![7](./pic/9/7.jpg) 68 | 69 | 其中stall信号是一个宽度为6的信号,用每位的数值(0或者1)来给出是否暂停的信号。 70 | 71 | 代码如下: 72 | 73 | ```verilog 74 | `include "defines.v" 75 | 76 | module ctrl( 77 | 78 | input wire rst, 79 | 80 | input wire stallreq_from_id, // 来自ID阶段的暂停请求 81 | input wire stallreq_from_ex, // 来自EX阶段的暂停请求 82 | output reg[5:0] stall 83 | 84 | ); 85 | 86 | 87 | // 1表示暂停,0表示继续执行 88 | always @ (*) begin 89 | if(rst == `RstEnable) begin 90 | stall <= 6'b000000; 91 | end else if(stallreq_from_ex == `Stop) begin 92 | stall <= 6'b001111; 93 | end else if(stallreq_from_id == `Stop) begin 94 | stall <= 6'b000111; 95 | end else begin 96 | stall <= 6'b000000; 97 | end //if 98 | end //always 99 | 100 | 101 | endmodule 102 | ``` 103 | 104 | ### 修改IF阶段 105 | 106 | PC模块的代码如下: 107 | 108 | ```verilog 109 | always @ (posedge clk) begin 110 | if (ce == `ChipDisable) begin 111 | pc <= 32'h00000000; 112 | // 如果IF阶段不需要暂停,则PC值继续增加 113 | end else if(stall[0] == `NoStop) begin 114 | pc <= pc + 4'h4; 115 | end 116 | end 117 | ``` 118 | 119 | 修改IF/ID模块: 120 | 121 | ```verilog 122 | always @ (posedge clk) begin 123 | if (rst == `RstEnable) begin 124 | id_pc <= `ZeroWord; 125 | id_inst <= `ZeroWord; 126 | // 当IF阶段暂停且ID阶段继续的时候,用空指令作为下一个周期进入译码阶段的指令 127 | end else if(stall[1] == `Stop && stall[2] == `NoStop) begin 128 | id_pc <= `ZeroWord; 129 | id_inst <= `ZeroWord; 130 | // 否则继续执行 131 | end else if(stall[1] == `NoStop) begin 132 | id_pc <= if_pc; 133 | id_inst <= if_inst; 134 | end 135 | end 136 | ``` 137 | 138 | ### 修改ID阶段 139 | 140 | ID模块可以请求流水线暂停,采用流水线暂停解决ORI指令数据冲突就需要在这个地方发出流水线暂停请求,但我们建议采用**数据前推**的方式解决流水线数据冲突问题,我们给出具体思路: 141 | 142 | ```verilog 143 | if(与前面指令数据相关) begin 144 | stallreq_from_id <= `Stop; 145 | end 146 | ``` 147 | 148 | 那如何判断与前面的指令数据相关呢?我们给出两种思路: 149 | 150 | - 和数据前推类似,从EX和MEM段查看是否有读写相同寄存器的情况发生 151 | - 在ID模块增加寄存器,存储前两条指令的写寄存器地址,用于判断是否发生冲突 152 | 153 | 对于第一种,其实已经和数据前推类似,这里感觉“多此一举” 154 | 155 | 对于第二种,我们可以说**强烈不推荐**,因为这增加了ID段的“负担”,而且不利于整个CPU的“鲁棒性” 156 | 157 | > 注意: 158 | > 159 | > 对于Load指令的数据相关问题,我们只能用流水线暂停完成(大家可以思考为什么?) 160 | 161 | 修改ID/EX模块: 162 | 163 | ```verilog 164 | always @ (posedge clk) begin 165 | if (rst == `RstEnable) begin 166 | ex_aluop <= `EXE_NOP_OP; 167 | ex_alusel <= `EXE_RES_NOP; 168 | ex_reg1 <= `ZeroWord; 169 | ex_reg2 <= `ZeroWord; 170 | ex_wd <= `NOPRegAddr; 171 | ex_wreg <= `WriteDisable; 172 | // 如果ID阶段暂停而且EX阶段继续执行,则给EX阶段传递空操作 173 | end else if(stall[2] == `Stop && stall[3] == `NoStop) begin 174 | ex_aluop <= `EXE_NOP_OP; 175 | ex_alusel <= `EXE_RES_NOP; 176 | ex_reg1 <= `ZeroWord; 177 | ex_reg2 <= `ZeroWord; 178 | ex_wd <= `NOPRegAddr; 179 | ex_wreg <= `WriteDisable; 180 | // 否则继续执行 181 | end else if(stall[2] == `NoStop) begin 182 | ex_aluop <= id_aluop; 183 | ex_alusel <= id_alusel; 184 | ex_reg1 <= id_reg1; 185 | ex_reg2 <= id_reg2; 186 | ex_wd <= id_wd; 187 | ex_wreg <= id_wreg; 188 | end 189 | end 190 | ``` 191 | 192 | ### 修改EX阶段 193 | 194 | EX模块可以请求暂停,但是由于目前ORI指令不会在EX阶段请求暂停(感兴趣的同学自行学习),所以忽略EX模块的修改。 195 | 196 | 修改EX/MEM模块: 197 | 198 | ```verilog 199 | always @ (posedge clk) begin 200 | if(rst == `RstEnable) begin 201 | mem_wd <= `NOPRegAddr; 202 | mem_wreg <= `WriteDisable; 203 | mem_wdata <= `ZeroWord; 204 | // 如果EX阶段暂停而且MEM阶段继续执行,则给MEM阶段传递空操作 205 | end else if(stall[3] == `Stop && stall[4] == `NoStop) begin 206 | mem_wd <= `NOPRegAddr; 207 | mem_wreg <= `WriteDisable; 208 | mem_wdata <= `ZeroWord; 209 | // 否则继续执行 210 | end else if(stall[3] == `NoStop) begin 211 | mem_wd <= ex_wd; 212 | mem_wreg <= ex_wreg; 213 | mem_wdata <= ex_wdata; 214 | end //if 215 | end //always 216 | 217 | 218 | endmodule 219 | ``` 220 | 221 | ### 修改MEM阶段 222 | 223 | 此阶段只需要修改MEM/WB模块: 224 | 225 | ```verilog 226 | always @ (posedge clk) begin 227 | if(rst == `RstEnable) begin 228 | wb_wd <= `NOPRegAddr; 229 | wb_wreg <= `WriteDisable; 230 | wb_wdata <= `ZeroWord; 231 | // 如果MEM阶段暂停而且WB阶段继续执行,则给WB阶段传递空操作 232 | end else if(stall[4] == `Stop && stall[5] == `NoStop) begin 233 | wb_wd <= `NOPRegAddr; 234 | wb_wreg <= `WriteDisable; 235 | wb_wdata <= `ZeroWord; 236 | // 否则继续执行 237 | end else if(stall[4] == `NoStop) begin 238 | wb_wd <= mem_wd; 239 | wb_wreg <= mem_wreg; 240 | wb_wdata <= mem_wdata; 241 | end //if 242 | end //always 243 | ``` 244 | 245 | 至此,流水线暂停已经实现! -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HITwh NSCSCC Team | 哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组 2 | 3 | [TOC] 4 | 5 | # 知识版权 Copyright 6 | 7 | 文档:版权 ® [哈尔滨工业大学(威海)全国大学生计算机系统能力培养大赛小组](https://github.com/hitwh-nscscc) 2019 8 | 9 | Documents: Copyright ® [HITwh NSCSCC Team](https://github.com/hitwh-nscscc) 2019 10 | 11 | ## 版权许可 - 中文 12 | 13 | 本作品文档采用知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。 14 | 15 | 要查看该许可协议,可访问 http://creativecommons.org/licenses/by-nc-sa/4.0/ 或者写信到 Creative Commons, PO Box 1866, Mountain View, CA 94042, USA。 16 | 17 | ## Copyright License - English 18 | 19 | Documents containing in this work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. 20 | 21 | To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. 22 | 23 | 24 | 25 | # 跟我一步一步实现简单的五级流水MIPS 26 | 27 | 作为体系结构实验课前的一次讲解,本系列文档参考《自己动手写 CPU》一书中的实现步骤,将体系结构课程教授的知识具体化,让同学们完全靠自己实现一个简单的五级流水架构以深入理解课本中的理论知识,将其运用到实际,并最终独立地完成此次实验。 28 | 29 | ## 基本提纲 30 | 31 | 本文档将用以下的顺序,层层深入,一步一步指导同学们实现一个**最简单的(ORI指令)、带数据前推及流水线暂停的32位静态五级流水MIPS**,之后大家举一反三来完成这次体系结构实验: 32 | 33 | 1. 单周期、多周期和流水线处理器; 34 | 2. 浅析计组课设中制作的CPU; 35 | 3. 什么是五级流水、数据前推、流水线暂停; 36 | 4. 一个静态五级流水MIPS的最基本架构; 37 | 5. 第一条指令 ORI 的实现: 38 | 1. 一个原始的五级流水线结构; 39 | 2. IF / ID / EX / MEM / WB 阶段的分别实现; 40 | 3. VIVADO 行为仿真; 41 | 4. 再次拿出 5.1 提及的原始的五级流水线结构,回顾所学内容。 42 | 6. 流水线相关问题; 43 | 7. 数据相关的解决办法介绍: 44 | - 流水线暂停; 45 | - 数据前推; 46 | - 编译器调度(仅提及); 47 | 8. ORI 的数据相关; 48 | 9. **ORI 指令数据相关的解决办法 1 - 数据前推:** 49 | - 针对 ORI 指令的数据前推的原理; 50 | - 修改相应模块; 51 | - VIVADO 行为仿真; 52 | - 修改后的五级流水线结构(与原始的五级流水线结构对比); 53 | 10. **ORI 指令数据相关的解决办法 2 - 流水线暂停:** 54 | - 针对 ORI 指令的流水线暂停的原理; 55 | - 修改相应模块; 56 | - 修改后的五级流水线结构(与原始的五级流水线结构对比); 57 | 58 | 11. (可选)MIPS 交叉编译环境的搭建指南。 59 | 60 | ## 参考资料 61 | 62 | 《自己动手写 CPU》 - 雷思磊 63 | -------------------------------------------------------------------------------- /chapter09_指令流水线.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/chapter09_指令流水线.ppt -------------------------------------------------------------------------------- /pic/1/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/1/1.jpg -------------------------------------------------------------------------------- /pic/2/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/2/1.jpg -------------------------------------------------------------------------------- /pic/3/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/3/1.png -------------------------------------------------------------------------------- /pic/4/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/4/1.jpg -------------------------------------------------------------------------------- /pic/5/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/1.jpg -------------------------------------------------------------------------------- /pic/5/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/10.jpg -------------------------------------------------------------------------------- /pic/5/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/11.jpg -------------------------------------------------------------------------------- /pic/5/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/12.jpg -------------------------------------------------------------------------------- /pic/5/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/13.jpg -------------------------------------------------------------------------------- /pic/5/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/14.jpg -------------------------------------------------------------------------------- /pic/5/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/15.jpg -------------------------------------------------------------------------------- /pic/5/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/16.jpg -------------------------------------------------------------------------------- /pic/5/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/17.jpg -------------------------------------------------------------------------------- /pic/5/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/2.jpg -------------------------------------------------------------------------------- /pic/5/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/3.jpg -------------------------------------------------------------------------------- /pic/5/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/4.jpg -------------------------------------------------------------------------------- /pic/5/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/5.jpg -------------------------------------------------------------------------------- /pic/5/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/6.jpg -------------------------------------------------------------------------------- /pic/5/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/7.jpg -------------------------------------------------------------------------------- /pic/5/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/8.jpg -------------------------------------------------------------------------------- /pic/5/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/5/9.jpg -------------------------------------------------------------------------------- /pic/6/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/6/1.jpg -------------------------------------------------------------------------------- /pic/7/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/7/1.jpg -------------------------------------------------------------------------------- /pic/7/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/7/2.jpg -------------------------------------------------------------------------------- /pic/8/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/8/1.jpg -------------------------------------------------------------------------------- /pic/9/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/9/1.jpg -------------------------------------------------------------------------------- /pic/9/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/9/2.jpg -------------------------------------------------------------------------------- /pic/9/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/9/3.jpg -------------------------------------------------------------------------------- /pic/9/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/9/4.jpg -------------------------------------------------------------------------------- /pic/9/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/9/5.jpg -------------------------------------------------------------------------------- /pic/9/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/9/6.jpg -------------------------------------------------------------------------------- /pic/9/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitwh-nscscc/simple-5stage-pipeline-MIPS-imple/3d984aa2f52fd17be9caa85246996b66cbdc67af/pic/9/7.jpg --------------------------------------------------------------------------------