引言

之前,我们分析or1200的控制通路中的sprs模块和except模块,本小节,我们就分析一下or1200控制通路的最后一个模块,就是freeze模块。

1,整体分析

freeze模块,顾名思义,就是根据各个流水阶段的反馈信号,负责产生控制整条流水线各个阶段的暂停信号,如取指阶段的genpc_freeze和if_freeze信号,解码阶段的id_freeze信号,执行阶段的ex_freeze信号,以及写回阶段的wb_freeze信号,共5个暂停信号。

可以这么说,freeze就好像整条流水线的监工,如果发现某一阶段出现问题,就控制那个流水阶段暂停。

2,暂停信号产生规则

freeze模块产生的这5个信号不是相互独立的,是有一定的规则的,那么到底有什么规则呢?关于freeze模块的5个暂停信号的产生过则,or1200_freeze.v中有如下描述:

//
// Pipeline freeze
//
// Rules how to create freeze signals:
// 1. Not overwriting pipeline stages:
// Freeze signals at the beginning of pipeline (such as if_freeze) can be
// asserted more often than freeze signals at the of pipeline (such as
// wb_freeze). In other words, wb_freeze must never be asserted when ex_freeze
// is not. ex_freeze must never be asserted when id_freeze is not etc.
//
// 2. Inserting NOPs in the middle of pipeline only if supported:
// At this time, only ex_freeze (and wb_freeze) can be deassrted when id_freeze
// (and if_freeze) are asserted.
// This way NOP is asserted from stage ID into EX stage.
//

那如何理解呢?

关于第一条:

这一条比较容易理解,就是说流水线的某一个阶段如果想产生暂停信号,那么这个阶段的前一个流水阶段必须先产生。假如要想产生wb_freeze信号,必须先产生ex_freeze信号。

问什么要有这条规则呢?为了便于理解,我们假设一个情景来说明一下。

我记得我小的时候,我们家每年会种几亩地的西瓜,等西瓜成熟的时候,我爸妈会开着农用车,带着我和我的两个弟弟(老四和老五)去地里摘西瓜,为了加快速度,我们各有分工,我爸负责把西瓜从瓜藤上摘下来,并送到我妈手里,我妈负责把西瓜传到我手里,我负责把这个西瓜送到站在车旁边的老四,老四负责把西瓜递给在车上的老五,老五负责将西瓜慢慢的堆放到车上。

上面的情景分别对应流水线的五个阶段,假如我在摘瓜的过程中突然感觉口渴了,想去喝点水,那么我妈必须先暂停下来,要不然,如果我妈把西瓜向我扔来,但我这时我在喝水,那么这个西瓜就肯定会摔碎。所以,我妈必须先停下来,同样道理,我妈要想停下来,我爸必须也停下来。

如果处在最末端的我的老五如果想想停下来,根据这条规则,那么处在最开始的我爸爸也必须停下来,否则的话就会出问题。

还回到流水线,这条规则保证了不会有指令丢失。设想一下,如果流水线的EX阶段暂停了,ID阶段却没暂停下来,就会出现ID阶段解码的指令,EX不会执行的情况。

关于第二条:

如果说第一条是规定暂定信号产生规则的话,那么第二条就是规定暂停信号如何解除了。举个例子,如果EX阶段要想解除暂停信号,那么EX阶段的前面的阶段必须不能解除,否则的话就会违背第一条规则了。

3,代码分析

了解了freeze模块的功能和暂停信号的产生规则之后,那rtl代码具体是如何实现的呢?

首先是取指阶段的暂停信号,代码如下:

assign genpc_freeze = (du_stall & !saving_if_insn) | flushpipe_r;
assign if_freeze = id_freeze | extend_flush;

这里需要说明的是,如果在取指阶段出现问题,比如出现指令总线的应答错误,那么就需要刷新流水线,代码如下:

//
// registered flushpipe
//
always @(posedge clk or `OR1200_RST_EVENT rst)
if (rst == `OR1200_RST_VALUE)
flushpipe_r <= 1'b0;
else if (icpu_ack_i | icpu_err_i)
// else if (!if_stall)
flushpipe_r <= flushpipe;
else if (!flushpipe)
flushpipe_r <= 1'b0;

其次是解码,执行和写回阶段的暂停信号,代码如下:

assign id_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze
| (|waiting_on) | force_dslot_fetch) | du_stall;
assign ex_freeze = wb_freeze; assign wb_freeze = (lsu_stall | (~lsu_unstall & if_stall) | multicycle_freeze
| (|waiting_on)) | du_stall | abort_ex;

需要说明的是这三个阶段的暂停信号的产生有一个多周期的问题,和流水线等待问题。

or1200的大部分指令都需要一个指令周期,但是有几条指令需要多个指令周期,如果需要这几条指令时,就需要暂停信号,代码如下:

//
// Multicycle freeze
//
assign multicycle_freeze = |multicycle_cnt; //
// Multicycle counter
//
always @(posedge clk or `OR1200_RST_EVENT rst)
if (rst == `OR1200_RST_VALUE)
multicycle_cnt <= `OR1200_MULTICYCLE_WIDTH'd0;
else if (|multicycle_cnt)
multicycle_cnt <= multicycle_cnt - `OR1200_MULTICYCLE_WIDTH'd1;
else if (|multicycle & !ex_freeze)
multicycle_cnt <= multicycle;

那么都有哪些指令是多周期指令呢?or1200_define.v中相关代码如下:

// Execution control which will "wait on" a module to finish
`define OR1200_WAIT_ON_WIDTH 2
`define OR1200_WAIT_ON_NOTHING `OR1200_WAIT_ON_WIDTH'd0
`define OR1200_WAIT_ON_MULTMAC `OR1200_WAIT_ON_WIDTH'd1
`define OR1200_WAIT_ON_FPU `OR1200_WAIT_ON_WIDTH'd2
`define OR1200_WAIT_ON_MTSPR `OR1200_WAIT_ON_WIDTH'd3

此外,在遇到一些特殊情况,流水线需要等待(wait_on),这时,也需要暂停流水线,代码如下:

//
// Waiting on generation
//
always @(posedge clk or `OR1200_RST_EVENT rst)
if (rst == `OR1200_RST_VALUE)
waiting_on <= 0;
else if ((waiting_on == `OR1200_WAIT_ON_MULTMAC) & !mac_stall)
waiting_on <= 0;
else if ((waiting_on == `OR1200_WAIT_ON_FPU) & fpu_done)
waiting_on <= 0;
else if ((waiting_on == `OR1200_WAIT_ON_MTSPR) & mtspr_done)
waiting_on <= 0;
else if (!ex_freeze)
waiting_on <= wait_on;

关于wait_on信号的产生,我们在分析ID模块(ctrl)时,已经介绍过了,如有疑问请参考:
http://blog.csdn.net/rill_zhen/article/details/9816129

4,小结

freeze模块是整条流水线的大管家,控制着流水线的暂停和执行大权,但其代码却没有想象的那么复杂,越是深奥的道理,一般使用的语言都非常简单,freeze模块也正好证明了这一点。

自此,我们将or1200的数据通路和控制通路都分析了一下,剩下的工作就是其它可选但却不可或缺的debug模块,负责精确定时的tick timer模块,以及负责整个CPU功耗管理的power management模块了。

革命尚未成功,同志仍需努力。

