mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/eddie/abc9_refactor' into eddie/abc9_required
This commit is contained in:
		
						commit
						915e7dde73
					
				
					 22 changed files with 789 additions and 389 deletions
				
			
		|  | @ -156,7 +156,6 @@ struct XAigerWriter | ||||||
| 			if (wire->get_bool_attribute(ID::keep)) | 			if (wire->get_bool_attribute(ID::keep)) | ||||||
| 				sigmap.add(wire); | 				sigmap.add(wire); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 		for (auto wire : module->wires()) | 		for (auto wire : module->wires()) | ||||||
| 			for (int i = 0; i < GetSize(wire); i++) | 			for (int i = 0; i < GetSize(wire); i++) | ||||||
| 			{ | 			{ | ||||||
|  | @ -174,18 +173,21 @@ struct XAigerWriter | ||||||
| 				undriven_bits.insert(bit); | 				undriven_bits.insert(bit); | ||||||
| 				unused_bits.insert(bit); | 				unused_bits.insert(bit); | ||||||
| 
 | 
 | ||||||
| 				if (wire->port_input) | 				bool keep = wire->get_bool_attribute(ID::keep); | ||||||
|  | 				if (wire->port_input || keep) | ||||||
| 					input_bits.insert(bit); | 					input_bits.insert(bit); | ||||||
| 
 | 
 | ||||||
| 				if (wire->port_output) { | 				if (wire->port_output || keep) { | ||||||
| 					if (bit != wirebit) | 					if (bit != wirebit) | ||||||
| 						alias_map[wirebit] = bit; | 						alias_map[wirebit] = bit; | ||||||
| 					output_bits.insert(wirebit); | 					output_bits.insert(wirebit); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 		std::vector<int> arrivals; | 		dict<IdString,dict<IdString,std::vector<int>>> arrivals_cache; | ||||||
| 		for (auto cell : module->cells()) { | 		for (auto cell : module->cells()) { | ||||||
|  | 			RTLIL::Module* inst_module = module->design->module(cell->type); | ||||||
|  | 			if (!cell->has_keep_attr()) { | ||||||
| 				if (cell->type == "$_NOT_") | 				if (cell->type == "$_NOT_") | ||||||
| 				{ | 				{ | ||||||
| 					SigBit A = sigmap(cell->getPort("\\A").as_bit()); | 					SigBit A = sigmap(cell->getPort("\\A").as_bit()); | ||||||
|  | @ -223,8 +225,7 @@ struct XAigerWriter | ||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Module* inst_module = module->design->module(cell->type); | 				if (inst_module) { | ||||||
| 			if (inst_module && inst_module->get_blackbox_attribute()) { |  | ||||||
| 					auto it = cell->attributes.find("\\abc9_box_seq"); | 					auto it = cell->attributes.find("\\abc9_box_seq"); | ||||||
| 					if (it != cell->attributes.end()) { | 					if (it != cell->attributes.end()) { | ||||||
| 						int abc9_box_seq = it->second.as_int(); | 						int abc9_box_seq = it->second.as_int(); | ||||||
|  | @ -237,10 +238,15 @@ struct XAigerWriter | ||||||
| 							continue; | 							continue; | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  | 					auto &cell_arrivals = arrivals_cache[cell->type]; | ||||||
| 					for (const auto &conn : cell->connections()) { | 					for (const auto &conn : cell->connections()) { | ||||||
| 						auto port_wire = inst_module->wire(conn.first); | 						auto port_wire = inst_module->wire(conn.first); | ||||||
| 					if (port_wire->port_output) { | 						if (!port_wire->port_output) | ||||||
| 						arrivals.clear(); | 							continue; | ||||||
|  | 
 | ||||||
|  | 						auto r = cell_arrivals.insert(conn.first); | ||||||
|  | 						auto &arrivals = r.first->second; | ||||||
|  | 						if (r.second) { | ||||||
| 							auto it = port_wire->attributes.find("\\abc9_arrival"); | 							auto it = port_wire->attributes.find("\\abc9_arrival"); | ||||||
| 							if (it == port_wire->attributes.end()) | 							if (it == port_wire->attributes.end()) | ||||||
| 								continue; | 								continue; | ||||||
|  | @ -249,18 +255,19 @@ struct XAigerWriter | ||||||
| 							else | 							else | ||||||
| 								for (const auto &tok : split_tokens(it->second.decode_string())) | 								for (const auto &tok : split_tokens(it->second.decode_string())) | ||||||
| 									arrivals.push_back(atoi(tok.c_str())); | 									arrivals.push_back(atoi(tok.c_str())); | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
| 						if (GetSize(arrivals) > 1 && GetSize(arrivals) != GetSize(port_wire)) | 						if (GetSize(arrivals) > 1 && GetSize(arrivals) != GetSize(port_wire)) | ||||||
| 							log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), | 							log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first), | ||||||
| 									GetSize(port_wire), log_signal(it->second), GetSize(arrivals)); | 									GetSize(port_wire), log_signal(it->second), GetSize(arrivals)); | ||||||
| 						auto jt = arrivals.begin(); |  | ||||||
| 
 | 
 | ||||||
|  | 						auto jt = arrivals.begin(); | ||||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||||
| 						if (ys_debug(1)) { | 						if (ys_debug(1)) { | ||||||
| 							static std::set<std::pair<IdString,IdString>> seen; | 							static std::set<std::pair<IdString,IdString>> seen; | ||||||
| 							if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_arrival = %d\n", log_id(cell->type), log_id(conn.first), *jt); | 							if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_arrival = %d\n", log_id(cell->type), log_id(conn.first), *jt); | ||||||
| 						} | 						} | ||||||
| #endif | #endif | ||||||
| 
 |  | ||||||
| 						for (auto bit : sigmap(conn.second)) { | 						for (auto bit : sigmap(conn.second)) { | ||||||
| 							arrival_times[bit] = *jt; | 							arrival_times[bit] = *jt; | ||||||
| 							if (arrivals.size() > 1) | 							if (arrivals.size() > 1) | ||||||
|  | @ -283,6 +290,9 @@ struct XAigerWriter | ||||||
| 					for (auto b : c.second) { | 					for (auto b : c.second) { | ||||||
| 						Wire *w = b.wire; | 						Wire *w = b.wire; | ||||||
| 						if (!w) continue; | 						if (!w) continue; | ||||||
|  | 						// Do not add as PO if bit is already a PI
 | ||||||
|  | 						if (input_bits.count(b)) | ||||||
|  | 							continue; | ||||||
| 						if (!w->port_output || !cell_known) { | 						if (!w->port_output || !cell_known) { | ||||||
| 							SigBit I = sigmap(b); | 							SigBit I = sigmap(b); | ||||||
| 							if (I != b) | 							if (I != b) | ||||||
|  | @ -337,12 +347,11 @@ struct XAigerWriter | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			// 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
 |  | ||||||
| 			for (auto port_name : r.first->second) { | 			for (auto port_name : r.first->second) { | ||||||
| 				auto w = box_module->wire(port_name); | 				auto w = box_module->wire(port_name); | ||||||
| 				log_assert(w); | 				log_assert(w); | ||||||
| 				auto rhs = cell->getPort(port_name); | 				auto rhs = cell->connections_.at(port_name, SigSpec()); | ||||||
|  | 				rhs.append(Const(State::Sx, GetSize(w)-GetSize(rhs))); | ||||||
| 				if (w->port_input) | 				if (w->port_input) | ||||||
| 					for (auto b : rhs) { | 					for (auto b : rhs) { | ||||||
| 						SigBit I = sigmap(b); | 						SigBit I = sigmap(b); | ||||||
|  | @ -364,6 +373,11 @@ struct XAigerWriter | ||||||
| 							alias_map[O] = b; | 							alias_map[O] = b; | ||||||
| 						ci_bits.emplace_back(b); | 						ci_bits.emplace_back(b); | ||||||
| 						undriven_bits.erase(O); | 						undriven_bits.erase(O); | ||||||
|  | 						// If PI and CI, then must be a (* keep *) wire
 | ||||||
|  | 						if (input_bits.erase(O)) { | ||||||
|  | 							log_assert(output_bits.count(O)); | ||||||
|  | 							log_assert(O.wire->get_bool_attribute(ID::keep)); | ||||||
|  | 						} | ||||||
| 					} | 					} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -432,6 +446,10 @@ struct XAigerWriter | ||||||
| 
 | 
 | ||||||
| 		for (auto &bit : ci_bits) { | 		for (auto &bit : ci_bits) { | ||||||
| 			aig_m++, aig_i++; | 			aig_m++, aig_i++; | ||||||
|  | 			// 1'bx may exist here due to a box output
 | ||||||
|  | 			//   that has been padded to its full width
 | ||||||
|  | 			if (bit == State::Sx) | ||||||
|  | 				continue; | ||||||
| 			log_assert(!aig_map.count(bit)); | 			log_assert(!aig_map.count(bit)); | ||||||
| 			aig_map[bit] = 2*aig_m; | 			aig_map[bit] = 2*aig_m; | ||||||
| 		} | 		} | ||||||
|  | @ -443,7 +461,27 @@ struct XAigerWriter | ||||||
| 
 | 
 | ||||||
| 		for (const auto &bit : output_bits) { | 		for (const auto &bit : output_bits) { | ||||||
| 			ordered_outputs[bit] = aig_o++; | 			ordered_outputs[bit] = aig_o++; | ||||||
| 			aig_outputs.push_back(bit2aig(bit)); | 			int aig; | ||||||
|  | 			// Unlike bit2aig() which checks aig_map first, for
 | ||||||
|  | 			//   inout/keep bits, since aig_map will point to
 | ||||||
|  | 			//   the PI, first attempt to find the NOT/AND driver
 | ||||||
|  | 			//   before resorting to an aig_map lookup (which
 | ||||||
|  | 			//   could be another PO)
 | ||||||
|  | 			if (input_bits.count(bit)) { | ||||||
|  | 				if (not_map.count(bit)) { | ||||||
|  | 					aig = 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 = mkgate(a0, a1); | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 					aig = aig_map.at(bit); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 				aig = bit2aig(bit); | ||||||
|  | 			aig_outputs.push_back(aig); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (auto &i : ff_bits) { | 		for (auto &i : ff_bits) { | ||||||
|  | @ -720,7 +758,8 @@ struct XAigerBackend : public Backend { | ||||||
| 		log("Write the top module (according to the (* top *) attribute or if only one module\n"); | 		log("Write the top module (according to the (* top *) attribute or if only one module\n"); | ||||||
| 		log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, or"); | 		log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, or"); | ||||||
| 		log("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n"); | 		log("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n"); | ||||||
| 		log("pseudo-outputs.\n"); | 		log("pseudo-outputs. Whitebox contents will be taken from the '<module-name>$holes'\n"); | ||||||
|  | 		log("module, if it exists.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -ascii\n"); | 		log("    -ascii\n"); | ||||||
| 		log("        write ASCII version of AIGER format\n"); | 		log("        write ASCII version of AIGER format\n"); | ||||||
|  |  | ||||||
|  | @ -300,6 +300,26 @@ struct EdifBackend : public Backend { | ||||||
| 		*f << stringf("  (library DESIGN\n"); | 		*f << stringf("  (library DESIGN\n"); | ||||||
| 		*f << stringf("    (edifLevel 0)\n"); | 		*f << stringf("    (edifLevel 0)\n"); | ||||||
| 		*f << stringf("    (technology (numberDefinition))\n"); | 		*f << stringf("    (technology (numberDefinition))\n"); | ||||||
|  | 
 | ||||||
|  | 		auto add_prop = [&](IdString name, Const val) { | ||||||
|  | 			if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) | ||||||
|  | 				*f << stringf("\n            (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str()); | ||||||
|  | 			else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def()) | ||||||
|  | 				*f << stringf("\n            (property %s (integer %u))", EDIF_DEF(name), val.as_int()); | ||||||
|  | 			else { | ||||||
|  | 				std::string hex_string = ""; | ||||||
|  | 				for (size_t i = 0; i < val.bits.size(); i += 4) { | ||||||
|  | 					int digit_value = 0; | ||||||
|  | 					if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; | ||||||
|  | 					if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; | ||||||
|  | 					if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; | ||||||
|  | 					if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; | ||||||
|  | 					char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; | ||||||
|  | 					hex_string = std::string(digit_str) + hex_string; | ||||||
|  | 				} | ||||||
|  | 				*f << stringf("\n            (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str()); | ||||||
|  | 			} | ||||||
|  | 		};		 | ||||||
| 		for (auto module : sorted_modules) | 		for (auto module : sorted_modules) | ||||||
| 		{ | 		{ | ||||||
| 			if (module->get_blackbox_attribute()) | 			if (module->get_blackbox_attribute()) | ||||||
|  | @ -323,14 +343,23 @@ struct EdifBackend : public Backend { | ||||||
| 				else if (!wire->port_input) | 				else if (!wire->port_input) | ||||||
| 					dir = "OUTPUT"; | 					dir = "OUTPUT"; | ||||||
| 				if (wire->width == 1) { | 				if (wire->width == 1) { | ||||||
| 					*f << stringf("          (port %s (direction %s))\n", EDIF_DEF(wire->name), dir); | 					*f << stringf("          (port %s (direction %s)", EDIF_DEF(wire->name), dir); | ||||||
|  | 					if (attr_properties) | ||||||
|  | 						for (auto &p : wire->attributes) | ||||||
|  | 							add_prop(p.first, p.second); | ||||||
|  | 					*f << ")\n"; | ||||||
| 					RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire)); | 					RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire)); | ||||||
| 					net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name))); | 					net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name))); | ||||||
| 				} else { | 				} else { | ||||||
| 					int b[2]; | 					int b[2]; | ||||||
| 					b[wire->upto ? 0 : 1] = wire->start_offset; | 					b[wire->upto ? 0 : 1] = wire->start_offset; | ||||||
| 					b[wire->upto ? 1 : 0] = wire->start_offset + GetSize(wire) - 1; | 					b[wire->upto ? 1 : 0] = wire->start_offset + GetSize(wire) - 1; | ||||||
| 					*f << stringf("          (port (array %s %d) (direction %s))\n", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir); | 					*f << stringf("          (port (array %s %d) (direction %s)", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir); | ||||||
|  | 					if (attr_properties) | ||||||
|  | 						for (auto &p : wire->attributes) | ||||||
|  | 							add_prop(p.first, p.second); | ||||||
|  | 
 | ||||||
|  | 					*f << ")\n"; | ||||||
| 					for (int i = 0; i < wire->width; i++) { | 					for (int i = 0; i < wire->width; i++) { | ||||||
| 						RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i)); | 						RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i)); | ||||||
| 						net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), GetSize(wire)-i-1)); | 						net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), GetSize(wire)-i-1)); | ||||||
|  | @ -348,27 +377,6 @@ struct EdifBackend : public Backend { | ||||||
| 				*f << stringf("          (instance %s\n", EDIF_DEF(cell->name)); | 				*f << stringf("          (instance %s\n", EDIF_DEF(cell->name)); | ||||||
| 				*f << stringf("            (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), | 				*f << stringf("            (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), | ||||||
| 						lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); | 						lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); | ||||||
| 
 |  | ||||||
| 				auto add_prop = [&](IdString name, Const val) { |  | ||||||
| 					if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0) |  | ||||||
| 						*f << stringf("\n            (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str()); |  | ||||||
| 					else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def()) |  | ||||||
| 						*f << stringf("\n            (property %s (integer %u))", EDIF_DEF(name), val.as_int()); |  | ||||||
| 					else { |  | ||||||
| 						std::string hex_string = ""; |  | ||||||
| 						for (size_t i = 0; i < val.bits.size(); i += 4) { |  | ||||||
| 							int digit_value = 0; |  | ||||||
| 							if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1; |  | ||||||
| 							if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2; |  | ||||||
| 							if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4; |  | ||||||
| 							if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8; |  | ||||||
| 							char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; |  | ||||||
| 							hex_string = std::string(digit_str) + hex_string; |  | ||||||
| 						} |  | ||||||
| 						*f << stringf("\n            (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str()); |  | ||||||
| 					} |  | ||||||
| 				}; |  | ||||||
| 
 |  | ||||||
| 				for (auto &p : cell->parameters) | 				for (auto &p : cell->parameters) | ||||||
| 					add_prop(p.first, p.second); | 					add_prop(p.first, p.second); | ||||||
| 				if (attr_properties) | 				if (attr_properties) | ||||||
|  | @ -432,7 +440,11 @@ struct EdifBackend : public Backend { | ||||||
| 					if (sig == RTLIL::State::S1) | 					if (sig == RTLIL::State::S1) | ||||||
| 						*f << stringf("            (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P'); | 						*f << stringf("            (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P'); | ||||||
| 				}				 | 				}				 | ||||||
| 				*f << stringf("          ))\n"); | 				*f << stringf("            )"); | ||||||
|  | 				if (attr_properties && sig.wire != NULL) | ||||||
|  | 					for (auto &p : sig.wire->attributes) | ||||||
|  | 						add_prop(p.first, p.second); | ||||||
|  | 				*f << stringf("\n          )\n"); | ||||||
| 			} | 			} | ||||||
| 			*f << stringf("        )\n"); | 			*f << stringf("        )\n"); | ||||||
| 			*f << stringf("      )\n"); | 			*f << stringf("      )\n"); | ||||||
|  |  | ||||||
|  | @ -206,7 +206,7 @@ eval_end: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports) | 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) | 	: design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports), aiger_autoidx(autoidx++) | ||||||
| { | { | ||||||
| 	module = new RTLIL::Module; | 	module = new RTLIL::Module; | ||||||
| 	module->name = module_name; | 	module->name = module_name; | ||||||
|  | @ -255,7 +255,7 @@ end_of_header: | ||||||
| 	else | 	else | ||||||
| 		log_abort(); | 		log_abort(); | ||||||
| 
 | 
 | ||||||
| 	RTLIL::Wire* n0 = module->wire("$0"); | 	RTLIL::Wire* n0 = module->wire(stringf("$aiger%d$0", aiger_autoidx)); | ||||||
| 	if (n0) | 	if (n0) | ||||||
| 		module->connect(n0, State::S0); | 		module->connect(n0, State::S0); | ||||||
| 
 | 
 | ||||||
|  | @ -323,18 +323,18 @@ static uint32_t parse_xaiger_literal(std::istream &f) | ||||||
| 	return from_big_endian(l); | 	return from_big_endian(l); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) | RTLIL::Wire* AigerReader::createWireIfNotExists(RTLIL::Module *module, unsigned literal) | ||||||
| { | { | ||||||
| 	const unsigned variable = literal >> 1; | 	const unsigned variable = literal >> 1; | ||||||
| 	const bool invert = literal & 1; | 	const bool invert = literal & 1; | ||||||
| 	RTLIL::IdString wire_name(stringf("$%d%s", variable, invert ? "b" : "")); | 	RTLIL::IdString wire_name(stringf("$aiger%d$%d%s", aiger_autoidx, variable, invert ? "b" : "")); | ||||||
| 	RTLIL::Wire *wire = module->wire(wire_name); | 	RTLIL::Wire *wire = module->wire(wire_name); | ||||||
| 	if (wire) return wire; | 	if (wire) return wire; | ||||||
| 	log_debug2("Creating %s\n", wire_name.c_str()); | 	log_debug2("Creating %s\n", wire_name.c_str()); | ||||||
| 	wire = module->addWire(wire_name); | 	wire = module->addWire(wire_name); | ||||||
| 	wire->port_input = wire->port_output = false; | 	wire->port_input = wire->port_output = false; | ||||||
| 	if (!invert) return wire; | 	if (!invert) return wire; | ||||||
| 	RTLIL::IdString wire_inv_name(stringf("$%d", variable)); | 	RTLIL::IdString wire_inv_name(stringf("$aiger%d$%d", aiger_autoidx, variable)); | ||||||
| 	RTLIL::Wire *wire_inv = module->wire(wire_inv_name); | 	RTLIL::Wire *wire_inv = module->wire(wire_inv_name); | ||||||
| 	if (wire_inv) { | 	if (wire_inv) { | ||||||
| 		if (module->cell(wire_inv_name)) return wire; | 		if (module->cell(wire_inv_name)) return wire; | ||||||
|  | @ -346,7 +346,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	log_debug2("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); | 	log_debug2("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); | ||||||
| 	module->addNotGate(stringf("$%d$not", variable), wire_inv, wire); | 	module->addNotGate(stringf("$not$aiger%d$%d", aiger_autoidx, variable), wire_inv, wire); | ||||||
| 
 | 
 | ||||||
| 	return wire; | 	return wire; | ||||||
| } | } | ||||||
|  | @ -383,7 +383,7 @@ void AigerReader::parse_xaiger() | ||||||
| 	else | 	else | ||||||
| 		log_abort(); | 		log_abort(); | ||||||
| 
 | 
 | ||||||
| 	RTLIL::Wire* n0 = module->wire("$0"); | 	RTLIL::Wire* n0 = module->wire(stringf("$aiger%d$0", aiger_autoidx)); | ||||||
| 	if (n0) | 	if (n0) | ||||||
| 		module->connect(n0, State::S0); | 		module->connect(n0, State::S0); | ||||||
| 
 | 
 | ||||||
|  | @ -407,13 +407,14 @@ void AigerReader::parse_xaiger() | ||||||
| 				uint32_t rootNodeID = parse_xaiger_literal(f); | 				uint32_t rootNodeID = parse_xaiger_literal(f); | ||||||
| 				uint32_t cutLeavesM = parse_xaiger_literal(f); | 				uint32_t cutLeavesM = parse_xaiger_literal(f); | ||||||
| 				log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); | 				log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); | ||||||
| 				RTLIL::Wire *output_sig = module->wire(stringf("$%d", rootNodeID)); | 				RTLIL::Wire *output_sig = module->wire(stringf("$aiger%d$%d", aiger_autoidx, rootNodeID)); | ||||||
|  | 				log_assert(output_sig); | ||||||
| 				uint32_t nodeID; | 				uint32_t nodeID; | ||||||
| 				RTLIL::SigSpec input_sig; | 				RTLIL::SigSpec input_sig; | ||||||
| 				for (unsigned j = 0; j < cutLeavesM; ++j) { | 				for (unsigned j = 0; j < cutLeavesM; ++j) { | ||||||
| 					nodeID = parse_xaiger_literal(f); | 					nodeID = parse_xaiger_literal(f); | ||||||
| 					log_debug2("\t%u\n", nodeID); | 					log_debug2("\t%u\n", nodeID); | ||||||
| 					RTLIL::Wire *wire = module->wire(stringf("$%d", nodeID)); | 					RTLIL::Wire *wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, nodeID)); | ||||||
| 					log_assert(wire); | 					log_assert(wire); | ||||||
| 					input_sig.append(wire); | 					input_sig.append(wire); | ||||||
| 				} | 				} | ||||||
|  | @ -430,10 +431,10 @@ void AigerReader::parse_xaiger() | ||||||
| 					log_assert(o.wire == nullptr); | 					log_assert(o.wire == nullptr); | ||||||
| 					lut_mask[gray] = o.data; | 					lut_mask[gray] = o.data; | ||||||
| 				} | 				} | ||||||
| 				RTLIL::Cell *output_cell = module->cell(stringf("$%d$and", rootNodeID)); | 				RTLIL::Cell *output_cell = module->cell(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID)); | ||||||
| 				log_assert(output_cell); | 				log_assert(output_cell); | ||||||
| 				module->remove(output_cell); | 				module->remove(output_cell); | ||||||
| 				module->addLut(stringf("$%d$lut", rootNodeID), input_sig, output_sig, std::move(lut_mask)); | 				module->addLut(stringf("$lut$aiger%d$%d", aiger_autoidx, rootNodeID), input_sig, output_sig, std::move(lut_mask)); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		else if (c == 'r') { | 		else if (c == 'r') { | ||||||
|  | @ -603,7 +604,7 @@ void AigerReader::parse_aiger_ascii() | ||||||
| 		RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); | 		RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); | ||||||
| 		RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); | 		RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); | ||||||
| 		RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); | 		RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); | ||||||
| 		module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire); | 		module->addAndGate("$and" + o_wire->name.str(), i1_wire, i2_wire, o_wire); | ||||||
| 	} | 	} | ||||||
| 	std::getline(f, line); // Ignore up to start of next line
 | 	std::getline(f, line); // Ignore up to start of next line
 | ||||||
