mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Merge e7cfb0381c into 1b07d204bb
				
					
				
			This commit is contained in:
		
						commit
						7c2bffb645
					
				
					 4 changed files with 295 additions and 97 deletions
				
			
		| 
						 | 
					@ -28,9 +28,25 @@ struct CellType
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	RTLIL::IdString type;
 | 
						RTLIL::IdString type;
 | 
				
			||||||
	pool<RTLIL::IdString> inputs, outputs;
 | 
						pool<RTLIL::IdString> inputs, outputs;
 | 
				
			||||||
	bool is_evaluable;
 | 
						// Cell is defined in celltypes.h, as opposed to design-specific
 | 
				
			||||||
	bool is_combinatorial;
 | 
						bool is_internal;
 | 
				
			||||||
	bool is_synthesizable;
 | 
						// Cell can be handled by CellTypes::eval()
 | 
				
			||||||
 | 
						bool is_evaluable = false;
 | 
				
			||||||
 | 
						// Cell has no state; outputs are determined solely by inputs
 | 
				
			||||||
 | 
						bool is_combinatorial = false;
 | 
				
			||||||
 | 
						// Cell is able to be synthesized
 | 
				
			||||||
 | 
						bool is_synthesizable = false;
 | 
				
			||||||
 | 
						// Cell is built-in memory logic, includes flip-flops and latches, but not complex
 | 
				
			||||||
 | 
						// cells like $mem
 | 
				
			||||||
 | 
						bool is_builtin_ff = false;
 | 
				
			||||||
 | 
						// Cell is non-synthesizable, but used for formal verification
 | 
				
			||||||
 | 
						bool is_formal = false;
 | 
				
			||||||
 | 
						// Cell is intended for internal Yosys use, containing informational metadata and
 | 
				
			||||||
 | 
						// shouldn't be automatically cleaned; currently only used for $scopeinfo
 | 
				
			||||||
 | 
						bool is_metainfo = false;
 | 
				
			||||||
 | 
						// Non-synthesizable cell with effects that mean it shouldn't be automatically
 | 
				
			||||||
 | 
						// cleaned, e.g. $print
 | 
				
			||||||
 | 
						bool has_effects = false;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct CellTypes
 | 
					struct CellTypes
 | 
				
			||||||
| 
						 | 
					@ -58,12 +74,60 @@ struct CellTypes
 | 
				
			||||||
		setup_stdcells_mem();
 | 
							setup_stdcells_mem();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs, bool is_evaluable = false, bool is_combinatorial = false, bool is_synthesizable = false)
 | 
						void setup_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		CellType ct = {type, inputs, outputs, is_evaluable, is_combinatorial, is_synthesizable};
 | 
							CellType ct = { type, inputs, outputs, false };
 | 
				
			||||||
		cell_types[ct.type] = ct;
 | 
							cell_types[ct.type] = ct;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup internal cell type with no other default properties
 | 
				
			||||||
 | 
						void setup_internal_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs,
 | 
				
			||||||
 | 
								bool is_combinatorial = false, bool is_evaluable = false,
 | 
				
			||||||
 | 
								bool is_synthesizable = false, bool is_builtin_ff = false, bool is_formal = false,
 | 
				
			||||||
 | 
								bool is_metainfo = false, bool has_effects = false)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							CellType ct = {
 | 
				
			||||||
 | 
								type, inputs, outputs, true,
 | 
				
			||||||
 | 
								is_evaluable, is_combinatorial,
 | 
				
			||||||
 | 
								is_synthesizable, is_builtin_ff, is_formal,
 | 
				
			||||||
 | 
								is_metainfo, has_effects,
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							cell_types[ct.type] = ct;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup combinatorial cell type which is synthesizable and evaluable (by default)
 | 
				
			||||||
 | 
						void setup_comb_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs,
 | 
				
			||||||
 | 
								bool is_evaluable = true)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							setup_internal_type(type, inputs, outputs, true, is_evaluable, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup builtin ff cell type which is synthesizable
 | 
				
			||||||
 | 
						void setup_ff_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							setup_internal_type(type, inputs, outputs, false, false, true, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup formal cell type which may be combinatorial, and may have effects
 | 
				
			||||||
 | 
						void setup_formal_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs,
 | 
				
			||||||
 | 
								bool is_combinatorial = false)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							setup_internal_type(type, inputs, outputs, is_combinatorial, false, false, false, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup cell type which has effects, and may be formal
 | 
				
			||||||
 | 
						void setup_effects_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs,
 | 
				
			||||||
 | 
								bool is_formal = false)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							setup_internal_type(type, inputs, outputs, false, false, false, false, is_formal, false, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Setup meta-info cell type
 | 
				
			||||||
 | 
						void setup_metainfo_type(RTLIL::IdString type, const pool<RTLIL::IdString> &inputs, const pool<RTLIL::IdString> &outputs)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							setup_internal_type(type, inputs, outputs, false, false, false, false, false, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_module(RTLIL::Module *module)
 | 
						void setup_module(RTLIL::Module *module)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		pool<RTLIL::IdString> inputs, outputs;
 | 
							pool<RTLIL::IdString> inputs, outputs;
 | 
				
			||||||
| 
						 | 
					@ -87,30 +151,40 @@ struct CellTypes
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		setup_internals_eval();
 | 
							setup_internals_eval();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setup_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, true);
 | 
							// synthesizable
 | 
				
			||||||
 | 
							setup_comb_type(ID($tribuf), {ID::A, ID::EN}, {ID::Y}, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setup_type(ID($assert), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
							// combinatorial formal
 | 
				
			||||||
		setup_type(ID($assume), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
							setup_formal_type(ID($assert), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
		setup_type(ID($live), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
							setup_formal_type(ID($assume), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
		setup_type(ID($fair), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
							setup_formal_type(ID($live), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
		setup_type(ID($cover), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
							setup_formal_type(ID($fair), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
		setup_type(ID($initstate), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
							setup_formal_type(ID($cover), {ID::A, ID::EN}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
		setup_type(ID($anyconst), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
							setup_formal_type(ID($initstate), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
				
			||||||
		setup_type(ID($anyseq), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
							setup_formal_type(ID($anyconst), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
				
			||||||
		setup_type(ID($allconst), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
							setup_formal_type(ID($anyseq), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
				
			||||||
		setup_type(ID($allseq), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
							setup_formal_type(ID($allconst), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
				
			||||||
		setup_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_formal_type(ID($allseq), pool<RTLIL::IdString>(), {ID::Y}, true);
 | 
				
			||||||
		setup_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool<RTLIL::IdString>(), true);
 | 
							setup_formal_type(ID($equiv), {ID::A, ID::B}, {ID::Y}, true);
 | 
				
			||||||
		setup_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool<RTLIL::IdString>(), true);
 | 
					
 | 
				
			||||||
		setup_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool<RTLIL::IdString>(), true);
 | 
							// combinatorial non-synthesizable
 | 
				
			||||||
		setup_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
 | 
							setup_internal_type(ID($specify2), {ID::EN, ID::SRC, ID::DST}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
		setup_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
 | 
							setup_internal_type(ID($specify3), {ID::EN, ID::SRC, ID::DST, ID::DAT}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
		setup_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y});
 | 
							setup_internal_type(ID($specrule), {ID::EN_SRC, ID::EN_DST, ID::SRC, ID::DST}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
		setup_type(ID($get_tag), {ID::A}, {ID::Y});
 | 
					
 | 
				
			||||||
		setup_type(ID($overwrite_tag), {ID::A, ID::SET, ID::CLR}, pool<RTLIL::IdString>());
 | 
							// non-combinatorial formal
 | 
				
			||||||
		setup_type(ID($original_tag), {ID::A}, {ID::Y});
 | 
							setup_formal_type(ID($set_tag), {ID::A, ID::SET, ID::CLR}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($future_ff), {ID::A}, {ID::Y});
 | 
							setup_formal_type(ID($get_tag), {ID::A}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($scopeinfo), {}, {});
 | 
							setup_formal_type(ID($overwrite_tag), {ID::A, ID::SET, ID::CLR}, pool<RTLIL::IdString>());
 | 
				
			||||||
 | 
							setup_formal_type(ID($original_tag), {ID::A}, {ID::Y});
 | 
				
			||||||
 | 
							setup_formal_type(ID($future_ff), {ID::A}, {ID::Y});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// has effects
 | 
				
			||||||
 | 
							setup_effects_type(ID($print), {ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>());
 | 
				
			||||||
 | 
							setup_effects_type(ID($check), {ID::A, ID::EN, ID::ARGS, ID::TRG}, pool<RTLIL::IdString>(), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// meta-info
 | 
				
			||||||
 | 
							setup_metainfo_type(ID($scopeinfo), {}, {});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_internals_eval()
 | 
						void setup_internals_eval()
 | 
				
			||||||
| 
						 | 
					@ -131,91 +205,91 @@ struct CellTypes
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto type : unary_ops)
 | 
							for (auto type : unary_ops)
 | 
				
			||||||
			setup_type(type, {ID::A}, {ID::Y}, true);
 | 
								setup_comb_type(type, {ID::A}, {ID::Y});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto type : binary_ops)
 | 
							for (auto type : binary_ops)
 | 
				
			||||||
			setup_type(type, {ID::A, ID::B}, {ID::Y}, true);
 | 
								setup_comb_type(type, {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto type : std::vector<RTLIL::IdString>({ID($mux), ID($pmux), ID($bwmux)}))
 | 
							for (auto type : std::vector<RTLIL::IdString>({ID($mux), ID($pmux), ID($bwmux)}))
 | 
				
			||||||
			setup_type(type, {ID::A, ID::B, ID::S}, {ID::Y}, true);
 | 
								setup_comb_type(type, {ID::A, ID::B, ID::S}, {ID::Y});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto type : std::vector<RTLIL::IdString>({ID($bmux), ID($demux)}))
 | 
							for (auto type : std::vector<RTLIL::IdString>({ID($bmux), ID($demux)}))
 | 
				
			||||||
			setup_type(type, {ID::A, ID::S}, {ID::Y}, true);
 | 
								setup_comb_type(type, {ID::A, ID::S}, {ID::Y});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setup_type(ID($lcu), {ID::P, ID::G, ID::CI}, {ID::CO}, true);
 | 
							setup_comb_type(ID($lcu), {ID::P, ID::G, ID::CI}, {ID::CO});
 | 
				
			||||||
		setup_type(ID($alu), {ID::A, ID::B, ID::CI, ID::BI}, {ID::X, ID::Y, ID::CO}, true);
 | 
							setup_comb_type(ID($alu), {ID::A, ID::B, ID::CI, ID::BI}, {ID::X, ID::Y, ID::CO});
 | 
				
			||||||
		setup_type(ID($fa), {ID::A, ID::B, ID::C}, {ID::X, ID::Y}, true);
 | 
							setup_comb_type(ID($fa), {ID::A, ID::B, ID::C}, {ID::X, ID::Y});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_internals_ff()
 | 
						void setup_internals_ff()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		setup_type(ID($sr), {ID::SET, ID::CLR}, {ID::Q});
 | 
							setup_ff_type(ID($sr), {ID::SET, ID::CLR}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($ff), {ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($ff), {ID::D}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($dff), {ID::CLK, ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($dff), {ID::CLK, ID::D}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($dffe), {ID::CLK, ID::EN, ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($dffe), {ID::CLK, ID::EN, ID::D}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($dffsr), {ID::CLK, ID::SET, ID::CLR, ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($dffsr), {ID::CLK, ID::SET, ID::CLR, ID::D}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($dffsre), {ID::CLK, ID::SET, ID::CLR, ID::D, ID::EN}, {ID::Q});
 | 
							setup_ff_type(ID($dffsre), {ID::CLK, ID::SET, ID::CLR, ID::D, ID::EN}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($adff), {ID::CLK, ID::ARST, ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($adff), {ID::CLK, ID::ARST, ID::D}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($adffe), {ID::CLK, ID::ARST, ID::D, ID::EN}, {ID::Q});
 | 
							setup_ff_type(ID($adffe), {ID::CLK, ID::ARST, ID::D, ID::EN}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($aldff), {ID::CLK, ID::ALOAD, ID::AD, ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($aldff), {ID::CLK, ID::ALOAD, ID::AD, ID::D}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($aldffe), {ID::CLK, ID::ALOAD, ID::AD, ID::D, ID::EN}, {ID::Q});
 | 
							setup_ff_type(ID($aldffe), {ID::CLK, ID::ALOAD, ID::AD, ID::D, ID::EN}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($sdff), {ID::CLK, ID::SRST, ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($sdff), {ID::CLK, ID::SRST, ID::D}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($sdffe), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q});
 | 
							setup_ff_type(ID($sdffe), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($sdffce), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q});
 | 
							setup_ff_type(ID($sdffce), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($dlatch), {ID::EN, ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($dlatch), {ID::EN, ID::D}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($adlatch), {ID::EN, ID::D, ID::ARST}, {ID::Q});
 | 
							setup_ff_type(ID($adlatch), {ID::EN, ID::D, ID::ARST}, {ID::Q});
 | 
				
			||||||
		setup_type(ID($dlatchsr), {ID::EN, ID::SET, ID::CLR, ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($dlatchsr), {ID::EN, ID::SET, ID::CLR, ID::D}, {ID::Q});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_internals_anyinit()
 | 
						void setup_internals_anyinit()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		setup_type(ID($anyinit), {ID::D}, {ID::Q});
 | 
							setup_formal_type(ID($anyinit), {ID::D}, {ID::Q});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_internals_mem()
 | 
						void setup_internals_mem()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		setup_internals_ff();
 | 
							setup_internals_ff();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setup_type(ID($memrd), {ID::CLK, ID::EN, ID::ADDR}, {ID::DATA});
 | 
							setup_internal_type(ID($memrd), {ID::CLK, ID::EN, ID::ADDR}, {ID::DATA});
 | 
				
			||||||
		setup_type(ID($memrd_v2), {ID::CLK, ID::EN, ID::ARST, ID::SRST, ID::ADDR}, {ID::DATA});
 | 
							setup_internal_type(ID($memrd_v2), {ID::CLK, ID::EN, ID::ARST, ID::SRST, ID::ADDR}, {ID::DATA});
 | 
				
			||||||
		setup_type(ID($memwr), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
 | 
							setup_internal_type(ID($memwr), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
 | 
				
			||||||
		setup_type(ID($memwr_v2), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
 | 
							setup_internal_type(ID($memwr_v2), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
 | 
				
			||||||
		setup_type(ID($meminit), {ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
 | 
							setup_internal_type(ID($meminit), {ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
 | 
				
			||||||
		setup_type(ID($meminit_v2), {ID::ADDR, ID::DATA, ID::EN}, pool<RTLIL::IdString>());
 | 
							setup_internal_type(ID($meminit_v2), {ID::ADDR, ID::DATA, ID::EN}, pool<RTLIL::IdString>());
 | 
				
			||||||
		setup_type(ID($mem), {ID::RD_CLK, ID::RD_EN, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA});
 | 
							setup_internal_type(ID($mem), {ID::RD_CLK, ID::RD_EN, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA});
 | 
				
			||||||
		setup_type(ID($mem_v2), {ID::RD_CLK, ID::RD_EN, ID::RD_ARST, ID::RD_SRST, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA});
 | 
							setup_internal_type(ID($mem_v2), {ID::RD_CLK, ID::RD_EN, ID::RD_ARST, ID::RD_SRST, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setup_type(ID($fsm), {ID::CLK, ID::ARST, ID::CTRL_IN}, {ID::CTRL_OUT});
 | 
							setup_internal_type(ID($fsm), {ID::CLK, ID::ARST, ID::CTRL_IN}, {ID::CTRL_OUT});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_stdcells()
 | 
						void setup_stdcells()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		setup_stdcells_eval();
 | 
							setup_stdcells_eval();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setup_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_TBUF_), {ID::A, ID::E}, {ID::Y}, false);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_stdcells_eval()
 | 
						void setup_stdcells_eval()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		setup_type(ID($_BUF_), {ID::A}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_BUF_), {ID::A}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_NOT_), {ID::A}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_NOT_), {ID::A}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_AND_), {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_AND_), {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_NAND_), {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_NAND_), {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_OR_),  {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_OR_),  {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_NOR_),  {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_NOR_),  {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_XOR_), {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_XOR_), {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_XNOR_), {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_XNOR_), {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_ANDNOT_), {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_ANDNOT_), {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_ORNOT_), {ID::A, ID::B}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_ORNOT_), {ID::A, ID::B}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_MUX_), {ID::A, ID::B, ID::S}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_MUX_), {ID::A, ID::B, ID::S}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_NMUX_), {ID::A, ID::B, ID::S}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_NMUX_), {ID::A, ID::B, ID::S}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_MUX4_), {ID::A, ID::B, ID::C, ID::D, ID::S, ID::T}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_MUX4_), {ID::A, ID::B, ID::C, ID::D, ID::S, ID::T}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_MUX8_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::S, ID::T, ID::U}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_MUX8_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::S, ID::T, ID::U}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_MUX16_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::I, ID::J, ID::K, ID::L, ID::M, ID::N, ID::O, ID::P, ID::S, ID::T, ID::U, ID::V}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_MUX16_), {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::I, ID::J, ID::K, ID::L, ID::M, ID::N, ID::O, ID::P, ID::S, ID::T, ID::U, ID::V}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_AOI3_), {ID::A, ID::B, ID::C}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_AOI3_), {ID::A, ID::B, ID::C}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_OAI3_), {ID::A, ID::B, ID::C}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_OAI3_), {ID::A, ID::B, ID::C}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_AOI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_AOI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y});
 | 
				
			||||||
		setup_type(ID($_OAI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y}, true);
 | 
							setup_comb_type(ID($_OAI4_), {ID::A, ID::B, ID::C, ID::D}, {ID::Y});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void setup_stdcells_mem()
 | 
						void setup_stdcells_mem()
 | 
				
			||||||
| 
						 | 
					@ -224,77 +298,77 @@ struct CellTypes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_SR_%c%c_", c1, c2), {ID::S, ID::R}, {ID::Q});
 | 
								setup_ff_type(stringf("$_SR_%c%c_", c1, c2), {ID::S, ID::R}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setup_type(ID($_FF_), {ID::D}, {ID::Q});
 | 
							setup_ff_type(ID($_FF_), {ID::D}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_DFF_%c_", c1), {ID::C, ID::D}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DFF_%c_", c1), {ID::C, ID::D}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_DFFE_%c%c_", c1, c2), {ID::C, ID::D, ID::E}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DFFE_%c%c_", c1, c2), {ID::C, ID::D, ID::E}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_01)
 | 
							for (auto c3 : list_01)
 | 
				
			||||||
			setup_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {ID::C, ID::R, ID::D}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DFF_%c%c%c_", c1, c2, c3), {ID::C, ID::R, ID::D}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_01)
 | 
							for (auto c3 : list_01)
 | 
				
			||||||
		for (auto c4 : list_np)
 | 
							for (auto c4 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_DFFE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DFFE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_ALDFF_%c%c_", c1, c2), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q});
 | 
								setup_ff_type(stringf("$_ALDFF_%c%c_", c1, c2), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_np)
 | 
							for (auto c3 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_ALDFFE_%c%c%c_", c1, c2, c3), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q});
 | 
								setup_ff_type(stringf("$_ALDFFE_%c%c%c_", c1, c2, c3), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_np)
 | 
							for (auto c3 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {ID::C, ID::S, ID::R, ID::D}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {ID::C, ID::S, ID::R, ID::D}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_np)
 | 
							for (auto c3 : list_np)
 | 
				
			||||||
		for (auto c4 : list_np)
 | 
							for (auto c4 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_DFFSRE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DFFSRE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::S, ID::R, ID::D, ID::E}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_01)
 | 
							for (auto c3 : list_01)
 | 
				
			||||||
			setup_type(stringf("$_SDFF_%c%c%c_", c1, c2, c3), {ID::C, ID::R, ID::D}, {ID::Q});
 | 
								setup_ff_type(stringf("$_SDFF_%c%c%c_", c1, c2, c3), {ID::C, ID::R, ID::D}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_01)
 | 
							for (auto c3 : list_01)
 | 
				
			||||||
		for (auto c4 : list_np)
 | 
							for (auto c4 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_SDFFE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q});
 | 
								setup_ff_type(stringf("$_SDFFE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_01)
 | 
							for (auto c3 : list_01)
 | 
				
			||||||
		for (auto c4 : list_np)
 | 
							for (auto c4 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_SDFFCE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q});
 | 
								setup_ff_type(stringf("$_SDFFCE_%c%c%c%c_", c1, c2, c3, c4), {ID::C, ID::R, ID::D, ID::E}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_DLATCH_%c_", c1), {ID::E, ID::D}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DLATCH_%c_", c1), {ID::E, ID::D}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_01)
 | 
							for (auto c3 : list_01)
 | 
				
			||||||
			setup_type(stringf("$_DLATCH_%c%c%c_", c1, c2, c3), {ID::E, ID::R, ID::D}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DLATCH_%c%c%c_", c1, c2, c3), {ID::E, ID::R, ID::D}, {ID::Q});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto c1 : list_np)
 | 
							for (auto c1 : list_np)
 | 
				
			||||||
		for (auto c2 : list_np)
 | 
							for (auto c2 : list_np)
 | 
				
			||||||
		for (auto c3 : list_np)
 | 
							for (auto c3 : list_np)
 | 
				
			||||||
			setup_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {ID::E, ID::S, ID::R, ID::D}, {ID::Q});
 | 
								setup_ff_type(stringf("$_DLATCHSR_%c%c%c_", c1, c2, c3), {ID::E, ID::S, ID::R, ID::D}, {ID::Q});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void clear()
 | 
						void clear()
 | 
				
			||||||
| 
						 | 
					@ -302,6 +376,15 @@ struct CellTypes
 | 
				
			||||||
		cell_types.clear();
 | 
							cell_types.clear();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const CellType* get_cell(RTLIL::IdString type) const
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto it = cell_types.find(type);
 | 
				
			||||||
 | 
							if (it == cell_types.end())
 | 
				
			||||||
 | 
								return nullptr;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								return &(it->second);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool cell_known(RTLIL::IdString type) const
 | 
						bool cell_known(RTLIL::IdString type) const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return cell_types.count(type) != 0;
 | 
							return cell_types.count(type) != 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1074,6 +1074,36 @@ struct HelpPass : public Pass {
 | 
				
			||||||
				log("\n");
 | 
									log("\n");
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								else if (args[1] == "-celltypes") {
 | 
				
			||||||
 | 
									log("\n");
 | 
				
			||||||
 | 
									for (auto &it : cell_help_messages.cell_help) {
 | 
				
			||||||
 | 
										SimHelper help_cell = it.second;
 | 
				
			||||||
 | 
										auto *ct = yosys_celltypes.get_cell(it.first);
 | 
				
			||||||
 | 
										char ct_flags[8] = "";
 | 
				
			||||||
 | 
										if (ct != nullptr && ct->is_internal) {
 | 
				
			||||||
 | 
											ct_flags[0] = ct->is_evaluable ? 'E' : '-';
 | 
				
			||||||
 | 
											ct_flags[1] = ct->is_combinatorial ? 'C' : '-';
 | 
				
			||||||
 | 
											ct_flags[2] = ct->is_synthesizable ? 'S' : '-';
 | 
				
			||||||
 | 
											ct_flags[3] = ct->is_builtin_ff ? 'M' : '-';
 | 
				
			||||||
 | 
											ct_flags[4] = ct->is_formal ? 'F' : '-';
 | 
				
			||||||
 | 
											ct_flags[5] = ct->is_metainfo ? 'I' : '-';
 | 
				
			||||||
 | 
											ct_flags[6] = ct->has_effects ? 'X' : '-';
 | 
				
			||||||
 | 
											ct_flags[7] = 0;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										log("    %-15s %s\n", help_cell.name.c_str(), ct_flags);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									log("\n");
 | 
				
			||||||
 | 
									log("Legend:\n");
 | 
				
			||||||
 | 
									log("    E = evaluable\n");
 | 
				
			||||||
 | 
									log("    C = combinatorial\n");
 | 
				
			||||||
 | 
									log("    S = synthesizable\n");
 | 
				
			||||||
 | 
									log("    M = builtin_ff\n");
 | 
				
			||||||
 | 
									log("    F = formal\n");
 | 
				
			||||||
 | 
									log("    I = metainfo\n");
 | 
				
			||||||
 | 
									log("    X = effects\n");
 | 
				
			||||||
 | 
									log("\n");
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			// this option is undocumented as it is for internal use only
 | 
								// this option is undocumented as it is for internal use only
 | 
				
			||||||
			else if (args[1] == "-write-rst-command-reference-manual") {
 | 
								else if (args[1] == "-write-rst-command-reference-manual") {
 | 
				
			||||||
				for (auto &it : pass_register) {
 | 
									for (auto &it : pass_register) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,6 +141,39 @@ static bool match_attr(const dict<RTLIL::IdString, RTLIL::Const> &attributes, co
 | 
				
			||||||
	return match_attr(attributes, match_expr, std::string(), 0);
 | 
						return match_attr(attributes, match_expr, std::string(), 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool match_type_prop(RTLIL::IdString type, const std::string &property)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto *ct = yosys_celltypes.get_cell(type);
 | 
				
			||||||
 | 
						if (ct == nullptr) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
						if (property.compare("internal") == 0) {
 | 
				
			||||||
 | 
							return ct->is_internal;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
						if (property.compare("evaluable") == 0) {
 | 
				
			||||||
 | 
							return ct->is_evaluable;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
						if (property.compare("combinatorial") == 0) {
 | 
				
			||||||
 | 
							return ct->is_combinatorial;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
						if (property.compare("synthesizable") == 0) {
 | 
				
			||||||
 | 
							return ct->is_synthesizable;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
						if (property.compare("builtin_ff") == 0) {
 | 
				
			||||||
 | 
							return ct->is_builtin_ff;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
						if (property.compare("formal") == 0) {
 | 
				
			||||||
 | 
							return ct->is_formal;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
						if (property.compare("metainfo") == 0) {
 | 
				
			||||||
 | 
							return ct->is_metainfo;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
						if (property.compare("effects") == 0) {
 | 
				
			||||||
 | 
							return ct->has_effects;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							log_cmd_error("Unsupported type property '%s'!\n", property.c_str());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs)
 | 
					static void select_op_neg(RTLIL::Design *design, RTLIL::Selection &lhs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (lhs.full_selection) {
 | 
						if (lhs.full_selection) {
 | 
				
			||||||
| 
						 | 
					@ -891,6 +924,11 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp
 | 
				
			||||||
						sel.selected_members[mod->name].insert(cell->name);
 | 
											sel.selected_members[mod->name].insert(cell->name);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
 | 
							if (arg_memb.compare(0, 2, "y:") == 0) {
 | 
				
			||||||
 | 
								for (auto cell : mod->cells())
 | 
				
			||||||
 | 
									if (match_type_prop(cell->type, arg_memb.substr(2)))
 | 
				
			||||||
 | 
										sel.selected_members[mod->name].insert(cell->name);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
		if (arg_memb.compare(0, 2, "p:") == 0) {
 | 
							if (arg_memb.compare(0, 2, "p:") == 0) {
 | 
				
			||||||
			for (auto &it : mod->processes)
 | 
								for (auto &it : mod->processes)
 | 
				
			||||||
				if (match_ids(it.first, arg_memb.substr(2)))
 | 
									if (match_ids(it.first, arg_memb.substr(2)))
 | 
				
			||||||
| 
						 | 
					@ -1178,6 +1216,11 @@ struct SelectPass : public Pass {
 | 
				
			||||||
		log("    t:@<name>\n");
 | 
							log("    t:@<name>\n");
 | 
				
			||||||
		log("        all cells with a type matching a module in the saved selection <name>\n");
 | 
							log("        all cells with a type matching a module in the saved selection <name>\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    y:<property>\n");
 | 
				
			||||||
 | 
							log("        all cells with a given type property, possible values are:\n");
 | 
				
			||||||
 | 
							log("        evaluable, combinatorial, synthesizable, builtin_ff, formal\n");
 | 
				
			||||||
 | 
							log("        (currently only internal cells can have type properties)\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
		log("    p:<pattern>\n");
 | 
							log("    p:<pattern>\n");
 | 
				
			||||||
		log("        all processes with a name matching the given pattern\n");
 | 
							log("        all processes with a name matching the given pattern\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										42
									
								
								tests/select/type_props.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								tests/select/type_props.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					read_rtlil << EOF
 | 
				
			||||||
 | 
					module \sm2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  wire input 1 \clk
 | 
				
			||||||
 | 
					  wire input 2 \rst
 | 
				
			||||||
 | 
					  wire width 2 input 3 \a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  wire width 2 \add_Y
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  attribute \init 2'00
 | 
				
			||||||
 | 
					  wire width 2 output 4 \y
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cell $add \add
 | 
				
			||||||
 | 
					    parameter \A_SIGNED 0
 | 
				
			||||||
 | 
					    parameter \A_WIDTH 2
 | 
				
			||||||
 | 
					    parameter \B_SIGNED 0
 | 
				
			||||||
 | 
					    parameter \B_WIDTH 2
 | 
				
			||||||
 | 
					    parameter \Y_WIDTH 2
 | 
				
			||||||
 | 
					    connect \A \y
 | 
				
			||||||
 | 
					    connect \B \a
 | 
				
			||||||
 | 
					    connect \Y \add_Y
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cell $sdff \sdff
 | 
				
			||||||
 | 
					    parameter \CLK_POLARITY 1
 | 
				
			||||||
 | 
					    parameter \SRST_POLARITY 1
 | 
				
			||||||
 | 
					    parameter \SRST_VALUE 2'00
 | 
				
			||||||
 | 
					    parameter \WIDTH 2
 | 
				
			||||||
 | 
					    connect \CLK \clk
 | 
				
			||||||
 | 
					    connect \D \add_Y
 | 
				
			||||||
 | 
					    connect \Q \y
 | 
				
			||||||
 | 
					    connect \SRST \rst
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select -assert-count 1 y:evaluable
 | 
				
			||||||
 | 
					select -assert-count 1 y:combinatorial
 | 
				
			||||||
 | 
					select -assert-count 2 y:synthesizable
 | 
				
			||||||
 | 
					select -assert-count 1 y:builtin_ff
 | 
				
			||||||
 | 
					select -assert-count 0 y:formal
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue