MMU的设计

本文转载自: FPGA的现今未微信公众号

注:本文由作者授权转发,如需转载请联系作者本人

什么是MMU?MMU是Memory Management Unit的缩写,这原本是软件内存管理方面的一个概念,这里我们借用到了FPGA设计里,主要用于管理大缓存,比如DDR等。在说明这个问题前,我们先说明DDR使用的一种场景。

DDR在使用的时候,往往先把DDR划分成固定大小的“block”块,如下图所示,每个块的容量大小根据具体的使用场景有所不同,比如64byte、128byte、256byte、512byte、2Kbyte、4Kbyte等。为了便于对这些块的寻址,我们需要给每个块进行编号,编号可以是每个块的首地址,也可以是块的序号。那么这些编号如何管理呢?这就需要这个MMU的模块。

假定如下一个场景,某个功能收到报文后需要提取报文头某些字段,然后把报文缓存到DDR中,报文长度不超过1500byte。将报文头送给后继模块处理,处理完成后读出报文如下图所示。

我们现在假定一个场景,那就是存入DDR的报文顺序和读出DDR的报文顺序是一致的,即把DDR当成一个大“FIFO”,报文先进先出。那MMU的管理会非常简单,简单到用2个计数器就可以搞定。一个计数器用来记录MMU中剩余的DDR块数,一个计数器用来指示下一次要使用的块。

这里再假定一种复杂点的场景,假定每个报文处理的时间不一致,那么报文读出的顺序就会出现乱序。即随着DDR块的使用和释放,对MMU请求获得的块序号将不再是连续的,以4个块为例,如下图所示:

这个场景的MMU如何设计了,MMU主要有3个功能,第一就是块序号的初始化;第二是块序号的发送;第三是块序号的回收。MMU模块的架构如下图所示:

初始化逻辑完成上电或者复位后,对MMU管理的块序号进行初始化,假定块序号从0到FFF。
发送逻辑,当用户对MMU有请求的时候,将可用的块序号发送给用户。
回收逻辑,当用户将数据从DDR块中读出后,需要将该块释放,即要把块序号给到MMU模块,以便下次重复利用该DDR块。
总结下,MMU模块就是对DDR块的申请和回收,即对块号0到FFF的管理。从这个角度看,MMU管理还是非常简单。

MMU有一个致命的地方,会出现“踩内存”,定位起来非常复杂。例如当用户释放MMU块号的时候,如果因为用户的原因多释放块号,就会出现相同的块号,如果被2个以上用户同时使用的时候,就会出现“踩内存”,它的致命点在于多释放MMU块的时间和出现“踩内存”的时间可能相隔很久,使得问题的定位非常困难。
从可靠性来讲,这里需要配套一个内存检测模块,比如基于bitmap查找的方式,如果检测到用户释放回重复的内存块,就及时拦截或者告警,提前发现问题,方便问题的定位和解决。

关于MMU的设计,就介绍到这里,如果有其他问题,欢迎留言交流。