mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into mwk/xilinx_bufgmap
This commit is contained in:
		
						commit
						6b51c154c6
					
				
					 57 changed files with 3405 additions and 3376 deletions
				
			
		| 
						 | 
				
			
			@ -107,7 +107,7 @@ struct DeletePass : public Pass {
 | 
			
		|||
			for (auto &it : module->cells_) {
 | 
			
		||||
				if (design->selected(module, it.second))
 | 
			
		||||
					delete_cells.insert(it.second);
 | 
			
		||||
				if ((it.second->type == "$memrd" || it.second->type == "$memwr") &&
 | 
			
		||||
				if (it.second->type.in("$memrd", "$memwr") &&
 | 
			
		||||
						delete_mems.count(it.second->parameters.at("\\MEMID").decode_string()) != 0)
 | 
			
		||||
					delete_cells.insert(it.second);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,22 +37,22 @@ struct ExclusiveDatabase
 | 
			
		|||
		SigBit y_port;
 | 
			
		||||
		pool<Cell*> reduce_or;
 | 
			
		||||
		for (auto cell : module->cells()) {
 | 
			
		||||
			if (cell->type == "$eq") {
 | 
			
		||||
				nonconst_sig = sigmap(cell->getPort("\\A"));
 | 
			
		||||
				const_sig = sigmap(cell->getPort("\\B"));
 | 
			
		||||
			if (cell->type == ID($eq)) {
 | 
			
		||||
				nonconst_sig = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
				const_sig = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
				if (!const_sig.is_fully_const()) {
 | 
			
		||||
					if (!nonconst_sig.is_fully_const())
 | 
			
		||||
						continue;
 | 
			
		||||
					std::swap(nonconst_sig, const_sig);
 | 
			
		||||
				}
 | 
			
		||||
				y_port = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
				y_port = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
			}
 | 
			
		||||
			else if (cell->type == "$logic_not") {
 | 
			
		||||
				nonconst_sig = sigmap(cell->getPort("\\A"));
 | 
			
		||||
			else if (cell->type == ID($logic_not)) {
 | 
			
		||||
				nonconst_sig = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
				const_sig = Const(State::S0, GetSize(nonconst_sig));
 | 
			
		||||
				y_port = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
				y_port = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
			}
 | 
			
		||||
			else if (cell->type == "$reduce_or") {
 | 
			
		||||
			else if (cell->type == ID($reduce_or)) {
 | 
			
		||||
				reduce_or.insert(cell);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +66,7 @@ struct ExclusiveDatabase
 | 
			
		|||
		for (auto cell : reduce_or) {
 | 
			
		||||
			nonconst_sig = SigSpec();
 | 
			
		||||
			std::vector<Const> values;
 | 
			
		||||
			SigSpec a_port = sigmap(cell->getPort("\\A"));
 | 
			
		||||
			SigSpec a_port = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
			for (auto bit : a_port) {
 | 
			
		||||
				auto it = sig_cmp_prev.find(bit);
 | 
			
		||||
				if (it == sig_cmp_prev.end()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +84,7 @@ struct ExclusiveDatabase
 | 
			
		|||
			}
 | 
			
		||||
			if (nonconst_sig.empty())
 | 
			
		||||
				continue;
 | 
			
		||||
			y_port = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
			y_port = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
			sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +135,7 @@ struct MuxpackWorker
 | 
			
		|||
	{
 | 
			
		||||
		for (auto wire : module->wires())
 | 
			
		||||
		{
 | 
			
		||||
			if (wire->port_output || wire->get_bool_attribute("\\keep")) {
 | 
			
		||||
			if (wire->port_output || wire->get_bool_attribute(ID(keep))) {
 | 
			
		||||
				for (auto bit : sigmap(wire))
 | 
			
		||||
					sigbit_with_non_chain_users.insert(bit);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -143,13 +143,13 @@ struct MuxpackWorker
 | 
			
		|||
 | 
			
		||||
		for (auto cell : module->cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep"))
 | 
			
		||||
			if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID(keep)))
 | 
			
		||||
			{
 | 
			
		||||
				SigSpec a_sig = sigmap(cell->getPort("\\A"));
 | 
			
		||||
				SigSpec a_sig = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
				SigSpec b_sig;
 | 
			
		||||
				if (cell->type == "$mux")
 | 
			
		||||
					b_sig = sigmap(cell->getPort("\\B"));
 | 
			
		||||
				SigSpec y_sig = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
				if (cell->type == ID($mux))
 | 
			
		||||
					b_sig = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
				SigSpec y_sig = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
   
 | 
			
		||||
				if (sig_chain_next.count(a_sig))
 | 
			
		||||
					for (auto a_bit : a_sig.bits())
 | 
			
		||||
| 
						 | 
				
			
			@ -186,16 +186,16 @@ struct MuxpackWorker
 | 
			
		|||
		{
 | 
			
		||||
			log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
 | 
			
		||||
 | 
			
		||||
			SigSpec a_sig = sigmap(cell->getPort("\\A"));
 | 
			
		||||
			if (cell->type == "$mux") {
 | 
			
		||||
				SigSpec b_sig = sigmap(cell->getPort("\\B"));
 | 
			
		||||
			SigSpec a_sig = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
			if (cell->type == ID($mux)) {
 | 
			
		||||
				SigSpec b_sig = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
				if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
 | 
			
		||||
					goto start_cell;
 | 
			
		||||
 | 
			
		||||
				if (!sig_chain_prev.count(a_sig))
 | 
			
		||||
					a_sig = b_sig;
 | 
			
		||||
			}
 | 
			
		||||
			else if (cell->type == "$pmux") {
 | 
			
		||||
			else if (cell->type == ID($pmux)) {
 | 
			
		||||
				if (!sig_chain_prev.count(a_sig))
 | 
			
		||||
					goto start_cell;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -208,8 +208,8 @@ struct MuxpackWorker
 | 
			
		|||
			{
 | 
			
		||||
				Cell *prev_cell = sig_chain_prev.at(a_sig);
 | 
			
		||||
				log_assert(prev_cell);
 | 
			
		||||
				SigSpec s_sig = sigmap(cell->getPort("\\S"));
 | 
			
		||||
				s_sig.append(sigmap(prev_cell->getPort("\\S")));
 | 
			
		||||
				SigSpec s_sig = sigmap(cell->getPort(ID(S)));
 | 
			
		||||
				s_sig.append(sigmap(prev_cell->getPort(ID(S))));
 | 
			
		||||
				if (!excl_db.query(s_sig))
 | 
			
		||||
					goto start_cell;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -230,7 +230,7 @@ struct MuxpackWorker
 | 
			
		|||
		{
 | 
			
		||||
			chain.push_back(c);
 | 
			
		||||
 | 
			
		||||
			SigSpec y_sig = sigmap(c->getPort("\\Y"));
 | 
			
		||||
			SigSpec y_sig = sigmap(c->getPort(ID(Y)));
 | 
			
		||||
 | 
			
		||||
			if (sig_chain_next.count(y_sig) == 0)
 | 
			
		||||
				break;
 | 
			
		||||
| 
						 | 
				
			
			@ -269,29 +269,29 @@ struct MuxpackWorker
 | 
			
		|||
			mux_count += cases;
 | 
			
		||||
			pmux_count += 1;
 | 
			
		||||
 | 
			
		||||
			first_cell->type = "$pmux";
 | 
			
		||||
			SigSpec b_sig = first_cell->getPort("\\B");
 | 
			
		||||
			SigSpec s_sig = first_cell->getPort("\\S");
 | 
			
		||||
			first_cell->type = ID($pmux);
 | 
			
		||||
			SigSpec b_sig = first_cell->getPort(ID(B));
 | 
			
		||||
			SigSpec s_sig = first_cell->getPort(ID(S));
 | 
			
		||||
 | 
			
		||||
			for (int i = 1; i < cases; i++) {
 | 
			
		||||
				Cell* prev_cell = chain[cursor+i-1];
 | 
			
		||||
				Cell* cursor_cell = chain[cursor+i];
 | 
			
		||||
				if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) {
 | 
			
		||||
					b_sig.append(cursor_cell->getPort("\\B"));
 | 
			
		||||
					s_sig.append(cursor_cell->getPort("\\S"));
 | 
			
		||||
				if (sigmap(prev_cell->getPort(ID(Y))) == sigmap(cursor_cell->getPort(ID(A)))) {
 | 
			
		||||
					b_sig.append(cursor_cell->getPort(ID(B)));
 | 
			
		||||
					s_sig.append(cursor_cell->getPort(ID(S)));
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					log_assert(cursor_cell->type == "$mux");
 | 
			
		||||
					b_sig.append(cursor_cell->getPort("\\A"));
 | 
			
		||||
					s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S")));
 | 
			
		||||
					log_assert(cursor_cell->type == ID($mux));
 | 
			
		||||
					b_sig.append(cursor_cell->getPort(ID(A)));
 | 
			
		||||
					s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID(S))));
 | 
			
		||||
				}
 | 
			
		||||
				remove_cells.insert(cursor_cell);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			first_cell->setPort("\\B", b_sig);
 | 
			
		||||
			first_cell->setPort("\\S", s_sig);
 | 
			
		||||
			first_cell->setParam("\\S_WIDTH", GetSize(s_sig));
 | 
			
		||||
			first_cell->setPort("\\Y", last_cell->getPort("\\Y"));
 | 
			
		||||
			first_cell->setPort(ID(B), b_sig);
 | 
			
		||||
			first_cell->setPort(ID(S), s_sig);
 | 
			
		||||
			first_cell->setParam(ID(S_WIDTH), GetSize(s_sig));
 | 
			
		||||
			first_cell->setPort(ID(Y), last_cell->getPort(ID(Y)));
 | 
			
		||||
 | 
			
		||||
			cursor += cases;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,7 +52,7 @@ struct keep_cache_t
 | 
			
		|||
			return cache.at(module);
 | 
			
		||||
 | 
			
		||||
		cache[module] = true;
 | 
			
		||||
		if (!module->get_bool_attribute("\\keep")) {
 | 
			
		||||
		if (!module->get_bool_attribute(ID(keep))) {
 | 
			
		||||
			bool found_keep = false;
 | 
			
		||||
			for (auto cell : module->cells())
 | 
			
		||||
				if (query(cell)) found_keep = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ struct keep_cache_t
 | 
			
		|||
 | 
			
		||||
	bool query(Cell *cell)
 | 
			
		||||
	{
 | 
			
		||||
		if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3", "$specrule"))
 | 
			
		||||
		if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover), ID($specify2), ID($specify3), ID($specrule)))
 | 
			
		||||
			return true;
 | 
			
		||||
 | 
			
		||||
		if (cell->has_keep_attr())
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +122,7 @@ void rmunused_module_cells(Module *module, bool verbose)
 | 
			
		|||
 | 
			
		||||
	for (auto &it : module->wires_) {
 | 
			
		||||
		Wire *wire = it.second;
 | 
			
		||||
		if (wire->port_output || wire->get_bool_attribute("\\keep")) {
 | 
			
		||||
		if (wire->port_output || wire->get_bool_attribute(ID(keep))) {
 | 
			
		||||
			for (auto bit : sigmap(wire))
 | 
			
		||||
			for (auto c : wire2driver[bit])
 | 
			
		||||
				queue.insert(c), unused.erase(c);
 | 
			
		||||
| 
						 | 
				
			
			@ -177,8 +177,8 @@ void rmunused_module_cells(Module *module, bool verbose)
 | 
			
		|||
int count_nontrivial_wire_attrs(RTLIL::Wire *w)
 | 
			
		||||
{
 | 
			
		||||
	int count = w->attributes.size();
 | 
			
		||||
	count -= w->attributes.count("\\src");
 | 
			
		||||
	count -= w->attributes.count("\\unused_bits");
 | 
			
		||||
	count -= w->attributes.count(ID(src));
 | 
			
		||||
	count -= w->attributes.count(ID(unused_bits));
 | 
			
		||||
	return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -297,7 +297,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 | 
			
		|||
			if (!wire->port_input)
 | 
			
		||||
				used_signals_nodrivers.add(sig);
 | 
			
		||||
		}
 | 
			
		||||
		if (wire->get_bool_attribute("\\keep")) {
 | 
			
		||||
		if (wire->get_bool_attribute(ID(keep))) {
 | 
			
		||||
			RTLIL::SigSpec sig = RTLIL::SigSpec(wire);
 | 
			
		||||
			assign_map.apply(sig);
 | 
			
		||||
			used_signals.add(sig);
 | 
			
		||||
| 
						 | 
				
			
			@ -311,19 +311,19 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 | 
			
		|||
		log_assert(GetSize(s1) == GetSize(s2));
 | 
			
		||||
 | 
			
		||||
		Const initval;
 | 
			
		||||
		if (wire->attributes.count("\\init"))
 | 
			
		||||
			initval = wire->attributes.at("\\init");
 | 
			
		||||
		if (wire->attributes.count(ID(init)))
 | 
			
		||||
			initval = wire->attributes.at(ID(init));
 | 
			
		||||
		if (GetSize(initval) != GetSize(wire))
 | 
			
		||||
			initval.bits.resize(GetSize(wire), State::Sx);
 | 
			
		||||
		if (initval.is_fully_undef())
 | 
			
		||||
			wire->attributes.erase("\\init");
 | 
			
		||||
			wire->attributes.erase(ID(init));
 | 
			
		||||
 | 
			
		||||
		if (GetSize(wire) == 0) {
 | 
			
		||||
			// delete zero-width wires, unless they are module ports
 | 
			
		||||
			if (wire->port_id == 0)
 | 
			
		||||
				goto delete_this_wire;
 | 
			
		||||
		} else
 | 
			
		||||
		if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) {
 | 
			
		||||
		if (wire->port_id != 0 || wire->get_bool_attribute(ID(keep)) || !initval.is_fully_undef()) {
 | 
			
		||||
			// do not delete anything with "keep" or module ports or initialized wires
 | 
			
		||||
		} else
 | 
			
		||||
		if (!purge_mode && check_public_name(wire->name) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -357,9 +357,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 | 
			
		|||
				}
 | 
			
		||||
			if (new_conn.first.size() > 0) {
 | 
			
		||||
				if (initval.is_fully_undef())
 | 
			
		||||
					wire->attributes.erase("\\init");
 | 
			
		||||
					wire->attributes.erase(ID(init));
 | 
			
		||||
				else
 | 
			
		||||
					wire->attributes.at("\\init") = initval;
 | 
			
		||||
					wire->attributes.at(ID(init)) = initval;
 | 
			
		||||
				used_signals.add(new_conn.first);
 | 
			
		||||
				used_signals.add(new_conn.second);
 | 
			
		||||
				module->connect(new_conn);
 | 
			
		||||
| 
						 | 
				
			
			@ -377,11 +377,11 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 | 
			
		|||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if (unused_bits.empty() || wire->port_id != 0)
 | 
			
		||||
					wire->attributes.erase("\\unused_bits");
 | 
			
		||||
					wire->attributes.erase(ID(unused_bits));
 | 
			
		||||
				else
 | 
			
		||||
					wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits);
 | 
			
		||||
					wire->attributes[ID(unused_bits)] = RTLIL::Const(unused_bits);
 | 
			
		||||
			} else {
 | 
			
		||||
				wire->attributes.erase("\\unused_bits");
 | 
			
		||||
				wire->attributes.erase(ID(unused_bits));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -413,18 +413,18 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
 | 
			
		|||
	dict<SigBit, State> qbits;
 | 
			
		||||
 | 
			
		||||
	for (auto cell : module->cells())
 | 
			
		||||
		if (fftypes.cell_known(cell->type) && cell->hasPort("\\Q"))
 | 
			
		||||
		if (fftypes.cell_known(cell->type) && cell->hasPort(ID(Q)))
 | 
			
		||||
		{
 | 
			
		||||
			SigSpec sig = cell->getPort("\\Q");
 | 
			
		||||
			SigSpec sig = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < GetSize(sig); i++)
 | 
			
		||||
			{
 | 
			
		||||
				SigBit bit = sig[i];
 | 
			
		||||
 | 
			
		||||
				if (bit.wire == nullptr || bit.wire->attributes.count("\\init") == 0)
 | 
			
		||||
				if (bit.wire == nullptr || bit.wire->attributes.count(ID(init)) == 0)
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				Const init = bit.wire->attributes.at("\\init");
 | 
			
		||||
				Const init = bit.wire->attributes.at(ID(init));
 | 
			
		||||
 | 
			
		||||
				if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz)
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -439,10 +439,10 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
 | 
			
		|||
		if (!purge_mode && wire->name[0] == '\\')
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (wire->attributes.count("\\init") == 0)
 | 
			
		||||
		if (wire->attributes.count(ID(init)) == 0)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		Const init = wire->attributes.at("\\init");
 | 
			
		||||
		Const init = wire->attributes.at(ID(init));
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -465,7 +465,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
 | 
			
		|||
		if (verbose)
 | 
			
		||||
			log_debug("  removing redundant init attribute on %s.\n", log_id(wire));
 | 
			
		||||
 | 
			
		||||
		wire->attributes.erase("\\init");
 | 
			
		||||
		wire->attributes.erase(ID(init));
 | 
			
		||||
		did_something = true;
 | 
			
		||||
	next_wire:;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -480,10 +480,10 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
 | 
			
		|||
 | 
			
		||||
	std::vector<RTLIL::Cell*> delcells;
 | 
			
		||||
	for (auto cell : module->cells())
 | 
			
		||||
		if (cell->type.in("$pos", "$_BUF_") && !cell->has_keep_attr()) {
 | 
			
		||||
			bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool();
 | 
			
		||||
			RTLIL::SigSpec a = cell->getPort("\\A");
 | 
			
		||||
			RTLIL::SigSpec y = cell->getPort("\\Y");
 | 
			
		||||
		if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) {
 | 
			
		||||
			bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool();
 | 
			
		||||
			RTLIL::SigSpec a = cell->getPort(ID(A));
 | 
			
		||||
			RTLIL::SigSpec y = cell->getPort(ID(Y));
 | 
			
		||||
			a.extend_u0(GetSize(y), is_signed);
 | 
			
		||||
			module->connect(y, a);
 | 
			
		||||
			delcells.push_back(cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -491,7 +491,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
 | 
			
		|||
	for (auto cell : delcells) {
 | 
			
		||||
		if (verbose)
 | 
			
		||||
			log_debug("  removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
 | 
			
		||||
					log_signal(cell->getPort("\\Y")), log_signal(cell->getPort("\\A")));
 | 
			
		||||
					log_signal(cell->getPort(ID(Y))), log_signal(cell->getPort(ID(A))));
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
	}
 | 
			
		||||
	if (!delcells.empty())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,10 +35,10 @@ void demorgan_worker(
 | 
			
		|||
	//TODO: Add support for reduce_xor
 | 
			
		||||
	//DeMorgan of XOR is either XOR (if even number of inputs) or XNOR (if odd number)
 | 
			
		||||
 | 
			
		||||
	if( (cell->type != "$reduce_and") && (cell->type != "$reduce_or") )
 | 
			
		||||
	if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) )
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	auto insig = sigmap(cell->getPort("\\A"));
 | 
			
		||||
	auto insig = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
	log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig));
 | 
			
		||||
	int num_inverted = 0;
 | 
			
		||||
	for(int i=0; i<GetSize(insig); i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +51,7 @@ void demorgan_worker(
 | 
			
		|||
		bool inverted = false;
 | 
			
		||||
		for(auto x : ports)
 | 
			
		||||
		{
 | 
			
		||||
			if(x.port == "\\Y" && x.cell->type == "$_NOT_")
 | 
			
		||||
			if(x.port == ID(Y) && x.cell->type == ID($_NOT_))
 | 
			
		||||
			{
 | 
			
		||||
				inverted = true;
 | 
			
		||||
				break;
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ void demorgan_worker(
 | 
			
		|||
		RTLIL::Cell* srcinv = NULL;
 | 
			
		||||
		for(auto x : ports)
 | 
			
		||||
		{
 | 
			
		||||
			if(x.port == "\\Y" && x.cell->type == "$_NOT_")
 | 
			
		||||
			if(x.port == ID(Y) && x.cell->type == ID($_NOT_))
 | 
			
		||||
			{
 | 
			
		||||
				srcinv = x.cell;
 | 
			
		||||
				break;
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ void demorgan_worker(
 | 
			
		|||
		//We ARE inverted - bypass it
 | 
			
		||||
		//Don't automatically delete the inverter since other stuff might still use it
 | 
			
		||||
		else
 | 
			
		||||
			insig[i] = srcinv->getPort("\\A");
 | 
			
		||||
			insig[i] = srcinv->getPort(ID(A));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//Cosmetic fixup: If our input is just a scrambled version of one bus, rearrange it
 | 
			
		||||
| 
						 | 
				
			
			@ -151,20 +151,20 @@ void demorgan_worker(
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	//Push the new input signal back to the reduction (after bypassing/adding inverters)
 | 
			
		||||
	cell->setPort("\\A", insig);
 | 
			
		||||
	cell->setPort(ID(A), insig);
 | 
			
		||||
 | 
			
		||||
	//Change the cell type
 | 
			
		||||
	if(cell->type == "$reduce_and")
 | 
			
		||||
		cell->type = "$reduce_or";
 | 
			
		||||
	else if(cell->type == "$reduce_or")
 | 
			
		||||
		cell->type = "$reduce_and";
 | 
			
		||||
	if(cell->type == ID($reduce_and))
 | 
			
		||||
		cell->type = ID($reduce_or);
 | 
			
		||||
	else if(cell->type == ID($reduce_or))
 | 
			
		||||
		cell->type = ID($reduce_and);
 | 
			
		||||
	//don't change XOR
 | 
			
		||||
 | 
			
		||||
	//Add an inverter to the output
 | 
			
		||||
	auto inverted_output = cell->getPort("\\Y");
 | 
			
		||||
	auto inverted_output = cell->getPort(ID(Y));
 | 
			
		||||
	auto uninverted_output = m->addWire(NEW_ID);
 | 
			
		||||
	m->addNot(NEW_ID, RTLIL::SigSpec(uninverted_output), inverted_output);
 | 
			
		||||
	cell->setPort("\\Y", uninverted_output);
 | 
			
		||||
	cell->setPort(ID(Y), uninverted_output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct OptDemorganPass : public Pass {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -40,9 +40,9 @@ struct OptLutWorker
 | 
			
		|||
 | 
			
		||||
	bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
 | 
			
		||||
	{
 | 
			
		||||
		SigSpec lut_input = sigmap(lut->getPort("\\A"));
 | 
			
		||||
		int lut_width = lut->getParam("\\WIDTH").as_int();
 | 
			
		||||
		Const lut_table = lut->getParam("\\LUT");
 | 
			
		||||
		SigSpec lut_input = sigmap(lut->getPort(ID(A)));
 | 
			
		||||
		int lut_width = lut->getParam(ID(WIDTH)).as_int();
 | 
			
		||||
		Const lut_table = lut->getParam(ID(LUT));
 | 
			
		||||
		int lut_index = 0;
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < lut_width; i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -99,16 +99,16 @@ struct OptLutWorker
 | 
			
		|||
		log("Discovering LUTs.\n");
 | 
			
		||||
		for (auto cell : module->selected_cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type == "$lut")
 | 
			
		||||
			if (cell->type == ID($lut))
 | 
			
		||||
			{
 | 
			
		||||
				if (cell->has_keep_attr())
 | 
			
		||||
					continue;
 | 
			
		||||
				SigBit lut_output = cell->getPort("\\Y");
 | 
			
		||||
				if (lut_output.wire->get_bool_attribute("\\keep"))
 | 
			
		||||
				SigBit lut_output = cell->getPort(ID(Y));
 | 
			
		||||
				if (lut_output.wire->get_bool_attribute(ID(keep)))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				int lut_width = cell->getParam("\\WIDTH").as_int();
 | 
			
		||||
				SigSpec lut_input = cell->getPort("\\A");
 | 
			
		||||
				int lut_width = cell->getParam(ID(WIDTH)).as_int();
 | 
			
		||||
				SigSpec lut_input = cell->getPort(ID(A));
 | 
			
		||||
				int lut_arity = 0;
 | 
			
		||||
 | 
			
		||||
				log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +205,7 @@ struct OptLutWorker
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			auto lut = worklist.pop();
 | 
			
		||||
			SigSpec lut_input = sigmap(lut->getPort("\\A"));
 | 
			
		||||
			SigSpec lut_input = sigmap(lut->getPort(ID(A)));
 | 
			
		||||
			pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut];
 | 
			
		||||
 | 
			
		||||
			vector<SigBit> lut_inputs;
 | 
			
		||||
| 
						 | 
				
			
			@ -267,7 +267,7 @@ struct OptLutWorker
 | 
			
		|||
					log_debug("  Not eliminating cell (connected to dedicated logic).\n");
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					SigSpec lut_output = lut->getPort("\\Y");
 | 
			
		||||
					SigSpec lut_output = lut->getPort(ID(Y));
 | 
			
		||||
					for (auto &port : index.query_ports(lut_output))
 | 
			
		||||
					{
 | 
			
		||||
						if (port.cell != lut && luts.count(port.cell))
 | 
			
		||||
| 
						 | 
				
			
			@ -303,13 +303,13 @@ struct OptLutWorker
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			auto lutA = worklist.pop();
 | 
			
		||||
			SigSpec lutA_input = sigmap(lutA->getPort("\\A"));
 | 
			
		||||
			SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]);
 | 
			
		||||
			int lutA_width = lutA->getParam("\\WIDTH").as_int();
 | 
			
		||||
			SigSpec lutA_input = sigmap(lutA->getPort(ID(A)));
 | 
			
		||||
			SigSpec lutA_output = sigmap(lutA->getPort(ID(Y))[0]);
 | 
			
		||||
			int lutA_width = lutA->getParam(ID(WIDTH)).as_int();
 | 
			
		||||
			int lutA_arity = luts_arity[lutA];
 | 
			
		||||
			pool<int> &lutA_dlogic_inputs = luts_dlogic_inputs[lutA];
 | 
			
		||||
 | 
			
		||||
			auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y"));
 | 
			
		||||
			auto lutA_output_ports = index.query_ports(lutA->getPort(ID(Y)));
 | 
			
		||||
			if (lutA_output_ports.size() != 2)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -321,15 +321,15 @@ struct OptLutWorker
 | 
			
		|||
				if (luts.count(port.cell))
 | 
			
		||||
				{
 | 
			
		||||
					auto lutB = port.cell;
 | 
			
		||||
					SigSpec lutB_input = sigmap(lutB->getPort("\\A"));
 | 
			
		||||
					SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]);
 | 
			
		||||
					int lutB_width = lutB->getParam("\\WIDTH").as_int();
 | 
			
		||||
					SigSpec lutB_input = sigmap(lutB->getPort(ID(A)));
 | 
			
		||||
					SigSpec lutB_output = sigmap(lutB->getPort(ID(Y))[0]);
 | 
			
		||||
					int lutB_width = lutB->getParam(ID(WIDTH)).as_int();
 | 
			
		||||
					int lutB_arity = luts_arity[lutB];
 | 
			
		||||
					pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[lutB];
 | 
			
		||||
 | 
			
		||||
					log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
 | 
			
		||||
 | 
			
		||||
					if (index.query_is_output(lutA->getPort("\\Y")))
 | 
			
		||||
					if (index.query_is_output(lutA->getPort(ID(Y))))
 | 
			
		||||
					{
 | 
			
		||||
						log_debug("  Not combining LUTs (cascade connection feeds module output).\n");
 | 
			
		||||
						continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +372,7 @@ struct OptLutWorker
 | 
			
		|||
						log_debug("  Not combining LUTs into cell A (combined LUT wider than cell A).\n");
 | 
			
		||||
					else if (lutB_dlogic_inputs.size() > 0)
 | 
			
		||||
						log_debug("  Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
 | 
			
		||||
					else if (lutB->get_bool_attribute("\\lut_keep"))
 | 
			
		||||
					else if (lutB->get_bool_attribute(ID(lut_keep)))
 | 
			
		||||
						log_debug("  Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
 | 
			
		||||
					else
 | 
			
		||||
						combine_mask |= COMBINE_A;
 | 
			
		||||
| 
						 | 
				
			
			@ -380,7 +380,7 @@ struct OptLutWorker
 | 
			
		|||
						log_debug("  Not combining LUTs into cell B (combined LUT wider than cell B).\n");
 | 
			
		||||
					else if (lutA_dlogic_inputs.size() > 0)
 | 
			
		||||
						log_debug("  Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
 | 
			
		||||
					else if (lutA->get_bool_attribute("\\lut_keep"))
 | 
			
		||||
					else if (lutA->get_bool_attribute(ID(lut_keep)))
 | 
			
		||||
						log_debug("  Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
 | 
			
		||||
					else
 | 
			
		||||
						combine_mask |= COMBINE_B;
 | 
			
		||||
| 
						 | 
				
			
			@ -440,8 +440,8 @@ struct OptLutWorker
 | 
			
		|||
							lutR_unique.insert(bit);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					int lutM_width = lutM->getParam("\\WIDTH").as_int();
 | 
			
		||||
					SigSpec lutM_input = sigmap(lutM->getPort("\\A"));
 | 
			
		||||
					int lutM_width = lutM->getParam(ID(WIDTH)).as_int();
 | 
			
		||||
					SigSpec lutM_input = sigmap(lutM->getPort(ID(A)));
 | 
			
		||||
					std::vector<SigBit> lutM_new_inputs;
 | 
			
		||||
					for (int i = 0; i < lutM_width; i++)
 | 
			
		||||
					{
 | 
			
		||||
| 
						 | 
				
			
			@ -482,13 +482,13 @@ struct OptLutWorker
 | 
			
		|||
						lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					log_debug("  Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str());
 | 
			
		||||
					log_debug("  Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str());
 | 
			
		||||
					log_debug("  Cell A truth table: %s.\n", lutA->getParam(ID(LUT)).as_string().c_str());
 | 
			
		||||
					log_debug("  Cell B truth table: %s.\n", lutB->getParam(ID(LUT)).as_string().c_str());
 | 
			
		||||
					log_debug("  Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
 | 
			
		||||
 | 
			
		||||
					lutM->setParam("\\LUT", lutM_new_table);
 | 
			
		||||
					lutM->setPort("\\A", lutM_new_inputs);
 | 
			
		||||
					lutM->setPort("\\Y", lutB_output);
 | 
			
		||||
					lutM->setParam(ID(LUT), lutM_new_table);
 | 
			
		||||
					lutM->setPort(ID(A), lutM_new_inputs);
 | 
			
		||||
					lutM->setPort(ID(Y), lutB_output);
 | 
			
		||||
 | 
			
		||||
					luts_arity[lutM] = lutM_arity;
 | 
			
		||||
					luts.erase(lutR);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,8 +47,8 @@ struct OptMergeWorker
 | 
			
		|||
 | 
			
		||||
	static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn)
 | 
			
		||||
	{
 | 
			
		||||
		SigSpec sig_s = conn.at("\\S");
 | 
			
		||||
		SigSpec sig_b = conn.at("\\B");
 | 
			
		||||
		SigSpec sig_s = conn.at(ID(S));
 | 
			
		||||
		SigSpec sig_b = conn.at(ID(B));
 | 
			
		||||
 | 
			
		||||
		int s_width = GetSize(sig_s);
 | 
			
		||||
		int width = GetSize(sig_b) / s_width;
 | 
			
		||||
| 
						 | 
				
			
			@ -59,12 +59,12 @@ struct OptMergeWorker
 | 
			
		|||
 | 
			
		||||
		std::sort(sb_pairs.begin(), sb_pairs.end());
 | 
			
		||||
 | 
			
		||||
		conn["\\S"] = SigSpec();
 | 
			
		||||
		conn["\\B"] = SigSpec();
 | 
			
		||||
		conn[ID(S)] = SigSpec();
 | 
			
		||||
		conn[ID(B)] = SigSpec();
 | 
			
		||||
 | 
			
		||||
		for (auto &it : sb_pairs) {
 | 
			
		||||
			conn["\\S"].append(it.first);
 | 
			
		||||
			conn["\\B"].append(it.second);
 | 
			
		||||
			conn[ID(S)].append(it.first);
 | 
			
		||||
			conn[ID(B)].append(it.second);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -94,32 +94,32 @@ struct OptMergeWorker
 | 
			
		|||
		const dict<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->connections();
 | 
			
		||||
		dict<RTLIL::IdString, RTLIL::SigSpec> alt_conn;
 | 
			
		||||
 | 
			
		||||
		if (cell->type.in("$and", "$or", "$xor", "$xnor", "$add", "$mul",
 | 
			
		||||
				"$logic_and", "$logic_or", "$_AND_", "$_OR_", "$_XOR_")) {
 | 
			
		||||
		if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul),
 | 
			
		||||
				ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) {
 | 
			
		||||
			alt_conn = *conn;
 | 
			
		||||
			if (assign_map(alt_conn.at("\\A")) < assign_map(alt_conn.at("\\B"))) {
 | 
			
		||||
				alt_conn["\\A"] = conn->at("\\B");
 | 
			
		||||
				alt_conn["\\B"] = conn->at("\\A");
 | 
			
		||||
			if (assign_map(alt_conn.at(ID(A))) < assign_map(alt_conn.at(ID(B)))) {
 | 
			
		||||
				alt_conn[ID(A)] = conn->at(ID(B));
 | 
			
		||||
				alt_conn[ID(B)] = conn->at(ID(A));
 | 
			
		||||
			}
 | 
			
		||||
			conn = &alt_conn;
 | 
			
		||||
		} else
 | 
			
		||||
		if (cell->type.in("$reduce_xor", "$reduce_xnor")) {
 | 
			
		||||
		if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) {
 | 
			
		||||
			alt_conn = *conn;
 | 
			
		||||
			assign_map.apply(alt_conn.at("\\A"));
 | 
			
		||||
			alt_conn.at("\\A").sort();
 | 
			
		||||
			assign_map.apply(alt_conn.at(ID(A)));
 | 
			
		||||
			alt_conn.at(ID(A)).sort();
 | 
			
		||||
			conn = &alt_conn;
 | 
			
		||||
		} else
 | 
			
		||||
		if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool")) {
 | 
			
		||||
		if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) {
 | 
			
		||||
			alt_conn = *conn;
 | 
			
		||||
			assign_map.apply(alt_conn.at("\\A"));
 | 
			
		||||
			alt_conn.at("\\A").sort_and_unify();
 | 
			
		||||
			assign_map.apply(alt_conn.at(ID(A)));
 | 
			
		||||
			alt_conn.at(ID(A)).sort_and_unify();
 | 
			
		||||
			conn = &alt_conn;
 | 
			
		||||
		} else
 | 
			
		||||
		if (cell->type == "$pmux") {
 | 
			
		||||
		if (cell->type == ID($pmux)) {
 | 
			
		||||
			alt_conn = *conn;
 | 
			
		||||
			assign_map.apply(alt_conn.at("\\A"));
 | 
			
		||||
			assign_map.apply(alt_conn.at("\\B"));
 | 
			
		||||
			assign_map.apply(alt_conn.at("\\S"));
 | 
			
		||||
			assign_map.apply(alt_conn.at(ID(A)));
 | 
			
		||||
			assign_map.apply(alt_conn.at(ID(B)));
 | 
			
		||||
			assign_map.apply(alt_conn.at(ID(S)));
 | 
			
		||||
			sort_pmux_conn(alt_conn);
 | 
			
		||||
			conn = &alt_conn;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -189,28 +189,28 @@ struct OptMergeWorker
 | 
			
		|||
				assign_map.apply(it.second);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell1->type == "$and" || cell1->type == "$or" || cell1->type == "$xor" || cell1->type == "$xnor" || cell1->type == "$add" || cell1->type == "$mul" ||
 | 
			
		||||
				cell1->type == "$logic_and" || cell1->type == "$logic_or" || cell1->type == "$_AND_" || cell1->type == "$_OR_" || cell1->type == "$_XOR_") {
 | 
			
		||||
			if (conn1.at("\\A") < conn1.at("\\B")) {
 | 
			
		||||
				RTLIL::SigSpec tmp = conn1["\\A"];
 | 
			
		||||
				conn1["\\A"] = conn1["\\B"];
 | 
			
		||||
				conn1["\\B"] = tmp;
 | 
			
		||||
		if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) ||
 | 
			
		||||
				cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) {
 | 
			
		||||
			if (conn1.at(ID(A)) < conn1.at(ID(B))) {
 | 
			
		||||
				RTLIL::SigSpec tmp = conn1[ID(A)];
 | 
			
		||||
				conn1[ID(A)] = conn1[ID(B)];
 | 
			
		||||
				conn1[ID(B)] = tmp;
 | 
			
		||||
			}
 | 
			
		||||
			if (conn2.at("\\A") < conn2.at("\\B")) {
 | 
			
		||||
				RTLIL::SigSpec tmp = conn2["\\A"];
 | 
			
		||||
				conn2["\\A"] = conn2["\\B"];
 | 
			
		||||
				conn2["\\B"] = tmp;
 | 
			
		||||
			if (conn2.at(ID(A)) < conn2.at(ID(B))) {
 | 
			
		||||
				RTLIL::SigSpec tmp = conn2[ID(A)];
 | 
			
		||||
				conn2[ID(A)] = conn2[ID(B)];
 | 
			
		||||
				conn2[ID(B)] = tmp;
 | 
			
		||||
			}
 | 
			
		||||
		} else
 | 
			
		||||
		if (cell1->type == "$reduce_xor" || cell1->type == "$reduce_xnor") {
 | 
			
		||||
			conn1["\\A"].sort();
 | 
			
		||||
			conn2["\\A"].sort();
 | 
			
		||||
		if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) {
 | 
			
		||||
			conn1[ID(A)].sort();
 | 
			
		||||
			conn2[ID(A)].sort();
 | 
			
		||||
		} else
 | 
			
		||||
		if (cell1->type == "$reduce_and" || cell1->type == "$reduce_or" || cell1->type == "$reduce_bool") {
 | 
			
		||||
			conn1["\\A"].sort_and_unify();
 | 
			
		||||
			conn2["\\A"].sort_and_unify();
 | 
			
		||||
		if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) {
 | 
			
		||||
			conn1[ID(A)].sort_and_unify();
 | 
			
		||||
			conn2[ID(A)].sort_and_unify();
 | 
			
		||||
		} else
 | 
			
		||||
		if (cell1->type == "$pmux") {
 | 
			
		||||
		if (cell1->type == ID($pmux)) {
 | 
			
		||||
			sort_pmux_conn(conn1);
 | 
			
		||||
			sort_pmux_conn(conn2);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -222,9 +222,9 @@ struct OptMergeWorker
 | 
			
		|||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell1->type.begins_with("$") && conn1.count("\\Q") != 0) {
 | 
			
		||||
			std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort("\\Q")).to_sigbit_vector();
 | 
			
		||||
			std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort("\\Q")).to_sigbit_vector();
 | 
			
		||||
		if (cell1->type.begins_with("$") && conn1.count(ID(Q)) != 0) {
 | 
			
		||||
			std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector();
 | 
			
		||||
			std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector();
 | 
			
		||||
			for (size_t i = 0; i < q1.size(); i++)
 | 
			
		||||
				if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) {
 | 
			
		||||
					lt = q1.at(i) < q2.at(i);
 | 
			
		||||
| 
						 | 
				
			
			@ -271,24 +271,24 @@ struct OptMergeWorker
 | 
			
		|||
		ct.setup_stdcells_mem();
 | 
			
		||||
 | 
			
		||||
		if (mode_nomux) {
 | 
			
		||||
			ct.cell_types.erase("$mux");
 | 
			
		||||
			ct.cell_types.erase("$pmux");
 | 
			
		||||
			ct.cell_types.erase(ID($mux));
 | 
			
		||||
			ct.cell_types.erase(ID($pmux));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ct.cell_types.erase("$tribuf");
 | 
			
		||||
		ct.cell_types.erase("$_TBUF_");
 | 
			
		||||
		ct.cell_types.erase("$anyseq");
 | 
			
		||||
		ct.cell_types.erase("$anyconst");
 | 
			
		||||
		ct.cell_types.erase("$allseq");
 | 
			
		||||
		ct.cell_types.erase("$allconst");
 | 
			
		||||
		ct.cell_types.erase(ID($tribuf));
 | 
			
		||||
		ct.cell_types.erase(ID($_TBUF_));
 | 
			
		||||
		ct.cell_types.erase(ID($anyseq));
 | 
			
		||||
		ct.cell_types.erase(ID($anyconst));
 | 
			
		||||
		ct.cell_types.erase(ID($allseq));
 | 
			
		||||
		ct.cell_types.erase(ID($allconst));
 | 
			
		||||
 | 
			
		||||
		log("Finding identical cells in module `%s'.\n", module->name.c_str());
 | 
			
		||||
		assign_map.set(module);
 | 
			
		||||
 | 
			
		||||
		dff_init_map.set(module);
 | 
			
		||||
		for (auto &it : module->wires_)
 | 
			
		||||
			if (it.second->attributes.count("\\init") != 0) {
 | 
			
		||||
				Const initval = it.second->attributes.at("\\init");
 | 
			
		||||
			if (it.second->attributes.count(ID(init)) != 0) {
 | 
			
		||||
				Const initval = it.second->attributes.at(ID(init));
 | 
			
		||||
				for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++)
 | 
			
		||||
					if (initval[i] == State::S0 || initval[i] == State::S1)
 | 
			
		||||
						dff_init_map.add(SigBit(it.second, i), initval[i]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,12 +84,12 @@ struct OptMuxtreeWorker
 | 
			
		|||
		//	.const_deactivated
 | 
			
		||||
		for (auto cell : module->cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type.in("$mux", "$pmux"))
 | 
			
		||||
			if (cell->type.in(ID($mux), ID($pmux)))
 | 
			
		||||
			{
 | 
			
		||||
				RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
				RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
				RTLIL::SigSpec sig_s = cell->getPort("\\S");
 | 
			
		||||
				RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
				RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
				RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
				RTLIL::SigSpec sig_s = cell->getPort(ID(S));
 | 
			
		||||
				RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
				muxinfo_t muxinfo;
 | 
			
		||||
				muxinfo.cell = cell;
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +137,7 @@ struct OptMuxtreeWorker
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for (auto wire : module->wires()) {
 | 
			
		||||
			if (wire->port_output || wire->get_bool_attribute("\\keep"))
 | 
			
		||||
			if (wire->port_output || wire->get_bool_attribute(ID(keep)))
 | 
			
		||||
				for (int idx : sig2bits(RTLIL::SigSpec(wire)))
 | 
			
		||||
					bit2info[idx].seen_non_mux = true;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -227,10 +227,10 @@ struct OptMuxtreeWorker
 | 
			
		|||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec sig_a = mi.cell->getPort("\\A");
 | 
			
		||||
			RTLIL::SigSpec sig_b = mi.cell->getPort("\\B");
 | 
			
		||||
			RTLIL::SigSpec sig_s = mi.cell->getPort("\\S");
 | 
			
		||||
			RTLIL::SigSpec sig_y = mi.cell->getPort("\\Y");
 | 
			
		||||
			RTLIL::SigSpec sig_a = mi.cell->getPort(ID(A));
 | 
			
		||||
			RTLIL::SigSpec sig_b = mi.cell->getPort(ID(B));
 | 
			
		||||
			RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S));
 | 
			
		||||
			RTLIL::SigSpec sig_y = mi.cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec sig_ports = sig_b;
 | 
			
		||||
			sig_ports.append(sig_a);
 | 
			
		||||
| 
						 | 
				
			
			@ -255,14 +255,14 @@ struct OptMuxtreeWorker
 | 
			
		|||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				mi.cell->setPort("\\A", new_sig_a);
 | 
			
		||||
				mi.cell->setPort("\\B", new_sig_b);
 | 
			
		||||
				mi.cell->setPort("\\S", new_sig_s);
 | 
			
		||||
				mi.cell->setPort(ID(A), new_sig_a);
 | 
			
		||||
				mi.cell->setPort(ID(B), new_sig_b);
 | 
			
		||||
				mi.cell->setPort(ID(S), new_sig_s);
 | 
			
		||||
				if (GetSize(new_sig_s) == 1) {
 | 
			
		||||
					mi.cell->type = "$mux";
 | 
			
		||||
					mi.cell->parameters.erase("\\S_WIDTH");
 | 
			
		||||
					mi.cell->type = ID($mux);
 | 
			
		||||
					mi.cell->parameters.erase(ID(S_WIDTH));
 | 
			
		||||
				} else {
 | 
			
		||||
					mi.cell->parameters["\\S_WIDTH"] = RTLIL::Const(GetSize(new_sig_s));
 | 
			
		||||
					mi.cell->parameters[ID(S_WIDTH)] = RTLIL::Const(GetSize(new_sig_s));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -364,9 +364,9 @@ struct OptMuxtreeWorker
 | 
			
		|||
 | 
			
		||||
		int width = 0;
 | 
			
		||||
		idict<int> ctrl_bits;
 | 
			
		||||
		if (portname == "\\B")
 | 
			
		||||
			width = GetSize(muxinfo.cell->getPort("\\A"));
 | 
			
		||||
		for (int bit : sig2bits(muxinfo.cell->getPort("\\S"), false))
 | 
			
		||||
		if (portname == ID(B))
 | 
			
		||||
			width = GetSize(muxinfo.cell->getPort(ID(A)));
 | 
			
		||||
		for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false))
 | 
			
		||||
			ctrl_bits(bit);
 | 
			
		||||
 | 
			
		||||
		int port_idx = 0, port_off = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -414,8 +414,8 @@ struct OptMuxtreeWorker
 | 
			
		|||
 | 
			
		||||
		// set input ports to constants if we find known active or inactive signals
 | 
			
		||||
		if (do_replace_known) {
 | 
			
		||||
			replace_known(knowledge, muxinfo, "\\A");
 | 
			
		||||
			replace_known(knowledge, muxinfo, "\\B");
 | 
			
		||||
			replace_known(knowledge, muxinfo, ID(A));
 | 
			
		||||
			replace_known(knowledge, muxinfo, ID(B));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// if there is a constant activated port we just use it
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,13 +43,13 @@ struct OptReduceWorker
 | 
			
		|||
			return;
 | 
			
		||||
		cells.erase(cell);
 | 
			
		||||
 | 
			
		||||
		RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
 | 
			
		||||
		RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
 | 
			
		||||
		pool<RTLIL::SigBit> new_sig_a_bits;
 | 
			
		||||
 | 
			
		||||
		for (auto &bit : sig_a.to_sigbit_set())
 | 
			
		||||
		{
 | 
			
		||||
			if (bit == RTLIL::State::S0) {
 | 
			
		||||
				if (cell->type == "$reduce_and") {
 | 
			
		||||
				if (cell->type == ID($reduce_and)) {
 | 
			
		||||
					new_sig_a_bits.clear();
 | 
			
		||||
					new_sig_a_bits.insert(RTLIL::State::S0);
 | 
			
		||||
					break;
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +57,7 @@ struct OptReduceWorker
 | 
			
		|||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (bit == RTLIL::State::S1) {
 | 
			
		||||
				if (cell->type == "$reduce_or") {
 | 
			
		||||
				if (cell->type == ID($reduce_or)) {
 | 
			
		||||
					new_sig_a_bits.clear();
 | 
			
		||||
					new_sig_a_bits.insert(RTLIL::State::S1);
 | 
			
		||||
					break;
 | 
			
		||||
| 
						 | 
				
			
			@ -73,8 +73,8 @@ struct OptReduceWorker
 | 
			
		|||
			for (auto child_cell : drivers.find(bit)) {
 | 
			
		||||
				if (child_cell->type == cell->type) {
 | 
			
		||||
					opt_reduce(cells, drivers, child_cell);
 | 
			
		||||
					if (child_cell->getPort("\\Y")[0] == bit) {
 | 
			
		||||
						pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort("\\A")).to_sigbit_pool();
 | 
			
		||||
					if (child_cell->getPort(ID(Y))[0] == bit) {
 | 
			
		||||
						pool<RTLIL::SigBit> child_sig_a_bits = assign_map(child_cell->getPort(ID(A))).to_sigbit_pool();
 | 
			
		||||
						new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end());
 | 
			
		||||
					} else
 | 
			
		||||
						new_sig_a_bits.insert(RTLIL::State::S0);
 | 
			
		||||
| 
						 | 
				
			
			@ -87,22 +87,22 @@ struct OptReduceWorker
 | 
			
		|||
 | 
			
		||||
		RTLIL::SigSpec new_sig_a(new_sig_a_bits);
 | 
			
		||||
 | 
			
		||||
		if (new_sig_a != sig_a || sig_a.size() != cell->getPort("\\A").size()) {
 | 
			
		||||
		if (new_sig_a != sig_a || sig_a.size() != cell->getPort(ID(A)).size()) {
 | 
			
		||||
			log("    New input vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_a));
 | 
			
		||||
			did_something = true;
 | 
			
		||||
			total_count++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cell->setPort("\\A", new_sig_a);
 | 
			
		||||
		cell->parameters["\\A_WIDTH"] = RTLIL::Const(new_sig_a.size());
 | 
			
		||||
		cell->setPort(ID(A), new_sig_a);
 | 
			
		||||
		cell->parameters[ID(A_WIDTH)] = RTLIL::Const(new_sig_a.size());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void opt_mux(RTLIL::Cell *cell)
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A"));
 | 
			
		||||
		RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B"));
 | 
			
		||||
		RTLIL::SigSpec sig_s = assign_map(cell->getPort("\\S"));
 | 
			
		||||
		RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A)));
 | 
			
		||||
		RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B)));
 | 
			
		||||
		RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID(S)));
 | 
			
		||||
 | 
			
		||||
		RTLIL::SigSpec new_sig_b, new_sig_s;
 | 
			
		||||
		pool<RTLIL::SigSpec> handled_sig;
 | 
			
		||||
| 
						 | 
				
			
			@ -123,15 +123,15 @@ struct OptReduceWorker
 | 
			
		|||
 | 
			
		||||
			if (this_s.size() > 1)
 | 
			
		||||
			{
 | 
			
		||||
				RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, "$reduce_or");
 | 
			
		||||
				reduce_or_cell->setPort("\\A", this_s);
 | 
			
		||||
				reduce_or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
 | 
			
		||||
				reduce_or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(this_s.size());
 | 
			
		||||
				reduce_or_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
 | 
			
		||||
				RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or));
 | 
			
		||||
				reduce_or_cell->setPort(ID(A), this_s);
 | 
			
		||||
				reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0);
 | 
			
		||||
				reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size());
 | 
			
		||||
				reduce_or_cell->parameters[ID(Y_WIDTH)] = RTLIL::Const(1);
 | 
			
		||||
 | 
			
		||||
				RTLIL::Wire *reduce_or_wire = module->addWire(NEW_ID);
 | 
			
		||||
				this_s = RTLIL::SigSpec(reduce_or_wire);
 | 
			
		||||
				reduce_or_cell->setPort("\\Y", this_s);
 | 
			
		||||
				reduce_or_cell->setPort(ID(Y), this_s);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			new_sig_b.append(this_b);
 | 
			
		||||
| 
						 | 
				
			
			@ -147,28 +147,28 @@ struct OptReduceWorker
 | 
			
		|||
 | 
			
		||||
		if (new_sig_s.size() == 0)
 | 
			
		||||
		{
 | 
			
		||||
			module->connect(RTLIL::SigSig(cell->getPort("\\Y"), cell->getPort("\\A")));
 | 
			
		||||
			assign_map.add(cell->getPort("\\Y"), cell->getPort("\\A"));
 | 
			
		||||
			module->connect(RTLIL::SigSig(cell->getPort(ID(Y)), cell->getPort(ID(A))));
 | 
			
		||||
			assign_map.add(cell->getPort(ID(Y)), cell->getPort(ID(A)));
 | 
			
		||||
			module->remove(cell);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			cell->setPort("\\B", new_sig_b);
 | 
			
		||||
			cell->setPort("\\S", new_sig_s);
 | 
			
		||||
			cell->setPort(ID(B), new_sig_b);
 | 
			
		||||
			cell->setPort(ID(S), new_sig_s);
 | 
			
		||||
			if (new_sig_s.size() > 1) {
 | 
			
		||||
				cell->parameters["\\S_WIDTH"] = RTLIL::Const(new_sig_s.size());
 | 
			
		||||
				cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size());
 | 
			
		||||
			} else {
 | 
			
		||||
				cell->type = "$mux";
 | 
			
		||||
				cell->parameters.erase("\\S_WIDTH");
 | 
			
		||||
				cell->type = ID($mux);
 | 
			
		||||
				cell->parameters.erase(ID(S_WIDTH));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void opt_mux_bits(RTLIL::Cell *cell)
 | 
			
		||||
	{
 | 
			
		||||
		std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort("\\A")).to_sigbit_vector();
 | 
			
		||||
		std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort("\\B")).to_sigbit_vector();
 | 
			
		||||
		std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort("\\Y")).to_sigbit_vector();
 | 
			
		||||
		std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort(ID(A))).to_sigbit_vector();
 | 
			
		||||
		std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort(ID(B))).to_sigbit_vector();
 | 
			
		||||
		std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort(ID(Y))).to_sigbit_vector();
 | 
			
		||||
 | 
			
		||||
		std::vector<RTLIL::SigBit> new_sig_y;
 | 
			
		||||
		RTLIL::SigSig old_sig_conn;
 | 
			
		||||
| 
						 | 
				
			
			@ -209,29 +209,29 @@ struct OptReduceWorker
 | 
			
		|||
		if (new_sig_y.size() != sig_y.size())
 | 
			
		||||
		{
 | 
			
		||||
			log("    Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
 | 
			
		||||
			log("      Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort("\\A")),
 | 
			
		||||
					log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y")));
 | 
			
		||||
			log("      Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))),
 | 
			
		||||
					log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y))));
 | 
			
		||||
 | 
			
		||||
			cell->setPort("\\A", RTLIL::SigSpec());
 | 
			
		||||
			cell->setPort(ID(A), RTLIL::SigSpec());
 | 
			
		||||
			for (auto &in_tuple : consolidated_in_tuples) {
 | 
			
		||||
				RTLIL::SigSpec new_a = cell->getPort("\\A");
 | 
			
		||||
				RTLIL::SigSpec new_a = cell->getPort(ID(A));
 | 
			
		||||
				new_a.append(in_tuple.at(0));
 | 
			
		||||
				cell->setPort("\\A", new_a);
 | 
			
		||||
				cell->setPort(ID(A), new_a);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cell->setPort("\\B", RTLIL::SigSpec());
 | 
			
		||||
			for (int i = 1; i <= cell->getPort("\\S").size(); i++)
 | 
			
		||||
			cell->setPort(ID(B), RTLIL::SigSpec());
 | 
			
		||||
			for (int i = 1; i <= cell->getPort(ID(S)).size(); i++)
 | 
			
		||||
				for (auto &in_tuple : consolidated_in_tuples) {
 | 
			
		||||
					RTLIL::SigSpec new_b = cell->getPort("\\B");
 | 
			
		||||
					RTLIL::SigSpec new_b = cell->getPort(ID(B));
 | 
			
		||||
					new_b.append(in_tuple.at(i));
 | 
			
		||||
					cell->setPort("\\B", new_b);
 | 
			
		||||
					cell->setPort(ID(B), new_b);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			cell->parameters["\\WIDTH"] = RTLIL::Const(new_sig_y.size());
 | 
			
		||||
			cell->setPort("\\Y", new_sig_y);
 | 
			
		||||
			cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size());
 | 
			
		||||
			cell->setPort(ID(Y), new_sig_y);
 | 
			
		||||
 | 
			
		||||
			log("      New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort("\\A")),
 | 
			
		||||
					log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y")));
 | 
			
		||||
			log("      New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))),
 | 
			
		||||
					log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y))));
 | 
			
		||||
			log("      New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
 | 
			
		||||
 | 
			
		||||
			module->connect(old_sig_conn);
 | 
			
		||||
| 
						 | 
				
			
			@ -253,15 +253,15 @@ struct OptReduceWorker
 | 
			
		|||
		SigPool mem_wren_sigs;
 | 
			
		||||
		for (auto &cell_it : module->cells_) {
 | 
			
		||||
			RTLIL::Cell *cell = cell_it.second;
 | 
			
		||||
			if (cell->type == "$mem")
 | 
			
		||||
				mem_wren_sigs.add(assign_map(cell->getPort("\\WR_EN")));
 | 
			
		||||
			if (cell->type == "$memwr")
 | 
			
		||||
				mem_wren_sigs.add(assign_map(cell->getPort("\\EN")));
 | 
			
		||||
			if (cell->type == ID($mem))
 | 
			
		||||
				mem_wren_sigs.add(assign_map(cell->getPort(ID(WR_EN))));
 | 
			
		||||
			if (cell->type == ID($memwr))
 | 
			
		||||
				mem_wren_sigs.add(assign_map(cell->getPort(ID(EN))));
 | 
			
		||||
		}
 | 
			
		||||
		for (auto &cell_it : module->cells_) {
 | 
			
		||||
			RTLIL::Cell *cell = cell_it.second;
 | 
			
		||||
			if (cell->type == "$dff" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Q"))))
 | 
			
		||||
				mem_wren_sigs.add(assign_map(cell->getPort("\\D")));
 | 
			
		||||
			if (cell->type == ID($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Q)))))
 | 
			
		||||
				mem_wren_sigs.add(assign_map(cell->getPort(ID(D))));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool keep_expanding_mem_wren_sigs = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -269,12 +269,12 @@ struct OptReduceWorker
 | 
			
		|||
			keep_expanding_mem_wren_sigs = false;
 | 
			
		||||
			for (auto &cell_it : module->cells_) {
 | 
			
		||||
				RTLIL::Cell *cell = cell_it.second;
 | 
			
		||||
				if (cell->type == "$mux" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Y")))) {
 | 
			
		||||
					if (!mem_wren_sigs.check_all(assign_map(cell->getPort("\\A"))) ||
 | 
			
		||||
							!mem_wren_sigs.check_all(assign_map(cell->getPort("\\B"))))
 | 
			
		||||
				if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y))))) {
 | 
			
		||||
					if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID(A)))) ||
 | 
			
		||||
							!mem_wren_sigs.check_all(assign_map(cell->getPort(ID(B)))))
 | 
			
		||||
						keep_expanding_mem_wren_sigs = true;
 | 
			
		||||
					mem_wren_sigs.add(assign_map(cell->getPort("\\A")));
 | 
			
		||||
					mem_wren_sigs.add(assign_map(cell->getPort("\\B")));
 | 
			
		||||
					mem_wren_sigs.add(assign_map(cell->getPort(ID(A))));
 | 
			
		||||
					mem_wren_sigs.add(assign_map(cell->getPort(ID(B))));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -286,7 +286,7 @@ struct OptReduceWorker
 | 
			
		|||
			// merge trees of reduce_* cells to one single cell and unify input vectors
 | 
			
		||||
			// (only handle reduce_and and reduce_or for various reasons)
 | 
			
		||||
 | 
			
		||||
			const char *type_list[] = { "$reduce_or", "$reduce_and" };
 | 
			
		||||
			const IdString type_list[] = { ID($reduce_or), ID($reduce_and) };
 | 
			
		||||
			for (auto type : type_list)
 | 
			
		||||
			{
 | 
			
		||||
				SigSet<RTLIL::Cell*> drivers;
 | 
			
		||||
| 
						 | 
				
			
			@ -296,7 +296,7 @@ struct OptReduceWorker
 | 
			
		|||
					RTLIL::Cell *cell = cell_it.second;
 | 
			
		||||
					if (cell->type != type || !design->selected(module, cell))
 | 
			
		||||
						continue;
 | 
			
		||||
					drivers.insert(assign_map(cell->getPort("\\Y")), cell);
 | 
			
		||||
					drivers.insert(assign_map(cell->getPort(ID(Y))), cell);
 | 
			
		||||
					cells.insert(cell);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -311,14 +311,14 @@ struct OptReduceWorker
 | 
			
		|||
			std::vector<RTLIL::Cell*> cells;
 | 
			
		||||
 | 
			
		||||
			for (auto &it : module->cells_)
 | 
			
		||||
				if ((it.second->type == "$mux" || it.second->type == "$pmux") && design->selected(module, it.second))
 | 
			
		||||
				if ((it.second->type == ID($mux) || it.second->type == ID($pmux)) && design->selected(module, it.second))
 | 
			
		||||
					cells.push_back(it.second);
 | 
			
		||||
 | 
			
		||||
			for (auto cell : cells)
 | 
			
		||||
			{
 | 
			
		||||
				// this optimization is to aggressive for most coarse-grain applications.
 | 
			
		||||
				// but we always want it for multiplexers driving write enable ports.
 | 
			
		||||
				if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort("\\Y"))))
 | 
			
		||||
				if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y)))))
 | 
			
		||||
					opt_mux_bits(cell);
 | 
			
		||||
 | 
			
		||||
				opt_mux(cell);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ void remove_init_attr(SigSpec sig)
 | 
			
		|||
	for (auto bit : assign_map(sig))
 | 
			
		||||
		if (init_attributes.count(bit))
 | 
			
		||||
			for (auto wbit : init_attributes.at(bit))
 | 
			
		||||
				wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx;
 | 
			
		||||
				wbit.wire->attributes.at(ID(init))[wbit.offset] = State::Sx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 | 
			
		||||
| 
						 | 
				
			
			@ -49,17 +49,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 | 
			
		|||
	SigSpec sig_set, sig_clr;
 | 
			
		||||
	State pol_set, pol_clr;
 | 
			
		||||
 | 
			
		||||
	if (cell->hasPort("\\S"))
 | 
			
		||||
		sig_set = cell->getPort("\\S");
 | 
			
		||||
	if (cell->hasPort(ID(S)))
 | 
			
		||||
		sig_set = cell->getPort(ID(S));
 | 
			
		||||
 | 
			
		||||
	if (cell->hasPort("\\R"))
 | 
			
		||||
		sig_clr = cell->getPort("\\R");
 | 
			
		||||
	if (cell->hasPort(ID(R)))
 | 
			
		||||
		sig_clr = cell->getPort(ID(R));
 | 
			
		||||
 | 
			
		||||
	if (cell->hasPort("\\SET"))
 | 
			
		||||
		sig_set = cell->getPort("\\SET");
 | 
			
		||||
	if (cell->hasPort(ID(SET)))
 | 
			
		||||
		sig_set = cell->getPort(ID(SET));
 | 
			
		||||
 | 
			
		||||
	if (cell->hasPort("\\CLR"))
 | 
			
		||||
		sig_clr = cell->getPort("\\CLR");
 | 
			
		||||
	if (cell->hasPort(ID(CLR)))
 | 
			
		||||
		sig_clr = cell->getPort(ID(CLR));
 | 
			
		||||
 | 
			
		||||
	log_assert(GetSize(sig_set) == GetSize(sig_clr));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,17 +71,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 | 
			
		|||
		pol_set = cell->type[12] == 'P' ? State::S1 : State::S0;
 | 
			
		||||
		pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0;
 | 
			
		||||
	} else
 | 
			
		||||
	if (cell->type.in("$dffsr", "$dlatchsr")) {
 | 
			
		||||
		pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0;
 | 
			
		||||
		pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0;
 | 
			
		||||
	if (cell->type.in(ID($dffsr), ID($dlatchsr))) {
 | 
			
		||||
		pol_set = cell->parameters[ID(SET_POLARITY)].as_bool() ? State::S1 : State::S0;
 | 
			
		||||
		pol_clr = cell->parameters[ID(CLR_POLARITY)].as_bool() ? State::S1 : State::S0;
 | 
			
		||||
	} else
 | 
			
		||||
		log_abort();
 | 
			
		||||
 | 
			
		||||
	State npol_set = pol_set == State::S0 ? State::S1 : State::S0;
 | 
			
		||||
	State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0;
 | 
			
		||||
 | 
			
		||||
	SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
	SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
	SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
	SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
	bool did_something = false;
 | 
			
		||||
	bool proper_sr = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -137,20 +137,20 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$dffsr", "$dlatchsr"))
 | 
			
		||||
	if (cell->type.in(ID($dffsr), ID($dlatchsr)))
 | 
			
		||||
	{
 | 
			
		||||
		cell->setParam("\\WIDTH", GetSize(sig_d));
 | 
			
		||||
		cell->setPort("\\SET", sig_set);
 | 
			
		||||
		cell->setPort("\\CLR", sig_clr);
 | 
			
		||||
		cell->setPort("\\D", sig_d);
 | 
			
		||||
		cell->setPort("\\Q", sig_q);
 | 
			
		||||
		cell->setParam(ID(WIDTH), GetSize(sig_d));
 | 
			
		||||
		cell->setPort(ID(SET), sig_set);
 | 
			
		||||
		cell->setPort(ID(CLR), sig_clr);
 | 
			
		||||
		cell->setPort(ID(D), sig_d);
 | 
			
		||||
		cell->setPort(ID(Q), sig_q);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		cell->setPort("\\S", sig_set);
 | 
			
		||||
		cell->setPort("\\R", sig_clr);
 | 
			
		||||
		cell->setPort("\\D", sig_d);
 | 
			
		||||
		cell->setPort("\\Q", sig_q);
 | 
			
		||||
		cell->setPort(ID(S), sig_set);
 | 
			
		||||
		cell->setPort(ID(R), sig_clr);
 | 
			
		||||
		cell->setPort(ID(D), sig_d);
 | 
			
		||||
		cell->setPort(ID(Q), sig_q);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (proper_sr)
 | 
			
		||||
| 
						 | 
				
			
			@ -159,36 +159,36 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 | 
			
		|||
	if (used_pol_set && used_pol_clr && pol_set != pol_clr)
 | 
			
		||||
		return did_something;
 | 
			
		||||
 | 
			
		||||
	if (cell->type == "$dlatchsr")
 | 
			
		||||
	if (cell->type == ID($dlatchsr))
 | 
			
		||||
		return did_something;
 | 
			
		||||
 | 
			
		||||
	State unified_pol = used_pol_set ? pol_set : pol_clr;
 | 
			
		||||
 | 
			
		||||
	if (cell->type == "$dffsr")
 | 
			
		||||
	if (cell->type == ID($dffsr))
 | 
			
		||||
	{
 | 
			
		||||
		if (hasreset)
 | 
			
		||||
		{
 | 
			
		||||
			log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod));
 | 
			
		||||
 | 
			
		||||
			cell->type = "$adff";
 | 
			
		||||
			cell->setParam("\\ARST_POLARITY", unified_pol);
 | 
			
		||||
			cell->setParam("\\ARST_VALUE", reset_val);
 | 
			
		||||
			cell->setPort("\\ARST", sig_reset);
 | 
			
		||||
			cell->type = ID($adff);
 | 
			
		||||
			cell->setParam(ID(ARST_POLARITY), unified_pol);
 | 
			
		||||
			cell->setParam(ID(ARST_VALUE), reset_val);
 | 
			
		||||
			cell->setPort(ID(ARST), sig_reset);
 | 
			
		||||
 | 
			
		||||
			cell->unsetParam("\\SET_POLARITY");
 | 
			
		||||
			cell->unsetParam("\\CLR_POLARITY");
 | 
			
		||||
			cell->unsetPort("\\SET");
 | 
			
		||||
			cell->unsetPort("\\CLR");
 | 
			
		||||
			cell->unsetParam(ID(SET_POLARITY));
 | 
			
		||||
			cell->unsetParam(ID(CLR_POLARITY));
 | 
			
		||||
			cell->unsetPort(ID(SET));
 | 
			
		||||
			cell->unsetPort(ID(CLR));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod));
 | 
			
		||||
 | 
			
		||||
			cell->type = "$dff";
 | 
			
		||||
			cell->unsetParam("\\SET_POLARITY");
 | 
			
		||||
			cell->unsetParam("\\CLR_POLARITY");
 | 
			
		||||
			cell->unsetPort("\\SET");
 | 
			
		||||
			cell->unsetPort("\\CLR");
 | 
			
		||||
			cell->type = ID($dff);
 | 
			
		||||
			cell->unsetParam(ID(SET_POLARITY));
 | 
			
		||||
			cell->unsetParam(ID(CLR_POLARITY));
 | 
			
		||||
			cell->unsetPort(ID(SET));
 | 
			
		||||
			cell->unsetPort(ID(CLR));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -208,8 +208,8 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell)
 | 
			
		|||
		log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod));
 | 
			
		||||
 | 
			
		||||
		cell->type = new_type;
 | 
			
		||||
		cell->unsetPort("\\S");
 | 
			
		||||
		cell->unsetPort("\\R");
 | 
			
		||||
		cell->unsetPort(ID(S));
 | 
			
		||||
		cell->unsetPort(ID(R));
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -222,18 +222,18 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
 | 
			
		|||
	SigSpec sig_e;
 | 
			
		||||
	State on_state, off_state;
 | 
			
		||||
 | 
			
		||||
	if (dlatch->type == "$dlatch") {
 | 
			
		||||
		sig_e = assign_map(dlatch->getPort("\\EN"));
 | 
			
		||||
		on_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S1 : State::S0;
 | 
			
		||||
		off_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S0 : State::S1;
 | 
			
		||||
	if (dlatch->type == ID($dlatch)) {
 | 
			
		||||
		sig_e = assign_map(dlatch->getPort(ID(EN)));
 | 
			
		||||
		on_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S1 : State::S0;
 | 
			
		||||
		off_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S0 : State::S1;
 | 
			
		||||
	} else
 | 
			
		||||
	if (dlatch->type == "$_DLATCH_P_") {
 | 
			
		||||
		sig_e = assign_map(dlatch->getPort("\\E"));
 | 
			
		||||
	if (dlatch->type == ID($_DLATCH_P_)) {
 | 
			
		||||
		sig_e = assign_map(dlatch->getPort(ID(E)));
 | 
			
		||||
		on_state = State::S1;
 | 
			
		||||
		off_state = State::S0;
 | 
			
		||||
	} else
 | 
			
		||||
	if (dlatch->type == "$_DLATCH_N_") {
 | 
			
		||||
		sig_e = assign_map(dlatch->getPort("\\E"));
 | 
			
		||||
	if (dlatch->type == ID($_DLATCH_N_)) {
 | 
			
		||||
		sig_e = assign_map(dlatch->getPort(ID(E)));
 | 
			
		||||
		on_state = State::S0;
 | 
			
		||||
		off_state = State::S1;
 | 
			
		||||
	} else
 | 
			
		||||
| 
						 | 
				
			
			@ -242,15 +242,15 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
 | 
			
		|||
	if (sig_e == off_state)
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::Const val_init;
 | 
			
		||||
		for (auto bit : dff_init_map(dlatch->getPort("\\Q")))
 | 
			
		||||
		for (auto bit : dff_init_map(dlatch->getPort(ID(Q))))
 | 
			
		||||
			val_init.bits.push_back(bit.wire == NULL ? bit.data : State::Sx);
 | 
			
		||||
		mod->connect(dlatch->getPort("\\Q"), val_init);
 | 
			
		||||
		mod->connect(dlatch->getPort(ID(Q)), val_init);
 | 
			
		||||
		goto delete_dlatch;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sig_e == on_state)
 | 
			
		||||
	{
 | 
			
		||||
		mod->connect(dlatch->getPort("\\Q"), dlatch->getPort("\\D"));
 | 
			
		||||
		mod->connect(dlatch->getPort(ID(Q)), dlatch->getPort(ID(D)));
 | 
			
		||||
		goto delete_dlatch;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -258,7 +258,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
 | 
			
		|||
 | 
			
		||||
delete_dlatch:
 | 
			
		||||
	log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod));
 | 
			
		||||
	remove_init_attr(dlatch->getPort("\\Q"));
 | 
			
		||||
	remove_init_attr(dlatch->getPort(ID(Q)));
 | 
			
		||||
	mod->remove(dlatch);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -268,24 +268,24 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 | 
			
		|||
	RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e;
 | 
			
		||||
	RTLIL::Const val_cp, val_rp, val_rv, val_ep;
 | 
			
		||||
 | 
			
		||||
	if (dff->type == "$_FF_") {
 | 
			
		||||
		sig_d = dff->getPort("\\D");
 | 
			
		||||
		sig_q = dff->getPort("\\Q");
 | 
			
		||||
	if (dff->type == ID($_FF_)) {
 | 
			
		||||
		sig_d = dff->getPort(ID(D));
 | 
			
		||||
		sig_q = dff->getPort(ID(Q));
 | 
			
		||||
	}
 | 
			
		||||
	else if (dff->type == "$_DFF_N_" || dff->type == "$_DFF_P_") {
 | 
			
		||||
		sig_d = dff->getPort("\\D");
 | 
			
		||||
		sig_q = dff->getPort("\\Q");
 | 
			
		||||
		sig_c = dff->getPort("\\C");
 | 
			
		||||
		val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1);
 | 
			
		||||
	else if (dff->type == ID($_DFF_N_) || dff->type == ID($_DFF_P_)) {
 | 
			
		||||
		sig_d = dff->getPort(ID(D));
 | 
			
		||||
		sig_q = dff->getPort(ID(Q));
 | 
			
		||||
		sig_c = dff->getPort(ID(C));
 | 
			
		||||
		val_cp = RTLIL::Const(dff->type == ID($_DFF_P_), 1);
 | 
			
		||||
	}
 | 
			
		||||
	else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 &&
 | 
			
		||||
			(dff->type[6] == 'N' || dff->type[6] == 'P') &&
 | 
			
		||||
			(dff->type[7] == 'N' || dff->type[7] == 'P') &&
 | 
			
		||||
			(dff->type[8] == '0' || dff->type[8] == '1')) {
 | 
			
		||||
		sig_d = dff->getPort("\\D");
 | 
			
		||||
		sig_q = dff->getPort("\\Q");
 | 
			
		||||
		sig_c = dff->getPort("\\C");
 | 
			
		||||
		sig_r = dff->getPort("\\R");
 | 
			
		||||
		sig_d = dff->getPort(ID(D));
 | 
			
		||||
		sig_q = dff->getPort(ID(Q));
 | 
			
		||||
		sig_c = dff->getPort(ID(C));
 | 
			
		||||
		sig_r = dff->getPort(ID(R));
 | 
			
		||||
		val_cp = RTLIL::Const(dff->type[6] == 'P', 1);
 | 
			
		||||
		val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
 | 
			
		||||
		val_rv = RTLIL::Const(dff->type[8] == '1', 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -293,39 +293,39 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 | 
			
		|||
	else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 &&
 | 
			
		||||
			(dff->type[7] == 'N' || dff->type[7] == 'P') &&
 | 
			
		||||
			(dff->type[8] == 'N' || dff->type[8] == 'P')) {
 | 
			
		||||
		sig_d = dff->getPort("\\D");
 | 
			
		||||
		sig_q = dff->getPort("\\Q");
 | 
			
		||||
		sig_c = dff->getPort("\\C");
 | 
			
		||||
		sig_e = dff->getPort("\\E");
 | 
			
		||||
		sig_d = dff->getPort(ID(D));
 | 
			
		||||
		sig_q = dff->getPort(ID(Q));
 | 
			
		||||
		sig_c = dff->getPort(ID(C));
 | 
			
		||||
		sig_e = dff->getPort(ID(E));
 | 
			
		||||
		val_cp = RTLIL::Const(dff->type[7] == 'P', 1);
 | 
			
		||||
		val_ep = RTLIL::Const(dff->type[8] == 'P', 1);
 | 
			
		||||
	}
 | 
			
		||||
	else if (dff->type == "$ff") {
 | 
			
		||||
		sig_d = dff->getPort("\\D");
 | 
			
		||||
		sig_q = dff->getPort("\\Q");
 | 
			
		||||
	else if (dff->type == ID($ff)) {
 | 
			
		||||
		sig_d = dff->getPort(ID(D));
 | 
			
		||||
		sig_q = dff->getPort(ID(Q));
 | 
			
		||||
	}
 | 
			
		||||
	else if (dff->type == "$dff") {
 | 
			
		||||
		sig_d = dff->getPort("\\D");
 | 
			
		||||
		sig_q = dff->getPort("\\Q");
 | 
			
		||||
		sig_c = dff->getPort("\\CLK");
 | 
			
		||||
		val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
 | 
			
		||||
	else if (dff->type == ID($dff)) {
 | 
			
		||||
		sig_d = dff->getPort(ID(D));
 | 
			
		||||
		sig_q = dff->getPort(ID(Q));
 | 
			
		||||
		sig_c = dff->getPort(ID(CLK));
 | 
			
		||||
		val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
 | 
			
		||||
	}
 | 
			
		||||
	else if (dff->type == "$dffe") {
 | 
			
		||||
		sig_e = dff->getPort("\\EN");
 | 
			
		||||
		sig_d = dff->getPort("\\D");
 | 
			
		||||
		sig_q = dff->getPort("\\Q");
 | 
			
		||||
		sig_c = dff->getPort("\\CLK");
 | 
			
		||||
		val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
 | 
			
		||||
		val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1);
 | 
			
		||||
	else if (dff->type == ID($dffe)) {
 | 
			
		||||
		sig_e = dff->getPort(ID(EN));
 | 
			
		||||
		sig_d = dff->getPort(ID(D));
 | 
			
		||||
		sig_q = dff->getPort(ID(Q));
 | 
			
		||||
		sig_c = dff->getPort(ID(CLK));
 | 
			
		||||
		val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
 | 
			
		||||
		val_ep = RTLIL::Const(dff->parameters[ID(EN_POLARITY)].as_bool(), 1);
 | 
			
		||||
	}
 | 
			
		||||
	else if (dff->type == "$adff") {
 | 
			
		||||
		sig_d = dff->getPort("\\D");
 | 
			
		||||
		sig_q = dff->getPort("\\Q");
 | 
			
		||||
		sig_c = dff->getPort("\\CLK");
 | 
			
		||||
		sig_r = dff->getPort("\\ARST");
 | 
			
		||||
		val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
 | 
			
		||||
		val_rp = RTLIL::Const(dff->parameters["\\ARST_POLARITY"].as_bool(), 1);
 | 
			
		||||
		val_rv = dff->parameters["\\ARST_VALUE"];
 | 
			
		||||
	else if (dff->type == ID($adff)) {
 | 
			
		||||
		sig_d = dff->getPort(ID(D));
 | 
			
		||||
		sig_q = dff->getPort(ID(Q));
 | 
			
		||||
		sig_c = dff->getPort(ID(CLK));
 | 
			
		||||
		sig_r = dff->getPort(ID(ARST));
 | 
			
		||||
		val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1);
 | 
			
		||||
		val_rp = RTLIL::Const(dff->parameters[ID(ARST_POLARITY)].as_bool(), 1);
 | 
			
		||||
		val_rv = dff->parameters[ID(ARST_VALUE)];
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		log_abort();
 | 
			
		||||
| 
						 | 
				
			
			@ -343,12 +343,12 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 | 
			
		|||
		val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) {
 | 
			
		||||
	if (dff->type.in(ID($ff), ID($dff)) && mux_drivers.has(sig_d)) {
 | 
			
		||||
		std::set<RTLIL::Cell*> muxes;
 | 
			
		||||
		mux_drivers.find(sig_d, muxes);
 | 
			
		||||
		for (auto mux : muxes) {
 | 
			
		||||
			RTLIL::SigSpec sig_a = assign_map(mux->getPort("\\A"));
 | 
			
		||||
			RTLIL::SigSpec sig_b = assign_map(mux->getPort("\\B"));
 | 
			
		||||
			RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID(A)));
 | 
			
		||||
			RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID(B)));
 | 
			
		||||
			if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) {
 | 
			
		||||
				mod->connect(sig_q, sig_b);
 | 
			
		||||
				goto delete_dff;
 | 
			
		||||
| 
						 | 
				
			
			@ -420,17 +420,17 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 | 
			
		|||
 | 
			
		||||
		log("Removing unused reset from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
 | 
			
		||||
 | 
			
		||||
		if (dff->type == "$adff") {
 | 
			
		||||
			dff->type = "$dff";
 | 
			
		||||
			dff->unsetPort("\\ARST");
 | 
			
		||||
			dff->unsetParam("\\ARST_POLARITY");
 | 
			
		||||
			dff->unsetParam("\\ARST_VALUE");
 | 
			
		||||
		if (dff->type == ID($adff)) {
 | 
			
		||||
			dff->type = ID($dff);
 | 
			
		||||
			dff->unsetPort(ID(ARST));
 | 
			
		||||
			dff->unsetParam(ID(ARST_POLARITY));
 | 
			
		||||
			dff->unsetParam(ID(ARST_VALUE));
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_assert(dff->type.begins_with("$_DFF_"));
 | 
			
		||||
		dff->type = stringf("$_DFF_%c_", + dff->type[6]);
 | 
			
		||||
		dff->unsetPort("\\R");
 | 
			
		||||
		dff->unsetPort(ID(R));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If enable signal is present, and is fully constant
 | 
			
		||||
| 
						 | 
				
			
			@ -445,16 +445,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 | 
			
		|||
 | 
			
		||||
		log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
 | 
			
		||||
 | 
			
		||||
		if (dff->type == "$dffe") {
 | 
			
		||||
			dff->type = "$dff";
 | 
			
		||||
			dff->unsetPort("\\EN");
 | 
			
		||||
			dff->unsetParam("\\EN_POLARITY");
 | 
			
		||||
		if (dff->type == ID($dffe)) {
 | 
			
		||||
			dff->type = ID($dff);
 | 
			
		||||
			dff->unsetPort(ID(EN));
 | 
			
		||||
			dff->unsetParam(ID(EN_POLARITY));
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_assert(dff->type.begins_with("$_DFFE_"));
 | 
			
		||||
		dff->type = stringf("$_DFF_%c_", + dff->type[7]);
 | 
			
		||||
		dff->unsetPort("\\E");
 | 
			
		||||
		dff->unsetPort(ID(E));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (sat && has_init && (!sig_r.size() || val_init == val_rv))
 | 
			
		||||
| 
						 | 
				
			
			@ -509,9 +509,9 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 | 
			
		|||
				log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0,
 | 
			
		||||
						position, log_id(dff), log_id(dff->type), log_id(mod));
 | 
			
		||||
 | 
			
		||||
				SigSpec tmp = dff->getPort("\\D");
 | 
			
		||||
				SigSpec tmp = dff->getPort(ID(D));
 | 
			
		||||
				tmp[position] = sigbit_init_val;
 | 
			
		||||
				dff->setPort("\\D", tmp);
 | 
			
		||||
				dff->setPort(ID(D), tmp);
 | 
			
		||||
 | 
			
		||||
				removed_sigbits = true;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -528,7 +528,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
 | 
			
		|||
 | 
			
		||||
delete_dff:
 | 
			
		||||
	log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
 | 
			
		||||
	remove_init_attr(dff->getPort("\\Q"));
 | 
			
		||||
	remove_init_attr(dff->getPort(ID(Q)));
 | 
			
		||||
	mod->remove(dff);
 | 
			
		||||
 | 
			
		||||
	for (auto &entry : bit2driver)
 | 
			
		||||
| 
						 | 
				
			
			@ -588,8 +588,8 @@ struct OptRmdffPass : public Pass {
 | 
			
		|||
 | 
			
		||||
			for (auto wire : module->wires())
 | 
			
		||||
			{
 | 
			
		||||
				if (wire->attributes.count("\\init") != 0) {
 | 
			
		||||
					Const initval = wire->attributes.at("\\init");
 | 
			
		||||
				if (wire->attributes.count(ID(init)) != 0) {
 | 
			
		||||
					Const initval = wire->attributes.at(ID(init));
 | 
			
		||||
					for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++)
 | 
			
		||||
						if (initval[i] == State::S0 || initval[i] == State::S1)
 | 
			
		||||
							dff_init_map.add(SigBit(wire, i), initval[i]);
 | 
			
		||||
| 
						 | 
				
			
			@ -624,29 +624,29 @@ struct OptRmdffPass : public Pass {
 | 
			
		|||
						}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (cell->type.in("$mux", "$pmux")) {
 | 
			
		||||
					if (cell->getPort("\\A").size() == cell->getPort("\\B").size())
 | 
			
		||||
						mux_drivers.insert(assign_map(cell->getPort("\\Y")), cell);
 | 
			
		||||
				if (cell->type.in(ID($mux), ID($pmux))) {
 | 
			
		||||
					if (cell->getPort(ID(A)).size() == cell->getPort(ID(B)).size())
 | 
			
		||||
						mux_drivers.insert(assign_map(cell->getPort(ID(Y))), cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (!design->selected(module, cell))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_",
 | 
			
		||||
						"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", "$dffsr",
 | 
			
		||||
						"$_DLATCHSR_NNN_", "$_DLATCHSR_NNP_", "$_DLATCHSR_NPN_", "$_DLATCHSR_NPP_",
 | 
			
		||||
						"$_DLATCHSR_PNN_", "$_DLATCHSR_PNP_", "$_DLATCHSR_PPN_", "$_DLATCHSR_PPP_", "$dlatchsr"))
 | 
			
		||||
				if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
 | 
			
		||||
						ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), ID($dffsr),
 | 
			
		||||
						ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
 | 
			
		||||
						ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), ID($dlatchsr)))
 | 
			
		||||
					dffsr_list.push_back(cell->name);
 | 
			
		||||
 | 
			
		||||
				if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_",
 | 
			
		||||
						"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
 | 
			
		||||
						"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_",
 | 
			
		||||
						"$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_",
 | 
			
		||||
						"$ff", "$dff", "$dffe", "$adff"))
 | 
			
		||||
				if (cell->type.in(ID($_FF_), ID($_DFF_N_), ID($_DFF_P_),
 | 
			
		||||
						ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
 | 
			
		||||
						ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
 | 
			
		||||
						ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
 | 
			
		||||
						ID($ff), ID($dff), ID($dffe), ID($adff)))
 | 
			
		||||
					dff_list.push_back(cell->name);
 | 
			
		||||
 | 
			
		||||
				if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_"))
 | 
			
		||||
				if (cell->type.in(ID($dlatch), ID($_DLATCH_P_), ID($_DLATCH_N_)))
 | 
			
		||||
					dlatch_list.push_back(cell->name);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ struct OnehotDatabase
 | 
			
		|||
 | 
			
		||||
		for (auto wire : module->wires())
 | 
			
		||||
		{
 | 
			
		||||
			auto it = wire->attributes.find("\\init");
 | 
			
		||||
			auto it = wire->attributes.find(ID(init));
 | 
			
		||||
			if (it == wire->attributes.end())
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,19 +63,19 @@ struct OnehotDatabase
 | 
			
		|||
			vector<SigSpec> inputs;
 | 
			
		||||
			SigSpec output;
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$adff", "$dff", "$dffe", "$dlatch", "$ff"))
 | 
			
		||||
			if (cell->type.in(ID($adff), ID($dff), ID($dffe), ID($dlatch), ID($ff)))
 | 
			
		||||
			{
 | 
			
		||||
				output = cell->getPort("\\Q");
 | 
			
		||||
				if (cell->type == "$adff")
 | 
			
		||||
					inputs.push_back(cell->getParam("\\ARST_VALUE"));
 | 
			
		||||
				inputs.push_back(cell->getPort("\\D"));
 | 
			
		||||
				output = cell->getPort(ID(Q));
 | 
			
		||||
				if (cell->type == ID($adff))
 | 
			
		||||
					inputs.push_back(cell->getParam(ID(ARST_VALUE)));
 | 
			
		||||
				inputs.push_back(cell->getPort(ID(D)));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$mux", "$pmux"))
 | 
			
		||||
			if (cell->type.in(ID($mux), ID($pmux)))
 | 
			
		||||
			{
 | 
			
		||||
				output = cell->getPort("\\Y");
 | 
			
		||||
				inputs.push_back(cell->getPort("\\A"));
 | 
			
		||||
				SigSpec B = cell->getPort("\\B");
 | 
			
		||||
				output = cell->getPort(ID(Y));
 | 
			
		||||
				inputs.push_back(cell->getPort(ID(A)));
 | 
			
		||||
				SigSpec B = cell->getPort(ID(B));
 | 
			
		||||
				for (int i = 0; i < GetSize(B); i += GetSize(output))
 | 
			
		||||
					inputs.push_back(B.extract(i, GetSize(output)));
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -292,23 +292,23 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
 | 
			
		||||
			for (auto cell : module->cells())
 | 
			
		||||
			{
 | 
			
		||||
				if (cell->type == "$eq")
 | 
			
		||||
				if (cell->type == ID($eq))
 | 
			
		||||
				{
 | 
			
		||||
					dict<SigBit, State> bits;
 | 
			
		||||
 | 
			
		||||
					SigSpec A = sigmap(cell->getPort("\\A"));
 | 
			
		||||
					SigSpec B = sigmap(cell->getPort("\\B"));
 | 
			
		||||
					SigSpec A = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
					SigSpec B = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
 | 
			
		||||
					int a_width = cell->getParam("\\A_WIDTH").as_int();
 | 
			
		||||
					int b_width = cell->getParam("\\B_WIDTH").as_int();
 | 
			
		||||
					int a_width = cell->getParam(ID(A_WIDTH)).as_int();
 | 
			
		||||
					int b_width = cell->getParam(ID(B_WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
					if (a_width < b_width) {
 | 
			
		||||
						bool a_signed = cell->getParam("\\A_SIGNED").as_int();
 | 
			
		||||
						bool a_signed = cell->getParam(ID(A_SIGNED)).as_int();
 | 
			
		||||
						A.extend_u0(b_width, a_signed);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (b_width < a_width) {
 | 
			
		||||
						bool b_signed = cell->getParam("\\B_SIGNED").as_int();
 | 
			
		||||
						bool b_signed = cell->getParam(ID(B_SIGNED)).as_int();
 | 
			
		||||
						B.extend_u0(a_width, b_signed);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -335,15 +335,15 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
						entry.second.bits.push_back(it.second);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					eqdb[sigmap(cell->getPort("\\Y")[0])] = entry;
 | 
			
		||||
					eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry;
 | 
			
		||||
					goto next_cell;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (cell->type == "$logic_not")
 | 
			
		||||
				if (cell->type == ID($logic_not))
 | 
			
		||||
				{
 | 
			
		||||
					dict<SigBit, State> bits;
 | 
			
		||||
 | 
			
		||||
					SigSpec A = sigmap(cell->getPort("\\A"));
 | 
			
		||||
					SigSpec A = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
 | 
			
		||||
					for (int i = 0; i < GetSize(A); i++)
 | 
			
		||||
						bits[A[i]] = State::S0;
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +356,7 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
						entry.second.bits.push_back(it.second);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					eqdb[sigmap(cell->getPort("\\Y")[0])] = entry;
 | 
			
		||||
					eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry;
 | 
			
		||||
					goto next_cell;
 | 
			
		||||
				}
 | 
			
		||||
		next_cell:;
 | 
			
		||||
| 
						 | 
				
			
			@ -364,11 +364,11 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
 | 
			
		||||
			for (auto cell : module->selected_cells())
 | 
			
		||||
			{
 | 
			
		||||
				if (cell->type != "$pmux")
 | 
			
		||||
				if (cell->type != ID($pmux))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				string src = cell->get_src_attribute();
 | 
			
		||||
				int width = cell->getParam("\\WIDTH").as_int();
 | 
			
		||||
				int width = cell->getParam(ID(WIDTH)).as_int();
 | 
			
		||||
				int width_bits = ceil_log2(width);
 | 
			
		||||
				int extwidth = width;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -377,9 +377,9 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
 | 
			
		||||
				dict<SigSpec, pool<int>> seldb;
 | 
			
		||||
 | 
			
		||||
				SigSpec A = cell->getPort("\\A");
 | 
			
		||||
				SigSpec B = cell->getPort("\\B");
 | 
			
		||||
				SigSpec S = sigmap(cell->getPort("\\S"));
 | 
			
		||||
				SigSpec A = cell->getPort(ID(A));
 | 
			
		||||
				SigSpec B = cell->getPort(ID(B));
 | 
			
		||||
				SigSpec S = sigmap(cell->getPort(ID(S)));
 | 
			
		||||
				for (int i = 0; i < GetSize(S); i++)
 | 
			
		||||
				{
 | 
			
		||||
					if (!eqdb.count(S[i]))
 | 
			
		||||
| 
						 | 
				
			
			@ -400,8 +400,8 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
					log("  data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				SigSpec updated_S = cell->getPort("\\S");
 | 
			
		||||
				SigSpec updated_B = cell->getPort("\\B");
 | 
			
		||||
				SigSpec updated_S = cell->getPort(ID(S));
 | 
			
		||||
				SigSpec updated_B = cell->getPort(ID(B));
 | 
			
		||||
 | 
			
		||||
				while (!seldb.empty())
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			@ -727,9 +727,9 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
				// update $pmux cell
 | 
			
		||||
				cell->setPort("\\S", updated_S);
 | 
			
		||||
				cell->setPort("\\B", updated_B);
 | 
			
		||||
				cell->setParam("\\S_WIDTH", GetSize(updated_S));
 | 
			
		||||
				cell->setPort(ID(S), updated_S);
 | 
			
		||||
				cell->setPort(ID(B), updated_B);
 | 
			
		||||
				cell->setParam(ID(S_WIDTH), GetSize(updated_S));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -779,22 +779,22 @@ struct OnehotPass : public Pass {
 | 
			
		|||
 | 
			
		||||
			for (auto cell : module->selected_cells())
 | 
			
		||||
			{
 | 
			
		||||
				if (cell->type != "$eq")
 | 
			
		||||
				if (cell->type != ID($eq))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				SigSpec A = sigmap(cell->getPort("\\A"));
 | 
			
		||||
				SigSpec B = sigmap(cell->getPort("\\B"));
 | 
			
		||||
				SigSpec A = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
				SigSpec B = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
 | 
			
		||||
				int a_width = cell->getParam("\\A_WIDTH").as_int();
 | 
			
		||||
				int b_width = cell->getParam("\\B_WIDTH").as_int();
 | 
			
		||||
				int a_width = cell->getParam(ID(A_WIDTH)).as_int();
 | 
			
		||||
				int b_width = cell->getParam(ID(B_WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
				if (a_width < b_width) {
 | 
			
		||||
					bool a_signed = cell->getParam("\\A_SIGNED").as_int();
 | 
			
		||||
					bool a_signed = cell->getParam(ID(A_SIGNED)).as_int();
 | 
			
		||||
					A.extend_u0(b_width, a_signed);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (b_width < a_width) {
 | 
			
		||||
					bool b_signed = cell->getParam("\\B_SIGNED").as_int();
 | 
			
		||||
					bool b_signed = cell->getParam(ID(B_SIGNED)).as_int();
 | 
			
		||||
					B.extend_u0(a_width, b_signed);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -830,7 +830,7 @@ struct OnehotPass : public Pass {
 | 
			
		|||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				SigSpec Y = cell->getPort("\\Y");
 | 
			
		||||
				SigSpec Y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
				if (not_onehot)
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,8 +89,8 @@ struct ShareWorker
 | 
			
		|||
			queue_bits.clear();
 | 
			
		||||
 | 
			
		||||
			for (auto &pbit : portbits) {
 | 
			
		||||
				if (pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") {
 | 
			
		||||
					pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort("\\S")).to_sigbit_pool();
 | 
			
		||||
				if (pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) {
 | 
			
		||||
					pool<RTLIL::SigBit> bits = modwalker.sigmap(pbit.cell->getPort(ID(S))).to_sigbit_pool();
 | 
			
		||||
					terminal_bits.insert(bits.begin(), bits.end());
 | 
			
		||||
					queue_bits.insert(bits.begin(), bits.end());
 | 
			
		||||
					visited_cells.insert(pbit.cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +128,7 @@ struct ShareWorker
 | 
			
		|||
	static int bits_macc(RTLIL::Cell *c)
 | 
			
		||||
	{
 | 
			
		||||
		Macc m(c);
 | 
			
		||||
		int width = GetSize(c->getPort("\\Y"));
 | 
			
		||||
		int width = GetSize(c->getPort(ID(Y)));
 | 
			
		||||
		return bits_macc(m, width);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -242,7 +242,7 @@ struct ShareWorker
 | 
			
		|||
	{
 | 
			
		||||
		Macc m1(c1), m2(c2), supermacc;
 | 
			
		||||
 | 
			
		||||
		int w1 = GetSize(c1->getPort("\\Y")), w2 = GetSize(c2->getPort("\\Y"));
 | 
			
		||||
		int w1 = GetSize(c1->getPort(ID(Y))), w2 = GetSize(c2->getPort(ID(Y)));
 | 
			
		||||
		int width = max(w1, w2);
 | 
			
		||||
 | 
			
		||||
		m1.optimize(w1);
 | 
			
		||||
| 
						 | 
				
			
			@ -328,11 +328,11 @@ struct ShareWorker
 | 
			
		|||
		{
 | 
			
		||||
			RTLIL::SigSpec sig_y = module->addWire(NEW_ID, width);
 | 
			
		||||
 | 
			
		||||
			supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort("\\Y")));
 | 
			
		||||
			supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort("\\Y")));
 | 
			
		||||
			supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID(Y))));
 | 
			
		||||
			supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID(Y))));
 | 
			
		||||
 | 
			
		||||
			supercell->setParam("\\Y_WIDTH", width);
 | 
			
		||||
			supercell->setPort("\\Y", sig_y);
 | 
			
		||||
			supercell->setParam(ID(Y_WIDTH), width);
 | 
			
		||||
			supercell->setPort(ID(Y), sig_y);
 | 
			
		||||
 | 
			
		||||
			supermacc.optimize(width);
 | 
			
		||||
			supermacc.to_cell(supercell);
 | 
			
		||||
| 
						 | 
				
			
			@ -368,22 +368,22 @@ struct ShareWorker
 | 
			
		|||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$memrd") {
 | 
			
		||||
				if (cell->parameters.at("\\CLK_ENABLE").as_bool())
 | 
			
		||||
			if (cell->type == ID($memrd)) {
 | 
			
		||||
				if (cell->parameters.at(ID(CLK_ENABLE)).as_bool())
 | 
			
		||||
					continue;
 | 
			
		||||
				if (config.opt_aggressive || !modwalker.sigmap(cell->getPort("\\ADDR")).is_fully_const())
 | 
			
		||||
				if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(ID(ADDR))).is_fully_const())
 | 
			
		||||
					shareable_cells.insert(cell);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$mul", "$div", "$mod")) {
 | 
			
		||||
				if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 4)
 | 
			
		||||
			if (cell->type.in(ID($mul), ID($div), ID($mod))) {
 | 
			
		||||
				if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 4)
 | 
			
		||||
					shareable_cells.insert(cell);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$shl", "$shr", "$sshl", "$sshr")) {
 | 
			
		||||
				if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 8)
 | 
			
		||||
			if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
 | 
			
		||||
				if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 8)
 | 
			
		||||
					shareable_cells.insert(cell);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -401,9 +401,9 @@ struct ShareWorker
 | 
			
		|||
		if (c1->type != c2->type)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		if (c1->type == "$memrd")
 | 
			
		||||
		if (c1->type == ID($memrd))
 | 
			
		||||
		{
 | 
			
		||||
			if (c1->parameters.at("\\MEMID").decode_string() != c2->parameters.at("\\MEMID").decode_string())
 | 
			
		||||
			if (c1->parameters.at(ID(MEMID)).decode_string() != c2->parameters.at(ID(MEMID)).decode_string())
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
			return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -413,11 +413,11 @@ struct ShareWorker
 | 
			
		|||
		{
 | 
			
		||||
			if (!config.opt_aggressive)
 | 
			
		||||
			{
 | 
			
		||||
				int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
 | 
			
		||||
				int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
 | 
			
		||||
				int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
 | 
			
		||||
				int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
				int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
 | 
			
		||||
				int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
 | 
			
		||||
				int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
 | 
			
		||||
				int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
				if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false;
 | 
			
		||||
				if (max(y1_width, y2_width) > 2 * min(y1_width, y2_width)) return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -426,17 +426,17 @@ struct ShareWorker
 | 
			
		|||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (config.generic_bin_ops.count(c1->type) || c1->type == "$alu")
 | 
			
		||||
		if (config.generic_bin_ops.count(c1->type) || c1->type == ID($alu))
 | 
			
		||||
		{
 | 
			
		||||
			if (!config.opt_aggressive)
 | 
			
		||||
			{
 | 
			
		||||
				int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
 | 
			
		||||
				int b1_width = c1->parameters.at("\\B_WIDTH").as_int();
 | 
			
		||||
				int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
 | 
			
		||||
				int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
 | 
			
		||||
				int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int();
 | 
			
		||||
				int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
				int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
 | 
			
		||||
				int b2_width = c2->parameters.at("\\B_WIDTH").as_int();
 | 
			
		||||
				int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
 | 
			
		||||
				int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
 | 
			
		||||
				int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int();
 | 
			
		||||
				int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
				if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false;
 | 
			
		||||
				if (max(b1_width, b2_width) > 2 * min(b1_width, b2_width)) return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -450,13 +450,13 @@ struct ShareWorker
 | 
			
		|||
		{
 | 
			
		||||
			if (!config.opt_aggressive)
 | 
			
		||||
			{
 | 
			
		||||
				int a1_width = c1->parameters.at("\\A_WIDTH").as_int();
 | 
			
		||||
				int b1_width = c1->parameters.at("\\B_WIDTH").as_int();
 | 
			
		||||
				int y1_width = c1->parameters.at("\\Y_WIDTH").as_int();
 | 
			
		||||
				int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int();
 | 
			
		||||
				int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int();
 | 
			
		||||
				int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
				int a2_width = c2->parameters.at("\\A_WIDTH").as_int();
 | 
			
		||||
				int b2_width = c2->parameters.at("\\B_WIDTH").as_int();
 | 
			
		||||
				int y2_width = c2->parameters.at("\\Y_WIDTH").as_int();
 | 
			
		||||
				int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int();
 | 
			
		||||
				int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int();
 | 
			
		||||
				int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
				int min1_width = min(a1_width, b1_width);
 | 
			
		||||
				int max1_width = max(a1_width, b1_width);
 | 
			
		||||
| 
						 | 
				
			
			@ -472,7 +472,7 @@ struct ShareWorker
 | 
			
		|||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (c1->type == "$macc")
 | 
			
		||||
		if (c1->type == ID($macc))
 | 
			
		||||
		{
 | 
			
		||||
			if (!config.opt_aggressive)
 | 
			
		||||
				if (share_macc(c1, c2) > 2 * min(bits_macc(c1), bits_macc(c2))) return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -510,27 +510,27 @@ struct ShareWorker
 | 
			
		|||
 | 
			
		||||
		if (config.generic_uni_ops.count(c1->type))
 | 
			
		||||
		{
 | 
			
		||||
			if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\A_SIGNED").as_bool())
 | 
			
		||||
			if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool())
 | 
			
		||||
			{
 | 
			
		||||
				RTLIL::Cell *unsigned_cell = c1->parameters.at("\\A_SIGNED").as_bool() ? c2 : c1;
 | 
			
		||||
				if (unsigned_cell->getPort("\\A").to_sigbit_vector().back() != RTLIL::State::S0) {
 | 
			
		||||
					unsigned_cell->parameters.at("\\A_WIDTH") = unsigned_cell->parameters.at("\\A_WIDTH").as_int() + 1;
 | 
			
		||||
					RTLIL::SigSpec new_a = unsigned_cell->getPort("\\A");
 | 
			
		||||
				RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
 | 
			
		||||
				if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) {
 | 
			
		||||
					unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
 | 
			
		||||
					RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A));
 | 
			
		||||
					new_a.append_bit(RTLIL::State::S0);
 | 
			
		||||
					unsigned_cell->setPort("\\A", new_a);
 | 
			
		||||
					unsigned_cell->setPort(ID(A), new_a);
 | 
			
		||||
				}
 | 
			
		||||
				unsigned_cell->parameters.at("\\A_SIGNED") = true;
 | 
			
		||||
				unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
 | 
			
		||||
				unsigned_cell->check();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool();
 | 
			
		||||
			log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool());
 | 
			
		||||
			bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
 | 
			
		||||
			log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec a1 = c1->getPort("\\A");
 | 
			
		||||
			RTLIL::SigSpec y1 = c1->getPort("\\Y");
 | 
			
		||||
			RTLIL::SigSpec a1 = c1->getPort(ID(A));
 | 
			
		||||
			RTLIL::SigSpec y1 = c1->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec a2 = c2->getPort("\\A");
 | 
			
		||||
			RTLIL::SigSpec y2 = c2->getPort("\\Y");
 | 
			
		||||
			RTLIL::SigSpec a2 = c2->getPort(ID(A));
 | 
			
		||||
			RTLIL::SigSpec y2 = c2->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
			int a_width = max(a1.size(), a2.size());
 | 
			
		||||
			int y_width = max(y1.size(), y2.size());
 | 
			
		||||
| 
						 | 
				
			
			@ -544,11 +544,11 @@ struct ShareWorker
 | 
			
		|||
			RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
 | 
			
		||||
			supercell->parameters["\\A_SIGNED"] = a_signed;
 | 
			
		||||
			supercell->parameters["\\A_WIDTH"] = a_width;
 | 
			
		||||
			supercell->parameters["\\Y_WIDTH"] = y_width;
 | 
			
		||||
			supercell->setPort("\\A", a);
 | 
			
		||||
			supercell->setPort("\\Y", y);
 | 
			
		||||
			supercell->parameters[ID(A_SIGNED)] = a_signed;
 | 
			
		||||
			supercell->parameters[ID(A_WIDTH)] = a_width;
 | 
			
		||||
			supercell->parameters[ID(Y_WIDTH)] = y_width;
 | 
			
		||||
			supercell->setPort(ID(A), a);
 | 
			
		||||
			supercell->setPort(ID(Y), y);
 | 
			
		||||
 | 
			
		||||
			supercell_aux.insert(module->addPos(NEW_ID, y, y1));
 | 
			
		||||
			supercell_aux.insert(module->addPos(NEW_ID, y, y2));
 | 
			
		||||
| 
						 | 
				
			
			@ -557,54 +557,54 @@ struct ShareWorker
 | 
			
		|||
			return supercell;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == "$alu")
 | 
			
		||||
		if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == ID($alu))
 | 
			
		||||
		{
 | 
			
		||||
			bool modified_src_cells = false;
 | 
			
		||||
 | 
			
		||||
			if (config.generic_cbin_ops.count(c1->type))
 | 
			
		||||
			{
 | 
			
		||||
				int score_unflipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int()) +
 | 
			
		||||
						max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int());
 | 
			
		||||
				int score_unflipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int()) +
 | 
			
		||||
						max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int());
 | 
			
		||||
 | 
			
		||||
				int score_flipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int()) +
 | 
			
		||||
						max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int());
 | 
			
		||||
				int score_flipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int()) +
 | 
			
		||||
						max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int());
 | 
			
		||||
 | 
			
		||||
				if (score_flipped < score_unflipped)
 | 
			
		||||
				{
 | 
			
		||||
					RTLIL::SigSpec tmp = c2->getPort("\\A");
 | 
			
		||||
					c2->setPort("\\A", c2->getPort("\\B"));
 | 
			
		||||
					c2->setPort("\\B", tmp);
 | 
			
		||||
					RTLIL::SigSpec tmp = c2->getPort(ID(A));
 | 
			
		||||
					c2->setPort(ID(A), c2->getPort(ID(B)));
 | 
			
		||||
					c2->setPort(ID(B), tmp);
 | 
			
		||||
 | 
			
		||||
					std::swap(c2->parameters.at("\\A_WIDTH"), c2->parameters.at("\\B_WIDTH"));
 | 
			
		||||
					std::swap(c2->parameters.at("\\A_SIGNED"), c2->parameters.at("\\B_SIGNED"));
 | 
			
		||||
					std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH)));
 | 
			
		||||
					std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED)));
 | 
			
		||||
					modified_src_cells = true;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\A_SIGNED").as_bool())
 | 
			
		||||
			if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool())
 | 
			
		||||
 | 
			
		||||
			{
 | 
			
		||||
				RTLIL::Cell *unsigned_cell = c1->parameters.at("\\A_SIGNED").as_bool() ? c2 : c1;
 | 
			
		||||
				if (unsigned_cell->getPort("\\A").to_sigbit_vector().back() != RTLIL::State::S0) {
 | 
			
		||||
					unsigned_cell->parameters.at("\\A_WIDTH") = unsigned_cell->parameters.at("\\A_WIDTH").as_int() + 1;
 | 
			
		||||
					RTLIL::SigSpec new_a = unsigned_cell->getPort("\\A");
 | 
			
		||||
				RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1;
 | 
			
		||||
				if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) {
 | 
			
		||||
					unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1;
 | 
			
		||||
					RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A));
 | 
			
		||||
					new_a.append_bit(RTLIL::State::S0);
 | 
			
		||||
					unsigned_cell->setPort("\\A", new_a);
 | 
			
		||||
					unsigned_cell->setPort(ID(A), new_a);
 | 
			
		||||
				}
 | 
			
		||||
				unsigned_cell->parameters.at("\\A_SIGNED") = true;
 | 
			
		||||
				unsigned_cell->parameters.at(ID(A_SIGNED)) = true;
 | 
			
		||||
				modified_src_cells = true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (c1->parameters.at("\\B_SIGNED").as_bool() != c2->parameters.at("\\B_SIGNED").as_bool())
 | 
			
		||||
			if (c1->parameters.at(ID(B_SIGNED)).as_bool() != c2->parameters.at(ID(B_SIGNED)).as_bool())
 | 
			
		||||
			{
 | 
			
		||||
				RTLIL::Cell *unsigned_cell = c1->parameters.at("\\B_SIGNED").as_bool() ? c2 : c1;
 | 
			
		||||
				if (unsigned_cell->getPort("\\B").to_sigbit_vector().back() != RTLIL::State::S0) {
 | 
			
		||||
					unsigned_cell->parameters.at("\\B_WIDTH") = unsigned_cell->parameters.at("\\B_WIDTH").as_int() + 1;
 | 
			
		||||
					RTLIL::SigSpec new_b = unsigned_cell->getPort("\\B");
 | 
			
		||||
				RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1;
 | 
			
		||||
				if (unsigned_cell->getPort(ID(B)).to_sigbit_vector().back() != RTLIL::State::S0) {
 | 
			
		||||
					unsigned_cell->parameters.at(ID(B_WIDTH)) = unsigned_cell->parameters.at(ID(B_WIDTH)).as_int() + 1;
 | 
			
		||||
					RTLIL::SigSpec new_b = unsigned_cell->getPort(ID(B));
 | 
			
		||||
					new_b.append_bit(RTLIL::State::S0);
 | 
			
		||||
					unsigned_cell->setPort("\\B", new_b);
 | 
			
		||||
					unsigned_cell->setPort(ID(B), new_b);
 | 
			
		||||
				}
 | 
			
		||||
				unsigned_cell->parameters.at("\\B_SIGNED") = true;
 | 
			
		||||
				unsigned_cell->parameters.at(ID(B_SIGNED)) = true;
 | 
			
		||||
				modified_src_cells = true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -613,28 +613,28 @@ struct ShareWorker
 | 
			
		|||
				c2->check();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool();
 | 
			
		||||
			bool b_signed = c1->parameters.at("\\B_SIGNED").as_bool();
 | 
			
		||||
			bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool();
 | 
			
		||||
			bool b_signed = c1->parameters.at(ID(B_SIGNED)).as_bool();
 | 
			
		||||
 | 
			
		||||
			log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool());
 | 
			
		||||
			log_assert(b_signed == c2->parameters.at("\\B_SIGNED").as_bool());
 | 
			
		||||
			log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool());
 | 
			
		||||
			log_assert(b_signed == c2->parameters.at(ID(B_SIGNED)).as_bool());
 | 
			
		||||
 | 
			
		||||
			if (c1->type == "$shl" || c1->type == "$shr" || c1->type == "$sshl" || c1->type == "$sshr")
 | 
			
		||||
			if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr))
 | 
			
		||||
				b_signed = false;
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec a1 = c1->getPort("\\A");
 | 
			
		||||
			RTLIL::SigSpec b1 = c1->getPort("\\B");
 | 
			
		||||
			RTLIL::SigSpec y1 = c1->getPort("\\Y");
 | 
			
		||||
			RTLIL::SigSpec a1 = c1->getPort(ID(A));
 | 
			
		||||
			RTLIL::SigSpec b1 = c1->getPort(ID(B));
 | 
			
		||||
			RTLIL::SigSpec y1 = c1->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec a2 = c2->getPort("\\A");
 | 
			
		||||
			RTLIL::SigSpec b2 = c2->getPort("\\B");
 | 
			
		||||
			RTLIL::SigSpec y2 = c2->getPort("\\Y");
 | 
			
		||||
			RTLIL::SigSpec a2 = c2->getPort(ID(A));
 | 
			
		||||
			RTLIL::SigSpec b2 = c2->getPort(ID(B));
 | 
			
		||||
			RTLIL::SigSpec y2 = c2->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
			int a_width = max(a1.size(), a2.size());
 | 
			
		||||
			int b_width = max(b1.size(), b2.size());
 | 
			
		||||
			int y_width = max(y1.size(), y2.size());
 | 
			
		||||
 | 
			
		||||
			if (c1->type == "$shr" && a_signed)
 | 
			
		||||
			if (c1->type == ID($shr) && a_signed)
 | 
			
		||||
			{
 | 
			
		||||
				a_width = max(y_width, a_width);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -660,43 +660,43 @@ struct ShareWorker
 | 
			
		|||
			supercell_aux.insert(module->addMux(NEW_ID, b2, b1, act, b));
 | 
			
		||||
 | 
			
		||||
			RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
 | 
			
		||||
			RTLIL::Wire *x = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr;
 | 
			
		||||
			RTLIL::Wire *co = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr;
 | 
			
		||||
			RTLIL::Wire *x = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr;
 | 
			
		||||
			RTLIL::Wire *co = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr;
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
 | 
			
		||||
			supercell->parameters["\\A_SIGNED"] = a_signed;
 | 
			
		||||
			supercell->parameters["\\B_SIGNED"] = b_signed;
 | 
			
		||||
			supercell->parameters["\\A_WIDTH"] = a_width;
 | 
			
		||||
			supercell->parameters["\\B_WIDTH"] = b_width;
 | 
			
		||||
			supercell->parameters["\\Y_WIDTH"] = y_width;
 | 
			
		||||
			supercell->setPort("\\A", a);
 | 
			
		||||
			supercell->setPort("\\B", b);
 | 
			
		||||
			supercell->setPort("\\Y", y);
 | 
			
		||||
			if (c1->type == "$alu") {
 | 
			
		||||
			supercell->parameters[ID(A_SIGNED)] = a_signed;
 | 
			
		||||
			supercell->parameters[ID(B_SIGNED)] = b_signed;
 | 
			
		||||
			supercell->parameters[ID(A_WIDTH)] = a_width;
 | 
			
		||||
			supercell->parameters[ID(B_WIDTH)] = b_width;
 | 
			
		||||
			supercell->parameters[ID(Y_WIDTH)] = y_width;
 | 
			
		||||
			supercell->setPort(ID(A), a);
 | 
			
		||||
			supercell->setPort(ID(B), b);
 | 
			
		||||
			supercell->setPort(ID(Y), y);
 | 
			
		||||
			if (c1->type == ID($alu)) {
 | 
			
		||||
				RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID);
 | 
			
		||||
				supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\CI"), c1->getPort("\\CI"), act, ci));
 | 
			
		||||
				supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\BI"), c1->getPort("\\BI"), act, bi));
 | 
			
		||||
				supercell->setPort("\\CI", ci);
 | 
			
		||||
				supercell->setPort("\\BI", bi);
 | 
			
		||||
				supercell->setPort("\\CO", co);
 | 
			
		||||
				supercell->setPort("\\X", x);
 | 
			
		||||
				supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(CI)), c1->getPort(ID(CI)), act, ci));
 | 
			
		||||
				supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(BI)), c1->getPort(ID(BI)), act, bi));
 | 
			
		||||
				supercell->setPort(ID(CI), ci);
 | 
			
		||||
				supercell->setPort(ID(BI), bi);
 | 
			
		||||
				supercell->setPort(ID(CO), co);
 | 
			
		||||
				supercell->setPort(ID(X), x);
 | 
			
		||||
			}
 | 
			
		||||
			supercell->check();
 | 
			
		||||
 | 
			
		||||
			supercell_aux.insert(module->addPos(NEW_ID, y, y1));
 | 
			
		||||
			supercell_aux.insert(module->addPos(NEW_ID, y, y2));
 | 
			
		||||
			if (c1->type == "$alu") {
 | 
			
		||||
				supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort("\\CO")));
 | 
			
		||||
				supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort("\\CO")));
 | 
			
		||||
				supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort("\\X")));
 | 
			
		||||
				supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort("\\X")));
 | 
			
		||||
			if (c1->type == ID($alu)) {
 | 
			
		||||
				supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort(ID(CO))));
 | 
			
		||||
				supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort(ID(CO))));
 | 
			
		||||
				supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort(ID(X))));
 | 
			
		||||
				supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort(ID(X))));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			supercell_aux.insert(supercell);
 | 
			
		||||
			return supercell;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (c1->type == "$macc")
 | 
			
		||||
		if (c1->type == ID($macc))
 | 
			
		||||
		{
 | 
			
		||||
			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
 | 
			
		||||
			supercell_aux.insert(supercell);
 | 
			
		||||
| 
						 | 
				
			
			@ -705,18 +705,18 @@ struct ShareWorker
 | 
			
		|||
			return supercell;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (c1->type == "$memrd")
 | 
			
		||||
		if (c1->type == ID($memrd))
 | 
			
		||||
		{
 | 
			
		||||
			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1);
 | 
			
		||||
			RTLIL::SigSpec addr1 = c1->getPort("\\ADDR");
 | 
			
		||||
			RTLIL::SigSpec addr2 = c2->getPort("\\ADDR");
 | 
			
		||||
			RTLIL::SigSpec addr1 = c1->getPort(ID(ADDR));
 | 
			
		||||
			RTLIL::SigSpec addr2 = c2->getPort(ID(ADDR));
 | 
			
		||||
			if (GetSize(addr1) < GetSize(addr2))
 | 
			
		||||
				addr1.extend_u0(GetSize(addr2));
 | 
			
		||||
			else
 | 
			
		||||
				addr2.extend_u0(GetSize(addr1));
 | 
			
		||||
			supercell->setPort("\\ADDR", addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1);
 | 
			
		||||
			supercell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr1));
 | 
			
		||||
			supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort("\\DATA"), c2->getPort("\\DATA")));
 | 
			
		||||
			supercell->setPort(ID(ADDR), addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1);
 | 
			
		||||
			supercell->parameters[ID(ABITS)] = RTLIL::Const(GetSize(addr1));
 | 
			
		||||
			supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort(ID(DATA)), c2->getPort(ID(DATA))));
 | 
			
		||||
			supercell_aux.insert(supercell);
 | 
			
		||||
			return supercell;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -747,8 +747,8 @@ struct ShareWorker
 | 
			
		|||
		modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]);
 | 
			
		||||
 | 
			
		||||
		for (auto &bit : pbits) {
 | 
			
		||||
			if ((bit.cell->type == "$mux" || bit.cell->type == "$pmux") && bit.port == "\\S")
 | 
			
		||||
				forbidden_controls_cache[cell].insert(bit.cell->getPort("\\S").extract(bit.offset, 1));
 | 
			
		||||
			if ((bit.cell->type == ID($mux) || bit.cell->type == ID($pmux)) && bit.port == ID(S))
 | 
			
		||||
				forbidden_controls_cache[cell].insert(bit.cell->getPort(ID(S)).extract(bit.offset, 1));
 | 
			
		||||
			consumer_cells.insert(bit.cell);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -874,7 +874,7 @@ struct ShareWorker
 | 
			
		|||
			}
 | 
			
		||||
			for (auto &pbit : modwalker.signal_consumers[bit]) {
 | 
			
		||||
				log_assert(fwd_ct.cell_known(pbit.cell->type));
 | 
			
		||||
				if ((pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") && (pbit.port == "\\A" || pbit.port == "\\B"))
 | 
			
		||||
				if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID(A) || pbit.port == ID(B)))
 | 
			
		||||
					driven_data_muxes.insert(pbit.cell);
 | 
			
		||||
				else
 | 
			
		||||
					driven_cells.insert(pbit.cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -890,10 +890,10 @@ struct ShareWorker
 | 
			
		|||
			bool used_in_a = false;
 | 
			
		||||
			std::set<int> used_in_b_parts;
 | 
			
		||||
 | 
			
		||||
			int width = c->parameters.at("\\WIDTH").as_int();
 | 
			
		||||
			std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort("\\A"));
 | 
			
		||||
			std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort("\\B"));
 | 
			
		||||
			std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort("\\S"));
 | 
			
		||||
			int width = c->parameters.at(ID(WIDTH)).as_int();
 | 
			
		||||
			std::vector<RTLIL::SigBit> sig_a = modwalker.sigmap(c->getPort(ID(A)));
 | 
			
		||||
			std::vector<RTLIL::SigBit> sig_b = modwalker.sigmap(c->getPort(ID(B)));
 | 
			
		||||
			std::vector<RTLIL::SigBit> sig_s = modwalker.sigmap(c->getPort(ID(S)));
 | 
			
		||||
 | 
			
		||||
			for (auto &bit : sig_a)
 | 
			
		||||
				if (cell_out_bits.count(bit))
 | 
			
		||||
| 
						 | 
				
			
			@ -1132,14 +1132,14 @@ struct ShareWorker
 | 
			
		|||
		fwd_ct.setup_internals();
 | 
			
		||||
 | 
			
		||||
		cone_ct.setup_internals();
 | 
			
		||||
		cone_ct.cell_types.erase("$mul");
 | 
			
		||||
		cone_ct.cell_types.erase("$mod");
 | 
			
		||||
		cone_ct.cell_types.erase("$div");
 | 
			
		||||
		cone_ct.cell_types.erase("$pow");
 | 
			
		||||
		cone_ct.cell_types.erase("$shl");
 | 
			
		||||
		cone_ct.cell_types.erase("$shr");
 | 
			
		||||
		cone_ct.cell_types.erase("$sshl");
 | 
			
		||||
		cone_ct.cell_types.erase("$sshr");
 | 
			
		||||
		cone_ct.cell_types.erase(ID($mul));
 | 
			
		||||
		cone_ct.cell_types.erase(ID($mod));
 | 
			
		||||
		cone_ct.cell_types.erase(ID($div));
 | 
			
		||||
		cone_ct.cell_types.erase(ID($pow));
 | 
			
		||||
		cone_ct.cell_types.erase(ID($shl));
 | 
			
		||||
		cone_ct.cell_types.erase(ID($shr));
 | 
			
		||||
		cone_ct.cell_types.erase(ID($sshl));
 | 
			
		||||
		cone_ct.cell_types.erase(ID($sshr));
 | 
			
		||||
 | 
			
		||||
		modwalker.setup(design, module);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1153,9 +1153,9 @@ struct ShareWorker
 | 
			
		|||
				GetSize(shareable_cells), log_id(module));
 | 
			
		||||
 | 
			
		||||
		for (auto cell : module->cells())
 | 
			
		||||
			if (cell->type == "$pmux")
 | 
			
		||||
				for (auto bit : cell->getPort("\\S"))
 | 
			
		||||
				for (auto other_bit : cell->getPort("\\S"))
 | 
			
		||||
			if (cell->type == ID($pmux))
 | 
			
		||||
				for (auto bit : cell->getPort(ID(S)))
 | 
			
		||||
				for (auto other_bit : cell->getPort(ID(S)))
 | 
			
		||||
					if (bit < other_bit)
 | 
			
		||||
						exclusive_ctrls.push_back(std::pair<RTLIL::SigBit, RTLIL::SigBit>(bit, other_bit));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1466,43 +1466,43 @@ struct SharePass : public Pass {
 | 
			
		|||
		config.opt_aggressive = false;
 | 
			
		||||
		config.opt_fast = false;
 | 
			
		||||
 | 
			
		||||
		config.generic_uni_ops.insert("$not");
 | 
			
		||||
		// config.generic_uni_ops.insert("$pos");
 | 
			
		||||
		config.generic_uni_ops.insert("$neg");
 | 
			
		||||
		config.generic_uni_ops.insert(ID($not));
 | 
			
		||||
		// config.generic_uni_ops.insert(ID($pos));
 | 
			
		||||
		config.generic_uni_ops.insert(ID($neg));
 | 
			
		||||
 | 
			
		||||
		config.generic_cbin_ops.insert("$and");
 | 
			
		||||
		config.generic_cbin_ops.insert("$or");
 | 
			
		||||
		config.generic_cbin_ops.insert("$xor");
 | 
			
		||||
		config.generic_cbin_ops.insert("$xnor");
 | 
			
		||||
		config.generic_cbin_ops.insert(ID($and));
 | 
			
		||||
		config.generic_cbin_ops.insert(ID($or));
 | 
			
		||||
		config.generic_cbin_ops.insert(ID($xor));
 | 
			
		||||
		config.generic_cbin_ops.insert(ID($xnor));
 | 
			
		||||
 | 
			
		||||
		config.generic_bin_ops.insert("$shl");
 | 
			
		||||
		config.generic_bin_ops.insert("$shr");
 | 
			
		||||
		config.generic_bin_ops.insert("$sshl");
 | 
			
		||||
		config.generic_bin_ops.insert("$sshr");
 | 
			
		||||
		config.generic_bin_ops.insert(ID($shl));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($shr));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($sshl));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($sshr));
 | 
			
		||||
 | 
			
		||||
		config.generic_bin_ops.insert("$lt");
 | 
			
		||||
		config.generic_bin_ops.insert("$le");
 | 
			
		||||
		config.generic_bin_ops.insert("$eq");
 | 
			
		||||
		config.generic_bin_ops.insert("$ne");
 | 
			
		||||
		config.generic_bin_ops.insert("$eqx");
 | 
			
		||||
		config.generic_bin_ops.insert("$nex");
 | 
			
		||||
		config.generic_bin_ops.insert("$ge");
 | 
			
		||||
		config.generic_bin_ops.insert("$gt");
 | 
			
		||||
		config.generic_bin_ops.insert(ID($lt));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($le));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($eq));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($ne));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($eqx));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($nex));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($ge));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($gt));
 | 
			
		||||
 | 
			
		||||
		config.generic_cbin_ops.insert("$add");
 | 
			
		||||
		config.generic_cbin_ops.insert("$mul");
 | 
			
		||||
		config.generic_cbin_ops.insert(ID($add));
 | 
			
		||||
		config.generic_cbin_ops.insert(ID($mul));
 | 
			
		||||
 | 
			
		||||
		config.generic_bin_ops.insert("$sub");
 | 
			
		||||
		config.generic_bin_ops.insert("$div");
 | 
			
		||||
		config.generic_bin_ops.insert("$mod");
 | 
			
		||||
		// config.generic_bin_ops.insert("$pow");
 | 
			
		||||
		config.generic_bin_ops.insert(ID($sub));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($div));
 | 
			
		||||
		config.generic_bin_ops.insert(ID($mod));
 | 
			
		||||
		// config.generic_bin_ops.insert(ID($pow));
 | 
			
		||||
 | 
			
		||||
		config.generic_uni_ops.insert("$logic_not");
 | 
			
		||||
		config.generic_cbin_ops.insert("$logic_and");
 | 
			
		||||
		config.generic_cbin_ops.insert("$logic_or");
 | 
			
		||||
		config.generic_uni_ops.insert(ID($logic_not));
 | 
			
		||||
		config.generic_cbin_ops.insert(ID($logic_and));
 | 
			
		||||
		config.generic_cbin_ops.insert(ID($logic_or));
 | 
			
		||||
 | 
			
		||||
		config.generic_other_ops.insert("$alu");
 | 
			
		||||
		config.generic_other_ops.insert("$macc");
 | 
			
		||||
		config.generic_other_ops.insert(ID($alu));
 | 
			
		||||
		config.generic_other_ops.insert(ID($macc));
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,13 +34,13 @@ struct WreduceConfig
 | 
			
		|||
	WreduceConfig()
 | 
			
		||||
	{
 | 
			
		||||
		supported_cell_types = pool<IdString>({
 | 
			
		||||
			"$not", "$pos", "$neg",
 | 
			
		||||
			"$and", "$or", "$xor", "$xnor",
 | 
			
		||||
			"$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
 | 
			
		||||
			"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
 | 
			
		||||
			"$add", "$sub", "$mul", // "$div", "$mod", "$pow",
 | 
			
		||||
			"$mux", "$pmux",
 | 
			
		||||
			"$dff", "$adff"
 | 
			
		||||
			ID($not), ID($pos), ID($neg),
 | 
			
		||||
			ID($and), ID($or), ID($xor), ID($xnor),
 | 
			
		||||
			ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
 | 
			
		||||
			ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
 | 
			
		||||
			ID($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($pow),
 | 
			
		||||
			ID($mux), ID($pmux),
 | 
			
		||||
			ID($dff), ID($adff)
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -64,10 +64,10 @@ struct WreduceWorker
 | 
			
		|||
	{
 | 
			
		||||
		// Reduce size of MUX if inputs agree on a value for a bit or a output bit is unused
 | 
			
		||||
 | 
			
		||||
		SigSpec sig_a = mi.sigmap(cell->getPort("\\A"));
 | 
			
		||||
		SigSpec sig_b = mi.sigmap(cell->getPort("\\B"));
 | 
			
		||||
		SigSpec sig_s = mi.sigmap(cell->getPort("\\S"));
 | 
			
		||||
		SigSpec sig_y = mi.sigmap(cell->getPort("\\Y"));
 | 
			
		||||
		SigSpec sig_a = mi.sigmap(cell->getPort(ID(A)));
 | 
			
		||||
		SigSpec sig_b = mi.sigmap(cell->getPort(ID(B)));
 | 
			
		||||
		SigSpec sig_s = mi.sigmap(cell->getPort(ID(S)));
 | 
			
		||||
		SigSpec sig_y = mi.sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
		std::vector<SigBit> bits_removed;
 | 
			
		||||
 | 
			
		||||
		if (sig_y.has_const())
 | 
			
		||||
| 
						 | 
				
			
			@ -130,9 +130,9 @@ struct WreduceWorker
 | 
			
		|||
		for (auto bit : new_work_queue_bits)
 | 
			
		||||
			work_queue_bits.insert(bit);
 | 
			
		||||
 | 
			
		||||
		cell->setPort("\\A", new_sig_a);
 | 
			
		||||
		cell->setPort("\\B", new_sig_b);
 | 
			
		||||
		cell->setPort("\\Y", new_sig_y);
 | 
			
		||||
		cell->setPort(ID(A), new_sig_a);
 | 
			
		||||
		cell->setPort(ID(B), new_sig_b);
 | 
			
		||||
		cell->setPort(ID(Y), new_sig_y);
 | 
			
		||||
		cell->fixup_parameters();
 | 
			
		||||
 | 
			
		||||
		module->connect(sig_y.extract(n_kept, n_removed), sig_removed);
 | 
			
		||||
| 
						 | 
				
			
			@ -142,8 +142,8 @@ struct WreduceWorker
 | 
			
		|||
	{
 | 
			
		||||
		// Reduce size of FF if inputs are just sign/zero extended or output bit is not used
 | 
			
		||||
 | 
			
		||||
		SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
 | 
			
		||||
		SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
 | 
			
		||||
		SigSpec sig_d = mi.sigmap(cell->getPort(ID(D)));
 | 
			
		||||
		SigSpec sig_q = mi.sigmap(cell->getPort(ID(Q)));
 | 
			
		||||
		Const initval;
 | 
			
		||||
 | 
			
		||||
		int width_before = GetSize(sig_q);
 | 
			
		||||
| 
						 | 
				
			
			@ -214,14 +214,14 @@ struct WreduceWorker
 | 
			
		|||
			work_queue_bits.insert(bit);
 | 
			
		||||
 | 
			
		||||
		// Narrow ARST_VALUE parameter to new size.
 | 
			
		||||
		if (cell->parameters.count("\\ARST_VALUE")) {
 | 
			
		||||
			Const arst_value = cell->getParam("\\ARST_VALUE");
 | 
			
		||||
		if (cell->parameters.count(ID(ARST_VALUE))) {
 | 
			
		||||
			Const arst_value = cell->getParam(ID(ARST_VALUE));
 | 
			
		||||
			arst_value.bits.resize(GetSize(sig_q));
 | 
			
		||||
			cell->setParam("\\ARST_VALUE", arst_value);
 | 
			
		||||
			cell->setParam(ID(ARST_VALUE), arst_value);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cell->setPort("\\D", sig_d);
 | 
			
		||||
		cell->setPort("\\Q", sig_q);
 | 
			
		||||
		cell->setPort(ID(D), sig_d);
 | 
			
		||||
		cell->setPort(ID(Q), sig_q);
 | 
			
		||||
		cell->fixup_parameters();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -230,7 +230,7 @@ struct WreduceWorker
 | 
			
		|||
		port_signed = cell->getParam(stringf("\\%c_SIGNED", port)).as_bool();
 | 
			
		||||
		SigSpec sig = mi.sigmap(cell->getPort(stringf("\\%c", port)));
 | 
			
		||||
 | 
			
		||||
		if (port == 'B' && cell->type.in("$shl", "$shr", "$sshl", "$sshr"))
 | 
			
		||||
		if (port == 'B' && cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr)))
 | 
			
		||||
			port_signed = false;
 | 
			
		||||
 | 
			
		||||
		int bits_removed = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -264,13 +264,13 @@ struct WreduceWorker
 | 
			
		|||
		if (!cell->type.in(config->supported_cell_types))
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		if (cell->type.in("$mux", "$pmux"))
 | 
			
		||||
		if (cell->type.in(ID($mux), ID($pmux)))
 | 
			
		||||
			return run_cell_mux(cell);
 | 
			
		||||
 | 
			
		||||
		if (cell->type.in("$dff", "$adff"))
 | 
			
		||||
		if (cell->type.in(ID($dff), ID($adff)))
 | 
			
		||||
			return run_cell_dff(cell);
 | 
			
		||||
 | 
			
		||||
		SigSpec sig = mi.sigmap(cell->getPort("\\Y"));
 | 
			
		||||
		SigSpec sig = mi.sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
 | 
			
		||||
		if (sig.has_const())
 | 
			
		||||
			return;
 | 
			
		||||
| 
						 | 
				
			
			@ -278,10 +278,10 @@ struct WreduceWorker
 | 
			
		|||
 | 
			
		||||
		// Reduce size of ports A and B based on constant input bits and size of output port
 | 
			
		||||
 | 
			
		||||
		int max_port_a_size = cell->hasPort("\\A") ? GetSize(cell->getPort("\\A")) : -1;
 | 
			
		||||
		int max_port_b_size = cell->hasPort("\\B") ? GetSize(cell->getPort("\\B")) : -1;
 | 
			
		||||
		int max_port_a_size = cell->hasPort(ID(A)) ? GetSize(cell->getPort(ID(A))) : -1;
 | 
			
		||||
		int max_port_b_size = cell->hasPort(ID(B)) ? GetSize(cell->getPort(ID(B))) : -1;
 | 
			
		||||
 | 
			
		||||
		if (cell->type.in("$not", "$pos", "$neg", "$and", "$or", "$xor", "$add", "$sub")) {
 | 
			
		||||
		if (cell->type.in(ID($not), ID($pos), ID($neg), ID($and), ID($or), ID($xor), ID($add), ID($sub))) {
 | 
			
		||||
			max_port_a_size = min(max_port_a_size, GetSize(sig));
 | 
			
		||||
			max_port_b_size = min(max_port_b_size, GetSize(sig));
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -289,32 +289,32 @@ struct WreduceWorker
 | 
			
		|||
		bool port_a_signed = false;
 | 
			
		||||
		bool port_b_signed = false;
 | 
			
		||||
 | 
			
		||||
		if (max_port_a_size >= 0 && cell->type != "$shiftx")
 | 
			
		||||
		if (max_port_a_size >= 0 && cell->type != ID($shiftx))
 | 
			
		||||
			run_reduce_inport(cell, 'A', max_port_a_size, port_a_signed, did_something);
 | 
			
		||||
 | 
			
		||||
		if (max_port_b_size >= 0)
 | 
			
		||||
			run_reduce_inport(cell, 'B', max_port_b_size, port_b_signed, did_something);
 | 
			
		||||
 | 
			
		||||
		if (cell->hasPort("\\A") && cell->hasPort("\\B") && port_a_signed && port_b_signed) {
 | 
			
		||||
			SigSpec sig_a = mi.sigmap(cell->getPort("\\A")), sig_b = mi.sigmap(cell->getPort("\\B"));
 | 
			
		||||
		if (cell->hasPort(ID(A)) && cell->hasPort(ID(B)) && port_a_signed && port_b_signed) {
 | 
			
		||||
			SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))), sig_b = mi.sigmap(cell->getPort(ID(B)));
 | 
			
		||||
			if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 &&
 | 
			
		||||
					GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) {
 | 
			
		||||
				log("Converting cell %s.%s (%s) from signed to unsigned.\n",
 | 
			
		||||
						log_id(module), log_id(cell), log_id(cell->type));
 | 
			
		||||
				cell->setParam("\\A_SIGNED", 0);
 | 
			
		||||
				cell->setParam("\\B_SIGNED", 0);
 | 
			
		||||
				cell->setParam(ID(A_SIGNED), 0);
 | 
			
		||||
				cell->setParam(ID(B_SIGNED), 0);
 | 
			
		||||
				port_a_signed = false;
 | 
			
		||||
				port_b_signed = false;
 | 
			
		||||
				did_something = true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->hasPort("\\A") && !cell->hasPort("\\B") && port_a_signed) {
 | 
			
		||||
			SigSpec sig_a = mi.sigmap(cell->getPort("\\A"));
 | 
			
		||||
		if (cell->hasPort(ID(A)) && !cell->hasPort(ID(B)) && port_a_signed) {
 | 
			
		||||
			SigSpec sig_a = mi.sigmap(cell->getPort(ID(A)));
 | 
			
		||||
			if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) {
 | 
			
		||||
				log("Converting cell %s.%s (%s) from signed to unsigned.\n",
 | 
			
		||||
						log_id(module), log_id(cell), log_id(cell->type));
 | 
			
		||||
				cell->setParam("\\A_SIGNED", 0);
 | 
			
		||||
				cell->setParam(ID(A_SIGNED), 0);
 | 
			
		||||
				port_a_signed = false;
 | 
			
		||||
				did_something = true;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -324,7 +324,7 @@ struct WreduceWorker
 | 
			
		|||
		// Reduce size of port Y based on sizes for A and B and unused bits in Y
 | 
			
		||||
 | 
			
		||||
		int bits_removed = 0;
 | 
			
		||||
		if (port_a_signed && cell->type == "$shr") {
 | 
			
		||||
		if (port_a_signed && cell->type == ID($shr)) {
 | 
			
		||||
			// do not reduce size of output on $shr cells with signed A inputs
 | 
			
		||||
		} else {
 | 
			
		||||
			while (GetSize(sig) > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -342,20 +342,20 @@ struct WreduceWorker
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor", "$sub"))
 | 
			
		||||
		if (cell->type.in(ID($pos), ID($add), ID($mul), ID($and), ID($or), ID($xor), ID($sub)))
 | 
			
		||||
		{
 | 
			
		||||
			bool is_signed = cell->getParam("\\A_SIGNED").as_bool() || cell->type == "$sub";
 | 
			
		||||
			bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool() || cell->type == ID($sub);
 | 
			
		||||
 | 
			
		||||
			int a_size = 0, b_size = 0;
 | 
			
		||||
			if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A"));
 | 
			
		||||
			if (cell->hasPort("\\B")) b_size = GetSize(cell->getPort("\\B"));
 | 
			
		||||
			if (cell->hasPort(ID(A))) a_size = GetSize(cell->getPort(ID(A)));
 | 
			
		||||
			if (cell->hasPort(ID(B))) b_size = GetSize(cell->getPort(ID(B)));
 | 
			
		||||
 | 
			
		||||
			int max_y_size = max(a_size, b_size);
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$add", "$sub"))
 | 
			
		||||
			if (cell->type.in(ID($add), ID($sub)))
 | 
			
		||||
				max_y_size++;
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$mul")
 | 
			
		||||
			if (cell->type == ID($mul))
 | 
			
		||||
				max_y_size = a_size + b_size;
 | 
			
		||||
 | 
			
		||||
			while (GetSize(sig) > 1 && GetSize(sig) > max_y_size) {
 | 
			
		||||
| 
						 | 
				
			
			@ -374,7 +374,7 @@ struct WreduceWorker
 | 
			
		|||
		if (bits_removed) {
 | 
			
		||||
			log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n",
 | 
			
		||||
					bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type));
 | 
			
		||||
			cell->setPort("\\Y", sig);
 | 
			
		||||
			cell->setPort(ID(Y), sig);
 | 
			
		||||
			did_something = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -387,8 +387,8 @@ struct WreduceWorker
 | 
			
		|||
	static int count_nontrivial_wire_attrs(RTLIL::Wire *w)
 | 
			
		||||
	{
 | 
			
		||||
		int count = w->attributes.size();
 | 
			
		||||
		count -= w->attributes.count("\\src");
 | 
			
		||||
		count -= w->attributes.count("\\unused_bits");
 | 
			
		||||
		count -= w->attributes.count(ID(src));
 | 
			
		||||
		count -= w->attributes.count(ID(unused_bits));
 | 
			
		||||
		return count;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -398,11 +398,11 @@ struct WreduceWorker
 | 
			
		|||
		SigMap init_attr_sigmap = mi.sigmap;
 | 
			
		||||
 | 
			
		||||
		for (auto w : module->wires()) {
 | 
			
		||||
			if (w->get_bool_attribute("\\keep"))
 | 
			
		||||
			if (w->get_bool_attribute(ID(keep)))
 | 
			
		||||
				for (auto bit : mi.sigmap(w))
 | 
			
		||||
					keep_bits.insert(bit);
 | 
			
		||||
			if (w->attributes.count("\\init")) {
 | 
			
		||||
				Const initval = w->attributes.at("\\init");
 | 
			
		||||
			if (w->attributes.count(ID(init))) {
 | 
			
		||||
				Const initval = w->attributes.at(ID(init));
 | 
			
		||||
				SigSpec initsig = init_attr_sigmap(w);
 | 
			
		||||
				int width = std::min(GetSize(initval), GetSize(initsig));
 | 
			
		||||
				for (int i = 0; i < width; i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -459,8 +459,8 @@ struct WreduceWorker
 | 
			
		|||
 | 
			
		||||
		if (!remove_init_bits.empty()) {
 | 
			
		||||
			for (auto w : module->wires()) {
 | 
			
		||||
				if (w->attributes.count("\\init")) {
 | 
			
		||||
					Const initval = w->attributes.at("\\init");
 | 
			
		||||
				if (w->attributes.count(ID(init))) {
 | 
			
		||||
					Const initval = w->attributes.at(ID(init));
 | 
			
		||||
					Const new_initval(State::Sx, GetSize(w));
 | 
			
		||||
					SigSpec initsig = init_attr_sigmap(w);
 | 
			
		||||
					int width = std::min(GetSize(initval), GetSize(initsig));
 | 
			
		||||
| 
						 | 
				
			
			@ -468,7 +468,7 @@ struct WreduceWorker
 | 
			
		|||
						if (!remove_init_bits.count(initsig[i]))
 | 
			
		||||
							new_initval[i] = initval[i];
 | 
			
		||||
					}
 | 
			
		||||
					w->attributes.at("\\init") = new_initval;
 | 
			
		||||
					w->attributes.at(ID(init)) = new_initval;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -528,23 +528,23 @@ struct WreducePass : public Pass {
 | 
			
		|||
 | 
			
		||||
			for (auto c : module->selected_cells())
 | 
			
		||||
			{
 | 
			
		||||
				if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
 | 
			
		||||
						"$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
 | 
			
		||||
						"$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) {
 | 
			
		||||
					SigSpec sig = c->getPort("\\Y");
 | 
			
		||||
				if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool),
 | 
			
		||||
						ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
 | 
			
		||||
						ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID(Y))) > 1) {
 | 
			
		||||
					SigSpec sig = c->getPort(ID(Y));
 | 
			
		||||
					if (!sig.has_const()) {
 | 
			
		||||
						c->setPort("\\Y", sig[0]);
 | 
			
		||||
						c->setParam("\\Y_WIDTH", 1);
 | 
			
		||||
						c->setPort(ID(Y), sig[0]);
 | 
			
		||||
						c->setParam(ID(Y_WIDTH), 1);
 | 
			
		||||
						sig.remove(0);
 | 
			
		||||
						module->connect(sig, Const(0, GetSize(sig)));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (c->type.in("$div", "$mod", "$pow"))
 | 
			
		||||
				if (c->type.in(ID($div), ID($mod), ID($pow)))
 | 
			
		||||
				{
 | 
			
		||||
					SigSpec A = c->getPort("\\A");
 | 
			
		||||
					SigSpec A = c->getPort(ID(A));
 | 
			
		||||
					int original_a_width = GetSize(A);
 | 
			
		||||
					if (c->getParam("\\A_SIGNED").as_bool()) {
 | 
			
		||||
					if (c->getParam(ID(A_SIGNED)).as_bool()) {
 | 
			
		||||
						while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0)
 | 
			
		||||
							A.remove(GetSize(A)-1, 1);
 | 
			
		||||
					} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -554,13 +554,13 @@ struct WreducePass : public Pass {
 | 
			
		|||
					if (original_a_width != GetSize(A)) {
 | 
			
		||||
						log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n",
 | 
			
		||||
								original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type));
 | 
			
		||||
						c->setPort("\\A", A);
 | 
			
		||||
						c->setParam("\\A_WIDTH", GetSize(A));
 | 
			
		||||
						c->setPort(ID(A), A);
 | 
			
		||||
						c->setParam(ID(A_WIDTH), GetSize(A));
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					SigSpec B = c->getPort("\\B");
 | 
			
		||||
					SigSpec B = c->getPort(ID(B));
 | 
			
		||||
					int original_b_width = GetSize(B);
 | 
			
		||||
					if (c->getParam("\\B_SIGNED").as_bool()) {
 | 
			
		||||
					if (c->getParam(ID(B_SIGNED)).as_bool()) {
 | 
			
		||||
						while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0)
 | 
			
		||||
							B.remove(GetSize(B)-1, 1);
 | 
			
		||||
					} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -570,24 +570,24 @@ struct WreducePass : public Pass {
 | 
			
		|||
					if (original_b_width != GetSize(B)) {
 | 
			
		||||
						log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n",
 | 
			
		||||
								original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type));
 | 
			
		||||
						c->setPort("\\B", B);
 | 
			
		||||
						c->setParam("\\B_WIDTH", GetSize(B));
 | 
			
		||||
						c->setPort(ID(B), B);
 | 
			
		||||
						c->setParam(ID(B_WIDTH), GetSize(B));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) {
 | 
			
		||||
					IdString memid = c->getParam("\\MEMID").decode_string();
 | 
			
		||||
				if (!opt_memx && c->type.in(ID($memrd), ID($memwr), ID($meminit))) {
 | 
			
		||||
					IdString memid = c->getParam(ID(MEMID)).decode_string();
 | 
			
		||||
					RTLIL::Memory *mem = module->memories.at(memid);
 | 
			
		||||
					if (mem->start_offset >= 0) {
 | 
			
		||||
						int cur_addrbits = c->getParam("\\ABITS").as_int();
 | 
			
		||||
						int cur_addrbits = c->getParam(ID(ABITS)).as_int();
 | 
			
		||||
						int max_addrbits = ceil_log2(mem->start_offset + mem->size);
 | 
			
		||||
						if (cur_addrbits > max_addrbits) {
 | 
			
		||||
							log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n",
 | 
			
		||||
									cur_addrbits-max_addrbits, cur_addrbits,
 | 
			
		||||
									c->type == "$memrd" ? "read" : c->type == "$memwr" ? "write" : "init",
 | 
			
		||||
									c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init",
 | 
			
		||||
									log_id(module), log_id(c), log_id(memid));
 | 
			
		||||
							c->setParam("\\ABITS", max_addrbits);
 | 
			
		||||
							c->setPort("\\ADDR", c->getPort("\\ADDR").extract(0, max_addrbits));
 | 
			
		||||
							c->setParam(ID(ABITS), max_addrbits);
 | 
			
		||||
							c->setPort(ID(ADDR), c->getPort(ID(ADDR)).extract(0, max_addrbits));
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -143,7 +143,7 @@ void create_dff_dq_map(std::map<RTLIL::IdString, dff_map_info_t> &map, RTLIL::De
 | 
			
		|||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (info.cell->type == "$_DFF_N_" || info.cell->type == "$_DFF_P_") {
 | 
			
		||||
		if (info.cell->type.in("$_DFF_N_", "$_DFF_P_")) {
 | 
			
		||||
			info.bit_clk = sigmap(info.cell->getPort("\\C")).as_bit();
 | 
			
		||||
			info.clk_polarity = info.cell->type == "$_DFF_P_";
 | 
			
		||||
			info.bit_d = sigmap(info.cell->getPort("\\D")).as_bit();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -166,39 +166,39 @@ void mark_port(RTLIL::SigSpec sig)
 | 
			
		|||
 | 
			
		||||
void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		||||
{
 | 
			
		||||
	if (cell->type.in("$_DFF_N_", "$_DFF_P_"))
 | 
			
		||||
	if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
 | 
			
		||||
	{
 | 
			
		||||
		if (clk_polarity != (cell->type == "$_DFF_P_"))
 | 
			
		||||
		if (clk_polarity != (cell->type == ID($_DFF_P_)))
 | 
			
		||||
			return;
 | 
			
		||||
		if (clk_sig != assign_map(cell->getPort("\\C")))
 | 
			
		||||
		if (clk_sig != assign_map(cell->getPort(ID(C))))
 | 
			
		||||
			return;
 | 
			
		||||
		if (GetSize(en_sig) != 0)
 | 
			
		||||
			return;
 | 
			
		||||
		goto matching_dff;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_"))
 | 
			
		||||
	if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
			
		||||
	{
 | 
			
		||||
		if (clk_polarity != cell->type.in("$_DFFE_PN_", "$_DFFE_PP_"))
 | 
			
		||||
		if (clk_polarity != cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
			
		||||
			return;
 | 
			
		||||
		if (en_polarity != cell->type.in("$_DFFE_NP_", "$_DFFE_PP_"))
 | 
			
		||||
		if (en_polarity != cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)))
 | 
			
		||||
			return;
 | 
			
		||||
		if (clk_sig != assign_map(cell->getPort("\\C")))
 | 
			
		||||
		if (clk_sig != assign_map(cell->getPort(ID(C))))
 | 
			
		||||
			return;
 | 
			
		||||
		if (en_sig != assign_map(cell->getPort("\\E")))
 | 
			
		||||
		if (en_sig != assign_map(cell->getPort(ID(E))))
 | 
			
		||||
			return;
 | 
			
		||||
		goto matching_dff;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (0) {
 | 
			
		||||
	matching_dff:
 | 
			
		||||
		RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
		RTLIL::SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
		RTLIL::SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
		RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
		if (keepff)
 | 
			
		||||
			for (auto &c : sig_q.chunks())
 | 
			
		||||
				if (c.wire != NULL)
 | 
			
		||||
					c.wire->attributes["\\keep"] = 1;
 | 
			
		||||
					c.wire->attributes[ID(keep)] = 1;
 | 
			
		||||
 | 
			
		||||
		assign_map.apply(sig_d);
 | 
			
		||||
		assign_map.apply(sig_q);
 | 
			
		||||
| 
						 | 
				
			
			@ -209,25 +209,25 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_BUF_", "$_NOT_"))
 | 
			
		||||
	if (cell->type.in(ID($_BUF_), ID($_NOT_)))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
		assign_map.apply(sig_a);
 | 
			
		||||
		assign_map.apply(sig_y);
 | 
			
		||||
 | 
			
		||||
		map_signal(sig_y, cell->type == "$_BUF_" ? G(BUF) : G(NOT), map_signal(sig_a));
 | 
			
		||||
		map_signal(sig_y, cell->type == ID($_BUF_) ? G(BUF) : G(NOT), map_signal(sig_a));
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
 | 
			
		||||
	if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_)))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
		assign_map.apply(sig_a);
 | 
			
		||||
		assign_map.apply(sig_b);
 | 
			
		||||
| 
						 | 
				
			
			@ -236,21 +236,21 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		int mapped_a = map_signal(sig_a);
 | 
			
		||||
		int mapped_b = map_signal(sig_b);
 | 
			
		||||
 | 
			
		||||
		if (cell->type == "$_AND_")
 | 
			
		||||
		if (cell->type == ID($_AND_))
 | 
			
		||||
			map_signal(sig_y, G(AND), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_NAND_")
 | 
			
		||||
		else if (cell->type == ID($_NAND_))
 | 
			
		||||
			map_signal(sig_y, G(NAND), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_OR_")
 | 
			
		||||
		else if (cell->type == ID($_OR_))
 | 
			
		||||
			map_signal(sig_y, G(OR), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_NOR_")
 | 
			
		||||
		else if (cell->type == ID($_NOR_))
 | 
			
		||||
			map_signal(sig_y, G(NOR), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_XOR_")
 | 
			
		||||
		else if (cell->type == ID($_XOR_))
 | 
			
		||||
			map_signal(sig_y, G(XOR), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_XNOR_")
 | 
			
		||||
		else if (cell->type == ID($_XNOR_))
 | 
			
		||||
			map_signal(sig_y, G(XNOR), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_ANDNOT_")
 | 
			
		||||
		else if (cell->type == ID($_ANDNOT_))
 | 
			
		||||
			map_signal(sig_y, G(ANDNOT), mapped_a, mapped_b);
 | 
			
		||||
		else if (cell->type == "$_ORNOT_")
 | 
			
		||||
		else if (cell->type == ID($_ORNOT_))
 | 
			
		||||
			map_signal(sig_y, G(ORNOT), mapped_a, mapped_b);
 | 
			
		||||
		else
 | 
			
		||||
			log_abort();
 | 
			
		||||
| 
						 | 
				
			
			@ -259,12 +259,12 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_MUX_", "$_NMUX_"))
 | 
			
		||||
	if (cell->type.in(ID($_MUX_), ID($_NMUX_)))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
		RTLIL::SigSpec sig_s = cell->getPort("\\S");
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
		RTLIL::SigSpec sig_s = cell->getPort(ID(S));
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
		assign_map.apply(sig_a);
 | 
			
		||||
		assign_map.apply(sig_b);
 | 
			
		||||
| 
						 | 
				
			
			@ -275,18 +275,18 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		int mapped_b = map_signal(sig_b);
 | 
			
		||||
		int mapped_s = map_signal(sig_s);
 | 
			
		||||
 | 
			
		||||
		map_signal(sig_y, cell->type == "$_MUX_" ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s);
 | 
			
		||||
		map_signal(sig_y, cell->type == ID($_MUX_) ? G(MUX) : G(NMUX), mapped_a, mapped_b, mapped_s);
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_AOI3_", "$_OAI3_"))
 | 
			
		||||
	if (cell->type.in(ID($_AOI3_), ID($_OAI3_)))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
		RTLIL::SigSpec sig_c = cell->getPort("\\C");
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
		RTLIL::SigSpec sig_c = cell->getPort(ID(C));
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
		assign_map.apply(sig_a);
 | 
			
		||||
		assign_map.apply(sig_b);
 | 
			
		||||
| 
						 | 
				
			
			@ -297,19 +297,19 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		int mapped_b = map_signal(sig_b);
 | 
			
		||||
		int mapped_c = map_signal(sig_c);
 | 
			
		||||
 | 
			
		||||
		map_signal(sig_y, cell->type == "$_AOI3_" ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c);
 | 
			
		||||
		map_signal(sig_y, cell->type == ID($_AOI3_) ? G(AOI3) : G(OAI3), mapped_a, mapped_b, mapped_c);
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_AOI4_", "$_OAI4_"))
 | 
			
		||||
	if (cell->type.in(ID($_AOI4_), ID($_OAI4_)))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
		RTLIL::SigSpec sig_c = cell->getPort("\\C");
 | 
			
		||||
		RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
		RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
		RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
		RTLIL::SigSpec sig_c = cell->getPort(ID(C));
 | 
			
		||||
		RTLIL::SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
		RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
		assign_map.apply(sig_a);
 | 
			
		||||
		assign_map.apply(sig_b);
 | 
			
		||||
| 
						 | 
				
			
			@ -322,7 +322,7 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
 | 
			
		|||
		int mapped_c = map_signal(sig_c);
 | 
			
		||||
		int mapped_d = map_signal(sig_d);
 | 
			
		||||
 | 
			
		||||
		map_signal(sig_y, cell->type == "$_AOI4_" ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d);
 | 
			
		||||
		map_signal(sig_y, cell->type == ID($_AOI4_) ? G(AOI4) : G(OAI4), mapped_a, mapped_b, mapped_c, mapped_d);
 | 
			
		||||
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -352,23 +352,20 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp
 | 
			
		|||
				auto sig = signal_list.at(sid);
 | 
			
		||||
				if (sig.bit.wire != nullptr)
 | 
			
		||||
				{
 | 
			
		||||
					std::stringstream sstr;
 | 
			
		||||
					sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1);
 | 
			
		||||
					std::string s = stringf("$abc$%d$%s", map_autoidx, sig.bit.wire->name.c_str()+1);
 | 
			
		||||
					if (sig.bit.wire->width != 1)
 | 
			
		||||
						sstr << "[" << sig.bit.offset << "]";
 | 
			
		||||
						s += stringf("[%d]", sig.bit.offset);
 | 
			
		||||
					if (isnew)
 | 
			
		||||
						sstr << "_new";
 | 
			
		||||
					sstr << postfix;
 | 
			
		||||
						s += "_new";
 | 
			
		||||
					s += postfix;
 | 
			
		||||
					if (orig_wire != nullptr)
 | 
			
		||||
						*orig_wire = sig.bit.wire;
 | 
			
		||||
					return sstr.str();
 | 
			
		||||
					return s;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	std::stringstream sstr;
 | 
			
		||||
	sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1);
 | 
			
		||||
	return sstr.str();
 | 
			
		||||
	return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edges, std::set<int> &workpool, std::vector<int> &in_counts)
 | 
			
		||||
| 
						 | 
				
			
			@ -790,7 +787,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 | 
			
		|||
		extract_cell(c, keepff);
 | 
			
		||||
 | 
			
		||||
	for (auto &wire_it : module->wires_) {
 | 
			
		||||
		if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute("\\keep"))
 | 
			
		||||
		if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute(ID(keep)))
 | 
			
		||||
			mark_port(RTLIL::SigSpec(wire_it.second));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -939,42 +936,42 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 | 
			
		|||
			log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
 | 
			
		||||
		fprintf(f, "GATE ZERO    1 Y=CONST0;\n");
 | 
			
		||||
		fprintf(f, "GATE ONE     1 Y=CONST1;\n");
 | 
			
		||||
		fprintf(f, "GATE BUF    %d Y=A;                  PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_BUF_"));
 | 
			
		||||
		fprintf(f, "GATE NOT    %d Y=!A;                 PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NOT_"));
 | 
			
		||||
		fprintf(f, "GATE BUF    %d Y=A;                  PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at(ID($_BUF_)));
 | 
			
		||||
		fprintf(f, "GATE NOT    %d Y=!A;                 PIN * INV     1 999 1 0 1 0\n", cell_cost.at(ID($_NOT_)));
 | 
			
		||||
		if (enabled_gates.count("AND"))
 | 
			
		||||
			fprintf(f, "GATE AND    %d Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_AND_"));
 | 
			
		||||
			fprintf(f, "GATE AND    %d Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at(ID($_AND_)));
 | 
			
		||||
		if (enabled_gates.count("NAND"))
 | 
			
		||||
			fprintf(f, "GATE NAND   %d Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NAND_"));
 | 
			
		||||
			fprintf(f, "GATE NAND   %d Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n", cell_cost.at(ID($_NAND_)));
 | 
			
		||||
		if (enabled_gates.count("OR"))
 | 
			
		||||
			fprintf(f, "GATE OR     %d Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_OR_"));
 | 
			
		||||
			fprintf(f, "GATE OR     %d Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at(ID($_OR_)));
 | 
			
		||||
		if (enabled_gates.count("NOR"))
 | 
			
		||||
			fprintf(f, "GATE NOR    %d Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NOR_"));
 | 
			
		||||
			fprintf(f, "GATE NOR    %d Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n", cell_cost.at(ID($_NOR_)));
 | 
			
		||||
		if (enabled_gates.count("XOR"))
 | 
			
		||||
			fprintf(f, "GATE XOR    %d Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_"));
 | 
			
		||||
			fprintf(f, "GATE XOR    %d Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XOR_)));
 | 
			
		||||
		if (enabled_gates.count("XNOR"))
 | 
			
		||||
			fprintf(f, "GATE XNOR   %d Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_"));
 | 
			
		||||
			fprintf(f, "GATE XNOR   %d Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XNOR_)));
 | 
			
		||||
		if (enabled_gates.count("ANDNOT"))
 | 
			
		||||
			fprintf(f, "GATE ANDNOT %d Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_"));
 | 
			
		||||
			fprintf(f, "GATE ANDNOT %d Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ANDNOT_)));
 | 
			
		||||
		if (enabled_gates.count("ORNOT"))
 | 
			
		||||
			fprintf(f, "GATE ORNOT  %d Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_"));
 | 
			
		||||
			fprintf(f, "GATE ORNOT  %d Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ORNOT_)));
 | 
			
		||||
		if (enabled_gates.count("AOI3"))
 | 
			
		||||
			fprintf(f, "GATE AOI3   %d Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_AOI3_"));
 | 
			
		||||
			fprintf(f, "GATE AOI3   %d Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n", cell_cost.at(ID($_AOI3_)));
 | 
			
		||||
		if (enabled_gates.count("OAI3"))
 | 
			
		||||
			fprintf(f, "GATE OAI3   %d Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_OAI3_"));
 | 
			
		||||
			fprintf(f, "GATE OAI3   %d Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n", cell_cost.at(ID($_OAI3_)));
 | 
			
		||||
		if (enabled_gates.count("AOI4"))
 | 
			
		||||
			fprintf(f, "GATE AOI4   %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_AOI4_"));
 | 
			
		||||
			fprintf(f, "GATE AOI4   %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", cell_cost.at(ID($_AOI4_)));
 | 
			
		||||
		if (enabled_gates.count("OAI4"))
 | 
			
		||||
			fprintf(f, "GATE OAI4   %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_OAI4_"));
 | 
			
		||||
			fprintf(f, "GATE OAI4   %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", cell_cost.at(ID($_OAI4_)));
 | 
			
		||||
		if (enabled_gates.count("MUX"))
 | 
			
		||||
			fprintf(f, "GATE MUX    %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_"));
 | 
			
		||||
			fprintf(f, "GATE MUX    %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_MUX_)));
 | 
			
		||||
		if (enabled_gates.count("NMUX"))
 | 
			
		||||
			fprintf(f, "GATE NMUX   %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_"));
 | 
			
		||||
			fprintf(f, "GATE NMUX   %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_NMUX_)));
 | 
			
		||||
		if (map_mux4)
 | 
			
		||||
			fprintf(f, "GATE MUX4   %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at("$_MUX_"));
 | 
			
		||||
			fprintf(f, "GATE MUX4   %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at(ID($_MUX_)));
 | 
			
		||||
		if (map_mux8)
 | 
			
		||||
			fprintf(f, "GATE MUX8   %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at("$_MUX_"));
 | 
			
		||||
			fprintf(f, "GATE MUX8   %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at(ID($_MUX_)));
 | 
			
		||||
		if (map_mux16)
 | 
			
		||||
			fprintf(f, "GATE MUX16  %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at("$_MUX_"));
 | 
			
		||||
			fprintf(f, "GATE MUX16  %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at(ID($_MUX_)));
 | 
			
		||||
		fclose(f);
 | 
			
		||||
 | 
			
		||||
		if (!lut_costs.empty()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1019,21 +1016,21 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 | 
			
		|||
 | 
			
		||||
		bool builtin_lib = liberty_file.empty();
 | 
			
		||||
		RTLIL::Design *mapped_design = new RTLIL::Design;
 | 
			
		||||
		parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
 | 
			
		||||
		parse_blif(mapped_design, ifs, builtin_lib ? ID(DFF) : ID(_dff_), false, sop_mode);
 | 
			
		||||
 | 
			
		||||
		ifs.close();
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Re-integrating ABC results.\n");
 | 
			
		||||
		RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"];
 | 
			
		||||
		RTLIL::Module *mapped_mod = mapped_design->modules_[ID(netlist)];
 | 
			
		||||
		if (mapped_mod == NULL)
 | 
			
		||||
			log_error("ABC output file does not contain a module `netlist'.\n");
 | 
			
		||||
		for (auto &it : mapped_mod->wires_) {
 | 
			
		||||
			RTLIL::Wire *w = it.second;
 | 
			
		||||
			RTLIL::Wire *orig_wire = nullptr;
 | 
			
		||||
			RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire));
 | 
			
		||||
			if (orig_wire != nullptr && orig_wire->attributes.count("\\src"))
 | 
			
		||||
				wire->attributes["\\src"] = orig_wire->attributes["\\src"];
 | 
			
		||||
			if (markgroups) wire->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
			if (orig_wire != nullptr && orig_wire->attributes.count(ID(src)))
 | 
			
		||||
				wire->attributes[ID(src)] = orig_wire->attributes[ID(src)];
 | 
			
		||||
			if (markgroups) wire->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
			design->select(module, wire);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1043,141 +1040,140 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 | 
			
		|||
			if (builtin_lib)
 | 
			
		||||
			{
 | 
			
		||||
				cell_stats[RTLIL::unescape_id(c->type)]++;
 | 
			
		||||
				if (c->type == "\\ZERO" || c->type == "\\ONE") {
 | 
			
		||||
				if (c->type.in(ID(ZERO), ID(ONE))) {
 | 
			
		||||
					RTLIL::SigSig conn;
 | 
			
		||||
					conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]);
 | 
			
		||||
					conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1);
 | 
			
		||||
					conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]);
 | 
			
		||||
					conn.second = RTLIL::SigSpec(c->type == ID(ZERO) ? 0 : 1, 1);
 | 
			
		||||
					module->connect(conn);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\BUF") {
 | 
			
		||||
				if (c->type == ID(BUF)) {
 | 
			
		||||
					RTLIL::SigSig conn;
 | 
			
		||||
					conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]);
 | 
			
		||||
					conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]);
 | 
			
		||||
					conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]);
 | 
			
		||||
					conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]);
 | 
			
		||||
					module->connect(conn);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\NOT") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_NOT_");
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
				if (c->type == ID(NOT)) {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_NOT_));
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" ||
 | 
			
		||||
						c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\ORNOT") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
				if (c->type.in(ID(AND), ID(OR), ID(XOR), ID(NAND), ID(NOR), ID(XNOR), ID(ANDNOT), ID(ORNOT))) {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\MUX" || c->type == "\\NMUX") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
				if (c->type.in(ID(MUX), ID(NMUX))) {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\MUX4") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX4_");
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
				if (c->type == ID(MUX4)) {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX4_));
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\MUX8") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX8_");
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
				if (c->type == ID(MUX8)) {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX8_));
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(F), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(F)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(G), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(G)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(H), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(H)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\MUX16") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX16_");
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\I", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\I").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\J", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\J").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\K", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\K").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\L", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\L").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\M", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\M").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\N", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\N").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\O", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\O").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\P", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\P").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
				if (c->type == ID(MUX16)) {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX16_));
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(E), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(E)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(F), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(F)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(G), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(G)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(H), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(H)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(I), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(I)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(J), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(J)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(K), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(K)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(L), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(L)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(M), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(M)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(N), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(N)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(O), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(O)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(P), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(P)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(S), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(S)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(T), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(T)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(U), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(U)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(V), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(V)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\AOI3" || c->type == "\\OAI3") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
				if (c->type.in(ID(AOI3), ID(OAI3))) {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\AOI4" || c->type == "\\OAI4") {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
 | 
			
		||||
				if (c->type.in(ID(AOI4), ID(OAI4))) {
 | 
			
		||||
					RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1));
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(A), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(B), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(B)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(C), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(C)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Y), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)]));
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (c->type == "\\DFF") {
 | 
			
		||||
				if (c->type == ID(DFF)) {
 | 
			
		||||
					log_assert(clk_sig.size() == 1);
 | 
			
		||||
					RTLIL::Cell *cell;
 | 
			
		||||
					if (en_sig.size() == 0) {
 | 
			
		||||
						cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
 | 
			
		||||
						cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_));
 | 
			
		||||
					} else {
 | 
			
		||||
						log_assert(en_sig.size() == 1);
 | 
			
		||||
						cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
 | 
			
		||||
						cell->setPort("\\E", en_sig);
 | 
			
		||||
						cell->setPort(ID(E), en_sig);
 | 
			
		||||
					}
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
 | 
			
		||||
					cell->setPort("\\C", clk_sig);
 | 
			
		||||
					if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(Q), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Q)).as_wire()->name)]));
 | 
			
		||||
					cell->setPort(ID(C), clk_sig);
 | 
			
		||||
					design->select(module, cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -1185,41 +1181,41 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 | 
			
		|||
			else
 | 
			
		||||
				cell_stats[RTLIL::unescape_id(c->type)]++;
 | 
			
		||||
 | 
			
		||||
			if (c->type == "\\_const0_" || c->type == "\\_const1_") {
 | 
			
		||||
			if (c->type.in(ID(_const0_), ID(_const1_))) {
 | 
			
		||||
				RTLIL::SigSig conn;
 | 
			
		||||
				conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]);
 | 
			
		||||
				conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1);
 | 
			
		||||
				conn.second = RTLIL::SigSpec(c->type == ID(_const0_) ? 0 : 1, 1);
 | 
			
		||||
				module->connect(conn);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (c->type == "\\_dff_") {
 | 
			
		||||
			if (c->type == ID(_dff_)) {
 | 
			
		||||
				log_assert(clk_sig.size() == 1);
 | 
			
		||||
				RTLIL::Cell *cell;
 | 
			
		||||
				if (en_sig.size() == 0) {
 | 
			
		||||
					cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
 | 
			
		||||
					cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_));
 | 
			
		||||
				} else {
 | 
			
		||||
					log_assert(en_sig.size() == 1);
 | 
			
		||||
					cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
 | 
			
		||||
					cell->setPort("\\E", en_sig);
 | 
			
		||||
					cell->setPort(ID(E), en_sig);
 | 
			
		||||
				}
 | 
			
		||||
				if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
				cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
 | 
			
		||||
				cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
 | 
			
		||||
				cell->setPort("\\C", clk_sig);
 | 
			
		||||
				if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
				cell->setPort(ID(D), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(D)).as_wire()->name)]));
 | 
			
		||||
				cell->setPort(ID(Q), RTLIL::SigSpec(module->wires_[remap_name(c->getPort(ID(Q)).as_wire()->name)]));
 | 
			
		||||
				cell->setPort(ID(C), clk_sig);
 | 
			
		||||
				design->select(module, cell);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
 | 
			
		||||
				SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)];
 | 
			
		||||
				SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)];
 | 
			
		||||
			if (c->type == ID($lut) && GetSize(c->getPort(ID(A))) == 1 && c->getParam(ID(LUT)).as_int() == 2) {
 | 
			
		||||
				SigSpec my_a = module->wires_[remap_name(c->getPort(ID(A)).as_wire()->name)];
 | 
			
		||||
				SigSpec my_y = module->wires_[remap_name(c->getPort(ID(Y)).as_wire()->name)];
 | 
			
		||||
				module->connect(my_y, my_a);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type);
 | 
			
		||||
			if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
			if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
			cell->parameters = c->parameters;
 | 
			
		||||
			for (auto &conn : c->connections()) {
 | 
			
		||||
				RTLIL::SigSpec newsig;
 | 
			
		||||
| 
						 | 
				
			
			@ -1244,10 +1240,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 | 
			
		|||
 | 
			
		||||
		if (recover_init)
 | 
			
		||||
			for (auto wire : mapped_mod->wires()) {
 | 
			
		||||
				if (wire->attributes.count("\\init")) {
 | 
			
		||||
				if (wire->attributes.count(ID(init))) {
 | 
			
		||||
					Wire *w = module->wires_[remap_name(wire->name)];
 | 
			
		||||
					log_assert(w->attributes.count("\\init") == 0);
 | 
			
		||||
					w->attributes["\\init"] = wire->attributes.at("\\init");
 | 
			
		||||
					log_assert(w->attributes.count(ID(init)) == 0);
 | 
			
		||||
					w->attributes[ID(init)] = wire->attributes.at(ID(init));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1634,6 +1630,7 @@ struct AbcPass : public Pass {
 | 
			
		|||
					if (g == "ANDNOT") goto ok_gate;
 | 
			
		||||
					if (g == "ORNOT") goto ok_gate;
 | 
			
		||||
					if (g == "MUX") goto ok_gate;
 | 
			
		||||
					if (g == "NMUX") goto ok_gate;
 | 
			
		||||
					if (g == "AOI3") goto ok_gate;
 | 
			
		||||
					if (g == "OAI3") goto ok_gate;
 | 
			
		||||
					if (g == "AOI4") goto ok_gate;
 | 
			
		||||
| 
						 | 
				
			
			@ -1802,9 +1799,9 @@ struct AbcPass : public Pass {
 | 
			
		|||
			signal_init.clear();
 | 
			
		||||
 | 
			
		||||
			for (Wire *wire : mod->wires())
 | 
			
		||||
				if (wire->attributes.count("\\init")) {
 | 
			
		||||
				if (wire->attributes.count(ID(init))) {
 | 
			
		||||
					SigSpec initsig = assign_map(wire);
 | 
			
		||||
					Const initval = wire->attributes.at("\\init");
 | 
			
		||||
					Const initval = wire->attributes.at(ID(init));
 | 
			
		||||
					for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
 | 
			
		||||
						switch (initval[i]) {
 | 
			
		||||
							case State::S0:
 | 
			
		||||
| 
						 | 
				
			
			@ -1861,16 +1858,16 @@ struct AbcPass : public Pass {
 | 
			
		|||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (cell->type.in("$_DFF_N_", "$_DFF_P_"))
 | 
			
		||||
				if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
 | 
			
		||||
				{
 | 
			
		||||
					key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec());
 | 
			
		||||
					key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				if (cell->type.in("$_DFFE_NN_", "$_DFFE_NP_" "$_DFFE_PN_", "$_DFFE_PP_"))
 | 
			
		||||
				if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
			
		||||
				{
 | 
			
		||||
					bool this_clk_pol = cell->type.in("$_DFFE_PN_", "$_DFFE_PP_");
 | 
			
		||||
					bool this_en_pol = cell->type.in("$_DFFE_NP_", "$_DFFE_PP_");
 | 
			
		||||
					key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E")));
 | 
			
		||||
					bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
 | 
			
		||||
					bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
 | 
			
		||||
					key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E))));
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,11 +71,9 @@ RTLIL::Module *module;
 | 
			
		|||
bool clk_polarity, en_polarity;
 | 
			
		||||
RTLIL::SigSpec clk_sig, en_sig;
 | 
			
		||||
 | 
			
		||||
std::string remap_name(RTLIL::IdString abc_name)
 | 
			
		||||
inline std::string remap_name(RTLIL::IdString abc_name)
 | 
			
		||||
{
 | 
			
		||||
	std::stringstream sstr;
 | 
			
		||||
	sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1);
 | 
			
		||||
	return sstr.str();
 | 
			
		||||
	return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void handle_loops(RTLIL::Design *design)
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +87,7 @@ void handle_loops(RTLIL::Design *design)
 | 
			
		|||
	// wires
 | 
			
		||||
	pool<RTLIL::Const> ids_seen;
 | 
			
		||||
	for (auto cell : module->cells()) {
 | 
			
		||||
		auto it = cell->attributes.find("\\abc_scc_id");
 | 
			
		||||
		auto it = cell->attributes.find(ID(abc_scc_id));
 | 
			
		||||
		if (it != cell->attributes.end()) {
 | 
			
		||||
			auto r = ids_seen.insert(it->second);
 | 
			
		||||
			if (r.second) {
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +107,7 @@ void handle_loops(RTLIL::Design *design)
 | 
			
		|||
							log_assert(w->port_input);
 | 
			
		||||
							log_assert(b.offset < GetSize(w));
 | 
			
		||||
						}
 | 
			
		||||
						w->set_bool_attribute("\\abc_scc_break");
 | 
			
		||||
						w->set_bool_attribute(ID(abc_scc_break));
 | 
			
		||||
						module->swap_names(b.wire, w);
 | 
			
		||||
						c.second = RTLIL::SigBit(w, b.offset);
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +121,7 @@ void handle_loops(RTLIL::Design *design)
 | 
			
		|||
			std::vector<IdString> ports;
 | 
			
		||||
			RTLIL::Module* box_module = design->module(cell->type);
 | 
			
		||||
			if (box_module) {
 | 
			
		||||
				auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string();
 | 
			
		||||
				auto ports_csv = box_module->attributes.at(ID(abc_scc_break), RTLIL::Const::from_string("")).decode_string();
 | 
			
		||||
				for (const auto &port_name : split_tokens(ports_csv, ",")) {
 | 
			
		||||
					auto port_id = RTLIL::escape_id(port_name);
 | 
			
		||||
					auto kt = cell->connections_.find(port_id);
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +140,7 @@ void handle_loops(RTLIL::Design *design)
 | 
			
		|||
				Wire *w = b.wire;
 | 
			
		||||
				if (!w) continue;
 | 
			
		||||
				w->port_output = true;
 | 
			
		||||
				w->set_bool_attribute("\\abc_scc_break");
 | 
			
		||||
				w->set_bool_attribute(ID(abc_scc_break));
 | 
			
		||||
				w = module->wire(stringf("%s.abci", w->name.c_str()));
 | 
			
		||||
				if (!w) {
 | 
			
		||||
					w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire));
 | 
			
		||||
| 
						 | 
				
			
			@ -446,14 +444,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		if (ifs.fail())
 | 
			
		||||
			log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
 | 
			
		||||
		buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
 | 
			
		||||
		log_assert(!design->module("$__abc9__"));
 | 
			
		||||
		log_assert(!design->module(ID($__abc9__)));
 | 
			
		||||
		{
 | 
			
		||||
			AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
 | 
			
		||||
			AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
 | 
			
		||||
			reader.parse_xaiger();
 | 
			
		||||
		}
 | 
			
		||||
		ifs.close();
 | 
			
		||||
		Pass::call(design, stringf("write_verilog -noexpr -norename"));
 | 
			
		||||
		design->remove(design->module("$__abc9__"));
 | 
			
		||||
		design->remove(design->module(ID($__abc9__)));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		design->selection_stack.pop_back();
 | 
			
		||||
| 
						 | 
				
			
			@ -462,7 +460,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		// the expose operation -- remove them from PO/PI
 | 
			
		||||
		// and re-connecting them back together
 | 
			
		||||
		for (auto wire : module->wires()) {
 | 
			
		||||
			auto it = wire->attributes.find("\\abc_scc_break");
 | 
			
		||||
			auto it = wire->attributes.find(ID(abc_scc_break));
 | 
			
		||||
			if (it != wire->attributes.end()) {
 | 
			
		||||
				wire->attributes.erase(it);
 | 
			
		||||
				log_assert(wire->port_output);
 | 
			
		||||
| 
						 | 
				
			
			@ -518,9 +516,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
			log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
 | 
			
		||||
 | 
			
		||||
		buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
 | 
			
		||||
		log_assert(!design->module("$__abc9__"));
 | 
			
		||||
		log_assert(!design->module(ID($__abc9__)));
 | 
			
		||||
 | 
			
		||||
		AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
 | 
			
		||||
		AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
 | 
			
		||||
		reader.parse_xaiger(box_lookup);
 | 
			
		||||
		ifs.close();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -529,7 +527,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Re-integrating ABC9 results.\n");
 | 
			
		||||
		RTLIL::Module *mapped_mod = design->module("$__abc9__");
 | 
			
		||||
		RTLIL::Module *mapped_mod = design->module(ID($__abc9__));
 | 
			
		||||
		if (mapped_mod == NULL)
 | 
			
		||||
			log_error("ABC output file does not contain a module `$__abc9__'.\n");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -537,7 +535,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		for (auto &it : mapped_mod->wires_) {
 | 
			
		||||
			RTLIL::Wire *w = it.second;
 | 
			
		||||
			RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w));
 | 
			
		||||
			if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
			if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
			if (w->port_output) {
 | 
			
		||||
				RTLIL::Wire *wire = module->wire(w->name);
 | 
			
		||||
				log_assert(wire);
 | 
			
		||||
| 
						 | 
				
			
			@ -559,14 +557,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		vector<RTLIL::Cell*> boxes;
 | 
			
		||||
		for (const auto &it : module->cells_) {
 | 
			
		||||
			auto cell = it.second;
 | 
			
		||||
			if (cell->type.in("$_AND_", "$_NOT_")) {
 | 
			
		||||
			if (cell->type.in(ID($_AND_), ID($_NOT_))) {
 | 
			
		||||
				module->remove(cell);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			auto jt = abc_box.find(cell->type);
 | 
			
		||||
			if (jt == abc_box.end()) {
 | 
			
		||||
				RTLIL::Module* box_module = design->module(cell->type);
 | 
			
		||||
				jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count("\\abc_box_id"))).first;
 | 
			
		||||
				jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc_box_id)))).first;
 | 
			
		||||
			}
 | 
			
		||||
			if (jt->second)
 | 
			
		||||
				boxes.emplace_back(cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -577,20 +575,20 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		dict<RTLIL::Cell*,RTLIL::Cell*> not2drivers;
 | 
			
		||||
		dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks;
 | 
			
		||||
 | 
			
		||||
		std::map<std::string, int> cell_stats;
 | 
			
		||||
		std::map<IdString, int> cell_stats;
 | 
			
		||||
		for (auto c : mapped_mod->cells())
 | 
			
		||||
		{
 | 
			
		||||
			toposort.node(c->name);
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *cell = nullptr;
 | 
			
		||||
			if (c->type == "$_NOT_") {
 | 
			
		||||
				RTLIL::SigBit a_bit = c->getPort("\\A");
 | 
			
		||||
				RTLIL::SigBit y_bit = c->getPort("\\Y");
 | 
			
		||||
			if (c->type == ID($_NOT_)) {
 | 
			
		||||
				RTLIL::SigBit a_bit = c->getPort(ID(A));
 | 
			
		||||
				RTLIL::SigBit y_bit = c->getPort(ID(Y));
 | 
			
		||||
				bit_users[a_bit].insert(c->name);
 | 
			
		||||
				bit_drivers[y_bit].insert(c->name);
 | 
			
		||||
 | 
			
		||||
				if (!a_bit.wire) {
 | 
			
		||||
					c->setPort("\\Y", module->addWire(NEW_ID));
 | 
			
		||||
					c->setPort(ID(Y), module->addWire(NEW_ID));
 | 
			
		||||
					RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
 | 
			
		||||
					log_assert(wire);
 | 
			
		||||
					module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1);
 | 
			
		||||
| 
						 | 
				
			
			@ -618,8 +616,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
								RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
 | 
			
		||||
								RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
 | 
			
		||||
								RTLIL::Const::from_string("01"));
 | 
			
		||||
						bit2sinks[cell->getPort("\\A")].push_back(cell);
 | 
			
		||||
						cell_stats["$lut"]++;
 | 
			
		||||
						bit2sinks[cell->getPort(ID(A))].push_back(cell);
 | 
			
		||||
						cell_stats[ID($lut)]++;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
						not2drivers[c] = driver_lut;
 | 
			
		||||
| 
						 | 
				
			
			@ -627,18 +625,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
				}
 | 
			
		||||
				else
 | 
			
		||||
					log_abort();
 | 
			
		||||
				if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
				if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			cell_stats[RTLIL::unescape_id(c->type)]++;
 | 
			
		||||
			cell_stats[c->type]++;
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *existing_cell = nullptr;
 | 
			
		||||
			if (c->type == "$lut") {
 | 
			
		||||
				if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT") == RTLIL::Const::from_string("01")) {
 | 
			
		||||
					SigSpec my_a = module->wires_.at(remap_name(c->getPort("\\A").as_wire()->name));
 | 
			
		||||
					SigSpec my_y = module->wires_.at(remap_name(c->getPort("\\Y").as_wire()->name));
 | 
			
		||||
			if (c->type == ID($lut)) {
 | 
			
		||||
				if (GetSize(c->getPort(ID(A))) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) {
 | 
			
		||||
					SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID(A)).as_wire()->name));
 | 
			
		||||
					SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID(Y)).as_wire()->name));
 | 
			
		||||
					module->connect(my_y, my_a);
 | 
			
		||||
					if (markgroups) c->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
					log_abort();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -651,7 +649,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
				module->swap_names(cell, existing_cell);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
			if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
 | 
			
		||||
			if (existing_cell) {
 | 
			
		||||
				cell->parameters = existing_cell->parameters;
 | 
			
		||||
				cell->attributes = existing_cell->attributes;
 | 
			
		||||
| 
						 | 
				
			
			@ -747,14 +745,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
 | 
			
		||||
			RTLIL::Cell *not_cell = mapped_mod->cell(*ii);
 | 
			
		||||
			log_assert(not_cell);
 | 
			
		||||
			if (not_cell->type != "$_NOT_")
 | 
			
		||||
			if (not_cell->type != ID($_NOT_))
 | 
			
		||||
				continue;
 | 
			
		||||
			auto it = not2drivers.find(not_cell);
 | 
			
		||||
			if (it == not2drivers.end())
 | 
			
		||||
				continue;
 | 
			
		||||
			RTLIL::Cell *driver_lut = it->second;
 | 
			
		||||
			RTLIL::SigBit a_bit = not_cell->getPort("\\A");
 | 
			
		||||
			RTLIL::SigBit y_bit = not_cell->getPort("\\Y");
 | 
			
		||||
			RTLIL::SigBit a_bit = not_cell->getPort(ID(A));
 | 
			
		||||
			RTLIL::SigBit y_bit = not_cell->getPort(ID(Y));
 | 
			
		||||
			RTLIL::Const driver_mask;
 | 
			
		||||
 | 
			
		||||
			a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
 | 
			
		||||
| 
						 | 
				
			
			@ -765,13 +763,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
				goto clone_lut;
 | 
			
		||||
 | 
			
		||||
			for (auto sink_cell : jt->second)
 | 
			
		||||
				if (sink_cell->type != "$lut")
 | 
			
		||||
				if (sink_cell->type != ID($lut))
 | 
			
		||||
					goto clone_lut;
 | 
			
		||||
 | 
			
		||||
			// Push downstream LUTs past inverter
 | 
			
		||||
			for (auto sink_cell : jt->second) {
 | 
			
		||||
				SigSpec A = sink_cell->getPort("\\A");
 | 
			
		||||
				RTLIL::Const mask = sink_cell->getParam("\\LUT");
 | 
			
		||||
				SigSpec A = sink_cell->getPort(ID(A));
 | 
			
		||||
				RTLIL::Const mask = sink_cell->getParam(ID(LUT));
 | 
			
		||||
				int index = 0;
 | 
			
		||||
				for (; index < GetSize(A); index++)
 | 
			
		||||
					if (A[index] == a_bit)
 | 
			
		||||
| 
						 | 
				
			
			@ -784,8 +782,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
					i += 1 << (index+1);
 | 
			
		||||
				}
 | 
			
		||||
				A[index] = y_bit;
 | 
			
		||||
				sink_cell->setPort("\\A", A);
 | 
			
		||||
				sink_cell->setParam("\\LUT", mask);
 | 
			
		||||
				sink_cell->setPort(ID(A), A);
 | 
			
		||||
				sink_cell->setParam(ID(LUT), mask);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Since we have rewritten all sinks (which we know
 | 
			
		||||
| 
						 | 
				
			
			@ -794,16 +792,16 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
			// that the original driving LUT will become dangling
 | 
			
		||||
			// and get cleaned away
 | 
			
		||||
clone_lut:
 | 
			
		||||
			driver_mask = driver_lut->getParam("\\LUT");
 | 
			
		||||
			driver_mask = driver_lut->getParam(ID(LUT));
 | 
			
		||||
			for (auto &b : driver_mask.bits) {
 | 
			
		||||
				if (b == RTLIL::State::S0) b = RTLIL::State::S1;
 | 
			
		||||
				else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
 | 
			
		||||
			}
 | 
			
		||||
			auto cell = module->addLut(NEW_ID,
 | 
			
		||||
					driver_lut->getPort("\\A"),
 | 
			
		||||
					driver_lut->getPort(ID(A)),
 | 
			
		||||
					y_bit,
 | 
			
		||||
					driver_mask);
 | 
			
		||||
			for (auto &bit : cell->connections_.at("\\A")) {
 | 
			
		||||
			for (auto &bit : cell->connections_.at(ID(A))) {
 | 
			
		||||
				bit.wire = module->wires_.at(remap_name(bit.wire->name));
 | 
			
		||||
				bit2sinks[bit].push_back(cell);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -1084,7 +1082,7 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
 | 
			
		||||
		dict<int,IdString> box_lookup;
 | 
			
		||||
		for (auto m : design->modules()) {
 | 
			
		||||
			auto it = m->attributes.find("\\abc_box_id");
 | 
			
		||||
			auto it = m->attributes.find(ID(abc_box_id));
 | 
			
		||||
			if (it == m->attributes.end())
 | 
			
		||||
				continue;
 | 
			
		||||
			if (m->name.begins_with("$paramod"))
 | 
			
		||||
| 
						 | 
				
			
			@ -1099,7 +1097,7 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
 | 
			
		||||
		for (auto mod : design->selected_modules())
 | 
			
		||||
		{
 | 
			
		||||
			if (mod->attributes.count("\\abc_box_id"))
 | 
			
		||||
			if (mod->attributes.count(ID(abc_box_id)))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (mod->processes.size() > 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1153,16 +1151,16 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (cell->type.in("$_DFF_N_", "$_DFF_P_"))
 | 
			
		||||
				if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
 | 
			
		||||
				{
 | 
			
		||||
					key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec());
 | 
			
		||||
					key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID(C))), true, RTLIL::SigSpec());
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				if (cell->type.in("$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_"))
 | 
			
		||||
				if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
 | 
			
		||||
				{
 | 
			
		||||
					bool this_clk_pol = cell->type.in("$_DFFE_PN_", "$_DFFE_PP_");
 | 
			
		||||
					bool this_en_pol = cell->type.in("$_DFFE_NP_", "$_DFFE_PP_");
 | 
			
		||||
					key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E")));
 | 
			
		||||
					bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
 | 
			
		||||
					bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
 | 
			
		||||
					key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID(C))), this_en_pol, assign_map(cell->getPort(ID(E))));
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,10 +66,10 @@ struct AigmapPass : public Pass {
 | 
			
		|||
			{
 | 
			
		||||
				Aig aig(cell);
 | 
			
		||||
 | 
			
		||||
				if (cell->type.in("$_AND_", "$_NOT_"))
 | 
			
		||||
				if (cell->type.in(ID($_AND_), ID($_NOT_)))
 | 
			
		||||
					aig.name.clear();
 | 
			
		||||
 | 
			
		||||
				if (nand_mode && cell->type == "$_NAND_")
 | 
			
		||||
				if (nand_mode && cell->type == ID($_NAND_))
 | 
			
		||||
					aig.name.clear();
 | 
			
		||||
 | 
			
		||||
				if (aig.name.empty()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ struct AlumaccWorker
 | 
			
		|||
 | 
			
		||||
		RTLIL::SigSpec get_eq() {
 | 
			
		||||
			if (GetSize(cached_eq) == 0)
 | 
			
		||||
				cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort("\\X"), false, alu_cell->get_src_attribute());
 | 
			
		||||
				cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort(ID(X)), false, alu_cell->get_src_attribute());
 | 
			
		||||
			return cached_eq;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +73,7 @@ struct AlumaccWorker
 | 
			
		|||
 | 
			
		||||
		RTLIL::SigSpec get_cf() {
 | 
			
		||||
			if (GetSize(cached_cf) == 0) {
 | 
			
		||||
				cached_cf = alu_cell->getPort("\\CO");
 | 
			
		||||
				cached_cf = alu_cell->getPort(ID(CO));
 | 
			
		||||
				log_assert(GetSize(cached_cf) >= 1);
 | 
			
		||||
				cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1], false, alu_cell->get_src_attribute());
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ struct AlumaccWorker
 | 
			
		|||
 | 
			
		||||
		RTLIL::SigSpec get_of() {
 | 
			
		||||
			if (GetSize(cached_of) == 0) {
 | 
			
		||||
				cached_of = {alu_cell->getPort("\\CO"), alu_cell->getPort("\\CI")};
 | 
			
		||||
				cached_of = {alu_cell->getPort(ID(CO)), alu_cell->getPort(ID(CI))};
 | 
			
		||||
				log_assert(GetSize(cached_of) >= 2);
 | 
			
		||||
				cached_of = alu_cell->module->Xor(NEW_ID, cached_of[GetSize(cached_of)-1], cached_of[GetSize(cached_of)-2]);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +91,7 @@ struct AlumaccWorker
 | 
			
		|||
 | 
			
		||||
		RTLIL::SigSpec get_sf() {
 | 
			
		||||
			if (GetSize(cached_sf) == 0) {
 | 
			
		||||
				cached_sf = alu_cell->getPort("\\Y");
 | 
			
		||||
				cached_sf = alu_cell->getPort(ID(Y));
 | 
			
		||||
				cached_sf = cached_sf[GetSize(cached_sf)-1];
 | 
			
		||||
			}
 | 
			
		||||
			return cached_sf;
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +125,7 @@ struct AlumaccWorker
 | 
			
		|||
	{
 | 
			
		||||
		for (auto cell : module->selected_cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (!cell->type.in("$pos", "$neg", "$add", "$sub", "$mul"))
 | 
			
		||||
			if (!cell->type.in(ID($pos), ID($neg), ID($add), ID($sub), ID($mul)))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			log("  creating $macc model for %s (%s).\n", log_id(cell), log_id(cell->type));
 | 
			
		||||
| 
						 | 
				
			
			@ -134,38 +134,38 @@ struct AlumaccWorker
 | 
			
		|||
			Macc::port_t new_port;
 | 
			
		||||
 | 
			
		||||
			n->cell = cell;
 | 
			
		||||
			n->y = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
			n->y = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
			n->users = 0;
 | 
			
		||||
 | 
			
		||||
			for (auto bit : n->y)
 | 
			
		||||
				n->users = max(n->users, bit_users.at(bit) - 1);
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$pos", "$neg"))
 | 
			
		||||
			if (cell->type.in(ID($pos), ID($neg)))
 | 
			
		||||
			{
 | 
			
		||||
				new_port.in_a = sigmap(cell->getPort("\\A"));
 | 
			
		||||
				new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool();
 | 
			
		||||
				new_port.do_subtract = cell->type == "$neg";
 | 
			
		||||
				new_port.in_a = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
				new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 | 
			
		||||
				new_port.do_subtract = cell->type == ID($neg);
 | 
			
		||||
				n->macc.ports.push_back(new_port);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$add", "$sub"))
 | 
			
		||||
			if (cell->type.in(ID($add), ID($sub)))
 | 
			
		||||
			{
 | 
			
		||||
				new_port.in_a = sigmap(cell->getPort("\\A"));
 | 
			
		||||
				new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool();
 | 
			
		||||
				new_port.in_a = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
				new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 | 
			
		||||
				new_port.do_subtract = false;
 | 
			
		||||
				n->macc.ports.push_back(new_port);
 | 
			
		||||
 | 
			
		||||
				new_port.in_a = sigmap(cell->getPort("\\B"));
 | 
			
		||||
				new_port.is_signed = cell->getParam("\\B_SIGNED").as_bool();
 | 
			
		||||
				new_port.do_subtract = cell->type == "$sub";
 | 
			
		||||
				new_port.in_a = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
				new_port.is_signed = cell->getParam(ID(B_SIGNED)).as_bool();
 | 
			
		||||
				new_port.do_subtract = cell->type == ID($sub);
 | 
			
		||||
				n->macc.ports.push_back(new_port);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$mul"))
 | 
			
		||||
			if (cell->type.in(ID($mul)))
 | 
			
		||||
			{
 | 
			
		||||
				new_port.in_a = sigmap(cell->getPort("\\A"));
 | 
			
		||||
				new_port.in_b = sigmap(cell->getPort("\\B"));
 | 
			
		||||
				new_port.is_signed = cell->getParam("\\A_SIGNED").as_bool();
 | 
			
		||||
				new_port.in_a = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
				new_port.in_b = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
				new_port.is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 | 
			
		||||
				new_port.do_subtract = false;
 | 
			
		||||
				n->macc.ports.push_back(new_port);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -351,7 +351,7 @@ struct AlumaccWorker
 | 
			
		|||
		for (auto &it : sig_macc)
 | 
			
		||||
		{
 | 
			
		||||
			auto n = it.second;
 | 
			
		||||
			auto cell = module->addCell(NEW_ID, "$macc");
 | 
			
		||||
			auto cell = module->addCell(NEW_ID, ID($macc));
 | 
			
		||||
 | 
			
		||||
			macc_counter++;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -361,7 +361,7 @@ struct AlumaccWorker
 | 
			
		|||
 | 
			
		||||
			n->macc.optimize(GetSize(n->y));
 | 
			
		||||
			n->macc.to_cell(cell);
 | 
			
		||||
			cell->setPort("\\Y", n->y);
 | 
			
		||||
			cell->setPort(ID(Y), n->y);
 | 
			
		||||
			cell->fixup_parameters();
 | 
			
		||||
			module->remove(n->cell);
 | 
			
		||||
			delete n;
 | 
			
		||||
| 
						 | 
				
			
			@ -376,9 +376,9 @@ struct AlumaccWorker
 | 
			
		|||
 | 
			
		||||
		for (auto cell : module->selected_cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type.in("$lt", "$le", "$ge", "$gt"))
 | 
			
		||||
			if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt)))
 | 
			
		||||
				lge_cells.push_back(cell);
 | 
			
		||||
			if (cell->type.in("$eq", "$eqx", "$ne", "$nex"))
 | 
			
		||||
			if (cell->type.in(ID($eq), ID($eqx), ID($ne), ID($nex)))
 | 
			
		||||
				eq_cells.push_back(cell);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -386,13 +386,13 @@ struct AlumaccWorker
 | 
			
		|||
		{
 | 
			
		||||
			log("  creating $alu model for %s (%s):", log_id(cell), log_id(cell->type));
 | 
			
		||||
 | 
			
		||||
			bool cmp_less = cell->type.in("$lt", "$le");
 | 
			
		||||
			bool cmp_equal = cell->type.in("$le", "$ge");
 | 
			
		||||
			bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
 | 
			
		||||
			bool cmp_less = cell->type.in(ID($lt), ID($le));
 | 
			
		||||
			bool cmp_equal = cell->type.in(ID($le), ID($ge));
 | 
			
		||||
			bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec A = sigmap(cell->getPort("\\A"));
 | 
			
		||||
			RTLIL::SigSpec B = sigmap(cell->getPort("\\B"));
 | 
			
		||||
			RTLIL::SigSpec Y = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
			RTLIL::SigSpec A = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
			RTLIL::SigSpec B = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
			RTLIL::SigSpec Y = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
 | 
			
		||||
			if (B < A && GetSize(B)) {
 | 
			
		||||
				cmp_less = !cmp_less;
 | 
			
		||||
| 
						 | 
				
			
			@ -427,12 +427,12 @@ struct AlumaccWorker
 | 
			
		|||
 | 
			
		||||
		for (auto cell : eq_cells)
 | 
			
		||||
		{
 | 
			
		||||
			bool cmp_equal = cell->type.in("$eq", "$eqx");
 | 
			
		||||
			bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
 | 
			
		||||
			bool cmp_equal = cell->type.in(ID($eq), ID($eqx));
 | 
			
		||||
			bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool();
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec A = sigmap(cell->getPort("\\A"));
 | 
			
		||||
			RTLIL::SigSpec B = sigmap(cell->getPort("\\B"));
 | 
			
		||||
			RTLIL::SigSpec Y = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
			RTLIL::SigSpec A = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
			RTLIL::SigSpec B = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
			RTLIL::SigSpec Y = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
 | 
			
		||||
			if (B < A && GetSize(B))
 | 
			
		||||
				std::swap(A, B);
 | 
			
		||||
| 
						 | 
				
			
			@ -471,7 +471,7 @@ struct AlumaccWorker
 | 
			
		|||
				goto delete_node;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			n->alu_cell = module->addCell(NEW_ID, "$alu");
 | 
			
		||||
			n->alu_cell = module->addCell(NEW_ID, ID($alu));
 | 
			
		||||
			alu_counter++;
 | 
			
		||||
 | 
			
		||||
			log("  creating $alu cell for ");
 | 
			
		||||
| 
						 | 
				
			
			@ -482,13 +482,13 @@ struct AlumaccWorker
 | 
			
		|||
			if (n->cells.size() > 0)
 | 
			
		||||
				n->alu_cell->set_src_attribute(n->cells[0]->get_src_attribute());
 | 
			
		||||
 | 
			
		||||
			n->alu_cell->setPort("\\A", n->a);
 | 
			
		||||
			n->alu_cell->setPort("\\B", n->b);
 | 
			
		||||
			n->alu_cell->setPort("\\CI", GetSize(n->c) ? n->c : State::S0);
 | 
			
		||||
			n->alu_cell->setPort("\\BI", n->invert_b ? State::S1 : State::S0);
 | 
			
		||||
			n->alu_cell->setPort("\\Y", n->y);
 | 
			
		||||
			n->alu_cell->setPort("\\X", module->addWire(NEW_ID, GetSize(n->y)));
 | 
			
		||||
			n->alu_cell->setPort("\\CO", module->addWire(NEW_ID, GetSize(n->y)));
 | 
			
		||||
			n->alu_cell->setPort(ID(A), n->a);
 | 
			
		||||
			n->alu_cell->setPort(ID(B), n->b);
 | 
			
		||||
			n->alu_cell->setPort(ID(CI), GetSize(n->c) ? n->c : State::S0);
 | 
			
		||||
			n->alu_cell->setPort(ID(BI), n->invert_b ? State::S1 : State::S0);
 | 
			
		||||
			n->alu_cell->setPort(ID(Y), n->y);
 | 
			
		||||
			n->alu_cell->setPort(ID(X), module->addWire(NEW_ID, GetSize(n->y)));
 | 
			
		||||
			n->alu_cell->setPort(ID(CO), module->addWire(NEW_ID, GetSize(n->y)));
 | 
			
		||||
			n->alu_cell->fixup_parameters(n->is_signed, n->is_signed);
 | 
			
		||||
 | 
			
		||||
			for (auto &it : n->cmp)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,13 +83,13 @@ struct DeminoutPass : public Pass {
 | 
			
		|||
						for (auto bit : sigmap(conn.second))
 | 
			
		||||
							bits_used.insert(bit);
 | 
			
		||||
 | 
			
		||||
					if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_", "$tribuf"))
 | 
			
		||||
					if (conn.first == ID(Y) && cell->type.in(ID($mux), ID($pmux), ID($_MUX_), ID($_TBUF_), ID($tribuf)))
 | 
			
		||||
					{
 | 
			
		||||
						bool tribuf = cell->type.in("$_TBUF_", "$tribuf");
 | 
			
		||||
						bool tribuf = cell->type.in(ID($_TBUF_), ID($tribuf));
 | 
			
		||||
 | 
			
		||||
						if (!tribuf) {
 | 
			
		||||
							for (auto &c : cell->connections()) {
 | 
			
		||||
								if (!c.first.in("\\A", "\\B"))
 | 
			
		||||
								if (!c.first.in(ID(A), ID(B)))
 | 
			
		||||
									continue;
 | 
			
		||||
								for (auto b : sigmap(c.second))
 | 
			
		||||
									if (b == State::Sz)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,13 +52,13 @@ struct Dff2dffeWorker
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto cell : module->cells()) {
 | 
			
		||||
			if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
 | 
			
		||||
				RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
			if (cell->type.in(ID($mux), ID($pmux), ID($_MUX_))) {
 | 
			
		||||
				RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
				for (int i = 0; i < GetSize(sig_y); i++)
 | 
			
		||||
					bit2mux[sig_y[i]] = cell_int_t(cell, i);
 | 
			
		||||
			}
 | 
			
		||||
			if (direct_dict.empty()) {
 | 
			
		||||
				if (cell->type.in("$dff", "$_DFF_N_", "$_DFF_P_"))
 | 
			
		||||
				if (cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_)))
 | 
			
		||||
					dff_cells.push_back(cell);
 | 
			
		||||
			} else {
 | 
			
		||||
				if (direct_dict.count(cell->type))
 | 
			
		||||
| 
						 | 
				
			
			@ -86,9 +86,9 @@ struct Dff2dffeWorker
 | 
			
		|||
			return ret;
 | 
			
		||||
 | 
			
		||||
		cell_int_t mux_cell_int = bit2mux.at(d);
 | 
			
		||||
		RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort("\\A"));
 | 
			
		||||
		RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort("\\B"));
 | 
			
		||||
		RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort("\\S"));
 | 
			
		||||
		RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort(ID(A)));
 | 
			
		||||
		RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort(ID(B)));
 | 
			
		||||
		RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort(ID(S)));
 | 
			
		||||
		int width = GetSize(sig_a), index = mux_cell_int.second;
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < GetSize(sig_s); i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -97,9 +97,9 @@ struct Dff2dffeWorker
 | 
			
		|||
				ret = find_muxtree_feedback_patterns(sig_b[i*width + index], q, path);
 | 
			
		||||
 | 
			
		||||
				if (sig_b[i*width + index] == q) {
 | 
			
		||||
					RTLIL::SigSpec s = mux_cell_int.first->getPort("\\B");
 | 
			
		||||
					RTLIL::SigSpec s = mux_cell_int.first->getPort(ID(B));
 | 
			
		||||
					s[i*width + index] = RTLIL::Sx;
 | 
			
		||||
					mux_cell_int.first->setPort("\\B", s);
 | 
			
		||||
					mux_cell_int.first->setPort(ID(B), s);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -120,9 +120,9 @@ struct Dff2dffeWorker
 | 
			
		|||
				ret.insert(pat);
 | 
			
		||||
 | 
			
		||||
			if (sig_b[i*width + index] == q) {
 | 
			
		||||
				RTLIL::SigSpec s = mux_cell_int.first->getPort("\\B");
 | 
			
		||||
				RTLIL::SigSpec s = mux_cell_int.first->getPort(ID(B));
 | 
			
		||||
				s[i*width + index] = RTLIL::Sx;
 | 
			
		||||
				mux_cell_int.first->setPort("\\B", s);
 | 
			
		||||
				mux_cell_int.first->setPort(ID(B), s);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -130,9 +130,9 @@ struct Dff2dffeWorker
 | 
			
		|||
			ret.insert(pat);
 | 
			
		||||
 | 
			
		||||
		if (sig_a[index] == q) {
 | 
			
		||||
			RTLIL::SigSpec s = mux_cell_int.first->getPort("\\A");
 | 
			
		||||
			RTLIL::SigSpec s = mux_cell_int.first->getPort(ID(A));
 | 
			
		||||
			s[index] = RTLIL::Sx;
 | 
			
		||||
			mux_cell_int.first->setPort("\\A", s);
 | 
			
		||||
			mux_cell_int.first->setPort(ID(A), s);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -185,8 +185,8 @@ struct Dff2dffeWorker
 | 
			
		|||
 | 
			
		||||
	void handle_dff_cell(RTLIL::Cell *dff_cell)
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort("\\D"));
 | 
			
		||||
		RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort("\\Q"));
 | 
			
		||||
		RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort(ID(D)));
 | 
			
		||||
		RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort(ID(Q)));
 | 
			
		||||
 | 
			
		||||
		std::map<patterns_t, std::set<int>> grouped_patterns;
 | 
			
		||||
		std::set<int> remaining_indices;
 | 
			
		||||
| 
						 | 
				
			
			@ -208,16 +208,16 @@ struct Dff2dffeWorker
 | 
			
		|||
			}
 | 
			
		||||
			if (!direct_dict.empty()) {
 | 
			
		||||
				log("  converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_dict.at(dff_cell->type)), log_signal(new_sig_d), log_signal(new_sig_q));
 | 
			
		||||
				dff_cell->setPort("\\E", make_patterns_logic(it.first, true));
 | 
			
		||||
				dff_cell->setPort(ID(E), make_patterns_logic(it.first, true));
 | 
			
		||||
				dff_cell->type = direct_dict.at(dff_cell->type);
 | 
			
		||||
			} else
 | 
			
		||||
			if (dff_cell->type == "$dff") {
 | 
			
		||||
				RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first, false),
 | 
			
		||||
						new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true);
 | 
			
		||||
			if (dff_cell->type == ID($dff)) {
 | 
			
		||||
				RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort(ID(CLK)), make_patterns_logic(it.first, false),
 | 
			
		||||
						new_sig_d, new_sig_q, dff_cell->getParam(ID(CLK_POLARITY)).as_bool(), true);
 | 
			
		||||
				log("  created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q));
 | 
			
		||||
			} else {
 | 
			
		||||
				RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort("\\C"), make_patterns_logic(it.first, true),
 | 
			
		||||
						new_sig_d, new_sig_q, dff_cell->type == "$_DFF_P_", true);
 | 
			
		||||
				RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort(ID(C)), make_patterns_logic(it.first, true),
 | 
			
		||||
						new_sig_d, new_sig_q, dff_cell->type == ID($_DFF_P_), true);
 | 
			
		||||
				log("  created %s cell %s for %s -> %s.\n", log_id(new_cell->type), log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -235,9 +235,9 @@ struct Dff2dffeWorker
 | 
			
		|||
				new_sig_d.append(sig_d[i]);
 | 
			
		||||
				new_sig_q.append(sig_q[i]);
 | 
			
		||||
			}
 | 
			
		||||
			dff_cell->setPort("\\D", new_sig_d);
 | 
			
		||||
			dff_cell->setPort("\\Q", new_sig_q);
 | 
			
		||||
			dff_cell->setParam("\\WIDTH", GetSize(remaining_indices));
 | 
			
		||||
			dff_cell->setPort(ID(D), new_sig_d);
 | 
			
		||||
			dff_cell->setPort(ID(Q), new_sig_q);
 | 
			
		||||
			dff_cell->setParam(ID(WIDTH), GetSize(remaining_indices));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -316,25 +316,25 @@ struct Dff2dffePass : public Pass {
 | 
			
		|||
			if (args[argidx] == "-direct-match" && argidx + 1 < args.size()) {
 | 
			
		||||
				bool found_match = false;
 | 
			
		||||
				const char *pattern = args[++argidx].c_str();
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_P_"  )) found_match = true, direct_dict["$_DFF_P_"  ] = "$_DFFE_PP_";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_N_"  )) found_match = true, direct_dict["$_DFF_N_"  ] = "$_DFFE_NP_";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict["$_DFF_NN0_"] = "$__DFFE_NN0";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict["$_DFF_NN1_"] = "$__DFFE_NN1";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict["$_DFF_NP0_"] = "$__DFFE_NP0";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict["$_DFF_NP1_"] = "$__DFFE_NP1";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict["$_DFF_PN0_"] = "$__DFFE_PN0";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict["$_DFF_PN1_"] = "$__DFFE_PN1";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict["$_DFF_PP0_"] = "$__DFFE_PP0";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict["$_DFF_PP1_"] = "$__DFFE_PP1";
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_P_"  )) found_match = true, direct_dict[ID($_DFF_P_)  ] = ID($_DFFE_PP_);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_N_"  )) found_match = true, direct_dict[ID($_DFF_N_)  ] = ID($_DFFE_NP_);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict[ID($_DFF_NN0_)] = ID($__DFFE_NN0);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict[ID($_DFF_NN1_)] = ID($__DFFE_NN1);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict[ID($_DFF_NP0_)] = ID($__DFFE_NP0);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict[ID($_DFF_NP1_)] = ID($__DFFE_NP1);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict[ID($_DFF_PN0_)] = ID($__DFFE_PN0);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict[ID($_DFF_PN1_)] = ID($__DFFE_PN1);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict[ID($_DFF_PP0_)] = ID($__DFFE_PP0);
 | 
			
		||||
				if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict[ID($_DFF_PP1_)] = ID($__DFFE_PP1);
 | 
			
		||||
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict["$__DFFS_NN0_"] = "$__DFFSE_NN0";
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict["$__DFFS_NN1_"] = "$__DFFSE_NN1";
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict["$__DFFS_NP0_"] = "$__DFFSE_NP0";
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict["$__DFFS_NP1_"] = "$__DFFSE_NP1";
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict["$__DFFS_PN0_"] = "$__DFFSE_PN0";
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict["$__DFFS_PN1_"] = "$__DFFSE_PN1";
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict["$__DFFS_PP0_"] = "$__DFFSE_PP0";
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict["$__DFFS_PP1_"] = "$__DFFSE_PP1";
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict[ID($__DFFS_NN0_)] = ID($__DFFSE_NN0);
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict[ID($__DFFS_NN1_)] = ID($__DFFSE_NN1);
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict[ID($__DFFS_NP0_)] = ID($__DFFSE_NP0);
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict[ID($__DFFS_NP1_)] = ID($__DFFSE_NP1);
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict[ID($__DFFS_PN0_)] = ID($__DFFSE_PN0);
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict[ID($__DFFS_PN1_)] = ID($__DFFSE_PN1);
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict[ID($__DFFS_PP0_)] = ID($__DFFSE_PP0);
 | 
			
		||||
				if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict[ID($__DFFS_PP1_)] = ID($__DFFSE_PP1);
 | 
			
		||||
				if (!found_match)
 | 
			
		||||
					log_cmd_error("No cell types matched pattern '%s'.\n", pattern);
 | 
			
		||||
				continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -355,25 +355,25 @@ struct Dff2dffePass : public Pass {
 | 
			
		|||
				if (unmap_mode) {
 | 
			
		||||
					SigMap sigmap(mod);
 | 
			
		||||
					for (auto cell : mod->selected_cells()) {
 | 
			
		||||
						if (cell->type == "$dffe") {
 | 
			
		||||
						if (cell->type == ID($dffe)) {
 | 
			
		||||
							if (min_ce_use >= 0) {
 | 
			
		||||
								int ce_use = 0;
 | 
			
		||||
								for (auto cell_other : mod->selected_cells()) {
 | 
			
		||||
									if (cell_other->type != cell->type)
 | 
			
		||||
										continue;
 | 
			
		||||
									if (sigmap(cell->getPort("\\EN")) == sigmap(cell_other->getPort("\\EN")))
 | 
			
		||||
									if (sigmap(cell->getPort(ID(EN))) == sigmap(cell_other->getPort(ID(EN))))
 | 
			
		||||
										ce_use++;
 | 
			
		||||
								}
 | 
			
		||||
								if (ce_use >= min_ce_use)
 | 
			
		||||
									continue;
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort("\\D")));
 | 
			
		||||
							mod->addDff(NEW_ID, cell->getPort("\\CLK"), tmp, cell->getPort("\\Q"), cell->getParam("\\CLK_POLARITY").as_bool());
 | 
			
		||||
							if (cell->getParam("\\EN_POLARITY").as_bool())
 | 
			
		||||
								mod->addMux(NEW_ID, cell->getPort("\\Q"), cell->getPort("\\D"), cell->getPort("\\EN"), tmp);
 | 
			
		||||
							RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort(ID(D))));
 | 
			
		||||
							mod->addDff(NEW_ID, cell->getPort(ID(CLK)), tmp, cell->getPort(ID(Q)), cell->getParam(ID(CLK_POLARITY)).as_bool());
 | 
			
		||||
							if (cell->getParam(ID(EN_POLARITY)).as_bool())
 | 
			
		||||
								mod->addMux(NEW_ID, cell->getPort(ID(Q)), cell->getPort(ID(D)), cell->getPort(ID(EN)), tmp);
 | 
			
		||||
							else
 | 
			
		||||
								mod->addMux(NEW_ID, cell->getPort("\\D"), cell->getPort("\\Q"), cell->getPort("\\EN"), tmp);
 | 
			
		||||
								mod->addMux(NEW_ID, cell->getPort(ID(D)), cell->getPort(ID(Q)), cell->getPort(ID(EN)), tmp);
 | 
			
		||||
							mod->remove(cell);
 | 
			
		||||
							continue;
 | 
			
		||||
						}
 | 
			
		||||
| 
						 | 
				
			
			@ -383,7 +383,7 @@ struct Dff2dffePass : public Pass {
 | 
			
		|||
								for (auto cell_other : mod->selected_cells()) {
 | 
			
		||||
									if (cell_other->type != cell->type)
 | 
			
		||||
										continue;
 | 
			
		||||
									if (sigmap(cell->getPort("\\E")) == sigmap(cell_other->getPort("\\E")))
 | 
			
		||||
									if (sigmap(cell->getPort(ID(E))) == sigmap(cell_other->getPort(ID(E))))
 | 
			
		||||
										ce_use++;
 | 
			
		||||
								}
 | 
			
		||||
								if (ce_use >= min_ce_use)
 | 
			
		||||
| 
						 | 
				
			
			@ -393,11 +393,11 @@ struct Dff2dffePass : public Pass {
 | 
			
		|||
							bool clk_pol = cell->type.compare(7, 1, "P") == 0;
 | 
			
		||||
							bool en_pol = cell->type.compare(8, 1, "P") == 0;
 | 
			
		||||
							RTLIL::SigSpec tmp = mod->addWire(NEW_ID);
 | 
			
		||||
							mod->addDff(NEW_ID, cell->getPort("\\C"), tmp, cell->getPort("\\Q"), clk_pol);
 | 
			
		||||
							mod->addDff(NEW_ID, cell->getPort(ID(C)), tmp, cell->getPort(ID(Q)), clk_pol);
 | 
			
		||||
							if (en_pol)
 | 
			
		||||
								mod->addMux(NEW_ID, cell->getPort("\\Q"), cell->getPort("\\D"), cell->getPort("\\E"), tmp);
 | 
			
		||||
								mod->addMux(NEW_ID, cell->getPort(ID(Q)), cell->getPort(ID(D)), cell->getPort(ID(E)), tmp);
 | 
			
		||||
							else
 | 
			
		||||
								mod->addMux(NEW_ID, cell->getPort("\\D"), cell->getPort("\\Q"), cell->getPort("\\E"), tmp);
 | 
			
		||||
								mod->addMux(NEW_ID, cell->getPort(ID(D)), cell->getPort(ID(Q)), cell->getPort(ID(E)), tmp);
 | 
			
		||||
							mod->remove(cell);
 | 
			
		||||
							continue;
 | 
			
		||||
						}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,8 +51,8 @@ struct Dff2dffsPass : public Pass {
 | 
			
		|||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		pool<IdString> dff_types;
 | 
			
		||||
		dff_types.insert("$_DFF_N_");
 | 
			
		||||
		dff_types.insert("$_DFF_P_");
 | 
			
		||||
		dff_types.insert(ID($_DFF_N_));
 | 
			
		||||
		dff_types.insert(ID($_DFF_P_));
 | 
			
		||||
 | 
			
		||||
		for (auto module : design->selected_modules())
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -69,19 +69,19 @@ struct Dff2dffsPass : public Pass {
 | 
			
		|||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (cell->type != "$_MUX_")
 | 
			
		||||
				if (cell->type != ID($_MUX_))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				SigBit bit_a = sigmap(cell->getPort("\\A"));
 | 
			
		||||
				SigBit bit_b = sigmap(cell->getPort("\\B"));
 | 
			
		||||
				SigBit bit_a = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
				SigBit bit_b = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
 | 
			
		||||
				if (bit_a.wire == nullptr || bit_b.wire == nullptr)
 | 
			
		||||
					sr_muxes[sigmap(cell->getPort("\\Y"))] = cell;
 | 
			
		||||
					sr_muxes[sigmap(cell->getPort(ID(Y)))] = cell;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (auto cell : ff_cells)
 | 
			
		||||
			{
 | 
			
		||||
				SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
				SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
 | 
			
		||||
				if (GetSize(sig_d) < 1)
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,9 +92,9 @@ struct Dff2dffsPass : public Pass {
 | 
			
		|||
					continue;
 | 
			
		||||
 | 
			
		||||
				Cell *mux_cell = sr_muxes.at(bit_d);
 | 
			
		||||
				SigBit bit_a = sigmap(mux_cell->getPort("\\A"));
 | 
			
		||||
				SigBit bit_b = sigmap(mux_cell->getPort("\\B"));
 | 
			
		||||
				SigBit bit_s = sigmap(mux_cell->getPort("\\S"));
 | 
			
		||||
				SigBit bit_a = sigmap(mux_cell->getPort(ID(A)));
 | 
			
		||||
				SigBit bit_b = sigmap(mux_cell->getPort(ID(B)));
 | 
			
		||||
				SigBit bit_s = sigmap(mux_cell->getPort(ID(S)));
 | 
			
		||||
 | 
			
		||||
				log("  Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
 | 
			
		||||
						log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
 | 
			
		||||
| 
						 | 
				
			
			@ -114,26 +114,26 @@ struct Dff2dffsPass : public Pass {
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
				if (sr_val == State::S1) {
 | 
			
		||||
					if (cell->type == "$_DFF_N_") {
 | 
			
		||||
						if (invert_sr) cell->type = "$__DFFS_NN1_";
 | 
			
		||||
						else cell->type = "$__DFFS_NP1_";
 | 
			
		||||
					if (cell->type == ID($_DFF_N_)) {
 | 
			
		||||
						if (invert_sr) cell->type = ID($__DFFS_NN1_);
 | 
			
		||||
						else cell->type = ID($__DFFS_NP1_);
 | 
			
		||||
					} else {
 | 
			
		||||
						log_assert(cell->type == "$_DFF_P_");
 | 
			
		||||
						if (invert_sr) cell->type = "$__DFFS_PN1_";
 | 
			
		||||
						else cell->type = "$__DFFS_PP1_";
 | 
			
		||||
						log_assert(cell->type == ID($_DFF_P_));
 | 
			
		||||
						if (invert_sr) cell->type = ID($__DFFS_PN1_);
 | 
			
		||||
						else cell->type = ID($__DFFS_PP1_);
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					if (cell->type == "$_DFF_N_") {
 | 
			
		||||
						if (invert_sr) cell->type = "$__DFFS_NN0_";
 | 
			
		||||
						else cell->type = "$__DFFS_NP0_";
 | 
			
		||||
					if (cell->type == ID($_DFF_N_)) {
 | 
			
		||||
						if (invert_sr) cell->type = ID($__DFFS_NN0_);
 | 
			
		||||
						else cell->type = ID($__DFFS_NP0_);
 | 
			
		||||
					} else {
 | 
			
		||||
						log_assert(cell->type == "$_DFF_P_");
 | 
			
		||||
						if (invert_sr) cell->type = "$__DFFS_PN0_";
 | 
			
		||||
						else cell->type = "$__DFFS_PP0_";
 | 
			
		||||
						log_assert(cell->type == ID($_DFF_P_));
 | 
			
		||||
						if (invert_sr) cell->type = ID($__DFFS_PN0_);
 | 
			
		||||
						else cell->type = ID($__DFFS_PP0_);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				cell->setPort("\\R", sr_sig);
 | 
			
		||||
				cell->setPort("\\D", bit_d);
 | 
			
		||||
				cell->setPort(ID(R), sr_sig);
 | 
			
		||||
				cell->setPort(ID(D), bit_d);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -99,8 +99,8 @@ struct DffinitPass : public Pass {
 | 
			
		|||
			pool<SigBit> used_bits;
 | 
			
		||||
 | 
			
		||||
			for (auto wire : module->selected_wires()) {
 | 
			
		||||
				if (wire->attributes.count("\\init")) {
 | 
			
		||||
					Const value = wire->attributes.at("\\init");
 | 
			
		||||
				if (wire->attributes.count(ID(init))) {
 | 
			
		||||
					Const value = wire->attributes.at(ID(init));
 | 
			
		||||
					for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++)
 | 
			
		||||
						if (value[i] != State::Sx)
 | 
			
		||||
							init_bits[sigmap(SigBit(wire, i))] = value[i];
 | 
			
		||||
| 
						 | 
				
			
			@ -161,8 +161,8 @@ struct DffinitPass : public Pass {
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			for (auto wire : module->selected_wires())
 | 
			
		||||
				if (wire->attributes.count("\\init")) {
 | 
			
		||||
					Const &value = wire->attributes.at("\\init");
 | 
			
		||||
				if (wire->attributes.count(ID(init))) {
 | 
			
		||||
					Const &value = wire->attributes.at(ID(init));
 | 
			
		||||
					bool do_cleanup = true;
 | 
			
		||||
					for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) {
 | 
			
		||||
						SigBit bit = sigmap(SigBit(wire, i));
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +173,7 @@ struct DffinitPass : public Pass {
 | 
			
		|||
					}
 | 
			
		||||
					if (do_cleanup) {
 | 
			
		||||
						log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire));
 | 
			
		||||
						wire->attributes.erase("\\init");
 | 
			
		||||
						wire->attributes.erase(ID(init));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,12 +27,12 @@ USING_YOSYS_NAMESPACE
 | 
			
		|||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
struct cell_mapping {
 | 
			
		||||
	std::string cell_name;
 | 
			
		||||
	IdString cell_name;
 | 
			
		||||
	std::map<std::string, char> ports;
 | 
			
		||||
};
 | 
			
		||||
static std::map<RTLIL::IdString, cell_mapping> cell_mappings;
 | 
			
		||||
 | 
			
		||||
static void logmap(std::string dff)
 | 
			
		||||
static void logmap(IdString dff)
 | 
			
		||||
{
 | 
			
		||||
	if (cell_mappings.count(dff) == 0) {
 | 
			
		||||
		log("    unmapped dff cell: %s\n", dff.c_str());
 | 
			
		||||
| 
						 | 
				
			
			@ -54,26 +54,26 @@ static void logmap(std::string dff)
 | 
			
		|||
 | 
			
		||||
static void logmap_all()
 | 
			
		||||
{
 | 
			
		||||
	logmap("$_DFF_N_");
 | 
			
		||||
	logmap("$_DFF_P_");
 | 
			
		||||
	logmap(ID($_DFF_N_));
 | 
			
		||||
	logmap(ID($_DFF_P_));
 | 
			
		||||
 | 
			
		||||
	logmap("$_DFF_NN0_");
 | 
			
		||||
	logmap("$_DFF_NN1_");
 | 
			
		||||
	logmap("$_DFF_NP0_");
 | 
			
		||||
	logmap("$_DFF_NP1_");
 | 
			
		||||
	logmap("$_DFF_PN0_");
 | 
			
		||||
	logmap("$_DFF_PN1_");
 | 
			
		||||
	logmap("$_DFF_PP0_");
 | 
			
		||||
	logmap("$_DFF_PP1_");
 | 
			
		||||
	logmap(ID($_DFF_NN0_));
 | 
			
		||||
	logmap(ID($_DFF_NN1_));
 | 
			
		||||
	logmap(ID($_DFF_NP0_));
 | 
			
		||||
	logmap(ID($_DFF_NP1_));
 | 
			
		||||
	logmap(ID($_DFF_PN0_));
 | 
			
		||||
	logmap(ID($_DFF_PN1_));
 | 
			
		||||
	logmap(ID($_DFF_PP0_));
 | 
			
		||||
	logmap(ID($_DFF_PP1_));
 | 
			
		||||
 | 
			
		||||
	logmap("$_DFFSR_NNN_");
 | 
			
		||||
	logmap("$_DFFSR_NNP_");
 | 
			
		||||
	logmap("$_DFFSR_NPN_");
 | 
			
		||||
	logmap("$_DFFSR_NPP_");
 | 
			
		||||
	logmap("$_DFFSR_PNN_");
 | 
			
		||||
	logmap("$_DFFSR_PNP_");
 | 
			
		||||
	logmap("$_DFFSR_PPN_");
 | 
			
		||||
	logmap("$_DFFSR_PPP_");
 | 
			
		||||
	logmap(ID($_DFFSR_NNN_));
 | 
			
		||||
	logmap(ID($_DFFSR_NNP_));
 | 
			
		||||
	logmap(ID($_DFFSR_NPN_));
 | 
			
		||||
	logmap(ID($_DFFSR_NPP_));
 | 
			
		||||
	logmap(ID($_DFFSR_PNN_));
 | 
			
		||||
	logmap(ID($_DFFSR_PNP_));
 | 
			
		||||
	logmap(ID($_DFFSR_PPN_));
 | 
			
		||||
	logmap(ID($_DFFSR_PPP_));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol)
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
 | 
			
		|||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode)
 | 
			
		||||
static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode)
 | 
			
		||||
{
 | 
			
		||||
	LibertyAst *best_cell = NULL;
 | 
			
		||||
	std::map<std::string, char> best_cell_ports;
 | 
			
		||||
| 
						 | 
				
			
			@ -230,13 +230,13 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
 | 
			
		|||
			cell_mappings[cell_type].ports["D"] = 'D';
 | 
			
		||||
			cell_mappings[cell_type].ports["Q"] = 'Q';
 | 
			
		||||
		} else {
 | 
			
		||||
			cell_mappings[cell_type].cell_name = best_cell->args[0];
 | 
			
		||||
			cell_mappings[cell_type].cell_name = RTLIL::escape_id(best_cell->args[0]);
 | 
			
		||||
			cell_mappings[cell_type].ports = best_cell_ports;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode)
 | 
			
		||||
static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode)
 | 
			
		||||
{
 | 
			
		||||
	LibertyAst *best_cell = NULL;
 | 
			
		||||
	std::map<std::string, char> best_cell_ports;
 | 
			
		||||
| 
						 | 
				
			
			@ -347,7 +347,7 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
 | 
			
		|||
			cell_mappings[cell_type].ports["D"] = 'D';
 | 
			
		||||
			cell_mappings[cell_type].ports["Q"] = 'Q';
 | 
			
		||||
		} else {
 | 
			
		||||
			cell_mappings[cell_type].cell_name = best_cell->args[0];
 | 
			
		||||
			cell_mappings[cell_type].cell_name = RTLIL::escape_id(best_cell->args[0]);
 | 
			
		||||
			cell_mappings[cell_type].ports = best_cell_ports;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -404,7 +404,7 @@ static bool expand_cellmap(std::string pattern, std::string inv)
 | 
			
		|||
	return return_status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void map_sr_to_arst(const char *from, const char *to)
 | 
			
		||||
static void map_sr_to_arst(IdString from, IdString to)
 | 
			
		||||
{
 | 
			
		||||
	if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -419,7 +419,7 @@ static void map_sr_to_arst(const char *from, const char *to)
 | 
			
		|||
	log_assert(from_clk_pol == to_clk_pol);
 | 
			
		||||
	log_assert(to_rst_pol == from_set_pol && to_rst_pol == from_clr_pol);
 | 
			
		||||
 | 
			
		||||
	log("  create mapping for %s from mapping for %s.\n", to, from);
 | 
			
		||||
	log("  create mapping for %s from mapping for %s.\n", to.c_str(), from.c_str());
 | 
			
		||||
	cell_mappings[to].cell_name = cell_mappings[from].cell_name;
 | 
			
		||||
	cell_mappings[to].ports = cell_mappings[from].ports;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -450,7 +450,7 @@ static void map_sr_to_arst(const char *from, const char *to)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void map_adff_to_dff(const char *from, const char *to)
 | 
			
		||||
static void map_adff_to_dff(IdString from, IdString to)
 | 
			
		||||
{
 | 
			
		||||
	if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -461,7 +461,7 @@ static void map_adff_to_dff(const char *from, const char *to)
 | 
			
		|||
 | 
			
		||||
	log_assert(from_clk_pol == to_clk_pol);
 | 
			
		||||
 | 
			
		||||
	log("  create mapping for %s from mapping for %s.\n", to, from);
 | 
			
		||||
	log("  create mapping for %s from mapping for %s.\n", to.c_str(), from.c_str());
 | 
			
		||||
	cell_mappings[to].cell_name = cell_mappings[from].cell_name;
 | 
			
		||||
	cell_mappings[to].ports = cell_mappings[from].ports;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -484,8 +484,8 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
 | 
			
		|||
	for (auto &it : module->cells_) {
 | 
			
		||||
		if (design->selected(module, it.second) && cell_mappings.count(it.second->type) > 0)
 | 
			
		||||
			cell_list.push_back(it.second);
 | 
			
		||||
		if (it.second->type == "$_NOT_")
 | 
			
		||||
			notmap[sigmap(it.second->getPort("\\A"))].insert(it.second);
 | 
			
		||||
		if (it.second->type == ID($_NOT_))
 | 
			
		||||
			notmap[sigmap(it.second->getPort(ID(A)))].insert(it.second);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::map<std::string, int> stats;
 | 
			
		||||
| 
						 | 
				
			
			@ -499,7 +499,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
 | 
			
		|||
		module->remove(cell);
 | 
			
		||||
 | 
			
		||||
		cell_mapping &cm = cell_mappings[cell_type];
 | 
			
		||||
		RTLIL::Cell *new_cell = module->addCell(cell_name, prepare_mode ? cm.cell_name : "\\" + cm.cell_name);
 | 
			
		||||
		RTLIL::Cell *new_cell = module->addCell(cell_name, prepare_mode ? cm.cell_name : cm.cell_name);
 | 
			
		||||
 | 
			
		||||
		new_cell->set_src_attribute(src);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -519,8 +519,8 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
 | 
			
		|||
				sig = module->addWire(NEW_ID, GetSize(old_sig));
 | 
			
		||||
				if (has_q && has_qn) {
 | 
			
		||||
					for (auto &it : notmap[sigmap(old_sig)]) {
 | 
			
		||||
						module->connect(it->getPort("\\Y"), sig);
 | 
			
		||||
						it->setPort("\\Y", module->addWire(NEW_ID, GetSize(old_sig)));
 | 
			
		||||
						module->connect(it->getPort(ID(Y)), sig);
 | 
			
		||||
						it->setPort(ID(Y), module->addWire(NEW_ID, GetSize(old_sig)));
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					module->addNotGate(NEW_ID, sig, old_sig);
 | 
			
		||||
| 
						 | 
				
			
			@ -599,26 +599,26 @@ struct DfflibmapPass : public Pass {
 | 
			
		|||
		LibertyParser libparser(f);
 | 
			
		||||
		f.close();
 | 
			
		||||
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_N_", false, false, false, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_P_", true, false, false, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_N_), false, false, false, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_P_), true, false, false, false, prepare_mode);
 | 
			
		||||
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_NN0_", false, true, false, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_NN1_", false, true, false, true, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_NP0_", false, true, true, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_NP1_", false, true, true, true, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_PN0_", true, true, false, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_PN1_", true, true, false, true, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_PP0_", true, true, true, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, "$_DFF_PP1_", true, true, true, true, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_NN0_), false, true, false, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_NN1_), false, true, false, true, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_NP0_), false, true, true, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_NP1_), false, true, true, true, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_PN0_), true, true, false, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_PN1_), true, true, false, true, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_PP0_), true, true, true, false, prepare_mode);
 | 
			
		||||
		find_cell(libparser.ast, ID($_DFF_PP1_), true, true, true, true, prepare_mode);
 | 
			
		||||
 | 
			
		||||
		find_cell_sr(libparser.ast, "$_DFFSR_NNN_", false, false, false, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, "$_DFFSR_NNP_", false, false, true, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, "$_DFFSR_NPN_", false, true, false, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, "$_DFFSR_NPP_", false, true, true, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, "$_DFFSR_PNN_", true, false, false, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, "$_DFFSR_PNP_", true, false, true, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, "$_DFFSR_PPN_", true, true, false, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, "$_DFFSR_PPP_", true, true, true, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, ID($_DFFSR_NNN_), false, false, false, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, ID($_DFFSR_NNP_), false, false, true, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, ID($_DFFSR_NPN_), false, true, false, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, ID($_DFFSR_NPP_), false, true, true, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, ID($_DFFSR_PNN_), true, false, false, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, ID($_DFFSR_PNP_), true, false, true, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, ID($_DFFSR_PPN_), true, true, false, prepare_mode);
 | 
			
		||||
		find_cell_sr(libparser.ast, ID($_DFFSR_PPP_), true, true, true, prepare_mode);
 | 
			
		||||
 | 
			
		||||
		// try to implement as many cells as possible just by inverting
 | 
			
		||||
		// the SET and RESET pins. If necessary, implement cell types
 | 
			
		||||
| 
						 | 
				
			
			@ -642,23 +642,23 @@ struct DfflibmapPass : public Pass {
 | 
			
		|||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		map_sr_to_arst("$_DFFSR_NNN_", "$_DFF_NN0_");
 | 
			
		||||
		map_sr_to_arst("$_DFFSR_NNN_", "$_DFF_NN1_");
 | 
			
		||||
		map_sr_to_arst("$_DFFSR_NPP_", "$_DFF_NP0_");
 | 
			
		||||
		map_sr_to_arst("$_DFFSR_NPP_", "$_DFF_NP1_");
 | 
			
		||||
		map_sr_to_arst("$_DFFSR_PNN_", "$_DFF_PN0_");
 | 
			
		||||
		map_sr_to_arst("$_DFFSR_PNN_", "$_DFF_PN1_");
 | 
			
		||||
		map_sr_to_arst("$_DFFSR_PPP_", "$_DFF_PP0_");
 | 
			
		||||
		map_sr_to_arst("$_DFFSR_PPP_", "$_DFF_PP1_");
 | 
			
		||||
		map_sr_to_arst(ID($_DFFSR_NNN_), ID($_DFF_NN0_));
 | 
			
		||||
		map_sr_to_arst(ID($_DFFSR_NNN_), ID($_DFF_NN1_));
 | 
			
		||||
		map_sr_to_arst(ID($_DFFSR_NPP_), ID($_DFF_NP0_));
 | 
			
		||||
		map_sr_to_arst(ID($_DFFSR_NPP_), ID($_DFF_NP1_));
 | 
			
		||||
		map_sr_to_arst(ID($_DFFSR_PNN_), ID($_DFF_PN0_));
 | 
			
		||||
		map_sr_to_arst(ID($_DFFSR_PNN_), ID($_DFF_PN1_));
 | 
			
		||||
		map_sr_to_arst(ID($_DFFSR_PPP_), ID($_DFF_PP0_));
 | 
			
		||||
		map_sr_to_arst(ID($_DFFSR_PPP_), ID($_DFF_PP1_));
 | 
			
		||||
 | 
			
		||||
		map_adff_to_dff("$_DFF_NN0_", "$_DFF_N_");
 | 
			
		||||
		map_adff_to_dff("$_DFF_NN1_", "$_DFF_N_");
 | 
			
		||||
		map_adff_to_dff("$_DFF_NP0_", "$_DFF_N_");
 | 
			
		||||
		map_adff_to_dff("$_DFF_NP1_", "$_DFF_N_");
 | 
			
		||||
		map_adff_to_dff("$_DFF_PN0_", "$_DFF_P_");
 | 
			
		||||
		map_adff_to_dff("$_DFF_PN1_", "$_DFF_P_");
 | 
			
		||||
		map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_");
 | 
			
		||||
		map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_");
 | 
			
		||||
		map_adff_to_dff(ID($_DFF_NN0_), ID($_DFF_N_));
 | 
			
		||||
		map_adff_to_dff(ID($_DFF_NN1_), ID($_DFF_N_));
 | 
			
		||||
		map_adff_to_dff(ID($_DFF_NP0_), ID($_DFF_N_));
 | 
			
		||||
		map_adff_to_dff(ID($_DFF_NP1_), ID($_DFF_N_));
 | 
			
		||||
		map_adff_to_dff(ID($_DFF_PN0_), ID($_DFF_P_));
 | 
			
		||||
		map_adff_to_dff(ID($_DFF_PN1_), ID($_DFF_P_));
 | 
			
		||||
		map_adff_to_dff(ID($_DFF_PP0_), ID($_DFF_P_));
 | 
			
		||||
		map_adff_to_dff(ID($_DFF_PP1_), ID($_DFF_P_));
 | 
			
		||||
 | 
			
		||||
		log("  final dff cell mappings:\n");
 | 
			
		||||
		logmap_all();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,17 +25,17 @@ PRIVATE_NAMESPACE_BEGIN
 | 
			
		|||
 | 
			
		||||
void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	if (cell->type == "$dffsr")
 | 
			
		||||
	if (cell->type == ID($dffsr))
 | 
			
		||||
	{
 | 
			
		||||
		int width = cell->getParam("\\WIDTH").as_int();
 | 
			
		||||
		bool setpol = cell->getParam("\\SET_POLARITY").as_bool();
 | 
			
		||||
		bool clrpol = cell->getParam("\\CLR_POLARITY").as_bool();
 | 
			
		||||
		int width = cell->getParam(ID(WIDTH)).as_int();
 | 
			
		||||
		bool setpol = cell->getParam(ID(SET_POLARITY)).as_bool();
 | 
			
		||||
		bool clrpol = cell->getParam(ID(CLR_POLARITY)).as_bool();
 | 
			
		||||
 | 
			
		||||
		SigBit setunused = setpol ? State::S0 : State::S1;
 | 
			
		||||
		SigBit clrunused = clrpol ? State::S0 : State::S1;
 | 
			
		||||
 | 
			
		||||
		SigSpec setsig = sigmap(cell->getPort("\\SET"));
 | 
			
		||||
		SigSpec clrsig = sigmap(cell->getPort("\\CLR"));
 | 
			
		||||
		SigSpec setsig = sigmap(cell->getPort(ID(SET)));
 | 
			
		||||
		SigSpec clrsig = sigmap(cell->getPort(ID(CLR)));
 | 
			
		||||
 | 
			
		||||
		Const reset_val;
 | 
			
		||||
		SigSpec setctrl, clrctrl;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,32 +78,32 @@ void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
 | 
			
		|||
		log("Converting %s cell %s.%s to $adff.\n", log_id(cell->type), log_id(module), log_id(cell));
 | 
			
		||||
 | 
			
		||||
		if (GetSize(setctrl) == 1) {
 | 
			
		||||
			cell->setPort("\\ARST", setctrl);
 | 
			
		||||
			cell->setParam("\\ARST_POLARITY", setpol);
 | 
			
		||||
			cell->setPort(ID(ARST), setctrl);
 | 
			
		||||
			cell->setParam(ID(ARST_POLARITY), setpol);
 | 
			
		||||
		} else {
 | 
			
		||||
			cell->setPort("\\ARST", clrctrl);
 | 
			
		||||
			cell->setParam("\\ARST_POLARITY", clrpol);
 | 
			
		||||
			cell->setPort(ID(ARST), clrctrl);
 | 
			
		||||
			cell->setParam(ID(ARST_POLARITY), clrpol);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cell->type = "$adff";
 | 
			
		||||
		cell->unsetPort("\\SET");
 | 
			
		||||
		cell->unsetPort("\\CLR");
 | 
			
		||||
		cell->setParam("\\ARST_VALUE", reset_val);
 | 
			
		||||
		cell->unsetParam("\\SET_POLARITY");
 | 
			
		||||
		cell->unsetParam("\\CLR_POLARITY");
 | 
			
		||||
		cell->type = ID($adff);
 | 
			
		||||
		cell->unsetPort(ID(SET));
 | 
			
		||||
		cell->unsetPort(ID(CLR));
 | 
			
		||||
		cell->setParam(ID(ARST_VALUE), reset_val);
 | 
			
		||||
		cell->unsetParam(ID(SET_POLARITY));
 | 
			
		||||
		cell->unsetParam(ID(CLR_POLARITY));
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_",
 | 
			
		||||
			"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_"))
 | 
			
		||||
	if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
 | 
			
		||||
			ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_)))
 | 
			
		||||
	{
 | 
			
		||||
		char clkpol = cell->type.c_str()[8];
 | 
			
		||||
		char setpol = cell->type.c_str()[9];
 | 
			
		||||
		char clrpol = cell->type.c_str()[10];
 | 
			
		||||
 | 
			
		||||
		SigBit setbit = sigmap(cell->getPort("\\S"));
 | 
			
		||||
		SigBit clrbit = sigmap(cell->getPort("\\R"));
 | 
			
		||||
		SigBit setbit = sigmap(cell->getPort(ID(S)));
 | 
			
		||||
		SigBit clrbit = sigmap(cell->getPort(ID(R)));
 | 
			
		||||
 | 
			
		||||
		SigBit setunused = setpol == 'P' ? State::S0 : State::S1;
 | 
			
		||||
		SigBit clrunused = clrpol == 'P' ? State::S0 : State::S1;
 | 
			
		||||
| 
						 | 
				
			
			@ -112,14 +112,14 @@ void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
 | 
			
		|||
 | 
			
		||||
		if (setbit == setunused) {
 | 
			
		||||
			cell->type = stringf("$_DFF_%c%c0_", clkpol, clrpol);
 | 
			
		||||
			cell->unsetPort("\\S");
 | 
			
		||||
			cell->unsetPort(ID(S));
 | 
			
		||||
			goto converted_gate;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (clrbit == clrunused) {
 | 
			
		||||
			cell->type = stringf("$_DFF_%c%c1_", clkpol, setpol);
 | 
			
		||||
			cell->setPort("\\R", cell->getPort("\\S"));
 | 
			
		||||
			cell->unsetPort("\\S");
 | 
			
		||||
			cell->setPort(ID(R), cell->getPort(ID(S)));
 | 
			
		||||
			cell->unsetPort(ID(S));
 | 
			
		||||
			goto converted_gate;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -133,32 +133,32 @@ void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
 | 
			
		|||
 | 
			
		||||
void adff_worker(SigMap &sigmap, Module *module, Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	if (cell->type == "$adff")
 | 
			
		||||
	if (cell->type == ID($adff))
 | 
			
		||||
	{
 | 
			
		||||
		bool rstpol = cell->getParam("\\ARST_POLARITY").as_bool();
 | 
			
		||||
		bool rstpol = cell->getParam(ID(ARST_POLARITY)).as_bool();
 | 
			
		||||
		SigBit rstunused = rstpol ? State::S0 : State::S1;
 | 
			
		||||
		SigSpec rstsig = sigmap(cell->getPort("\\ARST"));
 | 
			
		||||
		SigSpec rstsig = sigmap(cell->getPort(ID(ARST)));
 | 
			
		||||
 | 
			
		||||
		if (rstsig != rstunused)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		log("Converting %s cell %s.%s to $dff.\n", log_id(cell->type), log_id(module), log_id(cell));
 | 
			
		||||
 | 
			
		||||
		cell->type = "$dff";
 | 
			
		||||
		cell->unsetPort("\\ARST");
 | 
			
		||||
		cell->unsetParam("\\ARST_VALUE");
 | 
			
		||||
		cell->unsetParam("\\ARST_POLARITY");
 | 
			
		||||
		cell->type = ID($dff);
 | 
			
		||||
		cell->unsetPort(ID(ARST));
 | 
			
		||||
		cell->unsetParam(ID(ARST_VALUE));
 | 
			
		||||
		cell->unsetParam(ID(ARST_POLARITY));
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in("$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
 | 
			
		||||
			"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_"))
 | 
			
		||||
	if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
 | 
			
		||||
			ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
 | 
			
		||||
	{
 | 
			
		||||
		char clkpol = cell->type.c_str()[6];
 | 
			
		||||
		char rstpol = cell->type.c_str()[7];
 | 
			
		||||
 | 
			
		||||
		SigBit rstbit = sigmap(cell->getPort("\\R"));
 | 
			
		||||
		SigBit rstbit = sigmap(cell->getPort(ID(R)));
 | 
			
		||||
		SigBit rstunused = rstpol == 'P' ? State::S0 : State::S1;
 | 
			
		||||
 | 
			
		||||
		if (rstbit != rstunused)
 | 
			
		||||
| 
						 | 
				
			
			@ -168,7 +168,7 @@ void adff_worker(SigMap &sigmap, Module *module, Cell *cell)
 | 
			
		|||
		log("Converting %s cell %s.%s to %s.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(newtype));
 | 
			
		||||
 | 
			
		||||
		cell->type = newtype;
 | 
			
		||||
		cell->unsetPort("\\R");
 | 
			
		||||
		cell->unsetPort(ID(R));
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,36 +58,36 @@ public:
 | 
			
		|||
			return value;
 | 
			
		||||
 | 
			
		||||
	#define param_bool(_n) if (param == _n) return value.as_bool();
 | 
			
		||||
		param_bool("\\ARST_POLARITY");
 | 
			
		||||
		param_bool("\\A_SIGNED");
 | 
			
		||||
		param_bool("\\B_SIGNED");
 | 
			
		||||
		param_bool("\\CLK_ENABLE");
 | 
			
		||||
		param_bool("\\CLK_POLARITY");
 | 
			
		||||
		param_bool("\\CLR_POLARITY");
 | 
			
		||||
		param_bool("\\EN_POLARITY");
 | 
			
		||||
		param_bool("\\SET_POLARITY");
 | 
			
		||||
		param_bool("\\TRANSPARENT");
 | 
			
		||||
		param_bool(ID(ARST_POLARITY));
 | 
			
		||||
		param_bool(ID(A_SIGNED));
 | 
			
		||||
		param_bool(ID(B_SIGNED));
 | 
			
		||||
		param_bool(ID(CLK_ENABLE));
 | 
			
		||||
		param_bool(ID(CLK_POLARITY));
 | 
			
		||||
		param_bool(ID(CLR_POLARITY));
 | 
			
		||||
		param_bool(ID(EN_POLARITY));
 | 
			
		||||
		param_bool(ID(SET_POLARITY));
 | 
			
		||||
		param_bool(ID(TRANSPARENT));
 | 
			
		||||
	#undef param_bool
 | 
			
		||||
 | 
			
		||||
	#define param_int(_n) if (param == _n) return value.as_int();
 | 
			
		||||
		param_int("\\ABITS")
 | 
			
		||||
		param_int("\\A_WIDTH")
 | 
			
		||||
		param_int("\\B_WIDTH")
 | 
			
		||||
		param_int("\\CTRL_IN_WIDTH")
 | 
			
		||||
		param_int("\\CTRL_OUT_WIDTH")
 | 
			
		||||
		param_int("\\OFFSET")
 | 
			
		||||
		param_int("\\PRIORITY")
 | 
			
		||||
		param_int("\\RD_PORTS")
 | 
			
		||||
		param_int("\\SIZE")
 | 
			
		||||
		param_int("\\STATE_BITS")
 | 
			
		||||
		param_int("\\STATE_NUM")
 | 
			
		||||
		param_int("\\STATE_NUM_LOG2")
 | 
			
		||||
		param_int("\\STATE_RST")
 | 
			
		||||
		param_int("\\S_WIDTH")
 | 
			
		||||
		param_int("\\TRANS_NUM")
 | 
			
		||||
		param_int("\\WIDTH")
 | 
			
		||||
		param_int("\\WR_PORTS")
 | 
			
		||||
		param_int("\\Y_WIDTH")
 | 
			
		||||
		param_int(ID(ABITS))
 | 
			
		||||
		param_int(ID(A_WIDTH))
 | 
			
		||||
		param_int(ID(B_WIDTH))
 | 
			
		||||
		param_int(ID(CTRL_IN_WIDTH))
 | 
			
		||||
		param_int(ID(CTRL_OUT_WIDTH))
 | 
			
		||||
		param_int(ID(OFFSET))
 | 
			
		||||
		param_int(ID(PRIORITY))
 | 
			
		||||
		param_int(ID(RD_PORTS))
 | 
			
		||||
		param_int(ID(SIZE))
 | 
			
		||||
		param_int(ID(STATE_BITS))
 | 
			
		||||
		param_int(ID(STATE_NUM))
 | 
			
		||||
		param_int(ID(STATE_NUM_LOG2))
 | 
			
		||||
		param_int(ID(STATE_RST))
 | 
			
		||||
		param_int(ID(S_WIDTH))
 | 
			
		||||
		param_int(ID(TRANS_NUM))
 | 
			
		||||
		param_int(ID(WIDTH))
 | 
			
		||||
		param_int(ID(WR_PORTS))
 | 
			
		||||
		param_int(ID(Y_WIDTH))
 | 
			
		||||
	#undef param_int
 | 
			
		||||
 | 
			
		||||
		return value;
 | 
			
		||||
| 
						 | 
				
			
			@ -341,10 +341,10 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit:
 | 
			
		|||
bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right)
 | 
			
		||||
{
 | 
			
		||||
	int left_idx = 0, right_idx = 0;
 | 
			
		||||
	if (left->attributes.count("\\extract_order") > 0)
 | 
			
		||||
		left_idx = left->attributes.at("\\extract_order").as_int();
 | 
			
		||||
	if (right->attributes.count("\\extract_order") > 0)
 | 
			
		||||
		right_idx = right->attributes.at("\\extract_order").as_int();
 | 
			
		||||
	if (left->attributes.count(ID(extract_order)) > 0)
 | 
			
		||||
		left_idx = left->attributes.at(ID(extract_order)).as_int();
 | 
			
		||||
	if (right->attributes.count(ID(extract_order)) > 0)
 | 
			
		||||
		right_idx = right->attributes.at(ID(extract_order)).as_int();
 | 
			
		||||
	if (left_idx != right_idx)
 | 
			
		||||
		return left_idx < right_idx;
 | 
			
		||||
	return left->name < right->name;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,71 +120,71 @@ int counter_tryextract(
 | 
			
		|||
 | 
			
		||||
	//A counter with less than 2 bits makes no sense
 | 
			
		||||
	//TODO: configurable min threshold
 | 
			
		||||
	int a_width = cell->getParam("\\A_WIDTH").as_int();
 | 
			
		||||
	int a_width = cell->getParam(ID(A_WIDTH)).as_int();
 | 
			
		||||
	extract.width = a_width;
 | 
			
		||||
	if( (a_width < 2) || (a_width > maxwidth) )
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	//Second input must be a single bit
 | 
			
		||||
	int b_width = cell->getParam("\\B_WIDTH").as_int();
 | 
			
		||||
	int b_width = cell->getParam(ID(B_WIDTH)).as_int();
 | 
			
		||||
	if(b_width != 1)
 | 
			
		||||
		return 2;
 | 
			
		||||
 | 
			
		||||
	//Both inputs must be unsigned, so don't extract anything with a signed input
 | 
			
		||||
	bool a_sign = cell->getParam("\\A_SIGNED").as_bool();
 | 
			
		||||
	bool b_sign = cell->getParam("\\B_SIGNED").as_bool();
 | 
			
		||||
	bool a_sign = cell->getParam(ID(A_SIGNED)).as_bool();
 | 
			
		||||
	bool b_sign = cell->getParam(ID(B_SIGNED)).as_bool();
 | 
			
		||||
	if(a_sign || b_sign)
 | 
			
		||||
		return 3;
 | 
			
		||||
 | 
			
		||||
	//To be a counter, one input of the ALU must be a constant 1
 | 
			
		||||
	//TODO: can A or B be swapped in synthesized RTL or is B always the 1?
 | 
			
		||||
	const RTLIL::SigSpec b_port = sigmap(cell->getPort("\\B"));
 | 
			
		||||
	const RTLIL::SigSpec b_port = sigmap(cell->getPort(ID(B)));
 | 
			
		||||
	if(!b_port.is_fully_const() || (b_port.as_int() != 1) )
 | 
			
		||||
		return 4;
 | 
			
		||||
 | 
			
		||||
	//BI and CI must be constant 1 as well
 | 
			
		||||
	const RTLIL::SigSpec bi_port = sigmap(cell->getPort("\\BI"));
 | 
			
		||||
	const RTLIL::SigSpec bi_port = sigmap(cell->getPort(ID(BI)));
 | 
			
		||||
	if(!bi_port.is_fully_const() || (bi_port.as_int() != 1) )
 | 
			
		||||
		return 5;
 | 
			
		||||
	const RTLIL::SigSpec ci_port = sigmap(cell->getPort("\\CI"));
 | 
			
		||||
	const RTLIL::SigSpec ci_port = sigmap(cell->getPort(ID(CI)));
 | 
			
		||||
	if(!ci_port.is_fully_const() || (ci_port.as_int() != 1) )
 | 
			
		||||
		return 6;
 | 
			
		||||
 | 
			
		||||
	//CO and X must be unconnected (exactly one connection to each port)
 | 
			
		||||
	if(!is_unconnected(sigmap(cell->getPort("\\CO")), index))
 | 
			
		||||
	if(!is_unconnected(sigmap(cell->getPort(ID(CO))), index))
 | 
			
		||||
		return 7;
 | 
			
		||||
	if(!is_unconnected(sigmap(cell->getPort("\\X")), index))
 | 
			
		||||
	if(!is_unconnected(sigmap(cell->getPort(ID(X))), index))
 | 
			
		||||
		return 8;
 | 
			
		||||
 | 
			
		||||
	//Y must have exactly one connection, and it has to be a $mux cell.
 | 
			
		||||
	//We must have a direct bus connection from our Y to their A.
 | 
			
		||||
	const RTLIL::SigSpec aluy = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
	const RTLIL::SigSpec aluy = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
	pool<Cell*> y_loads = get_other_cells(aluy, index, cell);
 | 
			
		||||
	if(y_loads.size() != 1)
 | 
			
		||||
		return 9;
 | 
			
		||||
	Cell* count_mux = *y_loads.begin();
 | 
			
		||||
	extract.count_mux = count_mux;
 | 
			
		||||
	if(count_mux->type != "$mux")
 | 
			
		||||
	if(count_mux->type != ID($mux))
 | 
			
		||||
		return 10;
 | 
			
		||||
	if(!is_full_bus(aluy, index, cell, "\\Y", count_mux, "\\A"))
 | 
			
		||||
	if(!is_full_bus(aluy, index, cell, ID(Y), count_mux, ID(A)))
 | 
			
		||||
		return 11;
 | 
			
		||||
 | 
			
		||||
	//B connection of the mux is our underflow value
 | 
			
		||||
	const RTLIL::SigSpec underflow = sigmap(count_mux->getPort("\\B"));
 | 
			
		||||
	const RTLIL::SigSpec underflow = sigmap(count_mux->getPort(ID(B)));
 | 
			
		||||
	if(!underflow.is_fully_const())
 | 
			
		||||
		return 12;
 | 
			
		||||
	extract.count_value = underflow.as_int();
 | 
			
		||||
 | 
			
		||||
	//S connection of the mux must come from an inverter (need not be the only load)
 | 
			
		||||
	const RTLIL::SigSpec muxsel = sigmap(count_mux->getPort("\\S"));
 | 
			
		||||
	const RTLIL::SigSpec muxsel = sigmap(count_mux->getPort(ID(S)));
 | 
			
		||||
	extract.outsig = muxsel;
 | 
			
		||||
	pool<Cell*> muxsel_conns = get_other_cells(muxsel, index, count_mux);
 | 
			
		||||
	Cell* underflow_inv = NULL;
 | 
			
		||||
	for(auto c : muxsel_conns)
 | 
			
		||||
	{
 | 
			
		||||
		if(c->type != "$logic_not")
 | 
			
		||||
		if(c->type != ID($logic_not))
 | 
			
		||||
			continue;
 | 
			
		||||
		if(!is_full_bus(muxsel, index, c, "\\Y", count_mux, "\\S", true))
 | 
			
		||||
		if(!is_full_bus(muxsel, index, c, ID(Y), count_mux, ID(S), true))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		underflow_inv = c;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +196,7 @@ int counter_tryextract(
 | 
			
		|||
 | 
			
		||||
	//Y connection of the mux must have exactly one load, the counter's internal register, if there's no clock enable
 | 
			
		||||
	//If we have a clock enable, Y drives the B input of a mux. A of that mux must come from our register
 | 
			
		||||
	const RTLIL::SigSpec muxy = sigmap(count_mux->getPort("\\Y"));
 | 
			
		||||
	const RTLIL::SigSpec muxy = sigmap(count_mux->getPort(ID(Y)));
 | 
			
		||||
	pool<Cell*> muxy_loads = get_other_cells(muxy, index, count_mux);
 | 
			
		||||
	if(muxy_loads.size() != 1)
 | 
			
		||||
		return 14;
 | 
			
		||||
| 
						 | 
				
			
			@ -204,12 +204,12 @@ int counter_tryextract(
 | 
			
		|||
	Cell* count_reg = muxload;
 | 
			
		||||
	Cell* cemux = NULL;
 | 
			
		||||
	RTLIL::SigSpec cey;
 | 
			
		||||
	if(muxload->type == "$mux")
 | 
			
		||||
	if(muxload->type == ID($mux))
 | 
			
		||||
	{
 | 
			
		||||
		//This mux is probably a clock enable mux.
 | 
			
		||||
		//Find our count register (should be our only load)
 | 
			
		||||
		cemux = muxload;
 | 
			
		||||
		cey = sigmap(cemux->getPort("\\Y"));
 | 
			
		||||
		cey = sigmap(cemux->getPort(ID(Y)));
 | 
			
		||||
		pool<Cell*> cey_loads = get_other_cells(cey, index, cemux);
 | 
			
		||||
		if(cey_loads.size() != 1)
 | 
			
		||||
			return 24;
 | 
			
		||||
| 
						 | 
				
			
			@ -217,32 +217,32 @@ int counter_tryextract(
 | 
			
		|||
 | 
			
		||||
		//Mux should have A driven by count Q, and B by muxy
 | 
			
		||||
		//TODO: if A and B are swapped, CE polarity is inverted
 | 
			
		||||
		if(sigmap(cemux->getPort("\\B")) != muxy)
 | 
			
		||||
		if(sigmap(cemux->getPort(ID(B))) != muxy)
 | 
			
		||||
			return 24;
 | 
			
		||||
		if(sigmap(cemux->getPort("\\A")) != sigmap(count_reg->getPort("\\Q")))
 | 
			
		||||
		if(sigmap(cemux->getPort(ID(A))) != sigmap(count_reg->getPort(ID(Q))))
 | 
			
		||||
			return 24;
 | 
			
		||||
		if(sigmap(cemux->getPort("\\Y")) != sigmap(count_reg->getPort("\\D")))
 | 
			
		||||
		if(sigmap(cemux->getPort(ID(Y))) != sigmap(count_reg->getPort(ID(D))))
 | 
			
		||||
			return 24;
 | 
			
		||||
 | 
			
		||||
		//Select of the mux is our clock enable
 | 
			
		||||
		extract.has_ce = true;
 | 
			
		||||
		extract.ce = sigmap(cemux->getPort("\\S"));
 | 
			
		||||
		extract.ce = sigmap(cemux->getPort(ID(S)));
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		extract.has_ce = false;
 | 
			
		||||
 | 
			
		||||
	extract.count_reg = count_reg;
 | 
			
		||||
	if(count_reg->type == "$dff")
 | 
			
		||||
	if(count_reg->type == ID($dff))
 | 
			
		||||
		extract.has_reset = false;
 | 
			
		||||
	else if(count_reg->type == "$adff")
 | 
			
		||||
	else if(count_reg->type == ID($adff))
 | 
			
		||||
	{
 | 
			
		||||
		extract.has_reset = true;
 | 
			
		||||
 | 
			
		||||
		//Check polarity of reset - we may have to add an inverter later on!
 | 
			
		||||
		extract.rst_inverted = (count_reg->getParam("\\ARST_POLARITY").as_int() != 1);
 | 
			
		||||
		extract.rst_inverted = (count_reg->getParam(ID(ARST_POLARITY)).as_int() != 1);
 | 
			
		||||
 | 
			
		||||
		//Verify ARST_VALUE is zero or full scale
 | 
			
		||||
		int rst_value = count_reg->getParam("\\ARST_VALUE").as_int();
 | 
			
		||||
		int rst_value = count_reg->getParam(ID(ARST_VALUE)).as_int();
 | 
			
		||||
		if(rst_value == 0)
 | 
			
		||||
			extract.rst_to_max = false;
 | 
			
		||||
		else if(rst_value == extract.count_value)
 | 
			
		||||
| 
						 | 
				
			
			@ -251,7 +251,7 @@ int counter_tryextract(
 | 
			
		|||
			return 23;
 | 
			
		||||
 | 
			
		||||
		//Save the reset
 | 
			
		||||
		extract.rst = sigmap(count_reg->getPort("\\ARST"));
 | 
			
		||||
		extract.rst = sigmap(count_reg->getPort(ID(ARST)));
 | 
			
		||||
	}
 | 
			
		||||
	//TODO: support synchronous reset
 | 
			
		||||
	else
 | 
			
		||||
| 
						 | 
				
			
			@ -260,12 +260,12 @@ int counter_tryextract(
 | 
			
		|||
	//Sanity check that we use the ALU output properly
 | 
			
		||||
	if(extract.has_ce)
 | 
			
		||||
	{
 | 
			
		||||
		if(!is_full_bus(muxy, index, count_mux, "\\Y", cemux, "\\B"))
 | 
			
		||||
		if(!is_full_bus(muxy, index, count_mux, ID(Y), cemux, ID(B)))
 | 
			
		||||
			return 16;
 | 
			
		||||
		if(!is_full_bus(cey, index, cemux, "\\Y", count_reg, "\\D"))
 | 
			
		||||
		if(!is_full_bus(cey, index, cemux, ID(Y), count_reg, ID(D)))
 | 
			
		||||
			return 16;
 | 
			
		||||
	}
 | 
			
		||||
	else if(!is_full_bus(muxy, index, count_mux, "\\Y", count_reg, "\\D"))
 | 
			
		||||
	else if(!is_full_bus(muxy, index, count_mux, ID(Y), count_reg, ID(D)))
 | 
			
		||||
		return 16;
 | 
			
		||||
 | 
			
		||||
	//TODO: Verify count_reg CLK_POLARITY is 1
 | 
			
		||||
| 
						 | 
				
			
			@ -273,7 +273,7 @@ int counter_tryextract(
 | 
			
		|||
	//Register output must have exactly two loads, the inverter and ALU
 | 
			
		||||
	//(unless we have a parallel output!)
 | 
			
		||||
	//If we have a clock enable, 3 is OK
 | 
			
		||||
	const RTLIL::SigSpec qport = count_reg->getPort("\\Q");
 | 
			
		||||
	const RTLIL::SigSpec qport = count_reg->getPort(ID(Q));
 | 
			
		||||
	const RTLIL::SigSpec cnout = sigmap(qport);
 | 
			
		||||
	pool<Cell*> cnout_loads = get_other_cells(cnout, index, count_reg);
 | 
			
		||||
	unsigned int max_loads = 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -312,19 +312,19 @@ int counter_tryextract(
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if(!is_full_bus(cnout, index, count_reg, "\\Q", underflow_inv, "\\A", true))
 | 
			
		||||
	if(!is_full_bus(cnout, index, count_reg, ID(Q), underflow_inv, ID(A), true))
 | 
			
		||||
		return 18;
 | 
			
		||||
	if(!is_full_bus(cnout, index, count_reg, "\\Q", cell, "\\A", true))
 | 
			
		||||
	if(!is_full_bus(cnout, index, count_reg, ID(Q), cell, ID(A), true))
 | 
			
		||||
		return 19;
 | 
			
		||||
 | 
			
		||||
	//Look up the clock from the register
 | 
			
		||||
	extract.clk = sigmap(count_reg->getPort("\\CLK"));
 | 
			
		||||
	extract.clk = sigmap(count_reg->getPort(ID(CLK)));
 | 
			
		||||
 | 
			
		||||
	//Register output net must have an INIT attribute equal to the count value
 | 
			
		||||
	extract.rwire = cnout.as_wire();
 | 
			
		||||
	if(extract.rwire->attributes.find("\\init") == extract.rwire->attributes.end())
 | 
			
		||||
	if(extract.rwire->attributes.find(ID(init)) == extract.rwire->attributes.end())
 | 
			
		||||
		return 20;
 | 
			
		||||
	int rinit = extract.rwire->attributes["\\init"].as_int();
 | 
			
		||||
	int rinit = extract.rwire->attributes[ID(init)].as_int();
 | 
			
		||||
	if(rinit != extract.count_value)
 | 
			
		||||
		return 21;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -343,21 +343,21 @@ void counter_worker(
 | 
			
		|||
	SigMap& sigmap = index.sigmap;
 | 
			
		||||
 | 
			
		||||
	//Core of the counter must be an ALU
 | 
			
		||||
	if (cell->type != "$alu")
 | 
			
		||||
	if (cell->type != ID($alu))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	//A input is the count value. Check if it has COUNT_EXTRACT set.
 | 
			
		||||
	//If it's not a wire, don't even try
 | 
			
		||||
	auto port = sigmap(cell->getPort("\\A"));
 | 
			
		||||
	auto port = sigmap(cell->getPort(ID(A)));
 | 
			
		||||
	if(!port.is_wire())
 | 
			
		||||
		return;
 | 
			
		||||
	RTLIL::Wire* a_wire = port.as_wire();
 | 
			
		||||
	bool force_extract = false;
 | 
			
		||||
	bool never_extract = false;
 | 
			
		||||
	string count_reg_src = a_wire->attributes["\\src"].decode_string().c_str();
 | 
			
		||||
	if(a_wire->attributes.find("\\COUNT_EXTRACT") != a_wire->attributes.end())
 | 
			
		||||
	string count_reg_src = a_wire->attributes[ID(src)].decode_string().c_str();
 | 
			
		||||
	if(a_wire->attributes.find(ID(COUNT_EXTRACT)) != a_wire->attributes.end())
 | 
			
		||||
	{
 | 
			
		||||
		pool<string> sa = a_wire->get_strpool_attribute("\\COUNT_EXTRACT");
 | 
			
		||||
		pool<string> sa = a_wire->get_strpool_attribute(ID(COUNT_EXTRACT));
 | 
			
		||||
		string extract_value;
 | 
			
		||||
		if(sa.size() >= 1)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -434,66 +434,66 @@ void counter_worker(
 | 
			
		|||
	string countname = string("$COUNTx$") + log_id(extract.rwire->name.str());
 | 
			
		||||
 | 
			
		||||
	//Wipe all of the old connections to the ALU
 | 
			
		||||
	cell->unsetPort("\\A");
 | 
			
		||||
	cell->unsetPort("\\B");
 | 
			
		||||
	cell->unsetPort("\\BI");
 | 
			
		||||
	cell->unsetPort("\\CI");
 | 
			
		||||
	cell->unsetPort("\\CO");
 | 
			
		||||
	cell->unsetPort("\\X");
 | 
			
		||||
	cell->unsetPort("\\Y");
 | 
			
		||||
	cell->unsetParam("\\A_SIGNED");
 | 
			
		||||
	cell->unsetParam("\\A_WIDTH");
 | 
			
		||||
	cell->unsetParam("\\B_SIGNED");
 | 
			
		||||
	cell->unsetParam("\\B_WIDTH");
 | 
			
		||||
	cell->unsetParam("\\Y_WIDTH");
 | 
			
		||||
	cell->unsetPort(ID(A));
 | 
			
		||||
	cell->unsetPort(ID(B));
 | 
			
		||||
	cell->unsetPort(ID(BI));
 | 
			
		||||
	cell->unsetPort(ID(CI));
 | 
			
		||||
	cell->unsetPort(ID(CO));
 | 
			
		||||
	cell->unsetPort(ID(X));
 | 
			
		||||
	cell->unsetPort(ID(Y));
 | 
			
		||||
	cell->unsetParam(ID(A_SIGNED));
 | 
			
		||||
	cell->unsetParam(ID(A_WIDTH));
 | 
			
		||||
	cell->unsetParam(ID(B_SIGNED));
 | 
			
		||||
	cell->unsetParam(ID(B_WIDTH));
 | 
			
		||||
	cell->unsetParam(ID(Y_WIDTH));
 | 
			
		||||
 | 
			
		||||
	//Change the cell type
 | 
			
		||||
	cell->type = "$__COUNT_";
 | 
			
		||||
	cell->type = ID($__COUNT_);
 | 
			
		||||
 | 
			
		||||
	//Hook up resets
 | 
			
		||||
	if(extract.has_reset)
 | 
			
		||||
	{
 | 
			
		||||
		//TODO: support other kinds of reset
 | 
			
		||||
		cell->setParam("\\RESET_MODE", RTLIL::Const("LEVEL"));
 | 
			
		||||
		cell->setParam(ID(RESET_MODE), RTLIL::Const("LEVEL"));
 | 
			
		||||
 | 
			
		||||
		//If the reset is active low, infer an inverter ($__COUNT_ cells always have active high reset)
 | 
			
		||||
		if(extract.rst_inverted)
 | 
			
		||||
		{
 | 
			
		||||
			auto realreset = cell->module->addWire(NEW_ID);
 | 
			
		||||
			cell->module->addNot(NEW_ID, extract.rst, RTLIL::SigSpec(realreset));
 | 
			
		||||
			cell->setPort("\\RST", realreset);
 | 
			
		||||
			cell->setPort(ID(RST), realreset);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			cell->setPort("\\RST", extract.rst);
 | 
			
		||||
			cell->setPort(ID(RST), extract.rst);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		cell->setParam("\\RESET_MODE", RTLIL::Const("RISING"));
 | 
			
		||||
		cell->setPort("\\RST", RTLIL::SigSpec(false));
 | 
			
		||||
		cell->setParam(ID(RESET_MODE), RTLIL::Const("RISING"));
 | 
			
		||||
		cell->setPort(ID(RST), RTLIL::SigSpec(false));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//Hook up other stuff
 | 
			
		||||
	//cell->setParam("\\CLKIN_DIVIDE", RTLIL::Const(1));
 | 
			
		||||
	cell->setParam("\\COUNT_TO", RTLIL::Const(extract.count_value));
 | 
			
		||||
	cell->setParam("\\WIDTH", RTLIL::Const(extract.width));
 | 
			
		||||
	cell->setPort("\\CLK", extract.clk);
 | 
			
		||||
	cell->setPort("\\OUT", extract.outsig);
 | 
			
		||||
	//cell->setParam(ID(CLKIN_DIVIDE), RTLIL::Const(1));
 | 
			
		||||
	cell->setParam(ID(COUNT_TO), RTLIL::Const(extract.count_value));
 | 
			
		||||
	cell->setParam(ID(WIDTH), RTLIL::Const(extract.width));
 | 
			
		||||
	cell->setPort(ID(CLK), extract.clk);
 | 
			
		||||
	cell->setPort(ID(OUT), extract.outsig);
 | 
			
		||||
 | 
			
		||||
	//Hook up clock enable
 | 
			
		||||
	if(extract.has_ce)
 | 
			
		||||
	{
 | 
			
		||||
		cell->setParam("\\HAS_CE", RTLIL::Const(1));
 | 
			
		||||
		cell->setPort("\\CE", extract.ce);
 | 
			
		||||
		cell->setParam(ID(HAS_CE), RTLIL::Const(1));
 | 
			
		||||
		cell->setPort(ID(CE), extract.ce);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		cell->setParam("\\HAS_CE", RTLIL::Const(0));
 | 
			
		||||
		cell->setParam(ID(HAS_CE), RTLIL::Const(0));
 | 
			
		||||
 | 
			
		||||
	//Hook up hard-wired ports (for now up/down are not supported), default to no parallel output
 | 
			
		||||
	cell->setParam("\\HAS_POUT", RTLIL::Const(0));
 | 
			
		||||
	cell->setParam("\\RESET_TO_MAX", RTLIL::Const(0));
 | 
			
		||||
	cell->setParam("\\DIRECTION", RTLIL::Const("DOWN"));
 | 
			
		||||
	cell->setPort("\\CE", RTLIL::Const(1));
 | 
			
		||||
	cell->setPort("\\UP", RTLIL::Const(0));
 | 
			
		||||
	cell->setParam(ID(HAS_POUT), RTLIL::Const(0));
 | 
			
		||||
	cell->setParam(ID(RESET_TO_MAX), RTLIL::Const(0));
 | 
			
		||||
	cell->setParam(ID(DIRECTION), RTLIL::Const("DOWN"));
 | 
			
		||||
	cell->setPort(ID(CE), RTLIL::Const(1));
 | 
			
		||||
	cell->setPort(ID(UP), RTLIL::Const(0));
 | 
			
		||||
 | 
			
		||||
	//Hook up any parallel outputs
 | 
			
		||||
	for(auto load : extract.pouts)
 | 
			
		||||
| 
						 | 
				
			
			@ -505,8 +505,8 @@ void counter_worker(
 | 
			
		|||
 | 
			
		||||
		//Connect it to our parallel output
 | 
			
		||||
		//(this is OK to do more than once b/c they all go to the same place)
 | 
			
		||||
		cell->setPort("\\POUT", sig);
 | 
			
		||||
		cell->setParam("\\HAS_POUT", RTLIL::Const(1));
 | 
			
		||||
		cell->setPort(ID(POUT), sig);
 | 
			
		||||
		cell->setParam(ID(HAS_POUT), RTLIL::Const(1));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//Delete the cells we've replaced (let opt_clean handle deleting the now-redundant wires)
 | 
			
		||||
| 
						 | 
				
			
			@ -546,7 +546,7 @@ void counter_worker(
 | 
			
		|||
		int newbits = ceil(log2(extract.count_value));
 | 
			
		||||
		if(extract.width != newbits)
 | 
			
		||||
		{
 | 
			
		||||
			cell->setParam("\\WIDTH", RTLIL::Const(newbits));
 | 
			
		||||
			cell->setParam(ID(WIDTH), RTLIL::Const(newbits));
 | 
			
		||||
			log("    Optimizing out %d unused high-order bits (new width is %d)\n",
 | 
			
		||||
				extract.width - newbits,
 | 
			
		||||
				newbits);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,11 +85,11 @@ struct ExtractFaWorker
 | 
			
		|||
	{
 | 
			
		||||
		for (auto cell : module->selected_cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_",
 | 
			
		||||
					"$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_", "$_NMUX_",
 | 
			
		||||
					"$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
 | 
			
		||||
			if (cell->type.in( ID($_BUF_), ID($_NOT_), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_),
 | 
			
		||||
					ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($_MUX_), ID($_NMUX_),
 | 
			
		||||
					ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)))
 | 
			
		||||
			{
 | 
			
		||||
				SigBit y = sigmap(SigBit(cell->getPort("\\Y")));
 | 
			
		||||
				SigBit y = sigmap(SigBit(cell->getPort(ID(Y))));
 | 
			
		||||
				log_assert(driver.count(y) == 0);
 | 
			
		||||
				driver[y] = cell;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -262,10 +262,10 @@ struct ExtractFaWorker
 | 
			
		|||
			pool<SigBit> new_leaves = leaves;
 | 
			
		||||
 | 
			
		||||
			new_leaves.erase(bit);
 | 
			
		||||
			if (cell->hasPort("\\A")) new_leaves.insert(sigmap(SigBit(cell->getPort("\\A"))));
 | 
			
		||||
			if (cell->hasPort("\\B")) new_leaves.insert(sigmap(SigBit(cell->getPort("\\B"))));
 | 
			
		||||
			if (cell->hasPort("\\C")) new_leaves.insert(sigmap(SigBit(cell->getPort("\\C"))));
 | 
			
		||||
			if (cell->hasPort("\\D")) new_leaves.insert(sigmap(SigBit(cell->getPort("\\D"))));
 | 
			
		||||
			if (cell->hasPort(ID(A))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(A)))));
 | 
			
		||||
			if (cell->hasPort(ID(B))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(B)))));
 | 
			
		||||
			if (cell->hasPort(ID(C))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(C)))));
 | 
			
		||||
			if (cell->hasPort(ID(D))) new_leaves.insert(sigmap(SigBit(cell->getPort(ID(D)))));
 | 
			
		||||
 | 
			
		||||
			if (GetSize(new_leaves) > maxbreadth)
 | 
			
		||||
				continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -277,8 +277,8 @@ struct ExtractFaWorker
 | 
			
		|||
	void assign_new_driver(SigBit bit, SigBit new_driver)
 | 
			
		||||
	{
 | 
			
		||||
		Cell *cell = driver.at(bit);
 | 
			
		||||
		if (sigmap(cell->getPort("\\Y")) == bit) {
 | 
			
		||||
			cell->setPort("\\Y", module->addWire(NEW_ID));
 | 
			
		||||
		if (sigmap(cell->getPort(ID(Y))) == bit) {
 | 
			
		||||
			cell->setPort(ID(Y), module->addWire(NEW_ID));
 | 
			
		||||
			module->connect(bit, new_driver);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -289,7 +289,7 @@ struct ExtractFaWorker
 | 
			
		|||
 | 
			
		||||
		for (auto it : driver)
 | 
			
		||||
		{
 | 
			
		||||
			if (it.second->type.in("$_BUF_", "$_NOT_"))
 | 
			
		||||
			if (it.second->type.in(ID($_BUF_), ID($_NOT_)))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			SigBit root = it.first;
 | 
			
		||||
| 
						 | 
				
			
			@ -390,20 +390,20 @@ struct ExtractFaWorker
 | 
			
		|||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					Cell *cell = module->addCell(NEW_ID, "$fa");
 | 
			
		||||
					cell->setParam("\\WIDTH", 1);
 | 
			
		||||
					Cell *cell = module->addCell(NEW_ID, ID($fa));
 | 
			
		||||
					cell->setParam(ID(WIDTH), 1);
 | 
			
		||||
 | 
			
		||||
					log("      Created $fa cell %s.\n", log_id(cell));
 | 
			
		||||
 | 
			
		||||
					cell->setPort("\\A", f3i.inv_a ? module->NotGate(NEW_ID, A) : A);
 | 
			
		||||
					cell->setPort("\\B", f3i.inv_b ? module->NotGate(NEW_ID, B) : B);
 | 
			
		||||
					cell->setPort("\\C", f3i.inv_c ? module->NotGate(NEW_ID, C) : C);
 | 
			
		||||
					cell->setPort(ID(A), f3i.inv_a ? module->NotGate(NEW_ID, A) : A);
 | 
			
		||||
					cell->setPort(ID(B), f3i.inv_b ? module->NotGate(NEW_ID, B) : B);
 | 
			
		||||
					cell->setPort(ID(C), f3i.inv_c ? module->NotGate(NEW_ID, C) : C);
 | 
			
		||||
 | 
			
		||||
					X = module->addWire(NEW_ID);
 | 
			
		||||
					Y = module->addWire(NEW_ID);
 | 
			
		||||
 | 
			
		||||
					cell->setPort("\\X", X);
 | 
			
		||||
					cell->setPort("\\Y", Y);
 | 
			
		||||
					cell->setPort(ID(X), X);
 | 
			
		||||
					cell->setPort(ID(Y), Y);
 | 
			
		||||
 | 
			
		||||
					facache[fakey] = make_tuple(X, Y, cell);
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -496,30 +496,30 @@ struct ExtractFaWorker
 | 
			
		|||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					Cell *cell = module->addCell(NEW_ID, "$fa");
 | 
			
		||||
					cell->setParam("\\WIDTH", 1);
 | 
			
		||||
					Cell *cell = module->addCell(NEW_ID, ID($fa));
 | 
			
		||||
					cell->setParam(ID(WIDTH), 1);
 | 
			
		||||
 | 
			
		||||
					log("      Created $fa cell %s.\n", log_id(cell));
 | 
			
		||||
 | 
			
		||||
					cell->setPort("\\A", f2i.inv_a ? module->NotGate(NEW_ID, A) : A);
 | 
			
		||||
					cell->setPort("\\B", f2i.inv_b ? module->NotGate(NEW_ID, B) : B);
 | 
			
		||||
					cell->setPort("\\C", State::S0);
 | 
			
		||||
					cell->setPort(ID(A), f2i.inv_a ? module->NotGate(NEW_ID, A) : A);
 | 
			
		||||
					cell->setPort(ID(B), f2i.inv_b ? module->NotGate(NEW_ID, B) : B);
 | 
			
		||||
					cell->setPort(ID(C), State::S0);
 | 
			
		||||
 | 
			
		||||
					X = module->addWire(NEW_ID);
 | 
			
		||||
					Y = module->addWire(NEW_ID);
 | 
			
		||||
 | 
			
		||||
					cell->setPort("\\X", X);
 | 
			
		||||
					cell->setPort("\\Y", Y);
 | 
			
		||||
					cell->setPort(ID(X), X);
 | 
			
		||||
					cell->setPort(ID(Y), Y);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (func2.at(key).count(xor2_func)) {
 | 
			
		||||
					SigBit YY = invert_xy ? module->NotGate(NEW_ID, Y) : Y;
 | 
			
		||||
					SigBit YY = invert_xy || (f2i.inv_a && !f2i.inv_b) || (!f2i.inv_a && f2i.inv_b) ? module->NotGate(NEW_ID, Y) : Y;
 | 
			
		||||
					for (auto bit : func2.at(key).at(xor2_func))
 | 
			
		||||
						assign_new_driver(bit, YY);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (func2.at(key).count(xnor2_func)) {
 | 
			
		||||
					SigBit YY = invert_xy ? Y : module->NotGate(NEW_ID, Y);
 | 
			
		||||
					SigBit YY = invert_xy || (f2i.inv_a && !f2i.inv_b) || (!f2i.inv_a && f2i.inv_b) ? Y : module->NotGate(NEW_ID, Y);
 | 
			
		||||
					for (auto bit : func2.at(key).at(xnor2_func))
 | 
			
		||||
						assign_new_driver(bit, YY);
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,9 +58,9 @@ struct ExtractReducePass : public Pass
 | 
			
		|||
 | 
			
		||||
	inline bool IsRightType(Cell* cell, GateType gt)
 | 
			
		||||
	{
 | 
			
		||||
		return (cell->type == "$_AND_" && gt == GateType::And) ||
 | 
			
		||||
				(cell->type == "$_OR_" && gt == GateType::Or) ||
 | 
			
		||||
				(cell->type == "$_XOR_" && gt == GateType::Xor);
 | 
			
		||||
		return (cell->type == ID($_AND_) && gt == GateType::And) ||
 | 
			
		||||
				(cell->type == ID($_OR_) && gt == GateType::Or) ||
 | 
			
		||||
				(cell->type == ID($_XOR_) && gt == GateType::Xor);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
| 
						 | 
				
			
			@ -124,11 +124,11 @@ struct ExtractReducePass : public Pass
 | 
			
		|||
 | 
			
		||||
				GateType gt;
 | 
			
		||||
 | 
			
		||||
				if (cell->type == "$_AND_")
 | 
			
		||||
				if (cell->type == ID($_AND_))
 | 
			
		||||
					gt = GateType::And;
 | 
			
		||||
				else if (cell->type == "$_OR_")
 | 
			
		||||
				else if (cell->type == ID($_OR_))
 | 
			
		||||
					gt = GateType::Or;
 | 
			
		||||
				else if (cell->type == "$_XOR_")
 | 
			
		||||
				else if (cell->type == ID($_XOR_))
 | 
			
		||||
					gt = GateType::Xor;
 | 
			
		||||
				else
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ struct ExtractReducePass : public Pass
 | 
			
		|||
 | 
			
		||||
						head_cell = x;
 | 
			
		||||
 | 
			
		||||
						auto y = sigmap(x->getPort("\\Y"));
 | 
			
		||||
						auto y = sigmap(x->getPort(ID(Y)));
 | 
			
		||||
						log_assert(y.size() == 1);
 | 
			
		||||
 | 
			
		||||
						// Should only continue if there is one fanout back into a cell (not to a port)
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +166,7 @@ struct ExtractReducePass : public Pass
 | 
			
		|||
				{
 | 
			
		||||
					//BFS, following all chains until they hit a cell of a different type
 | 
			
		||||
					//Pick the longest one
 | 
			
		||||
					auto y = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
					auto y = sigmap(cell->getPort(ID(Y)));
 | 
			
		||||
					pool<Cell*> current_loads = sig_to_sink[y];
 | 
			
		||||
					pool<Cell*> next_loads;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -233,7 +233,7 @@ struct ExtractReducePass : public Pass
 | 
			
		|||
 | 
			
		||||
						cur_supercell.insert(x);
 | 
			
		||||
 | 
			
		||||
						auto a = sigmap(x->getPort("\\A"));
 | 
			
		||||
						auto a = sigmap(x->getPort(ID(A)));
 | 
			
		||||
						log_assert(a.size() == 1);
 | 
			
		||||
 | 
			
		||||
						// Must have only one sink unless we're going off chain
 | 
			
		||||
| 
						 | 
				
			
			@ -249,7 +249,7 @@ struct ExtractReducePass : public Pass
 | 
			
		|||
							}
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						auto b = sigmap(x->getPort("\\B"));
 | 
			
		||||
						auto b = sigmap(x->getPort(ID(B)));
 | 
			
		||||
						log_assert(b.size() == 1);
 | 
			
		||||
 | 
			
		||||
						// Must have only one sink
 | 
			
		||||
| 
						 | 
				
			
			@ -279,26 +279,26 @@ struct ExtractReducePass : public Pass
 | 
			
		|||
						pool<SigBit> input_pool_intermed;
 | 
			
		||||
						for (auto x : cur_supercell)
 | 
			
		||||
						{
 | 
			
		||||
							input_pool.insert(sigmap(x->getPort("\\A"))[0]);
 | 
			
		||||
							input_pool.insert(sigmap(x->getPort("\\B"))[0]);
 | 
			
		||||
							input_pool_intermed.insert(sigmap(x->getPort("\\Y"))[0]);
 | 
			
		||||
							input_pool.insert(sigmap(x->getPort(ID(A)))[0]);
 | 
			
		||||
							input_pool.insert(sigmap(x->getPort(ID(B)))[0]);
 | 
			
		||||
							input_pool_intermed.insert(sigmap(x->getPort(ID(Y)))[0]);
 | 
			
		||||
						}
 | 
			
		||||
						SigSpec input;
 | 
			
		||||
						for (auto b : input_pool)
 | 
			
		||||
							if (input_pool_intermed.count(b) == 0)
 | 
			
		||||
								input.append_bit(b);
 | 
			
		||||
 | 
			
		||||
						SigBit output = sigmap(head_cell->getPort("\\Y")[0]);
 | 
			
		||||
						SigBit output = sigmap(head_cell->getPort(ID(Y))[0]);
 | 
			
		||||
 | 
			
		||||
						auto new_reduce_cell = module->addCell(NEW_ID,
 | 
			
		||||
							gt == GateType::And ? "$reduce_and" :
 | 
			
		||||
							gt == GateType::Or ? "$reduce_or" :
 | 
			
		||||
							gt == GateType::Xor ? "$reduce_xor" : "");
 | 
			
		||||
						new_reduce_cell->setParam("\\A_SIGNED", 0);
 | 
			
		||||
						new_reduce_cell->setParam("\\A_WIDTH", input.size());
 | 
			
		||||
						new_reduce_cell->setParam("\\Y_WIDTH", 1);
 | 
			
		||||
						new_reduce_cell->setPort("\\A", input);
 | 
			
		||||
						new_reduce_cell->setPort("\\Y", output);
 | 
			
		||||
							gt == GateType::And ? ID($reduce_and) :
 | 
			
		||||
							gt == GateType::Or ? ID($reduce_or) :
 | 
			
		||||
							gt == GateType::Xor ? ID($reduce_xor) : "");
 | 
			
		||||
						new_reduce_cell->setParam(ID(A_SIGNED), 0);
 | 
			
		||||
						new_reduce_cell->setParam(ID(A_WIDTH), input.size());
 | 
			
		||||
						new_reduce_cell->setParam(ID(Y_WIDTH), 1);
 | 
			
		||||
						new_reduce_cell->setPort(ID(A), input);
 | 
			
		||||
						new_reduce_cell->setPort(ID(Y), output);
 | 
			
		||||
 | 
			
		||||
						if(allow_off_chain)
 | 
			
		||||
							consumed_cells.insert(head_cell);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -671,8 +671,8 @@ struct FlowmapWorker
 | 
			
		|||
			labels[node] = -1;
 | 
			
		||||
		for (auto input : inputs)
 | 
			
		||||
		{
 | 
			
		||||
			if (input.wire->attributes.count("\\$flowmap_level"))
 | 
			
		||||
				labels[input] = input.wire->attributes["\\$flowmap_level"].as_int();
 | 
			
		||||
			if (input.wire->attributes.count(ID($flowmap_level)))
 | 
			
		||||
				labels[input] = input.wire->attributes[ID($flowmap_level)].as_int();
 | 
			
		||||
			else
 | 
			
		||||
				labels[input] = 0;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1412,7 +1412,7 @@ struct FlowmapWorker
 | 
			
		|||
			for (auto gate_node : lut_gates[node])
 | 
			
		||||
			{
 | 
			
		||||
				auto gate_origin = node_origins[gate_node];
 | 
			
		||||
				lut->add_strpool_attribute("\\src", gate_origin.cell->get_strpool_attribute("\\src"));
 | 
			
		||||
				lut->add_strpool_attribute(ID(src), gate_origin.cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
				packed_count++;
 | 
			
		||||
			}
 | 
			
		||||
			lut_count++;
 | 
			
		||||
| 
						 | 
				
			
			@ -1586,7 +1586,7 @@ struct FlowmapPass : public Pass {
 | 
			
		|||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			cell_types = {"$_NOT_", "$_AND_", "$_OR_", "$_XOR_", "$_MUX_"};
 | 
			
		||||
			cell_types = {ID($_NOT_), ID($_AND_), ID($_OR_), ID($_XOR_), ID($_MUX_)};
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const char *algo_r = relax ? "-r" : "";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -197,8 +197,8 @@ struct IopadmapPass : public Pass {
 | 
			
		|||
				SigMap rewrites;
 | 
			
		||||
 | 
			
		||||
				for (auto cell : module->cells())
 | 
			
		||||
					if (cell->type == "$_TBUF_") {
 | 
			
		||||
						SigBit bit = sigmap(cell->getPort("\\Y").as_bit());
 | 
			
		||||
					if (cell->type == ID($_TBUF_)) {
 | 
			
		||||
						SigBit bit = sigmap(cell->getPort(ID(Y)).as_bit());
 | 
			
		||||
						tbuf_bits[bit].first = cell->name;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -230,8 +230,8 @@ struct IopadmapPass : public Pass {
 | 
			
		|||
						if (tbuf_cell == nullptr)
 | 
			
		||||
							continue;
 | 
			
		||||
 | 
			
		||||
						SigBit en_sig = tbuf_cell->getPort("\\E").as_bit();
 | 
			
		||||
						SigBit data_sig = tbuf_cell->getPort("\\A").as_bit();
 | 
			
		||||
						SigBit en_sig = tbuf_cell->getPort(ID(E)).as_bit();
 | 
			
		||||
						SigBit data_sig = tbuf_cell->getPort(ID(A)).as_bit();
 | 
			
		||||
 | 
			
		||||
						if (wire->port_input && !tinoutpad_celltype.empty())
 | 
			
		||||
						{
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +244,7 @@ struct IopadmapPass : public Pass {
 | 
			
		|||
							cell->setPort(RTLIL::escape_id(tinoutpad_portname2), owire);
 | 
			
		||||
							cell->setPort(RTLIL::escape_id(tinoutpad_portname3), data_sig);
 | 
			
		||||
							cell->setPort(RTLIL::escape_id(tinoutpad_portname4), wire_bit);
 | 
			
		||||
							cell->attributes["\\keep"] = RTLIL::Const(1);
 | 
			
		||||
							cell->attributes[ID(keep)] = RTLIL::Const(1);
 | 
			
		||||
 | 
			
		||||
							for (auto cn : tbuf_cache.second) {
 | 
			
		||||
								auto c = module->cell(cn);
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +281,7 @@ struct IopadmapPass : public Pass {
 | 
			
		|||
							cell->setPort(RTLIL::escape_id(toutpad_portname), en_sig);
 | 
			
		||||
							cell->setPort(RTLIL::escape_id(toutpad_portname2), data_sig);
 | 
			
		||||
							cell->setPort(RTLIL::escape_id(toutpad_portname3), wire_bit);
 | 
			
		||||
							cell->attributes["\\keep"] = RTLIL::Const(1);
 | 
			
		||||
							cell->attributes[ID(keep)] = RTLIL::Const(1);
 | 
			
		||||
 | 
			
		||||
							for (auto cn : tbuf_cache.second) {
 | 
			
		||||
								auto c = module->cell(cn);
 | 
			
		||||
| 
						 | 
				
			
			@ -408,7 +408,7 @@ struct IopadmapPass : public Pass {
 | 
			
		|||
							cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(1);
 | 
			
		||||
						if (!nameparam.empty())
 | 
			
		||||
							cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(stringf("%s[%d]", RTLIL::id2cstr(wire->name), i));
 | 
			
		||||
						cell->attributes["\\keep"] = RTLIL::Const(1);
 | 
			
		||||
						cell->attributes[ID(keep)] = RTLIL::Const(1);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
| 
						 | 
				
			
			@ -421,7 +421,7 @@ struct IopadmapPass : public Pass {
 | 
			
		|||
						cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);
 | 
			
		||||
					if (!nameparam.empty())
 | 
			
		||||
						cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(RTLIL::id2cstr(wire->name));
 | 
			
		||||
					cell->attributes["\\keep"] = RTLIL::Const(1);
 | 
			
		||||
					cell->attributes[ID(keep)] = RTLIL::Const(1);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				wire->port_id = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,9 +25,9 @@ PRIVATE_NAMESPACE_BEGIN
 | 
			
		|||
 | 
			
		||||
int lut2mux(Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	Const lut = cell->getParam("\\LUT");
 | 
			
		||||
	SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
	Const lut = cell->getParam(ID(LUT));
 | 
			
		||||
	int count = 1;
 | 
			
		||||
 | 
			
		||||
	if (GetSize(sig_a) == 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +81,7 @@ struct Lut2muxPass : public Pass {
 | 
			
		|||
 | 
			
		||||
		for (auto module : design->selected_modules())
 | 
			
		||||
		for (auto cell : module->selected_cells()) {
 | 
			
		||||
			if (cell->type == "$lut") {
 | 
			
		||||
			if (cell->type == ID($lut)) {
 | 
			
		||||
				IdString cell_name = cell->name;
 | 
			
		||||
				int count = lut2mux(cell);
 | 
			
		||||
				log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,13 +111,13 @@ struct MaccmapWorker
 | 
			
		|||
			RTLIL::Wire *w1 = module->addWire(NEW_ID, width);
 | 
			
		||||
			RTLIL::Wire *w2 = module->addWire(NEW_ID, width);
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *cell = module->addCell(NEW_ID, "$fa");
 | 
			
		||||
			cell->setParam("\\WIDTH", width);
 | 
			
		||||
			cell->setPort("\\A", in1);
 | 
			
		||||
			cell->setPort("\\B", in2);
 | 
			
		||||
			cell->setPort("\\C", in3);
 | 
			
		||||
			cell->setPort("\\Y", w1);
 | 
			
		||||
			cell->setPort("\\X", w2);
 | 
			
		||||
			RTLIL::Cell *cell = module->addCell(NEW_ID, ID($fa));
 | 
			
		||||
			cell->setParam(ID(WIDTH), width);
 | 
			
		||||
			cell->setPort(ID(A), in1);
 | 
			
		||||
			cell->setPort(ID(B), in2);
 | 
			
		||||
			cell->setPort(ID(C), in3);
 | 
			
		||||
			cell->setPort(ID(Y), w1);
 | 
			
		||||
			cell->setPort(ID(X), w2);
 | 
			
		||||
 | 
			
		||||
			out1 = {out_zeros_msb, w1, out_zeros_lsb};
 | 
			
		||||
			out2 = {out_zeros_msb, w2, out_zeros_lsb};
 | 
			
		||||
| 
						 | 
				
			
			@ -237,23 +237,23 @@ struct MaccmapWorker
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		RTLIL::Cell *c = module->addCell(NEW_ID, "$alu");
 | 
			
		||||
		c->setPort("\\A", summands.front());
 | 
			
		||||
		c->setPort("\\B", summands.back());
 | 
			
		||||
		c->setPort("\\CI", State::S0);
 | 
			
		||||
		c->setPort("\\BI", State::S0);
 | 
			
		||||
		c->setPort("\\Y", module->addWire(NEW_ID, width));
 | 
			
		||||
		c->setPort("\\X", module->addWire(NEW_ID, width));
 | 
			
		||||
		c->setPort("\\CO", module->addWire(NEW_ID, width));
 | 
			
		||||
		RTLIL::Cell *c = module->addCell(NEW_ID, ID($alu));
 | 
			
		||||
		c->setPort(ID(A), summands.front());
 | 
			
		||||
		c->setPort(ID(B), summands.back());
 | 
			
		||||
		c->setPort(ID(CI), State::S0);
 | 
			
		||||
		c->setPort(ID(BI), State::S0);
 | 
			
		||||
		c->setPort(ID(Y), module->addWire(NEW_ID, width));
 | 
			
		||||
		c->setPort(ID(X), module->addWire(NEW_ID, width));
 | 
			
		||||
		c->setPort(ID(CO), module->addWire(NEW_ID, width));
 | 
			
		||||
		c->fixup_parameters();
 | 
			
		||||
 | 
			
		||||
		if (!tree_sum_bits.empty()) {
 | 
			
		||||
			c->setPort("\\CI", tree_sum_bits.back());
 | 
			
		||||
			c->setPort(ID(CI), tree_sum_bits.back());
 | 
			
		||||
			tree_sum_bits.pop_back();
 | 
			
		||||
		}
 | 
			
		||||
		log_assert(tree_sum_bits.empty());
 | 
			
		||||
 | 
			
		||||
		return c->getPort("\\Y");
 | 
			
		||||
		return c->getPort(ID(Y));
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -264,17 +264,17 @@ extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false
 | 
			
		|||
 | 
			
		||||
void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
 | 
			
		||||
{
 | 
			
		||||
	int width = GetSize(cell->getPort("\\Y"));
 | 
			
		||||
	int width = GetSize(cell->getPort(ID(Y)));
 | 
			
		||||
 | 
			
		||||
	Macc macc;
 | 
			
		||||
	macc.from_cell(cell);
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec all_input_bits;
 | 
			
		||||
	all_input_bits.append(cell->getPort("\\A"));
 | 
			
		||||
	all_input_bits.append(cell->getPort("\\B"));
 | 
			
		||||
	all_input_bits.append(cell->getPort(ID(A)));
 | 
			
		||||
	all_input_bits.append(cell->getPort(ID(B)));
 | 
			
		||||
 | 
			
		||||
	if (all_input_bits.to_sigbit_set().count(RTLIL::Sx)) {
 | 
			
		||||
		module->connect(cell->getPort("\\Y"), RTLIL::SigSpec(RTLIL::Sx, width));
 | 
			
		||||
		module->connect(cell->getPort(ID(Y)), RTLIL::SigSpec(RTLIL::Sx, width));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -339,9 +339,9 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if (summands.front().second)
 | 
			
		||||
			module->addNeg(NEW_ID, summands.front().first, cell->getPort("\\Y"));
 | 
			
		||||
			module->addNeg(NEW_ID, summands.front().first, cell->getPort(ID(Y)));
 | 
			
		||||
		else
 | 
			
		||||
			module->connect(cell->getPort("\\Y"), summands.front().first);
 | 
			
		||||
			module->connect(cell->getPort(ID(Y)), summands.front().first);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -356,7 +356,7 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
 | 
			
		|||
		for (auto &bit : macc.bit_ports)
 | 
			
		||||
			worker.add(bit, 0);
 | 
			
		||||
 | 
			
		||||
		module->connect(cell->getPort("\\Y"), worker.synth());
 | 
			
		||||
		module->connect(cell->getPort(ID(Y)), worker.synth());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -393,7 +393,7 @@ struct MaccmapPass : public Pass {
 | 
			
		|||
 | 
			
		||||
		for (auto mod : design->selected_modules())
 | 
			
		||||
		for (auto cell : mod->selected_cells())
 | 
			
		||||
			if (cell->type == "$macc") {
 | 
			
		||||
			if (cell->type == ID($macc)) {
 | 
			
		||||
				log("Mapping %s.%s (%s).\n", log_id(mod), log_id(cell), log_id(cell->type));
 | 
			
		||||
				maccmap(mod, cell, unmap_mode);
 | 
			
		||||
				mod->remove(cell);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -116,13 +116,13 @@ struct MuxcoverWorker
 | 
			
		|||
				if (!cell->input(conn.first))
 | 
			
		||||
					continue;
 | 
			
		||||
				for (auto bit : sigmap(conn.second)) {
 | 
			
		||||
					if (used_once.count(bit) || cell->type != "$_MUX_" || conn.first == "\\S")
 | 
			
		||||
					if (used_once.count(bit) || cell->type != ID($_MUX_) || conn.first == ID(S))
 | 
			
		||||
						roots.insert(bit);
 | 
			
		||||
					used_once.insert(bit);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (cell->type == "$_MUX_")
 | 
			
		||||
				sig_to_mux[sigmap(cell->getPort("\\Y"))] = cell;
 | 
			
		||||
			if (cell->type == ID($_MUX_))
 | 
			
		||||
				sig_to_mux[sigmap(cell->getPort(ID(Y)))] = cell;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log("  Treeifying %d MUXes:\n", GetSize(sig_to_mux));
 | 
			
		||||
| 
						 | 
				
			
			@ -141,8 +141,8 @@ struct MuxcoverWorker
 | 
			
		|||
				if (sig_to_mux.count(bit) && (bit == rootsig || !roots.count(bit))) {
 | 
			
		||||
					Cell *c = sig_to_mux.at(bit);
 | 
			
		||||
					tree.muxes[bit] = c;
 | 
			
		||||
					wavefront.insert(sigmap(c->getPort("\\A")));
 | 
			
		||||
					wavefront.insert(sigmap(c->getPort("\\B")));
 | 
			
		||||
					wavefront.insert(sigmap(c->getPort(ID(A))));
 | 
			
		||||
					wavefront.insert(sigmap(c->getPort(ID(B))));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -516,69 +516,69 @@ struct MuxcoverWorker
 | 
			
		|||
 | 
			
		||||
		if (GetSize(mux.inputs) == 2) {
 | 
			
		||||
			count_muxes_by_type[0]++;
 | 
			
		||||
			Cell *cell = module->addCell(NEW_ID, "$_MUX_");
 | 
			
		||||
			cell->setPort("\\A", mux.inputs[0]);
 | 
			
		||||
			cell->setPort("\\B", mux.inputs[1]);
 | 
			
		||||
			cell->setPort("\\S", mux.selects[0]);
 | 
			
		||||
			cell->setPort("\\Y", bit);
 | 
			
		||||
			Cell *cell = module->addCell(NEW_ID, ID($_MUX_));
 | 
			
		||||
			cell->setPort(ID(A), mux.inputs[0]);
 | 
			
		||||
			cell->setPort(ID(B), mux.inputs[1]);
 | 
			
		||||
			cell->setPort(ID(S), mux.selects[0]);
 | 
			
		||||
			cell->setPort(ID(Y), bit);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (GetSize(mux.inputs) == 4) {
 | 
			
		||||
			count_muxes_by_type[1]++;
 | 
			
		||||
			Cell *cell = module->addCell(NEW_ID, "$_MUX4_");
 | 
			
		||||
			cell->setPort("\\A", mux.inputs[0]);
 | 
			
		||||
			cell->setPort("\\B", mux.inputs[1]);
 | 
			
		||||
			cell->setPort("\\C", mux.inputs[2]);
 | 
			
		||||
			cell->setPort("\\D", mux.inputs[3]);
 | 
			
		||||
			cell->setPort("\\S", mux.selects[0]);
 | 
			
		||||
			cell->setPort("\\T", mux.selects[1]);
 | 
			
		||||
			cell->setPort("\\Y", bit);
 | 
			
		||||
			Cell *cell = module->addCell(NEW_ID, ID($_MUX4_));
 | 
			
		||||
			cell->setPort(ID(A), mux.inputs[0]);
 | 
			
		||||
			cell->setPort(ID(B), mux.inputs[1]);
 | 
			
		||||
			cell->setPort(ID(C), mux.inputs[2]);
 | 
			
		||||
			cell->setPort(ID(D), mux.inputs[3]);
 | 
			
		||||
			cell->setPort(ID(S), mux.selects[0]);
 | 
			
		||||
			cell->setPort(ID(T), mux.selects[1]);
 | 
			
		||||
			cell->setPort(ID(Y), bit);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (GetSize(mux.inputs) == 8) {
 | 
			
		||||
			count_muxes_by_type[2]++;
 | 
			
		||||
			Cell *cell = module->addCell(NEW_ID, "$_MUX8_");
 | 
			
		||||
			cell->setPort("\\A", mux.inputs[0]);
 | 
			
		||||
			cell->setPort("\\B", mux.inputs[1]);
 | 
			
		||||
			cell->setPort("\\C", mux.inputs[2]);
 | 
			
		||||
			cell->setPort("\\D", mux.inputs[3]);
 | 
			
		||||
			cell->setPort("\\E", mux.inputs[4]);
 | 
			
		||||
			cell->setPort("\\F", mux.inputs[5]);
 | 
			
		||||
			cell->setPort("\\G", mux.inputs[6]);
 | 
			
		||||
			cell->setPort("\\H", mux.inputs[7]);
 | 
			
		||||
			cell->setPort("\\S", mux.selects[0]);
 | 
			
		||||
			cell->setPort("\\T", mux.selects[1]);
 | 
			
		||||
			cell->setPort("\\U", mux.selects[2]);
 | 
			
		||||
			cell->setPort("\\Y", bit);
 | 
			
		||||
			Cell *cell = module->addCell(NEW_ID, ID($_MUX8_));
 | 
			
		||||
			cell->setPort(ID(A), mux.inputs[0]);
 | 
			
		||||
			cell->setPort(ID(B), mux.inputs[1]);
 | 
			
		||||
			cell->setPort(ID(C), mux.inputs[2]);
 | 
			
		||||
			cell->setPort(ID(D), mux.inputs[3]);
 | 
			
		||||
			cell->setPort(ID(E), mux.inputs[4]);
 | 
			
		||||
			cell->setPort(ID(F), mux.inputs[5]);
 | 
			
		||||
			cell->setPort(ID(G), mux.inputs[6]);
 | 
			
		||||
			cell->setPort(ID(H), mux.inputs[7]);
 | 
			
		||||
			cell->setPort(ID(S), mux.selects[0]);
 | 
			
		||||
			cell->setPort(ID(T), mux.selects[1]);
 | 
			
		||||
			cell->setPort(ID(U), mux.selects[2]);
 | 
			
		||||
			cell->setPort(ID(Y), bit);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (GetSize(mux.inputs) == 16) {
 | 
			
		||||
			count_muxes_by_type[3]++;
 | 
			
		||||
			Cell *cell = module->addCell(NEW_ID, "$_MUX16_");
 | 
			
		||||
			cell->setPort("\\A", mux.inputs[0]);
 | 
			
		||||
			cell->setPort("\\B", mux.inputs[1]);
 | 
			
		||||
			cell->setPort("\\C", mux.inputs[2]);
 | 
			
		||||
			cell->setPort("\\D", mux.inputs[3]);
 | 
			
		||||
			cell->setPort("\\E", mux.inputs[4]);
 | 
			
		||||
			cell->setPort("\\F", mux.inputs[5]);
 | 
			
		||||
			cell->setPort("\\G", mux.inputs[6]);
 | 
			
		||||
			cell->setPort("\\H", mux.inputs[7]);
 | 
			
		||||
			cell->setPort("\\I", mux.inputs[8]);
 | 
			
		||||
			cell->setPort("\\J", mux.inputs[9]);
 | 
			
		||||
			cell->setPort("\\K", mux.inputs[10]);
 | 
			
		||||
			cell->setPort("\\L", mux.inputs[11]);
 | 
			
		||||
			cell->setPort("\\M", mux.inputs[12]);
 | 
			
		||||
			cell->setPort("\\N", mux.inputs[13]);
 | 
			
		||||
			cell->setPort("\\O", mux.inputs[14]);
 | 
			
		||||
			cell->setPort("\\P", mux.inputs[15]);
 | 
			
		||||
			cell->setPort("\\S", mux.selects[0]);
 | 
			
		||||
			cell->setPort("\\T", mux.selects[1]);
 | 
			
		||||
			cell->setPort("\\U", mux.selects[2]);
 | 
			
		||||
			cell->setPort("\\V", mux.selects[3]);
 | 
			
		||||
			cell->setPort("\\Y", bit);
 | 
			
		||||
			Cell *cell = module->addCell(NEW_ID, ID($_MUX16_));
 | 
			
		||||
			cell->setPort(ID(A), mux.inputs[0]);
 | 
			
		||||
			cell->setPort(ID(B), mux.inputs[1]);
 | 
			
		||||
			cell->setPort(ID(C), mux.inputs[2]);
 | 
			
		||||
			cell->setPort(ID(D), mux.inputs[3]);
 | 
			
		||||
			cell->setPort(ID(E), mux.inputs[4]);
 | 
			
		||||
			cell->setPort(ID(F), mux.inputs[5]);
 | 
			
		||||
			cell->setPort(ID(G), mux.inputs[6]);
 | 
			
		||||
			cell->setPort(ID(H), mux.inputs[7]);
 | 
			
		||||
			cell->setPort(ID(I), mux.inputs[8]);
 | 
			
		||||
			cell->setPort(ID(J), mux.inputs[9]);
 | 
			
		||||
			cell->setPort(ID(K), mux.inputs[10]);
 | 
			
		||||
			cell->setPort(ID(L), mux.inputs[11]);
 | 
			
		||||
			cell->setPort(ID(M), mux.inputs[12]);
 | 
			
		||||
			cell->setPort(ID(N), mux.inputs[13]);
 | 
			
		||||
			cell->setPort(ID(O), mux.inputs[14]);
 | 
			
		||||
			cell->setPort(ID(P), mux.inputs[15]);
 | 
			
		||||
			cell->setPort(ID(S), mux.selects[0]);
 | 
			
		||||
			cell->setPort(ID(T), mux.selects[1]);
 | 
			
		||||
			cell->setPort(ID(U), mux.selects[2]);
 | 
			
		||||
			cell->setPort(ID(V), mux.selects[3]);
 | 
			
		||||
			cell->setPort(ID(Y), bit);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,10 +82,10 @@ struct NlutmapWorker
 | 
			
		|||
 | 
			
		||||
			for (auto cell : module->cells())
 | 
			
		||||
			{
 | 
			
		||||
				if (cell->type != "$lut" || mapped_cells.count(cell))
 | 
			
		||||
				if (cell->type != ID($lut) || mapped_cells.count(cell))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				if (GetSize(cell->getPort("\\A")) == lut_size || lut_size == 2)
 | 
			
		||||
				if (GetSize(cell->getPort(ID(A))) == lut_size || lut_size == 2)
 | 
			
		||||
					candidate_ratings[cell] = 0;
 | 
			
		||||
 | 
			
		||||
				for (auto &conn : cell->connections())
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +119,7 @@ struct NlutmapWorker
 | 
			
		|||
 | 
			
		||||
		if (config.assert_mode) {
 | 
			
		||||
			for (auto cell : module->cells())
 | 
			
		||||
				if (cell->type == "$lut" && !mapped_cells.count(cell))
 | 
			
		||||
				if (cell->type == ID($lut) && !mapped_cells.count(cell))
 | 
			
		||||
					log_error("Insufficient number of LUTs to map all logic cells!\n");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,21 +89,21 @@ struct PmuxtreePass : public Pass {
 | 
			
		|||
		for (auto module : design->selected_modules())
 | 
			
		||||
		for (auto cell : module->selected_cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type != "$pmux")
 | 
			
		||||
			if (cell->type != ID($pmux))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			SigSpec sig_data = cell->getPort("\\B");
 | 
			
		||||
			SigSpec sig_sel = cell->getPort("\\S");
 | 
			
		||||
			SigSpec sig_data = cell->getPort(ID(B));
 | 
			
		||||
			SigSpec sig_sel = cell->getPort(ID(S));
 | 
			
		||||
 | 
			
		||||
			if (!cell->getPort("\\A").is_fully_undef()) {
 | 
			
		||||
				sig_data.append(cell->getPort("\\A"));
 | 
			
		||||
			if (!cell->getPort(ID(A)).is_fully_undef()) {
 | 
			
		||||
				sig_data.append(cell->getPort(ID(A)));
 | 
			
		||||
				SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel);
 | 
			
		||||
				sig_sel.append(module->Not(NEW_ID, sig_sel_or));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			SigSpec result, result_or;
 | 
			
		||||
			result = recursive_mux_generator(module, sig_data, sig_sel, result_or);
 | 
			
		||||
			module->connect(cell->getPort("\\Y"), result);
 | 
			
		||||
			module->connect(cell->getPort(ID(Y)), result);
 | 
			
		||||
			module->remove(cell);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,22 +73,22 @@ struct ShregmapTechGreenpak4 : ShregmapTech
 | 
			
		|||
 | 
			
		||||
	bool fixup(Cell *cell, dict<int, SigBit> &taps)
 | 
			
		||||
	{
 | 
			
		||||
		auto D = cell->getPort("\\D");
 | 
			
		||||
		auto C = cell->getPort("\\C");
 | 
			
		||||
		auto D = cell->getPort(ID(D));
 | 
			
		||||
		auto C = cell->getPort(ID(C));
 | 
			
		||||
 | 
			
		||||
		auto newcell = cell->module->addCell(NEW_ID, "\\GP_SHREG");
 | 
			
		||||
		newcell->setPort("\\nRST", State::S1);
 | 
			
		||||
		newcell->setPort("\\CLK", C);
 | 
			
		||||
		newcell->setPort("\\IN", D);
 | 
			
		||||
		auto newcell = cell->module->addCell(NEW_ID, ID(GP_SHREG));
 | 
			
		||||
		newcell->setPort(ID(nRST), State::S1);
 | 
			
		||||
		newcell->setPort(ID(CLK), C);
 | 
			
		||||
		newcell->setPort(ID(IN), D);
 | 
			
		||||
 | 
			
		||||
		int i = 0;
 | 
			
		||||
		for (auto tap : taps) {
 | 
			
		||||
			newcell->setPort(i ? "\\OUTB" : "\\OUTA", tap.second);
 | 
			
		||||
			newcell->setParam(i ? "\\OUTB_TAP" : "\\OUTA_TAP", tap.first + 1);
 | 
			
		||||
			newcell->setPort(i ? ID(OUTB) : ID(OUTA), tap.second);
 | 
			
		||||
			newcell->setParam(i ? ID(OUTB_TAP) : ID(OUTA_TAP), tap.first + 1);
 | 
			
		||||
			i++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cell->setParam("\\OUTA_INVERT", 0);
 | 
			
		||||
		cell->setParam(ID(OUTA_INVERT), 0);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -104,19 +104,19 @@ struct ShregmapTechXilinx7 : ShregmapTech
 | 
			
		|||
	{
 | 
			
		||||
		for (const auto &i : module->cells_) {
 | 
			
		||||
			auto cell = i.second;
 | 
			
		||||
			if (cell->type == "$shiftx") {
 | 
			
		||||
				if (cell->getParam("\\Y_WIDTH") != 1) continue;
 | 
			
		||||
			if (cell->type == ID($shiftx)) {
 | 
			
		||||
				if (cell->getParam(ID(Y_WIDTH)) != 1) continue;
 | 
			
		||||
				int j = 0;
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort("\\A")))
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort(ID(A))))
 | 
			
		||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0);
 | 
			
		||||
				log_assert(j == cell->getParam("\\A_WIDTH").as_int());
 | 
			
		||||
				log_assert(j == cell->getParam(ID(A_WIDTH)).as_int());
 | 
			
		||||
			}
 | 
			
		||||
			else if (cell->type == "$mux") {
 | 
			
		||||
			else if (cell->type == ID($mux)) {
 | 
			
		||||
				int j = 0;
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort("\\A")))
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort(ID(A))))
 | 
			
		||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++);
 | 
			
		||||
				j = 0;
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort("\\B")))
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort(ID(B))))
 | 
			
		||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -128,9 +128,9 @@ struct ShregmapTechXilinx7 : ShregmapTech
 | 
			
		|||
		if (it == sigbit_to_shiftx_offset.end())
 | 
			
		||||
			return;
 | 
			
		||||
		if (cell) {
 | 
			
		||||
			if (cell->type == "$shiftx" && port == "\\A")
 | 
			
		||||
			if (cell->type == ID($shiftx) && port == ID(A))
 | 
			
		||||
				return;
 | 
			
		||||
			if (cell->type == "$mux" && (port == "\\A" || port == "\\B"))
 | 
			
		||||
			if (cell->type == ID($mux) && port.in(ID(A), ID(B)))
 | 
			
		||||
				return;
 | 
			
		||||
		}
 | 
			
		||||
		sigbit_to_shiftx_offset.erase(it);
 | 
			
		||||
| 
						 | 
				
			
			@ -177,21 +177,21 @@ struct ShregmapTechXilinx7 : ShregmapTech
 | 
			
		|||
		log_assert(shiftx);
 | 
			
		||||
 | 
			
		||||
		// Only map if $shiftx exclusively covers the shift register
 | 
			
		||||
		if (shiftx->type == "$shiftx") {
 | 
			
		||||
			if (GetSize(taps) > shiftx->getParam("\\A_WIDTH").as_int())
 | 
			
		||||
		if (shiftx->type == ID($shiftx)) {
 | 
			
		||||
			if (GetSize(taps) > shiftx->getParam(ID(A_WIDTH)).as_int())
 | 
			
		||||
				return false;
 | 
			
		||||
			// Due to padding the most significant bits of A may be 1'bx,
 | 
			
		||||
			//   and if so, discount them
 | 
			
		||||
			if (GetSize(taps) < shiftx->getParam("\\A_WIDTH").as_int()) {
 | 
			
		||||
				const SigSpec A = shiftx->getPort("\\A");
 | 
			
		||||
				const int A_width = shiftx->getParam("\\A_WIDTH").as_int();
 | 
			
		||||
			if (GetSize(taps) < shiftx->getParam(ID(A_WIDTH)).as_int()) {
 | 
			
		||||
				const SigSpec A = shiftx->getPort(ID(A));
 | 
			
		||||
				const int A_width = shiftx->getParam(ID(A_WIDTH)).as_int();
 | 
			
		||||
				for (int i = GetSize(taps); i < A_width; ++i)
 | 
			
		||||
					if (A[i] != RTLIL::Sx) return false;
 | 
			
		||||
			}
 | 
			
		||||
			else if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int())
 | 
			
		||||
			else if (GetSize(taps) != shiftx->getParam(ID(A_WIDTH)).as_int())
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
		else if (shiftx->type == "$mux") {
 | 
			
		||||
		else if (shiftx->type == ID($mux)) {
 | 
			
		||||
			if (GetSize(taps) != 2)
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -208,34 +208,34 @@ struct ShregmapTechXilinx7 : ShregmapTech
 | 
			
		|||
		auto it = sigbit_to_shiftx_offset.find(bit);
 | 
			
		||||
		log_assert(it != sigbit_to_shiftx_offset.end());
 | 
			
		||||
 | 
			
		||||
		auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_");
 | 
			
		||||
		auto newcell = cell->module->addCell(NEW_ID, ID($__XILINX_SHREG_));
 | 
			
		||||
		newcell->set_src_attribute(cell->get_src_attribute());
 | 
			
		||||
		newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH"));
 | 
			
		||||
		newcell->setParam("\\INIT", cell->getParam("\\INIT"));
 | 
			
		||||
		newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL"));
 | 
			
		||||
		newcell->setParam("\\ENPOL", cell->getParam("\\ENPOL"));
 | 
			
		||||
		newcell->setParam(ID(DEPTH), cell->getParam(ID(DEPTH)));
 | 
			
		||||
		newcell->setParam(ID(INIT), cell->getParam(ID(INIT)));
 | 
			
		||||
		newcell->setParam(ID(CLKPOL), cell->getParam(ID(CLKPOL)));
 | 
			
		||||
		newcell->setParam(ID(ENPOL), cell->getParam(ID(ENPOL)));
 | 
			
		||||
 | 
			
		||||
		newcell->setPort("\\C", cell->getPort("\\C"));
 | 
			
		||||
		newcell->setPort("\\D", cell->getPort("\\D"));
 | 
			
		||||
		if (cell->hasPort("\\E"))
 | 
			
		||||
			newcell->setPort("\\E", cell->getPort("\\E"));
 | 
			
		||||
		newcell->setPort(ID(C), cell->getPort(ID(C)));
 | 
			
		||||
		newcell->setPort(ID(D), cell->getPort(ID(D)));
 | 
			
		||||
		if (cell->hasPort(ID(E)))
 | 
			
		||||
			newcell->setPort(ID(E), cell->getPort(ID(E)));
 | 
			
		||||
 | 
			
		||||
		Cell* shiftx = std::get<0>(it->second);
 | 
			
		||||
		RTLIL::SigSpec l_wire, q_wire;
 | 
			
		||||
		if (shiftx->type == "$shiftx") {
 | 
			
		||||
			l_wire = shiftx->getPort("\\B");
 | 
			
		||||
			q_wire = shiftx->getPort("\\Y");
 | 
			
		||||
			shiftx->setPort("\\Y", cell->module->addWire(NEW_ID));
 | 
			
		||||
		if (shiftx->type == ID($shiftx)) {
 | 
			
		||||
			l_wire = shiftx->getPort(ID(B));
 | 
			
		||||
			q_wire = shiftx->getPort(ID(Y));
 | 
			
		||||
			shiftx->setPort(ID(Y), cell->module->addWire(NEW_ID));
 | 
			
		||||
		}
 | 
			
		||||
		else if (shiftx->type == "$mux") {
 | 
			
		||||
			l_wire = shiftx->getPort("\\S");
 | 
			
		||||
			q_wire = shiftx->getPort("\\Y");
 | 
			
		||||
			shiftx->setPort("\\Y", cell->module->addWire(NEW_ID));
 | 
			
		||||
		else if (shiftx->type == ID($mux)) {
 | 
			
		||||
			l_wire = shiftx->getPort(ID(S));
 | 
			
		||||
			q_wire = shiftx->getPort(ID(Y));
 | 
			
		||||
			shiftx->setPort(ID(Y), cell->module->addWire(NEW_ID));
 | 
			
		||||
		}
 | 
			
		||||
		else log_abort();
 | 
			
		||||
 | 
			
		||||
		newcell->setPort("\\Q", q_wire);
 | 
			
		||||
		newcell->setPort("\\L", l_wire);
 | 
			
		||||
		newcell->setPort(ID(Q), q_wire);
 | 
			
		||||
		newcell->setPort(ID(L), l_wire);
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -263,16 +263,16 @@ struct ShregmapWorker
 | 
			
		|||
	{
 | 
			
		||||
		for (auto wire : module->wires())
 | 
			
		||||
		{
 | 
			
		||||
			if (wire->port_output || wire->get_bool_attribute("\\keep")) {
 | 
			
		||||
			if (wire->port_output || wire->get_bool_attribute(ID(keep))) {
 | 
			
		||||
				for (auto bit : sigmap(wire)) {
 | 
			
		||||
					sigbit_with_non_chain_users.insert(bit);
 | 
			
		||||
					if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {});
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (wire->attributes.count("\\init")) {
 | 
			
		||||
			if (wire->attributes.count(ID(init))) {
 | 
			
		||||
				SigSpec initsig = sigmap(wire);
 | 
			
		||||
				Const initval = wire->attributes.at("\\init");
 | 
			
		||||
				Const initval = wire->attributes.at(ID(init));
 | 
			
		||||
				for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
 | 
			
		||||
					if (initval[i] == State::S0 && !opts.zinit)
 | 
			
		||||
						sigbit_init[initsig[i]] = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +283,7 @@ struct ShregmapWorker
 | 
			
		|||
 | 
			
		||||
		for (auto cell : module->cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep"))
 | 
			
		||||
			if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute(ID(keep)))
 | 
			
		||||
			{
 | 
			
		||||
				IdString d_port = opts.ffcells.at(cell->type).first;
 | 
			
		||||
				IdString q_port = opts.ffcells.at(cell->type).second;
 | 
			
		||||
| 
						 | 
				
			
			@ -474,7 +474,7 @@ struct ShregmapWorker
 | 
			
		|||
						initval.push_back(State::S0);
 | 
			
		||||
					remove_init.insert(bit);
 | 
			
		||||
				}
 | 
			
		||||
				first_cell->setParam("\\INIT", initval);
 | 
			
		||||
				first_cell->setParam(ID(INIT), initval);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (opts.zinit)
 | 
			
		||||
| 
						 | 
				
			
			@ -488,22 +488,22 @@ struct ShregmapWorker
 | 
			
		|||
				int param_clkpol = -1;
 | 
			
		||||
				int param_enpol = 2;
 | 
			
		||||
 | 
			
		||||
				if (first_cell->type == "$_DFF_N_") param_clkpol = 0;
 | 
			
		||||
				if (first_cell->type == "$_DFF_P_") param_clkpol = 1;
 | 
			
		||||
				if (first_cell->type == ID($_DFF_N_)) param_clkpol = 0;
 | 
			
		||||
				if (first_cell->type == ID($_DFF_P_)) param_clkpol = 1;
 | 
			
		||||
 | 
			
		||||
				if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0;
 | 
			
		||||
				if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1;
 | 
			
		||||
				if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0;
 | 
			
		||||
				if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1;
 | 
			
		||||
				if (first_cell->type == ID($_DFFE_NN_)) param_clkpol = 0, param_enpol = 0;
 | 
			
		||||
				if (first_cell->type == ID($_DFFE_NP_)) param_clkpol = 0, param_enpol = 1;
 | 
			
		||||
				if (first_cell->type == ID($_DFFE_PN_)) param_clkpol = 1, param_enpol = 0;
 | 
			
		||||
				if (first_cell->type == ID($_DFFE_PP_)) param_clkpol = 1, param_enpol = 1;
 | 
			
		||||
 | 
			
		||||
				log_assert(param_clkpol >= 0);
 | 
			
		||||
				first_cell->setParam("\\CLKPOL", param_clkpol);
 | 
			
		||||
				if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol);
 | 
			
		||||
				first_cell->setParam(ID(CLKPOL), param_clkpol);
 | 
			
		||||
				if (opts.ffe) first_cell->setParam(ID(ENPOL), param_enpol);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			first_cell->type = shreg_cell_type_str;
 | 
			
		||||
			first_cell->setPort(q_port, last_cell->getPort(q_port));
 | 
			
		||||
			first_cell->setParam("\\DEPTH", depth);
 | 
			
		||||
			first_cell->setParam(ID(DEPTH), depth);
 | 
			
		||||
 | 
			
		||||
			if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict))
 | 
			
		||||
				remove_cells.insert(first_cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -521,18 +521,18 @@ struct ShregmapWorker
 | 
			
		|||
 | 
			
		||||
		for (auto wire : module->wires())
 | 
			
		||||
		{
 | 
			
		||||
			if (wire->attributes.count("\\init") == 0)
 | 
			
		||||
			if (wire->attributes.count(ID(init)) == 0)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			SigSpec initsig = sigmap(wire);
 | 
			
		||||
			Const &initval = wire->attributes.at("\\init");
 | 
			
		||||
			Const &initval = wire->attributes.at(ID(init));
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
 | 
			
		||||
				if (remove_init.count(initsig[i]))
 | 
			
		||||
					initval[i] = State::Sx;
 | 
			
		||||
 | 
			
		||||
			if (SigSpec(initval).is_fully_undef())
 | 
			
		||||
				wire->attributes.erase("\\init");
 | 
			
		||||
				wire->attributes.erase(ID(init));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		remove_cells.clear();
 | 
			
		||||
| 
						 | 
				
			
			@ -717,19 +717,19 @@ struct ShregmapPass : public Pass {
 | 
			
		|||
			bool en_neg = enpol == "neg" || enpol == "any" || enpol == "any_or_none";
 | 
			
		||||
 | 
			
		||||
			if (clk_pos && en_none)
 | 
			
		||||
				opts.ffcells["$_DFF_P_"] = make_pair(IdString("\\D"), IdString("\\Q"));
 | 
			
		||||
				opts.ffcells[ID($_DFF_P_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
 | 
			
		||||
			if (clk_neg && en_none)
 | 
			
		||||
				opts.ffcells["$_DFF_N_"] = make_pair(IdString("\\D"), IdString("\\Q"));
 | 
			
		||||
				opts.ffcells[ID($_DFF_N_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
 | 
			
		||||
 | 
			
		||||
			if (clk_pos && en_pos)
 | 
			
		||||
				opts.ffcells["$_DFFE_PP_"] = make_pair(IdString("\\D"), IdString("\\Q"));
 | 
			
		||||
				opts.ffcells[ID($_DFFE_PP_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
 | 
			
		||||
			if (clk_pos && en_neg)
 | 
			
		||||
				opts.ffcells["$_DFFE_PN_"] = make_pair(IdString("\\D"), IdString("\\Q"));
 | 
			
		||||
				opts.ffcells[ID($_DFFE_PN_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
 | 
			
		||||
 | 
			
		||||
			if (clk_neg && en_pos)
 | 
			
		||||
				opts.ffcells["$_DFFE_NP_"] = make_pair(IdString("\\D"), IdString("\\Q"));
 | 
			
		||||
				opts.ffcells[ID($_DFFE_NP_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
 | 
			
		||||
			if (clk_neg && en_neg)
 | 
			
		||||
				opts.ffcells["$_DFFE_NN_"] = make_pair(IdString("\\D"), IdString("\\Q"));
 | 
			
		||||
				opts.ffcells[ID($_DFFE_NN_)] = make_pair(IdString(ID(D)), IdString(ID(Q)));
 | 
			
		||||
 | 
			
		||||
			if (en_pos || en_neg)
 | 
			
		||||
				opts.ffe = true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,82 +28,82 @@ YOSYS_NAMESPACE_BEGIN
 | 
			
		|||
 | 
			
		||||
void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
 | 
			
		||||
	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < GetSize(sig_y); i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\A", sig_a[i]);
 | 
			
		||||
		gate->setPort("\\Y", sig_y[i]);
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(A), sig_a[i]);
 | 
			
		||||
		gate->setPort(ID(Y), sig_y[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
 | 
			
		||||
	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
 | 
			
		||||
 | 
			
		||||
	module->connect(RTLIL::SigSig(sig_y, sig_a));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
 | 
			
		||||
	sig_b.extend_u0(GetSize(sig_y), cell->parameters.at("\\B_SIGNED").as_bool());
 | 
			
		||||
	sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID(A_SIGNED)).as_bool());
 | 
			
		||||
	sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID(B_SIGNED)).as_bool());
 | 
			
		||||
 | 
			
		||||
	if (cell->type == "$xnor")
 | 
			
		||||
	if (cell->type == ID($xnor))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_t = module->addWire(NEW_ID, GetSize(sig_y));
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < GetSize(sig_y); i++) {
 | 
			
		||||
			RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
 | 
			
		||||
			gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
			gate->setPort("\\A", sig_t[i]);
 | 
			
		||||
			gate->setPort("\\Y", sig_y[i]);
 | 
			
		||||
			RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
 | 
			
		||||
			gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
			gate->setPort(ID(A), sig_t[i]);
 | 
			
		||||
			gate->setPort(ID(Y), sig_y[i]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sig_y = sig_t;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::string gate_type;
 | 
			
		||||
	if (cell->type == "$and")  gate_type = "$_AND_";
 | 
			
		||||
	if (cell->type == "$or")   gate_type = "$_OR_";
 | 
			
		||||
	if (cell->type == "$xor")  gate_type = "$_XOR_";
 | 
			
		||||
	if (cell->type == "$xnor") gate_type = "$_XOR_";
 | 
			
		||||
	IdString gate_type;
 | 
			
		||||
	if (cell->type == ID($and))  gate_type = ID($_AND_);
 | 
			
		||||
	if (cell->type == ID($or))   gate_type = ID($_OR_);
 | 
			
		||||
	if (cell->type == ID($xor))  gate_type = ID($_XOR_);
 | 
			
		||||
	if (cell->type == ID($xnor)) gate_type = ID($_XOR_);
 | 
			
		||||
	log_assert(!gate_type.empty());
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < GetSize(sig_y); i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\A", sig_a[i]);
 | 
			
		||||
		gate->setPort("\\B", sig_b[i]);
 | 
			
		||||
		gate->setPort("\\Y", sig_y[i]);
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(A), sig_a[i]);
 | 
			
		||||
		gate->setPort(ID(B), sig_b[i]);
 | 
			
		||||
		gate->setPort(ID(Y), sig_y[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
	if (sig_y.size() == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (sig_a.size() == 0) {
 | 
			
		||||
		if (cell->type == "$reduce_and")  module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
 | 
			
		||||
		if (cell->type == "$reduce_or")   module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
 | 
			
		||||
		if (cell->type == "$reduce_xor")  module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
 | 
			
		||||
		if (cell->type == "$reduce_xnor") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
 | 
			
		||||
		if (cell->type == "$reduce_bool") module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
 | 
			
		||||
		if (cell->type == ID($reduce_and))  module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
 | 
			
		||||
		if (cell->type == ID($reduce_or))   module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
 | 
			
		||||
		if (cell->type == ID($reduce_xor))  module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
 | 
			
		||||
		if (cell->type == ID($reduce_xnor)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(1, sig_y.size())));
 | 
			
		||||
		if (cell->type == ID($reduce_bool)) module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -112,12 +112,12 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		|||
		sig_y = sig_y.extract(0, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::string gate_type;
 | 
			
		||||
	if (cell->type == "$reduce_and")  gate_type = "$_AND_";
 | 
			
		||||
	if (cell->type == "$reduce_or")   gate_type = "$_OR_";
 | 
			
		||||
	if (cell->type == "$reduce_xor")  gate_type = "$_XOR_";
 | 
			
		||||
	if (cell->type == "$reduce_xnor") gate_type = "$_XOR_";
 | 
			
		||||
	if (cell->type == "$reduce_bool") gate_type = "$_OR_";
 | 
			
		||||
	IdString gate_type;
 | 
			
		||||
	if (cell->type == ID($reduce_and))  gate_type = ID($_AND_);
 | 
			
		||||
	if (cell->type == ID($reduce_or))   gate_type = ID($_OR_);
 | 
			
		||||
	if (cell->type == ID($reduce_xor))  gate_type = ID($_XOR_);
 | 
			
		||||
	if (cell->type == ID($reduce_xnor)) gate_type = ID($_XOR_);
 | 
			
		||||
	if (cell->type == ID($reduce_bool)) gate_type = ID($_OR_);
 | 
			
		||||
	log_assert(!gate_type.empty());
 | 
			
		||||
 | 
			
		||||
	RTLIL::Cell *last_output_cell = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -134,22 +134,22 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
			gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
			gate->setPort("\\A", sig_a[i]);
 | 
			
		||||
			gate->setPort("\\B", sig_a[i+1]);
 | 
			
		||||
			gate->setPort("\\Y", sig_t[i/2]);
 | 
			
		||||
			gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
			gate->setPort(ID(A), sig_a[i]);
 | 
			
		||||
			gate->setPort(ID(B), sig_a[i+1]);
 | 
			
		||||
			gate->setPort(ID(Y), sig_t[i/2]);
 | 
			
		||||
			last_output_cell = gate;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sig_a = sig_t;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type == "$reduce_xnor") {
 | 
			
		||||
	if (cell->type == ID($reduce_xnor)) {
 | 
			
		||||
		RTLIL::SigSpec sig_t = module->addWire(NEW_ID);
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\A", sig_a);
 | 
			
		||||
		gate->setPort("\\Y", sig_t);
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(A), sig_a);
 | 
			
		||||
		gate->setPort(ID(Y), sig_t);
 | 
			
		||||
		last_output_cell = gate;
 | 
			
		||||
		sig_a = sig_t;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +157,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		|||
	if (last_output_cell == NULL) {
 | 
			
		||||
		module->connect(RTLIL::SigSig(sig_y, sig_a));
 | 
			
		||||
	} else {
 | 
			
		||||
		last_output_cell->setPort("\\Y", sig_y);
 | 
			
		||||
		last_output_cell->setPort(ID(Y), sig_y);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -174,11 +174,11 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell
 | 
			
		|||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *gate = module->addCell(NEW_ID, "$_OR_");
 | 
			
		||||
			gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
			gate->setPort("\\A", sig[i]);
 | 
			
		||||
			gate->setPort("\\B", sig[i+1]);
 | 
			
		||||
			gate->setPort("\\Y", sig_t[i/2]);
 | 
			
		||||
			RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_OR_));
 | 
			
		||||
			gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
			gate->setPort(ID(A), sig[i]);
 | 
			
		||||
			gate->setPort(ID(B), sig[i+1]);
 | 
			
		||||
			gate->setPort(ID(Y), sig_t[i/2]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sig = sig_t;
 | 
			
		||||
| 
						 | 
				
			
			@ -190,10 +190,10 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell
 | 
			
		|||
 | 
			
		||||
void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	logic_reduce(module, sig_a, cell);
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
	if (sig_y.size() == 0)
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -203,21 +203,21 @@ void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		|||
		sig_y = sig_y.extract(0, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
 | 
			
		||||
	gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
	gate->setPort("\\A", sig_a);
 | 
			
		||||
	gate->setPort("\\Y", sig_y);
 | 
			
		||||
	RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
 | 
			
		||||
	gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
	gate->setPort(ID(A), sig_a);
 | 
			
		||||
	gate->setPort(ID(Y), sig_y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	logic_reduce(module, sig_a, cell);
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
	RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
	logic_reduce(module, sig_b, cell);
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
	if (sig_y.size() == 0)
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -227,41 +227,41 @@ void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		|||
		sig_y = sig_y.extract(0, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::string gate_type;
 | 
			
		||||
	if (cell->type == "$logic_and") gate_type = "$_AND_";
 | 
			
		||||
	if (cell->type == "$logic_or")  gate_type = "$_OR_";
 | 
			
		||||
	IdString gate_type;
 | 
			
		||||
	if (cell->type == ID($logic_and)) gate_type = ID($_AND_);
 | 
			
		||||
	if (cell->type == ID($logic_or))  gate_type = ID($_OR_);
 | 
			
		||||
	log_assert(!gate_type.empty());
 | 
			
		||||
 | 
			
		||||
	RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
	gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
	gate->setPort("\\A", sig_a);
 | 
			
		||||
	gate->setPort("\\B", sig_b);
 | 
			
		||||
	gate->setPort("\\Y", sig_y);
 | 
			
		||||
	gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
	gate->setPort(ID(A), sig_a);
 | 
			
		||||
	gate->setPort(ID(B), sig_b);
 | 
			
		||||
	gate->setPort(ID(Y), sig_y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
 | 
			
		||||
	bool is_ne = cell->type.in("$ne", "$nex");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
	bool is_signed = cell->parameters.at(ID(A_SIGNED)).as_bool();
 | 
			
		||||
	bool is_ne = cell->type.in(ID($ne), ID($nex));
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec xor_out = module->addWire(NEW_ID, max(GetSize(sig_a), GetSize(sig_b)));
 | 
			
		||||
	RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed);
 | 
			
		||||
	xor_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
	xor_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
	simplemap_bitop(module, xor_cell);
 | 
			
		||||
	module->remove(xor_cell);
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID);
 | 
			
		||||
	RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out);
 | 
			
		||||
	reduce_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
	reduce_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
	simplemap_reduce(module, reduce_cell);
 | 
			
		||||
	module->remove(reduce_cell);
 | 
			
		||||
 | 
			
		||||
	if (!is_ne) {
 | 
			
		||||
		RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y);
 | 
			
		||||
		not_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		not_cell->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		simplemap_lognot(module, not_cell);
 | 
			
		||||
		module->remove(not_cell);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -269,65 +269,65 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		|||
 | 
			
		||||
void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	RTLIL::SigSpec sig_b = cell->getPort(ID(B));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < GetSize(sig_y); i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, "$_MUX_");
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\A", sig_a[i]);
 | 
			
		||||
		gate->setPort("\\B", sig_b[i]);
 | 
			
		||||
		gate->setPort("\\S", cell->getPort("\\S"));
 | 
			
		||||
		gate->setPort("\\Y", sig_y[i]);
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(A), sig_a[i]);
 | 
			
		||||
		gate->setPort(ID(B), sig_b[i]);
 | 
			
		||||
		gate->setPort(ID(S), cell->getPort(ID(S)));
 | 
			
		||||
		gate->setPort(ID(Y), sig_y[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_e = cell->getPort("\\EN");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	RTLIL::SigSpec sig_e = cell->getPort(ID(EN));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < GetSize(sig_y); i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, "$_TBUF_");
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\A", sig_a[i]);
 | 
			
		||||
		gate->setPort("\\E", sig_e);
 | 
			
		||||
		gate->setPort("\\Y", sig_y[i]);
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_TBUF_));
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(A), sig_a[i]);
 | 
			
		||||
		gate->setPort(ID(E), sig_e);
 | 
			
		||||
		gate->setPort(ID(Y), sig_y[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	SigSpec lut_ctrl = cell->getPort("\\A");
 | 
			
		||||
	SigSpec lut_data = cell->getParam("\\LUT");
 | 
			
		||||
	lut_data.extend_u0(1 << cell->getParam("\\WIDTH").as_int());
 | 
			
		||||
	SigSpec lut_ctrl = cell->getPort(ID(A));
 | 
			
		||||
	SigSpec lut_data = cell->getParam(ID(LUT));
 | 
			
		||||
	lut_data.extend_u0(1 << cell->getParam(ID(WIDTH)).as_int());
 | 
			
		||||
 | 
			
		||||
	for (int idx = 0; GetSize(lut_data) > 1; idx++) {
 | 
			
		||||
		SigSpec sig_s = lut_ctrl[idx];
 | 
			
		||||
		SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2);
 | 
			
		||||
		for (int i = 0; i < GetSize(lut_data); i += 2) {
 | 
			
		||||
			RTLIL::Cell *gate = module->addCell(NEW_ID, "$_MUX_");
 | 
			
		||||
			gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
			gate->setPort("\\A", lut_data[i]);
 | 
			
		||||
			gate->setPort("\\B", lut_data[i+1]);
 | 
			
		||||
			gate->setPort("\\S", lut_ctrl[idx]);
 | 
			
		||||
			gate->setPort("\\Y", new_lut_data[i/2]);
 | 
			
		||||
			RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
 | 
			
		||||
			gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
			gate->setPort(ID(A), lut_data[i]);
 | 
			
		||||
			gate->setPort(ID(B), lut_data[i+1]);
 | 
			
		||||
			gate->setPort(ID(S), lut_ctrl[idx]);
 | 
			
		||||
			gate->setPort(ID(Y), new_lut_data[i/2]);
 | 
			
		||||
		}
 | 
			
		||||
		lut_data = new_lut_data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	module->connect(cell->getPort("\\Y"), lut_data);
 | 
			
		||||
	module->connect(cell->getPort(ID(Y)), lut_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	SigSpec ctrl = cell->getPort("\\A");
 | 
			
		||||
	SigSpec table = cell->getParam("\\TABLE");
 | 
			
		||||
	SigSpec ctrl = cell->getPort(ID(A));
 | 
			
		||||
	SigSpec table = cell->getParam(ID(TABLE));
 | 
			
		||||
 | 
			
		||||
	int width = cell->getParam("\\WIDTH").as_int();
 | 
			
		||||
	int depth = cell->getParam("\\DEPTH").as_int();
 | 
			
		||||
	int width = cell->getParam(ID(WIDTH)).as_int();
 | 
			
		||||
	int depth = cell->getParam(ID(DEPTH)).as_int();
 | 
			
		||||
	table.extend_u0(2 * width * depth);
 | 
			
		||||
 | 
			
		||||
	SigSpec products;
 | 
			
		||||
| 
						 | 
				
			
			@ -348,213 +348,213 @@ void simplemap_sop(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		|||
		products.append(GetSize(in) > 0 ? module->Eq(NEW_ID, in, pat) : State::S1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	module->connect(cell->getPort("\\Y"), module->ReduceOr(NEW_ID, products));
 | 
			
		||||
	module->connect(cell->getPort(ID(Y)), module->ReduceOr(NEW_ID, products));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	int offset = cell->parameters.at("\\OFFSET").as_int();
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort("\\A");
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	int offset = cell->parameters.at(ID(OFFSET)).as_int();
 | 
			
		||||
	RTLIL::SigSpec sig_a = cell->getPort(ID(A));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
	module->connect(RTLIL::SigSig(sig_y, sig_a.extract(offset, sig_y.size())));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::SigSpec sig_ab = cell->getPort("\\A");
 | 
			
		||||
	sig_ab.append(cell->getPort("\\B"));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort("\\Y");
 | 
			
		||||
	RTLIL::SigSpec sig_ab = cell->getPort(ID(A));
 | 
			
		||||
	sig_ab.append(cell->getPort(ID(B)));
 | 
			
		||||
	RTLIL::SigSpec sig_y = cell->getPort(ID(Y));
 | 
			
		||||
	module->connect(RTLIL::SigSig(sig_y, sig_ab));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	int width = cell->parameters.at("\\WIDTH").as_int();
 | 
			
		||||
	char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	char clr_pol = cell->parameters.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	int width = cell->parameters.at(ID(WIDTH)).as_int();
 | 
			
		||||
	char set_pol = cell->parameters.at(ID(SET_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
	char clr_pol = cell->parameters.at(ID(CLR_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_s = cell->getPort("\\SET");
 | 
			
		||||
	RTLIL::SigSpec sig_r = cell->getPort("\\CLR");
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
	RTLIL::SigSpec sig_s = cell->getPort(ID(SET));
 | 
			
		||||
	RTLIL::SigSpec sig_r = cell->getPort(ID(CLR));
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
	std::string gate_type = stringf("$_SR_%c%c_", set_pol, clr_pol);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < width; i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\S", sig_s[i]);
 | 
			
		||||
		gate->setPort("\\R", sig_r[i]);
 | 
			
		||||
		gate->setPort("\\Q", sig_q[i]);
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(S), sig_s[i]);
 | 
			
		||||
		gate->setPort(ID(R), sig_r[i]);
 | 
			
		||||
		gate->setPort(ID(Q), sig_q[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_ff(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	int width = cell->parameters.at("\\WIDTH").as_int();
 | 
			
		||||
	int width = cell->parameters.at(ID(WIDTH)).as_int();
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
	std::string gate_type = "$_FF_";
 | 
			
		||||
	IdString gate_type = ID($_FF_);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < width; i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\D", sig_d[i]);
 | 
			
		||||
		gate->setPort("\\Q", sig_q[i]);
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(D), sig_d[i]);
 | 
			
		||||
		gate->setPort(ID(Q), sig_q[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	int width = cell->parameters.at("\\WIDTH").as_int();
 | 
			
		||||
	char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	int width = cell->parameters.at(ID(WIDTH)).as_int();
 | 
			
		||||
	char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_clk = cell->getPort("\\CLK");
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
	RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK));
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
	std::string gate_type = stringf("$_DFF_%c_", clk_pol);
 | 
			
		||||
	IdString gate_type = stringf("$_DFF_%c_", clk_pol);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < width; i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\C", sig_clk);
 | 
			
		||||
		gate->setPort("\\D", sig_d[i]);
 | 
			
		||||
		gate->setPort("\\Q", sig_q[i]);
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(C), sig_clk);
 | 
			
		||||
		gate->setPort(ID(D), sig_d[i]);
 | 
			
		||||
		gate->setPort(ID(Q), sig_q[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	int width = cell->parameters.at("\\WIDTH").as_int();
 | 
			
		||||
	char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	int width = cell->parameters.at(ID(WIDTH)).as_int();
 | 
			
		||||
	char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
	char en_pol = cell->parameters.at(ID(EN_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_clk = cell->getPort("\\CLK");
 | 
			
		||||
	RTLIL::SigSpec sig_en = cell->getPort("\\EN");
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
	RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK));
 | 
			
		||||
	RTLIL::SigSpec sig_en = cell->getPort(ID(EN));
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
	std::string gate_type = stringf("$_DFFE_%c%c_", clk_pol, en_pol);
 | 
			
		||||
	IdString gate_type = stringf("$_DFFE_%c%c_", clk_pol, en_pol);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < width; i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\C", sig_clk);
 | 
			
		||||
		gate->setPort("\\E", sig_en);
 | 
			
		||||
		gate->setPort("\\D", sig_d[i]);
 | 
			
		||||
		gate->setPort("\\Q", sig_q[i]);
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(C), sig_clk);
 | 
			
		||||
		gate->setPort(ID(E), sig_en);
 | 
			
		||||
		gate->setPort(ID(D), sig_d[i]);
 | 
			
		||||
		gate->setPort(ID(Q), sig_q[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	int width = cell->parameters.at("\\WIDTH").as_int();
 | 
			
		||||
	char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	char clr_pol = cell->parameters.at("\\CLR_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	int width = cell->parameters.at(ID(WIDTH)).as_int();
 | 
			
		||||
	char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
	char set_pol = cell->parameters.at(ID(SET_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
	char clr_pol = cell->parameters.at(ID(CLR_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_clk = cell->getPort("\\CLK");
 | 
			
		||||
	RTLIL::SigSpec sig_s = cell->getPort("\\SET");
 | 
			
		||||
	RTLIL::SigSpec sig_r = cell->getPort("\\CLR");
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
	RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK));
 | 
			
		||||
	RTLIL::SigSpec sig_s = cell->getPort(ID(SET));
 | 
			
		||||
	RTLIL::SigSpec sig_r = cell->getPort(ID(CLR));
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
	std::string gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol);
 | 
			
		||||
	IdString gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < width; i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\C", sig_clk);
 | 
			
		||||
		gate->setPort("\\S", sig_s[i]);
 | 
			
		||||
		gate->setPort("\\R", sig_r[i]);
 | 
			
		||||
		gate->setPort("\\D", sig_d[i]);
 | 
			
		||||
		gate->setPort("\\Q", sig_q[i]);
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(C), sig_clk);
 | 
			
		||||
		gate->setPort(ID(S), sig_s[i]);
 | 
			
		||||
		gate->setPort(ID(R), sig_r[i]);
 | 
			
		||||
		gate->setPort(ID(D), sig_d[i]);
 | 
			
		||||
		gate->setPort(ID(Q), sig_q[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	int width = cell->parameters.at("\\WIDTH").as_int();
 | 
			
		||||
	char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	char rst_pol = cell->parameters.at("\\ARST_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	int width = cell->parameters.at(ID(WIDTH)).as_int();
 | 
			
		||||
	char clk_pol = cell->parameters.at(ID(CLK_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
	char rst_pol = cell->parameters.at(ID(ARST_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
 | 
			
		||||
	std::vector<RTLIL::State> rst_val = cell->parameters.at("\\ARST_VALUE").bits;
 | 
			
		||||
	std::vector<RTLIL::State> rst_val = cell->parameters.at(ID(ARST_VALUE)).bits;
 | 
			
		||||
	while (int(rst_val.size()) < width)
 | 
			
		||||
		rst_val.push_back(RTLIL::State::S0);
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_clk = cell->getPort("\\CLK");
 | 
			
		||||
	RTLIL::SigSpec sig_rst = cell->getPort("\\ARST");
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
	RTLIL::SigSpec sig_clk = cell->getPort(ID(CLK));
 | 
			
		||||
	RTLIL::SigSpec sig_rst = cell->getPort(ID(ARST));
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
	std::string gate_type_0 = stringf("$_DFF_%c%c0_", clk_pol, rst_pol);
 | 
			
		||||
	std::string gate_type_1 = stringf("$_DFF_%c%c1_", clk_pol, rst_pol);
 | 
			
		||||
	IdString gate_type_0 = stringf("$_DFF_%c%c0_", clk_pol, rst_pol);
 | 
			
		||||
	IdString gate_type_1 = stringf("$_DFF_%c%c1_", clk_pol, rst_pol);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < width; i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\C", sig_clk);
 | 
			
		||||
		gate->setPort("\\R", sig_rst);
 | 
			
		||||
		gate->setPort("\\D", sig_d[i]);
 | 
			
		||||
		gate->setPort("\\Q", sig_q[i]);
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(C), sig_clk);
 | 
			
		||||
		gate->setPort(ID(R), sig_rst);
 | 
			
		||||
		gate->setPort(ID(D), sig_d[i]);
 | 
			
		||||
		gate->setPort(ID(Q), sig_q[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	int width = cell->parameters.at("\\WIDTH").as_int();
 | 
			
		||||
	char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
 | 
			
		||||
	int width = cell->parameters.at(ID(WIDTH)).as_int();
 | 
			
		||||
	char en_pol = cell->parameters.at(ID(EN_POLARITY)).as_bool() ? 'P' : 'N';
 | 
			
		||||
 | 
			
		||||
	RTLIL::SigSpec sig_en = cell->getPort("\\EN");
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort("\\D");
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort("\\Q");
 | 
			
		||||
	RTLIL::SigSpec sig_en = cell->getPort(ID(EN));
 | 
			
		||||
	RTLIL::SigSpec sig_d = cell->getPort(ID(D));
 | 
			
		||||
	RTLIL::SigSpec sig_q = cell->getPort(ID(Q));
 | 
			
		||||
 | 
			
		||||
	std::string gate_type = stringf("$_DLATCH_%c_", en_pol);
 | 
			
		||||
	IdString gate_type = stringf("$_DLATCH_%c_", en_pol);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < width; i++) {
 | 
			
		||||
		RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
 | 
			
		||||
		gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
 | 
			
		||||
		gate->setPort("\\E", sig_en);
 | 
			
		||||
		gate->setPort("\\D", sig_d[i]);
 | 
			
		||||
		gate->setPort("\\Q", sig_q[i]);
 | 
			
		||||
		gate->add_strpool_attribute(ID(src), cell->get_strpool_attribute(ID(src)));
 | 
			
		||||
		gate->setPort(ID(E), sig_en);
 | 
			
		||||
		gate->setPort(ID(D), sig_d[i]);
 | 
			
		||||
		gate->setPort(ID(Q), sig_q[i]);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
 | 
			
		||||
{
 | 
			
		||||
	mappers["$not"]         = simplemap_not;
 | 
			
		||||
	mappers["$pos"]         = simplemap_pos;
 | 
			
		||||
	mappers["$and"]         = simplemap_bitop;
 | 
			
		||||
	mappers["$or"]          = simplemap_bitop;
 | 
			
		||||
	mappers["$xor"]         = simplemap_bitop;
 | 
			
		||||
	mappers["$xnor"]        = simplemap_bitop;
 | 
			
		||||
	mappers["$reduce_and"]  = simplemap_reduce;
 | 
			
		||||
	mappers["$reduce_or"]   = simplemap_reduce;
 | 
			
		||||
	mappers["$reduce_xor"]  = simplemap_reduce;
 | 
			
		||||
	mappers["$reduce_xnor"] = simplemap_reduce;
 | 
			
		||||
	mappers["$reduce_bool"] = simplemap_reduce;
 | 
			
		||||
	mappers["$logic_not"]   = simplemap_lognot;
 | 
			
		||||
	mappers["$logic_and"]   = simplemap_logbin;
 | 
			
		||||
	mappers["$logic_or"]    = simplemap_logbin;
 | 
			
		||||
	mappers["$eq"]          = simplemap_eqne;
 | 
			
		||||
	mappers["$eqx"]         = simplemap_eqne;
 | 
			
		||||
	mappers["$ne"]          = simplemap_eqne;
 | 
			
		||||
	mappers["$nex"]         = simplemap_eqne;
 | 
			
		||||
	mappers["$mux"]         = simplemap_mux;
 | 
			
		||||
	mappers["$tribuf"]      = simplemap_tribuf;
 | 
			
		||||
	mappers["$lut"]         = simplemap_lut;
 | 
			
		||||
	mappers["$sop"]         = simplemap_sop;
 | 
			
		||||
	mappers["$slice"]       = simplemap_slice;
 | 
			
		||||
	mappers["$concat"]      = simplemap_concat;
 | 
			
		||||
	mappers["$sr"]          = simplemap_sr;
 | 
			
		||||
	mappers["$ff"]          = simplemap_ff;
 | 
			
		||||
	mappers["$dff"]         = simplemap_dff;
 | 
			
		||||
	mappers["$dffe"]        = simplemap_dffe;
 | 
			
		||||
	mappers["$dffsr"]       = simplemap_dffsr;
 | 
			
		||||
	mappers["$adff"]        = simplemap_adff;
 | 
			
		||||
	mappers["$dlatch"]      = simplemap_dlatch;
 | 
			
		||||
	mappers[ID($not)]         = simplemap_not;
 | 
			
		||||
	mappers[ID($pos)]         = simplemap_pos;
 | 
			
		||||
	mappers[ID($and)]         = simplemap_bitop;
 | 
			
		||||
	mappers[ID($or)]          = simplemap_bitop;
 | 
			
		||||
	mappers[ID($xor)]         = simplemap_bitop;
 | 
			
		||||
	mappers[ID($xnor)]        = simplemap_bitop;
 | 
			
		||||
	mappers[ID($reduce_and)]  = simplemap_reduce;
 | 
			
		||||
	mappers[ID($reduce_or)]   = simplemap_reduce;
 | 
			
		||||
	mappers[ID($reduce_xor)]  = simplemap_reduce;
 | 
			
		||||
	mappers[ID($reduce_xnor)] = simplemap_reduce;
 | 
			
		||||
	mappers[ID($reduce_bool)] = simplemap_reduce;
 | 
			
		||||
	mappers[ID($logic_not)]   = simplemap_lognot;
 | 
			
		||||
	mappers[ID($logic_and)]   = simplemap_logbin;
 | 
			
		||||
	mappers[ID($logic_or)]    = simplemap_logbin;
 | 
			
		||||
	mappers[ID($eq)]          = simplemap_eqne;
 | 
			
		||||
	mappers[ID($eqx)]         = simplemap_eqne;
 | 
			
		||||
	mappers[ID($ne)]          = simplemap_eqne;
 | 
			
		||||
	mappers[ID($nex)]         = simplemap_eqne;
 | 
			
		||||
	mappers[ID($mux)]         = simplemap_mux;
 | 
			
		||||
	mappers[ID($tribuf)]      = simplemap_tribuf;
 | 
			
		||||
	mappers[ID($lut)]         = simplemap_lut;
 | 
			
		||||
	mappers[ID($sop)]         = simplemap_sop;
 | 
			
		||||
	mappers[ID($slice)]       = simplemap_slice;
 | 
			
		||||
	mappers[ID($concat)]      = simplemap_concat;
 | 
			
		||||
	mappers[ID($sr)]          = simplemap_sr;
 | 
			
		||||
	mappers[ID($ff)]          = simplemap_ff;
 | 
			
		||||
	mappers[ID($dff)]         = simplemap_dff;
 | 
			
		||||
	mappers[ID($dffe)]        = simplemap_dffe;
 | 
			
		||||
	mappers[ID($dffsr)]       = simplemap_dffsr;
 | 
			
		||||
	mappers[ID($adff)]        = simplemap_adff;
 | 
			
		||||
	mappers[ID($dlatch)]      = simplemap_dlatch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void simplemap(RTLIL::Module *module, RTLIL::Cell *cell)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,20 +39,20 @@ YOSYS_NAMESPACE_END
 | 
			
		|||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
void apply_prefix(std::string prefix, std::string &id)
 | 
			
		||||
void apply_prefix(IdString prefix, IdString &id)
 | 
			
		||||
{
 | 
			
		||||
	if (id[0] == '\\')
 | 
			
		||||
		id = prefix + "." + id.substr(1);
 | 
			
		||||
		id = stringf("%s.%s", prefix.c_str(), id.c_str()+1);
 | 
			
		||||
	else
 | 
			
		||||
		id = "$techmap" + prefix + "." + id;
 | 
			
		||||
		id = stringf("$techmap%s.%s", prefix.c_str(), id.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void apply_prefix(std::string prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
 | 
			
		||||
void apply_prefix(IdString prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
 | 
			
		||||
{
 | 
			
		||||
	vector<SigChunk> chunks = sig;
 | 
			
		||||
	for (auto &chunk : chunks)
 | 
			
		||||
		if (chunk.wire != NULL) {
 | 
			
		||||
			std::string wire_name = chunk.wire->name.str();
 | 
			
		||||
			IdString wire_name = chunk.wire->name;
 | 
			
		||||
			apply_prefix(prefix, wire_name);
 | 
			
		||||
			log_assert(module->wires_.count(wire_name) > 0);
 | 
			
		||||
			chunk.wire = module->wires_[wire_name];
 | 
			
		||||
| 
						 | 
				
			
			@ -145,8 +145,8 @@ struct TechmapWorker
 | 
			
		|||
				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);
 | 
			
		||||
				it.second->attributes[ID(keep)] = RTLIL::Const(1);
 | 
			
		||||
				it.second->attributes[ID(_techmap_special_)] = RTLIL::Const(1);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -175,11 +175,11 @@ struct TechmapWorker
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		std::string orig_cell_name;
 | 
			
		||||
		pool<string> extra_src_attrs = cell->get_strpool_attribute("\\src");
 | 
			
		||||
		pool<string> extra_src_attrs = cell->get_strpool_attribute(ID(src));
 | 
			
		||||
 | 
			
		||||
		if (!flatten_mode) {
 | 
			
		||||
			for (auto &it : tpl->cells_)
 | 
			
		||||
				if (it.first == "\\_TECHMAP_REPLACE_") {
 | 
			
		||||
				if (it.first == ID(_TECHMAP_REPLACE_)) {
 | 
			
		||||
					orig_cell_name = cell->name.str();
 | 
			
		||||
					module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str());
 | 
			
		||||
					break;
 | 
			
		||||
| 
						 | 
				
			
			@ -189,16 +189,16 @@ struct TechmapWorker
 | 
			
		|||
		dict<IdString, IdString> memory_renames;
 | 
			
		||||
 | 
			
		||||
		for (auto &it : tpl->memories) {
 | 
			
		||||
			std::string m_name = it.first.str();
 | 
			
		||||
			apply_prefix(cell->name.str(), m_name);
 | 
			
		||||
			IdString m_name = it.first;
 | 
			
		||||
			apply_prefix(cell->name, m_name);
 | 
			
		||||
			RTLIL::Memory *m = new RTLIL::Memory;
 | 
			
		||||
			m->name = m_name;
 | 
			
		||||
			m->width = it.second->width;
 | 
			
		||||
			m->start_offset = it.second->start_offset;
 | 
			
		||||
			m->size = it.second->size;
 | 
			
		||||
			m->attributes = it.second->attributes;
 | 
			
		||||
			if (m->attributes.count("\\src"))
 | 
			
		||||
				m->add_strpool_attribute("\\src", extra_src_attrs);
 | 
			
		||||
			if (m->attributes.count(ID(src)))
 | 
			
		||||
				m->add_strpool_attribute(ID(src), extra_src_attrs);
 | 
			
		||||
			module->memories[m->name] = m;
 | 
			
		||||
			memory_renames[it.first] = m->name;
 | 
			
		||||
			design->select(module, m);
 | 
			
		||||
| 
						 | 
				
			
			@ -209,16 +209,16 @@ struct TechmapWorker
 | 
			
		|||
		for (auto &it : tpl->wires_) {
 | 
			
		||||
			if (it.second->port_id > 0)
 | 
			
		||||
				positional_ports[stringf("$%d", it.second->port_id)] = it.first;
 | 
			
		||||
			std::string w_name = it.second->name.str();
 | 
			
		||||
			apply_prefix(cell->name.str(), w_name);
 | 
			
		||||
			IdString w_name = it.second->name;
 | 
			
		||||
			apply_prefix(cell->name, w_name);
 | 
			
		||||
			RTLIL::Wire *w = module->addWire(w_name, it.second);
 | 
			
		||||
			w->port_input = false;
 | 
			
		||||
			w->port_output = false;
 | 
			
		||||
			w->port_id = 0;
 | 
			
		||||
			if (it.second->get_bool_attribute("\\_techmap_special_"))
 | 
			
		||||
			if (it.second->get_bool_attribute(ID(_techmap_special_)))
 | 
			
		||||
				w->attributes.clear();
 | 
			
		||||
			if (w->attributes.count("\\src"))
 | 
			
		||||
				w->add_strpool_attribute("\\src", extra_src_attrs);
 | 
			
		||||
			if (w->attributes.count(ID(src)))
 | 
			
		||||
				w->add_strpool_attribute(ID(src), extra_src_attrs);
 | 
			
		||||
			design->select(module, w);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -257,18 +257,18 @@ struct TechmapWorker
 | 
			
		|||
			if (w->port_output && !w->port_input) {
 | 
			
		||||
				c.first = it.second;
 | 
			
		||||
				c.second = RTLIL::SigSpec(w);
 | 
			
		||||
				apply_prefix(cell->name.str(), c.second, module);
 | 
			
		||||
				apply_prefix(cell->name, c.second, module);
 | 
			
		||||
				extra_connect.first = c.second;
 | 
			
		||||
				extra_connect.second = c.first;
 | 
			
		||||
			} else if (!w->port_output && w->port_input) {
 | 
			
		||||
				c.first = RTLIL::SigSpec(w);
 | 
			
		||||
				c.second = it.second;
 | 
			
		||||
				apply_prefix(cell->name.str(), c.first, module);
 | 
			
		||||
				apply_prefix(cell->name, c.first, module);
 | 
			
		||||
				extra_connect.first = c.first;
 | 
			
		||||
				extra_connect.second = c.second;
 | 
			
		||||
			} else {
 | 
			
		||||
				SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second;
 | 
			
		||||
				apply_prefix(cell->name.str(), sig_tpl_pf, module);
 | 
			
		||||
				apply_prefix(cell->name, sig_tpl_pf, module);
 | 
			
		||||
				for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) {
 | 
			
		||||
					if (tpl_written_bits.count(tpl_sigmap(sig_tpl[i]))) {
 | 
			
		||||
						c.first.append(sig_mod[i]);
 | 
			
		||||
| 
						 | 
				
			
			@ -320,7 +320,7 @@ struct TechmapWorker
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
				for (auto &attr : w->attributes) {
 | 
			
		||||
					if (attr.first == "\\src")
 | 
			
		||||
					if (attr.first == ID(src))
 | 
			
		||||
						continue;
 | 
			
		||||
					module->connect(extra_connect);
 | 
			
		||||
					break;
 | 
			
		||||
| 
						 | 
				
			
			@ -330,13 +330,13 @@ struct TechmapWorker
 | 
			
		|||
 | 
			
		||||
		for (auto &it : tpl->cells_)
 | 
			
		||||
		{
 | 
			
		||||
			std::string c_name = it.second->name.str();
 | 
			
		||||
			bool techmap_replace_cell = (!flatten_mode) && (c_name == "\\_TECHMAP_REPLACE_");
 | 
			
		||||
			IdString c_name = it.second->name.str();
 | 
			
		||||
			bool techmap_replace_cell = (!flatten_mode) && (c_name == ID(_TECHMAP_REPLACE_));
 | 
			
		||||
 | 
			
		||||
			if (techmap_replace_cell)
 | 
			
		||||
				c_name = orig_cell_name;
 | 
			
		||||
			else
 | 
			
		||||
				apply_prefix(cell->name.str(), c_name);
 | 
			
		||||
				apply_prefix(cell->name, c_name);
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *c = module->addCell(c_name, it.second);
 | 
			
		||||
			design->select(module, c);
 | 
			
		||||
| 
						 | 
				
			
			@ -345,24 +345,24 @@ struct TechmapWorker
 | 
			
		|||
				c->type = c->type.substr(1);
 | 
			
		||||
 | 
			
		||||
			for (auto &it2 : c->connections_) {
 | 
			
		||||
				apply_prefix(cell->name.str(), it2.second, module);
 | 
			
		||||
				apply_prefix(cell->name, it2.second, module);
 | 
			
		||||
				port_signal_map.apply(it2.second);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (c->type == "$memrd" || c->type == "$memwr" || c->type == "$meminit") {
 | 
			
		||||
				IdString memid = c->getParam("\\MEMID").decode_string();
 | 
			
		||||
			if (c->type.in(ID($memrd), ID($memwr), ID($meminit))) {
 | 
			
		||||
				IdString memid = c->getParam(ID(MEMID)).decode_string();
 | 
			
		||||
				log_assert(memory_renames.count(memid) != 0);
 | 
			
		||||
				c->setParam("\\MEMID", Const(memory_renames[memid].str()));
 | 
			
		||||
				c->setParam(ID(MEMID), Const(memory_renames[memid].str()));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (c->type == "$mem") {
 | 
			
		||||
				string memid = c->getParam("\\MEMID").decode_string();
 | 
			
		||||
				apply_prefix(cell->name.str(), memid);
 | 
			
		||||
				c->setParam("\\MEMID", Const(memid));
 | 
			
		||||
			if (c->type == ID($mem)) {
 | 
			
		||||
				IdString memid = c->getParam(ID(MEMID)).decode_string();
 | 
			
		||||
				apply_prefix(cell->name, memid);
 | 
			
		||||
				c->setParam(ID(MEMID), Const(memid.c_str()));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (c->attributes.count("\\src"))
 | 
			
		||||
				c->add_strpool_attribute("\\src", extra_src_attrs);
 | 
			
		||||
			if (c->attributes.count(ID(src)))
 | 
			
		||||
				c->add_strpool_attribute(ID(src), extra_src_attrs);
 | 
			
		||||
 | 
			
		||||
			if (techmap_replace_cell)
 | 
			
		||||
				for (auto attr : cell->attributes)
 | 
			
		||||
| 
						 | 
				
			
			@ -416,9 +416,9 @@ struct TechmapWorker
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			if (flatten_mode) {
 | 
			
		||||
				bool keepit = cell->get_bool_attribute("\\keep_hierarchy");
 | 
			
		||||
				bool keepit = cell->get_bool_attribute(ID(keep_hierarchy));
 | 
			
		||||
				for (auto &tpl_name : celltypeMap.at(cell_type))
 | 
			
		||||
					if (map->modules_[tpl_name]->get_bool_attribute("\\keep_hierarchy"))
 | 
			
		||||
					if (map->modules_[tpl_name]->get_bool_attribute(ID(keep_hierarchy)))
 | 
			
		||||
						keepit = true;
 | 
			
		||||
				if (keepit) {
 | 
			
		||||
					if (!flatten_keep_list[cell]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -484,13 +484,13 @@ struct TechmapWorker
 | 
			
		|||
				{
 | 
			
		||||
					std::string extmapper_name;
 | 
			
		||||
 | 
			
		||||
					if (tpl->get_bool_attribute("\\techmap_simplemap"))
 | 
			
		||||
					if (tpl->get_bool_attribute(ID(techmap_simplemap)))
 | 
			
		||||
						extmapper_name = "simplemap";
 | 
			
		||||
 | 
			
		||||
					if (tpl->get_bool_attribute("\\techmap_maccmap"))
 | 
			
		||||
					if (tpl->get_bool_attribute(ID(techmap_maccmap)))
 | 
			
		||||
						extmapper_name = "maccmap";
 | 
			
		||||
 | 
			
		||||
					if (tpl->attributes.count("\\techmap_wrap"))
 | 
			
		||||
					if (tpl->attributes.count(ID(techmap_wrap)))
 | 
			
		||||
						extmapper_name = "wrap";
 | 
			
		||||
 | 
			
		||||
					if (!extmapper_name.empty())
 | 
			
		||||
| 
						 | 
				
			
			@ -505,7 +505,7 @@ struct TechmapWorker
 | 
			
		|||
								m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second));
 | 
			
		||||
 | 
			
		||||
							if (extmapper_name == "wrap")
 | 
			
		||||
								m_name += ":" + sha1(tpl->attributes.at("\\techmap_wrap").decode_string());
 | 
			
		||||
								m_name += ":" + sha1(tpl->attributes.at(ID(techmap_wrap)).decode_string());
 | 
			
		||||
 | 
			
		||||
							RTLIL::Design *extmapper_design = extern_mode && !in_recursion ? design : tpl->design;
 | 
			
		||||
							RTLIL::Module *extmapper_module = extmapper_design->module(m_name);
 | 
			
		||||
| 
						 | 
				
			
			@ -520,7 +520,7 @@ struct TechmapWorker
 | 
			
		|||
								int port_counter = 1;
 | 
			
		||||
								for (auto &c : extmapper_cell->connections_) {
 | 
			
		||||
									RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second));
 | 
			
		||||
									if (w->name == "\\Y" || w->name == "\\Q")
 | 
			
		||||
									if (w->name.in(ID(Y), ID(Q)))
 | 
			
		||||
										w->port_output = true;
 | 
			
		||||
									else
 | 
			
		||||
										w->port_input = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -541,14 +541,14 @@ struct TechmapWorker
 | 
			
		|||
 | 
			
		||||
								if (extmapper_name == "maccmap") {
 | 
			
		||||
									log("Creating %s with maccmap.\n", log_id(extmapper_module));
 | 
			
		||||
									if (extmapper_cell->type != "$macc")
 | 
			
		||||
									if (extmapper_cell->type != ID($macc))
 | 
			
		||||
										log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(extmapper_cell->type));
 | 
			
		||||
									maccmap(extmapper_module, extmapper_cell);
 | 
			
		||||
									extmapper_module->remove(extmapper_cell);
 | 
			
		||||
								}
 | 
			
		||||
 | 
			
		||||
								if (extmapper_name == "wrap") {
 | 
			
		||||
									std::string cmd_string = tpl->attributes.at("\\techmap_wrap").decode_string();
 | 
			
		||||
									std::string cmd_string = tpl->attributes.at(ID(techmap_wrap)).decode_string();
 | 
			
		||||
									log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module));
 | 
			
		||||
									mkdebug.on();
 | 
			
		||||
									Pass::call_on_module(extmapper_design, extmapper_module, cmd_string);
 | 
			
		||||
| 
						 | 
				
			
			@ -587,7 +587,7 @@ struct TechmapWorker
 | 
			
		|||
							}
 | 
			
		||||
 | 
			
		||||
							if (extmapper_name == "maccmap") {
 | 
			
		||||
								if (cell->type != "$macc")
 | 
			
		||||
								if (cell->type != ID($macc))
 | 
			
		||||
									log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(cell->type));
 | 
			
		||||
								maccmap(module, cell);
 | 
			
		||||
							}
 | 
			
		||||
| 
						 | 
				
			
			@ -616,8 +616,8 @@ struct TechmapWorker
 | 
			
		|||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (tpl->avail_parameters.count("\\_TECHMAP_CELLTYPE_") != 0)
 | 
			
		||||
						parameters["\\_TECHMAP_CELLTYPE_"] = RTLIL::unescape_id(cell->type);
 | 
			
		||||
					if (tpl->avail_parameters.count(ID(_TECHMAP_CELLTYPE_)) != 0)
 | 
			
		||||
						parameters[ID(_TECHMAP_CELLTYPE_)] = RTLIL::unescape_id(cell->type);
 | 
			
		||||
 | 
			
		||||
					for (auto conn : cell->connections()) {
 | 
			
		||||
						if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))) != 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -656,8 +656,8 @@ struct TechmapWorker
 | 
			
		|||
							bits = i;
 | 
			
		||||
					// Increment index by one to get number of bits
 | 
			
		||||
					bits++;
 | 
			
		||||
					if (tpl->avail_parameters.count("\\_TECHMAP_BITS_CONNMAP_"))
 | 
			
		||||
						parameters["\\_TECHMAP_BITS_CONNMAP_"] = bits;
 | 
			
		||||
					if (tpl->avail_parameters.count(ID(_TECHMAP_BITS_CONNMAP_)))
 | 
			
		||||
						parameters[ID(_TECHMAP_BITS_CONNMAP_)] = bits;
 | 
			
		||||
 | 
			
		||||
					for (auto conn : cell->connections())
 | 
			
		||||
						if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1136,8 +1136,8 @@ struct TechmapPass : public Pass {
 | 
			
		|||
 | 
			
		||||
		std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
 | 
			
		||||
		for (auto &it : map->modules_) {
 | 
			
		||||
			if (it.second->attributes.count("\\techmap_celltype") && !it.second->attributes.at("\\techmap_celltype").bits.empty()) {
 | 
			
		||||
				char *p = strdup(it.second->attributes.at("\\techmap_celltype").decode_string().c_str());
 | 
			
		||||
			if (it.second->attributes.count(ID(techmap_celltype)) && !it.second->attributes.at(ID(techmap_celltype)).bits.empty()) {
 | 
			
		||||
				char *p = strdup(it.second->attributes.at(ID(techmap_celltype)).decode_string().c_str());
 | 
			
		||||
				for (char *q = strtok(p, " \t\r\n"); q; q = strtok(NULL, " \t\r\n"))
 | 
			
		||||
					celltypeMap[RTLIL::escape_id(q)].insert(it.first);
 | 
			
		||||
				free(p);
 | 
			
		||||
| 
						 | 
				
			
			@ -1222,7 +1222,7 @@ struct FlattenPass : public Pass {
 | 
			
		|||
		RTLIL::Module *top_mod = NULL;
 | 
			
		||||
		if (design->full_selection())
 | 
			
		||||
			for (auto mod : design->modules())
 | 
			
		||||
				if (mod->get_bool_attribute("\\top"))
 | 
			
		||||
				if (mod->get_bool_attribute(ID(top)))
 | 
			
		||||
					top_mod = mod;
 | 
			
		||||
 | 
			
		||||
		std::set<RTLIL::Cell*> handled_cells;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,38 +63,38 @@ struct TribufWorker {
 | 
			
		|||
 | 
			
		||||
		for (auto cell : module->selected_cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type == "$tribuf")
 | 
			
		||||
				tribuf_cells[sigmap(cell->getPort("\\Y"))].push_back(cell);
 | 
			
		||||
			if (cell->type == ID($tribuf))
 | 
			
		||||
				tribuf_cells[sigmap(cell->getPort(ID(Y)))].push_back(cell);
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$_TBUF_")
 | 
			
		||||
				tribuf_cells[sigmap(cell->getPort("\\Y"))].push_back(cell);
 | 
			
		||||
			if (cell->type == ID($_TBUF_))
 | 
			
		||||
				tribuf_cells[sigmap(cell->getPort(ID(Y)))].push_back(cell);
 | 
			
		||||
 | 
			
		||||
			if (cell->type.in("$mux", "$_MUX_"))
 | 
			
		||||
			if (cell->type.in(ID($mux), ID($_MUX_)))
 | 
			
		||||
			{
 | 
			
		||||
				IdString en_port = cell->type == "$mux" ? "\\EN" : "\\E";
 | 
			
		||||
				IdString tri_type = cell->type == "$mux" ? "$tribuf" : "$_TBUF_";
 | 
			
		||||
				IdString en_port = cell->type == ID($mux) ? ID(EN) : ID(E);
 | 
			
		||||
				IdString tri_type = cell->type == ID($mux) ? ID($tribuf) : ID($_TBUF_);
 | 
			
		||||
 | 
			
		||||
				if (is_all_z(cell->getPort("\\A")) && is_all_z(cell->getPort("\\B"))) {
 | 
			
		||||
				if (is_all_z(cell->getPort(ID(A))) && is_all_z(cell->getPort(ID(B)))) {
 | 
			
		||||
					module->remove(cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (is_all_z(cell->getPort("\\A"))) {
 | 
			
		||||
					cell->setPort("\\A", cell->getPort("\\B"));
 | 
			
		||||
					cell->setPort(en_port, cell->getPort("\\S"));
 | 
			
		||||
					cell->unsetPort("\\B");
 | 
			
		||||
					cell->unsetPort("\\S");
 | 
			
		||||
				if (is_all_z(cell->getPort(ID(A)))) {
 | 
			
		||||
					cell->setPort(ID(A), cell->getPort(ID(B)));
 | 
			
		||||
					cell->setPort(en_port, cell->getPort(ID(S)));
 | 
			
		||||
					cell->unsetPort(ID(B));
 | 
			
		||||
					cell->unsetPort(ID(S));
 | 
			
		||||
					cell->type = tri_type;
 | 
			
		||||
					tribuf_cells[sigmap(cell->getPort("\\Y"))].push_back(cell);
 | 
			
		||||
					tribuf_cells[sigmap(cell->getPort(ID(Y)))].push_back(cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (is_all_z(cell->getPort("\\B"))) {
 | 
			
		||||
					cell->setPort(en_port, module->Not(NEW_ID, cell->getPort("\\S")));
 | 
			
		||||
					cell->unsetPort("\\B");
 | 
			
		||||
					cell->unsetPort("\\S");
 | 
			
		||||
				if (is_all_z(cell->getPort(ID(B)))) {
 | 
			
		||||
					cell->setPort(en_port, module->Not(NEW_ID, cell->getPort(ID(S))));
 | 
			
		||||
					cell->unsetPort(ID(B));
 | 
			
		||||
					cell->unsetPort(ID(S));
 | 
			
		||||
					cell->type = tri_type;
 | 
			
		||||
					tribuf_cells[sigmap(cell->getPort("\\Y"))].push_back(cell);
 | 
			
		||||
					tribuf_cells[sigmap(cell->getPort(ID(Y)))].push_back(cell);
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -118,11 +118,11 @@ struct TribufWorker {
 | 
			
		|||
 | 
			
		||||
				SigSpec pmux_b, pmux_s;
 | 
			
		||||
				for (auto cell : it.second) {
 | 
			
		||||
					if (cell->type == "$tribuf")
 | 
			
		||||
						pmux_s.append(cell->getPort("\\EN"));
 | 
			
		||||
					if (cell->type == ID($tribuf))
 | 
			
		||||
						pmux_s.append(cell->getPort(ID(EN)));
 | 
			
		||||
					else
 | 
			
		||||
						pmux_s.append(cell->getPort("\\E"));
 | 
			
		||||
					pmux_b.append(cell->getPort("\\A"));
 | 
			
		||||
						pmux_s.append(cell->getPort(ID(E)));
 | 
			
		||||
					pmux_b.append(cell->getPort(ID(A)));
 | 
			
		||||
					module->remove(cell);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,12 +62,12 @@ struct ZinitPass : public Pass {
 | 
			
		|||
 | 
			
		||||
			for (auto wire : module->selected_wires())
 | 
			
		||||
			{
 | 
			
		||||
				if (wire->attributes.count("\\init") == 0)
 | 
			
		||||
				if (wire->attributes.count(ID(init)) == 0)
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				SigSpec wirebits = sigmap(wire);
 | 
			
		||||
				Const initval = wire->attributes.at("\\init");
 | 
			
		||||
				wire->attributes.erase("\\init");
 | 
			
		||||
				Const initval = wire->attributes.at(ID(init));
 | 
			
		||||
				wire->attributes.erase(ID(init));
 | 
			
		||||
 | 
			
		||||
				for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			@ -90,12 +90,12 @@ struct ZinitPass : public Pass {
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			pool<IdString> dff_types = {
 | 
			
		||||
				"$ff", "$dff", "$dffe", "$dffsr", "$adff",
 | 
			
		||||
				"$_FF_", "$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_",
 | 
			
		||||
				"$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_",
 | 
			
		||||
				"$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_",
 | 
			
		||||
				"$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
 | 
			
		||||
				"$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_"
 | 
			
		||||
				ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($adff),
 | 
			
		||||
				ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
 | 
			
		||||
				ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
 | 
			
		||||
				ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
 | 
			
		||||
				ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
 | 
			
		||||
				ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			for (auto cell : module->selected_cells())
 | 
			
		||||
| 
						 | 
				
			
			@ -103,8 +103,8 @@ struct ZinitPass : public Pass {
 | 
			
		|||
				if (!dff_types.count(cell->type))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				SigSpec sig_d = sigmap(cell->getPort("\\D"));
 | 
			
		||||
				SigSpec sig_q = sigmap(cell->getPort("\\Q"));
 | 
			
		||||
				SigSpec sig_d = sigmap(cell->getPort(ID(D)));
 | 
			
		||||
				SigSpec sig_q = sigmap(cell->getPort(ID(Q)));
 | 
			
		||||
 | 
			
		||||
				if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -120,14 +120,14 @@ struct ZinitPass : public Pass {
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
				Wire *initwire = module->addWire(NEW_ID, GetSize(initval));
 | 
			
		||||
				initwire->attributes["\\init"] = initval;
 | 
			
		||||
				initwire->attributes[ID(init)] = initval;
 | 
			
		||||
 | 
			
		||||
				for (int i = 0; i < GetSize(initwire); i++)
 | 
			
		||||
					if (initval.bits.at(i) == State::S1)
 | 
			
		||||
					{
 | 
			
		||||
						sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
 | 
			
		||||
						module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
 | 
			
		||||
						initwire->attributes["\\init"].bits.at(i) = State::S0;
 | 
			
		||||
						initwire->attributes[ID(init)].bits.at(i) = State::S0;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
| 
						 | 
				
			
			@ -137,8 +137,8 @@ struct ZinitPass : public Pass {
 | 
			
		|||
				log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
 | 
			
		||||
						log_signal(sig_q), log_signal(initval));
 | 
			
		||||
 | 
			
		||||
				cell->setPort("\\D", sig_d);
 | 
			
		||||
				cell->setPort("\\Q", initwire);
 | 
			
		||||
				cell->setPort(ID(D), sig_d);
 | 
			
		||||
				cell->setPort(ID(Q), initwire);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (auto &it : initbits)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
 | 
			
		|||
	RTLIL::Cell *cell = module->addCell("\\UUT", cell_type);
 | 
			
		||||
	RTLIL::Wire *wire;
 | 
			
		||||
 | 
			
		||||
	if (cell_type == "$mux" || cell_type == "$pmux")
 | 
			
		||||
	if (cell_type.in("$mux", "$pmux"))
 | 
			
		||||
	{
 | 
			
		||||
		int width = 1 + xorshift32(8);
 | 
			
		||||
		int swidth = cell_type == "$mux" ? 1 : 1 + xorshift32(8);
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +264,7 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
 | 
			
		|||
		cell->setPort("\\Y", wire);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (muxdiv && (cell_type == "$div" || cell_type == "$mod")) {
 | 
			
		||||
	if (muxdiv && cell_type.in("$div", "$mod")) {
 | 
			
		||||
		auto b_not_zero = module->ReduceBool(NEW_ID, cell->getPort("\\B"));
 | 
			
		||||
		auto div_out = module->addWire(NEW_ID, GetSize(cell->getPort("\\Y")));
 | 
			
		||||
		module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(div_out)), div_out, b_not_zero, cell->getPort("\\Y"));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue