流水线的数据冲突分为三类:WAR,RAW,WAW

https://wenku.baidu.com/view/e066926d48d7c1c708a14508.html

  • WAR: write after read 相关性,又称先读后写相关性。比如下面的指令序列,第一条指令会读取x4,第二条指令会写x4。在流水线中,如果第二条指令比第一条指令先写x4,则第一条指令就会读出错误的值。

add x5, x4,x6

add x4, x3, x2

  • WAW: write after write 相关性,又称先写后写相关性。比如下面的指令序列,两条指令都会写x5。在流水线中,如果第二条指令比第一条指令先写x5,就会引起逻辑错误。

add x5, x4,x6

add x5, x3, x2

  • RAW:read after write相关性,又称先写后读相关性。比如下面指令序列,如果第二条指令,在第一条指令写x5之前,第二条指令先读x4,就会引起逻辑错误。

add x5, x4,x6

add x4, x5, x2

由于蜂鸟E200系列是按序派遣,按顺序写回的微架构,在指令派遣时候就已经从通用寄存器数组中读取了源操作数。后续执行的指令写回regfile的操作不可能影响到前面指令的读取,所以不可能发生WAR相关性造成的数据冲突。

正在派遣的指令处在流水线的第二级,假设之前派遣的指令是单周期指令,则前序指令肯定已经完成了执行且将结果写回了Regfile。因此正在派遣的指令不可能会发生RAW数据冲突。但是假设之前派遣的指令是多周期指令(长指令),由于指令需要多个周期才能写回结果。因此正在派遣的指令可能会产生前序相关的RAW相关性。

正在派遣的指令处在流水线的第二级,假设之前派遣的指令是单周期指令,则前序指令肯定已经完成了执行且将结果写回了Regfile。因此正在派遣的指令不可能会发生WAW数据冲突。但是假设之前派遣的指令是多周期指令(长指令),由于指令需要多个周期才能写回结果。因此正在派遣的指令可能会产生前序相关的WAW相关性。

为了能检测出长指令的RAW和WAW相关性,蜂鸟E200使用了一个outstanding instruction track fifo(OITF)模块。在流水线的派遣(Dispatch)点,每一次派遣一个长指令,则会在OITF中分配一个表项(Entry),在这个表项中会存储该长指令的结果寄存器索引。在流水线的写回(Write-back)点,每次按顺序写回一个长指令之后,就会将此指令在OITF中的表项移除。

每条指令派遣时,都会将本指令的源操作数和目的操作数寄存器索引和OITF中的各个表项进行比对,从而判断本指令是否与已经被派遣出,且尚未写回的长指令产生RAW和WAW相关性。如果产生相关性,则stall住当前指令的派遣。如果没有RAW和WAW相关性,且该指令为多周期长指令,把该指令写入OITF,如果OITF是full,则仍要stall住管线,等待OITF释放空间后,再写入并派遣。

在writeback模块,会进行长指令写回仲裁,长指令写回regfile后,会释放OITF中相应的表项。

OITF代码如下,如果fifo full,则dis_ready=0, 与dispatch模块握手失败,不会发送新的dispatch进来。如果不为空,会发送新的指令进来进行判断。

`include "e203_defines.v"

module e203_exu_oitf (
output dis_ready, input dis_ena, //dispatch a long instruction enable signal
input ret_ena, //write back a long instruction enable signal output [`E203_ITAG_WIDTH-1:0] dis_ptr, //write pointer
output [`E203_ITAG_WIDTH-1:0] ret_ptr, //read pointer output [`E203_RFIDX_WIDTH-1:0] ret_rdidx,
output ret_rdwen,
output ret_rdfpu,
output [`E203_PC_SIZE-1:0] ret_pc, input disp_i_rs1en, // enable if current dispatch instruction fetch first source operand
input disp_i_rs2en, // ...
input disp_i_rs3en, // ...
input disp_i_rdwen, // enable if current dispatch instruction write back to register
input disp_i_rs1fpu, // enable if current dispath instruction need to read float gpr
input disp_i_rs2fpu, //...
input disp_i_rs3fpu, //...
input disp_i_rdfpu, //enable if current dipatch instruction need to write back to float register files.
//register index
input [`E203_RFIDX_WIDTH-1:0] disp_i_rs1idx,
input [`E203_RFIDX_WIDTH-1:0] disp_i_rs2idx,
input [`E203_RFIDX_WIDTH-1:0] disp_i_rs3idx,
input [`E203_RFIDX_WIDTH-1:0] disp_i_rdidx,
input [`E203_PC_SIZE -1:0] disp_i_pc, //pc of current dispatch instruciotn output oitfrd_match_disprs1, //dispatch instruction rs1 is same as any item of result register in oitf
output oitfrd_match_disprs2, //...
output oitfrd_match_disprs3, //...
output oitfrd_match_disprd, //dispatch instruction rd is same as any item of result register in oitf.
//if empty, no conflict
output oitf_empty,
input clk,
input rst_n
); wire [`E203_OITF_DEPTH-1:0] vld_set;
wire [`E203_OITF_DEPTH-1:0] vld_clr;
wire [`E203_OITF_DEPTH-1:0] vld_ena;
wire [`E203_OITF_DEPTH-1:0] vld_nxt;
wire [`E203_OITF_DEPTH-1:0] vld_r; //if it is valid signal in all item
wire [`E203_OITF_DEPTH-1:0] rdwen_r;// if it is write back register in all item
wire [`E203_OITF_DEPTH-1:0] rdfpu_r; //result register in all item if are float
wire [`E203_RFIDX_WIDTH-1:0] rdidx_r[`E203_OITF_DEPTH-1:0]; //register index in all items
// The PC here is to be used at wback stage to track out the
// PC of exception of long-pipe instruction
wire [`E203_PC_SIZE-1:0] pc_r[`E203_OITF_DEPTH-1:0]; wire alc_ptr_ena = dis_ena; //dispatch a long instruction enable signal, as write pointer enable signal
wire ret_ptr_ena = ret_ena; //write back a long instruction enable signal, as read pointer enable signal wire oitf_full ; wire [`E203_ITAG_WIDTH-1:0] alc_ptr_r; //write pointer, long instruction dispatch
wire [`E203_ITAG_WIDTH-1:0] ret_ptr_r; //read pointer, long instruction write back generate
if(`E203_OITF_DEPTH > 1) begin: depth_gt1//{
//extra mark bit for write full
wire alc_ptr_flg_r;
wire alc_ptr_flg_nxt = ~alc_ptr_flg_r;
wire alc_ptr_flg_ena = (alc_ptr_r == ($unsigned(`E203_OITF_DEPTH-1))) & alc_ptr_ena; sirv_gnrl_dfflr #(1) alc_ptr_flg_dfflrs(alc_ptr_flg_ena, alc_ptr_flg_nxt, alc_ptr_flg_r, clk, rst_n); wire [`E203_ITAG_WIDTH-1:0] alc_ptr_nxt;
//if write to fifo depth, write ptr = 0,otherwise write ptr = write ptr + 1
assign alc_ptr_nxt = alc_ptr_flg_ena ? `E203_ITAG_WIDTH'b0 : (alc_ptr_r + 1'b1); sirv_gnrl_dfflr #(`E203_ITAG_WIDTH) alc_ptr_dfflrs(alc_ptr_ena, alc_ptr_nxt, alc_ptr_r, clk, rst_n); //extra mark bit for read empty
wire ret_ptr_flg_r;
wire ret_ptr_flg_nxt = ~ret_ptr_flg_r;
wire ret_ptr_flg_ena = (ret_ptr_r == ($unsigned(`E203_OITF_DEPTH-1))) & ret_ptr_ena; sirv_gnrl_dfflr #(1) ret_ptr_flg_dfflrs(ret_ptr_flg_ena, ret_ptr_flg_nxt, ret_ptr_flg_r, clk, rst_n); wire [`E203_ITAG_WIDTH-1:0] ret_ptr_nxt;
//if read to fifo depth, read ptr = 0, otherwise read prt = read prt + 1
assign ret_ptr_nxt = ret_ptr_flg_ena ? `E203_ITAG_WIDTH'b0 : (ret_ptr_r + 1'b1); sirv_gnrl_dfflr #(`E203_ITAG_WIDTH) ret_ptr_dfflrs(ret_ptr_ena, ret_ptr_nxt, ret_ptr_r, clk, rst_n);
//empty, full mark
assign oitf_empty = (ret_ptr_r == alc_ptr_r) & (ret_ptr_flg_r == alc_ptr_flg_r);
assign oitf_full = (ret_ptr_r == alc_ptr_r) & (~(ret_ptr_flg_r == alc_ptr_flg_r));
end//}
else begin: depth_eq1//}{
assign alc_ptr_r =1'b0;
assign ret_ptr_r =1'b0;
assign oitf_empty = ~vld_r[0];
assign oitf_full = vld_r[0];
end//}
endgenerate//} assign ret_ptr = ret_ptr_r;
assign dis_ptr = alc_ptr_r; ////
//// // If the OITF is not full, or it is under retiring, then it is ready to accept new dispatch
//// assign dis_ready = (~oitf_full) | ret_ena;
// To cut down the loop between ALU write-back valid --> oitf_ret_ena --> oitf_ready ---> dispatch_ready --- > alu_i_valid
// we exclude the ret_ena from the ready signal
assign dis_ready = (~oitf_full); wire [`E203_OITF_DEPTH-1:0] rd_match_rs1idx;
wire [`E203_OITF_DEPTH-1:0] rd_match_rs2idx;
wire [`E203_OITF_DEPTH-1:0] rd_match_rs3idx;
wire [`E203_OITF_DEPTH-1:0] rd_match_rdidx; genvar i;
generate //{
for (i=0; i<`E203_OITF_DEPTH; i=i+1) begin:oitf_entries//{
//every time, assign a item and write pointer same as current i, then
//valid set is high
assign vld_set[i] = alc_ptr_ena & (alc_ptr_r == i);
//every time, assign a item and read pointer same as current i, then
//valid clr is high
assign vld_clr[i] = ret_ptr_ena & (ret_ptr_r == i);
assign vld_ena[i] = vld_set[i] | vld_clr[i];
assign vld_nxt[i] = vld_set[i] | (~vld_clr[i]); sirv_gnrl_dfflr #(1) vld_dfflrs(vld_ena[i], vld_nxt[i], vld_r[i], clk, rst_n);
//Payload only set, no need to clear
sirv_gnrl_dffl #(`E203_RFIDX_WIDTH) rdidx_dfflrs(vld_set[i], disp_i_rdidx, rdidx_r[i], clk);
sirv_gnrl_dffl #(`E203_PC_SIZE ) pc_dfflrs (vld_set[i], disp_i_pc , pc_r[i] , clk);
sirv_gnrl_dffl #(1) rdwen_dfflrs(vld_set[i], disp_i_rdwen, rdwen_r[i], clk);
sirv_gnrl_dffl #(1) rdfpu_dfflrs(vld_set[i], disp_i_rdfpu, rdfpu_r[i], clk);
//compare dispatch source operand with result register in fifo
assign rd_match_rs1idx[i] = vld_r[i] & rdwen_r[i] & disp_i_rs1en & (rdfpu_r[i] == disp_i_rs1fpu) & (rdidx_r[i] == disp_i_rs1idx);
assign rd_match_rs2idx[i] = vld_r[i] & rdwen_r[i] & disp_i_rs2en & (rdfpu_r[i] == disp_i_rs2fpu) & (rdidx_r[i] == disp_i_rs2idx);
assign rd_match_rs3idx[i] = vld_r[i] & rdwen_r[i] & disp_i_rs3en & (rdfpu_r[i] == disp_i_rs3fpu) & (rdidx_r[i] == disp_i_rs3idx);
assign rd_match_rdidx [i] = vld_r[i] & rdwen_r[i] & disp_i_rdwen & (rdfpu_r[i] == disp_i_rdfpu ) & (rdidx_r[i] == disp_i_rdidx ); end//}
endgenerate//}
//rs1 in fifo, so RAW relative
assign oitfrd_match_disprs1 = |rd_match_rs1idx;
//rs2 in fifo, so RAW relative
assign oitfrd_match_disprs2 = |rd_match_rs2idx;
//rs3 in fifo, so RAW relative
assign oitfrd_match_disprs3 = |rd_match_rs3idx;
//rd in fifo, so WAW relative
assign oitfrd_match_disprd = |rd_match_rdidx ; assign ret_rdidx = rdidx_r[ret_ptr];
assign ret_pc = pc_r [ret_ptr];
assign ret_rdwen = rdwen_r[ret_ptr];
assign ret_rdfpu = rdfpu_r[ret_ptr]; endmodule

E203数据冲突处理OITF的更多相关文章

  1. 蜂鸟E203 IFU模块

    E203的IFU(instruction fetch unit)模块主要功能和接口如下: IFU的PC生成单元产生下一条指令的PC. 该PC传输到地址判断和ICB生成单元,就是根据PC值产生相应读指请 ...

  2. ORA-00001: unique constraint (...) violated并不一定是数据冲突

    原文链接:http://blog.163.com/jet_it_life/blog/static/205097083201301410303931/ 收到一位测试人员RAISE的JIRA,说在某张表上 ...

  3. SQLServer 可更新订阅数据冲突的一个原因

    原文:SQLServer 可更新订阅数据冲突的一个原因 可更新订阅为什么有冲突? 可更新订阅中,当升级增加一个字段时,通常在发布服务器的发布数据库中增加,对表增加字段后,发布自动同步到订阅数据库中(复 ...

  4. E203 itcm

    E203 itcm是64Kb,所以地址总线为16位,2^16=64Kb, 数据线宽度为64 bits(8 bytes),所以address width是16-3=13bit,ram depth 是2^ ...

  5. 在vcs中编译及运行测试E203例子

    E203的Makefile默认是调用 iverilog编译rtl,我们可以做如下修改,使其支持vcs编译. 1. 首先修改e200_opensource/tb/tb_top.v, 增加dump波形的两 ...

  6. E203 CSR rtl实现分析

    CSR状态控制寄存器,每个hart都有自己的CSR.对于每个hart,可以配置的状态寄存器是4k.CSR寄存器的功能见:https://www.cnblogs.com/mikewolf2002/p/1 ...

  7. E203 CSR寄存器

    RiscV架构则定义了一些控制和状态寄存器(CSR),用于配置或记录一些运行的状态.CSR寄存器是处理器内核内部的寄存器,使用专有的12位地址编码空间,对一个hart,可以配置4k的CSR寄存器. 蜂 ...

  8. E203 译码模块(1)

    E203是两级流水线结构,第一级是IFU进行取指操作,第二级包括译码.执行.交付和写回等功能.架构图如下: https://www.cnblogs.com/images/cnblogs_com/mik ...

  9. 蜂鸟E203系列——Linux开发工具

    欲观原文,请君移步 Vivado安装 vivado是运行工程的工具,所以必须安装 后台回复[vivado2017]可获取vivado 2017.4 | 后台回复[vivado2020]可获取vitis ...

随机推荐

  1. 周会材料:高并发程序设计<一>

    第一章 几个概念 同步:一次方法调用须等到其返回后才能有后续 异步:一次方法调用后在另一线程执行,调用者可不必等其返回就可进行后续 并发:任务以极短的时间交替进行 并行:任务同时进行 临界区:公共资源 ...

  2. echarts玩转图表之矩形树图

    前言 这是第一次用makedown编辑器写文章,感觉像一件利器,排版美观而且效率飙升.进入正题 Echart官网文档地址 针对于矩形树图api配置项链接 1. 完全从数据定义图形 $.get( &qu ...

  3. 25个JavaScript数组方法代码示例

    摘要: 通过代码掌握数组方法. 原文:通过实现25个数组方法来理解及高效使用数组方法(长文,建议收藏) 译者:前端小智 Fundebug经授权转载,版权归原作者所有. 要在给定数组上使用方法,只需要通 ...

  4. 如何通过RMAN使用传输表空间迁移到不同的Endian平台 (Doc ID 371556.1)

    How to Migrate to different Endian Platform Using Transportable Tablespaces With RMAN (Doc ID 371556 ...

  5. SSH的本地、远程、动态端口转发实验笔记

    SSH端口转发 SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据.但是,SSH 还能够将其他 TCP 端口的网络数据通过 SSH 链接来转发,并且自动提供了相应的加密及解密服务.这一 ...

  6. python读写Excel方法(xlwt和xlrd)

    在我们做平常工作中都会遇到操作excel,那么今天写一篇,如何通过python操作excel,当然python操作excel的库有很多,比如pandas,xlwt/xlrd,openpyxl等,每个库 ...

  7. 201871010116-祁英红《面向对象程序设计(java)》第十三周学习总结

    博文正文开头格式:(2分) 项目 内容 <面向对象程序设计(java)> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://ww ...

  8. vue-cil3 运行报错

    warnings potentially fixable with the `--fix` option. 将一下部分:"lint": "vue-cli-service ...

  9. 微服务、SpringCloud、k8s、Istio杂谈

    一.微服务与SOA “微服务”是一个名词,没有这个名词之前也有“微服务”,一个朗朗上口的名词能让大家产生一个认知共识,这对推动一个事务的发展挺重要的,不然你叫微服务他叫小服务的大家很难集中到一个点上. ...

  10. .NET Core 序列化对象输出字节数大小比较

    写代码验证了一下 .NET Core 中序列化对象输出字节数大小,.NET Core 版本是 3.0.100-preview8-013656 ,对象属性使用了 Guid 与 DateTime 类型,胜 ...