OpenRisc-50-or1200的freeze模块分析的更多相关文章

  1. OpenRisc-43-or1200的IF模块分析

    引言 “喂饱饥饿的CPU”,是计算机体系结构设计者时刻要考虑的问题.要解决这个问题,方法大体可分为两部分,第一就是利用principle of locality而引进的cache技术,缩短取指时间,第 ...

  2. OpenRisc-48-or1200的SPRS模块分析

    引言 之前,我们在分析or1200的WB模块时(http://blog.csdn.net/rill_zhen/article/details/10220619),介绍了OpenRISC的GPRS(ge ...

  3. OpenRisc-42-or1200的ALU模块分析

    引言 computer(计算机),顾名思义,就是用来compute(计算)的.计算机体系结构在上世纪五六十年代的时候,主要就是研究如何设计运算部件,就是想办法用最少的元器件(那时元器件很贵),最快的速 ...

  4. OpenRisc-41-or1200的cache模块分析

    引言 为CPU提供足够的,稳定的指令流和数据流是计算机体系结构设计中两个永恒的话题.为了给CPU提供指令流,需要设计分支预测机构,为了给CPU提供数据流,就需要设计cache了.其实,无论是insn还 ...

  5. OpenRisc-45-or1200的ID模块分析

    引言 之前,我们分析了or1200流水线的整体结构,也分析了流水线中IF级,EX级,本小节我们来分析ID(insn decode)级的一些细节. 1,基础 or1200的pipeline的ID阶段包含 ...

  6. OpenRisc-40-or1200的MMU模块分析

    引言 MMU(memory management unit),无论对于computer architecture designer还是OS designer,都是至关重要的部分,设计和使用的好坏,对性 ...

  7. OpenRisc-47-or1200的WB模块分析

    引言 “善妖善老,善始善终”,说的是无论什么事情要从有头有尾,别三分钟热度. 对于or1200的流水线来说,MA阶段是最后一个阶段,也是整条流水线的收尾阶段,负责战场的清扫工作.比如,把运算指令的运算 ...

  8. 【转】python模块分析之logging日志(四)

    [转]python模块分析之logging日志(四) python的logging模块是用来写日志的,是python的标准模块. 系列文章 python模块分析之random(一) python模块分 ...

  9. python模块分析之logging日志(四)

    前言 python的logging模块是用来设置日志的,是python的标准模块. 系列文章 python模块分析之random(一) python模块分析之hashlib加密(二) python模块 ...

随机推荐

  1. 宽屏手机显示9.png的图片拉伸不均衡

    制作的一个.9的背景图片,在一般的480宽的手机上显示没有问题,正常拉伸,用三星的一个宽屏手机测试时,没有完全拉伸,一边拉伸多一点,一边拉伸少一点 决绝办法:就是在制作.9的时候,我在横向拉伸的地方, ...

  2. Troubleshooting(updating...)

    记录了工作和学习中一些杂碎的问题. 问题:RDP一直处于连接状态,除非重启 描述:表面看上去是应该在一定时间还连接不上,就让它断开.深层问题是,初次连接一个新的IP地址,Win7以上的系统,会有个CA ...

  3. Hashtable的使用

    Hashtable mylist = new Hashtable();             mylist.Add("1", "100");          ...

  4. Java Swing界面编程(22)---事件处理:动作事件及监听处理

    要想让一个button变得有意义,就必须使用事件处理.在swing的事件处理中.能够使用ActionListener接口处理button的动作事件. package com.beyole.util; ...

  5. MySQL里求给定的时间是所在月份的第几个礼拜

    Share 一个昨天写的函数. 目的是求给定的时间是所在月份的第几个礼拜. DELIMITER $$ USE `t_girl`$$ DROP FUNCTION IF EXISTS `weekofmon ...

  6. 浅谈数据库技术,磁盘冗余阵列,IP分配,ECC内存,ADO,DAO,JDBC

    整理-----数据库技术,磁盘冗余阵列,IP分配, ECC内存,ADO, DAO,JDBC 1.MySQL MySQL是最受欢迎的开源SQL数据库管理系统,它由 MySQL AB开发.发布和支持.My ...

  7. C# - 重写虚方法

    项目目录: 创建教师类(Teacher),虚方法有Teach(); 创建学生类(Student),重写的方法是Teach(); 教师类: · 加上关键字 Virtual 就是声明可以重写此方法. us ...

  8. 出现Data Tools 与VS 不兼容问题

    转载自:http://www.yishimei.cn/network/73.html 相信很多人都遇到了“此版本的SQL Server Data Tools与此计算机中安装的数据库运行时组件不兼容”这 ...

  9. 使用SetLocaleInfo设置时间后必须调用广播WM_SETTINGCHANGE,通知其他程序格式已经更改

    uses messages; Procedure SetDateFormat; //设置系统日期格式var buf:pchar; i:integer; p:DWORD;begin getmem(buf ...

  10. c# in depth之泛型的实现

    1.默认值表达式 如果已经明确了要处理的类型,也就知道了它的“默认”值.不知道要引用的类型,就不能直接指定默认值.不能使用null,因为它可能不是一个引用类型,不能使用0,因为它可能不是数值类型.虽然 ...