| } | } | ||||||
|  | @ -729,7 +730,7 @@ void AigerReader::parse_aiger_binary() | ||||||
| 		RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); | 		RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); | ||||||
| 		RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); | 		RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); | ||||||
| 		RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); | 		RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); | ||||||
| 		module->addAndGate(o_wire->name.str() + "$and", i1_wire, i2_wire, o_wire); | 		module->addAndGate("$and" + o_wire->name.str(), i1_wire, i2_wire, o_wire); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -831,6 +832,7 @@ void AigerReader::post_process() | ||||||
| 					} | 					} | ||||||
| 					else { | 					else { | ||||||
| 						wire->port_output = false; | 						wire->port_output = false; | ||||||
|  | 						existing->port_output = true; | ||||||
| 						module->connect(wire, existing); | 						module->connect(wire, existing); | ||||||
| 						wire = existing; | 						wire = existing; | ||||||
| 					} | 					} | ||||||
|  | @ -845,8 +847,9 @@ void AigerReader::post_process() | ||||||
| 							wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); | 							wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index); | ||||||
| 					} | 					} | ||||||
| 					else { | 					else { | ||||||
| 						module->connect(wire, existing); |  | ||||||
| 						wire->port_output = false; | 						wire->port_output = false; | ||||||
|  | 						existing->port_output = true; | ||||||
|  | 						module->connect(wire, existing); | ||||||
| 					} | 					} | ||||||
| 					log_debug(" -> %s\n", log_id(indexed_name)); | 					log_debug(" -> %s\n", log_id(indexed_name)); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ struct AigerReader | ||||||
|     RTLIL::Module *module; |     RTLIL::Module *module; | ||||||
|     std::string map_filename; |     std::string map_filename; | ||||||
|     bool wideports; |     bool wideports; | ||||||
|  |     const int aiger_autoidx; | ||||||
| 
 | 
 | ||||||
|     unsigned M, I, L, O, A; |     unsigned M, I, L, O, A; | ||||||
|     unsigned B, C, J, F; // Optional in AIGER 1.9
 |     unsigned B, C, J, F; // Optional in AIGER 1.9
 | ||||||
|  | @ -51,6 +52,8 @@ struct AigerReader | ||||||
|     void parse_aiger_ascii(); |     void parse_aiger_ascii(); | ||||||
|     void parse_aiger_binary(); |     void parse_aiger_binary(); | ||||||
|     void post_process(); |     void post_process(); | ||||||
|  | 
 | ||||||
|  |     RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| YOSYS_NAMESPACE_END | YOSYS_NAMESPACE_END | ||||||
|  |  | ||||||
|  | @ -46,6 +46,7 @@ IdString RTLIL::ID::Y; | ||||||
| IdString RTLIL::ID::keep; | IdString RTLIL::ID::keep; | ||||||
| IdString RTLIL::ID::whitebox; | IdString RTLIL::ID::whitebox; | ||||||
| IdString RTLIL::ID::blackbox; | IdString RTLIL::ID::blackbox; | ||||||
|  | dict<std::string, std::string> RTLIL::constpad; | ||||||
| 
 | 
 | ||||||
| RTLIL::Const::Const() | RTLIL::Const::Const() | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -377,6 +377,8 @@ namespace RTLIL | ||||||
| 		extern IdString blackbox; | 		extern IdString blackbox; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	extern dict<std::string, std::string> constpad; | ||||||
|  | 
 | ||||||
| 	static inline std::string escape_id(std::string str) { | 	static inline std::string escape_id(std::string str) { | ||||||
| 		if (str.size() > 0 && str[0] != '\\' && str[0] != '$') | 		if (str.size() > 0 && str[0] != '\\' && str[0] != '$') | ||||||
| 			return "\\" + str; | 			return "\\" + str; | ||||||
|  |  | ||||||
|  | @ -56,7 +56,7 @@ int autoname_worker(Module *module) | ||||||
| 			for (auto &conn : cell->connections()) { | 			for (auto &conn : cell->connections()) { | ||||||
| 				string suffix = stringf("_%s", log_id(conn.first)); | 				string suffix = stringf("_%s", log_id(conn.first)); | ||||||
| 				for (auto bit : conn.second) | 				for (auto bit : conn.second) | ||||||
| 					if (bit.wire != nullptr && bit.wire->name[0] == '$') { | 					if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) { | ||||||
| 						IdString new_name(cell->name.str() + suffix); | 						IdString new_name(cell->name.str() + suffix); | ||||||
| 						int score = wire_score.at(bit.wire); | 						int score = wire_score.at(bit.wire); | ||||||
| 						if (cell->output(conn.first)) score = 0; | 						if (cell->output(conn.first)) score = 0; | ||||||
|  |  | ||||||
|  | @ -72,6 +72,8 @@ struct ScratchpadPass : public Pass { | ||||||
| 				string identifier = args[++argidx]; | 				string identifier = args[++argidx]; | ||||||
| 				if (design->scratchpad.count(identifier)) { | 				if (design->scratchpad.count(identifier)) { | ||||||
| 					log("%s\n", design->scratchpad_get_string(identifier).c_str()); | 					log("%s\n", design->scratchpad_get_string(identifier).c_str()); | ||||||
|  | 				} else if (RTLIL::constpad.count(identifier)) { | ||||||
|  | 					log("%s\n", RTLIL::constpad.at(identifier).c_str()); | ||||||
| 				} else { | 				} else { | ||||||
| 					log("\"%s\" not set\n", identifier.c_str()); | 					log("\"%s\" not set\n", identifier.c_str()); | ||||||
| 				} | 				} | ||||||
|  | @ -79,6 +81,8 @@ struct ScratchpadPass : public Pass { | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-set" && argidx+2 < args.size()) { | 			if (args[argidx] == "-set" && argidx+2 < args.size()) { | ||||||
| 				string identifier = args[++argidx]; | 				string identifier = args[++argidx]; | ||||||
|  | 				if (RTLIL::constpad.count(identifier)) | ||||||
|  | 					log_error("scratchpad entry \"%s\" is a global constant\n", identifier.c_str()); | ||||||
| 				string value = args[++argidx]; | 				string value = args[++argidx]; | ||||||
| 				if (value.front() == '\"' && value.back() == '\"') value = value.substr(1, value.size() - 2); | 				if (value.front() == '\"' && value.back() == '\"') value = value.substr(1, value.size() - 2); | ||||||
| 				design->scratchpad_set_string(identifier, value); | 				design->scratchpad_set_string(identifier, value); | ||||||
|  | @ -92,8 +96,15 @@ struct ScratchpadPass : public Pass { | ||||||
| 			if (args[argidx] == "-copy" && argidx+2 < args.size()) { | 			if (args[argidx] == "-copy" && argidx+2 < args.size()) { | ||||||
| 				string identifier_from = args[++argidx]; | 				string identifier_from = args[++argidx]; | ||||||
| 				string identifier_to = args[++argidx]; | 				string identifier_to = args[++argidx]; | ||||||
| 				if (design->scratchpad.count(identifier_from) == 0) log_error("\"%s\" not set\n", identifier_from.c_str()); | 				string value; | ||||||
| 				string value = design->scratchpad_get_string(identifier_from); | 				if (design->scratchpad.count(identifier_from)) | ||||||
|  | 					value = design->scratchpad_get_string(identifier_from); | ||||||
|  | 				else if (RTLIL::constpad.count(identifier_from)) | ||||||
|  | 					value = RTLIL::constpad.at(identifier_from); | ||||||
|  | 				else | ||||||
|  | 					log_error("\"%s\" not set\n", identifier_from.c_str()); | ||||||
|  | 				if (RTLIL::constpad.count(identifier_to)) | ||||||
|  | 					log_error("scratchpad entry \"%s\" is a global constant\n", identifier_to.c_str()); | ||||||
| 				design->scratchpad_set_string(identifier_to, value); | 				design->scratchpad_set_string(identifier_to, value); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | @ -102,10 +113,10 @@ struct ScratchpadPass : public Pass { | ||||||
| 				string expected = args[++argidx]; | 				string expected = args[++argidx]; | ||||||
| 				if (expected.front() == '\"' && expected.back() == '\"') expected = expected.substr(1, expected.size() - 2); | 				if (expected.front() == '\"' && expected.back() == '\"') expected = expected.substr(1, expected.size() - 2); | ||||||
| 				if (design->scratchpad.count(identifier) == 0) | 				if (design->scratchpad.count(identifier) == 0) | ||||||
| 					log_error("Assertion failed: scratchpad entry '%s' is not defined\n", identifier.c_str()); | 					log_error("scratchpad entry '%s' is not defined\n", identifier.c_str()); | ||||||
| 				string value = design->scratchpad_get_string(identifier); | 				string value = design->scratchpad_get_string(identifier); | ||||||
| 				if (value != expected) { | 				if (value != expected) { | ||||||
| 					log_error("Assertion failed: scratchpad entry '%s' is set to '%s' instead of the asserted '%s'\n", | 					log_error("scratchpad entry '%s' is set to '%s' instead of the asserted '%s'\n", | ||||||
| 					           identifier.c_str(), value.c_str(), expected.c_str()); | 					           identifier.c_str(), value.c_str(), expected.c_str()); | ||||||
| 				} | 				} | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -113,13 +124,13 @@ struct ScratchpadPass : public Pass { | ||||||
| 			if (args[argidx] == "-assert-set" && argidx+1 < args.size()) { | 			if (args[argidx] == "-assert-set" && argidx+1 < args.size()) { | ||||||
| 				string identifier = args[++argidx]; | 				string identifier = args[++argidx]; | ||||||
| 				if (design->scratchpad.count(identifier) == 0) | 				if (design->scratchpad.count(identifier) == 0) | ||||||
| 					log_error("Assertion failed: scratchpad entry '%s' is not defined\n", identifier.c_str()); | 					log_error("scratchpad entry '%s' is not defined\n", identifier.c_str()); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-assert-unset" && argidx+1 < args.size()) { | 			if (args[argidx] == "-assert-unset" && argidx+1 < args.size()) { | ||||||
| 				string identifier = args[++argidx]; | 				string identifier = args[++argidx]; | ||||||
| 				if (design->scratchpad.count(identifier) > 0) | 				if (design->scratchpad.count(identifier) > 0) | ||||||
| 					log_error("Assertion failed: scratchpad entry '%s' is defined\n", identifier.c_str()); | 					log_error("scratchpad entry '%s' is defined\n", identifier.c_str()); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
|  | @ -18,18 +18,69 @@ | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | // [[CITE]] ABC
 | ||||||
|  | // Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification
 | ||||||
|  | // http://www.eecs.berkeley.edu/~alanmi/abc/
 | ||||||
|  | 
 | ||||||
| #include "kernel/register.h" | #include "kernel/register.h" | ||||||
| #include "kernel/celltypes.h" | #include "kernel/celltypes.h" | ||||||
| #include "kernel/rtlil.h" | #include "kernel/rtlil.h" | ||||||
| #include "kernel/log.h" | #include "kernel/log.h" | ||||||
| 
 | 
 | ||||||
|  | // abc9_exe.cc
 | ||||||
|  | std::string fold_abc9_cmd(std::string str); | ||||||
|  | 
 | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| struct Abc9Pass : public ScriptPass | struct Abc9Pass : public ScriptPass | ||||||
| { | { | ||||||
| 	Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { } | 	Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { } | ||||||
| 
 | 	void on_register() YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		RTLIL::constpad["abc9.script.default"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs"; | ||||||
|  | 		RTLIL::constpad["abc9.script.default.area"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -a -v; &mfs"; | ||||||
|  | 		RTLIL::constpad["abc9.script.default.fast"] = "+&if {C} {W} {D} {R} -v"; | ||||||
|  | 		// Based on ABC's &flow
 | ||||||
|  | 		RTLIL::constpad["abc9.script.flow"] = "+&scorr; &sweep;" \ | ||||||
|  | 			"&dch -C 500;" \ | ||||||
|  | 			/* Round 1 */ \ | ||||||
|  | 			/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ | ||||||
|  | 			"&st; &dsdb;" \ | ||||||
|  | 			/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ | ||||||
|  | 			"&st; &syn2 -m -R 10; &dsdb;" \ | ||||||
|  | 			"&blut -a -K 6;" \ | ||||||
|  | 			/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ | ||||||
|  | 			/* Round 2 */ \ | ||||||
|  | 			"&st; &sopb;" \ | ||||||
|  | 			/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ | ||||||
|  | 			"&st; &dsdb;" \ | ||||||
|  | 			/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ | ||||||
|  | 			"&st; &syn2 -m -R 10; &dsdb;" \ | ||||||
|  | 			"&blut -a -K 6;" \ | ||||||
|  | 			/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ | ||||||
|  | 			/* Round 3 */ \ | ||||||
|  | 			/* Map 1 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ | ||||||
|  | 			"&st; &dsdb;" \ | ||||||
|  | 			/* Map 2 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;" \ | ||||||
|  | 			"&st; &syn2 -m -R 10; &dsdb;" \ | ||||||
|  | 			"&blut -a -K 6;" \ | ||||||
|  | 			/* Map 3 */ "&unmap; &if {C} {W} {D} {R} -v; &save; &load; &mfs;"; | ||||||
|  | 		// Based on ABC's &flow2
 | ||||||
|  | 		RTLIL::constpad["abc9.script.flow2"] = "+&scorr; &sweep;" \ | ||||||
|  | 			/* Comm1 */ "&synch2 -K 6 -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\ | ||||||
|  | 			/* Comm2 */ "&dch -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\ | ||||||
|  | 			"&load; &st; &sopb -R 10 -C 4; " \ | ||||||
|  | 			/* Comm3 */ "&synch2 -K 6 -C 500; &if -m "/*"-E 5"*/" {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save;"\ | ||||||
|  | 			/* Comm2 */ "&dch -C 500; &if -m {C} {W} {D} {R} -v; &mfs "/*"-W 4 -M 500 -C 7000"*/"; &save; "\ | ||||||
|  | 			"&load"; | ||||||
|  | 		// Based on ABC's &flow3
 | ||||||
|  | 		RTLIL::constpad["abc9.script.flow3"] = "+&scorr; &sweep;" \ | ||||||
|  | 			"&if {C} {W} {D}; &save; &st; &syn2; &if {C} {W} {D} {R} -v; &save; &load;"\ | ||||||
|  | 			"&st; &if {C} -g -K 6; &dch -f; &if {C} {W} {D} {R} -v; &save; &load;"\ | ||||||
|  | 			"&st; &if {C} -g -K 6; &synch2; &if {C} {W} {D} {R} -v; &save; &load;"\ | ||||||
|  | 			"&mfs"; | ||||||
|  | 	} | ||||||
| 	void help() YS_OVERRIDE | 	void help() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
|  | @ -40,6 +91,11 @@ struct Abc9Pass : public ScriptPass | ||||||
| 		log("tool [1] for technology mapping of the current design to a target FPGA\n"); | 		log("tool [1] for technology mapping of the current design to a target FPGA\n"); | ||||||
| 		log("architecture. Only fully-selected modules are supported.\n"); | 		log("architecture. Only fully-selected modules are supported.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -run <from_label>:<to_label>\n"); | ||||||
|  | 		log("        only run the commands between the labels (see below). an empty\n"); | ||||||
|  | 		log("        from label is synonymous to 'begin', and empty to label is\n"); | ||||||
|  | 		log("        synonymous to the end of the command list.\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("    -exe <command>\n"); | 		log("    -exe <command>\n"); | ||||||
| #ifdef ABCEXTERNAL | #ifdef ABCEXTERNAL | ||||||
| 		log("        use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); | 		log("        use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n"); | ||||||
|  | @ -57,14 +113,12 @@ struct Abc9Pass : public ScriptPass | ||||||
| 		log("        replaced with blanks before the string is passed to ABC.\n"); | 		log("        replaced with blanks before the string is passed to ABC.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("        if no -script parameter is given, the following scripts are used:\n"); | 		log("        if no -script parameter is given, the following scripts are used:\n"); | ||||||
| 		//FIXME:
 | 		log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos)).c_str()); | ||||||
| 		//log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
 |  | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -fast\n"); | 		log("    -fast\n"); | ||||||
| 		log("        use different default scripts that are slightly faster (at the cost\n"); | 		log("        use different default scripts that are slightly faster (at the cost\n"); | ||||||
| 		log("        of output quality):\n"); | 		log("        of output quality):\n"); | ||||||
| 		//FIXME:
 | 		log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)).c_str()); | ||||||
| 		//log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str());
 |  | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -D <picoseconds>\n"); | 		log("    -D <picoseconds>\n"); | ||||||
| 		log("        set delay target. the string {D} in the default scripts above is\n"); | 		log("        set delay target. the string {D} in the default scripts above is\n"); | ||||||
|  | @ -104,7 +158,7 @@ struct Abc9Pass : public ScriptPass | ||||||
| 		log("        command output is identical across runs.\n"); | 		log("        command output is identical across runs.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -box <file>\n"); | 		log("    -box <file>\n"); | ||||||
| 		log("        pass this file with box library to ABC. Use with -lut.\n"); | 		log("        pass this file with box library to ABC.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); | 		log("Note that this is a logic optimization pass within Yosys that is calling ABC\n"); | ||||||
| 		log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); | 		log("internally. This is not going to \"run ABC on your design\". It will instead run\n"); | ||||||
|  | @ -141,6 +195,11 @@ struct Abc9Pass : public ScriptPass | ||||||
| 		dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode); | 		dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode); | ||||||
| 		cleanup = !design->scratchpad_get_bool("abc9.nocleanup", !cleanup); | 		cleanup = !design->scratchpad_get_bool("abc9.nocleanup", !cleanup); | ||||||
| 
 | 
 | ||||||
|  | 		if (design->scratchpad_get_bool("abc9.debug")) { | ||||||
|  | 			cleanup = false; | ||||||
|  | 			exe_cmd << " -showtmp"; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
| 		for (argidx = 1; argidx < args.size(); argidx++) { | 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||||
| 			std::string arg = args[argidx]; | 			std::string arg = args[argidx]; | ||||||
|  | @ -152,13 +211,13 @@ struct Abc9Pass : public ScriptPass | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-fast" || /* arg == "-dff" || */ | 			if (arg == "-fast" || /* arg == "-dff" || */ | ||||||
| 					/* arg == "-nocleanup" || */ arg == "-showtmp" || | 					/* arg == "-nocleanup" || */ arg == "-showtmp") { | ||||||
| 					arg == "-nomfs") { |  | ||||||
| 				exe_cmd << " " << arg; | 				exe_cmd << " " << arg; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-dff") { | 			if (arg == "-dff") { | ||||||
| 				dff_mode = true; | 				dff_mode = true; | ||||||
|  | 				exe_cmd << " " << arg; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-nocleanup") { | 			if (arg == "-nocleanup") { | ||||||
|  | @ -169,6 +228,14 @@ struct Abc9Pass : public ScriptPass | ||||||
| 				box_file = args[++argidx]; | 				box_file = args[++argidx]; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (arg == "-run" && argidx+1 < args.size()) { | ||||||
|  | 				size_t pos = args[argidx+1].find(':'); | ||||||
|  | 				if (pos == std::string::npos) | ||||||
|  | 					break; | ||||||
|  | 				run_from = args[++argidx].substr(0, pos); | ||||||
|  | 				run_to = args[argidx].substr(pos+1); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		extra_args(args, argidx, design); | 		extra_args(args, argidx, design); | ||||||
|  | @ -184,9 +251,9 @@ struct Abc9Pass : public ScriptPass | ||||||
| 			run("abc9_ops -check"); | 			run("abc9_ops -check"); | ||||||
| 			run("scc -set_attr abc9_scc_id {}"); | 			run("scc -set_attr abc9_scc_id {}"); | ||||||
| 			if (help_mode) | 			if (help_mode) | ||||||
| 				run("abc9_ops -break_scc -prep_times -prep_holes [-dff]", "(option for -dff)"); | 				run("abc9_ops -mark_scc -prep_times -prep_xaiger [-dff]", "(option for -dff)"); | ||||||
| 			else | 			else | ||||||
| 				run("abc9_ops -break_scc -prep_times -prep_holes" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); | 				run("abc9_ops -mark_scc -prep_times -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); | ||||||
| 			run("select -set abc9_holes A:abc9_holes"); | 			run("select -set abc9_holes A:abc9_holes"); | ||||||
| 			run("flatten -wb @abc9_holes"); | 			run("flatten -wb @abc9_holes"); | ||||||
| 			run("techmap @abc9_holes"); | 			run("techmap @abc9_holes"); | ||||||
|  | @ -200,7 +267,7 @@ struct Abc9Pass : public ScriptPass | ||||||
| 		if (check_label("map")) { | 		if (check_label("map")) { | ||||||
| 			if (help_mode) { | 			if (help_mode) { | ||||||
| 				run("foreach module in selection"); | 				run("foreach module in selection"); | ||||||
| 				run("    abc9_ops -write_box [(-box value)|(null)] <abc-temp-dir>/input.box"); | 				run("    abc9_ops -write_box [(-box <path>)|(null)] <abc-temp-dir>/input.box"); | ||||||
| 				run("    write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig"); | 				run("    write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig"); | ||||||
| 				run("    abc9_exe [options] -cwd <abc-temp-dir> -box <abc-temp-dir>/input.box"); | 				run("    abc9_exe [options] -cwd <abc-temp-dir> -box <abc-temp-dir>/input.box"); | ||||||
| 				run("    read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig"); | 				run("    read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig"); | ||||||
|  | @ -234,14 +301,16 @@ struct Abc9Pass : public ScriptPass | ||||||
| 					run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); | 					run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); | ||||||
| 
 | 
 | ||||||
| 					int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); | 					int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); | ||||||
| 					log("Extracted %d AND gates and %d wires to a netlist network with %d inputs and %d outputs.\n", | 
 | ||||||
|  | 					log("Extracted %d AND gates and %d wires from module `%s' to a netlist network with %d inputs and %d outputs.\n", | ||||||
| 							active_design->scratchpad_get_int("write_xaiger.num_ands"), | 							active_design->scratchpad_get_int("write_xaiger.num_ands"), | ||||||
| 							active_design->scratchpad_get_int("write_xaiger.num_wires"), | 							active_design->scratchpad_get_int("write_xaiger.num_wires"), | ||||||
|  | 							log_id(mod), | ||||||
| 							active_design->scratchpad_get_int("write_xaiger.num_inputs"), | 							active_design->scratchpad_get_int("write_xaiger.num_inputs"), | ||||||
| 							num_outputs); | 							num_outputs); | ||||||
| 					if (num_outputs) { | 					if (num_outputs) { | ||||||
| 						run(stringf("%s -cwd %s -box %s/input.box", exe_cmd.str().c_str(), tempdir_name.c_str(), tempdir_name.c_str())); | 						run(stringf("%s -cwd %s -box %s/input.box", exe_cmd.str().c_str(), tempdir_name.c_str(), tempdir_name.c_str())); | ||||||
| 						run(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod->name), tempdir_name.c_str(), tempdir_name.c_str())); | 						run(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str())); | ||||||
| 						run("abc9_ops -reintegrate"); | 						run("abc9_ops -reintegrate"); | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
|  | @ -258,9 +327,6 @@ struct Abc9Pass : public ScriptPass | ||||||
| 				active_design->selection_stack.pop_back(); | 				active_design->selection_stack.pop_back(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		if (check_label("post")) |  | ||||||
| 			run("abc9_ops -unbreak_scc"); |  | ||||||
| 	} | 	} | ||||||
| } Abc9Pass; | } Abc9Pass; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,20 +22,6 @@ | ||||||
| // Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification
 | // Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification
 | ||||||
| // http://www.eecs.berkeley.edu/~alanmi/abc/
 | // http://www.eecs.berkeley.edu/~alanmi/abc/
 | ||||||
| 
 | 
 | ||||||
| #if 0 |  | ||||||
| // Based on &flow3 - better QoR but more experimental
 |  | ||||||
| #define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \ |  | ||||||
| 						"&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\ |  | ||||||
| 						"&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\ |  | ||||||
| 						"&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\ |  | ||||||
| 						"&mfs; &ps -l" |  | ||||||
| #else |  | ||||||
| #define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l" |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #define ABC_FAST_COMMAND_LUT "&st; &if {W} {D}" |  | ||||||
| 
 |  | ||||||
| #include "kernel/register.h" | #include "kernel/register.h" | ||||||
| #include "kernel/log.h" | #include "kernel/log.h" | ||||||
| 
 | 
 | ||||||
|  | @ -48,6 +34,25 @@ | ||||||
| extern "C" int Abc_RealMain(int argc, char *argv[]); | extern "C" int Abc_RealMain(int argc, char *argv[]); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | std::string fold_abc9_cmd(std::string str) | ||||||
|  | { | ||||||
|  | 	std::string token, new_str = "          "; | ||||||
|  | 	int char_counter = 10; | ||||||
|  | 
 | ||||||
|  | 	for (size_t i = 0; i <= str.size(); i++) { | ||||||
|  | 		if (i < str.size()) | ||||||
|  | 			token += str[i]; | ||||||
|  | 		if (i == str.size() || str[i] == ';') { | ||||||
|  | 			if (char_counter + token.size() > 75) | ||||||
|  | 				new_str += "\n              ", char_counter = 14; | ||||||
|  | 			new_str += token, char_counter += token.size(); | ||||||
|  | 			token.clear(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return new_str; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
|  | @ -73,25 +78,6 @@ std::string add_echos_to_abc9_cmd(std::string str) | ||||||
| 	return new_str; | 	return new_str; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::string fold_abc9_cmd(std::string str) |  | ||||||
| { |  | ||||||
| 	std::string token, new_str = "          "; |  | ||||||
| 	int char_counter = 10; |  | ||||||
| 
 |  | ||||||
| 	for (size_t i = 0; i <= str.size(); i++) { |  | ||||||
| 		if (i < str.size()) |  | ||||||
| 			token += str[i]; |  | ||||||
| 		if (i == str.size() || str[i] == ';') { |  | ||||||
| 			if (char_counter + token.size() > 75) |  | ||||||
| 				new_str += "\n              ", char_counter = 14; |  | ||||||
| 			new_str += token, char_counter += token.size(); |  | ||||||
| 			token.clear(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return new_str; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) | std::string replace_tempdir(std::string text, std::string tempdir_name, bool show_tempdir) | ||||||
| { | { | ||||||
| 	if (show_tempdir) | 	if (show_tempdir) | ||||||
|  | @ -177,25 +163,21 @@ struct abc9_output_filter | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe_file, | void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe_file, | ||||||
| 		vector<int> lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, | 		vector<int> lut_costs, bool dff_mode, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, | ||||||
| 		bool show_tempdir, std::string box_file, std::string lut_file, | 		bool show_tempdir, std::string box_file, std::string lut_file, | ||||||
| 		std::string wire_delay, bool nomfs, std::string tempdir_name | 		std::string wire_delay, std::string tempdir_name | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	//FIXME:
 |  | ||||||
| 	//log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n",
 |  | ||||||
| 	//		module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str());
 |  | ||||||
| 
 |  | ||||||
| 	std::string abc9_script; | 	std::string abc9_script; | ||||||
| 
 | 
 | ||||||
| 	if (!lut_costs.empty()) | 	if (!lut_costs.empty()) | ||||||
| 		abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); | 		abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); | ||||||
| 	else | 	else if (!lut_file.empty()) | ||||||
| 	if (!lut_file.empty()) |  | ||||||
| 		abc9_script += stringf("read_lut %s; ", lut_file.c_str()); | 		abc9_script += stringf("read_lut %s; ", lut_file.c_str()); | ||||||
| 	else | 	else | ||||||
| 		log_abort(); | 		log_abort(); | ||||||
| 
 | 
 | ||||||
|  | 	log_assert(!box_file.empty()); | ||||||
| 	abc9_script += stringf("read_box %s; ", box_file.c_str()); | 	abc9_script += stringf("read_box %s; ", box_file.c_str()); | ||||||
| 	abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); | 	abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); | ||||||
| 
 | 
 | ||||||
|  | @ -211,7 +193,8 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe | ||||||
| 		} else | 		} else | ||||||
| 			abc9_script += stringf("source %s", script_file.c_str()); | 			abc9_script += stringf("source %s", script_file.c_str()); | ||||||
| 	} else if (!lut_costs.empty() || !lut_file.empty()) { | 	} else if (!lut_costs.empty() || !lut_file.empty()) { | ||||||
| 		abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; | 		abc9_script += fast_mode ? RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos) | ||||||
|  | 			: RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos); | ||||||
| 	} else | 	} else | ||||||
| 		log_abort(); | 		log_abort(); | ||||||
| 
 | 
 | ||||||
|  | @ -224,11 +207,26 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe | ||||||
| 	for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) | 	for (size_t pos = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) | ||||||
| 		abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); | 		abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); | ||||||
| 
 | 
 | ||||||
| 	if (nomfs) | 	std::string C; | ||||||
| 		for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) | 	if (design->scratchpad.count("abc9.if.C")) | ||||||
| 			abc9_script = abc9_script.erase(pos, strlen("&mfs")); | 		C = "-C " + design->scratchpad_get_string("abc9.if.C"); | ||||||
|  | 	for (size_t pos = abc9_script.find("{C}"); pos != std::string::npos; pos = abc9_script.find("{C}", pos)) | ||||||
|  | 		abc9_script = abc9_script.substr(0, pos) + C + abc9_script.substr(pos+3); | ||||||
| 
 | 
 | ||||||
| 	abc9_script += stringf("; &write -n %s/output.aig", tempdir_name.c_str()); | 	std::string R; | ||||||
|  | 	if (design->scratchpad.count("abc9.if.R")) | ||||||
|  | 		R = "-R " + design->scratchpad_get_string("abc9.if.R"); | ||||||
|  | 	for (size_t pos = abc9_script.find("{R}"); pos != std::string::npos; pos = abc9_script.find("{R}", pos)) | ||||||
|  | 		abc9_script = abc9_script.substr(0, pos) + R + abc9_script.substr(pos+3); | ||||||
|  | 
 | ||||||
|  | 	abc9_script += stringf("; &ps -l; &write -n %s/output.aig;", tempdir_name.c_str()); | ||||||
|  | 	if (design->scratchpad_get_bool("abc9.verify")) { | ||||||
|  | 		if (dff_mode) | ||||||
|  | 			abc9_script += "verify -s;"; | ||||||
|  | 		else | ||||||
|  | 			abc9_script += "verify;"; | ||||||
|  | 	} | ||||||
|  | 	abc9_script += "time"; | ||||||
| 	abc9_script = add_echos_to_abc9_cmd(abc9_script); | 	abc9_script = add_echos_to_abc9_cmd(abc9_script); | ||||||
| 
 | 
 | ||||||
| 	for (size_t i = 0; i+1 < abc9_script.size(); i++) | 	for (size_t i = 0; i+1 < abc9_script.size(); i++) | ||||||
|  | @ -308,12 +306,12 @@ struct Abc9ExePass : public Pass { | ||||||
| 		log("        replaced with blanks before the string is passed to ABC.\n"); | 		log("        replaced with blanks before the string is passed to ABC.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("        if no -script parameter is given, the following scripts are used:\n"); | 		log("        if no -script parameter is given, the following scripts are used:\n"); | ||||||
| 		log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); | 		log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default").substr(1,std::string::npos)).c_str()); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -fast\n"); | 		log("    -fast\n"); | ||||||
| 		log("        use different default scripts that are slightly faster (at the cost\n"); | 		log("        use different default scripts that are slightly faster (at the cost\n"); | ||||||
| 		log("        of output quality):\n"); | 		log("        of output quality):\n"); | ||||||
| 		log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); | 		log("%s\n", fold_abc9_cmd(RTLIL::constpad.at("abc9.script.default.fast").substr(1,std::string::npos)).c_str()); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -D <picoseconds>\n"); | 		log("    -D <picoseconds>\n"); | ||||||
| 		log("        set delay target. the string {D} in the default scripts above is\n"); | 		log("        set delay target. the string {D} in the default scripts above is\n"); | ||||||
|  | @ -374,9 +372,8 @@ struct Abc9ExePass : public Pass { | ||||||
| 		std::string script_file, clk_str, box_file, lut_file; | 		std::string script_file, clk_str, box_file, lut_file; | ||||||
| 		std::string delay_target, lutin_shared = "-S 1", wire_delay; | 		std::string delay_target, lutin_shared = "-S 1", wire_delay; | ||||||
| 		std::string tempdir_name; | 		std::string tempdir_name; | ||||||
| 		bool fast_mode = false; | 		bool fast_mode = false, dff_mode = false; | ||||||
| 		bool show_tempdir = false; | 		bool show_tempdir = false; | ||||||
| 		bool nomfs = false; |  | ||||||
| 		vector<int> lut_costs; | 		vector<int> lut_costs; | ||||||
| 
 | 
 | ||||||
| #if 0 | #if 0 | ||||||
|  | @ -400,12 +397,12 @@ struct Abc9ExePass : public Pass { | ||||||
| 		lut_arg = design->scratchpad_get_string("abc9.lut", lut_arg); | 		lut_arg = design->scratchpad_get_string("abc9.lut", lut_arg); | ||||||
| 		luts_arg = design->scratchpad_get_string("abc9.luts", luts_arg); | 		luts_arg = design->scratchpad_get_string("abc9.luts", luts_arg); | ||||||
| 		fast_mode = design->scratchpad_get_bool("abc9.fast", fast_mode); | 		fast_mode = design->scratchpad_get_bool("abc9.fast", fast_mode); | ||||||
|  | 		dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode); | ||||||
| 		show_tempdir = design->scratchpad_get_bool("abc9.showtmp", show_tempdir); | 		show_tempdir = design->scratchpad_get_bool("abc9.showtmp", show_tempdir); | ||||||
| 		box_file = design->scratchpad_get_string("abc9.box", box_file); | 		box_file = design->scratchpad_get_string("abc9.box", box_file); | ||||||
| 		if (design->scratchpad.count("abc9.W")) { | 		if (design->scratchpad.count("abc9.W")) { | ||||||
| 			wire_delay = "-W " + design->scratchpad_get_string("abc9.W"); | 			wire_delay = "-W " + design->scratchpad_get_string("abc9.W"); | ||||||
| 		} | 		} | ||||||
| 		nomfs = design->scratchpad_get_bool("abc9.nomfs", nomfs); |  | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
| 		char pwd [PATH_MAX]; | 		char pwd [PATH_MAX]; | ||||||
|  | @ -443,6 +440,10 @@ struct Abc9ExePass : public Pass { | ||||||
| 				fast_mode = true; | 				fast_mode = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (arg == "-dff") { | ||||||
|  | 				dff_mode = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			if (arg == "-showtmp") { | 			if (arg == "-showtmp") { | ||||||
| 				show_tempdir = true; | 				show_tempdir = true; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -455,10 +456,6 @@ struct Abc9ExePass : public Pass { | ||||||
| 				wire_delay = "-W " + args[++argidx]; | 				wire_delay = "-W " + args[++argidx]; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-nomfs") { |  | ||||||
| 				nomfs = true; |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 			if (arg == "-cwd" && argidx+1 < args.size()) { | 			if (arg == "-cwd" && argidx+1 < args.size()) { | ||||||
| 				tempdir_name = args[++argidx]; | 				tempdir_name = args[++argidx]; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -525,9 +522,9 @@ struct Abc9ExePass : public Pass { | ||||||
| 			log_cmd_error("abc9_exe '-cwd' option is mandatory.\n"); | 			log_cmd_error("abc9_exe '-cwd' option is mandatory.\n"); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 		abc9_module(design, script_file, exe_file, lut_costs, | 		abc9_module(design, script_file, exe_file, lut_costs, dff_mode, | ||||||
| 				delay_target, lutin_shared, fast_mode, show_tempdir, | 				delay_target, lutin_shared, fast_mode, show_tempdir, | ||||||
| 				box_file, lut_file, wire_delay, nomfs, tempdir_name); | 				box_file, lut_file, wire_delay, tempdir_name); | ||||||
| 	} | 	} | ||||||
| } Abc9ExePass; | } Abc9ExePass; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -91,7 +91,7 @@ void check(RTLIL::Design *design) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void break_scc(RTLIL::Module *module) | void mark_scc(RTLIL::Module *module) | ||||||
| { | { | ||||||
| 	// For every unique SCC found, (arbitrarily) find the first
 | 	// For every unique SCC found, (arbitrarily) find the first
 | ||||||
| 	//   cell in the component, and convert all wires driven by
 | 	//   cell in the component, and convert all wires driven by
 | ||||||
|  | @ -102,7 +102,8 @@ void break_scc(RTLIL::Module *module) | ||||||
| 		auto it = cell->attributes.find(ID(abc9_scc_id)); | 		auto it = cell->attributes.find(ID(abc9_scc_id)); | ||||||
| 		if (it == cell->attributes.end()) | 		if (it == cell->attributes.end()) | ||||||
| 			continue; | 			continue; | ||||||
| 		auto r = ids_seen.insert(it->second); | 		auto id = it->second; | ||||||
|  | 		auto r = ids_seen.insert(id); | ||||||
| 		cell->attributes.erase(it); | 		cell->attributes.erase(it); | ||||||
| 		if (!r.second) | 		if (!r.second) | ||||||
| 			continue; | 			continue; | ||||||
|  | @ -111,30 +112,8 @@ void break_scc(RTLIL::Module *module) | ||||||
| 			if (cell->output(c.first)) { | 			if (cell->output(c.first)) { | ||||||
| 				SigBit b = c.second.as_bit(); | 				SigBit b = c.second.as_bit(); | ||||||
| 				Wire *w = b.wire; | 				Wire *w = b.wire; | ||||||
| 				if (w->port_input) { | 				w->set_bool_attribute(ID::keep); | ||||||
| 					// In this case, hopefully the loop break has been already created
 | 				w->attributes[ID(abc9_scc_id)] = id.as_int(); | ||||||
| 					// Get the non-prefixed wire
 |  | ||||||
| 					Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str())); |  | ||||||
| 					log_assert(wo != nullptr); |  | ||||||
| 					log_assert(wo->port_output); |  | ||||||
| 					log_assert(b.offset < GetSize(wo)); |  | ||||||
| 					c.second = RTLIL::SigBit(wo, b.offset); |  | ||||||
| 				} |  | ||||||
| 				else { |  | ||||||
| 					// Create a new output/input loop break
 |  | ||||||
| 					w->port_input = true; |  | ||||||
| 					w = module->wire(stringf("%s.abco", w->name.c_str())); |  | ||||||
| 					if (!w) { |  | ||||||
| 						w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire)); |  | ||||||
| 						w->port_output = true; |  | ||||||
| 					} |  | ||||||
| 					else { |  | ||||||
| 						log_assert(w->port_input); |  | ||||||
| 						log_assert(b.offset < GetSize(w)); |  | ||||||
| 					} |  | ||||||
| 					w->set_bool_attribute(ID(abc9_scc_break)); |  | ||||||
| 					c.second = RTLIL::SigBit(w, b.offset); |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -142,28 +121,6 @@ void break_scc(RTLIL::Module *module) | ||||||
| 	module->fixup_ports(); | 	module->fixup_ports(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void unbreak_scc(RTLIL::Module *module) |  | ||||||
| { |  | ||||||
| 	// Now 'unexpose' those wires by undoing
 |  | ||||||
| 	// the expose operation -- remove them from PO/PI
 |  | ||||||
| 	// and re-connecting them back together
 |  | ||||||
| 	for (auto wire : module->wires()) { |  | ||||||
| 		auto it = wire->attributes.find(ID(abc9_scc_break)); |  | ||||||
| 		if (it != wire->attributes.end()) { |  | ||||||
| 			wire->attributes.erase(it); |  | ||||||
| 			log_assert(wire->port_output); |  | ||||||
| 			wire->port_output = false; |  | ||||||
| 			std::string name = wire->name.str(); |  | ||||||
| 			RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5)); |  | ||||||
| 			log_assert(i_wire); |  | ||||||
| 			log_assert(i_wire->port_input); |  | ||||||
| 			i_wire->port_input = false; |  | ||||||
| 			module->connect(i_wire, wire); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	module->fixup_ports(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void prep_dff(RTLIL::Module *module) | void prep_dff(RTLIL::Module *module) | ||||||
| { | { | ||||||
| 	auto design = module->design; | 	auto design = module->design; | ||||||
|  | @ -244,7 +201,7 @@ void prep_dff(RTLIL::Module *module) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void prep_holes(RTLIL::Module *module, bool dff) | void prep_xaiger(RTLIL::Module *module, bool dff) | ||||||
| { | { | ||||||
| 	auto design = module->design; | 	auto design = module->design; | ||||||
| 	log_assert(design); | 	log_assert(design); | ||||||
|  | @ -253,7 +210,7 @@ void prep_holes(RTLIL::Module *module, bool dff) | ||||||
| 
 | 
 | ||||||
| 	dict<SigBit, pool<IdString>> bit_drivers, bit_users; | 	dict<SigBit, pool<IdString>> bit_drivers, bit_users; | ||||||
| 	TopoSort<IdString, RTLIL::sort_by_id_str> toposort; | 	TopoSort<IdString, RTLIL::sort_by_id_str> toposort; | ||||||
| 	bool abc9_box_seen = false; | 	dict<IdString, std::vector<IdString>> box_ports; | ||||||
| 
 | 
 | ||||||
| 	for (auto cell : module->cells()) { | 	for (auto cell : module->cells()) { | ||||||
| 		if (cell->type == "$__ABC9_FF_") | 		if (cell->type == "$__ABC9_FF_") | ||||||
|  | @ -266,7 +223,40 @@ void prep_holes(RTLIL::Module *module, bool dff) | ||||||
| 			abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); | 			abc9_flop = inst_module->get_bool_attribute("\\abc9_flop"); | ||||||
| 			if (abc9_flop && !dff) | 			if (abc9_flop && !dff) | ||||||
| 				continue; | 				continue; | ||||||
| 			abc9_box_seen = abc9_box; | 
 | ||||||
|  | 			auto r = box_ports.insert(cell->type); | ||||||
|  | 			if (r.second) { | ||||||
|  | 				// Make carry in the last PI, and carry out the last PO
 | ||||||
|  | 				//   since ABC requires it this way
 | ||||||
|  | 				IdString carry_in, carry_out; | ||||||
|  | 				for (const auto &port_name : inst_module->ports) { | ||||||
|  | 					auto w = inst_module->wire(port_name); | ||||||
|  | 					log_assert(w); | ||||||
|  | 					if (w->get_bool_attribute("\\abc9_carry")) { | ||||||
|  | 						if (w->port_input) { | ||||||
|  | 							if (carry_in != IdString()) | ||||||
|  | 								log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(inst_module)); | ||||||
|  | 							carry_in = port_name; | ||||||
|  | 						} | ||||||
|  | 						if (w->port_output) { | ||||||
|  | 							if (carry_out != IdString()) | ||||||
|  | 								log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(inst_module)); | ||||||
|  | 							carry_out = port_name; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					else | ||||||
|  | 						r.first->second.push_back(port_name); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (carry_in != IdString() && carry_out == IdString()) | ||||||
|  | 					log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(inst_module)); | ||||||
|  | 				if (carry_in == IdString() && carry_out != IdString()) | ||||||
|  | 					log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(inst_module)); | ||||||
|  | 				if (carry_in != IdString()) { | ||||||
|  | 					r.first->second.push_back(carry_in); | ||||||
|  | 					r.first->second.push_back(carry_out); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		else if (!yosys_celltypes.cell_known(cell->type)) | 		else if (!yosys_celltypes.cell_known(cell->type)) | ||||||
| 			continue; | 			continue; | ||||||
|  | @ -284,7 +274,7 @@ void prep_holes(RTLIL::Module *module, bool dff) | ||||||
| 		toposort.node(cell->name); | 		toposort.node(cell->name); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!abc9_box_seen) | 	if (box_ports.empty()) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	for (auto &it : bit_users) | 	for (auto &it : bit_users) | ||||||
|  | @ -312,7 +302,13 @@ void prep_holes(RTLIL::Module *module, bool dff) | ||||||
| 
 | 
 | ||||||
| 	log_assert(no_loops); | 	log_assert(no_loops); | ||||||
| 
 | 
 | ||||||
| 	vector<Cell*> box_list; | 	RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str())); | ||||||
|  | 	log_assert(holes_module); | ||||||
|  | 	holes_module->set_bool_attribute("\\abc9_holes"); | ||||||
|  | 
 | ||||||
|  | 	dict<IdString, Cell*> cell_cache; | ||||||
|  | 
 | ||||||
|  | 	int port_id = 1, box_count = 0; | ||||||
| 	for (auto cell_name : toposort.sorted) { | 	for (auto cell_name : toposort.sorted) { | ||||||
| 		RTLIL::Cell *cell = module->cell(cell_name); | 		RTLIL::Cell *cell = module->cell(cell_name); | ||||||
| 		log_assert(cell); | 		log_assert(cell); | ||||||
|  | @ -321,92 +317,16 @@ void prep_holes(RTLIL::Module *module, bool dff) | ||||||
| 		if (!box_module || !box_module->attributes.count("\\abc9_box_id")) | 		if (!box_module || !box_module->attributes.count("\\abc9_box_id")) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); | 		cell->attributes["\\abc9_box_seq"] = box_count++; | ||||||
| 
 | 
 | ||||||
| 		// Fully pad all unused input connections of this box cell with S0
 | 		IdString derived_name = box_module->derive(design, cell->parameters); | ||||||
| 		// Fully pad all undriven output connections of this box cell with anonymous wires
 | 		box_module = design->module(derived_name); | ||||||
| 		for (const auto &port_name : box_module->ports) { |  | ||||||
| 			RTLIL::Wire* w = box_module->wire(port_name); |  | ||||||
| 			log_assert(w); |  | ||||||
| 			auto it = cell->connections_.find(port_name); |  | ||||||
| 			if (w->port_input) { |  | ||||||
| 				RTLIL::SigSpec rhs; |  | ||||||
| 				if (it != cell->connections_.end()) { |  | ||||||
| 					if (GetSize(it->second) < GetSize(w)) |  | ||||||
| 						it->second.append(RTLIL::SigSpec(State::S0, GetSize(w)-GetSize(it->second))); |  | ||||||
| 					rhs = it->second; |  | ||||||
| 				} |  | ||||||
| 				else { |  | ||||||
| 					rhs = RTLIL::SigSpec(State::S0, GetSize(w)); |  | ||||||
| 					cell->setPort(port_name, rhs); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			if (w->port_output) { |  | ||||||
| 				RTLIL::SigSpec rhs; |  | ||||||
| 				auto it = cell->connections_.find(w->name); |  | ||||||
| 				if (it != cell->connections_.end()) { |  | ||||||
| 					if (GetSize(it->second) < GetSize(w)) |  | ||||||
| 						it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second))); |  | ||||||
| 					rhs = it->second; |  | ||||||
| 				} |  | ||||||
| 				else { |  | ||||||
| 					Wire *wire = module->addWire(NEW_ID, GetSize(w)); |  | ||||||
| 					if (blackbox) |  | ||||||
| 						wire->set_bool_attribute(ID(abc9_padding)); |  | ||||||
| 					rhs = wire; |  | ||||||
| 					cell->setPort(port_name, rhs); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		cell->attributes["\\abc9_box_seq"] = box_list.size(); |  | ||||||
| 		//log_debug("%s.%s is box %d\n", log_id(module), log_id(cell), box_list.size());
 |  | ||||||
| 		box_list.emplace_back(cell); |  | ||||||
| 	} |  | ||||||
| 	log_assert(!box_list.empty()); |  | ||||||
| 
 |  | ||||||
| 	RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str())); |  | ||||||
| 	log_assert(holes_module); |  | ||||||
| 	holes_module->set_bool_attribute("\\abc9_holes"); |  | ||||||
| 
 |  | ||||||
| 	dict<IdString, Cell*> cell_cache; |  | ||||||
| 	dict<IdString, std::vector<IdString>> box_ports; |  | ||||||
| 
 |  | ||||||
| 	int port_id = 1; |  | ||||||
| 	for (auto cell : box_list) { |  | ||||||
| 		RTLIL::Module* orig_box_module = design->module(cell->type); |  | ||||||
| 		log_assert(orig_box_module); |  | ||||||
| 		IdString derived_name = orig_box_module->derive(design, cell->parameters); |  | ||||||
| 		RTLIL::Module* box_module = design->module(derived_name); |  | ||||||
| 		//cell->type = derived_name;
 |  | ||||||
| 		//cell->parameters.clear();
 |  | ||||||
| 
 | 
 | ||||||
| 		auto r = cell_cache.insert(derived_name); | 		auto r = cell_cache.insert(derived_name); | ||||||
| 		auto &holes_cell = r.first->second; | 		auto &holes_cell = r.first->second; | ||||||
| 		if (r.second) { | 		if (r.second) { | ||||||
| 			auto r2 = box_ports.insert(cell->type); | 			if (box_module->has_processes()) | ||||||
| 			if (r2.second) { | 				Pass::call_on_module(design, box_module, "proc"); | ||||||
| 				// Make carry in the last PI, and carry out the last PO
 |  | ||||||
| 				//   since ABC requires it this way
 |  | ||||||
| 				IdString carry_in, carry_out; |  | ||||||
| 				for (const auto &port_name : box_module->ports) { |  | ||||||
| 					auto w = box_module->wire(port_name); |  | ||||||
| 					log_assert(w); |  | ||||||
| 					if (w->get_bool_attribute("\\abc9_carry")) { |  | ||||||
| 						if (w->port_input) |  | ||||||
| 							carry_in = port_name; |  | ||||||
| 						if (w->port_output) |  | ||||||
| 							carry_out = port_name; |  | ||||||
| 					} |  | ||||||
| 					else |  | ||||||
| 						r2.first->second.push_back(port_name); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if (carry_in != IdString()) { |  | ||||||
| 					r2.first->second.push_back(carry_in); |  | ||||||
| 					r2.first->second.push_back(carry_out); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			if (box_module->get_bool_attribute("\\whitebox")) { | 			if (box_module->get_bool_attribute("\\whitebox")) { | ||||||
| 				holes_cell = holes_module->addCell(cell->name, derived_name); | 				holes_cell = holes_module->addCell(cell->name, derived_name); | ||||||
|  | @ -655,6 +575,8 @@ void reintegrate(RTLIL::Module *module) | ||||||
| 	pool<IdString> delay_boxes; | 	pool<IdString> delay_boxes; | ||||||
| 	std::vector<Cell*> boxes; | 	std::vector<Cell*> boxes; | ||||||
| 	for (auto cell : module->cells().to_vector()) { | 	for (auto cell : module->cells().to_vector()) { | ||||||
|  | 		if (cell->has_keep_attr()) | ||||||
|  | 			continue; | ||||||
| 		if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) | 		if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) | ||||||
| 			module->remove(cell); | 			module->remove(cell); | ||||||
| 		else if (cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { | 		else if (cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { | ||||||
|  | @ -680,6 +602,8 @@ void reintegrate(RTLIL::Module *module) | ||||||
| 			RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A); | 			RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A); | ||||||
| 			RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y); | 			RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y); | ||||||
| 			bit_users[a_bit].insert(mapped_cell->name); | 			bit_users[a_bit].insert(mapped_cell->name); | ||||||
|  | 			// Ignore inouts for topo ordering
 | ||||||
|  | 			if (y_bit.wire && !(y_bit.wire->port_input && y_bit.wire->port_output)) | ||||||
| 				bit_drivers[y_bit].insert(mapped_cell->name); | 				bit_drivers[y_bit].insert(mapped_cell->name); | ||||||
| 
 | 
 | ||||||
| 			if (!a_bit.wire) { | 			if (!a_bit.wire) { | ||||||
|  | @ -698,16 +622,16 @@ void reintegrate(RTLIL::Module *module) | ||||||
| 					// (TODO: Optimise by not cloning unless will increase depth)
 | 					// (TODO: Optimise by not cloning unless will increase depth)
 | ||||||
| 					RTLIL::IdString driver_name; | 					RTLIL::IdString driver_name; | ||||||
| 					if (GetSize(a_bit.wire) == 1) | 					if (GetSize(a_bit.wire) == 1) | ||||||
| 						driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); | 						driver_name = stringf("$lut%s", a_bit.wire->name.c_str()); | ||||||
| 					else | 					else | ||||||
| 						driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); | 						driver_name = stringf("$lut%s[%d]", a_bit.wire->name.c_str(), a_bit.offset); | ||||||
| 					driver_lut = mapped_mod->cell(driver_name); | 					driver_lut = mapped_mod->cell(driver_name); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (!driver_lut) { | 				if (!driver_lut) { | ||||||
| 					// If a driver couldn't be found (could be from PI or box CI)
 | 					// If a driver couldn't be found (could be from PI or box CI)
 | ||||||
| 					// then implement using a LUT
 | 					// then implement using a LUT
 | ||||||
| 					RTLIL::Cell *cell = module->addLut(remap_name(stringf("%s$lut", mapped_cell->name.c_str())), | 					RTLIL::Cell *cell = module->addLut(remap_name(stringf("$lut%s", mapped_cell->name.c_str())), | ||||||
| 							RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), | 							RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), | ||||||
| 							RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), | 							RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), | ||||||
| 							RTLIL::Const::from_string("01")); | 							RTLIL::Const::from_string("01")); | ||||||
|  | @ -745,6 +669,8 @@ void reintegrate(RTLIL::Module *module) | ||||||
| 				} | 				} | ||||||
| 				if (cell->output(mapped_conn.first)) | 				if (cell->output(mapped_conn.first)) | ||||||
| 					for (auto i : mapped_conn.second) | 					for (auto i : mapped_conn.second) | ||||||
|  | 						// Ignore inouts for topo ordering
 | ||||||
|  | 						if (i.wire && !(i.wire->port_input && i.wire->port_output)) | ||||||
| 							bit_drivers[i].insert(mapped_cell->name); | 							bit_drivers[i].insert(mapped_cell->name); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -788,6 +714,8 @@ void reintegrate(RTLIL::Module *module) | ||||||
| 				for (const auto &i : inputs) | 				for (const auto &i : inputs) | ||||||
| 					bit_users[i].insert(mapped_cell->name); | 					bit_users[i].insert(mapped_cell->name); | ||||||
| 				for (const auto &i : outputs) | 				for (const auto &i : outputs) | ||||||
|  | 					// Ignore inouts for topo ordering
 | ||||||
|  | 					if (i.wire && !(i.wire->port_input && i.wire->port_output)) | ||||||
| 						bit_drivers[i].insert(mapped_cell->name); | 						bit_drivers[i].insert(mapped_cell->name); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -886,21 +814,25 @@ void reintegrate(RTLIL::Module *module) | ||||||
| 
 | 
 | ||||||
| 	// Stitch in mapped_mod's inputs/outputs into module
 | 	// Stitch in mapped_mod's inputs/outputs into module
 | ||||||
| 	for (auto port : mapped_mod->ports) { | 	for (auto port : mapped_mod->ports) { | ||||||
| 		RTLIL::Wire *w = mapped_mod->wire(port); | 		RTLIL::Wire *mapped_wire = mapped_mod->wire(port); | ||||||
| 		RTLIL::Wire *wire = module->wire(port); | 		RTLIL::Wire *wire = module->wire(port); | ||||||
| 		log_assert(wire); | 		log_assert(wire); | ||||||
|  | 		if (wire->attributes.erase(ID(abc9_scc_id))) { | ||||||
|  | 			auto r YS_ATTRIBUTE(unused) = wire->attributes.erase(ID::keep); | ||||||
|  | 			log_assert(r); | ||||||
|  | 		} | ||||||
| 		RTLIL::Wire *remap_wire = module->wire(remap_name(port)); | 		RTLIL::Wire *remap_wire = module->wire(remap_name(port)); | ||||||
| 		RTLIL::SigSpec signal(wire, 0, GetSize(remap_wire)); | 		RTLIL::SigSpec signal(wire, 0, GetSize(remap_wire)); | ||||||
| 		log_assert(GetSize(signal) >= GetSize(remap_wire)); | 		log_assert(GetSize(signal) >= GetSize(remap_wire)); | ||||||
| 
 | 
 | ||||||
| 		RTLIL::SigSig conn; | 		RTLIL::SigSig conn; | ||||||
| 		if (w->port_output) { | 		if (mapped_wire->port_output) { | ||||||
| 			conn.first = signal; | 			conn.first = signal; | ||||||
| 			conn.second = remap_wire; | 			conn.second = remap_wire; | ||||||
| 			out_wires++; | 			out_wires++; | ||||||
| 			module->connect(conn); | 			module->connect(conn); | ||||||
| 		} | 		} | ||||||
| 		else if (w->port_input) { | 		else if (mapped_wire->port_input) { | ||||||
| 			conn.first = remap_wire; | 			conn.first = remap_wire; | ||||||
| 			conn.second = signal; | 			conn.second = signal; | ||||||
| 			in_wires++; | 			in_wires++; | ||||||
|  | @ -996,6 +928,35 @@ struct Abc9OpsPass : public Pass { | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    abc9_ops [options] [selection]\n"); | 		log("    abc9_ops [options] [selection]\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("This pass contains a set of supporting operations for use during ABC technology\n"); | ||||||
|  | 		log("mapping, and is expected to be called in conjunction with other operations from\n"); | ||||||
|  | 		log("the `abc9' script pass. Only fully-selected modules are supported.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -mark_scc\n"); | ||||||
|  | 		log("        for an arbitrarily chosen cell in each unique SCC of each selected module\n"); | ||||||
|  | 		log("        (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all\n"); | ||||||
|  | 		log("        wires driven by this cell's outputs with a (* keep *) attribute in order\n"); | ||||||
|  | 		log("        to break the SCC. this temporary attribute will be removed on -reintegrate.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -prep_xaiger\n"); | ||||||
|  | 		log("        prepare the design for XAIGER output. this includes computing the\n"); | ||||||
|  | 		log("        topological ordering of ABC9 boxes, as well as preparing the\n"); | ||||||
|  | 		log("        '<module-name>$holes' module that contains the logic behaviour of ABC9\n"); | ||||||
|  | 		log("        whiteboxes.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -dff\n"); | ||||||
|  | 		log("        consider flop cells (those instantiating modules marked with (* abc9_flop *)\n"); | ||||||
|  | 		log("        during -prep_xaiger.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -prep_dff\n"); | ||||||
|  | 		log("        compute the clock domain and initial value of each flop in the design.\n"); | ||||||
|  | 		log("        process the '$holes' module to support clock-enable functionality.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -reintegrate\n"); | ||||||
|  | 		log("        for each selected module, re-intergrate the module '<module-name>$abc9'\n"); | ||||||
|  | 		log("        by first recovering ABC9 boxes, and then stitching in the remaining primary\n"); | ||||||
|  | 		log("        inputs and outputs.\n"); | ||||||
|  | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
|  | @ -1003,13 +964,12 @@ struct Abc9OpsPass : public Pass { | ||||||
| 
 | 
 | ||||||
| 		bool check_mode = false; | 		bool check_mode = false; | ||||||
| 		bool prep_times_mode = false; | 		bool prep_times_mode = false; | ||||||
| 		bool break_scc_mode = false; | 		bool mark_scc_mode = false; | ||||||
| 		bool unbreak_scc_mode = false; |  | ||||||
| 		bool prep_holes_mode = false; |  | ||||||
| 		bool prep_dff_mode = false; | 		bool prep_dff_mode = false; | ||||||
| 		std::string write_box_src, write_box_dst; | 		bool prep_xaiger_mode = false; | ||||||
| 		bool reintegrate_mode = false; | 		bool reintegrate_mode = false; | ||||||
| 		bool dff_mode = false; | 		bool dff_mode = false; | ||||||
|  | 		std::string write_box_src, write_box_dst; | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
| 		for (argidx = 1; argidx < args.size(); argidx++) { | 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||||
|  | @ -1018,20 +978,16 @@ struct Abc9OpsPass : public Pass { | ||||||
| 				check_mode = true; | 				check_mode = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-break_scc") { | 			if (arg == "-mark_scc") { | ||||||
| 				break_scc_mode = true; | 				mark_scc_mode = true; | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 			if (arg == "-unbreak_scc") { |  | ||||||
| 				unbreak_scc_mode = true; |  | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-prep_dff") { | 			if (arg == "-prep_dff") { | ||||||
| 				prep_dff_mode = true; | 				prep_dff_mode = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-prep_holes") { | 			if (arg == "-prep_xaiger") { | ||||||
| 				prep_holes_mode = true; | 				prep_xaiger_mode = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (arg == "-prep_times") { | 			if (arg == "-prep_times") { | ||||||
|  | @ -1057,11 +1013,11 @@ struct Abc9OpsPass : public Pass { | ||||||
| 		} | 		} | ||||||
| 		extra_args(args, argidx, design); | 		extra_args(args, argidx, design); | ||||||
| 
 | 
 | ||||||
| 		if (!(check_mode || break_scc_mode || unbreak_scc_mode || prep_times_mode || prep_holes_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode)) | 		if (!(check_mode || mark_scc_mode || prep_times_mode || prep_xaiger_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode)) | ||||||
| 			log_cmd_error("At least one of -check, -{,un}break_scc, -prep_{times,holes,dff}, -write_box, -reintegrate must be specified.\n"); | 			log_cmd_error("At least one of -check, -mark_scc, -prep_{times,xaiger,dff}, -write_box, -reintegrate must be specified.\n"); | ||||||
| 
 | 
 | ||||||
| 		if (dff_mode && !prep_holes_mode) | 		if (dff_mode && !prep_xaiger_mode) | ||||||
| 			log_cmd_error("'-dff' option is only relevant for -prep_holes.\n"); | 			log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n"); | ||||||
| 
 | 
 | ||||||
| 		if (check_mode) | 		if (check_mode) | ||||||
| 			check(design); | 			check(design); | ||||||
|  | @ -1080,16 +1036,14 @@ struct Abc9OpsPass : public Pass { | ||||||
| 			if (!design->selected_whole_module(mod)) | 			if (!design->selected_whole_module(mod)) | ||||||
| 				log_error("Can't handle partially selected module %s!\n", log_id(mod)); | 				log_error("Can't handle partially selected module %s!\n", log_id(mod)); | ||||||
| 
 | 
 | ||||||
| 			if (break_scc_mode) |  | ||||||
| 				break_scc(mod); |  | ||||||
| 			if (unbreak_scc_mode) |  | ||||||
| 				unbreak_scc(mod); |  | ||||||
| 			if (prep_holes_mode) |  | ||||||
| 				prep_holes(mod, dff_mode); |  | ||||||
| 			if (prep_dff_mode) |  | ||||||
| 				prep_dff(mod); |  | ||||||
| 			if (!write_box_src.empty()) | 			if (!write_box_src.empty()) | ||||||
| 				write_box(mod, write_box_src, write_box_dst); | 				write_box(mod, write_box_src, write_box_dst); | ||||||
|  | 			if (mark_scc_mode) | ||||||
|  | 				mark_scc(mod); | ||||||
|  | 			if (prep_dff_mode) | ||||||
|  | 				prep_dff(mod); | ||||||
|  | 			if (prep_xaiger_mode) | ||||||
|  | 				prep_xaiger(mod, dff_mode); | ||||||
| 			if (reintegrate_mode) | 			if (reintegrate_mode) | ||||||
| 				reintegrate(mod); | 				reintegrate(mod); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -102,8 +102,8 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	string top_opt, blif_file, edif_file, json_file, abc, device_opt; | 	string top_opt, blif_file, edif_file, json_file, device_opt; | ||||||
| 	bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr; | 	bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9; | ||||||
| 	int min_ce_use; | 	int min_ce_use; | ||||||
| 
 | 
 | ||||||
| 	void clear_flags() YS_OVERRIDE | 	void clear_flags() YS_OVERRIDE | ||||||
|  | @ -122,7 +122,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 		noabc = false; | 		noabc = false; | ||||||
| 		abc2 = false; | 		abc2 = false; | ||||||
| 		vpr = false; | 		vpr = false; | ||||||
| 		abc = "abc"; | 		abc9 = false; | ||||||
| 		device_opt = "hx"; | 		device_opt = "hx"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -207,7 +207,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-abc9") { | 			if (args[argidx] == "-abc9") { | ||||||
| 				abc = "abc9"; | 				abc9 = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-device" && argidx+1 < args.size()) { | 			if (args[argidx] == "-device" && argidx+1 < args.size()) { | ||||||
|  | @ -223,7 +223,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 		if (device_opt != "hx" && device_opt != "lp" && device_opt !="u") | 		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_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str()); | ||||||
| 
 | 
 | ||||||
| 		if (abc == "abc9" && retime) | 		if (abc9 && retime) | ||||||
| 			log_cmd_error("-retime option not currently compatible with -abc9!\n"); | 			log_cmd_error("-retime option not currently compatible with -abc9!\n"); | ||||||
| 
 | 
 | ||||||
| 		log_header(design, "Executing SYNTH_ICE40 pass.\n"); | 		log_header(design, "Executing SYNTH_ICE40 pass.\n"); | ||||||
|  | @ -316,7 +316,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 				run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); | 				run("techmap -map +/techmap.v -map +/ice40/arith_map.v"); | ||||||
| 			} | 			} | ||||||
| 			if (retime || help_mode) | 			if (retime || help_mode) | ||||||
| 				run(abc + " -dff -D 1", "(only if -retime)"); | 				run("abc -dff -D 1", "(only if -retime)"); | ||||||
| 			run("ice40_opt"); | 			run("ice40_opt"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -340,7 +340,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 		if (check_label("map_luts")) | 		if (check_label("map_luts")) | ||||||
| 		{ | 		{ | ||||||
| 			if (abc2 || help_mode) { | 			if (abc2 || help_mode) { | ||||||
| 				run(abc, "      (only if -abc2)"); | 				run("abc", "      (only if -abc2)"); | ||||||
| 				run("ice40_opt", "(only if -abc2)"); | 				run("ice40_opt", "(only if -abc2)"); | ||||||
| 			} | 			} | ||||||
| 			run("techmap -map +/ice40/latches_map.v"); | 			run("techmap -map +/ice40/latches_map.v"); | ||||||
|  | @ -349,7 +349,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 				run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)"); | 				run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)"); | ||||||
| 			} | 			} | ||||||
| 			if (!noabc) { | 			if (!noabc) { | ||||||
| 				if (abc == "abc9") { | 				if (abc9) { | ||||||
| 					run("read_verilog -icells -lib +/ice40/abc9_model.v"); | 					run("read_verilog -icells -lib +/ice40/abc9_model.v"); | ||||||
| 					int wire_delay; | 					int wire_delay; | ||||||
| 					if (device_opt == "lp") | 					if (device_opt == "lp") | ||||||
|  | @ -358,10 +358,10 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 						wire_delay = 750; | 						wire_delay = 750; | ||||||
| 					else | 					else | ||||||
| 						wire_delay = 250; | 						wire_delay = 250; | ||||||
| 					run(abc + stringf(" -W %d -lut +/ice40/abc9_%s.lut -box +/ice40/abc9_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)"); | 					run(stringf("abc9 -W %d -lut +/ice40/abc9_%s.lut -box +/ice40/abc9_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str())); | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 					run(abc + " -dress -lut 4", "(skip if -noabc)"); | 					run("abc -dress -lut 4", "(skip if -noabc)"); | ||||||
| 			} | 			} | ||||||
| 			run("ice40_wrapcarry -unwrap"); | 			run("ice40_wrapcarry -unwrap"); | ||||||
| 			run("techmap -D NO_LUT -map +/ice40/cells_map.v"); | 			run("techmap -D NO_LUT -map +/ice40/cells_map.v"); | ||||||
|  |  | ||||||
|  | @ -74,7 +74,7 @@ | ||||||
| // (e) a special _TECHMAP_REPLACE_.abc9_ff.Q wire that will be used for feedback | // (e) a special _TECHMAP_REPLACE_.abc9_ff.Q wire that will be used for feedback | ||||||
| //     into the (combinatorial) FD* cell to facilitate clock-enable behaviour | //     into the (combinatorial) FD* cell to facilitate clock-enable behaviour | ||||||
| 
 | 
 | ||||||
| module FDRE (output Q, input C, CE, D, R); | module FDRE (output Q, (* techmap_autopurge *) input C, CE, D, R); | ||||||
|   parameter [0:0] INIT = 1'b0; |   parameter [0:0] INIT = 1'b0; | ||||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; |   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||||
|   parameter [0:0] IS_D_INVERTED = 1'b0; |   parameter [0:0] IS_D_INVERTED = 1'b0; | ||||||
|  | @ -110,7 +110,7 @@ module FDRE (output Q, input C, CE, D, R); | ||||||
|   wire [0:0] abc9_ff.init = 1'b0; |   wire [0:0] abc9_ff.init = 1'b0; | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; |   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; | ||||||
| endmodule | endmodule | ||||||
| module FDRE_1 (output Q, input C, CE, D, R); | module FDRE_1 (output Q, (* techmap_autopurge *) input C, CE, D, R); | ||||||
|   parameter [0:0] INIT = 1'b0; |   parameter [0:0] INIT = 1'b0; | ||||||
|   wire QQ, $Q; |   wire QQ, $Q; | ||||||
|   generate if (INIT == 1'b1) begin |   generate if (INIT == 1'b1) begin | ||||||
|  | @ -138,7 +138,7 @@ module FDRE_1 (output Q, input C, CE, D, R); | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; |   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module FDSE (output Q, input C, CE, D, S); | module FDSE (output Q, (* techmap_autopurge *) input C, CE, D, S); | ||||||
|   parameter [0:0] INIT = 1'b1; |   parameter [0:0] INIT = 1'b1; | ||||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; |   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||||
|   parameter [0:0] IS_D_INVERTED = 1'b0; |   parameter [0:0] IS_D_INVERTED = 1'b0; | ||||||
|  | @ -173,7 +173,7 @@ module FDSE (output Q, input C, CE, D, S); | ||||||
|   wire [0:0] abc9_ff.init = 1'b0; |   wire [0:0] abc9_ff.init = 1'b0; | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; |   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; | ||||||
| endmodule | endmodule | ||||||
| module FDSE_1 (output Q, input C, CE, D, S); | module FDSE_1 (output Q, (* techmap_autopurge *) input C, CE, D, S); | ||||||
|   parameter [0:0] INIT = 1'b1; |   parameter [0:0] INIT = 1'b1; | ||||||
|   wire QQ, $Q; |   wire QQ, $Q; | ||||||
|   generate if (INIT == 1'b1) begin |   generate if (INIT == 1'b1) begin | ||||||
|  | @ -200,7 +200,7 @@ module FDSE_1 (output Q, input C, CE, D, S); | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; |   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module FDCE (output Q, input C, CE, D, CLR); | module FDCE (output Q, (* techmap_autopurge *) input C, CE, D, CLR); | ||||||
|   parameter [0:0] INIT = 1'b0; |   parameter [0:0] INIT = 1'b0; | ||||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; |   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||||
|   parameter [0:0] IS_D_INVERTED = 1'b0; |   parameter [0:0] IS_D_INVERTED = 1'b0; | ||||||
|  | @ -249,7 +249,7 @@ module FDCE (output Q, input C, CE, D, CLR); | ||||||
|   wire [0:0] abc9_ff.init = 1'b0; |   wire [0:0] abc9_ff.init = 1'b0; | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; |   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; | ||||||
| endmodule | endmodule | ||||||
| module FDCE_1 (output Q, input C, CE, D, CLR); | module FDCE_1 (output Q, (* techmap_autopurge *) input C, CE, D, CLR); | ||||||
|   parameter [0:0] INIT = 1'b0; |   parameter [0:0] INIT = 1'b0; | ||||||
|   wire QQ, $Q, $QQ; |   wire QQ, $Q, $QQ; | ||||||
|   generate if (INIT == 1'b1) begin |   generate if (INIT == 1'b1) begin | ||||||
|  | @ -288,7 +288,7 @@ module FDCE_1 (output Q, input C, CE, D, CLR); | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; |   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module FDPE (output Q, input C, CE, D, PRE); | module FDPE (output Q, (* techmap_autopurge *) input C, CE, D, PRE); | ||||||
|   parameter [0:0] INIT = 1'b1; |   parameter [0:0] INIT = 1'b1; | ||||||
|   parameter [0:0] IS_C_INVERTED = 1'b0; |   parameter [0:0] IS_C_INVERTED = 1'b0; | ||||||
|   parameter [0:0] IS_D_INVERTED = 1'b0; |   parameter [0:0] IS_D_INVERTED = 1'b0; | ||||||
|  | @ -335,7 +335,7 @@ module FDPE (output Q, input C, CE, D, PRE); | ||||||
|   wire [0:0] abc9_ff.init = 1'b0; |   wire [0:0] abc9_ff.init = 1'b0; | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; |   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; | ||||||
| endmodule | endmodule | ||||||
| module FDPE_1 (output Q, input C, CE, D, PRE); | module FDPE_1 (output Q, (* techmap_autopurge *) input C, CE, D, PRE); | ||||||
|   parameter [0:0] INIT = 1'b1; |   parameter [0:0] INIT = 1'b1; | ||||||
|   wire QQ, $Q, $QQ; |   wire QQ, $Q, $QQ; | ||||||
|   generate if (INIT == 1'b1) begin |   generate if (INIT == 1'b1) begin | ||||||
|  |  | ||||||
|  | @ -26,13 +26,16 @@ | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| #define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate
 |  | ||||||
|                            // to one LUT6 (instead of a LUT5 + LUT2)
 |  | ||||||
| 
 |  | ||||||
| struct SynthXilinxPass : public ScriptPass | struct SynthXilinxPass : public ScriptPass | ||||||
| { | { | ||||||
| 	SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { } | 	SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { } | ||||||
| 
 | 
 | ||||||
|  | 	void on_register() YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		RTLIL::constpad["synth_xilinx.abc9.xc7.W"] = "300"; // Number with which ABC will map a 6-input gate
 | ||||||
|  | 								    // to one LUT6 (instead of a LUT5 + LUT2)
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	void help() YS_OVERRIDE | 	void help() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||||
|  | @ -515,7 +518,7 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 				techmap_args += " -map +/xilinx/arith_map.v"; | 				techmap_args += " -map +/xilinx/arith_map.v"; | ||||||
| 				if (vpr) | 				if (vpr) | ||||||
| 					techmap_args += " -D _EXPLICIT_CARRY"; | 					techmap_args += " -D _EXPLICIT_CARRY"; | ||||||
| 				else if (abc9) | 				else | ||||||
| 					techmap_args += " -D _CLB_CARRY"; | 					techmap_args += " -D _CLB_CARRY"; | ||||||
| 			} | 			} | ||||||
| 			run("techmap " + techmap_args); | 			run("techmap " + techmap_args); | ||||||
|  | @ -555,7 +558,11 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 				run("techmap " + techmap_args); | 				run("techmap " + techmap_args); | ||||||
| 				run("read_verilog -icells -lib +/xilinx/abc9_model.v"); | 				run("read_verilog -icells -lib +/xilinx/abc9_model.v"); | ||||||
| 				std::string abc9_opts = " -box +/xilinx/abc9_xc7.box"; | 				std::string abc9_opts = " -box +/xilinx/abc9_xc7.box"; | ||||||
| 				abc9_opts += stringf(" -W %d", XC7_WIRE_DELAY); | 				auto k = stringf("synth_xilinx.abc9.%s.W", family.c_str()); | ||||||
|  | 				if (active_design->scratchpad.count(k)) | ||||||
|  | 					abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str()); | ||||||
|  | 				else | ||||||
|  | 					abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); | ||||||
| 				if (nowidelut) | 				if (nowidelut) | ||||||
| 					abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut"; | 					abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut"; | ||||||
| 				else | 				else | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								tests/arch/ecp5/bug1630.il.gz
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/arch/ecp5/bug1630.il.gz
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								tests/arch/ecp5/bug1630.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/arch/ecp5/bug1630.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | read_ilang bug1630.il.gz | ||||||
|  | abc9 -lut +/ecp5/abc9_5g.lut | ||||||
							
								
								
									
										217
									
								
								tests/arch/ice40/bug1626.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								tests/arch/ice40/bug1626.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,217 @@ | ||||||
|  | read_ilang <<EOT | ||||||
|  | # Generated by Yosys 0.9+1706 (git sha1 58ab9f60, clang 6.0.0-1ubuntu2 -fPIC -Os) | ||||||
|  | autoidx 2815 | ||||||
|  | attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:9" | ||||||
|  | attribute \cells_not_processed 1 | ||||||
|  | attribute \dynports 1 | ||||||
|  | module \ahb_async_sram_halfwidth | ||||||
|  |   parameter \DEPTH | ||||||
|  |   parameter \W_ADDR | ||||||
|  |   parameter \W_BYTEADDR | ||||||
|  |   parameter \W_DATA | ||||||
|  |   parameter \W_SRAM_ADDR | ||||||
|  |   parameter \W_SRAM_DATA | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:71" | ||||||
|  |   wire $0\addr_lsb[0:0] | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:71" | ||||||
|  |   wire $0\hready_r[0:0] | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:71" | ||||||
|  |   wire $0\long_dphase[0:0] | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:71" | ||||||
|  |   wire width 16 $0\rdata_buf[15:0] | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:71" | ||||||
|  |   wire $0\read_dph[0:0] | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:71" | ||||||
|  |   wire $0\write_dph[0:0] | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:63" | ||||||
|  |   wire width 32 $add$../hdl/mem/ahb_async_sram_halfwidth.v:63$2433_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:62" | ||||||
|  |   wire width 16 $and$../hdl/mem/ahb_async_sram_halfwidth.v:62$2431_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:56" | ||||||
|  |   wire $eq$../hdl/mem/ahb_async_sram_halfwidth.v:56$2424_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2450_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2451_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2452_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2453_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2454_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2455_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2456_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2457_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2458_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:112" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:112$2459_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:118" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:118$2444_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:133" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:133$2449_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:140" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:140$2461_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:140" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:140$2463_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:58" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:58$2425_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:59" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:59$2426_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:59" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:59$2427_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:59" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:59$2429_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:91" | ||||||
|  |   wire $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:91$2441_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:104" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:104$2442_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:118" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:118$2443_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:125" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:125$2446_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:132" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:132$2447_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:59" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:59$2428_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:72" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:72$2437_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:81" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:81$2438_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:83" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:83$2439_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:91" | ||||||
|  |   wire $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:91$2440_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:118" | ||||||
|  |   wire $logic_or$../hdl/mem/ahb_async_sram_halfwidth.v:118$2445_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:132" | ||||||
|  |   wire $logic_or$../hdl/mem/ahb_async_sram_halfwidth.v:132$2448_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:59" | ||||||
|  |   wire $logic_or$../hdl/mem/ahb_async_sram_halfwidth.v:59$2430_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:139" | ||||||
|  |   wire width 2 $not$../hdl/mem/ahb_async_sram_halfwidth.v:139$2460_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:139" | ||||||
|  |   wire width 2 $not$../hdl/mem/ahb_async_sram_halfwidth.v:139$2462_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:54" | ||||||
|  |   wire width 2 $not$../hdl/mem/ahb_async_sram_halfwidth.v:54$2421_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:63" | ||||||
|  |   wire width 16 $shiftx$../hdl/mem/ahb_async_sram_halfwidth.v:63$2434_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:54" | ||||||
|  |   wire width 8 $shl$../hdl/mem/ahb_async_sram_halfwidth.v:54$2419_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:54" | ||||||
|  |   wire width 2 $shl$../hdl/mem/ahb_async_sram_halfwidth.v:54$2420_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:55" | ||||||
|  |   wire width 2 $shl$../hdl/mem/ahb_async_sram_halfwidth.v:55$2422_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:56" | ||||||
|  |   wire width 32 $shl$../hdl/mem/ahb_async_sram_halfwidth.v:56$2423_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:63" | ||||||
|  |   wire width 32 $ternary$../hdl/mem/ahb_async_sram_halfwidth.v:63$2432_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:65" | ||||||
|  |   wire width 16 $ternary$../hdl/mem/ahb_async_sram_halfwidth.v:65$2435_Y | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:50" | ||||||
|  |   wire \addr_lsb | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:24" | ||||||
|  |   wire width 32 \ahbls_haddr | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:28" | ||||||
|  |   wire width 3 \ahbls_hburst | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:30" | ||||||
|  |   wire \ahbls_hmastlock | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:29" | ||||||
|  |   wire width 4 \ahbls_hprot | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:32" | ||||||
|  |   wire width 32 \ahbls_hrdata | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:22" | ||||||
|  |   wire \ahbls_hready | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:21" | ||||||
|  |   wire \ahbls_hready_resp | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:23" | ||||||
|  |   wire \ahbls_hresp | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:27" | ||||||
|  |   wire width 3 \ahbls_hsize | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:26" | ||||||
|  |   wire width 2 \ahbls_htrans | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:31" | ||||||
|  |   wire width 32 \ahbls_hwdata | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:25" | ||||||
|  |   wire \ahbls_hwrite | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:56" | ||||||
|  |   wire \aphase_full_width | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:55" | ||||||
|  |   wire width 2 \bytemask | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:54" | ||||||
|  |   wire width 2 \bytemask_noshift | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:17" | ||||||
|  |   wire \clk | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:46" | ||||||
|  |   wire \hready_r | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:47" | ||||||
|  |   wire \long_dphase | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:64" | ||||||
|  |   wire width 16 \rdata_buf | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:49" | ||||||
|  |   wire \read_dph | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:18" | ||||||
|  |   wire \rst_n | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:34" | ||||||
|  |   wire width 11 \sram_addr | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:39" | ||||||
|  |   wire width 2 \sram_byte_n | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:36" | ||||||
|  |   wire \sram_ce_n | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:35" | ||||||
|  |   wire width 16 \sram_dq | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:38" | ||||||
|  |   wire \sram_oe_n | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:61" | ||||||
|  |   wire width 16 \sram_q | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:62" | ||||||
|  |   wire width 16 \sram_rdata | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:63" | ||||||
|  |   wire width 16 \sram_wdata | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:37" | ||||||
|  |   wire \sram_we_n | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:58" | ||||||
|  |   wire \we_next | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:48" | ||||||
|  |   wire \write_dph | ||||||
|  |   attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:71" | ||||||
|  |   process $proc$../hdl/mem/ahb_async_sram_halfwidth.v:71$2436 | ||||||
|  |     attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:72" | ||||||
|  |     switch $logic_not$../hdl/mem/ahb_async_sram_halfwidth.v:72$2437_Y | ||||||
|  |       case 1'1 | ||||||
|  |       case  | ||||||
|  |         attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:78" | ||||||
|  |         switch \ahbls_hready | ||||||
|  |           case 1'1 | ||||||
|  |             attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:79" | ||||||
|  |             switch \ahbls_htrans [1] | ||||||
|  |               case 1'1 | ||||||
|  |               case  | ||||||
|  |             end | ||||||
|  |           case  | ||||||
|  |             attribute \src "../hdl/mem/ahb_async_sram_halfwidth.v:91" | ||||||
|  |             switch $logic_and$../hdl/mem/ahb_async_sram_halfwidth.v:91$2441_Y | ||||||
|  |               case 1'1 | ||||||
|  |               case  | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     sync posedge \clk | ||||||
|  |     sync negedge \rst_n | ||||||
|  |   end | ||||||
|  |   connect \ahbls_hresp 1'0 | ||||||
|  |   connect \bytemask_noshift $not$../hdl/mem/ahb_async_sram_halfwidth.v:54$2421_Y | ||||||
|  |   connect \bytemask $shl$../hdl/mem/ahb_async_sram_halfwidth.v:55$2422_Y | ||||||
|  |   connect \aphase_full_width $eq$../hdl/mem/ahb_async_sram_halfwidth.v:56$2424_Y | ||||||
|  |   connect \we_next $logic_or$../hdl/mem/ahb_async_sram_halfwidth.v:59$2430_Y | ||||||
|  |   connect \sram_rdata $and$../hdl/mem/ahb_async_sram_halfwidth.v:62$2431_Y | ||||||
|  |   connect \sram_wdata $shiftx$../hdl/mem/ahb_async_sram_halfwidth.v:63$2434_Y | ||||||
|  |   connect \ahbls_hrdata { \sram_rdata $ternary$../hdl/mem/ahb_async_sram_halfwidth.v:65$2435_Y } | ||||||
|  |   connect \ahbls_hready_resp \hready_r | ||||||
|  | end | ||||||
|  | EOT | ||||||
|  | 
 | ||||||
|  | synth_ice40 -abc2 -abc9 | ||||||
|  | @ -4,8 +4,8 @@ proc | ||||||
| equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check | equiv_opt -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check | ||||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||||
| cd top # Constrain all select calls below inside the top module | cd top # Constrain all select calls below inside the top module | ||||||
| select -assert-count 14 t:LUT2 | stat | ||||||
| select -assert-count 6 t:MUXCY | select -assert-count 16 t:LUT2 | ||||||
| select -assert-count 8 t:XORCY | select -assert-count 2 t:CARRY4 | ||||||
| select -assert-none t:LUT2 t:MUXCY t:XORCY %% t:* %D | select -assert-none t:LUT2 t:CARRY4 %% t:* %D | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,10 +5,9 @@ flatten | ||||||
| equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check | equiv_opt -async2sync -assert -map +/xilinx/cells_sim.v synth_xilinx -noiopad # equivalency check | ||||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||||
| cd top # Constrain all select calls below inside the top module | cd top # Constrain all select calls below inside the top module | ||||||
| 
 | stat | ||||||
| select -assert-count 1 t:BUFG | select -assert-count 1 t:BUFG | ||||||
| select -assert-count 8 t:FDCE | select -assert-count 8 t:FDCE | ||||||
| select -assert-count 1 t:INV | select -assert-count 1 t:INV | ||||||
| select -assert-count 7 t:MUXCY | select -assert-count 2 t:CARRY4 | ||||||
| select -assert-count 8 t:XORCY | select -assert-none t:BUFG t:FDCE t:INV t:CARRY4 %% t:* %D | ||||||
| select -assert-none t:BUFG t:FDCE t:INV t:MUXCY t:XORCY %% t:* %D |  | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip | ||||||
| 
 | 
 | ||||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||||
| cd fsm # Constrain all select calls below inside the top module | cd fsm # Constrain all select calls below inside the top module | ||||||
| 
 | stat | ||||||
| select -assert-count 1 t:BUFG | select -assert-count 1 t:BUFG | ||||||
| select -assert-count 4 t:FDRE | select -assert-count 4 t:FDRE | ||||||
| select -assert-count 1 t:FDSE | select -assert-count 1 t:FDSE | ||||||
|  |  | ||||||
							
								
								
									
										68
									
								
								tests/techmap/abc9.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								tests/techmap/abc9.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | ||||||
|  | read_verilog <<EOT | ||||||
|  | `define N 256 | ||||||
|  | module top(input [`N-1:0] a, output o); | ||||||
|  | wire [`N-2:0] w; | ||||||
|  | assign w[0] = a[0] & a[1]; | ||||||
|  | genvar i; | ||||||
|  | generate for (i = 1; i < `N-1; i++) | ||||||
|  | assign w[i] = w[i-1] & a[i+1]; | ||||||
|  | endgenerate | ||||||
|  | assign o = w[`N-2]; | ||||||
|  | endmodule | ||||||
|  | EOT | ||||||
|  | simplemap | ||||||
|  | dump | ||||||
|  | design -save gold | ||||||
|  | 
 | ||||||
|  | abc9 -lut 4 | ||||||
|  | 
 | ||||||
|  | design -load gold | ||||||
|  | abc9 -lut 4 -fast | ||||||
|  | 
 | ||||||
|  | design -load gold | ||||||
|  | scratchpad -copy abc9.script.default.area abc9.script | ||||||
|  | abc9 -lut 4 | ||||||
|  | 
 | ||||||
|  | design -load gold | ||||||
|  | scratchpad -copy abc9.script.default.fast abc9.script | ||||||
|  | abc9 -lut 4 | ||||||
|  | 
 | ||||||
|  | design -load gold | ||||||
|  | scratchpad -copy abc9.script.flow abc9.script | ||||||
|  | abc9 -lut 4 | ||||||
|  | 
 | ||||||
|  | design -load gold | ||||||
|  | scratchpad -copy abc9.script.flow2 abc9.script | ||||||
|  | abc9 -lut 4 | ||||||
|  | 
 | ||||||
|  | design -load gold | ||||||
|  | scratchpad -copy abc9.script.flow3 abc9.script | ||||||
|  | abc9 -lut 4 | ||||||
|  | 
 | ||||||
|  | design -reset | ||||||
|  | read_verilog <<EOT | ||||||
|  | module top(input a, b, output o); | ||||||
|  | (* keep *) wire w = a & b; | ||||||
|  | assign o = ~w; | ||||||
|  | endmodule | ||||||
|  | EOT | ||||||
|  | 
 | ||||||
|  | simplemap | ||||||
|  | equiv_opt -assert abc9 -lut 4 | ||||||
|  | design -load postopt | ||||||
|  | select -assert-count 2 t:$lut | ||||||
|  | 
 | ||||||
|  | design -reset | ||||||
|  | read_verilog -icells <<EOT | ||||||
|  | module top(input a, b, output o); | ||||||
|  | wire w; | ||||||
|  | (* keep *) $_AND_ gate (.Y(w), .A(a), .B(b)); | ||||||
|  | assign o = ~w; | ||||||
|  | endmodule | ||||||
|  | EOT | ||||||
|  | 
 | ||||||
|  | simplemap | ||||||
|  | equiv_opt -assert abc9 -lut 4 | ||||||
|  | design -load postopt | ||||||
|  | select -assert-count 1 t:$lut | ||||||
|  | select -assert-count 1 t:$_AND_ | ||||||
							
								
								
									
										19
									
								
								tests/various/autoname.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/various/autoname.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | read_ilang <<EOT | ||||||
|  | autoidx 2 | ||||||
|  | module \top | ||||||
|  |   wire output 3 $y | ||||||
|  |   wire input 1 \a | ||||||
|  |   wire input 2 \b | ||||||
|  |   cell $and \b_$and_B | ||||||
|  |     parameter \A_SIGNED 0 | ||||||
|  |     parameter \A_WIDTH 1 | ||||||
|  |     parameter \B_SIGNED 0 | ||||||
|  |     parameter \B_WIDTH 1 | ||||||
|  |     parameter \Y_WIDTH 1 | ||||||
|  |     connect \A \a | ||||||
|  |     connect \B \b | ||||||
|  |     connect \Y $y | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | EOT | ||||||
|  | autoname | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue