mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge branch 'xaig' into xc7mux
This commit is contained in:
		
						commit
						4cfef7897f
					
				
					 31 changed files with 952 additions and 282 deletions
				
			
		| 
						 | 
				
			
			@ -685,7 +685,7 @@ struct AigerBackend : public Backend {
 | 
			
		|||
		log("invariant constraints.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -ascii\n");
 | 
			
		||||
		log("        write ASCII version of AGIER format\n");
 | 
			
		||||
		log("        write ASCII version of AIGER format\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -zinit\n");
 | 
			
		||||
		log("        convert FFs to zero-initialized FFs, adding additional inputs for\n");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,8 @@
 | 
			
		|||
 | 
			
		||||
#include "kernel/yosys.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
#include "kernel/celltypes.h"
 | 
			
		||||
#include "kernel/utils.h"
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
| 
						 | 
				
			
			@ -46,9 +48,8 @@ struct XAigerWriter
 | 
			
		|||
	pool<SigBit> input_bits, output_bits;
 | 
			
		||||
	dict<SigBit, SigBit> not_map, ff_map, alias_map;
 | 
			
		||||
	dict<SigBit, pair<SigBit, SigBit>> and_map;
 | 
			
		||||
	pool<SigBit> initstate_bits;
 | 
			
		||||
	//pool<SigBit> initstate_bits;
 | 
			
		||||
	vector<std::pair<SigBit,int>> ci_bits, co_bits;
 | 
			
		||||
	dict<IdString, unsigned> type_map;
 | 
			
		||||
 | 
			
		||||
	vector<pair<int, int>> aig_gates;
 | 
			
		||||
	vector<int> aig_latchin, aig_latchinit, aig_outputs;
 | 
			
		||||
| 
						 | 
				
			
			@ -58,11 +59,11 @@ struct XAigerWriter
 | 
			
		|||
	dict<SigBit, int> ordered_outputs;
 | 
			
		||||
	dict<SigBit, int> ordered_latches;
 | 
			
		||||
 | 
			
		||||
	dict<SigBit, int> init_inputs;
 | 
			
		||||
	int initstate_ff = 0;
 | 
			
		||||
 | 
			
		||||
	vector<Cell*> box_list;
 | 
			
		||||
 | 
			
		||||
	//dict<SigBit, int> init_inputs;
 | 
			
		||||
	//int initstate_ff = 0;
 | 
			
		||||
 | 
			
		||||
	int mkgate(int a0, int a1)
 | 
			
		||||
	{
 | 
			
		||||
		aig_m++, aig_a++;
 | 
			
		||||
| 
						 | 
				
			
			@ -76,10 +77,10 @@ struct XAigerWriter
 | 
			
		|||
		{
 | 
			
		||||
			aig_map[bit] = -1;
 | 
			
		||||
 | 
			
		||||
			if (initstate_bits.count(bit)) {
 | 
			
		||||
				log_assert(initstate_ff > 0);
 | 
			
		||||
				aig_map[bit] = initstate_ff;
 | 
			
		||||
			} else
 | 
			
		||||
			//if (initstate_bits.count(bit)) {
 | 
			
		||||
			//	log_assert(initstate_ff > 0);
 | 
			
		||||
			//	aig_map[bit] = initstate_ff;
 | 
			
		||||
			//} else
 | 
			
		||||
			if (not_map.count(bit)) {
 | 
			
		||||
				int a = bit2aig(not_map.at(bit)) ^ 1;
 | 
			
		||||
				aig_map[bit] = a;
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +103,7 @@ struct XAigerWriter
 | 
			
		|||
		return aig_map.at(bit);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
 | 
			
		||||
	XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module)
 | 
			
		||||
	{
 | 
			
		||||
		pool<SigBit> undriven_bits;
 | 
			
		||||
		pool<SigBit> unused_bits;
 | 
			
		||||
| 
						 | 
				
			
			@ -159,19 +160,56 @@ struct XAigerWriter
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto bit : input_bits) {
 | 
			
		||||
			if (!bit.wire->port_output)
 | 
			
		||||
				undriven_bits.erase(bit);
 | 
			
		||||
			// Erase POs that are also PIs
 | 
			
		||||
			output_bits.erase(bit);
 | 
			
		||||
		}
 | 
			
		||||
		for (auto bit : input_bits)
 | 
			
		||||
			undriven_bits.erase(bit);
 | 
			
		||||
 | 
			
		||||
		for (auto bit : output_bits)
 | 
			
		||||
			if (!bit.wire->port_input)
 | 
			
		||||
				unused_bits.erase(bit);
 | 
			
		||||
 | 
			
		||||
		dict<SigBit, pool<IdString>> bit_drivers, bit_users;
 | 
			
		||||
		TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
 | 
			
		||||
		bool abc_box_seen = false;
 | 
			
		||||
 | 
			
		||||
		for (auto cell : module->cells())
 | 
			
		||||
		{
 | 
			
		||||
			RTLIL::Module* inst_module = module->design->module(cell->type);
 | 
			
		||||
			bool known_type = yosys_celltypes.cell_known(cell->type);
 | 
			
		||||
 | 
			
		||||
			if (!holes_mode) {
 | 
			
		||||
				toposort.node(cell->name);
 | 
			
		||||
				for (const auto &conn : cell->connections())
 | 
			
		||||
				{
 | 
			
		||||
					if (!cell->type.in("$_NOT_", "$_AND_")) {
 | 
			
		||||
						if (known_type) {
 | 
			
		||||
							if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA"))
 | 
			
		||||
								continue;
 | 
			
		||||
							if (cell->type == "$memrd" && conn.first == "\\DATA")
 | 
			
		||||
								continue;
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						if (inst_module) {
 | 
			
		||||
							RTLIL::Wire* inst_module_port = inst_module->wire(conn.first);
 | 
			
		||||
							log_assert(inst_module_port);
 | 
			
		||||
 | 
			
		||||
							if (inst_module_port->attributes.count("\\abc_flop_q"))
 | 
			
		||||
								continue;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (cell->input(conn.first)) {
 | 
			
		||||
						// Ignore inout for the sake of topographical ordering
 | 
			
		||||
						if (cell->output(conn.first)) continue;
 | 
			
		||||
						for (auto bit : sigmap(conn.second))
 | 
			
		||||
							bit_users[bit].insert(cell->name);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (cell->output(conn.first))
 | 
			
		||||
						for (auto bit : sigmap(conn.second))
 | 
			
		||||
							bit_drivers[bit].insert(cell->name);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$_NOT_")
 | 
			
		||||
			{
 | 
			
		||||
				SigBit A = sigmap(cell->getPort("\\A").as_bit());
 | 
			
		||||
| 
						 | 
				
			
			@ -204,59 +242,100 @@ struct XAigerWriter
 | 
			
		|||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (cell->type == "$initstate")
 | 
			
		||||
			{
 | 
			
		||||
				SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
 | 
			
		||||
				undriven_bits.erase(Y);
 | 
			
		||||
				initstate_bits.insert(Y);
 | 
			
		||||
				continue;
 | 
			
		||||
			//if (cell->type == "$initstate")
 | 
			
		||||
			//{
 | 
			
		||||
			//	SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
 | 
			
		||||
			//	undriven_bits.erase(Y);
 | 
			
		||||
			//	initstate_bits.insert(Y);
 | 
			
		||||
			//	continue;
 | 
			
		||||
			//}
 | 
			
		||||
 | 
			
		||||
			if (inst_module && inst_module->attributes.count("\\abc_box_id")) {
 | 
			
		||||
				abc_box_seen = true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			RTLIL::Module* box_module = module->design->module(cell->type);
 | 
			
		||||
			bool abc_box = box_module && box_module->attributes.count("\\abc_box_id");
 | 
			
		||||
 | 
			
		||||
			for (const auto &c : cell->connections()) {
 | 
			
		||||
				/*if (c.second.is_fully_const()) continue;*/
 | 
			
		||||
				for (auto b : c.second.bits()) {
 | 
			
		||||
					auto is_input = cell->input(c.first);
 | 
			
		||||
					auto is_output = cell->output(c.first);
 | 
			
		||||
					log_assert(is_input || is_output);
 | 
			
		||||
					if (is_input) {
 | 
			
		||||
						/*if (!w->port_input)*/ {
 | 
			
		||||
							SigBit I = sigmap(b);
 | 
			
		||||
							if (I != b)
 | 
			
		||||
								alias_map[b] = I;
 | 
			
		||||
							/*if (!output_bits.count(b))*/
 | 
			
		||||
							if (abc_box)
 | 
			
		||||
								co_bits.emplace_back(b, 0);
 | 
			
		||||
							else if (b.wire) {
 | 
			
		||||
			else {
 | 
			
		||||
				for (const auto &c : cell->connections()) {
 | 
			
		||||
					if (c.second.is_fully_const()) continue;
 | 
			
		||||
					for (auto b : c.second.bits()) {
 | 
			
		||||
						Wire *w = b.wire;
 | 
			
		||||
						if (!w) continue;
 | 
			
		||||
						auto is_input = cell->input(c.first);
 | 
			
		||||
						auto is_output = cell->output(c.first);
 | 
			
		||||
						log_assert(is_input || is_output);
 | 
			
		||||
						if (is_input) {
 | 
			
		||||
							if (!w->port_input) {
 | 
			
		||||
								SigBit I = sigmap(b);
 | 
			
		||||
								if (I != b)
 | 
			
		||||
									alias_map[b] = I;
 | 
			
		||||
								output_bits.insert(b);
 | 
			
		||||
								if (!b.wire->port_input)
 | 
			
		||||
									unused_bits.erase(b);
 | 
			
		||||
								unused_bits.erase(b);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if (is_output) {
 | 
			
		||||
						SigBit O = sigmap(b);
 | 
			
		||||
						/*if (!input_bits.count(O))*/
 | 
			
		||||
						if (abc_box)
 | 
			
		||||
							ci_bits.emplace_back(O, 0);
 | 
			
		||||
						else {
 | 
			
		||||
						if (is_output) {
 | 
			
		||||
							SigBit O = sigmap(b);
 | 
			
		||||
							input_bits.insert(O);
 | 
			
		||||
							if (!O.wire->port_output)
 | 
			
		||||
								undriven_bits.erase(O);
 | 
			
		||||
							undriven_bits.erase(O);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if (!type_map.count(cell->type))
 | 
			
		||||
					type_map[cell->type] = type_map.size()+1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (abc_box)
 | 
			
		||||
				box_list.emplace_back(cell);
 | 
			
		||||
			//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (abc_box_seen) {
 | 
			
		||||
			for (auto &it : bit_users)
 | 
			
		||||
				if (bit_drivers.count(it.first))
 | 
			
		||||
					for (auto driver_cell : bit_drivers.at(it.first))
 | 
			
		||||
					for (auto user_cell : it.second)
 | 
			
		||||
						toposort.edge(driver_cell, user_cell);
 | 
			
		||||
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
			toposort.analyze_loops = true;
 | 
			
		||||
#endif
 | 
			
		||||
			toposort.sort();
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
			for (auto &it : toposort.loops) {
 | 
			
		||||
				log("  loop");
 | 
			
		||||
				for (auto cell : it)
 | 
			
		||||
					log(" %s", log_id(cell));
 | 
			
		||||
				log("\n");
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
			log_assert(!toposort.found_loops);
 | 
			
		||||
 | 
			
		||||
			for (auto cell_name : toposort.sorted) {
 | 
			
		||||
				RTLIL::Cell *cell = module->cell(cell_name);
 | 
			
		||||
				RTLIL::Module* box_module = module->design->module(cell->type);
 | 
			
		||||
				if (!box_module || !box_module->attributes.count("\\abc_box_id"))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				// Box ordering is alphabetical
 | 
			
		||||
				cell->connections_.sort(RTLIL::sort_by_id_str());
 | 
			
		||||
				for (const auto &c : cell->connections()) {
 | 
			
		||||
					for (auto b : c.second.bits()) {
 | 
			
		||||
						auto is_input = cell->input(c.first);
 | 
			
		||||
						auto is_output = cell->output(c.first);
 | 
			
		||||
						log_assert(is_input || is_output);
 | 
			
		||||
						if (is_input) {
 | 
			
		||||
							SigBit I = sigmap(b);
 | 
			
		||||
							if (I != b)
 | 
			
		||||
								alias_map[b] = I;
 | 
			
		||||
							co_bits.emplace_back(b, 0);
 | 
			
		||||
						}
 | 
			
		||||
						if (is_output) {
 | 
			
		||||
							SigBit O = sigmap(b);
 | 
			
		||||
							ci_bits.emplace_back(O, 0);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				box_list.emplace_back(cell);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// TODO: Free memory from toposort, bit_drivers, bit_users
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto bit : input_bits) {
 | 
			
		||||
			RTLIL::Wire *wire = bit.wire;
 | 
			
		||||
			// If encountering an inout port, then create a new wire with $inout.out
 | 
			
		||||
| 
						 | 
				
			
			@ -274,27 +353,23 @@ struct XAigerWriter
 | 
			
		|||
					and_map[new_bit] = and_map.at(bit);
 | 
			
		||||
				else if (alias_map.count(bit))
 | 
			
		||||
					alias_map[new_bit] = alias_map.at(bit);
 | 
			
		||||
				else
 | 
			
		||||
					alias_map[new_bit] = bit;
 | 
			
		||||
				output_bits.insert(new_bit);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Do some CI/CO post-processing:
 | 
			
		||||
		// Erase all POs and COs that are undriven
 | 
			
		||||
		for (auto bit : undriven_bits) {
 | 
			
		||||
			//co_bits.erase(bit);
 | 
			
		||||
		// Erase all POs that are undriven
 | 
			
		||||
		for (auto bit : undriven_bits)
 | 
			
		||||
			output_bits.erase(bit);
 | 
			
		||||
		}
 | 
			
		||||
		// Erase all CIs that are also COs
 | 
			
		||||
		//for (auto bit : co_bits)
 | 
			
		||||
		//	ci_bits.erase(bit);
 | 
			
		||||
		// CIs cannot be undriven
 | 
			
		||||
		for (const auto &c : ci_bits)
 | 
			
		||||
			undriven_bits.erase(c.first);
 | 
			
		||||
 | 
			
		||||
		for (auto bit : unused_bits)
 | 
			
		||||
			undriven_bits.erase(bit);
 | 
			
		||||
 | 
			
		||||
		if (!undriven_bits.empty()) {
 | 
			
		||||
		if (!undriven_bits.empty() && !holes_mode) {
 | 
			
		||||
			undriven_bits.sort();
 | 
			
		||||
			for (auto bit : undriven_bits) {
 | 
			
		||||
				log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
 | 
			
		||||
| 
						 | 
				
			
			@ -313,30 +388,30 @@ struct XAigerWriter
 | 
			
		|||
		aig_map[State::S0] = 0;
 | 
			
		||||
		aig_map[State::S1] = 1;
 | 
			
		||||
 | 
			
		||||
		for (auto &c : ci_bits) {
 | 
			
		||||
			aig_m++, aig_i++;
 | 
			
		||||
			c.second = 2*aig_m;
 | 
			
		||||
			aig_map[c.first] = c.second;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto bit : input_bits) {
 | 
			
		||||
			aig_m++, aig_i++;
 | 
			
		||||
			aig_map[bit] = 2*aig_m;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto &c : ci_bits) {
 | 
			
		||||
			aig_m++, aig_i++;
 | 
			
		||||
			c.second = 2*aig_m;
 | 
			
		||||
            aig_map[c.first] = c.second;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (imode && input_bits.empty()) {
 | 
			
		||||
			aig_m++, aig_i++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (zinit_mode)
 | 
			
		||||
		{
 | 
			
		||||
			for (auto it : ff_map) {
 | 
			
		||||
				if (init_map.count(it.first))
 | 
			
		||||
					continue;
 | 
			
		||||
				aig_m++, aig_i++;
 | 
			
		||||
				init_inputs[it.first] = 2*aig_m;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		//if (zinit_mode)
 | 
			
		||||
		//{
 | 
			
		||||
		//	for (auto it : ff_map) {
 | 
			
		||||
		//		if (init_map.count(it.first))
 | 
			
		||||
		//			continue;
 | 
			
		||||
		//		aig_m++, aig_i++;
 | 
			
		||||
		//		init_inputs[it.first] = 2*aig_m;
 | 
			
		||||
		//	}
 | 
			
		||||
		//}
 | 
			
		||||
 | 
			
		||||
		for (auto it : ff_map) {
 | 
			
		||||
			aig_m++, aig_l++;
 | 
			
		||||
| 
						 | 
				
			
			@ -348,29 +423,29 @@ struct XAigerWriter
 | 
			
		|||
				aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!initstate_bits.empty() || !init_inputs.empty()) {
 | 
			
		||||
			aig_m++, aig_l++;
 | 
			
		||||
			initstate_ff = 2*aig_m+1;
 | 
			
		||||
			aig_latchinit.push_back(0);
 | 
			
		||||
		}
 | 
			
		||||
		//if (!initstate_bits.empty() || !init_inputs.empty()) {
 | 
			
		||||
		//	aig_m++, aig_l++;
 | 
			
		||||
		//	initstate_ff = 2*aig_m+1;
 | 
			
		||||
		//	aig_latchinit.push_back(0);
 | 
			
		||||
		//}
 | 
			
		||||
 | 
			
		||||
		if (zinit_mode)
 | 
			
		||||
		{
 | 
			
		||||
			for (auto it : ff_map)
 | 
			
		||||
			{
 | 
			
		||||
				int l = ordered_latches[it.first];
 | 
			
		||||
		//if (zinit_mode)
 | 
			
		||||
		//{
 | 
			
		||||
		//	for (auto it : ff_map)
 | 
			
		||||
		//	{
 | 
			
		||||
		//		int l = ordered_latches[it.first];
 | 
			
		||||
 | 
			
		||||
				if (aig_latchinit.at(l) == 1)
 | 
			
		||||
					aig_map[it.first] ^= 1;
 | 
			
		||||
		//		if (aig_latchinit.at(l) == 1)
 | 
			
		||||
		//			aig_map[it.first] ^= 1;
 | 
			
		||||
 | 
			
		||||
				if (aig_latchinit.at(l) == 2)
 | 
			
		||||
				{
 | 
			
		||||
					int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
 | 
			
		||||
					int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
 | 
			
		||||
					aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		//		if (aig_latchinit.at(l) == 2)
 | 
			
		||||
		//		{
 | 
			
		||||
		//			int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
 | 
			
		||||
		//			int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
 | 
			
		||||
		//			aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
 | 
			
		||||
		//		}
 | 
			
		||||
		//	}
 | 
			
		||||
		//}
 | 
			
		||||
 | 
			
		||||
		for (auto it : ff_map) {
 | 
			
		||||
			int a = bit2aig(it.second);
 | 
			
		||||
| 
						 | 
				
			
			@ -381,8 +456,8 @@ struct XAigerWriter
 | 
			
		|||
				aig_latchin.push_back(a);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!initstate_bits.empty() || !init_inputs.empty())
 | 
			
		||||
			aig_latchin.push_back(1);
 | 
			
		||||
		//if (!initstate_bits.empty() || !init_inputs.empty())
 | 
			
		||||
		//	aig_latchin.push_back(1);
 | 
			
		||||
 | 
			
		||||
		for (auto &c : co_bits) {
 | 
			
		||||
			RTLIL::SigBit bit = c.first;
 | 
			
		||||
| 
						 | 
				
			
			@ -517,14 +592,14 @@ struct XAigerWriter
 | 
			
		|||
							symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (init_inputs.count(sig[i])) {
 | 
			
		||||
						int a = init_inputs.at(sig[i]);
 | 
			
		||||
						log_assert((a & 1) == 0);
 | 
			
		||||
						if (GetSize(wire) != 1)
 | 
			
		||||
							symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
 | 
			
		||||
						else
 | 
			
		||||
							symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
 | 
			
		||||
					}
 | 
			
		||||
					//if (init_inputs.count(sig[i])) {
 | 
			
		||||
					//	int a = init_inputs.at(sig[i]);
 | 
			
		||||
					//	log_assert((a & 1) == 0);
 | 
			
		||||
					//	if (GetSize(wire) != 1)
 | 
			
		||||
					//		symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
 | 
			
		||||
					//	else
 | 
			
		||||
					//		symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
 | 
			
		||||
					//}
 | 
			
		||||
 | 
			
		||||
					if (ordered_latches.count(sig[i])) {
 | 
			
		||||
						int l = ordered_latches.at(sig[i]);
 | 
			
		||||
| 
						 | 
				
			
			@ -584,17 +659,17 @@ struct XAigerWriter
 | 
			
		|||
				if (holes_module && !holes_module->cell(stringf("\\u%d", box_id)))
 | 
			
		||||
					holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type);
 | 
			
		||||
				RTLIL::Wire *holes_wire;
 | 
			
		||||
				int num_inputs = 0;
 | 
			
		||||
				// NB: cell->connections_ already sorted from before
 | 
			
		||||
				for (const auto &c : cell->connections()) {
 | 
			
		||||
					log_assert(c.second.size() == 1);
 | 
			
		||||
					if (cell->input(c.first)) {
 | 
			
		||||
						box_inputs += c.second.size();
 | 
			
		||||
						if (holes_cell) {
 | 
			
		||||
							holes_wire = holes_module->wire(stringf("\\i%d", num_inputs));
 | 
			
		||||
							holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
 | 
			
		||||
							if (!holes_wire) {
 | 
			
		||||
								holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs));
 | 
			
		||||
								holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
 | 
			
		||||
								holes_wire->port_input = true;
 | 
			
		||||
							}
 | 
			
		||||
							++num_inputs;
 | 
			
		||||
							holes_cell->setPort(c.first, holes_wire);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -631,12 +706,12 @@ struct XAigerWriter
 | 
			
		|||
				RTLIL::Selection& sel = holes_module->design->selection_stack.back();
 | 
			
		||||
				sel.select(holes_module);
 | 
			
		||||
 | 
			
		||||
				Pass::call(holes_module->design, "flatten; aigmap");
 | 
			
		||||
				Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge");
 | 
			
		||||
 | 
			
		||||
				holes_module->design->selection_stack.pop_back();
 | 
			
		||||
 | 
			
		||||
				std::stringstream a_buffer;
 | 
			
		||||
				XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/);
 | 
			
		||||
				XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */);
 | 
			
		||||
				writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/);
 | 
			
		||||
 | 
			
		||||
				f << "a";
 | 
			
		||||
| 
						 | 
				
			
			@ -686,12 +761,12 @@ struct XAigerWriter
 | 
			
		|||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (init_inputs.count(sig[i])) {
 | 
			
		||||
					int a = init_inputs.at(sig[i]);
 | 
			
		||||
					log_assert((a & 1) == 0);
 | 
			
		||||
					init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				//if (init_inputs.count(sig[i])) {
 | 
			
		||||
				//	int a = init_inputs.at(sig[i]);
 | 
			
		||||
				//	log_assert((a & 1) == 0);
 | 
			
		||||
				//	init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
 | 
			
		||||
				//	continue;
 | 
			
		||||
				//}
 | 
			
		||||
 | 
			
		||||
				if (ordered_latches.count(sig[i])) {
 | 
			
		||||
					int l = ordered_latches.at(sig[i]);
 | 
			
		||||
| 
						 | 
				
			
			@ -716,7 +791,7 @@ struct XAigerWriter
 | 
			
		|||
			RTLIL::SigBit b = c.first;
 | 
			
		||||
			RTLIL::Wire *wire = b.wire;
 | 
			
		||||
			int i = b.offset;
 | 
			
		||||
			int a = c.second;
 | 
			
		||||
			int a = bit2aig(b);
 | 
			
		||||
			log_assert((a & 1) == 0);
 | 
			
		||||
			input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -769,7 +844,7 @@ struct XAigerBackend : public Backend {
 | 
			
		|||
		log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -ascii\n");
 | 
			
		||||
		log("        write ASCII version of AGIER format\n");
 | 
			
		||||
		log("        write ASCII version of AIGER format\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -zinit\n");
 | 
			
		||||
		log("        convert FFs to zero-initialized FFs, adding additional inputs for\n");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -130,72 +130,75 @@ struct JsonWriter
 | 
			
		|||
			f << stringf("        }");
 | 
			
		||||
			first = false;
 | 
			
		||||
		}
 | 
			
		||||
		f << stringf("\n      },\n");
 | 
			
		||||
		f << stringf("\n      }");
 | 
			
		||||
 | 
			
		||||
		f << stringf("      \"cells\": {");
 | 
			
		||||
		first = true;
 | 
			
		||||
		for (auto c : module->cells()) {
 | 
			
		||||
			if (use_selection && !module->selected(c))
 | 
			
		||||
				continue;
 | 
			
		||||
			f << stringf("%s\n", first ? "" : ",");
 | 
			
		||||
			f << stringf("        %s: {\n", get_name(c->name).c_str());
 | 
			
		||||
			f << stringf("          \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
 | 
			
		||||
			f << stringf("          \"type\": %s,\n", get_name(c->type).c_str());
 | 
			
		||||
			if (aig_mode) {
 | 
			
		||||
				Aig aig(c);
 | 
			
		||||
				if (!aig.name.empty()) {
 | 
			
		||||
					f << stringf("          \"model\": \"%s\",\n", aig.name.c_str());
 | 
			
		||||
					aig_models.insert(aig);
 | 
			
		||||
		if (!module->get_blackbox_attribute()) {
 | 
			
		||||
			f << stringf(",\n      \"cells\": {");
 | 
			
		||||
			first = true;
 | 
			
		||||
			for (auto c : module->cells()) {
 | 
			
		||||
				if (use_selection && !module->selected(c))
 | 
			
		||||
					continue;
 | 
			
		||||
				f << stringf("%s\n", first ? "" : ",");
 | 
			
		||||
				f << stringf("        %s: {\n", get_name(c->name).c_str());
 | 
			
		||||
				f << stringf("          \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
 | 
			
		||||
				f << stringf("          \"type\": %s,\n", get_name(c->type).c_str());
 | 
			
		||||
				if (aig_mode) {
 | 
			
		||||
					Aig aig(c);
 | 
			
		||||
					if (!aig.name.empty()) {
 | 
			
		||||
						f << stringf("          \"model\": \"%s\",\n", aig.name.c_str());
 | 
			
		||||
						aig_models.insert(aig);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			f << stringf("          \"parameters\": {");
 | 
			
		||||
			write_parameters(c->parameters);
 | 
			
		||||
			f << stringf("\n          },\n");
 | 
			
		||||
			f << stringf("          \"attributes\": {");
 | 
			
		||||
			write_parameters(c->attributes);
 | 
			
		||||
			f << stringf("\n          },\n");
 | 
			
		||||
			if (c->known()) {
 | 
			
		||||
				f << stringf("          \"port_directions\": {");
 | 
			
		||||
				f << stringf("          \"parameters\": {");
 | 
			
		||||
				write_parameters(c->parameters);
 | 
			
		||||
				f << stringf("\n          },\n");
 | 
			
		||||
				f << stringf("          \"attributes\": {");
 | 
			
		||||
				write_parameters(c->attributes);
 | 
			
		||||
				f << stringf("\n          },\n");
 | 
			
		||||
				if (c->known()) {
 | 
			
		||||
					f << stringf("          \"port_directions\": {");
 | 
			
		||||
					bool first2 = true;
 | 
			
		||||
					for (auto &conn : c->connections()) {
 | 
			
		||||
						string direction = "output";
 | 
			
		||||
						if (c->input(conn.first))
 | 
			
		||||
							direction = c->output(conn.first) ? "inout" : "input";
 | 
			
		||||
						f << stringf("%s\n", first2 ? "" : ",");
 | 
			
		||||
						f << stringf("            %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
 | 
			
		||||
						first2 = false;
 | 
			
		||||
					}
 | 
			
		||||
					f << stringf("\n          },\n");
 | 
			
		||||
				}
 | 
			
		||||
				f << stringf("          \"connections\": {");
 | 
			
		||||
				bool first2 = true;
 | 
			
		||||
				for (auto &conn : c->connections()) {
 | 
			
		||||
					string direction = "output";
 | 
			
		||||
					if (c->input(conn.first))
 | 
			
		||||
						direction = c->output(conn.first) ? "inout" : "input";
 | 
			
		||||
					f << stringf("%s\n", first2 ? "" : ",");
 | 
			
		||||
					f << stringf("            %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
 | 
			
		||||
					f << stringf("            %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
 | 
			
		||||
					first2 = false;
 | 
			
		||||
				}
 | 
			
		||||
				f << stringf("\n          },\n");
 | 
			
		||||
				f << stringf("\n          }\n");
 | 
			
		||||
				f << stringf("        }");
 | 
			
		||||
				first = false;
 | 
			
		||||
			}
 | 
			
		||||
			f << stringf("          \"connections\": {");
 | 
			
		||||
			bool first2 = true;
 | 
			
		||||
			for (auto &conn : c->connections()) {
 | 
			
		||||
				f << stringf("%s\n", first2 ? "" : ",");
 | 
			
		||||
				f << stringf("            %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
 | 
			
		||||
				first2 = false;
 | 
			
		||||
			}
 | 
			
		||||
			f << stringf("\n          }\n");
 | 
			
		||||
			f << stringf("        }");
 | 
			
		||||
			first = false;
 | 
			
		||||
		}
 | 
			
		||||
		f << stringf("\n      },\n");
 | 
			
		||||
			f << stringf("\n      },\n");
 | 
			
		||||
 | 
			
		||||
		f << stringf("      \"netnames\": {");
 | 
			
		||||
		first = true;
 | 
			
		||||
		for (auto w : module->wires()) {
 | 
			
		||||
			if (use_selection && !module->selected(w))
 | 
			
		||||
				continue;
 | 
			
		||||
			f << stringf("%s\n", first ? "" : ",");
 | 
			
		||||
			f << stringf("        %s: {\n", get_name(w->name).c_str());
 | 
			
		||||
			f << stringf("          \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
 | 
			
		||||
			f << stringf("          \"bits\": %s,\n", get_bits(w).c_str());
 | 
			
		||||
			f << stringf("          \"attributes\": {");
 | 
			
		||||
			write_parameters(w->attributes);
 | 
			
		||||
			f << stringf("\n          }\n");
 | 
			
		||||
			f << stringf("        }");
 | 
			
		||||
			first = false;
 | 
			
		||||
			f << stringf("      \"netnames\": {");
 | 
			
		||||
			first = true;
 | 
			
		||||
			for (auto w : module->wires()) {
 | 
			
		||||
				if (use_selection && !module->selected(w))
 | 
			
		||||
					continue;
 | 
			
		||||
				f << stringf("%s\n", first ? "" : ",");
 | 
			
		||||
				f << stringf("        %s: {\n", get_name(w->name).c_str());
 | 
			
		||||
				f << stringf("          \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
 | 
			
		||||
				f << stringf("          \"bits\": %s,\n", get_bits(w).c_str());
 | 
			
		||||
				f << stringf("          \"attributes\": {");
 | 
			
		||||
				write_parameters(w->attributes);
 | 
			
		||||
				f << stringf("\n          }\n");
 | 
			
		||||
				f << stringf("        }");
 | 
			
		||||
				first = false;
 | 
			
		||||
			}
 | 
			
		||||
			f << stringf("\n      }");
 | 
			
		||||
		}
 | 
			
		||||
		f << stringf("\n      }\n");
 | 
			
		||||
		f << stringf("\n");
 | 
			
		||||
 | 
			
		||||
		f << stringf("    }");
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -187,6 +187,10 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
 | 
			
		|||
{
 | 
			
		||||
	if (width < 0)
 | 
			
		||||
		width = data.bits.size() - offset;
 | 
			
		||||
	if (width == 0) {
 | 
			
		||||
		f << "\"\"";
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (nostr)
 | 
			
		||||
		goto dump_hex;
 | 
			
		||||
	if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -340,6 +344,10 @@ void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decima
 | 
			
		|||
 | 
			
		||||
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
 | 
			
		||||
{
 | 
			
		||||
	if (GetSize(sig) == 0) {
 | 
			
		||||
		f << "\"\"";
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (sig.is_chunk()) {
 | 
			
		||||
		dump_sigchunk(f, sig.as_chunk());
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,9 +35,6 @@
 | 
			
		|||
 | 
			
		||||
YOSYS_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//#define log_debug log
 | 
			
		||||
#define log_debug(...) ;
 | 
			
		||||
 | 
			
		||||
AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports)
 | 
			
		||||
    : design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -368,6 +365,13 @@ void AigerReader::parse_xaiger()
 | 
			
		|||
               f >> s;
 | 
			
		||||
               log_debug("n: '%s'\n", s.c_str());
 | 
			
		||||
            }
 | 
			
		||||
            else if (c == 'a' || c == 'i' || c == 'o' || c == 'h') {
 | 
			
		||||
                uint32_t dataSize = parse_xaiger_literal(f);
 | 
			
		||||
                f.ignore(dataSize);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (c == 'i' || c == 'l' || c == 'o') {
 | 
			
		||||
            f.ignore(1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1085,7 +1085,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
 | 
			
		||||
		// eval 1st expression
 | 
			
		||||
		AstNode *varbuf = init_ast->children[1]->clone();
 | 
			
		||||
		while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
 | 
			
		||||
		{
 | 
			
		||||
			int expr_width_hint = -1;
 | 
			
		||||
			bool expr_sign_hint = true;
 | 
			
		||||
			varbuf->detectSignWidth(expr_width_hint, expr_sign_hint);
 | 
			
		||||
			while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (varbuf->type != AST_CONSTANT)
 | 
			
		||||
			log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -1107,7 +1112,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
		{
 | 
			
		||||
			// eval 2nd expression
 | 
			
		||||
			AstNode *buf = while_ast->clone();
 | 
			
		||||
			while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
 | 
			
		||||
			{
 | 
			
		||||
				int expr_width_hint = -1;
 | 
			
		||||
				bool expr_sign_hint = true;
 | 
			
		||||
				buf->detectSignWidth(expr_width_hint, expr_sign_hint);
 | 
			
		||||
				while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, false)) { }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (buf->type != AST_CONSTANT)
 | 
			
		||||
				log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -1148,7 +1158,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
 | 
			
		||||
			// eval 3rd expression
 | 
			
		||||
			buf = next_ast->children[1]->clone();
 | 
			
		||||
			while (buf->simplify(true, false, false, stage, 32, true, false)) { }
 | 
			
		||||
			{
 | 
			
		||||
				int expr_width_hint = -1;
 | 
			
		||||
				bool expr_sign_hint = true;
 | 
			
		||||
				buf->detectSignWidth(expr_width_hint, expr_sign_hint);
 | 
			
		||||
				while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, true)) { }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (buf->type != AST_CONSTANT)
 | 
			
		||||
				log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -295,6 +295,9 @@ int main(int argc, char **argv)
 | 
			
		|||
		printf("    -E <depsfile>\n");
 | 
			
		||||
		printf("        write a Makefile dependencies file with in- and output file names\n");
 | 
			
		||||
		printf("\n");
 | 
			
		||||
		printf("    -g\n");
 | 
			
		||||
		printf("        globally enable debug log messages\n");
 | 
			
		||||
		printf("\n");
 | 
			
		||||
		printf("    -V\n");
 | 
			
		||||
		printf("        print version information and exit\n");
 | 
			
		||||
		printf("\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +318,7 @@ int main(int argc, char **argv)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	int opt;
 | 
			
		||||
	while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:")) != -1)
 | 
			
		||||
	while ((opt = getopt(argc, argv, "MXAQTVSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:")) != -1)
 | 
			
		||||
	{
 | 
			
		||||
		switch (opt)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -340,6 +343,9 @@ int main(int argc, char **argv)
 | 
			
		|||
		case 'S':
 | 
			
		||||
			passes_commands.push_back("synth");
 | 
			
		||||
			break;
 | 
			
		||||
		case 'g':
 | 
			
		||||
			log_force_debug++;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'm':
 | 
			
		||||
			plugin_filenames.push_back(optarg);
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,10 @@ int log_verbose_level;
 | 
			
		|||
string log_last_error;
 | 
			
		||||
void (*log_error_atexit)() = NULL;
 | 
			
		||||
 | 
			
		||||
int log_make_debug = 0;
 | 
			
		||||
int log_force_debug = 0;
 | 
			
		||||
int log_debug_suppressed = 0;
 | 
			
		||||
 | 
			
		||||
vector<int> header_count;
 | 
			
		||||
pool<RTLIL::IdString> log_id_cache;
 | 
			
		||||
vector<shared_str> string_buf;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +96,9 @@ void logv(const char *format, va_list ap)
 | 
			
		|||
		format++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (log_make_debug && !ys_debug(1))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	std::string str = vstringf(format, ap);
 | 
			
		||||
 | 
			
		||||
	if (str.empty())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										43
									
								
								kernel/log.h
									
										
									
									
									
								
							
							
						
						
									
										43
									
								
								kernel/log.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -64,6 +64,10 @@ extern int log_verbose_level;
 | 
			
		|||
extern string log_last_error;
 | 
			
		||||
extern void (*log_error_atexit)();
 | 
			
		||||
 | 
			
		||||
extern int log_make_debug;
 | 
			
		||||
extern int log_force_debug;
 | 
			
		||||
extern int log_debug_suppressed;
 | 
			
		||||
 | 
			
		||||
void logv(const char *format, va_list ap);
 | 
			
		||||
void logv_header(RTLIL::Design *design, const char *format, va_list ap);
 | 
			
		||||
void logv_warning(const char *format, va_list ap);
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +86,45 @@ YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf,
 | 
			
		|||
void log_file_error(const string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4), noreturn);
 | 
			
		||||
YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
 | 
			
		||||
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_debug_suppressed += n; return false; }
 | 
			
		||||
#  define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0)
 | 
			
		||||
#else
 | 
			
		||||
static inline bool ys_debug(int n = 0) { return false; }
 | 
			
		||||
#  define log_debug(_fmt, ...) do { } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline void log_suppressed() {
 | 
			
		||||
	if (log_debug_suppressed && !log_make_debug) {
 | 
			
		||||
		log("<suppressed ~%d debug messages>\n", log_debug_suppressed);
 | 
			
		||||
		log_debug_suppressed = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct LogMakeDebugHdl {
 | 
			
		||||
	bool status = false;
 | 
			
		||||
	LogMakeDebugHdl(bool start_on = false) {
 | 
			
		||||
		if (start_on)
 | 
			
		||||
			on();
 | 
			
		||||
	}
 | 
			
		||||
	~LogMakeDebugHdl() {
 | 
			
		||||
		off();
 | 
			
		||||
	}
 | 
			
		||||
	void on() {
 | 
			
		||||
		if (status) return;
 | 
			
		||||
		status=true;
 | 
			
		||||
		log_make_debug++;
 | 
			
		||||
	}
 | 
			
		||||
	void off_silent() {
 | 
			
		||||
		if (!status) return;
 | 
			
		||||
		status=false;
 | 
			
		||||
		log_make_debug--;
 | 
			
		||||
	}
 | 
			
		||||
	void off() {
 | 
			
		||||
		off_silent();
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void log_spacer();
 | 
			
		||||
void log_push();
 | 
			
		||||
void log_pop();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,6 +87,7 @@ Pass::pre_post_exec_state_t Pass::pre_execute()
 | 
			
		|||
void Pass::post_execute(Pass::pre_post_exec_state_t state)
 | 
			
		||||
{
 | 
			
		||||
	IdString::checkpoint();
 | 
			
		||||
	log_suppressed();
 | 
			
		||||
 | 
			
		||||
	int64_t time_ns = PerformanceTimer::query() - state.begin_ns;
 | 
			
		||||
	runtime_ns += time_ns;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,4 +94,38 @@ struct TracePass : public Pass {
 | 
			
		|||
	}
 | 
			
		||||
} TracePass;
 | 
			
		||||
 | 
			
		||||
struct DebugPass : public Pass {
 | 
			
		||||
	DebugPass() : Pass("debug", "run command with debug log messages enabled") { }
 | 
			
		||||
	void help() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    debug cmd\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("Execute the specified command with debug log messages enabled\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
	}
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
		for (argidx = 1; argidx < args.size(); argidx++)
 | 
			
		||||
		{
 | 
			
		||||
			// .. parse options ..
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_force_debug++;
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			std::vector<std::string> new_args(args.begin() + argidx, args.end());
 | 
			
		||||
			Pass::call(design, new_args);
 | 
			
		||||
		} catch (...) {
 | 
			
		||||
			log_force_debug--;
 | 
			
		||||
			throw;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_force_debug--;
 | 
			
		||||
	}
 | 
			
		||||
} DebugPass;
 | 
			
		||||
 | 
			
		||||
PRIVATE_NAMESPACE_END
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -137,7 +137,7 @@ void rmunused_module_cells(Module *module, bool verbose)
 | 
			
		|||
 | 
			
		||||
	for (auto cell : unused) {
 | 
			
		||||
		if (verbose)
 | 
			
		||||
			log("  removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
 | 
			
		||||
			log_debug("  removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
 | 
			
		||||
		module->design->scratchpad_set_bool("opt.did_something", true);
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
		count_rm_cells++;
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +326,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 | 
			
		|||
	for (auto wire : maybe_del_wires)
 | 
			
		||||
		if (!used_signals.check_any(RTLIL::SigSpec(wire))) {
 | 
			
		||||
			if (check_public_name(wire->name) && verbose) {
 | 
			
		||||
				log("  removing unused non-port wire %s.\n", wire->name.c_str());
 | 
			
		||||
				log_debug("  removing unused non-port wire %s.\n", wire->name.c_str());
 | 
			
		||||
			}
 | 
			
		||||
			del_wires.insert(wire);
 | 
			
		||||
			del_wires_count++;
 | 
			
		||||
| 
						 | 
				
			
			@ -336,7 +336,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
 | 
			
		|||
	count_rm_wires += del_wires.size();
 | 
			
		||||
 | 
			
		||||
	if (verbose && del_wires_count > 0)
 | 
			
		||||
		log("  removed %d unused temporary wires.\n", del_wires_count);
 | 
			
		||||
		log_debug("  removed %d unused temporary wires.\n", del_wires_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
 | 
			
		||||
| 
						 | 
				
			
			@ -399,7 +399,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if (verbose)
 | 
			
		||||
			log("  removing redundant init attribute on %s.\n", log_id(wire));
 | 
			
		||||
			log_debug("  removing redundant init attribute on %s.\n", log_id(wire));
 | 
			
		||||
 | 
			
		||||
		wire->attributes.erase("\\init");
 | 
			
		||||
		did_something = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -426,7 +426,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
 | 
			
		|||
		}
 | 
			
		||||
	for (auto cell : delcells) {
 | 
			
		||||
		if (verbose)
 | 
			
		||||
			log("  removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
 | 
			
		||||
			log_debug("  removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
 | 
			
		||||
					log_signal(cell->getPort("\\Y")), log_signal(cell->getPort("\\A")));
 | 
			
		||||
		module->remove(cell);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -551,6 +551,7 @@ struct CleanPass : public Pass {
 | 
			
		|||
			rmunused_module(module, purge_mode, false, false);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_suppressed();
 | 
			
		||||
		if (count_rm_cells > 0 || count_rm_wires > 0)
 | 
			
		||||
			log("Removed %d unused cells and %d unused wires.\n", count_rm_cells, count_rm_wires);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
 | 
			
		|||
		if (sig.size() == 0)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		log("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c));
 | 
			
		||||
		log_debug("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c));
 | 
			
		||||
		module->connect(RTLIL::SigSig(c, RTLIL::SigSpec(RTLIL::State::Sx, c.width)));
 | 
			
		||||
		did_something = true;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -78,7 +78,7 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
 | 
			
		|||
	RTLIL::SigSpec Y = cell->getPort(out_port);
 | 
			
		||||
	out_val.extend_u0(Y.size(), false);
 | 
			
		||||
 | 
			
		||||
	log("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
 | 
			
		||||
	log_debug("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
 | 
			
		||||
			cell->type.c_str(), cell->name.c_str(), info.c_str(),
 | 
			
		||||
			module->name.c_str(), log_signal(Y), log_signal(out_val));
 | 
			
		||||
	// log_cell(cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -134,7 +134,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
 | 
			
		|||
		if (GetSize(grouped_bits[i]) == GetSize(bits_y))
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
	log("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n",
 | 
			
		||||
	log_debug("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n",
 | 
			
		||||
			log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < GRP_N; i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +156,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->type.in("$and", "$or") && i == GRP_CONST_A) {
 | 
			
		||||
			log("  Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a));
 | 
			
		||||
			log_debug("  Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a));
 | 
			
		||||
			module->connect(new_y, new_b);
 | 
			
		||||
			module->connect(new_conn);
 | 
			
		||||
			continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -180,10 +180,10 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
 | 
			
		|||
 | 
			
		||||
		module->connect(new_conn);
 | 
			
		||||
 | 
			
		||||
		log("  New cell `%s': A=%s", log_id(c), log_signal(new_a));
 | 
			
		||||
		log_debug("  New cell `%s': A=%s", log_id(c), log_signal(new_a));
 | 
			
		||||
		if (b_name == "\\B")
 | 
			
		||||
			log(", B=%s", log_signal(new_b));
 | 
			
		||||
		log("\n");
 | 
			
		||||
			log_debug(", B=%s", log_signal(new_b));
 | 
			
		||||
		log_debug("\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cover_list("opt.opt_expr.fine.group", "$not", "$pos", "$and", "$or", "$xor", "$xnor", cell->type.str());
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +197,7 @@ void handle_polarity_inv(Cell *cell, IdString port, IdString param, const SigMap
 | 
			
		|||
{
 | 
			
		||||
	SigSpec sig = assign_map(cell->getPort(port));
 | 
			
		||||
	if (invert_map.count(sig)) {
 | 
			
		||||
		log("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
 | 
			
		||||
		log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
 | 
			
		||||
				log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module),
 | 
			
		||||
				log_signal(sig), log_signal(invert_map.at(sig)));
 | 
			
		||||
		cell->setPort(port, (invert_map.at(sig)));
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +226,7 @@ void handle_clkpol_celltype_swap(Cell *cell, string type1, string type2, IdStrin
 | 
			
		|||
	if (cell->type.in(type1, type2)) {
 | 
			
		||||
		SigSpec sig = assign_map(cell->getPort(port));
 | 
			
		||||
		if (invert_map.count(sig)) {
 | 
			
		||||
			log("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
 | 
			
		||||
			log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
 | 
			
		||||
					log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module),
 | 
			
		||||
					log_signal(sig), log_signal(invert_map.at(sig)));
 | 
			
		||||
			cell->setPort(port, (invert_map.at(sig)));
 | 
			
		||||
| 
						 | 
				
			
			@ -455,9 +455,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
		{
 | 
			
		||||
			if (cell->type == "$reduce_xnor") {
 | 
			
		||||
				cover("opt.opt_expr.reduce_xnor_not");
 | 
			
		||||
				log("Replacing %s cell `%s' in module `%s' with $not cell.\n",
 | 
			
		||||
				log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n",
 | 
			
		||||
						log_id(cell->type), log_id(cell->name), log_id(module));
 | 
			
		||||
				cell->type = "$not";
 | 
			
		||||
				did_something = true;
 | 
			
		||||
			} else {
 | 
			
		||||
				cover("opt.opt_expr.unary_buffer");
 | 
			
		||||
				replace_cell(assign_map, module, cell, "unary_buffer", "\\Y", cell->getPort("\\A"));
 | 
			
		||||
| 
						 | 
				
			
			@ -488,7 +489,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
				if (GetSize(new_sig_a) < GetSize(sig_a)) {
 | 
			
		||||
					cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str());
 | 
			
		||||
					log("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
 | 
			
		||||
					log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
 | 
			
		||||
							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a));
 | 
			
		||||
					cell->setPort("\\A", new_sig_a);
 | 
			
		||||
					cell->parameters.at("\\A_WIDTH") = GetSize(new_sig_a);
 | 
			
		||||
| 
						 | 
				
			
			@ -511,7 +512,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
				if (GetSize(new_sig_b) < GetSize(sig_b)) {
 | 
			
		||||
					cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str());
 | 
			
		||||
					log("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
 | 
			
		||||
					log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
 | 
			
		||||
							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b));
 | 
			
		||||
					cell->setPort("\\B", new_sig_b);
 | 
			
		||||
					cell->parameters.at("\\B_WIDTH") = GetSize(new_sig_b);
 | 
			
		||||
| 
						 | 
				
			
			@ -537,7 +538,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
				if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
 | 
			
		||||
					cover("opt.opt_expr.fine.$reduce_and");
 | 
			
		||||
					log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 | 
			
		||||
					log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 | 
			
		||||
							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
 | 
			
		||||
					cell->setPort("\\A", sig_a = new_a);
 | 
			
		||||
					cell->parameters.at("\\A_WIDTH") = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -563,7 +564,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
				if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
 | 
			
		||||
					cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
 | 
			
		||||
					log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 | 
			
		||||
					log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 | 
			
		||||
							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
 | 
			
		||||
					cell->setPort("\\A", sig_a = new_a);
 | 
			
		||||
					cell->parameters.at("\\A_WIDTH") = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -589,7 +590,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
				if (new_b != RTLIL::State::Sm && RTLIL::SigSpec(new_b) != sig_b) {
 | 
			
		||||
					cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str());
 | 
			
		||||
					log("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 | 
			
		||||
					log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
 | 
			
		||||
							cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b));
 | 
			
		||||
					cell->setPort("\\B", sig_b = new_b);
 | 
			
		||||
					cell->parameters.at("\\B_WIDTH") = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -640,7 +641,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
		if ((cell->type == "$_MUX_" || cell->type == "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) {
 | 
			
		||||
			cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
 | 
			
		||||
			log("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
			log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
			RTLIL::SigSpec tmp = cell->getPort("\\A");
 | 
			
		||||
			cell->setPort("\\A", cell->getPort("\\B"));
 | 
			
		||||
			cell->setPort("\\B", tmp);
 | 
			
		||||
| 
						 | 
				
			
			@ -750,7 +751,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
				ACTION_DO("\\Y", cell->getPort("\\A"));
 | 
			
		||||
			if (input == State::S0 && !a.is_fully_undef()) {
 | 
			
		||||
				cover("opt.opt_expr.action_" S__LINE__);
 | 
			
		||||
				log("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
 | 
			
		||||
				log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
 | 
			
		||||
					cell->type.c_str(), cell->name.c_str(), module->name.c_str());
 | 
			
		||||
				cell->setPort("\\A", SigSpec(State::Sx, GetSize(a)));
 | 
			
		||||
				did_something = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -822,7 +823,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
					ACTION_DO("\\Y", cell->getPort("\\A"));
 | 
			
		||||
				} else {
 | 
			
		||||
					cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str());
 | 
			
		||||
					log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
					log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
					cell->type = "$not";
 | 
			
		||||
					cell->parameters.erase("\\B_WIDTH");
 | 
			
		||||
					cell->parameters.erase("\\B_SIGNED");
 | 
			
		||||
| 
						 | 
				
			
			@ -837,7 +838,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
				(assign_map(cell->getPort("\\A")).is_fully_zero() || assign_map(cell->getPort("\\B")).is_fully_zero()))
 | 
			
		||||
		{
 | 
			
		||||
			cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
 | 
			
		||||
			log("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
 | 
			
		||||
			log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
 | 
			
		||||
					log_id(module), "$eq" ? "$logic_not" : "$reduce_bool");
 | 
			
		||||
			cell->type = cell->type == "$eq" ? "$logic_not" : "$reduce_bool";
 | 
			
		||||
			if (assign_map(cell->getPort("\\A")).is_fully_zero()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -876,7 +877,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
			cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
 | 
			
		||||
 | 
			
		||||
			log("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
 | 
			
		||||
			log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
 | 
			
		||||
					log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort("\\B"))), shift_bits, log_id(module), log_signal(sig_y));
 | 
			
		||||
 | 
			
		||||
			module->connect(cell->getPort("\\Y"), sig_y);
 | 
			
		||||
| 
						 | 
				
			
			@ -939,7 +940,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
				if (identity_wrt_b)
 | 
			
		||||
					cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
 | 
			
		||||
 | 
			
		||||
				log("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
 | 
			
		||||
				log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
 | 
			
		||||
					cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
 | 
			
		||||
 | 
			
		||||
				if (!identity_wrt_a) {
 | 
			
		||||
| 
						 | 
				
			
			@ -969,7 +970,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
		if (mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") &&
 | 
			
		||||
				cell->getPort("\\A") == RTLIL::SigSpec(1, 1) && cell->getPort("\\B") == RTLIL::SigSpec(0, 1)) {
 | 
			
		||||
			cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str());
 | 
			
		||||
			log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
			log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
			cell->setPort("\\A", cell->getPort("\\S"));
 | 
			
		||||
			cell->unsetPort("\\B");
 | 
			
		||||
			cell->unsetPort("\\S");
 | 
			
		||||
| 
						 | 
				
			
			@ -988,7 +989,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
		if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(0, 1)) {
 | 
			
		||||
			cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str());
 | 
			
		||||
			log("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
			log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
			cell->setPort("\\A", cell->getPort("\\S"));
 | 
			
		||||
			cell->unsetPort("\\S");
 | 
			
		||||
			if (cell->type == "$mux") {
 | 
			
		||||
| 
						 | 
				
			
			@ -1008,7 +1009,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
		if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\B") == RTLIL::SigSpec(1, 1)) {
 | 
			
		||||
			cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str());
 | 
			
		||||
			log("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
			log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
			cell->setPort("\\B", cell->getPort("\\S"));
 | 
			
		||||
			cell->unsetPort("\\S");
 | 
			
		||||
			if (cell->type == "$mux") {
 | 
			
		||||
| 
						 | 
				
			
			@ -1061,7 +1062,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
			}
 | 
			
		||||
			if (cell->getPort("\\S").size() != new_s.size()) {
 | 
			
		||||
				cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str());
 | 
			
		||||
				log("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
 | 
			
		||||
				log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
 | 
			
		||||
						GetSize(cell->getPort("\\S")) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
				cell->setPort("\\A", new_a);
 | 
			
		||||
				cell->setPort("\\B", new_b);
 | 
			
		||||
| 
						 | 
				
			
			@ -1179,7 +1180,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
				{
 | 
			
		||||
					cover("opt.opt_expr.mul_shift.zero");
 | 
			
		||||
 | 
			
		||||
					log("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
 | 
			
		||||
					log_debug("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
 | 
			
		||||
							cell->name.c_str(), module->name.c_str());
 | 
			
		||||
 | 
			
		||||
					module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
 | 
			
		||||
| 
						 | 
				
			
			@ -1197,7 +1198,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
						else
 | 
			
		||||
							cover("opt.opt_expr.mul_shift.unswapped");
 | 
			
		||||
 | 
			
		||||
						log("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
 | 
			
		||||
						log_debug("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
 | 
			
		||||
								a_val, cell->name.c_str(), module->name.c_str(), i);
 | 
			
		||||
 | 
			
		||||
						if (!swapped_ab) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1237,7 +1238,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
				{
 | 
			
		||||
					cover("opt.opt_expr.divmod_zero");
 | 
			
		||||
 | 
			
		||||
					log("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
 | 
			
		||||
					log_debug("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
 | 
			
		||||
							cell->name.c_str(), module->name.c_str());
 | 
			
		||||
 | 
			
		||||
					module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(State::Sx, sig_y.size())));
 | 
			
		||||
| 
						 | 
				
			
			@ -1254,7 +1255,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
						{
 | 
			
		||||
							cover("opt.opt_expr.div_shift");
 | 
			
		||||
 | 
			
		||||
							log("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
 | 
			
		||||
							log_debug("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
 | 
			
		||||
									b_val, cell->name.c_str(), module->name.c_str(), i);
 | 
			
		||||
 | 
			
		||||
							std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
 | 
			
		||||
| 
						 | 
				
			
			@ -1272,7 +1273,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
						{
 | 
			
		||||
							cover("opt.opt_expr.mod_mask");
 | 
			
		||||
 | 
			
		||||
							log("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
 | 
			
		||||
							log_debug("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
 | 
			
		||||
									b_val, cell->name.c_str(), module->name.c_str());
 | 
			
		||||
 | 
			
		||||
							std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(State::S1, i);
 | 
			
		||||
| 
						 | 
				
			
			@ -1342,7 +1343,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
				SigSpec y_sig = cell->getPort("\\Y");
 | 
			
		||||
				Const y_value(cell->type.in("$eq", "$eqx") ? 0 : 1, GetSize(y_sig));
 | 
			
		||||
 | 
			
		||||
				log("Replacing cell `%s' in module `%s' with constant driver %s.\n",
 | 
			
		||||
				log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n",
 | 
			
		||||
					log_id(cell), log_id(module), log_signal(y_value));
 | 
			
		||||
 | 
			
		||||
				module->connect(y_sig, y_value);
 | 
			
		||||
| 
						 | 
				
			
			@ -1354,7 +1355,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
			if (redundant_bits)
 | 
			
		||||
			{
 | 
			
		||||
				log("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
 | 
			
		||||
				log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
 | 
			
		||||
						redundant_bits, log_id(cell->type), log_id(cell), log_id(module));
 | 
			
		||||
 | 
			
		||||
				cell->setPort("\\A", sig_a);
 | 
			
		||||
| 
						 | 
				
			
			@ -1493,7 +1494,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 | 
			
		|||
 | 
			
		||||
				if (replace || remove)
 | 
			
		||||
				{
 | 
			
		||||
					log("Replacing %s cell `%s' (implementing %s) with %s.\n",
 | 
			
		||||
					log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n",
 | 
			
		||||
							log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str());
 | 
			
		||||
					if (replace)
 | 
			
		||||
						module->connect(cell->getPort("\\Y"), replace_sig);
 | 
			
		||||
| 
						 | 
				
			
			@ -1599,8 +1600,14 @@ struct OptExprPass : public Pass {
 | 
			
		|||
 | 
			
		||||
		for (auto module : design->selected_modules())
 | 
			
		||||
		{
 | 
			
		||||
			if (undriven)
 | 
			
		||||
			log("Optimizing module %s.\n", log_id(module));
 | 
			
		||||
 | 
			
		||||
			if (undriven) {
 | 
			
		||||
				did_something = false;
 | 
			
		||||
				replace_undriven(design, module);
 | 
			
		||||
				if (did_something)
 | 
			
		||||
					design->scratchpad_set_bool("opt.did_something", true);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			do {
 | 
			
		||||
				do {
 | 
			
		||||
| 
						 | 
				
			
			@ -1610,7 +1617,11 @@ struct OptExprPass : public Pass {
 | 
			
		|||
						design->scratchpad_set_bool("opt.did_something", true);
 | 
			
		||||
				} while (did_something);
 | 
			
		||||
				replace_const_cells(design, module, true, mux_undef, mux_bool, do_fine, keepdc, clkinv);
 | 
			
		||||
				if (did_something)
 | 
			
		||||
					design->scratchpad_set_bool("opt.did_something", true);
 | 
			
		||||
			} while (did_something);
 | 
			
		||||
 | 
			
		||||
			log_suppressed();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_pop();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -315,17 +315,17 @@ struct OptMergeWorker
 | 
			
		|||
			{
 | 
			
		||||
				if (sharemap.count(cell) > 0) {
 | 
			
		||||
					did_something = true;
 | 
			
		||||
					log("  Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str());
 | 
			
		||||
					log_debug("  Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str());
 | 
			
		||||
					for (auto &it : cell->connections()) {
 | 
			
		||||
						if (cell->output(it.first)) {
 | 
			
		||||
							RTLIL::SigSpec other_sig = sharemap[cell]->getPort(it.first);
 | 
			
		||||
							log("    Redirecting output %s: %s = %s\n", it.first.c_str(),
 | 
			
		||||
							log_debug("    Redirecting output %s: %s = %s\n", it.first.c_str(),
 | 
			
		||||
									log_signal(it.second), log_signal(other_sig));
 | 
			
		||||
							module->connect(RTLIL::SigSig(it.second, other_sig));
 | 
			
		||||
							assign_map.add(it.second, other_sig);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					log("    Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
 | 
			
		||||
					log_debug("    Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
 | 
			
		||||
#ifdef USE_CELL_HASH_CACHE
 | 
			
		||||
					cell_hash_cache.erase(cell);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -336,6 +336,8 @@ struct OptMergeWorker
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_suppressed();
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -181,14 +181,14 @@ struct OptMuxtreeWorker
 | 
			
		|||
 | 
			
		||||
		for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++)
 | 
			
		||||
			if (root_muxes.at(mux_idx)) {
 | 
			
		||||
				log("    Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : "");
 | 
			
		||||
				log_debug("    Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : "");
 | 
			
		||||
				root_mux_rerun.erase(mux_idx);
 | 
			
		||||
				eval_root_mux(mux_idx);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		while (!root_mux_rerun.empty()) {
 | 
			
		||||
			int mux_idx = *root_mux_rerun.begin();
 | 
			
		||||
			log("    Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell));
 | 
			
		||||
			log_debug("    Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell));
 | 
			
		||||
			log_assert(root_enable_muxes.at(mux_idx));
 | 
			
		||||
			root_mux_rerun.erase(mux_idx);
 | 
			
		||||
			eval_root_mux(mux_idx);
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +326,7 @@ struct OptMuxtreeWorker
 | 
			
		|||
				if (abort_count == 0) {
 | 
			
		||||
					root_mux_rerun.insert(m);
 | 
			
		||||
					root_enable_muxes.at(m) = true;
 | 
			
		||||
					log("      Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell));
 | 
			
		||||
					log_debug("      Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell));
 | 
			
		||||
				} else
 | 
			
		||||
					eval_mux(knowledge, m, false, do_enable_ports, abort_count - 1);
 | 
			
		||||
			} else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -369,6 +369,7 @@ 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"));
 | 
			
		||||
				for (int i = 0; i < GetSize(S); i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -419,6 +420,8 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
						choices[val] = i;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					bool full_pmux = GetSize(choices) == GetSize(S);
 | 
			
		||||
 | 
			
		||||
					// TBD: also find choices that are using signals that are subsets of the bits in "sig"
 | 
			
		||||
 | 
			
		||||
					if (!verbose)
 | 
			
		||||
| 
						 | 
				
			
			@ -634,7 +637,21 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
					log("    range density: %d%%\n", range_density);
 | 
			
		||||
					log("    absolute density: %d%%\n", absolute_density);
 | 
			
		||||
 | 
			
		||||
					bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (max_choice+1 == GetSize(choices));
 | 
			
		||||
					if (full_pmux) {
 | 
			
		||||
						int full_density = 100*GetSize(choices) / (1 << GetSize(sig));
 | 
			
		||||
						log("    full density: %d%%\n", full_density);
 | 
			
		||||
						if (full_density < min_density) {
 | 
			
		||||
							full_pmux = false;
 | 
			
		||||
						} else {
 | 
			
		||||
							min_choice = 0;
 | 
			
		||||
							max_choice = (1 << GetSize(sig))-1;
 | 
			
		||||
							log("    update to full case.\n");
 | 
			
		||||
							log("    new min choice: %d\n", min_choice);
 | 
			
		||||
							log("    new max choice: %d\n", max_choice);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (full_pmux || max_choice+1 == GetSize(choices));
 | 
			
		||||
					log("    full case: %s\n", full_case ? "true" : "false");
 | 
			
		||||
 | 
			
		||||
					// check density percentages
 | 
			
		||||
| 
						 | 
				
			
			@ -677,6 +694,10 @@ struct Pmux2ShiftxPass : public Pass {
 | 
			
		|||
 | 
			
		||||
					// create data signal
 | 
			
		||||
					SigSpec data(State::Sx, (max_choice+1)*extwidth);
 | 
			
		||||
					if (full_pmux) {
 | 
			
		||||
						for (int i = 0; i <= max_choice; i++)
 | 
			
		||||
							data.replace(i*extwidth, A);
 | 
			
		||||
					}
 | 
			
		||||
					for (auto &it : perm_choices) {
 | 
			
		||||
						int position = it.first.as_int()*extwidth;
 | 
			
		||||
						int data_index = it.second;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,8 @@
 | 
			
		|||
#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
 | 
			
		||||
#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
 | 
			
		||||
//#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
 | 
			
		||||
#define ABC_COMMAND_LUT "&st; &fraig; &scorr; &dc2; &retime; &dch -f; &if; &mfs"
 | 
			
		||||
//#define ABC_COMMAND_LUT "&st; &sweep; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps"
 | 
			
		||||
#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &ps -l -m"
 | 
			
		||||
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
 | 
			
		||||
#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -343,7 +344,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
	else
 | 
			
		||||
		abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str());
 | 
			
		||||
 | 
			
		||||
	abc_script += stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str());
 | 
			
		||||
	abc_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str());
 | 
			
		||||
 | 
			
		||||
	if (!script_file.empty()) {
 | 
			
		||||
		if (script_file[0] == '+') {
 | 
			
		||||
| 
						 | 
				
			
			@ -1401,6 +1402,9 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
 | 
			
		||||
		for (auto mod : design->selected_modules())
 | 
			
		||||
		{
 | 
			
		||||
			if (mod->attributes.count("\\abc_box_id"))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (mod->processes.size() > 0) {
 | 
			
		||||
				log("Skipping module %s as it contains processes.\n", log_id(mod));
 | 
			
		||||
				continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,6 +72,8 @@ struct TechmapWorker
 | 
			
		|||
	pool<IdString> flatten_done_list;
 | 
			
		||||
	pool<Cell*> flatten_keep_list;
 | 
			
		||||
 | 
			
		||||
	pool<string> log_msg_cache;
 | 
			
		||||
 | 
			
		||||
	struct TechmapWireData {
 | 
			
		||||
		RTLIL::Wire *wire;
 | 
			
		||||
		RTLIL::SigSpec value;
 | 
			
		||||
| 
						 | 
				
			
			@ -390,6 +392,7 @@ struct TechmapWorker
 | 
			
		|||
 | 
			
		||||
		bool log_continue = false;
 | 
			
		||||
		bool did_something = false;
 | 
			
		||||
		LogMakeDebugHdl mkdebug;
 | 
			
		||||
 | 
			
		||||
		SigMap sigmap(module);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -547,6 +550,7 @@ struct TechmapWorker
 | 
			
		|||
								if (extmapper_name == "wrap") {
 | 
			
		||||
									std::string cmd_string = tpl->attributes.at("\\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);
 | 
			
		||||
									log_continue = true;
 | 
			
		||||
								}
 | 
			
		||||
| 
						 | 
				
			
			@ -560,11 +564,21 @@ struct TechmapWorker
 | 
			
		|||
								goto use_wrapper_tpl;
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							log("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module));
 | 
			
		||||
							auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type));
 | 
			
		||||
							if (!log_msg_cache.count(msg)) {
 | 
			
		||||
								log_msg_cache.insert(msg);
 | 
			
		||||
								log("%s\n", msg.c_str());
 | 
			
		||||
							}
 | 
			
		||||
							log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module));
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
						{
 | 
			
		||||
							log("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str());
 | 
			
		||||
							auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name.c_str(), log_id(cell->type));
 | 
			
		||||
							if (!log_msg_cache.count(msg)) {
 | 
			
		||||
								log_msg_cache.insert(msg);
 | 
			
		||||
								log("%s\n", msg.c_str());
 | 
			
		||||
							}
 | 
			
		||||
							log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str());
 | 
			
		||||
 | 
			
		||||
							if (extmapper_name == "simplemap") {
 | 
			
		||||
								if (simplemap_mappers.count(cell->type) == 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -662,6 +676,7 @@ struct TechmapWorker
 | 
			
		|||
						tpl = techmap_cache[key];
 | 
			
		||||
					} else {
 | 
			
		||||
						if (parameters.size() != 0) {
 | 
			
		||||
							mkdebug.on();
 | 
			
		||||
							derived_name = tpl->derive(map, dict<RTLIL::IdString, RTLIL::Const>(parameters.begin(), parameters.end()));
 | 
			
		||||
							tpl = map->module(derived_name);
 | 
			
		||||
							log_continue = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -831,6 +846,7 @@ struct TechmapWorker
 | 
			
		|||
						if (log_continue) {
 | 
			
		||||
							log_header(design, "Continuing TECHMAP pass.\n");
 | 
			
		||||
							log_continue = false;
 | 
			
		||||
							mkdebug.off();
 | 
			
		||||
						}
 | 
			
		||||
						while (techmap_module(map, tpl, map, handled_cells, celltypeMap, true)) { }
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -842,6 +858,7 @@ struct TechmapWorker
 | 
			
		|||
				if (log_continue) {
 | 
			
		||||
					log_header(design, "Continuing TECHMAP pass.\n");
 | 
			
		||||
					log_continue = false;
 | 
			
		||||
					mkdebug.off();
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (extern_mode && !in_recursion)
 | 
			
		||||
| 
						 | 
				
			
			@ -861,13 +878,18 @@ struct TechmapWorker
 | 
			
		|||
						module_queue.insert(m);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					log("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name));
 | 
			
		||||
					log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name));
 | 
			
		||||
					cell->type = m_name;
 | 
			
		||||
					cell->parameters.clear();
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					log("%s %s.%s using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(tpl));
 | 
			
		||||
					auto msg = stringf("Using template %s for cells of type %s.", log_id(tpl), log_id(cell->type));
 | 
			
		||||
					if (!log_msg_cache.count(msg)) {
 | 
			
		||||
						log_msg_cache.insert(msg);
 | 
			
		||||
						log("%s\n", msg.c_str());
 | 
			
		||||
					}
 | 
			
		||||
					log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(tpl));
 | 
			
		||||
					techmap_module_worker(design, module, cell, tpl);
 | 
			
		||||
					cell = NULL;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -885,6 +907,7 @@ struct TechmapWorker
 | 
			
		|||
		if (log_continue) {
 | 
			
		||||
			log_header(design, "Continuing TECHMAP pass.\n");
 | 
			
		||||
			log_continue = false;
 | 
			
		||||
			mkdebug.off();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return did_something;
 | 
			
		||||
| 
						 | 
				
			
			@ -1085,7 +1108,7 @@ struct TechmapPass : public Pass {
 | 
			
		|||
		if (map_files.empty()) {
 | 
			
		||||
			std::istringstream f(stdcells_code);
 | 
			
		||||
			Frontend::frontend_call(map, &f, "<techmap.v>", verilog_frontend);
 | 
			
		||||
		} else
 | 
			
		||||
		} else {
 | 
			
		||||
			for (auto &fn : map_files)
 | 
			
		||||
				if (fn.substr(0, 1) == "%") {
 | 
			
		||||
					if (!saved_designs.count(fn.substr(1))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1104,6 +1127,9 @@ struct TechmapPass : public Pass {
 | 
			
		|||
						log_cmd_error("Can't open map file `%s'\n", fn.c_str());
 | 
			
		||||
					Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.substr(fn.size()-3) == ".il") ? "ilang" : verilog_frontend);
 | 
			
		||||
				}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Continuing TECHMAP pass.\n");
 | 
			
		||||
 | 
			
		||||
		std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
 | 
			
		||||
		for (auto &it : map->modules_) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1211,6 +1237,7 @@ struct FlattenPass : public Pass {
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_suppressed();
 | 
			
		||||
		log("No more expansions possible.\n");
 | 
			
		||||
 | 
			
		||||
		if (top_mod != NULL)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,12 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v))
 | 
			
		|||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
 | 
			
		||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.box))
 | 
			
		||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.lut))
 | 
			
		||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.box))
 | 
			
		||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.lut))
 | 
			
		||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.box))
 | 
			
		||||
$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.lut))
 | 
			
		||||
 | 
			
		||||
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh))
 | 
			
		||||
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										113
									
								
								techlibs/ice40/abc_hx.box
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								techlibs/ice40/abc_hx.box
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt
 | 
			
		||||
 | 
			
		||||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
			
		||||
 | 
			
		||||
# Inputs: C D
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFF 1 1 2 1
 | 
			
		||||
- -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFE 2 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFSR 3 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFR 4 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFSS 5 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFS 6 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFESR 7 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFER 8 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFESS 9 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFES 10 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFN 11 0 2 1
 | 
			
		||||
- -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNE 12 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNSR 13 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNR 14 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNSS 15 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNS 16 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNESR 17 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNER 18 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNESS 19 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNES 20 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: CI I0 I1
 | 
			
		||||
# Outputs: CO
 | 
			
		||||
SB_CARRY 21 1 3 1
 | 
			
		||||
126 259 231
 | 
			
		||||
 | 
			
		||||
# Inputs: I0 I1 I2 I3
 | 
			
		||||
# Outputs: O
 | 
			
		||||
SB_LUT4 22 0 4 1
 | 
			
		||||
449 400 379 316
 | 
			
		||||
							
								
								
									
										6
									
								
								techlibs/ice40/abc_hx.lut
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								techlibs/ice40/abc_hx.lut
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt
 | 
			
		||||
#       I3  I2  I1  I0
 | 
			
		||||
1   1   316
 | 
			
		||||
2   1   316 379
 | 
			
		||||
3   1   316 379 400
 | 
			
		||||
4   1   316 379 400 449
 | 
			
		||||
							
								
								
									
										113
									
								
								techlibs/ice40/abc_lp.box
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								techlibs/ice40/abc_lp.box
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt
 | 
			
		||||
 | 
			
		||||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
			
		||||
 | 
			
		||||
# Inputs: C D
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFF 1 1 2 1
 | 
			
		||||
- -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFE 2 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFSR 3 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFR 4 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFSS 5 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFS 6 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFESR 7 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFER 8 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFESS 9 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFES 10 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFN 11 0 2 1
 | 
			
		||||
- -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNE 12 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNSR 13 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNR 14 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNSS 15 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNS 16 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNESR 17 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNER 18 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNESS 19 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNES 20 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: CI I0 I1
 | 
			
		||||
# Outputs: CO
 | 
			
		||||
SB_CARRY 21 1 3 1
 | 
			
		||||
186 675 609
 | 
			
		||||
 | 
			
		||||
# Inputs: I0 I1 I2 I3
 | 
			
		||||
# Outputs: O
 | 
			
		||||
SB_LUT4 22 0 4 1
 | 
			
		||||
465 558 589 661
 | 
			
		||||
							
								
								
									
										6
									
								
								techlibs/ice40/abc_lp.lut
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								techlibs/ice40/abc_lp.lut
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt
 | 
			
		||||
#       I3  I2  I1  I0
 | 
			
		||||
1   1   465
 | 
			
		||||
2   1   465 558
 | 
			
		||||
3   1   465 558 589
 | 
			
		||||
4   1   465 558 589 661
 | 
			
		||||
							
								
								
									
										113
									
								
								techlibs/ice40/abc_u.box
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								techlibs/ice40/abc_u.box
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt
 | 
			
		||||
 | 
			
		||||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
			
		||||
 | 
			
		||||
# Inputs: C D
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFF 1 1 2 1
 | 
			
		||||
- -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFE 2 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFSR 3 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFR 4 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFSS 5 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFS 6 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFESR 7 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFER 8 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFESS 9 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFES 10 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFN 11 0 2 1
 | 
			
		||||
- -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNE 12 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNSR 13 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNR 14 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNSS 15 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNS 16 0 3 1
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNESR 17 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E R
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNER 18 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNESS 19 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C D E S
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
SB_DFFNES 20 0 4 1
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: CI I0 I1
 | 
			
		||||
# Outputs: CO
 | 
			
		||||
SB_CARRY 21 1 3 1
 | 
			
		||||
278 675 609
 | 
			
		||||
 | 
			
		||||
# Inputs: I0 I1 I2 I3
 | 
			
		||||
# Outputs: O
 | 
			
		||||
SB_LUT4 22 0 4 1
 | 
			
		||||
1285 1231 1205 874
 | 
			
		||||
							
								
								
									
										6
									
								
								techlibs/ice40/abc_u.lut
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								techlibs/ice40/abc_u.lut
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt
 | 
			
		||||
#       I3  I2  I1  I0
 | 
			
		||||
1   1   874
 | 
			
		||||
2   1   874 1205
 | 
			
		||||
3   1   874 1205 1231
 | 
			
		||||
4   1   874 1205 1231 1285
 | 
			
		||||
| 
						 | 
				
			
			@ -37,20 +37,24 @@ module \$lut (A, Y);
 | 
			
		|||
 | 
			
		||||
  generate
 | 
			
		||||
    if (WIDTH == 1) begin
 | 
			
		||||
      SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
 | 
			
		||||
        .I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0));
 | 
			
		||||
      localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}};
 | 
			
		||||
      SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
 | 
			
		||||
        .I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0]));
 | 
			
		||||
    end else
 | 
			
		||||
    if (WIDTH == 2) begin
 | 
			
		||||
      SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
 | 
			
		||||
        .I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0));
 | 
			
		||||
      localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[1]}}, {4{LUT[2]}}, {4{LUT[0]}}};
 | 
			
		||||
      SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
 | 
			
		||||
        .I0(1'b0), .I1(1'b0), .I2(A[1]), .I3(A[0]));
 | 
			
		||||
    end else
 | 
			
		||||
    if (WIDTH == 3) begin
 | 
			
		||||
      SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
 | 
			
		||||
        .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0));
 | 
			
		||||
      localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[3]}}, {2{LUT[5]}}, {2{LUT[1]}}, {2{LUT[6]}}, {2{LUT[2]}}, {2{LUT[4]}}, {2{LUT[0]}}};
 | 
			
		||||
      SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
 | 
			
		||||
        .I0(1'b0), .I1(A[2]), .I2(A[1]), .I3(A[0]));
 | 
			
		||||
    end else
 | 
			
		||||
    if (WIDTH == 4) begin
 | 
			
		||||
      localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]};
 | 
			
		||||
      SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
 | 
			
		||||
        .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
 | 
			
		||||
        .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0]));
 | 
			
		||||
    end else begin
 | 
			
		||||
      wire _TECHMAP_FAIL_ = 1;
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,6 +127,7 @@ endmodule
 | 
			
		|||
 | 
			
		||||
// SiliconBlue Logic Cells
 | 
			
		||||
 | 
			
		||||
(* abc_box_id = 22 *)
 | 
			
		||||
module SB_LUT4 (output O, input I0, I1, I2, I3);
 | 
			
		||||
	parameter [15:0] LUT_INIT = 0;
 | 
			
		||||
	wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
 | 
			
		||||
| 
						 | 
				
			
			@ -135,24 +136,32 @@ module SB_LUT4 (output O, input I0, I1, I2, I3);
 | 
			
		|||
	assign O = I0 ? s1[1] : s1[0];
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
(* abc_box_id = 21, lib_whitebox *)
 | 
			
		||||
module SB_CARRY (output CO, input I0, I1, CI);
 | 
			
		||||
	assign CO = (I0 && I1) || ((I0 || I1) && CI);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
// Positive Edge SiliconBlue FF Cells
 | 
			
		||||
 | 
			
		||||
module SB_DFF (output `SB_DFF_REG, input C, D);
 | 
			
		||||
(* abc_box_id = 1, abc_flop, lib_whitebox *)
 | 
			
		||||
module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
 | 
			
		||||
`ifndef ABC_MODEL
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		Q <= D;
 | 
			
		||||
`else
 | 
			
		||||
    always @* Q = D;
 | 
			
		||||
`endif
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFE (output `SB_DFF_REG, input C, E, D);
 | 
			
		||||
//(* abc_box_id = 2, abc_flop *)
 | 
			
		||||
module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (E)
 | 
			
		||||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
 | 
			
		||||
//(* abc_box_id = 3, abc_flop *)
 | 
			
		||||
module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +169,8 @@ module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFR (output `SB_DFF_REG, input C, R, D);
 | 
			
		||||
//(* abc_box_id = 4, abc_flop *)
 | 
			
		||||
module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C, posedge R)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -168,7 +178,8 @@ module SB_DFFR (output `SB_DFF_REG, input C, R, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
 | 
			
		||||
//(* abc_box_id = 5, abc_flop *)
 | 
			
		||||
module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +187,8 @@ module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFS (output `SB_DFF_REG, input C, S, D);
 | 
			
		||||
//(* abc_box_id = 6, abc_flop *)
 | 
			
		||||
module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C, posedge S)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -184,7 +196,8 @@ module SB_DFFS (output `SB_DFF_REG, input C, S, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		||||
//(* abc_box_id = 7, abc_flop *)
 | 
			
		||||
module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (E) begin
 | 
			
		||||
			if (R)
 | 
			
		||||
| 
						 | 
				
			
			@ -194,7 +207,8 @@ module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		|||
		end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		||||
//(* abc_box_id = 8, abc_flop *)
 | 
			
		||||
module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C, posedge R)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +216,8 @@ module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		||||
//(* abc_box_id = 9, abc_flop *)
 | 
			
		||||
module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (E) begin
 | 
			
		||||
			if (S)
 | 
			
		||||
| 
						 | 
				
			
			@ -212,7 +227,8 @@ module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		|||
		end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFES (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		||||
//(* abc_box_id = 10, abc_flop *)
 | 
			
		||||
module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(posedge C, posedge S)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -222,18 +238,21 @@ endmodule
 | 
			
		|||
 | 
			
		||||
// Negative Edge SiliconBlue FF Cells
 | 
			
		||||
 | 
			
		||||
module SB_DFFN (output `SB_DFF_REG, input C, D);
 | 
			
		||||
//(* abc_box_id = 11, abc_flop *)
 | 
			
		||||
module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNE (output `SB_DFF_REG, input C, E, D);
 | 
			
		||||
//(* abc_box_id = 12, abc_flop *)
 | 
			
		||||
module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (E)
 | 
			
		||||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
 | 
			
		||||
//(* abc_box_id = 13, abc_flop *)
 | 
			
		||||
module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -241,7 +260,8 @@ module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
 | 
			
		||||
//(* abc_box_id = 14, abc_flop *)
 | 
			
		||||
module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C, posedge R)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -249,7 +269,8 @@ module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
 | 
			
		||||
//(* abc_box_id = 15, abc_flop *)
 | 
			
		||||
module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -257,7 +278,8 @@ module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
 | 
			
		||||
//(* abc_box_id = 16, abc_flop *)
 | 
			
		||||
module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C, posedge S)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -265,7 +287,8 @@ module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		||||
//(* abc_box_id = 17, abc_flop *)
 | 
			
		||||
module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (E) begin
 | 
			
		||||
			if (R)
 | 
			
		||||
| 
						 | 
				
			
			@ -275,7 +298,8 @@ module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		|||
		end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		||||
//(* abc_box_id = 18, abc_flop *)
 | 
			
		||||
module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C, posedge R)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +307,8 @@ module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		||||
//(* abc_box_id = 19, abc_flop *)
 | 
			
		||||
module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (E) begin
 | 
			
		||||
			if (S)
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +318,8 @@ module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		|||
		end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		||||
//(* abc_box_id = 20, abc_flop *)
 | 
			
		||||
module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
 | 
			
		||||
	always @(negedge C, posedge S)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +330,7 @@ endmodule
 | 
			
		|||
// SiliconBlue RAM Cells
 | 
			
		||||
 | 
			
		||||
module SB_RAM40_4K (
 | 
			
		||||
	output [15:0] RDATA,
 | 
			
		||||
	(* abc_flop_q *) output [15:0] RDATA,
 | 
			
		||||
	input         RCLK, RCLKE, RE,
 | 
			
		||||
	input  [10:0] RADDR,
 | 
			
		||||
	input         WCLK, WCLKE, WE,
 | 
			
		||||
| 
						 | 
				
			
			@ -472,7 +498,7 @@ module SB_RAM40_4K (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_RAM40_4KNR (
 | 
			
		||||
	output [15:0] RDATA,
 | 
			
		||||
	(* abc_flop_q *) output [15:0] RDATA,
 | 
			
		||||
	input         RCLKN, RCLKE, RE,
 | 
			
		||||
	input  [10:0] RADDR,
 | 
			
		||||
	input         WCLK, WCLKE, WE,
 | 
			
		||||
| 
						 | 
				
			
			@ -537,7 +563,7 @@ module SB_RAM40_4KNR (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_RAM40_4KNW (
 | 
			
		||||
	output [15:0] RDATA,
 | 
			
		||||
	(* abc_flop_q *) output [15:0] RDATA,
 | 
			
		||||
	input         RCLK, RCLKE, RE,
 | 
			
		||||
	input  [10:0] RADDR,
 | 
			
		||||
	input         WCLKN, WCLKE, WE,
 | 
			
		||||
| 
						 | 
				
			
			@ -602,7 +628,7 @@ module SB_RAM40_4KNW (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_RAM40_4KNRNW (
 | 
			
		||||
	output [15:0] RDATA,
 | 
			
		||||
	(* abc_flop_q *) output [15:0] RDATA,
 | 
			
		||||
	input         RCLKN, RCLKE, RE,
 | 
			
		||||
	input  [10:0] RADDR,
 | 
			
		||||
	input         WCLKN, WCLKE, WE,
 | 
			
		||||
| 
						 | 
				
			
			@ -890,12 +916,13 @@ module SB_WARMBOOT (
 | 
			
		|||
);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
(* nomem2reg *)
 | 
			
		||||
module SB_SPRAM256KA (
 | 
			
		||||
	input [13:0] ADDRESS,
 | 
			
		||||
	input [15:0] DATAIN,
 | 
			
		||||
	input [3:0] MASKWREN,
 | 
			
		||||
	input WREN, CHIPSELECT, CLOCK, STANDBY, SLEEP, POWEROFF,
 | 
			
		||||
	output reg [15:0] DATAOUT
 | 
			
		||||
	(* abc_flop_q *) output reg [15:0] DATAOUT
 | 
			
		||||
);
 | 
			
		||||
`ifndef BLACKBOX
 | 
			
		||||
`ifndef EQUIV
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,10 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
		log("\n");
 | 
			
		||||
		log("This command runs synthesis for iCE40 FPGAs.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -device < hx | lp | u >\n");
 | 
			
		||||
		log("        optimise the synthesis netlist for the specified device.\n");
 | 
			
		||||
		log("        HX is the default target if no device argument specified.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -top <module>\n");
 | 
			
		||||
		log("        use the specified module as top module\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +106,7 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	string top_opt, blif_file, edif_file, json_file, abc;
 | 
			
		||||
	string top_opt, blif_file, edif_file, json_file, abc, device_opt;
 | 
			
		||||
	bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr;
 | 
			
		||||
	int min_ce_use;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +128,7 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
		abc2 = false;
 | 
			
		||||
		vpr = false;
 | 
			
		||||
		abc = "abc";
 | 
			
		||||
		device_opt = "hx";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
| 
						 | 
				
			
			@ -210,12 +215,18 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
				abc = "abc9";
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-device" && argidx+1 < args.size()) {
 | 
			
		||||
				device_opt = args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		if (!design->full_selection())
 | 
			
		||||
			log_cmd_error("This command only operates on fully selected designs!\n");
 | 
			
		||||
		if (device_opt != "hx" && device_opt != "lp" && device_opt !="u")
 | 
			
		||||
			log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str());
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing SYNTH_ICE40 pass.\n");
 | 
			
		||||
		log_push();
 | 
			
		||||
| 
						 | 
				
			
			@ -229,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
	{
 | 
			
		||||
		if (check_label("begin"))
 | 
			
		||||
		{
 | 
			
		||||
			run("read_verilog -lib +/ice40/cells_sim.v");
 | 
			
		||||
			run("read_verilog -lib -D ABC_MODEL +/ice40/cells_sim.v");
 | 
			
		||||
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
 | 
			
		||||
			run("proc");
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -282,7 +293,7 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
				run("techmap");
 | 
			
		||||
			else
 | 
			
		||||
				run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
 | 
			
		||||
			if (retime || help_mode)
 | 
			
		||||
			if ((retime || help_mode) && abc != "abc9")
 | 
			
		||||
				run(abc + " -dff", "(only if -retime)");
 | 
			
		||||
			run("ice40_opt");
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -316,7 +327,10 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
				run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
 | 
			
		||||
			}
 | 
			
		||||
			if (!noabc) {
 | 
			
		||||
				run(abc + " -dress -lut 4", "(skip if -noabc)");
 | 
			
		||||
				if (abc == "abc9")
 | 
			
		||||
					run(abc + stringf(" -dress -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
 | 
			
		||||
				else
 | 
			
		||||
					run(abc + " -lut 4", "(skip if -noabc)");
 | 
			
		||||
			}
 | 
			
		||||
			run("clean");
 | 
			
		||||
			if (relut || help_mode) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ struct SynthIntelPass : public ScriptPass {
 | 
			
		|||
    log("\n");
 | 
			
		||||
    log("    -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n");
 | 
			
		||||
    log("        generate the synthesis netlist for the specified family.\n");
 | 
			
		||||
    log("        MAX10 is the default target if not family argument specified.\n");
 | 
			
		||||
    log("        MAX10 is the default target if no family argument specified.\n");
 | 
			
		||||
    log("        For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
 | 
			
		||||
    log("        Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n");
 | 
			
		||||
    log("\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +146,7 @@ struct SynthIntelPass : public ScriptPass {
 | 
			
		|||
    if (!design->full_selection())
 | 
			
		||||
      log_cmd_error("This command only operates on fully selected designs!\n");
 | 
			
		||||
    if (family_opt != "max10" && family_opt !="a10gx" && family_opt != "cyclonev" && family_opt !="cycloneiv" && family_opt !="cycloneive" && family_opt != "cyclone10")
 | 
			
		||||
      log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str());
 | 
			
		||||
      log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str());
 | 
			
		||||
 | 
			
		||||
    log_header(design, "Executing SYNTH_INTEL pass.\n");
 | 
			
		||||
    log_push();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,4 +19,4 @@ fi
 | 
			
		|||
 | 
			
		||||
cp ../simple/*.v .
 | 
			
		||||
DOLLAR='?'
 | 
			
		||||
exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_'"
 | 
			
		||||
exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,8 +9,8 @@ opt
 | 
			
		|||
stat
 | 
			
		||||
# show -width
 | 
			
		||||
select -assert-count 1 t:$sub
 | 
			
		||||
select -assert-count 2 t:$mux
 | 
			
		||||
select -assert-count 2 t:$shift
 | 
			
		||||
select -assert-count 1 t:$mux
 | 
			
		||||
select -assert-count 1 t:$shift
 | 
			
		||||
select -assert-count 3 t:$shiftx
 | 
			
		||||
 | 
			
		||||
design -stash gate
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue