diff options
Diffstat (limited to 'passes/cmds/splitnets.cc')
| -rw-r--r-- | passes/cmds/splitnets.cc | 103 | 
1 files changed, 92 insertions, 11 deletions
| diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index d4e721a5d..14eeb066f 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -2,11 +2,11 @@   *  yosys -- Yosys Open SYnthesis Suite   *   *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> - *   + *   *  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 @@ -50,10 +50,23 @@ struct SplitnetsWorker  			new_wire_name += format.substr(1, 1);  		RTLIL::Wire *new_wire = module->addWire(module->uniquify(new_wire_name), width); -		new_wire->port_id = wire->port_id; +		new_wire->port_id = wire->port_id ? wire->port_id + offset : 0;  		new_wire->port_input = wire->port_input;  		new_wire->port_output = wire->port_output; +		if (wire->attributes.count("\\src")) +			new_wire->attributes["\\src"] = wire->attributes.at("\\src"); + +		if (wire->attributes.count("\\keep")) +			new_wire->attributes["\\keep"] = wire->attributes.at("\\keep"); + +		if (wire->attributes.count("\\init")) { +			Const old_init = wire->attributes.at("\\init"), new_init; +			for (int i = offset; i < offset+width; i++) +				new_init.bits.push_back(i < GetSize(old_init) ? old_init.bits.at(i) : State::Sx); +			new_wire->attributes["\\init"] = new_init; +		} +  		std::vector<RTLIL::SigBit> sigvec = RTLIL::SigSpec(new_wire).to_sigbit_vector();  		splitmap[wire].insert(splitmap[wire].end(), sigvec.begin(), sigvec.end());  	} @@ -96,7 +109,7 @@ struct SplitnetsPass : public Pass {  		bool flag_driver = false;  		std::string format = "[]:"; -		log_header("Executing SPLITNETS pass (splitting up multi-bit signals).\n"); +		log_header(design, "Executing SPLITNETS pass (splitting up multi-bit signals).\n");  		size_t argidx;  		for (argidx = 1; argidx < args.size(); argidx++) @@ -117,14 +130,27 @@ struct SplitnetsPass : public Pass {  		}  		extra_args(args, argidx, design); -		for (auto &mod_it : design->modules_) -		{ -			RTLIL::Module *module = mod_it.second; -			if (!design->selected(module)) -				continue; +		// module_ports_db[module_name][old_port_name] = new_port_name_list +		dict<IdString, dict<IdString, vector<IdString>>> module_ports_db; +		for (auto module : design->selected_modules()) +		{  			SplitnetsWorker worker; +			if (flag_ports) +			{ +				int normalized_port_factor = 0; + +				for (auto wire : module->wires()) +					if (wire->port_id != 0) { +						normalized_port_factor = max(normalized_port_factor, wire->port_id+1); +						normalized_port_factor = max(normalized_port_factor, GetSize(wire)+1); +					} + +				for (auto wire : module->wires()) +					wire->port_id *= normalized_port_factor; +			} +  			if (flag_driver)  			{  				CellTypes ct(design); @@ -176,14 +202,69 @@ struct SplitnetsPass : public Pass {  			module->rewrite_sigspecs(worker); +			if (flag_ports) +			{ +				for (auto wire : module->wires()) +				{ +					if (wire->port_id == 0) +						continue; + +					SigSpec sig(wire); +					worker(sig); + +					if (sig == wire) +						continue; + +					vector<IdString> &new_ports = module_ports_db[module->name][wire->name]; + +					for (SigSpec c : sig.chunks()) +						new_ports.push_back(c.as_wire()->name); +				} +			} +  			pool<RTLIL::Wire*> delete_wires;  			for (auto &it : worker.splitmap)  				delete_wires.insert(it.first);  			module->remove(delete_wires); -			module->fixup_ports(); +			if (flag_ports) +				module->fixup_ports(); +		} + +		if (!module_ports_db.empty()) +		{ +			for (auto module : design->modules()) +			for (auto cell : module->cells()) +			{ +				if (module_ports_db.count(cell->type) == 0) +					continue; + +				for (auto &it : module_ports_db.at(cell->type)) +				{ +					IdString port_id = it.first; +					const auto &new_port_ids = it.second; + +					if (!cell->hasPort(port_id)) +						continue; + +					int offset = 0; +					SigSpec sig = cell->getPort(port_id); + +					for (auto nid : new_port_ids) +					{ +						int nlen = GetSize(design->module(cell->type)->wire(nid)); +						if (offset + nlen > GetSize(sig)) +							nlen = GetSize(sig) - offset; +						if (nlen > 0) +							cell->setPort(nid, sig.extract(offset, nlen)); +						offset += nlen; +					} + +					cell->unsetPort(port_id); +				} +			}  		}  	}  } SplitnetsPass; -  +  PRIVATE_NAMESPACE_END | 
