mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	This commit is contained in:
		
						commit
						d57c85111f
					
				
					 6 changed files with 169 additions and 78 deletions
				
			
		|  | @ -216,6 +216,7 @@ int main(int argc, char **argv) | |||
| 		printf("    -D <header_id>[:<filename>]\n"); | ||||
| 		printf("        dump the design when printing the specified log header to a file.\n"); | ||||
| 		printf("        yosys_dump_<header_id>.il is used as filename if none is specified.\n"); | ||||
| 		printf("        Use 'ALL' as <header_id> to dump at every header.\n"); | ||||
| 		printf("\n"); | ||||
| 		printf("    -V\n"); | ||||
| 		printf("        print version information and exit\n"); | ||||
|  | @ -322,6 +323,15 @@ int main(int argc, char **argv) | |||
| 		case 'D': | ||||
| 			{ | ||||
| 				auto args = split_tokens(optarg, ":"); | ||||
| 				if (!args.empty() && args[0] == "ALL") { | ||||
| 					if (GetSize(args) != 1) { | ||||
| 						fprintf(stderr, "Invalid number of tokens in -D ALL.\n"); | ||||
| 						exit(1); | ||||
| 					} | ||||
| 					log_hdump_all = true; | ||||
| 				} else { | ||||
| 					if (!args.empty() && !args[0].empty() && args[0].back() == '.') | ||||
| 						args[0].pop_back(); | ||||
| 					if (GetSize(args) == 1) | ||||
| 						args.push_back("yosys_dump_" + args[0] + ".il"); | ||||
| 					if (GetSize(args) != 2) { | ||||
|  | @ -330,6 +340,7 @@ int main(int argc, char **argv) | |||
| 					} | ||||
| 					log_hdump[args[0]].insert(args[1]); | ||||
| 				} | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			fprintf(stderr, "Run '%s -h' for help.\n", argv[0]); | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ YOSYS_NAMESPACE_BEGIN | |||
| std::vector<FILE*> log_files; | ||||
| std::vector<std::ostream*> log_streams; | ||||
| std::map<std::string, std::set<std::string>> log_hdump; | ||||
| bool log_hdump_all = false; | ||||
| FILE *log_errfile = NULL; | ||||
| SHA1 *log_hasher = NULL; | ||||
| 
 | ||||
|  | @ -159,6 +160,9 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap) | |||
| 	logv(format, ap); | ||||
| 	log_flush(); | ||||
| 
 | ||||
| 	if (log_hdump_all) | ||||
| 		log_hdump[header_id].insert("yosys_dump_" + header_id + ".il"); | ||||
| 
 | ||||
| 	if (log_hdump.count(header_id) && design != nullptr) | ||||
| 		for (auto &filename : log_hdump.at(header_id)) { | ||||
| 			log("Dumping current design to '%s'.\n", filename.c_str()); | ||||
|  |  | |||
|  | @ -48,6 +48,7 @@ struct log_cmd_error_exception { }; | |||
| extern std::vector<FILE*> log_files; | ||||
| extern std::vector<std::ostream*> log_streams; | ||||
| extern std::map<std::string, std::set<std::string>> log_hdump; | ||||
| extern bool log_hdump_all; | ||||
| extern FILE *log_errfile; | ||||
| extern SHA1 *log_hasher; | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ struct proc_dlatch_db_t | |||
| 	Module *module; | ||||
| 	SigMap sigmap; | ||||
| 
 | ||||
| 	dict<Cell*, vector<SigBit>> mux_srcbits; | ||||
| 	dict<SigBit, pair<Cell*, int>> mux_drivers; | ||||
| 	dict<SigBit, int> sigusers; | ||||
| 
 | ||||
|  | @ -40,10 +41,24 @@ struct proc_dlatch_db_t | |||
| 	{ | ||||
| 		for (auto cell : module->cells()) | ||||
| 		{ | ||||
| 			if (cell->type.in("$mux", "$pmux")) { | ||||
| 			if (cell->type.in("$mux", "$pmux")) | ||||
| 			{ | ||||
| 				auto sig_y = sigmap(cell->getPort("\\Y")); | ||||
| 				for (int i = 0; i < GetSize(sig_y); i++) | ||||
| 					mux_drivers[sig_y[i]] = pair<Cell*, int>(cell, i); | ||||
| 
 | ||||
| 				pool<SigBit> mux_srcbits_pool; | ||||
| 				for (auto bit : sigmap(cell->getPort("\\A"))) | ||||
| 					mux_srcbits_pool.insert(bit); | ||||
| 				for (auto bit : sigmap(cell->getPort("\\B"))) | ||||
| 					mux_srcbits_pool.insert(bit); | ||||
| 
 | ||||
| 				vector<SigBit> mux_srcbits_vec; | ||||
| 				for (auto bit : mux_srcbits_pool) | ||||
| 					if (bit.wire != nullptr) | ||||
| 						mux_srcbits_vec.push_back(bit); | ||||
| 
 | ||||
| 				mux_srcbits[cell].swap(mux_srcbits_vec); | ||||
| 			} | ||||
| 
 | ||||
| 			for (auto &conn : cell->connections()) | ||||
|  | @ -58,6 +73,42 @@ struct proc_dlatch_db_t | |||
| 					sigusers[bit]++; | ||||
| 	} | ||||
| 
 | ||||
| 	bool quickcheck(const SigSpec &haystack, const SigSpec &needle) | ||||
| 	{ | ||||
| 		pool<SigBit> haystack_bits = sigmap(haystack).to_sigbit_pool(); | ||||
| 		pool<SigBit> needle_bits = sigmap(needle).to_sigbit_pool(); | ||||
| 
 | ||||
| 		pool<Cell*> cells_queue, cells_visited; | ||||
| 		pool<SigBit> bits_queue, bits_visited; | ||||
| 
 | ||||
| 		bits_queue = haystack_bits; | ||||
| 		while (!bits_queue.empty()) | ||||
| 		{ | ||||
| 			for (auto &bit : bits_queue) { | ||||
| 				auto it = mux_drivers.find(bit); | ||||
| 				if (it != mux_drivers.end()) | ||||
| 					if (!cells_visited.count(it->second.first)) | ||||
| 						cells_queue.insert(it->second.first); | ||||
| 				bits_visited.insert(bit); | ||||
| 			} | ||||
| 
 | ||||
| 			bits_queue.clear(); | ||||
| 
 | ||||
| 			for (auto c : cells_queue) { | ||||
| 				for (auto bit : mux_srcbits[c]) { | ||||
| 					if (needle_bits.count(bit)) | ||||
| 						return true; | ||||
| 					if (!bits_visited.count(bit)) | ||||
| 						bits_queue.insert(bit); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			cells_queue.clear(); | ||||
| 		} | ||||
| 
 | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	struct rule_node_t | ||||
| 	{ | ||||
| 		// a node is true if "signal" equals "match" and [any
 | ||||
|  | @ -218,9 +269,17 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) | |||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto ss : sr->actions) { | ||||
| 		for (auto ss : sr->actions) | ||||
| 		{ | ||||
| 			db.sigmap.apply(ss.first); | ||||
| 			db.sigmap.apply(ss.second); | ||||
| 
 | ||||
| 			if (!db.quickcheck(ss.second, ss.first)) { | ||||
| 				nolatches_bits.first.append(ss.first); | ||||
| 				nolatches_bits.second.append(ss.second); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			for (int i = 0; i < GetSize(ss.first); i++) | ||||
| 				latches_out_in[ss.first[i]] = ss.second[i]; | ||||
| 		} | ||||
|  |  | |||
|  | @ -25,22 +25,11 @@ | |||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) | ||||
| struct PrepPass : public ScriptPass | ||||
| { | ||||
| 	if (!run_from.empty() && run_from == run_to) { | ||||
| 		active = (label == run_from); | ||||
| 	} else { | ||||
| 		if (label == run_from) | ||||
| 			active = true; | ||||
| 		if (label == run_to) | ||||
| 			active = false; | ||||
| 	} | ||||
| 	return active; | ||||
| } | ||||
| 	PrepPass() : ScriptPass("prep", "generic synthesis script") { } | ||||
| 
 | ||||
| struct PrepPass : public Pass { | ||||
| 	PrepPass() : Pass("prep", "generic synthesis script") { } | ||||
| 	virtual void help() | ||||
| 	virtual void help() YS_OVERRIDE | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
|  | @ -53,6 +42,10 @@ struct PrepPass : public Pass { | |||
| 		log("    -top <module>\n"); | ||||
| 		log("        use the specified module as top module (default='top')\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -flatten\n"); | ||||
| 		log("        flatten the design before synthesis. this will pass '-auto-top' to\n"); | ||||
| 		log("        'hierarchy' if no top module is specified.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nordff\n"); | ||||
| 		log("        passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n"); | ||||
| 		log("\n"); | ||||
|  | @ -63,31 +56,23 @@ struct PrepPass : public Pass { | |||
| 		log("\n"); | ||||
| 		log("\n"); | ||||
| 		log("The following commands are executed by this synthesis command:\n"); | ||||
| 		log("\n"); | ||||
| 		log("    begin:\n"); | ||||
| 		log("        hierarchy -check [-top <top>]\n"); | ||||
| 		log("\n"); | ||||
| 		log("    prep:\n"); | ||||
| 		log("        proc\n"); | ||||
| 		log("        opt_expr -keepdc\n"); | ||||
| 		log("        opt_clean\n"); | ||||
| 		log("        check\n"); | ||||
| 		log("        opt -keepdc\n"); | ||||
| 		log("        wreduce\n"); | ||||
| 		log("        memory_dff [-nordff]\n"); | ||||
| 		log("        opt_clean\n"); | ||||
| 		log("        memory_collect\n"); | ||||
| 		log("        opt -keepdc -fast\n"); | ||||
| 		log("\n"); | ||||
| 		log("    check:\n"); | ||||
| 		log("        stat\n"); | ||||
| 		log("        check\n"); | ||||
| 		help_script(); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) | ||||
| 
 | ||||
| 	string top_module, fsm_opts, memory_opts; | ||||
| 	bool flatten; | ||||
| 
 | ||||
| 	virtual void clear_flags() YS_OVERRIDE | ||||
| 	{ | ||||
| 		std::string top_module, memory_opts; | ||||
| 		std::string run_from, run_to; | ||||
| 		top_module.clear(); | ||||
| 		memory_opts.clear(); | ||||
| 		flatten = false; | ||||
| 	} | ||||
| 
 | ||||
| 	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
| 		string run_from, run_to; | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
|  | @ -107,6 +92,10 @@ struct PrepPass : public Pass { | |||
| 				} | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-flatten") { | ||||
| 				flatten = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-nordff") { | ||||
| 				memory_opts += " -nordff"; | ||||
| 				continue; | ||||
|  | @ -118,41 +107,54 @@ struct PrepPass : public Pass { | |||
| 		if (!design->full_selection()) | ||||
| 			log_cmd_error("This comannd only operates on fully selected designs!\n"); | ||||
| 
 | ||||
| 		bool active = run_from.empty(); | ||||
| 
 | ||||
| 		log_header(design, "Executing PREP pass.\n"); | ||||
| 		log_push(); | ||||
| 
 | ||||
| 		if (check_label(active, run_from, run_to, "begin")) | ||||
| 		{ | ||||
| 			if (top_module.empty()) | ||||
| 				Pass::call(design, stringf("hierarchy -check")); | ||||
| 			else | ||||
| 				Pass::call(design, stringf("hierarchy -check -top %s", top_module.c_str())); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label(active, run_from, run_to, "coarse")) | ||||
| 		{ | ||||
| 			Pass::call(design, "proc"); | ||||
| 			Pass::call(design, "opt_expr -keepdc"); | ||||
| 			Pass::call(design, "opt_clean"); | ||||
| 			Pass::call(design, "check"); | ||||
| 			Pass::call(design, "opt -keepdc"); | ||||
| 			Pass::call(design, "wreduce"); | ||||
| 			Pass::call(design, "memory_dff" + memory_opts); | ||||
| 			Pass::call(design, "opt_clean"); | ||||
| 			Pass::call(design, "memory_collect"); | ||||
| 			Pass::call(design, "opt -keepdc -fast"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label(active, run_from, run_to, "check")) | ||||
| 		{ | ||||
| 			Pass::call(design, "stat"); | ||||
| 			Pass::call(design, "check"); | ||||
| 		} | ||||
| 		run_script(design, run_from, run_to); | ||||
| 
 | ||||
| 		log_pop(); | ||||
| 	} | ||||
| 
 | ||||
| 	virtual void script() YS_OVERRIDE | ||||
| 	{ | ||||
| 
 | ||||
| 		if (check_label("begin")) | ||||
| 		{ | ||||
| 			if (help_mode) { | ||||
| 				run("hierarchy -check [-top <top>]"); | ||||
| 			} else { | ||||
| 				if (top_module.empty()) { | ||||
| 					if (flatten) | ||||
| 						run("hierarchy -check -auto-top"); | ||||
| 					else | ||||
| 						run("hierarchy -check"); | ||||
| 				} else | ||||
| 					run(stringf("hierarchy -check -top %s", top_module.c_str())); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("coarse")) | ||||
| 		{ | ||||
| 			run("proc"); | ||||
| 			if (help_mode || flatten) | ||||
| 				run("flatten", "(if -flatten)"); | ||||
| 			run("opt_expr -keepdc"); | ||||
| 			run("opt_clean"); | ||||
| 			run("check"); | ||||
| 			run("opt -keepdc"); | ||||
| 			run("wreduce"); | ||||
| 			run("memory_dff" + (help_mode ? " [-nordff]" : memory_opts)); | ||||
| 			run("opt_clean"); | ||||
| 			run("memory_collect"); | ||||
| 			run("opt -keepdc -fast"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("check")) | ||||
| 		{ | ||||
| 			run("stat"); | ||||
| 			run("check"); | ||||
| 		} | ||||
| 	} | ||||
| } PrepPass; | ||||
| 
 | ||||
| PRIVATE_NAMESPACE_END | ||||
|  |  | |||
|  | @ -41,6 +41,10 @@ struct SynthPass : public ScriptPass | |||
| 		log("    -top <module>\n"); | ||||
| 		log("        use the specified module as top module (default='top')\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -flatten\n"); | ||||
| 		log("        flatten the design before synthesis. this will pass '-auto-top' to\n"); | ||||
| 		log("        'hierarchy' if no top module is specified.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -encfile <file>\n"); | ||||
| 		log("        passed to 'fsm_recode' via 'fsm'\n"); | ||||
| 		log("\n"); | ||||
|  | @ -68,8 +72,8 @@ struct SynthPass : public ScriptPass | |||
| 		log("\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	std::string top_module, fsm_opts, memory_opts; | ||||
| 	bool noalumacc, nofsm, noabc; | ||||
| 	string top_module, fsm_opts, memory_opts; | ||||
| 	bool flatten, noalumacc, nofsm, noabc; | ||||
| 
 | ||||
| 	virtual void clear_flags() YS_OVERRIDE | ||||
| 	{ | ||||
|  | @ -77,6 +81,7 @@ struct SynthPass : public ScriptPass | |||
| 		fsm_opts.clear(); | ||||
| 		memory_opts.clear(); | ||||
| 
 | ||||
| 		flatten = false; | ||||
| 		noalumacc = false; | ||||
| 		nofsm = false; | ||||
| 		noabc = false; | ||||
|  | @ -109,6 +114,10 @@ struct SynthPass : public ScriptPass | |||
| 				} | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-flatten") { | ||||
| 				flatten = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-nofsm") { | ||||
| 				nofsm = true; | ||||
| 				continue; | ||||
|  | @ -147,9 +156,12 @@ struct SynthPass : public ScriptPass | |||
| 			if (help_mode) { | ||||
| 				run("hierarchy -check [-top <top>]"); | ||||
| 			} else { | ||||
| 				if (top_module.empty()) | ||||
| 					run(stringf("hierarchy -check")); | ||||
| 				if (top_module.empty()) { | ||||
| 					if (flatten) | ||||
| 						run("hierarchy -check -auto-top"); | ||||
| 					else | ||||
| 						run("hierarchy -check"); | ||||
| 				} else | ||||
| 					run(stringf("hierarchy -check -top %s", top_module.c_str())); | ||||
| 			} | ||||
| 		} | ||||
|  | @ -157,6 +169,8 @@ struct SynthPass : public ScriptPass | |||
| 		if (check_label("coarse")) | ||||
| 		{ | ||||
| 			run("proc"); | ||||
| 			if (help_mode || flatten) | ||||
| 				run("flatten", "(if -flatten)"); | ||||
| 			run("opt_expr"); | ||||
| 			run("opt_clean"); | ||||
| 			run("check"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue