将陆续上传本人写的新书《自己动手写CPU》,今天是第28篇。我尽量每周四篇

China-pub的预售地址例如以下(有文件夹、内容简单介绍、前言):

http://product.china-pub.com/3804025

亚马逊的预售地址例如以下,欢迎大家围观呵。

http://www.amazon.cn/dp/b00mqkrlg8/ref=cm_sw_r_si_dp_5kq8tb1gyhja4

7.5 流水线暂停机制的设计与实现

7.5.1 流水线暂停机制设计

由于OpenMIPS设计乘累加、乘累减、除法指令在流水线运行阶段占用多个时钟周期,因此须要暂停流水线,以等待这些多周期指令运行完成。一种直观的实现方法是:要暂停流水线,仅仅需保持取指令地址PC的值不变。同一时候保持流水线各个阶段的寄存器(也就是IF/ID、ID/EX、EX/MEM、MEM/WB模块的输出)不变。

OpenMIPS採用的是一种改进的方法:假如位于流水线第n阶段的指令须要多个时钟周期,进而请求流水线暂停,那么需保持取指令地址PC的值不变。同一时候保持流水线第n阶段、第n阶段之前的各个阶段的寄存器不变,而第n阶段后面的指令继续执行。

比方:流水线执行阶段的指令请求流水线暂停,那么保持PC不变,同一时候保持取指、译码、执行阶段的寄存器不变。可是能够同意訪存、回写阶段的指令继续执行。

为此,设计加入CTRL模块。其作用是接收各个阶段传递过来的流水线暂停请求信号,从而控制流水线各个阶段的执行。

为了实现流水线暂停机制,对系统结构做如图7-10所看到的的改动。

CTRL模块的输入来自ID、EX模块的请求暂停信号stallreq。对于OpenMIPS教学版而言,仅仅有译码、运行阶段可能会有暂停请求。取指、訪存阶段都没有暂停请求。由于指令读取、数据存储器的读写操作都能够在一个时钟周期完毕。

CTRL模块对暂停请求信号进行推断,然后输出流水线暂停信号stall。从图7-10中可知,stall输出到PC、IF/ID、ID/EX、EX/MEM、MEM/WB等模块。从而控制PC的值,以及流水线各个阶段的寄存器。

7.5.2 流水线暂停机制实现

      1、CTRL模块的实现

CTRL模块的接口如图7-10中所看到的,各接口作用如表7-1所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVpc2hhbmd3ZW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

读者须要注意:输出信号stall是一个宽度为6的信号。其含义例如以下。

  • stall[0]表示取指地址PC是否保持不变。为1表示保持不变
  • stall[1]表示流水线取指阶段是否暂停,为1表示暂停
  • stall[2]表示流水线译码阶段是否暂停。为1表示暂停
  • stall[3]表示流水线运行阶段是否暂停,为1表示暂停
  • stall[4]表示流水线訪存阶段是否暂停,为1表示暂停
  • stall[5]表示流水线回写阶段是否暂停,为1表示暂停

CTRL模块的代码例如以下。源文件是本书附带光盘Code\Chapter7_2文件夹下的ctrl.v。

