Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
LEAP provides a number of memory services, ranging from small and fast memories to large structures backed by cache hierarchies.
Based on Bluespec’s RegFile, LUTRAM allocates LUT-based storage. The result of a LUTRAM read may be used in the same cycle as the read request. The base LUTRAM implementation (mkLUTRAMU) is implemented as a RegFile and exists as a separate module only to work around a bug in some Xilinx synthesis tools that incorrectly moves some LUT-based storage to Block RAMs, even when a Block RAM’s next-cycle read latency is inappropriate for the design.
A number of wrappers around the base LUTRAM are provided:
- mkLUTRAMInitialized() and mkLUTRAMWith() instantiate initialized storage.
- mkLUTRAMWithGet() also generates initialized storage, taking the initial data from a Get() interface. With this interface it is easy to initialize a LUTRAM from a software-generated stream.
- Like RegFile, LUTRAM read ports are managed by the Bluespec compiler. The compiler allocates at most 5 read ports and attempts to share ports across rules when it can be proven the rules are mutually exclusive. mkMultiReadLUTRAM() provides a LUTRAM with an explicit number of user-managed read ports. Explicitly naming ports is useful either when the number of read ports is greater than 5 or when the compiler’s allocation of read ports is inefficient.
Like LUTRAM, FPGA block RAM is also on-die storage. Block RAM is larger and denser, but has a one cycle read to use latency. LEAP’s block RAM implementation predates the library now provided with Bluespec. The LEAP version could, at some point, be reimplemented with Bluespec’s. The interface and module name would remain unchanged. All LEAP block RAM modules return the MEMORY_IFC interface.
Like LUTRAM, LEAP provides a number of wrappers around the base mkBRAM:
- mkBRAMInitialized and mkBRAMInitializedWith generate initialized storage.
- mkBRAMMultiRead builds a RAM with multiple read ports. Like LUTRAM, extra read ports are expensive. The separate copy of the RAM is replicated for each port.
- mkBRAMPseudoMultiRead is a less costly implementation of a RAM with multiple read ports. The interface is identical to mkBRAMMultiRead but only one memory is allocated. Because the memory is shared among all readers, read requests conflict with each other, even from separate ports. The pseudo-multi-read modules are useful for managing multiple read request/response rules and routing read responses to the rules corresponding to their read requests.
LEAP scratchpads are hierarchical storage structures, providing memories that have the same interface as block RAMs but permitting the allocation of arrays larger than would fit on an FPGA. A typical scratchpad builds a private L1 cache, shares an L2 cache in a large memory (e.g. on-board SDRAM) and is backed by host-side virtual memory. Like block RAM, scratchpad modules implement a MEMORY_IFC interface. In user code, mkScratchpad may replace any mkBRAM. Aside from memory size, the only visible difference will be the latencies of operations.
The base mkScratchpad() module takes two arguments: a user-provided UID to identify the scratchpad and a boolean indicating whether to allocate a cache hierarchy. Cached scratchpads allocate a private L1 cache. L1 caches are connected to a last-level cache that is shared, dynamically, among all scratchpads. Scratchpads are initialized with zeros.
mkMultiReadScratchpad() builds a scratchpad with multiple read ports. The read ports share the same L1 cache read port. Output read response buffering is provided, allowing reads on one port to bypass unconsumed reads on another port.
LEAP offers the ability to describe coherent memory spaces.