mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	Add memory_libmap pass.
This commit is contained in:
		
							parent
							
								
									9450f308f0
								
							
						
					
					
						commit
						7c5dba8b77
					
				
					 6 changed files with 3884 additions and 0 deletions
				
			
		| 
						 | 
					@ -29,10 +29,12 @@ X(A_SIGNED)
 | 
				
			||||||
X(A_WIDTH)
 | 
					X(A_WIDTH)
 | 
				
			||||||
X(B)
 | 
					X(B)
 | 
				
			||||||
X(BI)
 | 
					X(BI)
 | 
				
			||||||
 | 
					X(BITS_USED)
 | 
				
			||||||
X(blackbox)
 | 
					X(blackbox)
 | 
				
			||||||
X(B_SIGNED)
 | 
					X(B_SIGNED)
 | 
				
			||||||
X(bugpoint_keep)
 | 
					X(bugpoint_keep)
 | 
				
			||||||
X(B_WIDTH)
 | 
					X(B_WIDTH)
 | 
				
			||||||
 | 
					X(BYTE)
 | 
				
			||||||
X(C)
 | 
					X(C)
 | 
				
			||||||
X(cells_not_processed)
 | 
					X(cells_not_processed)
 | 
				
			||||||
X(CE_OVER_SRST)
 | 
					X(CE_OVER_SRST)
 | 
				
			||||||
| 
						 | 
					@ -116,6 +118,8 @@ X(keep_hierarchy)
 | 
				
			||||||
X(L)
 | 
					X(L)
 | 
				
			||||||
X(lib_whitebox)
 | 
					X(lib_whitebox)
 | 
				
			||||||
X(localparam)
 | 
					X(localparam)
 | 
				
			||||||
 | 
					X(logic_block)
 | 
				
			||||||
 | 
					X(lram)
 | 
				
			||||||
X(LUT)
 | 
					X(LUT)
 | 
				
			||||||
X(lut_keep)
 | 
					X(lut_keep)
 | 
				
			||||||
X(M)
 | 
					X(M)
 | 
				
			||||||
| 
						 | 
					@ -145,6 +149,9 @@ X(PRIORITY_MASK)
 | 
				
			||||||
X(Q)
 | 
					X(Q)
 | 
				
			||||||
X(qwp_position)
 | 
					X(qwp_position)
 | 
				
			||||||
X(R)
 | 
					X(R)
 | 
				
			||||||
 | 
					X(ram_block)
 | 
				
			||||||
 | 
					X(ram_style)
 | 
				
			||||||
 | 
					X(ramstyle)
 | 
				
			||||||
X(RD_ADDR)
 | 
					X(RD_ADDR)
 | 
				
			||||||
X(RD_ARST)
 | 
					X(RD_ARST)
 | 
				
			||||||
X(RD_ARST_VALUE)
 | 
					X(RD_ARST_VALUE)
 | 
				
			||||||
| 
						 | 
					@ -164,6 +171,9 @@ X(RD_TRANSPARENT)
 | 
				
			||||||
X(RD_WIDE_CONTINUATION)
 | 
					X(RD_WIDE_CONTINUATION)
 | 
				
			||||||
X(reg)
 | 
					X(reg)
 | 
				
			||||||
X(reprocess_after)
 | 
					X(reprocess_after)
 | 
				
			||||||
 | 
					X(rom_block)
 | 
				
			||||||
 | 
					X(rom_style)
 | 
				
			||||||
 | 
					X(romstyle)
 | 
				
			||||||
X(S)
 | 
					X(S)
 | 
				
			||||||
X(SET)
 | 
					X(SET)
 | 
				
			||||||
X(SET_POLARITY)
 | 
					X(SET_POLARITY)
 | 
				
			||||||
| 
						 | 
					@ -186,6 +196,8 @@ X(STATE_NUM_LOG2)
 | 
				
			||||||
X(STATE_RST)
 | 
					X(STATE_RST)
 | 
				
			||||||
X(STATE_TABLE)
 | 
					X(STATE_TABLE)
 | 
				
			||||||
X(submod)
 | 
					X(submod)
 | 
				
			||||||
 | 
					X(syn_ramstyle)
 | 
				
			||||||
 | 
					X(syn_romstyle)
 | 
				
			||||||
X(S_WIDTH)
 | 
					X(S_WIDTH)
 | 
				
			||||||
X(T)
 | 
					X(T)
 | 
				
			||||||
X(TABLE)
 | 
					X(TABLE)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,4 +9,6 @@ OBJS += passes/memory/memory_map.o
 | 
				
			||||||
OBJS += passes/memory/memory_memx.o
 | 
					OBJS += passes/memory/memory_memx.o
 | 
				
			||||||
OBJS += passes/memory/memory_nordff.o
 | 
					OBJS += passes/memory/memory_nordff.o
 | 
				
			||||||
OBJS += passes/memory/memory_narrow.o
 | 
					OBJS += passes/memory/memory_narrow.o
 | 
				
			||||||
 | 
					OBJS += passes/memory/memory_libmap.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OBJS += passes/memory/memlib.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1101
									
								
								passes/memory/memlib.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1101
									
								
								passes/memory/memlib.cc
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										171
									
								
								passes/memory/memlib.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								passes/memory/memlib.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,171 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  yosys -- Yosys Open SYnthesis Suite
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Copyright (C) 2021  Marcelina Kościelnicka <mwk@0x04.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Permission to use, copy, modify, and/or distribute this software for any
 | 
				
			||||||
 | 
					 *  purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 *  copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
				
			||||||
 | 
					 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
				
			||||||
 | 
					 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MEMLIB_H
 | 
				
			||||||
 | 
					#define MEMLIB_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "kernel/yosys.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					YOSYS_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MemLibrary {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class RamKind {
 | 
				
			||||||
 | 
						Auto,
 | 
				
			||||||
 | 
						Logic,
 | 
				
			||||||
 | 
						NotLogic,
 | 
				
			||||||
 | 
						Distributed,
 | 
				
			||||||
 | 
						Block,
 | 
				
			||||||
 | 
						Huge,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class WidthMode {
 | 
				
			||||||
 | 
						Single,
 | 
				
			||||||
 | 
						Global,
 | 
				
			||||||
 | 
						PerPort,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class MemoryInitKind {
 | 
				
			||||||
 | 
						None,
 | 
				
			||||||
 | 
						Zero,
 | 
				
			||||||
 | 
						Any,
 | 
				
			||||||
 | 
						NoUndef,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class PortKind {
 | 
				
			||||||
 | 
						Sr,
 | 
				
			||||||
 | 
						Ar,
 | 
				
			||||||
 | 
						Sw,
 | 
				
			||||||
 | 
						Srsw,
 | 
				
			||||||
 | 
						Arsw,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class ClkPolKind {
 | 
				
			||||||
 | 
						Anyedge,
 | 
				
			||||||
 | 
						Posedge,
 | 
				
			||||||
 | 
						Negedge,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class RdWrKind {
 | 
				
			||||||
 | 
						Undefined,
 | 
				
			||||||
 | 
						NoChange,
 | 
				
			||||||
 | 
						New,
 | 
				
			||||||
 | 
						Old,
 | 
				
			||||||
 | 
						NewOnly,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class ResetValKind {
 | 
				
			||||||
 | 
						None,
 | 
				
			||||||
 | 
						Zero,
 | 
				
			||||||
 | 
						Any,
 | 
				
			||||||
 | 
						NoUndef,
 | 
				
			||||||
 | 
						Init,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class SrstKind {
 | 
				
			||||||
 | 
						None,
 | 
				
			||||||
 | 
						Ungated,
 | 
				
			||||||
 | 
						GatedClkEn,
 | 
				
			||||||
 | 
						GatedRdEn,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class WrTransTargetKind {
 | 
				
			||||||
 | 
						All,
 | 
				
			||||||
 | 
						Group,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class WrTransKind {
 | 
				
			||||||
 | 
						New,
 | 
				
			||||||
 | 
						Old,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct WrTransDef {
 | 
				
			||||||
 | 
						WrTransTargetKind target_kind;
 | 
				
			||||||
 | 
						int target_group;
 | 
				
			||||||
 | 
						WrTransKind kind;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct PortVariant {
 | 
				
			||||||
 | 
						dict<std::string, Const> options;
 | 
				
			||||||
 | 
						PortKind kind;
 | 
				
			||||||
 | 
						int clk_shared;
 | 
				
			||||||
 | 
						ClkPolKind clk_pol;
 | 
				
			||||||
 | 
						bool clk_en;
 | 
				
			||||||
 | 
						bool width_tied;
 | 
				
			||||||
 | 
						int min_wr_wide_log2;
 | 
				
			||||||
 | 
						int max_wr_wide_log2;
 | 
				
			||||||
 | 
						int min_rd_wide_log2;
 | 
				
			||||||
 | 
						int max_rd_wide_log2;
 | 
				
			||||||
 | 
						bool rd_en;
 | 
				
			||||||
 | 
						RdWrKind rdwr;
 | 
				
			||||||
 | 
						ResetValKind rdinitval;
 | 
				
			||||||
 | 
						ResetValKind rdarstval;
 | 
				
			||||||
 | 
						ResetValKind rdsrstval;
 | 
				
			||||||
 | 
						SrstKind rdsrstmode;
 | 
				
			||||||
 | 
						bool rdsrst_block_wr;
 | 
				
			||||||
 | 
						bool wrbe_separate;
 | 
				
			||||||
 | 
						std::vector<int> wrprio;
 | 
				
			||||||
 | 
						std::vector<WrTransDef> wrtrans;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct PortGroup {
 | 
				
			||||||
 | 
						bool optional;
 | 
				
			||||||
 | 
						bool optional_rw;
 | 
				
			||||||
 | 
						std::vector<std::string> names;
 | 
				
			||||||
 | 
						std::vector<PortVariant> variants;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct RamClock {
 | 
				
			||||||
 | 
						std::string name;
 | 
				
			||||||
 | 
						bool anyedge;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Ram {
 | 
				
			||||||
 | 
						IdString id;
 | 
				
			||||||
 | 
						RamKind kind;
 | 
				
			||||||
 | 
						dict<std::string, Const> options;
 | 
				
			||||||
 | 
						std::vector<PortGroup> port_groups;
 | 
				
			||||||
 | 
						bool prune_rom;
 | 
				
			||||||
 | 
						int abits;
 | 
				
			||||||
 | 
						std::vector<int> dbits;
 | 
				
			||||||
 | 
						WidthMode width_mode;
 | 
				
			||||||
 | 
						std::string resource_name;
 | 
				
			||||||
 | 
						int resource_count;
 | 
				
			||||||
 | 
						double cost;
 | 
				
			||||||
 | 
						double widthscale;
 | 
				
			||||||
 | 
						int byte;
 | 
				
			||||||
 | 
						MemoryInitKind init;
 | 
				
			||||||
 | 
						std::vector<std::string> style;
 | 
				
			||||||
 | 
						std::vector<RamClock> shared_clocks;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Library {
 | 
				
			||||||
 | 
						std::vector<Ram> rams;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Library parse_library(const std::vector<std::string> &filenames, const pool<std::string> &defines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					YOSYS_NAMESPACE_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										505
									
								
								passes/memory/memlib.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										505
									
								
								passes/memory/memlib.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,505 @@
 | 
				
			||||||
 | 
					# The `memory_libmap` pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `memory_libmap` pass is used to map memories to hardware primitives.  To work,
 | 
				
			||||||
 | 
					it needs a description of available target memories in a custom format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Basic structure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A basic library could look like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # A distributed-class RAM called $__RAM16X4SDP_
 | 
				
			||||||
 | 
					    ram distributed $__RAM16X4SDP_ {
 | 
				
			||||||
 | 
					        # Has 4 address bits (ie. 16 rows).
 | 
				
			||||||
 | 
					        abits 4;
 | 
				
			||||||
 | 
					        # Has 4 data bits.
 | 
				
			||||||
 | 
					        width 4;
 | 
				
			||||||
 | 
					        # Cost for the selection heuristic.
 | 
				
			||||||
 | 
					        cost 4;
 | 
				
			||||||
 | 
					        # Can be initialized to any value on startup.
 | 
				
			||||||
 | 
					        init any;
 | 
				
			||||||
 | 
					        # Has a synchronous write port called "W"...
 | 
				
			||||||
 | 
					        port sw "W" {
 | 
				
			||||||
 | 
					            # ... with a positive edge clock.
 | 
				
			||||||
 | 
					            clock posedge;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        # Has an asynchronous read port called "R".
 | 
				
			||||||
 | 
					        port ar "R" {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # A block-class RAM called $__RAMB9K_
 | 
				
			||||||
 | 
					    ram block $__RAMB9K_ {
 | 
				
			||||||
 | 
					        # Has 13 address bits in the base (most narrow) data width.
 | 
				
			||||||
 | 
					        abits 13;
 | 
				
			||||||
 | 
					        # The available widths are:
 | 
				
			||||||
 | 
					        # - 1 (13 address bits)
 | 
				
			||||||
 | 
					        # - 2 (12 address bits)
 | 
				
			||||||
 | 
					        # - 4 (11 address bits)
 | 
				
			||||||
 | 
					        # - 9 (10 address bits)
 | 
				
			||||||
 | 
					        # - 18 (9 address bits)
 | 
				
			||||||
 | 
					        # The width selection is per-port.
 | 
				
			||||||
 | 
					        widths 1 2 4 9 18 per_port;
 | 
				
			||||||
 | 
					        # Has a write enable signal with 1 bit for every 9 data bits.
 | 
				
			||||||
 | 
					        byte 9;
 | 
				
			||||||
 | 
					        cost 64;
 | 
				
			||||||
 | 
					        init any;
 | 
				
			||||||
 | 
					        # Has two synchronous read+write ports, called "A" and "B".
 | 
				
			||||||
 | 
					        port srsw "A" "B" {
 | 
				
			||||||
 | 
					            clock posedge;
 | 
				
			||||||
 | 
					            # Has a clock enable signal (gates both read and write).
 | 
				
			||||||
 | 
					            clken;
 | 
				
			||||||
 | 
					            # Has three per-port selectable options for handling read+write behavior:
 | 
				
			||||||
 | 
					            portoption "RDWR" "NO_CHANGE" {
 | 
				
			||||||
 | 
					                # When port is writing, reading is not done (output register keeps
 | 
				
			||||||
 | 
					                # its value).
 | 
				
			||||||
 | 
					                rdwr no_change;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            portoption "RDWR" "OLD" {
 | 
				
			||||||
 | 
					                # When port is writing, the data read is the old value (before the
 | 
				
			||||||
 | 
					                # write).
 | 
				
			||||||
 | 
					                rdwr old;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            portoption "RDWR" "NEW" {
 | 
				
			||||||
 | 
					                # When port is writing, the data read is the new value.
 | 
				
			||||||
 | 
					                rdwr new;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The pass will automatically select between the two available cells and
 | 
				
			||||||
 | 
					the logic fallback (mapping the whole memory to LUTs+FFs) based on required
 | 
				
			||||||
 | 
					capabilities and cost function.  The selected memories will be transformed
 | 
				
			||||||
 | 
					to intermediate `$__RAM16X4SDP_` and `$__RAMB9K_` cells that need to be mapped
 | 
				
			||||||
 | 
					to actual hardware cells by a `techmap` pass, while memories selected for logic
 | 
				
			||||||
 | 
					fallback will be left unmapped and will be later mopped up by `memory_map` pass.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## RAM definition blocks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The syntax for a RAM definition is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ram <kind: distributed|block|huge> <name> {
 | 
				
			||||||
 | 
					        <ram properties>
 | 
				
			||||||
 | 
					        <ports>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `<name>` is used as the type of the mapped cell that will be passed to `techmap`.
 | 
				
			||||||
 | 
					The memory kind is one of `distributed`, `block`, or `huge`.  It describes the general
 | 
				
			||||||
 | 
					class of the memory and can be matched on by manual selection attributes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The available ram properties are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `abits <address bits>;`
 | 
				
			||||||
 | 
					- `width <width>;`
 | 
				
			||||||
 | 
					- `widths <width 1> <width 2> ... <width n> <global|per_port>;`
 | 
				
			||||||
 | 
					- `byte <width>;`
 | 
				
			||||||
 | 
					- `cost <cost>;`
 | 
				
			||||||
 | 
					- `widthscale [<factor>];`
 | 
				
			||||||
 | 
					- `resource <name> <count>;`
 | 
				
			||||||
 | 
					- `init <none|zero|any|no_undef>;`
 | 
				
			||||||
 | 
					- `style "<name 1>" "<name 2>" "<name 3>" ...;`
 | 
				
			||||||
 | 
					- `prune_rom;`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### RAM dimensions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The memory dimensions are described by `abits` and `width` or `widths` properties.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For a simple memory cell with a fixed width, use `abits` and `width` like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    abits 4;
 | 
				
			||||||
 | 
					    width 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This will result in a `2**abits × width` memory cell.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Multiple-width memories are also possible, and use the `widths` property instead.
 | 
				
			||||||
 | 
					The rules for multiple-width memories are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- the widths are given in `widths` property in increasing order
 | 
				
			||||||
 | 
					- the value in the `abits` property corresponds to the most narrow width
 | 
				
			||||||
 | 
					- every width in the list needs to be greater than or equal to twice
 | 
				
			||||||
 | 
					  the previous width (ie. `1 2 4 9 18` is valid, `1 2 4 7 14` is not)
 | 
				
			||||||
 | 
					- it is assumed that, for every width in progression, the word in memory
 | 
				
			||||||
 | 
					  is made of two smaller words, plus optionally some extra bits (eg. in the above
 | 
				
			||||||
 | 
					  list, the 9-bit word is made of two 4-bit words and 1 extra bit), and thus
 | 
				
			||||||
 | 
					  each sequential width in the list corresponds to one fewer usable address bit
 | 
				
			||||||
 | 
					- all addresses connected to memory ports are always `abits` bits wide, with const
 | 
				
			||||||
 | 
					  zero wired to the unused bits corresponding to wide ports
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When multiple widths are specified, they can be `per_port` or `global`.
 | 
				
			||||||
 | 
					For the `global` version, the pass has to pick one width for the whole cell,
 | 
				
			||||||
 | 
					and it is set on the resulting cell as the `WIDTH` parameter.  For the `per_port`
 | 
				
			||||||
 | 
					version, the selection is made on per-port basis, and passed using `PORT_*_WIDTH`
 | 
				
			||||||
 | 
					parameters.  When the mode is `per_port`, the width selection can be fine-tuned
 | 
				
			||||||
 | 
					with the port `width` property.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Specifying dimensions is mandatory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Byte width
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the memory cell has per-byte write enables, the `byte` property can be used
 | 
				
			||||||
 | 
					to define the byte size (ie. how many data bits correspond to one write enable
 | 
				
			||||||
 | 
					bit).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The property is optional.  If not used, it is assumed that there is a single
 | 
				
			||||||
 | 
					write enable signal for each writable port.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The rules for this property are as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- for every available width, the width needs to be a multiple of the byte size,
 | 
				
			||||||
 | 
					  or the byte size needs to be larger than the width
 | 
				
			||||||
 | 
					- if the byte size is larger than the width, the byte enable signel is assumed
 | 
				
			||||||
 | 
					  to be one bit wide and cover the whole port
 | 
				
			||||||
 | 
					- otherwise, the byte enable signal has one bit for every `byte` bits of the
 | 
				
			||||||
 | 
					  data port
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The exact kind of byte enable signal is determined by the presence or absence
 | 
				
			||||||
 | 
					of the per-port `wrbe_separate` property.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Cost properties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `cost` property is used to estimate the cost of using a given mapping.
 | 
				
			||||||
 | 
					This is the cost of using one cell, and will be scaled as appropriate if
 | 
				
			||||||
 | 
					the mapping requires multiple cells.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the `widthscale` property is specified, the mapping is assumed to be flexible,
 | 
				
			||||||
 | 
					with cost scaling with the percentage of data width actually used.  The value
 | 
				
			||||||
 | 
					of the `widthscale` property is how much of the cost is scalable as such.
 | 
				
			||||||
 | 
					If the value is omitted, all of the cost is assumed to scale.
 | 
				
			||||||
 | 
					Eg. for the following properties:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    width 14;
 | 
				
			||||||
 | 
					    cost 8;
 | 
				
			||||||
 | 
					    widthscale 7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The cost of a given cell will be assumed to be `(8 - 7) + 7 * (used_bits / 14)`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If `widthscale` is used, The pass will attach a `BITS_USED` parameter to mapped
 | 
				
			||||||
 | 
					calls, with a bitmask of which data bits of the memory are actually in use.
 | 
				
			||||||
 | 
					The parameter width will be the widest width in the `widths` property, and
 | 
				
			||||||
 | 
					the bit correspondence is defined accordingly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `cost` property is mandatory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `init` property
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This property describes the state of the memory at initialization time.  Can have
 | 
				
			||||||
 | 
					one of the following values:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `none`: the memory contents are unpredictable, memories requiring any sort
 | 
				
			||||||
 | 
					  of initialization will not be mapped to this cell
 | 
				
			||||||
 | 
					- `zero`: the memory contents are zero, memories can be mapped to this cell iff
 | 
				
			||||||
 | 
					  their initialization value is entirely zero or undef
 | 
				
			||||||
 | 
					- `any`: the memory contents can be arbitrarily selected, and the initialization
 | 
				
			||||||
 | 
					  will be passes as the `INIT` parameter to the mapped cell
 | 
				
			||||||
 | 
					- `no_undef`: like `any`, but only 0 and 1 bit values are supported (the pass will
 | 
				
			||||||
 | 
					  convert any x bits to 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `INIT` parameter is always constructed as a concatenation of words corresponding
 | 
				
			||||||
 | 
					to the widest available `widths` setting, so that all available memory cell bits
 | 
				
			||||||
 | 
					are covered.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This property is optional and assumed to be `none` when not present.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `style` property
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Provides a name (or names) for this definition that can be passed to the `ram_style`
 | 
				
			||||||
 | 
					or similar attribute to manually select it.  Optional and can be used multiple times.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `prune_rom` property
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Specifying this property disqualifies the definition from consideration for source
 | 
				
			||||||
 | 
					memories that have no write ports (ie. ROMs).  Use this on definitions that have
 | 
				
			||||||
 | 
					an obviously superior read-only alternative (eg. LUTRAMs) to make the pass skip
 | 
				
			||||||
 | 
					them over quickly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Port definition blocks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The syntax for a port group definition is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    port <ar|sr|sw|arsw|srsw> "NAME 1" "NAME 2" ... {
 | 
				
			||||||
 | 
					        <port properties>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A port group definition defines a group of ports with identical properties.
 | 
				
			||||||
 | 
					There are as many ports in a group as there are names given.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ports come in 5 kinds:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `ar`: asynchronous read port
 | 
				
			||||||
 | 
					- `sr`: synchronous read port
 | 
				
			||||||
 | 
					- `sw`: synchronous write port
 | 
				
			||||||
 | 
					- `arsw`: simultanous synchronous write + asynchronous read with common address (commonly found in LUT RAMs)
 | 
				
			||||||
 | 
					- `srsw`: synchronous write + synchronous read with common address
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The port properties available are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `width <tied|mix>;`
 | 
				
			||||||
 | 
					- `width <width 1> <width 2> ...;`
 | 
				
			||||||
 | 
					- `width <tied|mix> <width 1> <width 2> ...;`
 | 
				
			||||||
 | 
					- `width rd <width 1> <width 2> ... wr <width 1> <width 2> ...;`
 | 
				
			||||||
 | 
					- `clock <posedge|negedge|anyedge> ["SHARED_NAME"];`
 | 
				
			||||||
 | 
					- `clken;`
 | 
				
			||||||
 | 
					- `rden;`
 | 
				
			||||||
 | 
					- `wrbe_separate;`
 | 
				
			||||||
 | 
					- `rdwr <undefined|no_change|new|old|new_only>;`
 | 
				
			||||||
 | 
					- `rdinit <none|zero|any|no_undef>;`
 | 
				
			||||||
 | 
					- `rdarst <none|zero|any|no_undef|init>;`
 | 
				
			||||||
 | 
					- `rdsrst <none|zero|any|no_undef|init> <ungated|gatec_clken|gated_rden> [block_wr];`
 | 
				
			||||||
 | 
					- `wrprio "NAME" "NAME" ...;`
 | 
				
			||||||
 | 
					- `wrtrans <"NAME"|all> <old|new>;`
 | 
				
			||||||
 | 
					- `optional;`
 | 
				
			||||||
 | 
					- `optional_rw;`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The base signals connected to the mapped cell for ports are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `PORT_<name>_ADDR`: the address
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_DATA`: the write data (for `sw`/`arsw`/`srsw` ports only)
 | 
				
			||||||
 | 
					- `PORT_<name>_RD_DATA`: the read data (for `ar`/`sr`/`arsw`/`srsw` ports only)
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_EN`: the write enable or enables (for `sw`/`arsw`/`srsw` ports only)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The address is always `abits` wide.  If a non-narrowest width is used, the appropriate low
 | 
				
			||||||
 | 
					bits will be tied to 0.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Port `width` prooperty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the RAM has `per_port` widths, the available width selection can be further described
 | 
				
			||||||
 | 
					on per-port basis, by using one of the following properties:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `width tied;`: any width from the master `widths` list is acceptable, and
 | 
				
			||||||
 | 
					  (for read+write ports) the read and write width has to be the same
 | 
				
			||||||
 | 
					- `width tied <width 1> <width 2> ...;`: like above, but limits the width
 | 
				
			||||||
 | 
					  selection to the given list; the list has to be a contiguous sublist of the
 | 
				
			||||||
 | 
					  master `widths` list
 | 
				
			||||||
 | 
					- `width <width 1> <width 2> ...;`: alias for the above, to be used for read-only
 | 
				
			||||||
 | 
					  or write-only ports
 | 
				
			||||||
 | 
					- `width mix;`: any width from the master `widths` list is acceptable, and
 | 
				
			||||||
 | 
					  read width can be different than write width (only usable for read+write ports)
 | 
				
			||||||
 | 
					- `width mix <width 1> <width 2> ...;`: like above, but limits the width
 | 
				
			||||||
 | 
					  selection to the given list; the list has to be a contiguous sublist of the
 | 
				
			||||||
 | 
					  master `widths` list
 | 
				
			||||||
 | 
					- `width rd <width 1> <width 2> ... wr <width 1> <width 2> ...;`: like above,
 | 
				
			||||||
 | 
					  but the limitted selection can be different for read and write widths
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If `per_port` widths are in use and this property is not specified, `width tied;` is assumed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The parameters attached to the cell in `per_port` widths mode are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `PORT_<name>_WIDTH`: the selected width (for `tied` ports)
 | 
				
			||||||
 | 
					- `PORT_<name>_RD_WIDTH`: the selected read width (for `mix` ports)
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_WIDTH`: the selected write width (for `mix` ports)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `clock` property
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `clock` property is used with synchronous ports (and synchronous ports only).
 | 
				
			||||||
 | 
					It is mandatory for them and describes the clock polarity and clock sharing.
 | 
				
			||||||
 | 
					`anyedge` means that both polarities are supported.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If a shared clock name is provided, the port is assumed to have a shared clock signal
 | 
				
			||||||
 | 
					with all other ports using the same shared name.  Otherwise, the port is assumed to
 | 
				
			||||||
 | 
					have its own clock signal.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The port clock is always provided on the memory cell as `PORT_<name>_CLK` signal
 | 
				
			||||||
 | 
					(even if it is also shared).  Shared clocks are also provided as `CLK_<shared_name>`
 | 
				
			||||||
 | 
					signals.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For `anyedge` clocks, the cell gets a `PORT_<name>_CLKPOL` parameter that is set
 | 
				
			||||||
 | 
					to 1 for `posedge` clocks and 0 for `negedge` clocks.  If the clock is shared,
 | 
				
			||||||
 | 
					the same information will also be provided as `CLK_<shared_name>_POL` parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `clken` and `rden`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `clken` property, if present, means that the port has a clock enable signal
 | 
				
			||||||
 | 
					gating both reads and writes.  Such signal will be provided to the mapped cell
 | 
				
			||||||
 | 
					as `PORT_<name>_CLK_EN`.  It is only applicable to synchronous ports.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `rden` property, if present, means that the port has a read clock enable signal.
 | 
				
			||||||
 | 
					Such signal will be provided to the mapped cell as `PORT_<name>_RD_EN`.  It is only
 | 
				
			||||||
 | 
					applicable to synchronous read ports (`sr` and `srsw`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For `sr` ports, both of these options are effectively equivalent.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `wrbe_separate` and the write enables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `wrbe_separate` property specifies that the write byte enables are provided
 | 
				
			||||||
 | 
					as a separate signal from the main write enable.  It can only be used when the
 | 
				
			||||||
 | 
					RAM-level `byte` property is also specified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The rules are as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If no `byte` is specified:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `wrbe_separate` is not allowed
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_EN` signal is single bit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If `byte` is specified, but `wrbe_separate` is not:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_EN` signal has one bit for every data byte
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_EN_WIDTH` parameter is the width of the above (only present for multiple-width cells)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If `byte` is specified and `wrbe_separate` is present:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_EN` signal is single bit
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_BE` signal has one bit for every data byte
 | 
				
			||||||
 | 
					- `PORT_<name>_WR_BE_WIDTH` parameter is the width of the above (only present for multiple-width cells)
 | 
				
			||||||
 | 
					- a given byte is written iff all of `CLK_EN` (if present), `WR_EN`, and the corresponding `WR_BE` bit are one
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This property can only be used on write ports.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `rdwr` property
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This property is allowed only on `srsw` ports and describes read-write interactions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The possible values are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `no_change`: if write is being performed (any bit of `WR_EN` is set),
 | 
				
			||||||
 | 
					  reading is not performed and the `RD_DATA` keeps its old value
 | 
				
			||||||
 | 
					- `undefined`: all `RD_DATA` bits corresponding to enabled `WR_DATA` bits
 | 
				
			||||||
 | 
					  have undefined value, remaining bits read from memory
 | 
				
			||||||
 | 
					- `old`: all `RD_DATA` bits get the previous value in memory
 | 
				
			||||||
 | 
					- `new`: all `RD_DATA` bits get the new value in memory (transparent write)
 | 
				
			||||||
 | 
					- `new_only`: all `RD_DATA` bits corresponding to enabled `WR_DATA` bits
 | 
				
			||||||
 | 
					  get the new value, all others are undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If this property is not found on an `srsw` port, `undefined` is assumed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Read data initial value and resets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `rdinit`, `rdarst`, and `rdsrst` are applicable only to synchronous read
 | 
				
			||||||
 | 
					ports.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`rdinit` describes the initial value of the read port data, and can be set to
 | 
				
			||||||
 | 
					one of the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `none`: initial data is indeterminate
 | 
				
			||||||
 | 
					- `zero`: initial data is all-0
 | 
				
			||||||
 | 
					- `any`: initial data is arbitrarily configurable, and the selected value
 | 
				
			||||||
 | 
					  will be attached to the cell as `PORT_<name>_RD_INIT_VALUE` parameter
 | 
				
			||||||
 | 
					- `no_undef`: like `any`, but only 0 and 1 bits are allowed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`rdarst` and `rdsrst` describe the asynchronous and synchronous reset capabilities.
 | 
				
			||||||
 | 
					The values are similar to `rdinit`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `none`: no reset
 | 
				
			||||||
 | 
					- `zero`: reset to all-0 data
 | 
				
			||||||
 | 
					- `any`: reset to arbitrary value, the selected value
 | 
				
			||||||
 | 
					  will be attached to the cell as `PORT_<name>_RD_ARST_VALUE` or
 | 
				
			||||||
 | 
					  `PORT_<name>_RD_SRST_VALUE` parameter
 | 
				
			||||||
 | 
					- `no_undef`: like `any`, but only 0 and 1 bits are allowed
 | 
				
			||||||
 | 
					- `init`: reset to the initial value, as specified by `rdinit` (which must be `any`
 | 
				
			||||||
 | 
					  or `no_undef` itself)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the capability is anything other than `none`, the reset signal
 | 
				
			||||||
 | 
					will be provided as `PORT_<name>_RD_ARST` or `PORT_<name>_RD_SRST`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For `rdsrst`, the priority must be additionally specified, as one of:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `ungated`: `RD_SRST` has priority over both `CLK_EN` and `RD_EN` (if present)
 | 
				
			||||||
 | 
					- `gated_clken`: `CLK_EN` has priority over `RD_SRST`; `RD_SRST` has priority over `RD_EN` if present
 | 
				
			||||||
 | 
					- `gated_rden`: `RD_EN` and `CLK_EN` (if present) both have priority over `RD_SRST`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Also, `rdsrst` can optionally have `block_wr` specified, which means that sync reset
 | 
				
			||||||
 | 
					cannot be performed in the same cycle as a write.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If not provided, `none` is assumed for all three properties.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Write priority
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `wrprio` property is only allowed on write ports and defines a priority relationship
 | 
				
			||||||
 | 
					between port — when `wrprio "B";` is used in definition of port `"A"`, and both ports
 | 
				
			||||||
 | 
					simultanously write to the same memory cell, the value written by port `"A"` will have
 | 
				
			||||||
 | 
					precedence.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This property is optional, and can be used multiple times as necessary.  If no relationship
 | 
				
			||||||
 | 
					is described for a pair of write ports, no priority will be assumed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Write transparency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `wrtrans` property is only allowed on write ports and defines behavior when
 | 
				
			||||||
 | 
					another synchronous read port reads from the memory cell at the same time as the
 | 
				
			||||||
 | 
					given port writes it.  The values are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `old`: the read port will get the old value of the cell
 | 
				
			||||||
 | 
					- `new`: the read port will get the new value of the cell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This property is optional, and can be used multiple times as necessary.  If no relationship
 | 
				
			||||||
 | 
					is described for a pair of ports, the value read is assumed to be indeterminate.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that this property is not used to describe the read value on the port itself for `srsw`
 | 
				
			||||||
 | 
					ports — for that purpose, the `rdwr` property is used instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Optional ports
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `optional;` property will make the pass attach a `PORT_<name>_USED` parameter
 | 
				
			||||||
 | 
					with a boolean value specifying whether a given port was meaningfully used in
 | 
				
			||||||
 | 
					mapping a given cell.  Likewise, `optional_rw;` will attach `PORT_<name>_RD_USED`
 | 
				
			||||||
 | 
					and `PORT_<name>_WR_USED` the specify whether the read / write part in particular
 | 
				
			||||||
 | 
					was used.  These can be useful if the mapping has some meaningful optimization
 | 
				
			||||||
 | 
					to apply for unused ports, but doesn't otherwise influence the selection process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For highly configurable cells, multiple variants may be described in one cell description.
 | 
				
			||||||
 | 
					All properties and port definitions within a RAM or port definition can be put inside
 | 
				
			||||||
 | 
					an `option` block as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    option "NAME" <value> {
 | 
				
			||||||
 | 
					        <properties, ports, ...>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The value and name of an option are arbitrary, and the selected option value
 | 
				
			||||||
 | 
					will be provided to the cell as `OPTION_<name>` parameter.  Values can be
 | 
				
			||||||
 | 
					strings or integers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Likewise, for per-port options, a `portoption` block can be used:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    portoption "NAME" <value> {
 | 
				
			||||||
 | 
					        <properties, ...>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These options will be provided as `PORT_<pname>_OPTION_<oname>` parameters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The library parser will simply expand the RAM definition for every possible combination
 | 
				
			||||||
 | 
					of option values mentioned in the RAM body, and likewise for port definitions.
 | 
				
			||||||
 | 
					This can lead to a combinatorial explosion.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If some option values cannot be used together, a `forbid` pseudo-property can be used
 | 
				
			||||||
 | 
					to discard a given combination, eg:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    option "ABC" 1 {
 | 
				
			||||||
 | 
					        portoption "DEF" "GHI" {
 | 
				
			||||||
 | 
					            forbid;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					will disallow combining the RAM option `ABC = 2` with port option `DEF = "GHI"`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Ifdefs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To allow reusing a library for multiple FPGA families with slighly differing
 | 
				
			||||||
 | 
					capabilities, `ifdef` (and `ifndef`) blocks are provided:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ifdef IS_FANCY_FPGA_WITH_CONFIGURABLE_ASYNC_RESET {
 | 
				
			||||||
 | 
					        rdarst any;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        rdarst zero;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Such blocks can be enabled by passing the `-D` option to the pass.
 | 
				
			||||||
							
								
								
									
										2093
									
								
								passes/memory/memory_libmap.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2093
									
								
								passes/memory/memory_libmap.cc
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue