mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into xc7mux
This commit is contained in:
		
						commit
						4ef26d4755
					
				
					 22 changed files with 338 additions and 174 deletions
				
			
		
							
								
								
									
										11
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -666,6 +666,12 @@ else | |||
| SEEDOPT="" | ||||
| endif | ||||
| 
 | ||||
| ifneq ($(ABCEXTERNAL),) | ||||
| ABCOPT="-A $(ABCEXTERNAL)" | ||||
| else | ||||
| ABCOPT="" | ||||
| endif | ||||
| 
 | ||||
| test: $(TARGETS) $(EXTRA_TARGETS) | ||||
| 	+cd tests/simple && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/hana && bash run-test.sh $(SEEDOPT) | ||||
|  | @ -674,13 +680,14 @@ test: $(TARGETS) $(EXTRA_TARGETS) | |||
| 	+cd tests/share && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/fsm && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/techmap && bash run-test.sh | ||||
| 	+cd tests/memories && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT) | ||||
| 	+cd tests/bram && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/various && bash run-test.sh | ||||
| 	+cd tests/sat && bash run-test.sh | ||||
| 	+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/opt && bash run-test.sh | ||||
| 	+cd tests/aiger && bash run-test.sh | ||||
| 	+cd tests/aiger && bash run-test.sh $(ABCOPT) | ||||
| 	+cd tests/arch && bash run-test.sh | ||||
| 	+cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT) | ||||
| 	@echo "" | ||||
| 	@echo "  Passed \"make test\"." | ||||
|  |  | |||
|  | @ -70,35 +70,35 @@ struct AigerWriter | |||
| 
 | ||||
| 	int bit2aig(SigBit bit) | ||||
| 	{ | ||||
| 		if (aig_map.count(bit) == 0) | ||||
| 		{ | ||||
| 			aig_map[bit] = -1; | ||||
| 		auto it = aig_map.find(bit); | ||||
| 		if (it != aig_map.end()) { | ||||
| 			log_assert(it->second >= 0); | ||||
| 			return it->second; | ||||
| 		} | ||||
| 
 | ||||
| 			if (initstate_bits.count(bit)) { | ||||
| 				log_assert(initstate_ff > 0); | ||||
| 				aig_map[bit] = initstate_ff; | ||||
| 			} else | ||||
| 		// NB: Cannot use iterator returned from aig_map.insert()
 | ||||
| 		//     since this function is called recursively
 | ||||
| 
 | ||||
| 		int a = -1; | ||||
| 		if (not_map.count(bit)) { | ||||
| 				int a = bit2aig(not_map.at(bit)) ^ 1; | ||||
| 				aig_map[bit] = a; | ||||
| 			a = bit2aig(not_map.at(bit)) ^ 1; | ||||
| 		} else | ||||
| 		if (and_map.count(bit)) { | ||||
| 			auto args = and_map.at(bit); | ||||
| 			int a0 = bit2aig(args.first); | ||||
| 			int a1 = bit2aig(args.second); | ||||
| 				aig_map[bit] = mkgate(a0, a1); | ||||
| 			a = mkgate(a0, a1); | ||||
| 		} else | ||||
| 		if (alias_map.count(bit)) { | ||||
| 				int a = bit2aig(alias_map.at(bit)); | ||||
| 				aig_map[bit] = a; | ||||
| 			a = bit2aig(alias_map.at(bit)); | ||||
| 		} | ||||
| 
 | ||||
| 		if (bit == State::Sx || bit == State::Sz) | ||||
| 			log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		log_assert(aig_map.at(bit) >= 0); | ||||
| 		return aig_map.at(bit); | ||||
| 		log_assert(a >= 0); | ||||
| 		aig_map[bit] = a; | ||||
| 		return a; | ||||
| 	} | ||||
| 
 | ||||
| 	AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module) | ||||
|  |  | |||
|  | @ -25,6 +25,21 @@ | |||
| #elif defined(__APPLE__) | ||||
| #include <libkern/OSByteOrder.h> | ||||
| #define __builtin_bswap32 OSSwapInt32 | ||||
| #elif !defined(__GNUC__) | ||||
| #include <cstdint> | ||||
| inline uint32_t __builtin_bswap32(uint32_t x) | ||||
| { | ||||
| 	// https://stackoverflow.com/a/27796212
 | ||||
| 	register uint32_t value = number_to_be_reversed; | ||||
| 	uint8_t lolo = (value >> 0) & 0xFF; | ||||
| 	uint8_t lohi = (value >> 8) & 0xFF; | ||||
| 	uint8_t hilo = (value >> 16) & 0xFF; | ||||
| 	uint8_t hihi = (value >> 24) & 0xFF; | ||||
| 	return (hihi << 24) | ||||
| 		| (hilo << 16) | ||||
| 		| (lohi << 8) | ||||
| 		| (lolo << 0); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #include "kernel/yosys.h" | ||||
|  | @ -284,8 +299,6 @@ struct XAigerWriter | |||
| 					for (auto user_cell : it.second) | ||||
| 						toposort.edge(driver_cell, user_cell); | ||||
| 
 | ||||
| 			pool<RTLIL::Module*> abc_carry_modules; | ||||
| 
 | ||||
| #if 0 | ||||
| 			toposort.analyze_loops = true; | ||||
| #endif | ||||
|  | @ -303,55 +316,55 @@ struct XAigerWriter | |||
| #endif | ||||
| 			log_assert(no_loops); | ||||
| 
 | ||||
| 			pool<IdString> seen_boxes; | ||||
| 			for (auto cell_name : toposort.sorted) { | ||||
| 				RTLIL::Cell *cell = module->cell(cell_name); | ||||
| 				log_assert(cell); | ||||
| 
 | ||||
| 				RTLIL::Module* box_module = module->design->module(cell->type); | ||||
| 				if (!box_module || !box_module->attributes.count("\\abc_box_id")) | ||||
| 					continue; | ||||
| 
 | ||||
| 				if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { | ||||
| 				if (seen_boxes.insert(cell->type).second) { | ||||
| 					auto it = box_module->attributes.find("\\abc_carry"); | ||||
| 					if (it != box_module->attributes.end()) { | ||||
| 						RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; | ||||
| 						auto carry_in_out = it->second.decode_string(); | ||||
| 						auto pos = carry_in_out.find(','); | ||||
| 						if (pos == std::string::npos) | ||||
| 							log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); | ||||
| 						auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); | ||||
| 						carry_in = box_module->wire(carry_in_name); | ||||
| 						if (!carry_in || !carry_in->port_input) | ||||
| 							log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); | ||||
| 
 | ||||
| 						auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); | ||||
| 						carry_out = box_module->wire(carry_out_name); | ||||
| 						if (!carry_out || !carry_out->port_output) | ||||
| 							log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); | ||||
| 
 | ||||
| 						auto &ports = box_module->ports; | ||||
| 					for (auto it = ports.begin(); it != ports.end(); ) { | ||||
| 						RTLIL::Wire* w = box_module->wire(*it); | ||||
| 						for (auto jt = ports.begin(); jt != ports.end(); ) { | ||||
| 							RTLIL::Wire* w = box_module->wire(*jt); | ||||
| 							log_assert(w); | ||||
| 						if (w->port_input && w->attributes.count("\\abc_carry_in")) { | ||||
| 							if (carry_in) | ||||
| 								log_error("More than one port with attribute 'abc_carry_in' found in module '%s'\n", log_id(box_module)); | ||||
| 							carry_in = w; | ||||
| 							it = ports.erase(it); | ||||
| 							if (w == carry_in || w == carry_out) { | ||||
| 								jt = ports.erase(jt); | ||||
| 								continue; | ||||
| 							} | ||||
| 						if (w->port_output && w->attributes.count("\\abc_carry_out")) { | ||||
| 							if (carry_out) | ||||
| 								log_error("More than one port with attribute 'abc_carry_out' found in module '%s'\n", log_id(box_module)); | ||||
| 							carry_out = w; | ||||
| 							it = ports.erase(it); | ||||
| 							continue; | ||||
| 						} | ||||
| 						++it; | ||||
| 					} | ||||
| 
 | ||||
| 					if (!carry_in) | ||||
| 						log_error("Port with attribute 'abc_carry_in' not found in module '%s'\n", log_id(box_module)); | ||||
| 					if (!carry_out) | ||||
| 						log_error("Port with attribute 'abc_carry_out' not found in module '%s'\n", log_id(box_module)); | ||||
| 
 | ||||
| 					for (const auto port_name : ports) { | ||||
| 						RTLIL::Wire* w = box_module->wire(port_name); | ||||
| 						log_assert(w); | ||||
| 							if (w->port_id > carry_in->port_id) | ||||
| 								--w->port_id; | ||||
| 							if (w->port_id > carry_out->port_id) | ||||
| 								--w->port_id; | ||||
| 							log_assert(w->port_input || w->port_output); | ||||
| 							log_assert(ports[w->port_id-1] == w->name); | ||||
| 							++jt; | ||||
| 						} | ||||
| 						ports.push_back(carry_in->name); | ||||
| 						carry_in->port_id = ports.size(); | ||||
| 						ports.push_back(carry_out->name); | ||||
| 						carry_out->port_id = ports.size(); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				// Fully pad all unused input connections of this box cell with S0
 | ||||
| 				// Fully pad all undriven output connections of this box cell with anonymous wires
 | ||||
|  | @ -438,14 +451,18 @@ struct XAigerWriter | |||
| 					new_wire = module->addWire(wire_name, GetSize(wire)); | ||||
| 				SigBit new_bit(new_wire, bit.offset); | ||||
| 				module->connect(new_bit, bit); | ||||
| 				if (not_map.count(bit)) | ||||
| 					not_map[new_bit] = not_map.at(bit); | ||||
| 				else if (and_map.count(bit)) { | ||||
| 				    //and_map[new_bit] = and_map.at(bit); // Breaks gcc-4.8
 | ||||
| 				    and_map.insert(std::make_pair(new_bit, and_map.at(bit))); | ||||
| 				if (not_map.count(bit)) { | ||||
| 					auto a = not_map.at(bit); | ||||
| 					not_map[new_bit] = a; | ||||
| 				} | ||||
| 				else if (and_map.count(bit)) { | ||||
| 					auto a = and_map.at(bit); | ||||
| 					and_map[new_bit] = a; | ||||
| 				} | ||||
| 				else if (alias_map.count(bit)) { | ||||
| 					auto a = alias_map.at(bit); | ||||
| 					alias_map[new_bit] = a; | ||||
| 				} | ||||
| 				else if (alias_map.count(bit)) | ||||
| 					alias_map[new_bit] = alias_map.at(bit); | ||||
| 				else | ||||
| 					alias_map[new_bit] = bit; | ||||
| 				output_bits.erase(bit); | ||||
|  |  | |||
|  | @ -732,44 +732,50 @@ void AigerReader::parse_aiger_binary() | |||
| 
 | ||||
| void AigerReader::post_process() | ||||
| { | ||||
| 	pool<RTLIL::Module*> abc_carry_modules; | ||||
| 	pool<IdString> seen_boxes; | ||||
| 	unsigned ci_count = 0, co_count = 0; | ||||
| 	for (auto cell : boxes) { | ||||
| 		RTLIL::Module* box_module = design->module(cell->type); | ||||
| 		log_assert(box_module); | ||||
| 
 | ||||
| 		if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) { | ||||
| 		if (seen_boxes.insert(cell->type).second) { | ||||
| 			auto it = box_module->attributes.find("\\abc_carry"); | ||||
| 			if (it != box_module->attributes.end()) { | ||||
| 				RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; | ||||
| 			RTLIL::Wire* last_in = nullptr, *last_out = nullptr; | ||||
| 			for (const auto &port_name : box_module->ports) { | ||||
| 				RTLIL::Wire* w = box_module->wire(port_name); | ||||
| 				log_assert(w); | ||||
| 				if (w->port_input) { | ||||
| 					if (w->attributes.count("\\abc_carry_in")) { | ||||
| 						log_assert(!carry_in); | ||||
| 						carry_in = w; | ||||
| 					} | ||||
| 					log_assert(!last_in || last_in->port_id < w->port_id); | ||||
| 					last_in = w; | ||||
| 				} | ||||
| 				if (w->port_output) { | ||||
| 					if (w->attributes.count("\\abc_carry_out")) { | ||||
| 						log_assert(!carry_out); | ||||
| 						carry_out = w; | ||||
| 					} | ||||
| 					log_assert(!last_out || last_out->port_id < w->port_id); | ||||
| 					last_out = w; | ||||
| 				} | ||||
| 			} | ||||
| 				auto carry_in_out = it->second.decode_string(); | ||||
| 				auto pos = carry_in_out.find(','); | ||||
| 				if (pos == std::string::npos) | ||||
| 					log_error("'abc_carry' attribute on module '%s' does not contain ','.\n", log_id(cell->type)); | ||||
| 				auto carry_in_name = RTLIL::escape_id(carry_in_out.substr(0, pos)); | ||||
| 				carry_in = box_module->wire(carry_in_name); | ||||
| 				if (!carry_in || !carry_in->port_input) | ||||
| 					log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an input port.\n", log_id(cell->type), carry_in_name.c_str()); | ||||
| 
 | ||||
| 			if (carry_in != last_in) { | ||||
| 				std::swap(box_module->ports[carry_in->port_id], box_module->ports[last_in->port_id]); | ||||
| 				std::swap(carry_in->port_id, last_in->port_id); | ||||
| 				auto carry_out_name = RTLIL::escape_id(carry_in_out.substr(pos+1)); | ||||
| 				carry_out = box_module->wire(carry_out_name); | ||||
| 				if (!carry_out || !carry_out->port_output) | ||||
| 					log_error("'abc_carry' on module '%s' contains '%s' which does not exist or is not an output port.\n", log_id(cell->type), carry_out_name.c_str()); | ||||
| 
 | ||||
| 				auto &ports = box_module->ports; | ||||
| 				for (auto jt = ports.begin(); jt != ports.end(); ) { | ||||
| 					RTLIL::Wire* w = box_module->wire(*jt); | ||||
| 					log_assert(w); | ||||
| 					if (w == carry_in || w == carry_out) { | ||||
| 						jt = ports.erase(jt); | ||||
| 						continue; | ||||
| 					} | ||||
| 			if (carry_out != last_out) { | ||||
| 				log_assert(last_out); | ||||
| 				std::swap(box_module->ports[carry_out->port_id], box_module->ports[last_out->port_id]); | ||||
| 				std::swap(carry_out->port_id, last_out->port_id); | ||||
| 					if (w->port_id > carry_in->port_id) | ||||
| 						--w->port_id; | ||||
| 					if (w->port_id > carry_out->port_id) | ||||
| 						--w->port_id; | ||||
| 					log_assert(w->port_input || w->port_output); | ||||
| 					log_assert(ports[w->port_id-1] == w->name); | ||||
| 					++jt; | ||||
| 				} | ||||
| 				ports.push_back(carry_in->name); | ||||
| 				carry_in->port_id = ports.size(); | ||||
| 				ports.push_back(carry_out->name); | ||||
| 				carry_out->port_id = ports.size(); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -246,24 +246,24 @@ struct CellTypes | |||
| 		cell_types.clear(); | ||||
| 	} | ||||
| 
 | ||||
| 	bool cell_known(RTLIL::IdString type) | ||||
| 	bool cell_known(RTLIL::IdString type) const | ||||
| 	{ | ||||
| 		return cell_types.count(type) != 0; | ||||
| 	} | ||||
| 
 | ||||
| 	bool cell_output(RTLIL::IdString type, RTLIL::IdString port) | ||||
| 	bool cell_output(RTLIL::IdString type, RTLIL::IdString port) const | ||||
| 	{ | ||||
| 		auto it = cell_types.find(type); | ||||
| 		return it != cell_types.end() && it->second.outputs.count(port) != 0; | ||||
| 	} | ||||
| 
 | ||||
| 	bool cell_input(RTLIL::IdString type, RTLIL::IdString port) | ||||
| 	bool cell_input(RTLIL::IdString type, RTLIL::IdString port) const | ||||
| 	{ | ||||
| 		auto it = cell_types.find(type); | ||||
| 		return it != cell_types.end() && it->second.inputs.count(port) != 0; | ||||
| 	} | ||||
| 
 | ||||
| 	bool cell_evaluable(RTLIL::IdString type) | ||||
| 	bool cell_evaluable(RTLIL::IdString type) const | ||||
| 	{ | ||||
| 		auto it = cell_types.find(type); | ||||
| 		return it != cell_types.end() && it->second.is_evaluable; | ||||
|  | @ -482,4 +482,3 @@ extern CellTypes yosys_celltypes; | |||
| YOSYS_NAMESPACE_END | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -1595,10 +1595,9 @@ void RTLIL::Module::remove(RTLIL::Cell *cell) | |||
| 	while (!cell->connections_.empty()) | ||||
| 		cell->unsetPort(cell->connections_.begin()->first); | ||||
| 
 | ||||
| 	auto it = cells_.find(cell->name); | ||||
| 	log_assert(it != cells_.end()); | ||||
| 	log_assert(cells_.count(cell->name) != 0); | ||||
| 	log_assert(refcount_cells_ == 0); | ||||
| 	cells_.erase(it); | ||||
| 	cells_.erase(cell->name); | ||||
| 	delete cell; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ struct OptPass : public Pass { | |||
| 		log("        opt_muxtree\n"); | ||||
| 		log("        opt_reduce [-fine] [-full]\n"); | ||||
| 		log("        opt_merge [-share_all]\n"); | ||||
| 		log("        opt_rmdff [-keepdc]\n"); | ||||
| 		log("        opt_rmdff [-keepdc] [-sat]\n"); | ||||
| 		log("        opt_clean [-purge]\n"); | ||||
| 		log("        opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); | ||||
| 		log("    while <changed design>\n"); | ||||
|  | @ -54,7 +54,7 @@ struct OptPass : public Pass { | |||
| 		log("    do\n"); | ||||
| 		log("        opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); | ||||
| 		log("        opt_merge [-share_all]\n"); | ||||
| 		log("        opt_rmdff [-keepdc]\n"); | ||||
| 		log("        opt_rmdff [-keepdc] [-sat]\n"); | ||||
| 		log("        opt_clean [-purge]\n"); | ||||
| 		log("    while <changed design in opt_rmdff>\n"); | ||||
| 		log("\n"); | ||||
|  | @ -112,6 +112,10 @@ struct OptPass : public Pass { | |||
| 				opt_rmdff_args += " -keepdc"; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-sat") { | ||||
| 				opt_rmdff_args += " -sat"; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-share_all") { | ||||
| 				opt_merge_args += " -share_all"; | ||||
| 				continue; | ||||
|  |  | |||
|  | @ -17,19 +17,24 @@ | |||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "kernel/register.h" | ||||
| #include "kernel/sigtools.h" | ||||
| #include "kernel/log.h" | ||||
| #include <stdlib.h> | ||||
| #include "kernel/register.h" | ||||
| #include "kernel/rtlil.h" | ||||
| #include "kernel/satgen.h" | ||||
| #include "kernel/sigtools.h" | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
| 
 | ||||
| SigMap assign_map, dff_init_map; | ||||
| SigSet<RTLIL::Cell*> mux_drivers; | ||||
| dict<SigBit, RTLIL::Cell*> bit2driver; | ||||
| dict<SigBit, pool<SigBit>> init_attributes; | ||||
| 
 | ||||
| bool keepdc; | ||||
| bool sat; | ||||
| 
 | ||||
| void remove_init_attr(SigSpec sig) | ||||
| { | ||||
|  | @ -452,12 +457,84 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) | |||
| 		dff->unsetPort("\\E"); | ||||
| 	} | ||||
| 
 | ||||
| 	if (sat && has_init && (!sig_r.size() || val_init == val_rv)) | ||||
| 	{ | ||||
| 		bool removed_sigbits = false; | ||||
| 
 | ||||
| 		ezSatPtr ez; | ||||
| 		SatGen satgen(ez.get(), &assign_map); | ||||
| 		pool<Cell*> sat_cells; | ||||
| 
 | ||||
| 		std::function<void(Cell*)> sat_import_cell = [&](Cell *c) { | ||||
| 			if (!sat_cells.insert(c).second) | ||||
| 				return; | ||||
| 			if (!satgen.importCell(c)) | ||||
| 				return; | ||||
| 			for (auto &conn : c->connections()) { | ||||
| 				if (!c->input(conn.first)) | ||||
| 					continue; | ||||
| 				for (auto bit : assign_map(conn.second)) | ||||
| 					if (bit2driver.count(bit)) | ||||
| 						sat_import_cell(bit2driver.at(bit)); | ||||
| 			} | ||||
| 		}; | ||||
| 
 | ||||
| 		// For each register bit, try to prove that it cannot change from the initial value. If so, remove it
 | ||||
| 		for (int position = 0; position < GetSize(sig_d); position += 1) { | ||||
| 			RTLIL::SigBit q_sigbit = sig_q[position]; | ||||
| 			RTLIL::SigBit d_sigbit = sig_d[position]; | ||||
| 
 | ||||
| 			if ((!q_sigbit.wire) || (!d_sigbit.wire)) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (!bit2driver.count(d_sigbit)) | ||||
| 				continue; | ||||
| 
 | ||||
| 			sat_import_cell(bit2driver.at(d_sigbit)); | ||||
| 
 | ||||
| 			RTLIL::State sigbit_init_val = val_init[position]; | ||||
| 			if (sigbit_init_val != State::S0 && sigbit_init_val != State::S1) | ||||
| 				continue; | ||||
| 
 | ||||
| 			int init_sat_pi = satgen.importSigSpec(sigbit_init_val).front(); | ||||
| 			int q_sat_pi = satgen.importSigBit(q_sigbit); | ||||
| 			int d_sat_pi = satgen.importSigBit(d_sigbit); | ||||
| 
 | ||||
| 			// Try to find out whether the register bit can change under some circumstances
 | ||||
| 			bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); | ||||
| 
 | ||||
| 			// If the register bit cannot change, we can replace it with a constant
 | ||||
| 			if (!counter_example_found) | ||||
| 			{ | ||||
| 				log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0, | ||||
| 						position, log_id(dff), log_id(dff->type), log_id(mod)); | ||||
| 
 | ||||
| 				SigSpec tmp = dff->getPort("\\D"); | ||||
| 				tmp[position] = sigbit_init_val; | ||||
| 				dff->setPort("\\D", tmp); | ||||
| 
 | ||||
| 				removed_sigbits = true; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (removed_sigbits) { | ||||
| 			handle_dff(mod, dff); | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	return false; | ||||
| 
 | ||||
| delete_dff: | ||||
| 	log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); | ||||
| 	remove_init_attr(dff->getPort("\\Q")); | ||||
| 	mod->remove(dff); | ||||
| 
 | ||||
| 	for (auto &entry : bit2driver) | ||||
| 		if (entry.second == dff) | ||||
| 			bit2driver.erase(entry.first); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -467,11 +544,15 @@ struct OptRmdffPass : public Pass { | |||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    opt_rmdff [-keepdc] [selection]\n"); | ||||
| 		log("    opt_rmdff [-keepdc] [-sat] [selection]\n"); | ||||
| 		log("\n"); | ||||
| 		log("This pass identifies flip-flops with constant inputs and replaces them with\n"); | ||||
| 		log("a constant driver.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -sat\n"); | ||||
| 		log("        additionally invoke SAT solver to detect and remove flip-flops (with \n"); | ||||
| 		log("        non-constant inputs) that can also be replaced with a constant driver\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||
| 	{ | ||||
|  | @ -479,6 +560,7 @@ struct OptRmdffPass : public Pass { | |||
| 		log_header(design, "Executing OPT_RMDFF pass (remove dff with constant values).\n"); | ||||
| 
 | ||||
| 		keepdc = false; | ||||
| 		sat = false; | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||
|  | @ -486,18 +568,22 @@ struct OptRmdffPass : public Pass { | |||
| 				keepdc = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-sat") { | ||||
| 				sat = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		for (auto module : design->selected_modules()) | ||||
| 		{ | ||||
| 		for (auto module : design->selected_modules()) { | ||||
| 			pool<SigBit> driven_bits; | ||||
| 			dict<SigBit, State> init_bits; | ||||
| 
 | ||||
| 			assign_map.set(module); | ||||
| 			dff_init_map.set(module); | ||||
| 			mux_drivers.clear(); | ||||
| 			bit2driver.clear(); | ||||
| 			init_attributes.clear(); | ||||
| 
 | ||||
| 			for (auto wire : module->wires()) | ||||
|  | @ -522,17 +608,21 @@ struct OptRmdffPass : public Pass { | |||
| 						driven_bits.insert(bit); | ||||
| 				} | ||||
| 			} | ||||
| 			mux_drivers.clear(); | ||||
| 
 | ||||
| 			std::vector<RTLIL::IdString> dff_list; | ||||
| 			std::vector<RTLIL::IdString> dffsr_list; | ||||
| 			std::vector<RTLIL::IdString> dlatch_list; | ||||
| 			for (auto cell : module->cells()) | ||||
| 			{ | ||||
| 				for (auto &conn : cell->connections()) | ||||
| 					if (cell->output(conn.first) || !cell->known()) | ||||
| 						for (auto bit : assign_map(conn.second)) | ||||
| 				for (auto &conn : cell->connections()) { | ||||
| 					bool is_output = cell->output(conn.first); | ||||
| 					if (is_output || !cell->known()) | ||||
| 						for (auto bit : assign_map(conn.second)) { | ||||
| 							if (is_output) | ||||
| 								bit2driver[bit] = cell; | ||||
| 							driven_bits.insert(bit); | ||||
| 						} | ||||
| 				} | ||||
| 
 | ||||
| 				if (cell->type == "$mux" || cell->type == "$pmux") { | ||||
| 					if (cell->getPort("\\A").size() == cell->getPort("\\B").size()) | ||||
|  | @ -604,6 +694,7 @@ struct OptRmdffPass : public Pass { | |||
| 
 | ||||
| 		assign_map.clear(); | ||||
| 		mux_drivers.clear(); | ||||
| 		bit2driver.clear(); | ||||
| 		init_attributes.clear(); | ||||
| 
 | ||||
| 		if (total_count || total_initdrv) | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ | |||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #define ABC_FAST_COMMAND_LUT "&st; &retime; &if {W}" | ||||
| #define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}" | ||||
| 
 | ||||
| #include "kernel/register.h" | ||||
| #include "kernel/sigtools.h" | ||||
|  | @ -80,7 +80,7 @@ void handle_loops(RTLIL::Design *design) | |||
| { | ||||
| 	Pass::call(design, "scc -set_attr abc_scc_id {}"); | ||||
| 
 | ||||
|         dict<IdString, vector<IdString>> module_break; | ||||
|         dict<IdString, vector<IdString>> abc_scc_break; | ||||
| 
 | ||||
| 	// For every unique SCC found, (arbitrarily) find the first
 | ||||
| 	// cell in the component, and select (and mark) all its output
 | ||||
|  | @ -116,12 +116,11 @@ void handle_loops(RTLIL::Design *design) | |||
| 			cell->attributes.erase(it); | ||||
| 		} | ||||
| 
 | ||||
| 		auto jt = module_break.find(cell->type); | ||||
| 		if (jt == module_break.end()) { | ||||
| 		auto jt = abc_scc_break.find(cell->type); | ||||
| 		if (jt == abc_scc_break.end()) { | ||||
| 			std::vector<IdString> ports; | ||||
| 			if (!yosys_celltypes.cell_known(cell->type)) { | ||||
| 			RTLIL::Module* box_module = design->module(cell->type); | ||||
| 				log_assert(box_module); | ||||
| 			if (box_module) { | ||||
| 				auto ports_csv = box_module->attributes.at("\\abc_scc_break", RTLIL::Const::from_string("")).decode_string(); | ||||
| 				for (const auto &port_name : split_tokens(ports_csv, ",")) { | ||||
| 					auto port_id = RTLIL::escape_id(port_name); | ||||
|  | @ -131,7 +130,7 @@ void handle_loops(RTLIL::Design *design) | |||
| 					ports.push_back(port_id); | ||||
| 				} | ||||
| 			} | ||||
| 			jt = module_break.insert(std::make_pair(cell->type, std::move(ports))).first; | ||||
| 			jt = abc_scc_break.insert(std::make_pair(cell->type, std::move(ports))).first; | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto port_name : jt->second) { | ||||
|  | @ -554,15 +553,20 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri | |||
| 			signal = std::move(bits); | ||||
| 		} | ||||
| 
 | ||||
| 		dict<IdString, bool> abc_box; | ||||
| 		vector<RTLIL::Cell*> boxes; | ||||
| 		for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) { | ||||
| 			RTLIL::Cell *cell = it->second; | ||||
| 			if (cell->type.in("$_AND_", "$_NOT_", "$__ABC_FF_")) { | ||||
| 		for (const auto &it : module->cells_) { | ||||
| 			auto cell = it.second; | ||||
| 			if (cell->type.in("$_AND_", "$_NOT_")) { | ||||
| 				module->remove(cell); | ||||
| 				continue; | ||||
| 			} | ||||
| 			auto jt = abc_box.find(cell->type); | ||||
| 			if (jt == abc_box.end()) { | ||||
| 				RTLIL::Module* box_module = design->module(cell->type); | ||||
| 			if (box_module && box_module->attributes.count("\\abc_box_id")) | ||||
| 				jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count("\\abc_box_id"))).first; | ||||
| 			} | ||||
| 			if (jt->second) | ||||
| 				boxes.emplace_back(cell); | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ CCU2C   1      1   9      3 | |||
| 516  516  516  516  412   412  278  278  43 | ||||
| 
 | ||||
| # Box 2 : TRELLIS_DPR16X4 (16x4 dist ram) | ||||
| # Outputs: DO0, DO1, DO2, DO3, DO4 | ||||
| # Outputs: DO0, DO1, DO2, DO3 | ||||
| # name            ID  w/b   ins   outs | ||||
| TRELLIS_DPR16X4   2     0   14    4 | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,11 +15,9 @@ module L6MUX21 (input D0, D1, SD, output Z); | |||
| endmodule | ||||
| 
 | ||||
| // --------------------------------------- | ||||
| (* abc_box_id=1, abc_carry, lib_whitebox *) | ||||
| module CCU2C((* abc_carry_in *) input CIN, | ||||
| 			   input A0, B0, C0, D0, A1, B1, C1, D1, | ||||
| 	           output S0, S1, | ||||
| 	         (* abc_carry_out *) output COUT); | ||||
| (* abc_box_id=1, abc_carry="CIN,COUT", lib_whitebox *) | ||||
| module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1, | ||||
| 	           output S0, S1, COUT); | ||||
| 
 | ||||
| 	parameter [15:0] INIT0 = 16'h0000; | ||||
| 	parameter [15:0] INIT1 = 16'h0000; | ||||
|  | @ -106,7 +104,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); | |||
| endmodule | ||||
| 
 | ||||
| // --------------------------------------- | ||||
| (* abc_box_id=2, abc_scc_break="DI,WRE" *) | ||||
| //(* abc_box_id=2, abc_scc_break="DI,WAD,WRE" *) | ||||
| module TRELLIS_DPR16X4 ( | ||||
| 	input [3:0] DI, | ||||
| 	input [3:0] WAD, | ||||
|  |  | |||
|  | @ -136,20 +136,16 @@ module SB_LUT4 (output O, input I0, I1, I2, I3); | |||
| 	assign O = I0 ? s1[1] : s1[0]; | ||||
| endmodule | ||||
| 
 | ||||
| (* abc_box_id = 1, abc_carry, lib_whitebox *) | ||||
| module SB_CARRY ((* abc_carry_out *) output CO, input I0, I1, (* abc_carry_in *) input CI); | ||||
| (* abc_box_id = 1, abc_carry="CI,CO", 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); | ||||
| `ifndef _ABC | ||||
| 	always @(posedge C) | ||||
| 		Q <= D; | ||||
| `else | ||||
|     always @* Q <= D; | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| module SB_DFFE (output `SB_DFF_REG, input C, E, D); | ||||
|  | @ -896,7 +892,6 @@ module SB_WARMBOOT ( | |||
| ); | ||||
| endmodule | ||||
| 
 | ||||
| (* nomem2reg *) | ||||
| module SB_SPRAM256KA ( | ||||
| 	input [13:0] ADDRESS, | ||||
| 	input [15:0] DATAIN, | ||||
|  |  | |||
|  | @ -38,8 +38,8 @@ struct SynthIce40Pass : public ScriptPass | |||
| 		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("        relevant only for '-abc9' flow, optimise timing for the specified device.\n"); | ||||
| 		log("        default: hx\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -top <module>\n"); | ||||
| 		log("        use the specified module as top module\n"); | ||||
|  | @ -105,7 +105,6 @@ struct SynthIce40Pass : public ScriptPass | |||
| 		log("\n"); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	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; | ||||
|  |  | |||
|  | @ -23,13 +23,11 @@ | |||
| module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule | ||||
| (* techmap_celltype = "$_DFF_PN0_" *) | ||||
| module _90_dff_pn0_to_pp0 (input D, C, R, output Q); \$_DFF_PP0_  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule | ||||
| 
 | ||||
| (* techmap_celltype = "$_DFF_NN1_" *) | ||||
| module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1   _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule | ||||
| (* techmap_celltype = "$_DFF_PN1_" *) | ||||
| module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1   _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule | ||||
| 
 | ||||
| 
 | ||||
| module \$__SHREG_ (input C, input D, input E, output Q); | ||||
|   parameter DEPTH = 0; | ||||
|   parameter [DEPTH-1:0] INIT = 0; | ||||
|  |  | |||
|  | @ -181,8 +181,8 @@ module XORCY(output O, input CI, LI); | |||
|   assign O = CI ^ LI; | ||||
| endmodule | ||||
| 
 | ||||
| (* abc_box_id = 4, abc_carry, lib_whitebox *) | ||||
| module CARRY4((* abc_carry_out *) output [3:0] CO, output [3:0] O, (* abc_carry_in *) input CI, input CYINIT, input [3:0] DI, S); | ||||
| (* abc_box_id = 3, abc_carry="CI,CO", lib_whitebox *) | ||||
| module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S); | ||||
|   assign O = S ^ {CO[2:0], CI | CYINIT}; | ||||
|   assign CO[0] = S[0] ? CI | CYINIT : DI[0]; | ||||
|   assign CO[1] = S[1] ? CO[0] : DI[1]; | ||||
|  |  | |||
|  | @ -62,9 +62,6 @@ struct SynthXilinxPass : public ScriptPass | |||
| 		log("        generate an output netlist (and BLIF file) suitable for VPR\n"); | ||||
| 		log("        (this feature is experimental and incomplete)\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nocarry\n"); | ||||
| 		log("        disable inference of carry chains\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nobram\n"); | ||||
| 		log("        disable inference of block rams\n"); | ||||
| 		log("\n"); | ||||
|  |  | |||
|  | @ -2,6 +2,16 @@ | |||
| 
 | ||||
| set -e | ||||
| 
 | ||||
| OPTIND=1 | ||||
| abcprog="../../yosys-abc"    # default to built-in version of abc | ||||
| while getopts "A:" opt | ||||
| do | ||||
|     case "$opt" in | ||||
| 	A) abcprog="$OPTARG" ;; | ||||
|     esac | ||||
| done | ||||
| shift "$((OPTIND-1))" | ||||
| 
 | ||||
| # NB: *.aag and *.aig must contain a symbol table naming the primary | ||||
| #     inputs and outputs, otherwise ABC and Yosys will name them | ||||
| #     arbitrarily (and inconsistently with each other). | ||||
|  | @ -11,7 +21,7 @@ for aag in *.aag; do | |||
|     # (which would have been created by the reference aig2aig utility, | ||||
|     #  available from http://fmv.jku.at/aiger/) | ||||
|     echo "Checking $aag." | ||||
|     ../../yosys-abc -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" | ||||
|     $abcprog -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" | ||||
|     ../../yosys -qp " | ||||
| read_verilog ${aag%.*}_ref.v | ||||
| prep | ||||
|  | @ -28,7 +38,7 @@ done | |||
| 
 | ||||
| for aig in *.aig; do | ||||
|     echo "Checking $aig." | ||||
|     ../../yosys-abc -q "read -c $aig; write ${aig%.*}_ref.v" | ||||
|     $abcprog -q "read -c $aig; write ${aig%.*}_ref.v" | ||||
|     ../../yosys -qp " | ||||
| read_verilog ${aig%.*}_ref.v | ||||
| prep | ||||
|  |  | |||
							
								
								
									
										18
									
								
								tests/arch/run-test.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								tests/arch/run-test.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| #!/bin/bash | ||||
| 
 | ||||
| set -e | ||||
| 
 | ||||
| echo "Running syntax check on arch sim models" | ||||
| for arch in ../../techlibs/*; do | ||||
| 	find $arch -name cells_sim.v | while read path; do | ||||
| 		echo -n "Test $path ->" | ||||
| 		iverilog -t null -I$arch $path | ||||
| 		echo " ok" | ||||
| 	done | ||||
| done | ||||
| 
 | ||||
| for path in "../../techlibs/common/simcells.v"  "../../techlibs/common/simlib.v"; do | ||||
| 	echo -n "Test $path ->" | ||||
| 	iverilog -t null $path | ||||
| 	echo " ok" | ||||
| done | ||||
|  | @ -4,15 +4,17 @@ set -e | |||
| 
 | ||||
| OPTIND=1 | ||||
| seed=""    # default to no seed specified | ||||
| while getopts "S:" opt | ||||
| abcopt="" | ||||
| while getopts "A:S:" opt | ||||
| do | ||||
|     case "$opt" in | ||||
| 	A) abcopt="-A $OPTARG" ;; | ||||
| 	S) seed="-S $OPTARG" ;; | ||||
|     esac | ||||
| done | ||||
| shift "$((OPTIND-1))" | ||||
| 
 | ||||
| bash ../tools/autotest.sh $seed -G *.v | ||||
| bash ../tools/autotest.sh $abcopt $seed -G *.v | ||||
| 
 | ||||
| for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do | ||||
| 	echo -n "Testing expectations for $f .." | ||||
|  |  | |||
							
								
								
									
										12
									
								
								tests/opt/opt_ff_sat.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/opt/opt_ff_sat.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| module top ( | ||||
| 	input clk, | ||||
| 	output reg [7:0] cnt | ||||
| ); | ||||
| 	initial cnt = 0; | ||||
| 	always @(posedge clk) begin | ||||
| 		if (cnt < 20) | ||||
| 			cnt <= cnt + 1; | ||||
| 		else | ||||
| 			cnt <= 0; | ||||
| 	end | ||||
| endmodule | ||||
							
								
								
									
										5
									
								
								tests/opt/opt_ff_sat.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/opt/opt_ff_sat.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| read_verilog opt_ff_sat.v | ||||
| prep -flatten | ||||
| opt_rmdff -sat | ||||
| synth | ||||
| select -assert-count 5 t:$_DFF_P_ | ||||
|  | @ -23,12 +23,13 @@ warn_iverilog_git=false | |||
| # The tests are skipped if firrtl2verilog is the empty string (the default). | ||||
| firrtl2verilog="" | ||||
| xfirrtl="../xfirrtl" | ||||
| abcprog="$toolsdir/../../yosys-abc" | ||||
| 
 | ||||
| if [ ! -f $toolsdir/cmp_tbdata -o $toolsdir/cmp_tbdata.c -nt $toolsdir/cmp_tbdata ]; then | ||||
| 	( set -ex; ${CC:-gcc} -Wall -o $toolsdir/cmp_tbdata $toolsdir/cmp_tbdata.c; ) || exit 1 | ||||
| fi | ||||
| 
 | ||||
| while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do | ||||
| while getopts xmGl:wkjvref:s:p:n:S:I:A:-: opt; do | ||||
| 	case "$opt" in | ||||
| 		x) | ||||
| 			use_xsim=true ;; | ||||
|  | @ -65,6 +66,8 @@ while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do | |||
| 			include_opts="$include_opts -I $OPTARG" | ||||
| 			xinclude_opts="$xinclude_opts -i $OPTARG" | ||||
| 			minclude_opts="$minclude_opts +incdir+$OPTARG" ;; | ||||
| 		A) | ||||
| 			abcprog="$OPTARG" ;; | ||||
| 		-) | ||||
| 			case "${OPTARG}" in | ||||
| 			    xfirrtl) | ||||
|  | @ -147,7 +150,7 @@ do | |||
| 		if [[ "$ext" == "v" ]]; then | ||||
| 			egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext} | ||||
| 		elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then | ||||
| 			"$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.${refext}" | ||||
| 			$abcprog -c "read_aiger ../${fn}; write ${bn}_ref.${refext}" | ||||
| 		else | ||||
| 			refext=$ext | ||||
| 			cp ../${fn} ${bn}_ref.${refext} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue