E203数据冲突处理OITF
流水线的数据冲突分为三类: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的更多相关文章
- 蜂鸟E203 IFU模块
E203的IFU(instruction fetch unit)模块主要功能和接口如下: IFU的PC生成单元产生下一条指令的PC. 该PC传输到地址判断和ICB生成单元,就是根据PC值产生相应读指请 ...
- ORA-00001: unique constraint (...) violated并不一定是数据冲突
原文链接:http://blog.163.com/jet_it_life/blog/static/205097083201301410303931/ 收到一位测试人员RAISE的JIRA,说在某张表上 ...
- SQLServer 可更新订阅数据冲突的一个原因
原文:SQLServer 可更新订阅数据冲突的一个原因 可更新订阅为什么有冲突? 可更新订阅中,当升级增加一个字段时,通常在发布服务器的发布数据库中增加,对表增加字段后,发布自动同步到订阅数据库中(复 ...
- E203 itcm
E203 itcm是64Kb,所以地址总线为16位,2^16=64Kb, 数据线宽度为64 bits(8 bytes),所以address width是16-3=13bit,ram depth 是2^ ...
- 在vcs中编译及运行测试E203例子
E203的Makefile默认是调用 iverilog编译rtl,我们可以做如下修改,使其支持vcs编译. 1. 首先修改e200_opensource/tb/tb_top.v, 增加dump波形的两 ...
- E203 CSR rtl实现分析
CSR状态控制寄存器,每个hart都有自己的CSR.对于每个hart,可以配置的状态寄存器是4k.CSR寄存器的功能见:https://www.cnblogs.com/mikewolf2002/p/1 ...
- E203 CSR寄存器
RiscV架构则定义了一些控制和状态寄存器(CSR),用于配置或记录一些运行的状态.CSR寄存器是处理器内核内部的寄存器,使用专有的12位地址编码空间,对一个hart,可以配置4k的CSR寄存器. 蜂 ...
- E203 译码模块(1)
E203是两级流水线结构,第一级是IFU进行取指操作,第二级包括译码.执行.交付和写回等功能.架构图如下: https://www.cnblogs.com/images/cnblogs_com/mik ...
- 蜂鸟E203系列——Linux开发工具
欲观原文,请君移步 Vivado安装 vivado是运行工程的工具,所以必须安装 后台回复[vivado2017]可获取vivado 2017.4 | 后台回复[vivado2020]可获取vitis ...
随机推荐
- Java入门系列之StringBuilder、StringBuffer(三)
前言 上一节我们讲解了字符串的特性,除了字符串类外,还有两个我们也会经常用到的类,那就是StringBuffer和StringBuilder.因为字符串不可变,所以我们每次对字符串的修改比如通过连接c ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU特性那些事(1)- 概览
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的基本特性. ARM Cortex-M微控制器芯片厂商向来竞争激烈,具体可参看我的另一篇文章&l ...
- Go 自定义类型来实现枚举类型限制
今天使用iota 发现一个问题.定义别名类型的时候 调用函数报错.废话不多说,我们看一段示例(关于iota的用法这里就不介绍了,手册介绍滴比较详细): package main import &quo ...
- Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类
因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API.Stephen向JCP提交了 ...
- 【重学Git】高级命令篇
1.分离HEAD.HEAD 总是指向当前分支上最近一次提交记录. 所谓分离HEAD,就是让HEAD直接指向某一条具体的提交记录,而不是默认的通过分支名指向当前分支的最近一条提交记录. 2.相对引用^. ...
- 搭建SSM框架的配置文件
pom.xml所需要的基本依赖和插件: <dependency> <groupId>org.mybatis</groupId> ...
- vue $emit $on 从子组件传递数据给父组件
原理是: 子组件使用$emit发送数据,父组件使用$on,或者v-on绑定, 来监听子组件发送的数据. 子组件: <button @click="sendChildData" ...
- JS 验证
JS 验证 JavaScript 可用来在数据被送往服务器前对 HTML 表单中的这些输入数据进行验证. JavaScript 表单验证 JavaScript 可用来在数据被送往服务器前对 HTML ...
- python-初始网络编程
一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层 ...
- python接口自动化根据请求接口类型进行封装
根据不同的请求类型(GET/POST)进行接口请求封装 import requests import json class RunMain: def __init__(self, url, metho ...