跳转至

源码太多,基于 gpt 5.4 理解

LSU

一般 load/store:AG(Addr gen)->DC(Data Cache)->DA(Data Align,以及 store-load forwarding,来自 sq/wmb)->WB(Write back,写回 reg)

|559x459

可参考:https://zhuanlan.zhihu.com/p/492879610

  • lsu 以 16bytes 的粒度访问 cache,有 8 个 bank,每个 bank 4bytes,一个 cacheline 是 64bytes

wmb

store 所经过的层次:SQ->wmb_ce->wmb-> biu/L1D/VB

SQ commit 之后 pop 到 wmb_ce,wmb_ce 是用于 create wmb entry 的模块,VB 是 victim buffer

暂时无法在飞书文档外展示此内容

920 中所有的 store 种类:

  • Atomic:原子 store/Store conditional

  • Icc:icache、dcache、l2cache、tlb 等涉及缓存一致性的 store

  • sync/fence

  • 除以上几类之外的都是普通 store,每种普通 store 又分为 cacheable 和 uncacheable

    • Weak order

    • Strong order/device store

wmb 入口

wmb merge 针对的 store 种类:merge **只针对 weak order 开启,cacheable/uncacheable 都可能 merge,**源码是 wmb_ce_merge_en = wmb_ce_wo_st。

但是上述所有 store 都能且会进入 wmb,只是没有 merge 这一 feature。

只有一种特殊 store 不会进来,dcache all 这种“复用 store pipe 的维护操作”不应简单等同于普通 store,它会先经过缓存维护控制那条握手路径;先向 ICC 申请 sq_icc_req,等 icc_sq_grnt 且 icc_idle 后,再继续走 sq_wmb_pop_to_ce_req 这条路

wmb 内部

merge 指的是,把落在同一个 16B wmb data block 的 store 合并到同一个 entry,来减少写请求次数

merge 要求:weak order 以及 addr[PA-1:4] 相同

  • Wmb 一共有 8 个 entry,每个 entry 控制 16B,一共 8*16B

  • merge 窗口 是 16B

  • 覆盖粒度 是 byte

  • 允许字节重叠

  • 重叠时 后来的 store 覆盖前面的同字节数据(一般来说只有 weak order 可以,strong order 不能这样做)

Merge example:

假设两个 wo_st:

  • S0: 写 0x1000 ~ 0x1007,bytes_vld = 16'h00ff

  • S1: 写 0x1008 ~ 0x100f,bytes_vld = 16'hff00

注意掩码,是以 bytes 为单位,而不是 bits

合并:

  • 对每个 byte,若 wmb_ce_bytes_vld[i]=1,就用新 store 的 byte 覆盖旧 byte

  • 否则保留旧数据

  • 多个可以 merge 的 store,各自的 bytes_vld 做按位 OR

所以这个例子最后:

  • 原来 entry0.bytes_vld = 16'h00ff

  • merge 后变成 16'hffff

  • entry0.data[63:0] 来自 S0

  • entry0.data[127:64] 来自 S1

这个 bytes_vld 是如何生成的?bytes_vld 本质上是一个 16 bit 掩码,表示在当前这个 addr[PA-1:4] 对应的 16 字节窗口里,哪些 byte 被这条 store 写到。

  • 在 lsu 时,会根据写 byte 起始位置,store 写多少字节,算出结束位置,然后把[start,end)变为一个 16bits 的掩码,当然这个过程有可能会跨 16bytes,需要两次写,对应两个掩码

问题 1:store 的 merge 会不会导致 load 读到错误值

store1 addr1
load1 addr1
store2 addr1

是否会因为 wmb 把两个 store 把合并(因为其地址相同),导致 load 读到了合并后的结果

答:不会,由于 store 的顺序是先进入 SQ,然后从 SQ pop 时才进入 wmb。而又因为 store 指令只有 ROB commit 时才能出 SQ,这保证了 store2 指令是最新提交的,不可能有前面的 load1 在该条 store2 指令之后

问题 2:为什么 merge 时允许新的 store 直接覆盖同 byte 的数据,这不会造成内存状态的错误吗?

和上一个问题,其实是类似的。先想想,什么情况这种错误会有影响,那一定是在两个 store 中间穿插了一个 load,或者以某种别的方法要观测两个合并 store 的中间情况。但是由于进入 wmb 的 store,一定已经处在“对当前 load 来说足够老”的阶段,不可能会观测到这种中间情况。

所以说为什么允许合并,因为被覆盖的值还没成为**必须被外界观察到的状态,**这是最关键的,虽然错了一瞬间但是外界看不到

这也是为什么要求 weak order 才能合并,从内存状态更新的角度来看,确实少了一次旧值,如果真的 debug 时在这个地方有问题,那么软件开发者一定不知道是什么地方出错了。但是从程序执行的角度,执行结果还是正确的不会变。也就是 weak order 只保证程序结果正确,但是不保证中间每一个结果,内存都是正常更新

wmb 出口

出口:

  • Biu

    • Read(shareable cacheable store 的前置读/一部分 store conditinoal)

    • write

  • L1 Dcache(cacheable 命中或可直接更新的普通 store)

  • Victim buffer(部分 dcache 维护类操作,比如 clear/invalid)

为什么 write merge 会有 read?

  • 有些请求会先走“对外读地址通道”拿权限或做维护事务,然后才在另外三类里选一个真正落地的写出口。真正的“最终写落点”主要是后面三类:外部总线写、一级数据缓存、本地被替换缓存行缓冲区。

wmb 出口具体来说:

  1. 送到总线接口单元的“读地址通道”。

作用是“先读一下”或者“发缓存维护控制事务”,不是最终写数据。会走这里的类型有:可共享且可缓存的普通存储,前提是目标缓存行当前是共享状态或者本地无效;可共享且可缓存的存储条件指令;按地址操作的数据缓存维护;地址翻译缓冲区失效、指令缓存维护、二级缓存维护这类控制事务。

  1. 送到总线接口单元的“写地址通道和写数据通道”。

  2. 这是往核心外部真正发写请求的出口。会走这里的类型有:强序设备存储;不能在一级数据缓存内直接完成的普通存储;同步和栅栏;不能在一级数据缓存内直接完成的原子存储;不能在一级数据缓存内直接完成的存储条件指令。

  3. 直接更新一级数据缓存。

  4. 这是“本地完成写入”的出口。会走这里的类型有:可缓存而且目标缓存行当前在一级数据缓存中有效的普通存储;可缓存而且目标缓存行当前有效的原子存储;可缓存而且目标缓存行当前有效的存储条件指令;一部分单行“只做失效”的数据缓存维护操作。

  5. 送到“被替换缓存行缓冲区”。

  6. 这不是直接出核,而是先交给本地缓冲区,后面再由它决定是否要对外吐出、写回、清除或者失效。会走这里的类型主要是:可缓存、目标缓存行当前有效、并且属于“单行清除类”的数据缓存维护操作。

Wmb 什么时候往外发

每个entry会顺序经历五个阶段:biu read->biu write->wirte VB->write dcache->data(resp)

发出是看ptr落在哪个entry,并且满足一定条件,该entry就发出去,多个ptr功能独立,每周期都可以往外发

如果某一个entry不需要某一阶段,比如dcahce不需要经过biu,可以通过immediate skip跳过一些阶段

还有create_ptr

entry释放条件:

// ct_lsu_wmb_entry.v:2179
wmb_entry_pop_vld = vld                             // entry 有效
    && read_resp                                     // BIU R 响应已收到
    && (write_resp || write_resp_set                 // 写响应已收到
        || mem_set_req && !w_last)                    // 或 burst 中间 beat
    && (data_req_success || data_req_success_set)    // 数据已发送
    && wb_cmplt_success                               // 写回完成确认
    && wb_data_success;                              // 写回数据完成
没有仲裁  所有满足条件的 entry 同时 pop。 entry 自身把 vld 清零即可。

多个entry的ptr是否会同时valid:不会。ptr是独热码