聊聊内存序

最近读完了 A Primer on Memory Consistency and Cache Coherence这本书,写一篇文章结合我个人了解的其他知识总结一下内存序。 文章假定读者学习了基本的体系结构。 概念 Cache Coherence 相信大家对Cache有一个基本的理解。但这里需要引出一个新的概念,共享内存中的Private Cache。 即使是简单的单核处理器,往往L1 I-Cache与D-Cache也是Private的。因为IFU(取指单元)与LSU(访存单元)通常分布在处理器流水线的不同阶段,它们可能需要同时访问。既然是Private,这个时候如果我们通过访存指令写入了一些指令(通过D-Cache)到某个内存地址,而这个地址已经在I-Cache中,结果就在取指时有可能取到旧值,如何解决这一问题? 也许L1…

在Xilinx FPGA上搭建SoC

背景 之前出于科研需求和龙芯杯比赛需求都自己搭建过SoC来运行CPU软核,整理一下我的搭建SoC的流程。以下的讨论基于MIPS和RISC-V两种软核ISA为例。 大家也可以参考我搭建的两个SoC以及对应的软件: cyysoc (RISC-V Rocket+Coherent DMA) pblaze_soc 某大船SSD上的xc7k325t-2 FPGA+2G 72bit DDR3 ECC 用了某个PCI-E引出到SFP接口的扩展板,连接光模块/电口模块提供网络 PCI-E和SFP的IO在FPGA上都是GTX 用了某个该板子的IO接口转USB UART的扩展板 扩展板上面还有rgmii…

浅谈现代处理器实现超大L1 Cache的方式

浅谈现代处理器实现超大L1 Cache的方式 昨天观看WWDC时看到Apple M2处理器的L1 Cache大小已经达到了192K+128K,这不禁使我产生好奇,Apple如何做到这一点。(尽管事后发现M1处理器已经实现了,但那时的我还不懂电路上的困难。) 超大L1 Cache是一件复杂的事情,对于L1 Cache,我们都希望它的访问延迟尽可能低。而由于我们目前的处理器和操作系统采用的虚拟内存分页机制,在使用虚拟地址访问内存时,需要首先得到对应虚拟地址的物理地址,这就导致在一条访存指令算出访存的虚拟地址后,我们首先需要查询TLB,而若查询TLB再将地址送入缓存,无疑增加了访问延迟。而对于许多高性能设计的处理器而言,L1 Cache的访问往往是制约处理器频率的主要关键路径,因此涉及到L1 Cache的电路路径都需要非常慎重考虑具体设计的路径长度。 基于目前CPU中的Cache主要采用组相连的结构,在该结构上解决方法通常采用VIPT的方式,即Virtually Indexed Physically Tagged。如下图所示,通过虚拟地址的一部分作为访问Cache的索引,同时将虚拟地址送入TLB中,这样我们就实现了电路上访问Cache与访问TLB的并行,在访问结束后对比TLB输出的物理地址高位与Cache访问得到的物理地址Tag,就完成了缓存是否命中的判断。 VIPT Cache在具体实现时,我们需要考虑缓存重名的问题。例如CPU上运行着2个进程有一个共享内存,这块共享内存对应着一块物理地址,但在2个进程中的虚拟地址不同,而如果CPU只是简单地将两份虚拟地址的数据都直接保存在缓存中,就会导致缓存不一致的问题。 SOTA的大部分处理器并未解决该问题(例如我们常见的Intel和AMD),只是将VIPT简化为伪VIPT。因为在许多ISA的虚拟内存管理中,最小页面大小为4KB,因此,我只需要保证作为Index的部分在虚拟地址的低12位内(即4KB内)即可。不过,这种方法导致L1 Cache中单路的大小无法超过MMU规定的最小页面大小,而组相连的场景下,随着路数增加,电路上判断并选择带来的电路长度也随之增加,同样提高了电路的延迟,导致频率的降低或划分流水线阶段后IPC(Instructions…

Back to Top