module ctrl(

	input wire		rst,
input wire stallreq_from_id, // 来自译码阶段的暂停请求
input wire stallreq_from_ex, // 来自运行阶段的暂停请求
output reg[5:0] stall ); always @ (*) begin
if(rst == `RstEnable) begin
stall <= 6'b000000;
end else if(stallreq_from_ex == `Stop) begin
stall <= 6'b001111;
end else if(stallreq_from_id == `Stop) begin
stall <= 6'b000111;
end else begin
stall <= 6'b000000;
end
end endmodule 当中宏定义Stop在defines.v中定义。例如以下:
`define Stop 1'b1 // 流水线暂停
`define NoStop 1'b0 // 流水线继续

能够从下面三点理解。

(1)当处于流水线运行阶段的指令请求暂停时(即stallreq_from_ex等于Stop),依照OpenMIPS流水线暂停机制的设计。要求取指、译码、运行阶段暂停。而訪存、回写阶段继续,所以设置stall为6'b001111。

(2)当处于流水线译码阶段的指令请求暂停时(即stallreq_from_id等于Stop),依照OpenMIPS流水线暂停机制的设计。要求取指、译码阶段暂停,而运行、訪存、回写阶段继续,所以设置stall为6'b000111。

(3)其余情况下。设置stall为6'b000000,表示不暂停流水线。

      2、改动取指阶段

(1)改动PC模块

从图7-10中可知,PC模块新添加了一个输入信号stall,其值就是CTRL模块的接口stall。改动取指阶段PC模块的代码例如以下,当中改动的代码使用加粗、斜体标识。

源文件是本书附带光盘Code\Chapter7_2文件夹下的pc_reg.v。

module pc_reg(
input wire clk,
input wire rst,
input wire[5:0] stall, // 来自控制模块CTRL
output reg[`InstAddrBus] pc ,
output reg ce
); always @ (posedge clk) begin
if (rst == `RstEnable) begin
ce <= `ChipDisable;
end else begin
ce <= `ChipEnable;
end
end // 当stall[0]为NoStop时,pc加4,否则,保持pc不变
always @ (posedge clk) begin
if (ce == `ChipDisable) begin
pc <= 32'h00000000;
end else if(stall[0] == `NoStop) begin
pc <= pc + 4'h4;
end
end endmodule

(2)改动IF/ID模块

參考图7-10,IF/ID模块也新增了一个输入信号stall,主要改动例如以下,改动的代码使用加粗、斜体标识。完整代码參考本书附带光盘Code\Chapter7_2文件夹下的if_id.v文件。

module if_id(
......
input wire[5:0] stall,
); //(1)当stall[1]为Stop,stall[2]为NoStop时。表示取指阶段暂停,
// 而译码阶段继续,所以使用空指令作为下一个周期进入译码阶段的指令。
//(2)当stall[1]为NoStop时,取指阶段继续。取得的指令进入译码阶段。 //(3)其余情况下。保持译码阶段的寄存器id_pc、id_inst不变。
always @ (posedge clk) begin
if (rst == `RstEnable) begin
id_pc <= `ZeroWord;
id_inst <= `ZeroWord;
end else if(stall[1] == `Stop && stall[2] == `NoStop) begin
id_pc <= `ZeroWord;
id_inst <= `ZeroWord;
end else if(stall[1] == `NoStop) begin
id_pc <= if_pc;
id_inst <= if_inst;
end
end endmodule

      3、改动译码阶段

(1)改动ID模块

參考图7-10,ID模块新增了一个输出信号stallreq,在实现载入、存储指令的时候会给该信号赋值,眼下临时设置这个输出就是NoStop,详细代码不再给出。读者能够參考本书附带光盘Code\Chapter7_2文件夹下的id.v文件。

(2)改动ID/EX模块

參考图7-10,ID/EX模块新增了一个输入信号stall,主要改动例如以下,改动的代码使用加粗、斜体标识。完整代码位于本书附带光盘Code\Chapter7_2文件夹下的id_ex.v文件。

module id_ex(
...... //来自控制模块的信息
input wire[5:0] stall, ......
);
//(1)当stall[2]为Stop,stall[3]为NoStop时。表示译码阶段暂停,
// 而运行阶段继续,所以使用空指令作为下一个周期进入运行阶段的指令。 //(2)当stall[2]为NoStop时。译码阶段继续。译码后的指令进入运行阶段。 //(3)其余情况下,保持运行阶段的寄存器ex_aluop、ex_alusel、ex_reg1、
// ex_reg2、ex_wd、ex_wreg不变。 always @ (posedge clk) begin
if (rst == `RstEnable) begin
......
end else if(stall[2] == `Stop && stall[3] == `NoStop) begin
ex_aluop <= `EXE_NOP_OP;
ex_alusel <= `EXE_RES_NOP;
ex_reg1 <= `ZeroWord;
ex_reg2 <= `ZeroWord;
ex_wd <= `NOPRegAddr;
ex_wreg <= `WriteDisable;
end else if(stall[2] == `NoStop) begin
ex_aluop <= id_aluop;
ex_alusel <= id_alusel;
ex_reg1 <= id_reg1;
ex_reg2 <= id_reg2;
ex_wd <= id_wd;
ex_wreg <= id_wreg;
end
end endmodule

      4、改动运行阶段

(1)改动EX模块

參考图7-10,EX模块新增了一个输出信号stallreq_from_ex,在本章后面实现乘累加、乘累减、除法指令的时候会给该信号赋值。

(2)改动EX/MEM模块

參考图7-10,EX/MEM模块新增了一个输入信号stall,主要改动例如以下。改动的代码使用加粗、斜体标识。完整代码位于本书附带光盘Code\Chapter7_2文件夹下的ex_mem.v文件。

module ex_mem(
...... //来自控制模块的信息
input wire[5:0] stall, ......
);
//(1)当stall[3]为Stop,stall[4]为NoStop时,表示运行阶段暂停。
// 而訪存阶段继续,所以使用空指令作为下一个周期进入訪存阶段的指令。 //(2)当stall[3]为NoStop时,运行阶段继续,运行后的指令进入訪存阶段。
//(3)其余情况下。保持訪存阶段的寄存器mem_wb、mem_wreg、mwm_wdata、
// mem_hi、mem_lo、mem_whilo不变。
always @ (posedge clk) begin
if(rst == `RstEnable) begin
......
end else if(stall[3] == `Stop && stall[4] == `NoStop) begin
mem_wd <= `NOPRegAddr;
mem_wreg <= `WriteDisable;
mem_wdata <= `ZeroWord;
mem_hi <= `ZeroWord;
mem_lo <= `ZeroWord;
mem_whilo <= `WriteDisable;
end else if(stall[3] == `NoStop) begin
mem_wd <= ex_wd;
mem_wreg <= ex_wreg;
mem_wdata <= ex_wdata;
mem_hi <= ex_hi;
mem_lo <= ex_lo;
mem_whilo <= ex_whilo;
end //if
end //always
endmodule

      5、改动訪存阶段

訪存阶段仅仅要改动MEM/WB模块。參考图7-10,MEM/WB模块也新增了一个输入信号stall。主要改动例如以下,改动的代码使用加粗、斜体标识。

完整代码位于本书附带光盘Code\Chapter7_2文件夹下的mem_wb.v文件。

module mem_wb(
...... //来自控制模块的信息
input wire[5:0] stall, ......
);
//(1)当stall[4]为Stop。stall[5]为NoStop时,表示訪存阶段暂停,
// 而回写阶段继续。所以使用空指令作为下一个周期进入回写阶段的指令。
//(2)当stall[4]为NoStop时。訪存阶段继续,訪存后的指令进入回写阶段。 //(3)其余情况下,保持回写阶段的寄存器wb_wd、wb_wreg、wb_wdata、
// wb_hi、wb_lo、wb_whilo不变。
always @ (posedge clk) begin
if(rst == `RstEnable) begin
......
end else if(stall[4] == `Stop && stall[5] == `NoStop) begin
wb_wd <= `NOPRegAddr;
wb_wreg <= `WriteDisable;
wb_wdata <= `ZeroWord;
wb_hi <= `ZeroWord;
wb_lo <= `ZeroWord;
wb_whilo <= `WriteDisable;
end else if(stall[4] == `NoStop) begin
wb_wd <= mem_wd;
wb_wreg <= mem_wreg;
wb_wdata <= mem_wdata;
wb_hi <= mem_hi;
wb_lo <= mem_lo;
wb_whilo <= mem_whilo;
end //if
end //always
endmodule

      6、改动顶层模块OpenMIPS

由于上面加入了CTRL模块,并且对流水线各个阶段的模块也都添加了对应的接口。所以要改动OpenMIPS模块。以将新增接口与CTRL模块连接起来,连接关系如图7-10所看到的,详细代码不在书中列出,读者能够參考本书附带光盘Code\Chapter7_2文件夹下的openmips.v文件。

下一次将利用上面实现的流水线暂停机制实现乘累加、乘累减指令,敬请关注!

自己动手写CPU之第七阶段(5)——流水线暂停机制的设计与实现的更多相关文章

  1. 自己动手写CPU之第七阶段(7)——乘累加指令的实现

    将陆续上传本人写的新书<自己动手写CPU>.今天是第30篇.我尽量每周四篇 亚马逊的销售地址例如以下.欢迎大家围观呵! http://www.amazon.cn/dp/b00mqkrlg8 ...

  2. 自己动手写CPU之第四阶段(3)——MIPS编译环境的建立

    将陆续上传本人写的新书<自己动手写CPU>(尚未出版).今天是第13篇.我尽量每周四篇 4.4 MIPS编译环境的建立 OpenMIPS处理器在设计的时候就计划与MIPS32指令集架构兼容 ...

  3. 自己动手写CPU之第九阶段(8)——MIPS32中的LL、SC指令说明

    将陆续上传新书<自己动手写CPU>,今天是第47篇. 9.7 ll.sc指令实现思路 9.7.1 实现思路 这2条指令都涉及到訪问链接状态位LLbit,能够将LLbit当做寄存器处理,ll ...

  4. 自己动手写CPU之第五阶段(1)——流水线数据相关问题

    将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第15篇,我尽量每周四篇 上一章建立了原始的OpenMIPS五级流水线结构,可是仅仅实现了一条ori指令,从本章開始,将逐步完 ...

  5. 自己动手写CPU之第五阶段(3)——MIPS指令集中的逻辑、移位与空指令

    将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第17篇.我尽量每周四篇 5.4 逻辑.移位操作与空指令说明 MIPS32指令集架构中定义的逻辑操作指令有8条:and.and ...

  6. 自己动手写CPU之第六阶段(2)——移动操作指令实现思路

    将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第21篇,我尽量每周四篇 6.2 移动操作指令实现思路 6.2.1 实现思路 这6条移动操作指令能够分为两类:一类是不涉及特殊 ...

  7. 自己动手写CPU之第八阶段(4)——转移指令实现过程2

    将陆续上传本人写的新书<自己动手写CPU>,今天是第36篇,我尽量每周四篇 开展晒书评送书活动,在亚马逊.京东.当当三大图书站点上,发表<自己动手写CPU>书评的前十名读者,均 ...

  8. 自己动手写CPU 笔记

    自己动手写CPU 跳转至: 导航. 搜索 文件夹 1 处理器与MIPS 2 可编程逻辑器件与Verilog HDL 3 教学版OpenMIPS处理器蓝图 4 第一条指令ori 5 逻辑.移位与nop ...

  9. 《自己动手写CPU》写书评获赠书活动结果

    <自己动手写CPU>写书评获赠图书的读者有: 京东:8***2.16号哨兵.magicyu.kk6803.jddickyd.杰出的胡兵 亚马逊:徐贺.马先童.jaychen.farmfar ...

随机推荐

  1. ambari单节点集群塔建

    配置2台机器,发别为ambari01.ambari03.ambari01上部署Ambari-server和Mirror server,另一台机器上部署agent. 一.配置静态IP 运行命令,让配置生 ...

  2. 【Luogu】P2607骑士(基环树DP)

    题目链接 这题……好吧我比着题解打的 题解连接 #include<cstring> #include<cstdio> #include<cstdlib> #incl ...

  3. hdoj--1016<dfs>

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1016 题目描述:1-n的整数排成一个环,首尾相连,相邻的两个数相加是素数,输出满足的排列,1开头输出, ...

  4. 使用grunt实现自动化单元测试

    闲话不多说~ 使用步骤 1.安装插件 npm install grunt-contrib-qunit --save-dev 2.加载包含 "qunit" 任务的插件 grunt.l ...

  5. 刷题总结——松鼠的新家(bzoj3631)

    题目: Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上. ...

  6. Java2WSDL 和 WSDL2Java(Axis)

    原文地址:https://www.ibm.com/developerworks/cn/webservices/ws-axisfaq/ 生成或取得WSDL文件 生成客户端或服务端代码 执行WSDL2Ja ...

  7. ajax cache enable and ajax concurrency!

    Today, forget to close ajax cache which leads to duplicate result from cache as to Jquery, this way, ...

  8. 转 SPOOLING技术——操作系统

    传送门 SPOOLING技术——操作系统 SPOOLING技术(Simultaneous Peripheral Operating On Line) 同时联机外围操作技术,它是关于慢速字符设备如何与计 ...

  9. Django 博客首页视图

    Django 处理 HTTP 请求 Web 应用的交互过程其实就是 HTTP 请求与响应的过程.无论是在 PC 端还是移动端,我们通常使用浏览器来上网,上网流程大致来说是这样的: 我们打开浏览器,在地 ...

  10. poj 1459(网络流)

    Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 26688   Accepted: 13874 D ...