mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	icell_liberty: flops
This commit is contained in:
		
							parent
							
								
									7a56417c80
								
							
						
					
					
						commit
						897a625ad8
					
				
					 1 changed files with 84 additions and 2 deletions
				
			
		|  | @ -18,19 +18,27 @@ | |||
|  */ | ||||
| #include "kernel/yosys.h" | ||||
| #include "kernel/celltypes.h" | ||||
| #include "kernel/ff.h" | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| struct LibertyStubber { | ||||
| 	CellTypes ct; | ||||
| 	CellTypes ct_ff; | ||||
| 	LibertyStubber() { | ||||
| 		ct.setup(); | ||||
| 		ct.setup_internals_ff(); | ||||
| 	} | ||||
| 	void liberty_prefix(std::ostream& f) | ||||
| 	{ | ||||
| 		f << "/*\n"; | ||||
| 		f << stringf("Models interfaces of select Yosys internal cell.\n"); | ||||
| 		f << stringf("Likely contains INCORRECT POLARITIES.\n"); | ||||
| 		f << stringf("Impractical for any simulation, synthesis, or timing.\n"); | ||||
| 		f << stringf("Intended purely for SDC expansion.\n"); | ||||
| 		f << stringf("Do not microwave or tumble dry.\n"); | ||||
| 		f << stringf("Generated by %s\n", yosys_maybe_version()); | ||||
| 		f << "*/\n"; | ||||
| 		f << "library (yosys) {\n"; | ||||
| 		f << "\tinput_threshold_pct_fall : 50;\n"; | ||||
| 		f << "\tinput_threshold_pct_rise : 50;\n"; | ||||
|  | @ -45,6 +53,76 @@ struct LibertyStubber { | |||
| 	{ | ||||
| 		f << "}\n"; | ||||
| 	} | ||||
| 	struct LibertyItemizer { | ||||
| 		std::ostream& f; | ||||
| 		int indent; | ||||
| 		LibertyItemizer(std::ostream& f) : f(f), indent(0) {}; | ||||
| 		void item(std::string key, std::string val) | ||||
| 		{ | ||||
| 			f << std::string(indent, '\t') << key << " : \"" << val << "\";\n"; | ||||
| 		} | ||||
| 	}; | ||||
| 	void liberty_flop(Module* base, Module* derived, std::ostream& f) | ||||
| 	{ | ||||
| 		auto base_name = base->name.str().substr(1); | ||||
| 		auto derived_name = derived->name.str().substr(1); | ||||
| 
 | ||||
| 		FfTypeData ffType(base_name); | ||||
| 		LibertyItemizer i(f); | ||||
| 
 | ||||
| 		if (ffType.has_gclk) { | ||||
| 			log_warning("Formal flip flop %s can't be modeled\n", base_name.c_str()); | ||||
| 			return; | ||||
| 		} | ||||
| 		if (ffType.has_ce) { | ||||
| 			log_warning("DFFE %s can't be modeled\n", base_name.c_str()); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		f << "\tcell (\"" << derived_name << "\") {\n"; | ||||
| 		auto& base_type = ct.cell_types[base_name]; | ||||
| 		i.indent = 3; | ||||
| 		for (auto x : derived->ports) { | ||||
| 			bool is_input = base_type.inputs.count(x); | ||||
| 			bool is_output = base_type.outputs.count(x); | ||||
| 			f << "\t\tpin (" << RTLIL::unescape_id(x.str()) << ") {\n"; | ||||
| 			if (is_input && !is_output) { | ||||
| 				i.item("direction", "input"); | ||||
| 			} else if (!is_input && is_output) { | ||||
| 				i.item("direction", "output"); | ||||
| 			} else { | ||||
| 				i.item("direction", "inout"); | ||||
| 			} | ||||
| 			if (RTLIL::unescape_id(x) == "CLK" || RTLIL::unescape_id(x) == "C") | ||||
| 				i.item("clock", "true"); | ||||
| 			if (RTLIL::unescape_id(x) == "Q") | ||||
| 				i.item("function", "IQ"); | ||||
| 			f << "\t\t}\n"; | ||||
| 		} | ||||
| 
 | ||||
| 		f << "\t\tff (\"IQ\",\"IQ_N\") {\n"; | ||||
| 		i.indent = 3; | ||||
| 		// TODO polarities?
 | ||||
| 		if (ffType.has_clk) { | ||||
| 			auto pin = ffType.is_fine ? "C" : "CLK"; | ||||
| 			i.item("clocked_on", pin); | ||||
| 		} | ||||
| 		if (ffType.has_arst) { | ||||
| 			auto meaning = (ffType.val_arst == State::S1) ? "preset" : "clear"; | ||||
| 			auto pin = ffType.is_fine ? "R" : "ARST"; | ||||
| 			i.item(meaning, pin); | ||||
| 		} | ||||
| 		auto next_state = ffType.has_ce ? "D & EN" : "D"; | ||||
| 		i.item("next_state", next_state); | ||||
| 		f << "\t\t}\n"; | ||||
| 
 | ||||
| 
 | ||||
| 		// bool has_aload;
 | ||||
| 		// bool has_srst;
 | ||||
| 		// bool has_arst;
 | ||||
| 		// bool has_sr;
 | ||||
| 		f << "\t}\n"; | ||||
| 	} | ||||
| 	void liberty_cell(Module* base, Module* derived, std::ostream& f) | ||||
| 	{ | ||||
| 		auto base_name = base->name.str().substr(1); | ||||
|  | @ -53,6 +131,10 @@ struct LibertyStubber { | |||
| 			log_debug("skip skeleton for %s\n", base_name.c_str()); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (RTLIL::builtin_ff_cell_types().count(base_name)) | ||||
| 			return liberty_flop(base, derived, f); | ||||
| 
 | ||||
| 		auto& base_type = ct.cell_types[base_name]; | ||||
| 		f << "\tcell (\"" << derived_name << "\") {\n"; | ||||
| 		for (auto x : derived->ports) { | ||||
|  | @ -73,7 +155,7 @@ struct LibertyStubber { | |||
| }; | ||||
| 
 | ||||
| struct IcellLiberty : Pass { | ||||
| 	IcellLiberty() : Pass("icell_liberty", "derive box modules") {} | ||||
| 	IcellLiberty() : Pass("icell_liberty", "write Liberty interfaces for used internal cells") {} | ||||
| 	void help() override | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue