mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Added recursion support to techmap
This commit is contained in:
		
							parent
							
								
									aeb36b0b8b
								
							
						
					
					
						commit
						d3dc22a90f
					
				
					 1 changed files with 290 additions and 288 deletions
				
			
		|  | @ -50,317 +50,320 @@ static void apply_prefix(std::string prefix, RTLIL::SigSpec &sig, RTLIL::Module | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| std::map<std::string, void(*)(RTLIL::Module*, RTLIL::Cell*)> simplemap_mappers; | ||||
| std::map<std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>>, RTLIL::Module*> techmap_cache; | ||||
| std::map<RTLIL::Module*, bool> techmap_do_cache; | ||||
| 
 | ||||
| struct TechmapWireData { | ||||
| 	RTLIL::Wire *wire; | ||||
| 	RTLIL::SigSpec value; | ||||
| }; | ||||
| 
 | ||||
| typedef std::map<std::string, std::vector<TechmapWireData>> TechmapWires; | ||||
| 
 | ||||
| static TechmapWires techmap_find_special_wires(RTLIL::Module *module) | ||||
| struct TechmapWorker | ||||
| { | ||||
| 	TechmapWires result; | ||||
| 	std::map<std::string, void(*)(RTLIL::Module*, RTLIL::Cell*)> simplemap_mappers; | ||||
| 	std::map<std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>>, RTLIL::Module*> techmap_cache; | ||||
| 	std::map<RTLIL::Module*, bool> techmap_do_cache; | ||||
| 
 | ||||
| 	if (module == NULL) | ||||
| 		return result; | ||||
| 	struct TechmapWireData { | ||||
| 		RTLIL::Wire *wire; | ||||
| 		RTLIL::SigSpec value; | ||||
| 	}; | ||||
| 
 | ||||
| 	for (auto &it : module->wires) { | ||||
| 		const char *p = it.first.c_str(); | ||||
| 		if (*p == '$') | ||||
| 			continue; | ||||
| 	typedef std::map<std::string, std::vector<TechmapWireData>> TechmapWires; | ||||
| 
 | ||||
| 		const char *q = strrchr(p+1, '.'); | ||||
| 		p = q ? q : p+1; | ||||
| 
 | ||||
| 		if (!strncmp(p, "_TECHMAP_", 9)) { | ||||
| 			TechmapWireData record; | ||||
| 			record.wire = it.second; | ||||
| 			record.value = it.second; | ||||
| 			result[p].push_back(record); | ||||
| 			it.second->attributes["\\keep"] = RTLIL::Const(1); | ||||
| 			it.second->attributes["\\_techmap_special_"] = RTLIL::Const(1); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (!result.empty()) { | ||||
| 		SigMap sigmap(module); | ||||
| 		for (auto &it1 : result) | ||||
| 		for (auto &it2 : it1.second) | ||||
| 			sigmap.apply(it2.value); | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| static void techmap_module_worker(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, bool flatten_mode) | ||||
| { | ||||
| 	log("Mapping `%s.%s' using `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(tpl->name)); | ||||
| 
 | ||||
| 	if (tpl->memories.size() != 0) | ||||
| 		log_error("Technology map yielded memories -> this is not supported.\n"); | ||||
| 
 | ||||
| 	if (tpl->processes.size() != 0) | ||||
| 		log_error("Technology map yielded processes -> this is not supported.\n"); | ||||
| 
 | ||||
| 	std::map<RTLIL::IdString, RTLIL::IdString> positional_ports; | ||||
| 
 | ||||
| 	for (auto &it : tpl->wires) { | ||||
| 		if (it.second->port_id > 0) | ||||
| 			positional_ports[stringf("$%d", it.second->port_id)] = it.first; | ||||
| 		RTLIL::Wire *w = new RTLIL::Wire(*it.second); | ||||
| 		apply_prefix(cell->name, w->name); | ||||
| 		w->port_input = false; | ||||
| 		w->port_output = false; | ||||
| 		w->port_id = 0; | ||||
| 		if (it.second->get_bool_attribute("\\_techmap_special_")) | ||||
| 			w->attributes.clear(); | ||||
| 		module->wires[w->name] = w; | ||||
| 		design->select(module, w); | ||||
| 	} | ||||
| 
 | ||||
| 	SigMap port_signal_map; | ||||
| 
 | ||||
| 	for (auto &it : cell->connections) { | ||||
| 		RTLIL::IdString portname = it.first; | ||||
| 		if (positional_ports.count(portname) > 0) | ||||
| 			portname = positional_ports.at(portname); | ||||
| 		if (tpl->wires.count(portname) == 0 || tpl->wires.at(portname)->port_id == 0) { | ||||
| 			if (portname.substr(0, 1) == "$") | ||||
| 				log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", portname.c_str(), cell->name.c_str(), tpl->name.c_str()); | ||||
| 			continue; | ||||
| 		} | ||||
| 		RTLIL::Wire *w = tpl->wires.at(portname); | ||||
| 		RTLIL::SigSig c; | ||||
| 		if (w->port_output) { | ||||
| 			c.first = it.second; | ||||
| 			c.second = RTLIL::SigSpec(w); | ||||
| 			apply_prefix(cell->name, c.second, module); | ||||
| 		} else { | ||||
| 			c.first = RTLIL::SigSpec(w); | ||||
| 			c.second = it.second; | ||||
| 			apply_prefix(cell->name, c.first, module); | ||||
| 		} | ||||
| 		if (c.second.width > c.first.width) | ||||
| 			c.second.remove(c.first.width, c.second.width - c.first.width); | ||||
| 		if (c.second.width < c.first.width) | ||||
| 			c.second.append(RTLIL::SigSpec(RTLIL::State::S0, c.first.width - c.second.width)); | ||||
| 		assert(c.first.width == c.second.width); | ||||
| #if 0 | ||||
| 		// more conservative approach:
 | ||||
| 		// connect internal and external wires
 | ||||
| 		module->connections.push_back(c); | ||||
| #else | ||||
| 		// approach that yields nicer outputs:
 | ||||
| 		// replace internal wires that are connected to external wires
 | ||||
| 		if (w->port_output) | ||||
| 			port_signal_map.add(c.second, c.first); | ||||
| 		else | ||||
| 			port_signal_map.add(c.first, c.second); | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto &it : tpl->cells) { | ||||
| 		RTLIL::Cell *c = new RTLIL::Cell(*it.second); | ||||
| 		if (!flatten_mode && c->type.substr(0, 2) == "\\$") | ||||
| 			c->type = c->type.substr(1); | ||||
| 		apply_prefix(cell->name, c->name); | ||||
| 		for (auto &it2 : c->connections) { | ||||
| 			apply_prefix(cell->name, it2.second, module); | ||||
| 			port_signal_map.apply(it2.second); | ||||
| 		} | ||||
| 		module->cells[c->name] = c; | ||||
| 		design->select(module, c); | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto &it : tpl->connections) { | ||||
| 		RTLIL::SigSig c = it; | ||||
| 		apply_prefix(cell->name, c.first, module); | ||||
| 		apply_prefix(cell->name, c.second, module); | ||||
| 		port_signal_map.apply(c.first); | ||||
| 		port_signal_map.apply(c.second); | ||||
| 		module->connections.push_back(c); | ||||
| 	} | ||||
| 
 | ||||
| 	module->cells.erase(cell->name); | ||||
| 	delete cell; | ||||
| } | ||||
| 
 | ||||
| static bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, std::set<RTLIL::Cell*> &handled_cells, | ||||
| 		const std::map<RTLIL::IdString, std::set<RTLIL::IdString>> &celltypeMap, bool flatten_mode) | ||||
| { | ||||
| 	if (!design->selected(module)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	bool log_continue = false; | ||||
| 	bool did_something = false; | ||||
| 	std::vector<std::string> cell_names; | ||||
| 
 | ||||
| 	for (auto &cell_it : module->cells) | ||||
| 		cell_names.push_back(cell_it.first); | ||||
| 
 | ||||
| 	for (auto &cell_name : cell_names) | ||||
| 	TechmapWires techmap_find_special_wires(RTLIL::Module *module) | ||||
| 	{ | ||||
| 		if (module->cells.count(cell_name) == 0) | ||||
| 			continue; | ||||
| 		TechmapWires result; | ||||
| 
 | ||||
| 		RTLIL::Cell *cell = module->cells[cell_name]; | ||||
| 		if (module == NULL) | ||||
| 			return result; | ||||
| 
 | ||||
| 		if (!design->selected(module, cell) || handled_cells.count(cell) > 0) | ||||
| 			continue; | ||||
| 		for (auto &it : module->wires) { | ||||
| 			const char *p = it.first.c_str(); | ||||
| 			if (*p == '$') | ||||
| 				continue; | ||||
| 
 | ||||
| 		if (celltypeMap.count(cell->type) == 0) | ||||
| 			continue; | ||||
| 			const char *q = strrchr(p+1, '.'); | ||||
| 			p = q ? q : p+1; | ||||
| 
 | ||||
| 		for (auto &tpl_name : celltypeMap.at(cell->type)) | ||||
| 		{ | ||||
| 			std::string derived_name = tpl_name; | ||||
| 			RTLIL::Module *tpl = map->modules[tpl_name]; | ||||
| 			std::map<RTLIL::IdString, RTLIL::Const> parameters = cell->parameters; | ||||
| 
 | ||||
| 			if (!flatten_mode) | ||||
| 			{ | ||||
| 				if (tpl->get_bool_attribute("\\techmap_simplemap")) { | ||||
| 					log("Mapping %s.%s (%s) with simplemap.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); | ||||
| 					if (simplemap_mappers.count(cell->type) == 0) | ||||
| 						log_error("No simplemap mapper for cell type %s found!\n", RTLIL::id2cstr(cell->type)); | ||||
| 					simplemap_mappers.at(cell->type)(module, cell); | ||||
| 					module->cells.erase(cell->name); | ||||
| 					delete cell; | ||||
| 					cell = NULL; | ||||
| 					did_something = true; | ||||
| 					break; | ||||
| 				} | ||||
| 
 | ||||
| 				for (auto conn : cell->connections) { | ||||
| 					if (conn.first.substr(0, 1) == "$") | ||||
| 						continue; | ||||
| 					if (tpl->wires.count(conn.first) > 0 && tpl->wires.at(conn.first)->port_id > 0) | ||||
| 						continue; | ||||
| 					if (!conn.second.is_fully_const() || parameters.count(conn.first) > 0 || tpl->avail_parameters.count(conn.first) == 0) | ||||
| 						goto next_tpl; | ||||
| 					parameters[conn.first] = conn.second.as_const(); | ||||
| 				} | ||||
| 
 | ||||
| 				if (0) { | ||||
| 		next_tpl: | ||||
| 					continue; | ||||
| 				} | ||||
| 
 | ||||
| 				if (tpl->avail_parameters.count("\\_TECHMAP_CELLTYPE_") != 0) | ||||
| 					parameters["\\_TECHMAP_CELLTYPE_"] = RTLIL::unescape_id(cell->type); | ||||
| 			if (!strncmp(p, "_TECHMAP_", 9)) { | ||||
| 				TechmapWireData record; | ||||
| 				record.wire = it.second; | ||||
| 				record.value = it.second; | ||||
| 				result[p].push_back(record); | ||||
| 				it.second->attributes["\\keep"] = RTLIL::Const(1); | ||||
| 				it.second->attributes["\\_techmap_special_"] = RTLIL::Const(1); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 			std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>> key(tpl_name, parameters); | ||||
| 			if (techmap_cache.count(key) > 0) { | ||||
| 				tpl = techmap_cache[key]; | ||||
| 		if (!result.empty()) { | ||||
| 			SigMap sigmap(module); | ||||
| 			for (auto &it1 : result) | ||||
| 			for (auto &it2 : it1.second) | ||||
| 				sigmap.apply(it2.value); | ||||
| 		} | ||||
| 
 | ||||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
| 	void techmap_module_worker(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, bool flatten_mode) | ||||
| 	{ | ||||
| 		log("Mapping `%s.%s' using `%s'.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(tpl->name)); | ||||
| 
 | ||||
| 		if (tpl->memories.size() != 0) | ||||
| 			log_error("Technology map yielded memories -> this is not supported.\n"); | ||||
| 
 | ||||
| 		if (tpl->processes.size() != 0) | ||||
| 			log_error("Technology map yielded processes -> this is not supported.\n"); | ||||
| 
 | ||||
| 		std::map<RTLIL::IdString, RTLIL::IdString> positional_ports; | ||||
| 
 | ||||
| 		for (auto &it : tpl->wires) { | ||||
| 			if (it.second->port_id > 0) | ||||
| 				positional_ports[stringf("$%d", it.second->port_id)] = it.first; | ||||
| 			RTLIL::Wire *w = new RTLIL::Wire(*it.second); | ||||
| 			apply_prefix(cell->name, w->name); | ||||
| 			w->port_input = false; | ||||
| 			w->port_output = false; | ||||
| 			w->port_id = 0; | ||||
| 			if (it.second->get_bool_attribute("\\_techmap_special_")) | ||||
| 				w->attributes.clear(); | ||||
| 			module->wires[w->name] = w; | ||||
| 			design->select(module, w); | ||||
| 		} | ||||
| 
 | ||||
| 		SigMap port_signal_map; | ||||
| 
 | ||||
| 		for (auto &it : cell->connections) { | ||||
| 			RTLIL::IdString portname = it.first; | ||||
| 			if (positional_ports.count(portname) > 0) | ||||
| 				portname = positional_ports.at(portname); | ||||
| 			if (tpl->wires.count(portname) == 0 || tpl->wires.at(portname)->port_id == 0) { | ||||
| 				if (portname.substr(0, 1) == "$") | ||||
| 					log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", portname.c_str(), cell->name.c_str(), tpl->name.c_str()); | ||||
| 				continue; | ||||
| 			} | ||||
| 			RTLIL::Wire *w = tpl->wires.at(portname); | ||||
| 			RTLIL::SigSig c; | ||||
| 			if (w->port_output) { | ||||
| 				c.first = it.second; | ||||
| 				c.second = RTLIL::SigSpec(w); | ||||
| 				apply_prefix(cell->name, c.second, module); | ||||
| 			} else { | ||||
| 				if (cell->parameters.size() != 0) { | ||||
| 					derived_name = tpl->derive(map, parameters); | ||||
| 					tpl = map->modules[derived_name]; | ||||
| 					log_continue = true; | ||||
| 				} | ||||
| 				techmap_cache[key] = tpl; | ||||
| 				c.first = RTLIL::SigSpec(w); | ||||
| 				c.second = it.second; | ||||
| 				apply_prefix(cell->name, c.first, module); | ||||
| 			} | ||||
| 			if (c.second.width > c.first.width) | ||||
| 				c.second.remove(c.first.width, c.second.width - c.first.width); | ||||
| 			if (c.second.width < c.first.width) | ||||
| 				c.second.append(RTLIL::SigSpec(RTLIL::State::S0, c.first.width - c.second.width)); | ||||
| 			assert(c.first.width == c.second.width); | ||||
| #if 0 | ||||
| 			// more conservative approach:
 | ||||
| 			// connect internal and external wires
 | ||||
| 			module->connections.push_back(c); | ||||
| #else | ||||
| 			// approach that yields nicer outputs:
 | ||||
| 			// replace internal wires that are connected to external wires
 | ||||
| 			if (w->port_output) | ||||
| 				port_signal_map.add(c.second, c.first); | ||||
| 			else | ||||
| 				port_signal_map.add(c.first, c.second); | ||||
| #endif | ||||
| 		} | ||||
| 
 | ||||
| 			if (flatten_mode) | ||||
| 				techmap_do_cache[tpl] = true; | ||||
| 		for (auto &it : tpl->cells) { | ||||
| 			RTLIL::Cell *c = new RTLIL::Cell(*it.second); | ||||
| 			if (!flatten_mode && c->type.substr(0, 2) == "\\$") | ||||
| 				c->type = c->type.substr(1); | ||||
| 			apply_prefix(cell->name, c->name); | ||||
| 			for (auto &it2 : c->connections) { | ||||
| 				apply_prefix(cell->name, it2.second, module); | ||||
| 				port_signal_map.apply(it2.second); | ||||
| 			} | ||||
| 			module->cells[c->name] = c; | ||||
| 			design->select(module, c); | ||||
| 		} | ||||
| 
 | ||||
| 			if (techmap_do_cache.count(tpl) == 0) | ||||
| 		for (auto &it : tpl->connections) { | ||||
| 			RTLIL::SigSig c = it; | ||||
| 			apply_prefix(cell->name, c.first, module); | ||||
| 			apply_prefix(cell->name, c.second, module); | ||||
| 			port_signal_map.apply(c.first); | ||||
| 			port_signal_map.apply(c.second); | ||||
| 			module->connections.push_back(c); | ||||
| 		} | ||||
| 
 | ||||
| 		module->cells.erase(cell->name); | ||||
| 		delete cell; | ||||
| 	} | ||||
| 
 | ||||
| 	bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, std::set<RTLIL::Cell*> &handled_cells, | ||||
| 			const std::map<RTLIL::IdString, std::set<RTLIL::IdString>> &celltypeMap, bool flatten_mode) | ||||
| 	{ | ||||
| 		if (!design->selected(module)) | ||||
| 			return false; | ||||
| 
 | ||||
| 		bool log_continue = false; | ||||
| 		bool did_something = false; | ||||
| 		std::vector<std::string> cell_names; | ||||
| 
 | ||||
| 		for (auto &cell_it : module->cells) | ||||
| 			cell_names.push_back(cell_it.first); | ||||
| 
 | ||||
| 		for (auto &cell_name : cell_names) | ||||
| 		{ | ||||
| 			if (module->cells.count(cell_name) == 0) | ||||
| 				continue; | ||||
| 
 | ||||
| 			RTLIL::Cell *cell = module->cells[cell_name]; | ||||
| 
 | ||||
| 			if (!design->selected(module, cell) || handled_cells.count(cell) > 0) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (celltypeMap.count(cell->type) == 0) | ||||
| 				continue; | ||||
| 
 | ||||
| 			for (auto &tpl_name : celltypeMap.at(cell->type)) | ||||
| 			{ | ||||
| 				bool keep_running = true; | ||||
| 				techmap_do_cache[tpl] = true; | ||||
| 				std::string derived_name = tpl_name; | ||||
| 				RTLIL::Module *tpl = map->modules[tpl_name]; | ||||
| 				std::map<RTLIL::IdString, RTLIL::Const> parameters = cell->parameters; | ||||
| 
 | ||||
| 				while (keep_running) | ||||
| 				if (!flatten_mode) | ||||
| 				{ | ||||
| 					TechmapWires twd = techmap_find_special_wires(tpl); | ||||
| 					keep_running = false; | ||||
| 					if (tpl->get_bool_attribute("\\techmap_simplemap")) { | ||||
| 						log("Mapping %s.%s (%s) with simplemap.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); | ||||
| 						if (simplemap_mappers.count(cell->type) == 0) | ||||
| 							log_error("No simplemap mapper for cell type %s found!\n", RTLIL::id2cstr(cell->type)); | ||||
| 						simplemap_mappers.at(cell->type)(module, cell); | ||||
| 						module->cells.erase(cell->name); | ||||
| 						delete cell; | ||||
| 						cell = NULL; | ||||
| 						did_something = true; | ||||
| 						break; | ||||
| 					} | ||||
| 
 | ||||
| 					for (auto &it : twd["_TECHMAP_FAIL_"]) { | ||||
| 						RTLIL::SigSpec value = it.value; | ||||
| 						if (value.is_fully_const() && value.as_bool()) { | ||||
| 							log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n", | ||||
| 									derived_name.c_str(), RTLIL::id2cstr(it.wire->name), log_signal(value)); | ||||
| 							techmap_do_cache[tpl] = false; | ||||
| 					for (auto conn : cell->connections) { | ||||
| 						if (conn.first.substr(0, 1) == "$") | ||||
| 							continue; | ||||
| 						if (tpl->wires.count(conn.first) > 0 && tpl->wires.at(conn.first)->port_id > 0) | ||||
| 							continue; | ||||
| 						if (!conn.second.is_fully_const() || parameters.count(conn.first) > 0 || tpl->avail_parameters.count(conn.first) == 0) | ||||
| 							goto next_tpl; | ||||
| 						parameters[conn.first] = conn.second.as_const(); | ||||
| 					} | ||||
| 
 | ||||
| 					if (0) { | ||||
| 			next_tpl: | ||||
| 						continue; | ||||
| 					} | ||||
| 
 | ||||
| 					if (tpl->avail_parameters.count("\\_TECHMAP_CELLTYPE_") != 0) | ||||
| 						parameters["\\_TECHMAP_CELLTYPE_"] = RTLIL::unescape_id(cell->type); | ||||
| 				} | ||||
| 
 | ||||
| 				std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>> key(tpl_name, parameters); | ||||
| 				if (techmap_cache.count(key) > 0) { | ||||
| 					tpl = techmap_cache[key]; | ||||
| 				} else { | ||||
| 					if (cell->parameters.size() != 0) { | ||||
| 						derived_name = tpl->derive(map, parameters); | ||||
| 						tpl = map->modules[derived_name]; | ||||
| 						log_continue = true; | ||||
| 					} | ||||
| 					techmap_cache[key] = tpl; | ||||
| 				} | ||||
| 
 | ||||
| 				if (flatten_mode) | ||||
| 					techmap_do_cache[tpl] = true; | ||||
| 
 | ||||
| 				if (techmap_do_cache.count(tpl) == 0) | ||||
| 				{ | ||||
| 					bool keep_running = true; | ||||
| 					techmap_do_cache[tpl] = true; | ||||
| 
 | ||||
| 					while (keep_running) | ||||
| 					{ | ||||
| 						TechmapWires twd = techmap_find_special_wires(tpl); | ||||
| 						keep_running = false; | ||||
| 
 | ||||
| 						for (auto &it : twd["_TECHMAP_FAIL_"]) { | ||||
| 							RTLIL::SigSpec value = it.value; | ||||
| 							if (value.is_fully_const() && value.as_bool()) { | ||||
| 								log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n", | ||||
| 										derived_name.c_str(), RTLIL::id2cstr(it.wire->name), log_signal(value)); | ||||
| 								techmap_do_cache[tpl] = false; | ||||
| 							} | ||||
| 						} | ||||
| 
 | ||||
| 						if (!techmap_do_cache[tpl]) | ||||
| 							break; | ||||
| 
 | ||||
| 						for (auto &it : twd) | ||||
| 						{ | ||||
| 							if (it.first.substr(0, 12) != "_TECHMAP_DO_" || it.second.empty()) | ||||
| 								continue; | ||||
| 
 | ||||
| 							auto &data = it.second.front(); | ||||
| 
 | ||||
| 							if (!data.value.is_fully_const()) | ||||
| 								log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(data.wire->name), log_signal(data.value)); | ||||
| 
 | ||||
| 							tpl->wires.erase(data.wire->name); | ||||
| 							const char *p = data.wire->name.c_str(); | ||||
| 							const char *q = strrchr(p+1, '.'); | ||||
| 							q = q ? q : p+1; | ||||
| 
 | ||||
| 							assert(!strncmp(q, "_TECHMAP_DO_", 12)); | ||||
| 							std::string new_name = data.wire->name.substr(0, q-p) + "_TECHMAP_DONE_" + data.wire->name.substr(q-p+12); | ||||
| 							while (tpl->wires.count(new_name)) | ||||
| 								new_name += "_"; | ||||
| 							data.wire->name = new_name; | ||||
| 							tpl->add(data.wire); | ||||
| 
 | ||||
| 							std::string cmd_string = data.value.as_const().decode_string(); | ||||
| 
 | ||||
| 							RTLIL::Selection tpl_mod_sel(false); | ||||
| 							tpl_mod_sel.select(tpl); | ||||
| 							map->selection_stack.push_back(tpl_mod_sel); | ||||
| 							Pass::call(map, cmd_string); | ||||
| 							map->selection_stack.pop_back(); | ||||
| 
 | ||||
| 							keep_running = true; | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					if (!techmap_do_cache[tpl]) | ||||
| 						break; | ||||
| 
 | ||||
| 					for (auto &it : twd) | ||||
| 					{ | ||||
| 						if (it.first.substr(0, 12) != "_TECHMAP_DO_" || it.second.empty()) | ||||
| 							continue; | ||||
| 
 | ||||
| 						auto &data = it.second.front(); | ||||
| 
 | ||||
| 						if (!data.value.is_fully_const()) | ||||
| 							log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(data.wire->name), log_signal(data.value)); | ||||
| 
 | ||||
| 						tpl->wires.erase(data.wire->name); | ||||
| 						const char *p = data.wire->name.c_str(); | ||||
| 						const char *q = strrchr(p+1, '.'); | ||||
| 						q = q ? q : p+1; | ||||
| 
 | ||||
| 						assert(!strncmp(q, "_TECHMAP_DO_", 12)); | ||||
| 						std::string new_name = data.wire->name.substr(0, q-p) + "_TECHMAP_DONE_" + data.wire->name.substr(q-p+12); | ||||
| 						while (tpl->wires.count(new_name)) | ||||
| 							new_name += "_"; | ||||
| 						data.wire->name = new_name; | ||||
| 						tpl->add(data.wire); | ||||
| 
 | ||||
| 						std::string cmd_string = data.value.as_const().decode_string(); | ||||
| 
 | ||||
| 						RTLIL::Selection tpl_mod_sel(false); | ||||
| 						tpl_mod_sel.select(tpl); | ||||
| 						map->selection_stack.push_back(tpl_mod_sel); | ||||
| 						Pass::call(map, cmd_string); | ||||
| 						map->selection_stack.pop_back(); | ||||
| 
 | ||||
| 						keep_running = true; | ||||
| 						break; | ||||
| 					TechmapWires twd = techmap_find_special_wires(tpl); | ||||
| 					for (auto &it : twd) { | ||||
| 						if (it.first != "_TECHMAP_FAIL_" && it.first.substr(0, 12) != "_TECHMAP_DO_" && it.first.substr(0, 14) != "_TECHMAP_DONE_") | ||||
| 							log_error("Techmap yielded unknown config wire %s.\n", it.first.c_str()); | ||||
| 						if (techmap_do_cache[tpl]) | ||||
| 							for (auto &it2 : it.second) | ||||
| 								if (!it2.value.is_fully_const()) | ||||
| 									log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(it2.wire->name), log_signal(it2.value)); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				TechmapWires twd = techmap_find_special_wires(tpl); | ||||
| 				for (auto &it : twd) { | ||||
| 					if (it.first != "_TECHMAP_FAIL_" && it.first.substr(0, 12) != "_TECHMAP_DO_" && it.first.substr(0, 14) != "_TECHMAP_DONE_") | ||||
| 						log_error("Techmap yielded unknown config wire %s.\n", it.first.c_str()); | ||||
| 					if (techmap_do_cache[tpl]) | ||||
| 						for (auto &it2 : it.second) | ||||
| 							if (!it2.value.is_fully_const()) | ||||
| 								log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(it2.wire->name), log_signal(it2.value)); | ||||
| 				if (techmap_do_cache.at(tpl) == false) | ||||
| 					continue; | ||||
| 
 | ||||
| 				if (log_continue) { | ||||
| 					log_header("Continuing TECHMAP pass.\n"); | ||||
| 					log_continue = false; | ||||
| 				} | ||||
| 
 | ||||
| 				techmap_module_worker(design, module, cell, tpl, flatten_mode); | ||||
| 				did_something = true; | ||||
| 				cell = NULL; | ||||
| 				break; | ||||
| 			} | ||||
| 
 | ||||
| 			if (techmap_do_cache.at(tpl) == false) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (log_continue) { | ||||
| 				log_header("Continuing TECHMAP pass.\n"); | ||||
| 				log_continue = false; | ||||
| 			} | ||||
| 
 | ||||
| 			techmap_module_worker(design, module, cell, tpl, flatten_mode); | ||||
| 			did_something = true; | ||||
| 			cell = NULL; | ||||
| 			break; | ||||
| 			handled_cells.insert(cell); | ||||
| 		} | ||||
| 
 | ||||
| 		handled_cells.insert(cell); | ||||
| 	} | ||||
| 		if (log_continue) { | ||||
| 			log_header("Continuing TECHMAP pass.\n"); | ||||
| 			log_continue = false; | ||||
| 		} | ||||
| 
 | ||||
| 	if (log_continue) { | ||||
| 		log_header("Continuing TECHMAP pass.\n"); | ||||
| 		log_continue = false; | ||||
| 		return did_something; | ||||
| 	} | ||||
| 
 | ||||
| 	return did_something; | ||||
| } | ||||
| }; | ||||
| 
 | ||||
| struct TechmapPass : public Pass { | ||||
| 	TechmapPass() : Pass("techmap", "generic technology mapper") { } | ||||
|  | @ -469,7 +472,8 @@ struct TechmapPass : public Pass { | |||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		simplemap_get_mappers(simplemap_mappers); | ||||
| 		TechmapWorker worker; | ||||
| 		simplemap_get_mappers(worker.simplemap_mappers); | ||||
| 
 | ||||
| 		RTLIL::Design *map = new RTLIL::Design; | ||||
| 		if (map_files.empty()) { | ||||
|  | @ -509,17 +513,15 @@ struct TechmapPass : public Pass { | |||
| 		while (did_something) { | ||||
| 			did_something = false; | ||||
| 			for (auto &mod_it : design->modules) | ||||
| 				if (techmap_module(design, mod_it.second, map, handled_cells, celltypeMap, false)) | ||||
| 				if (worker.techmap_module(design, mod_it.second, map, handled_cells, celltypeMap, false)) | ||||
| 					did_something = true; | ||||
| 			if (did_something) | ||||
| 				design->check(); | ||||
| 		} | ||||
| 
 | ||||
| 		log("No more expansions possible.\n"); | ||||
| 		techmap_cache.clear(); | ||||
| 		techmap_do_cache.clear(); | ||||
| 		simplemap_mappers.clear(); | ||||
| 		delete map; | ||||
| 
 | ||||
| 		log_pop(); | ||||
| 	} | ||||
| } TechmapPass; | ||||
|  | @ -544,6 +546,8 @@ struct FlattenPass : public Pass { | |||
| 
 | ||||
| 		extra_args(args, 1, design); | ||||
| 
 | ||||
| 		TechmapWorker worker; | ||||
| 
 | ||||
| 		std::map<RTLIL::IdString, std::set<RTLIL::IdString>> celltypeMap; | ||||
| 		for (auto &it : design->modules) | ||||
| 			celltypeMap[it.first].insert(it.first); | ||||
|  | @ -559,11 +563,11 @@ struct FlattenPass : public Pass { | |||
| 		while (did_something) { | ||||
| 			did_something = false; | ||||
| 			if (top_mod != NULL) { | ||||
| 				if (techmap_module(design, top_mod, design, handled_cells, celltypeMap, true)) | ||||
| 				if (worker.techmap_module(design, top_mod, design, handled_cells, celltypeMap, true)) | ||||
| 					did_something = true; | ||||
| 			} else { | ||||
| 				for (auto &mod_it : design->modules) | ||||
| 					if (techmap_module(design, mod_it.second, design, handled_cells, celltypeMap, true)) | ||||
| 					if (worker.techmap_module(design, mod_it.second, design, handled_cells, celltypeMap, true)) | ||||
| 						did_something = true; | ||||
| 			} | ||||
| 		} | ||||
|  | @ -582,8 +586,6 @@ struct FlattenPass : public Pass { | |||
| 			design->modules.swap(new_modules); | ||||
| 		} | ||||
| 
 | ||||
| 		techmap_cache.clear(); | ||||
| 		techmap_do_cache.clear(); | ||||
| 		log_pop(); | ||||
| 	} | ||||
| } FlattenPass; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue