RVWMO观他人博客总结
#RISC-V弱内存模型
这里RISC-V内存模型为了保证执行顺序和程序的一致性,利用了四大类,13个规则。这里下面的指令是指访存指令,我们可以看看下面的规则,如何保证执行时保证前后两条访存的顺序。
重叠地址
一、 store 在后
不像TSO对于store
的顺序要求很严格,这里只要求对于同一个地址的顺序。
a) load/store addr0
b) store addr0
对于后面b
是store
的情况,我们必须保证这个顺序。
二、CoRR
对于两条load
之间没有写指令的情况,我们保证后一个load
不会读取到更老的值。
a) load a0,addr0
b) load a1,addr0
即使其他核上对addr0
,进行了写入,也只可能让b
读取到更新的值。
三、原子指令
前一个指令是原子指令,后一条指令是读取,那么后一条指令一定能读取到前一条指令写入的值。
显示同步
四、FENCE指令
如果两条访存指令之间有一条fence
指令,那么必须根据fence
的要求进行顺序的确定。
五、acquire
如果前一条指令有acquire,那么必须要求后面的指令不能超前。
六、release
如果后面一条指令有release,那么要求前面的指令不能延后。
七、两条指令都有acquire和release标志
当然也必须顺序
八、LR/SC
这里LR
是Load reserved
,SC
是store condition
,会要求只用先进行LR
之后才能
SC
。
语法依赖
语法依赖感觉有点像流水线中的依赖关系
- 九,后一条指令的地址依赖于前一条指令
- 十,后一条指令的数据依赖于前一条指令
- 十一,后一条指令在控制流上依赖前一条指令,即一个分支是否流向了后一条指令。
流水线依赖
十二
a) store/load
<memory operation depend on a>
b) load value stored by last memory op
十三
a) load/store
<memory operation address depend on a>
b) store
例子
int x = 0;
int y = 0;
void t1() {
y = 1;
int res = x;
printf("x=%d\n", res);
}
void t2() {
x = 1;
int res = y;
printf("y=%d\n",res);
}
这个程序在x86
上会出现0, 0
的情况,因为它是TSO
, 在如上的RISC-V
机器上也可能出现。
Sequential Consistency
在程序顺序上的前后,在插入全局内存序,依旧保持,而且部分是否是同一地址。
但是SC
也无法保证不同核上程序之间到底是什么顺序,我们可能需要一些原子指令。
int sum = 0;
void t1() {
sum += 1;
}
void t2() {
sum += 2;
}
这个程序由于没有原子性的保证所以,结果可能不是3。在RISC-V
中,我们可以使用LR
和SC
进行。
TSO
在流水线设计中,我们往往会加入一个store buffer
, load
可以使用buffer
转发的方式获取最新的值,store buffer
大大提高了外设和内存的访问效率。当然如果是外设的情况,不能进行转发,因为IO
必须保证顺序。
如果是这样,为了适应store buffer
的加入,load
就可以乱序到store
前面,那么就有了TSO
这种模型进行说明。