diff options
| author | Eddie Hung <eddie@fpgeh.com> | 2020-01-14 12:57:56 -0800 | 
|---|---|---|
| committer | Eddie Hung <eddie@fpgeh.com> | 2020-01-14 12:57:56 -0800 | 
| commit | 915e7dde734094e21803f83e37f8827b8ff2fe32 (patch) | |
| tree | f6d0a2fb338c92f865e6c6c1f2e43716d90716c8 | |
| parent | f9aae90e7a9d238f5063d980e2b1e85a94cff4c7 (diff) | |
| parent | 654247abe9078566f93960a135ce08b0cfc96442 (diff) | |
| download | yosys-915e7dde734094e21803f83e37f8827b8ff2fe32.tar.gz yosys-915e7dde734094e21803f83e37f8827b8ff2fe32.tar.bz2 yosys-915e7dde734094e21803f83e37f8827b8ff2fe32.zip  | |
Merge remote-tracking branch 'origin/eddie/abc9_refactor' into eddie/abc9_required
| -rw-r--r-- | backends/aiger/xaiger.cc | 177 | ||||
| -rw-r--r-- | backends/edif/edif.cc | 62 | ||||
| -rw-r--r-- | frontends/aiger/aigerparse.cc | 31 | ||||
| -rw-r--r-- | frontends/aiger/aigerparse.h | 3 | ||||
| -rw-r--r-- | kernel/rtlil.cc | 1 | ||||
| -rw-r--r-- | kernel/rtlil.h | 2 | ||||
| -rw-r--r-- | passes/cmds/autoname.cc | 2 | ||||
| -rw-r--r-- | passes/cmds/scratchpad.cc | 25 | ||||
| -rw-r--r-- | passes/techmap/abc9.cc | 98 | ||||
| -rw-r--r-- | passes/techmap/abc9_exe.cc | 113 | ||||
| -rw-r--r-- | passes/techmap/abc9_ops.cc | 288 | ||||
| -rw-r--r-- | techlibs/ice40/synth_ice40.cc | 20 | ||||
| -rw-r--r-- | techlibs/xilinx/abc9_map.v | 16 | ||||
| -rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 17 | ||||
| -rw-r--r-- | tests/arch/ecp5/bug1630.il.gz | bin | 0 -> 8527 bytes | |||
| -rw-r--r-- | tests/arch/ecp5/bug1630.ys | 2 | ||||
| -rw-r--r-- | tests/arch/ice40/bug1626.ys | 217 | ||||
| -rw-r--r-- | tests/arch/xilinx/add_sub.ys | 8 | ||||
| -rw-r--r-- | tests/arch/xilinx/counter.ys | 7 | ||||
| -rw-r--r-- | tests/arch/xilinx/fsm.ys | 2 | ||||
| -rw-r--r-- | tests/techmap/abc9.ys | 68 | ||||
| -rw-r--r-- | tests/various/autoname.ys | 19 | 
22 files changed, 789 insertions, 389 deletions
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index d934a9aa9..d3415e45d 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -156,7 +156,6 @@ struct XAigerWriter  			if (wire->get_bool_attribute(ID::keep))  				sigmap.add(wire); -  		for (auto wire : module->wires())  			for (int i = 0; i < GetSize(wire); i++)  			{ @@ -174,93 +173,101 @@ struct XAigerWriter  				undriven_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); -				if (wire->port_output) { +				if (wire->port_output || keep) {  					if (bit != wirebit)  						alias_map[wirebit] = bit;  					output_bits.insert(wirebit);  				}  			} -		std::vector<int> arrivals; +		dict<IdString,dict<IdString,std::vector<int>>> arrivals_cache;  		for (auto cell : module->cells()) { -			if (cell->type == "$_NOT_") -			{ -				SigBit A = sigmap(cell->getPort("\\A").as_bit()); -				SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); -				unused_bits.erase(A); -				undriven_bits.erase(Y); -				not_map[Y] = A; -				continue; -			} - -			if (cell->type == "$_AND_") -			{ -				SigBit A = sigmap(cell->getPort("\\A").as_bit()); -				SigBit B = sigmap(cell->getPort("\\B").as_bit()); -				SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); -				unused_bits.erase(A); -				unused_bits.erase(B); -				undriven_bits.erase(Y); -				and_map[Y] = make_pair(A, B); -				continue; -			} +			RTLIL::Module* inst_module = module->design->module(cell->type); +			if (!cell->has_keep_attr()) { +				if (cell->type == "$_NOT_") +				{ +					SigBit A = sigmap(cell->getPort("\\A").as_bit()); +					SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); +					unused_bits.erase(A); +					undriven_bits.erase(Y); +					not_map[Y] = A; +					continue; +				} -			if (cell->type == "$__ABC9_FF_" && -                                        // The presence of an abc9_mergeability attribute indicates -                                        //   that we do want to pass this flop to ABC -                                        cell->attributes.count("\\abc9_mergeability")) -			{ -				SigBit D = sigmap(cell->getPort("\\D").as_bit()); -				SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); -				unused_bits.erase(D); -				undriven_bits.erase(Q); -				alias_map[Q] = D; -				auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); -				log_assert(r.second); -				continue; -			} +				if (cell->type == "$_AND_") +				{ +					SigBit A = sigmap(cell->getPort("\\A").as_bit()); +					SigBit B = sigmap(cell->getPort("\\B").as_bit()); +					SigBit Y = sigmap(cell->getPort("\\Y").as_bit()); +					unused_bits.erase(A); +					unused_bits.erase(B); +					undriven_bits.erase(Y); +					and_map[Y] = make_pair(A, B); +					continue; +				} -			RTLIL::Module* inst_module = module->design->module(cell->type); -			if (inst_module && inst_module->get_blackbox_attribute()) { -				auto it = cell->attributes.find("\\abc9_box_seq"); -				if (it != cell->attributes.end()) { -					int abc9_box_seq = it->second.as_int(); -					if (GetSize(box_list) <= abc9_box_seq) -						box_list.resize(abc9_box_seq+1); -					box_list[abc9_box_seq] = cell; -					// Only flop boxes may have arrival times -					//   (all others are combinatorial) -					if (!inst_module->get_bool_attribute("\\abc9_flop")) -						continue; +				if (cell->type == "$__ABC9_FF_" && +						// The presence of an abc9_mergeability attribute indicates +						//   that we do want to pass this flop to ABC +						cell->attributes.count("\\abc9_mergeability")) +				{ +					SigBit D = sigmap(cell->getPort("\\D").as_bit()); +					SigBit Q = sigmap(cell->getPort("\\Q").as_bit()); +					unused_bits.erase(D); +					undriven_bits.erase(Q); +					alias_map[Q] = D; +					auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); +					log_assert(r.second); +					continue;  				} -				for (const auto &conn : cell->connections()) { -					auto port_wire = inst_module->wire(conn.first); -					if (port_wire->port_output) { -						arrivals.clear(); -						auto it = port_wire->attributes.find("\\abc9_arrival"); -						if (it == port_wire->attributes.end()) +				if (inst_module) { +					auto it = cell->attributes.find("\\abc9_box_seq"); +					if (it != cell->attributes.end()) { +						int abc9_box_seq = it->second.as_int(); +						if (GetSize(box_list) <= abc9_box_seq) +							box_list.resize(abc9_box_seq+1); +						box_list[abc9_box_seq] = cell; +						// Only flop boxes may have arrival times +						//   (all others are combinatorial) +						if (!inst_module->get_bool_attribute("\\abc9_flop"))  							continue; -						if (it->second.flags == 0) -							arrivals.emplace_back(it->second.as_int()); -						else -							for (const auto &tok : split_tokens(it->second.decode_string())) -								arrivals.push_back(atoi(tok.c_str())); +					} + +					auto &cell_arrivals = arrivals_cache[cell->type]; +					for (const auto &conn : cell->connections()) { +						auto port_wire = inst_module->wire(conn.first); +						if (!port_wire->port_output) +							continue; + +						auto r = cell_arrivals.insert(conn.first); +						auto &arrivals = r.first->second; +						if (r.second) { +							auto it = port_wire->attributes.find("\\abc9_arrival"); +							if (it == port_wire->attributes.end()) +								continue; +							if (it->second.flags == 0) +								arrivals.emplace_back(it->second.as_int()); +							else +								for (const auto &tok : split_tokens(it->second.decode_string())) +									arrivals.push_back(atoi(tok.c_str())); +						} +  						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),  									GetSize(port_wire), log_signal(it->second), GetSize(arrivals)); -						auto jt = arrivals.begin(); +						auto jt = arrivals.begin();  #ifndef NDEBUG  						if (ys_debug(1)) {  							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);  						}  #endif -  						for (auto bit : sigmap(conn.second)) {  							arrival_times[bit] = *jt;  							if (arrivals.size() > 1) @@ -283,6 +290,9 @@ struct XAigerWriter  					for (auto b : c.second) {  						Wire *w = b.wire;  						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) {  							SigBit I = sigmap(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) {  				auto w = box_module->wire(port_name);  				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)  					for (auto b : rhs) {  						SigBit I = sigmap(b); @@ -364,6 +373,11 @@ struct XAigerWriter  							alias_map[O] = b;  						ci_bits.emplace_back(b);  						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) {  			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));  			aig_map[bit] = 2*aig_m;  		} @@ -443,7 +461,27 @@ struct XAigerWriter  		for (const auto &bit : output_bits) {  			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) { @@ -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("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("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("    -ascii\n");  		log("        write ASCII version of AIGER format\n"); diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 6d9469538..6735d670f 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -300,6 +300,26 @@ struct EdifBackend : public Backend {  		*f << stringf("  (library DESIGN\n");  		*f << stringf("    (edifLevel 0)\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)  		{  			if (module->get_blackbox_attribute()) @@ -323,14 +343,23 @@ struct EdifBackend : public Backend {  				else if (!wire->port_input)  					dir = "OUTPUT";  				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));  					net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name)));  				} else {  					int b[2];  					b[wire->upto ? 0 : 1] = wire->start_offset;  					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++) {  						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)); @@ -348,27 +377,6 @@ struct EdifBackend : public Backend {  				*f << stringf("          (instance %s\n", EDIF_DEF(cell->name));  				*f << stringf("            (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type),  						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)  					add_prop(p.first, p.second);  				if (attr_properties) @@ -431,8 +439,12 @@ struct EdifBackend : public Backend {  						*f << stringf("            (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G');  					if (sig == RTLIL::State::S1)  						*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"); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b4304a581..cf9b33b3c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -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) -	: 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->name = module_name; @@ -255,7 +255,7 @@ end_of_header:  	else  		log_abort(); -	RTLIL::Wire* n0 = module->wire("$0"); +	RTLIL::Wire* n0 = module->wire(stringf("$aiger%d$0", aiger_autoidx));  	if (n0)  		module->connect(n0, State::S0); @@ -323,18 +323,18 @@ static uint32_t parse_xaiger_literal(std::istream &f)  	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 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);  	if (wire) return wire;  	log_debug2("Creating %s\n", wire_name.c_str());  	wire = module->addWire(wire_name);  	wire->port_input = wire->port_output = false;  	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);  	if (wire_inv) {  		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()); -	module->addNotGate(stringf("$%d$not", variable), wire_inv, wire); +	module->addNotGate(stringf("$not$aiger%d$%d", aiger_autoidx, variable), wire_inv, wire);  	return wire;  } @@ -383,7 +383,7 @@ void AigerReader::parse_xaiger()  	else  		log_abort(); -	RTLIL::Wire* n0 = module->wire("$0"); +	RTLIL::Wire* n0 = module->wire(stringf("$aiger%d$0", aiger_autoidx));  	if (n0)  		module->connect(n0, State::S0); @@ -407,13 +407,14 @@ void AigerReader::parse_xaiger()  				uint32_t rootNodeID = parse_xaiger_literal(f);  				uint32_t cutLeavesM = parse_xaiger_literal(f);  				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;  				RTLIL::SigSpec input_sig;  				for (unsigned j = 0; j < cutLeavesM; ++j) {  					nodeID = parse_xaiger_literal(f);  					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);  					input_sig.append(wire);  				} @@ -430,10 +431,10 @@ void AigerReader::parse_xaiger()  					log_assert(o.wire == nullptr);  					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);  				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') { @@ -603,7 +604,7 @@ void AigerReader::parse_aiger_ascii()  		RTLIL::Wire *o_wire = createWireIfNotExists(module, l1);  		RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2);  		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  } @@ -729,7 +730,7 @@ void AigerReader::parse_aiger_binary()  		RTLIL::Wire *o_wire = createWireIfNotExists(module, l1);  		RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2);  		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 {  						wire->port_output = false; +						existing->port_output = true;  						module->connect(wire, existing);  						wire = existing;  					} @@ -845,8 +847,9 @@ void AigerReader::post_process()  							wideports_cache[escaped_s] = std::max(wideports_cache[escaped_s], index);  					}  					else { -						module->connect(wire, existing);  						wire->port_output = false; +						existing->port_output = true; +						module->connect(wire, existing);  					}  					log_debug(" -> %s\n", log_id(indexed_name));  				} diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index de3c3efbc..722f1e472 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -33,6 +33,7 @@ struct AigerReader      RTLIL::Module *module;      std::string map_filename;      bool wideports; +    const int aiger_autoidx;      unsigned M, I, L, O, A;      unsigned B, C, J, F; // Optional in AIGER 1.9 @@ -51,6 +52,8 @@ struct AigerReader      void parse_aiger_ascii();      void parse_aiger_binary();      void post_process(); + +    RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal);  };  YOSYS_NAMESPACE_END diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index ab4f4f377..f286d139f 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -46,6 +46,7 @@ IdString RTLIL::ID::Y;  IdString RTLIL::ID::keep;  IdString RTLIL::ID::whitebox;  IdString RTLIL::ID::blackbox; +dict<std::string, std::string> RTLIL::constpad;  RTLIL::Const::Const()  { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index e5b24cc02..6251d265d 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -377,6 +377,8 @@ namespace RTLIL  		extern IdString blackbox;  	}; +	extern dict<std::string, std::string> constpad; +  	static inline std::string escape_id(std::string str) {  		if (str.size() > 0 && str[0] != '\\' && str[0] != '$')  			return "\\" + str; diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc index 4614a8153..50632201e 100644 --- a/passes/cmds/autoname.cc +++ b/passes/cmds/autoname.cc @@ -56,7 +56,7 @@ int autoname_worker(Module *module)  			for (auto &conn : cell->connections()) {  				string suffix = stringf("_%s", log_id(conn.first));  				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);  						int score = wire_score.at(bit.wire);  						if (cell->output(conn.first)) score = 0; diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc index 7ec55b78e..34ec0863a 100644 --- a/passes/cmds/scratchpad.cc +++ b/passes/cmds/scratchpad.cc @@ -70,8 +70,10 @@ struct ScratchpadPass : public Pass {  		{  			if (args[argidx] == "-get" && argidx+1 < args.size()) {  				string identifier = args[++argidx]; -				if (design->scratchpad.count(identifier)){ +				if (design->scratchpad.count(identifier)) {  					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 {  					log("\"%s\" not set\n", identifier.c_str());  				} @@ -79,6 +81,8 @@ struct ScratchpadPass : public Pass {  			}  			if (args[argidx] == "-set" && argidx+2 < args.size()) {  				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];  				if (value.front() == '\"' && value.back() == '\"') value = value.substr(1, value.size() - 2);  				design->scratchpad_set_string(identifier, value); @@ -92,8 +96,15 @@ struct ScratchpadPass : public Pass {  			if (args[argidx] == "-copy" && argidx+2 < args.size()) {  				string identifier_from = 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 = design->scratchpad_get_string(identifier_from); +				string value; +				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);  				continue;  			} @@ -102,10 +113,10 @@ struct ScratchpadPass : public Pass {  				string expected = args[++argidx];  				if (expected.front() == '\"' && expected.back() == '\"') expected = expected.substr(1, expected.size() - 2);  				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);  				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());  				}  				continue; @@ -113,13 +124,13 @@ struct ScratchpadPass : public Pass {  			if (args[argidx] == "-assert-set" && argidx+1 < args.size()) {  				string identifier = args[++argidx];  				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;  			}  			if (args[argidx] == "-assert-unset" && argidx+1 < args.size()) {  				string identifier = args[++argidx];  				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;  			}  			break; diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 1be7519b7..5ba87fa88 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -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/celltypes.h"  #include "kernel/rtlil.h"  #include "kernel/log.h" +// abc9_exe.cc +std::string fold_abc9_cmd(std::string str); +  USING_YOSYS_NAMESPACE  PRIVATE_NAMESPACE_BEGIN  struct Abc9Pass : public ScriptPass  {  	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  	{  		//   |---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("architecture. Only fully-selected modules are supported.\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");  #ifdef ABCEXTERNAL  		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("\n");  		log("        if no -script parameter is given, the following scripts are used:\n"); -		//FIXME: -		//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("    -fast\n");  		log("        use different default scripts that are slightly faster (at the cost\n");  		log("        of output quality):\n"); -		//FIXME: -		//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("    -D <picoseconds>\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("\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("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"); @@ -141,6 +195,11 @@ struct Abc9Pass : public ScriptPass  		dff_mode = design->scratchpad_get_bool("abc9.dff", dff_mode);  		cleanup = !design->scratchpad_get_bool("abc9.nocleanup", !cleanup); +		if (design->scratchpad_get_bool("abc9.debug")) { +			cleanup = false; +			exe_cmd << " -showtmp"; +		} +  		size_t argidx;  		for (argidx = 1; argidx < args.size(); argidx++) {  			std::string arg = args[argidx]; @@ -152,13 +211,13 @@ struct Abc9Pass : public ScriptPass  				continue;  			}  			if (arg == "-fast" || /* arg == "-dff" || */ -					/* arg == "-nocleanup" || */ arg == "-showtmp" || -					arg == "-nomfs") { +					/* arg == "-nocleanup" || */ arg == "-showtmp") {  				exe_cmd << " " << arg;  				continue;  			}  			if (arg == "-dff") {  				dff_mode = true; +				exe_cmd << " " << arg;  				continue;  			}  			if (arg == "-nocleanup") { @@ -169,6 +228,14 @@ struct Abc9Pass : public ScriptPass  				box_file = args[++argidx];  				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;  		}  		extra_args(args, argidx, design); @@ -184,9 +251,9 @@ struct Abc9Pass : public ScriptPass  			run("abc9_ops -check");  			run("scc -set_attr abc9_scc_id {}");  			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 -				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("flatten -wb @abc9_holes");  			run("techmap @abc9_holes"); @@ -200,7 +267,7 @@ struct Abc9Pass : public ScriptPass  		if (check_label("map")) {  			if (help_mode) {  				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("    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"); @@ -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()));  					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_wires"), +							log_id(mod),  							active_design->scratchpad_get_int("write_xaiger.num_inputs"),  							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("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");  					}  					else @@ -258,9 +327,6 @@ struct Abc9Pass : public ScriptPass  				active_design->selection_stack.pop_back();  			}  		} - -		if (check_label("post")) -			run("abc9_ops -unbreak_scc");  	}  } Abc9Pass; diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index d92285a51..a2acfac91 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -22,20 +22,6 @@  // Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification  // 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/log.h" @@ -48,6 +34,25 @@  extern "C" int Abc_RealMain(int argc, char *argv[]);  #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  PRIVATE_NAMESPACE_BEGIN @@ -73,25 +78,6 @@ std::string add_echos_to_abc9_cmd(std::string 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)  {  	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, -		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, -		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;  	if (!lut_costs.empty())  		abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); -	else -	if (!lut_file.empty()) +	else if (!lut_file.empty())  		abc9_script += stringf("read_lut %s; ", lut_file.c_str());  	else  		log_abort(); +	log_assert(!box_file.empty());  	abc9_script += stringf("read_box %s; ", box_file.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  			abc9_script += stringf("source %s", script_file.c_str());  	} 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  		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))  		abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_script.substr(pos+3); -	if (nomfs) -		for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) -			abc9_script = abc9_script.erase(pos, strlen("&mfs")); - -	abc9_script += stringf("; &write -n %s/output.aig", tempdir_name.c_str()); +	std::string C; +	if (design->scratchpad.count("abc9.if.C")) +		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); + +	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);  	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("\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("    -fast\n");  		log("        use different default scripts that are slightly faster (at the cost\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("    -D <picoseconds>\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 delay_target, lutin_shared = "-S 1", wire_delay;  		std::string tempdir_name; -		bool fast_mode = false; +		bool fast_mode = false, dff_mode = false;  		bool show_tempdir = false; -		bool nomfs = false;  		vector<int> lut_costs;  #if 0 @@ -400,12 +397,12 @@ struct Abc9ExePass : public Pass {  		lut_arg = design->scratchpad_get_string("abc9.lut", lut_arg);  		luts_arg = design->scratchpad_get_string("abc9.luts", luts_arg);  		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);  		box_file = design->scratchpad_get_string("abc9.box", box_file);  		if (design->scratchpad.count("abc9.W")) {  			wire_delay = "-W " + design->scratchpad_get_string("abc9.W");  		} -		nomfs = design->scratchpad_get_bool("abc9.nomfs", nomfs);  		size_t argidx;  		char pwd [PATH_MAX]; @@ -443,6 +440,10 @@ struct Abc9ExePass : public Pass {  				fast_mode = true;  				continue;  			} +			if (arg == "-dff") { +				dff_mode = true; +				continue; +			}  			if (arg == "-showtmp") {  				show_tempdir = true;  				continue; @@ -455,10 +456,6 @@ struct Abc9ExePass : public Pass {  				wire_delay = "-W " + args[++argidx];  				continue;  			} -			if (arg == "-nomfs") { -				nomfs = true; -				continue; -			}  			if (arg == "-cwd" && argidx+1 < args.size()) {  				tempdir_name = args[++argidx];  				continue; @@ -525,9 +522,9 @@ struct Abc9ExePass : public Pass {  			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, -				box_file, lut_file, wire_delay, nomfs, tempdir_name); +				box_file, lut_file, wire_delay, tempdir_name);  	}  } Abc9ExePass; diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 7f3bbc7ad..04a54fd63 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -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  	//   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));  		if (it == cell->attributes.end())  			continue; -		auto r = ids_seen.insert(it->second); +		auto id = it->second; +		auto r = ids_seen.insert(id);  		cell->attributes.erase(it);  		if (!r.second)  			continue; @@ -111,30 +112,8 @@ void break_scc(RTLIL::Module *module)  			if (cell->output(c.first)) {  				SigBit b = c.second.as_bit();  				Wire *w = b.wire; -				if (w->port_input) { -					// In this case, hopefully the loop break has been already created -					// 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); -				} +				w->set_bool_attribute(ID::keep); +				w->attributes[ID(abc9_scc_id)] = id.as_int();  			}  		}  	} @@ -142,28 +121,6 @@ void break_scc(RTLIL::Module *module)  	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)  {  	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;  	log_assert(design); @@ -253,7 +210,7 @@ void prep_holes(RTLIL::Module *module, bool dff)  	dict<SigBit, pool<IdString>> bit_drivers, bit_users;  	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()) {  		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");  			if (abc9_flop && !dff)  				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))  			continue; @@ -284,7 +274,7 @@ void prep_holes(RTLIL::Module *module, bool dff)  		toposort.node(cell->name);  	} -	if (!abc9_box_seen) +	if (box_ports.empty())  		return;  	for (auto &it : bit_users) @@ -312,7 +302,13 @@ void prep_holes(RTLIL::Module *module, bool dff)  	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) {  		RTLIL::Cell *cell = module->cell(cell_name);  		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"))  			continue; -		bool blackbox = box_module->get_blackbox_attribute(true /* ignore_wb */); - -		// 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 (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; +		cell->attributes["\\abc9_box_seq"] = box_count++; -	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(); +		IdString derived_name = box_module->derive(design, cell->parameters); +		box_module = design->module(derived_name);  		auto r = cell_cache.insert(derived_name);  		auto &holes_cell = r.first->second;  		if (r.second) { -			auto r2 = box_ports.insert(cell->type); -			if (r2.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 : 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->has_processes()) +				Pass::call_on_module(design, box_module, "proc");  			if (box_module->get_bool_attribute("\\whitebox")) {  				holes_cell = holes_module->addCell(cell->name, derived_name); @@ -655,6 +575,8 @@ void reintegrate(RTLIL::Module *module)  	pool<IdString> delay_boxes;  	std::vector<Cell*> boxes;  	for (auto cell : module->cells().to_vector()) { +		if (cell->has_keep_attr()) +			continue;  		if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))  			module->remove(cell);  		else if (cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) { @@ -680,7 +602,9 @@ void reintegrate(RTLIL::Module *module)  			RTLIL::SigBit a_bit = mapped_cell->getPort(ID::A);  			RTLIL::SigBit y_bit = mapped_cell->getPort(ID::Y);  			bit_users[a_bit].insert(mapped_cell->name); -			bit_drivers[y_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);  			if (!a_bit.wire) {  				mapped_cell->setPort(ID::Y, module->addWire(NEW_ID)); @@ -698,16 +622,16 @@ void reintegrate(RTLIL::Module *module)  					// (TODO: Optimise by not cloning unless will increase depth)  					RTLIL::IdString driver_name;  					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 -						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);  				}  				if (!driver_lut) {  					// If a driver couldn't be found (could be from PI or box CI)  					// 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(y_bit.wire->name)), y_bit.offset),  							RTLIL::Const::from_string("01")); @@ -745,7 +669,9 @@ void reintegrate(RTLIL::Module *module)  				}  				if (cell->output(mapped_conn.first))  					for (auto i : mapped_conn.second) -						bit_drivers[i].insert(mapped_cell->name); +						// Ignore inouts for topo ordering +						if (i.wire && !(i.wire->port_input && i.wire->port_output)) +							bit_drivers[i].insert(mapped_cell->name);  			}  		}  		else if (delay_boxes.count(mapped_cell->name)) { @@ -788,7 +714,9 @@ void reintegrate(RTLIL::Module *module)  				for (const auto &i : inputs)  					bit_users[i].insert(mapped_cell->name);  				for (const auto &i : outputs) -					bit_drivers[i].insert(mapped_cell->name); +					// Ignore inouts for topo ordering +					if (i.wire && !(i.wire->port_input && i.wire->port_output)) +						bit_drivers[i].insert(mapped_cell->name);  			}  			auto r2 = box_ports.insert(cell->type); @@ -886,21 +814,25 @@ void reintegrate(RTLIL::Module *module)  	// Stitch in mapped_mod's inputs/outputs into module  	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);  		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::SigSpec signal(wire, 0, GetSize(remap_wire));  		log_assert(GetSize(signal) >= GetSize(remap_wire));  		RTLIL::SigSig conn; -		if (w->port_output) { +		if (mapped_wire->port_output) {  			conn.first = signal;  			conn.second = remap_wire;  			out_wires++;  			module->connect(conn);  		} -		else if (w->port_input) { +		else if (mapped_wire->port_input) {  			conn.first = remap_wire;  			conn.second = signal;  			in_wires++; @@ -996,6 +928,35 @@ struct Abc9OpsPass : public Pass {  		log("\n");  		log("    abc9_ops [options] [selection]\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  	{ @@ -1003,13 +964,12 @@ struct Abc9OpsPass : public Pass {  		bool check_mode = false;  		bool prep_times_mode = false; -		bool break_scc_mode = false; -		bool unbreak_scc_mode = false; -		bool prep_holes_mode = false; +		bool mark_scc_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 dff_mode = false; +		std::string write_box_src, write_box_dst;  		size_t argidx;  		for (argidx = 1; argidx < args.size(); argidx++) { @@ -1018,20 +978,16 @@ struct Abc9OpsPass : public Pass {  				check_mode = true;  				continue;  			} -			if (arg == "-break_scc") { -				break_scc_mode = true; -				continue; -			} -			if (arg == "-unbreak_scc") { -				unbreak_scc_mode = true; +			if (arg == "-mark_scc") { +				mark_scc_mode = true;  				continue;  			}  			if (arg == "-prep_dff") {  				prep_dff_mode = true;  				continue;  			} -			if (arg == "-prep_holes") { -				prep_holes_mode = true; +			if (arg == "-prep_xaiger") { +				prep_xaiger_mode = true;  				continue;  			}  			if (arg == "-prep_times") { @@ -1057,11 +1013,11 @@ struct Abc9OpsPass : public Pass {  		}  		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)) -			log_cmd_error("At least one of -check, -{,un}break_scc, -prep_{times,holes,dff}, -write_box, -reintegrate must be specified.\n"); +		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, -mark_scc, -prep_{times,xaiger,dff}, -write_box, -reintegrate must be specified.\n"); -		if (dff_mode && !prep_holes_mode) -			log_cmd_error("'-dff' option is only relevant for -prep_holes.\n"); +		if (dff_mode && !prep_xaiger_mode) +			log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n");  		if (check_mode)  			check(design); @@ -1080,16 +1036,14 @@ struct Abc9OpsPass : public Pass {  			if (!design->selected_whole_module(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())  				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)  				reintegrate(mod);  		} diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 463c2063a..121bcff1f 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -102,8 +102,8 @@ struct SynthIce40Pass : public ScriptPass  		log("\n");  	} -	string top_opt, blif_file, edif_file, json_file, abc, device_opt; -	bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr; +	string top_opt, blif_file, edif_file, json_file, device_opt; +	bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9;  	int min_ce_use;  	void clear_flags() YS_OVERRIDE @@ -122,7 +122,7 @@ struct SynthIce40Pass : public ScriptPass  		noabc = false;  		abc2 = false;  		vpr = false; -		abc = "abc"; +		abc9 = false;  		device_opt = "hx";  	} @@ -207,7 +207,7 @@ struct SynthIce40Pass : public ScriptPass  				continue;  			}  			if (args[argidx] == "-abc9") { -				abc = "abc9"; +				abc9 = true;  				continue;  			}  			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")  			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_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");  			}  			if (retime || help_mode) -				run(abc + " -dff -D 1", "(only if -retime)"); +				run("abc -dff -D 1", "(only if -retime)");  			run("ice40_opt");  		} @@ -340,7 +340,7 @@ struct SynthIce40Pass : public ScriptPass  		if (check_label("map_luts"))  		{  			if (abc2 || help_mode) { -				run(abc, "      (only if -abc2)"); +				run("abc", "      (only if -abc2)");  				run("ice40_opt", "(only if -abc2)");  			}  			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)");  			}  			if (!noabc) { -				if (abc == "abc9") { +				if (abc9) {  					run("read_verilog -icells -lib +/ice40/abc9_model.v");  					int wire_delay;  					if (device_opt == "lp") @@ -358,10 +358,10 @@ struct SynthIce40Pass : public ScriptPass  						wire_delay = 750;  					else  						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 -					run(abc + " -dress -lut 4", "(skip if -noabc)"); +					run("abc -dress -lut 4", "(skip if -noabc)");  			}  			run("ice40_wrapcarry -unwrap");  			run("techmap -D NO_LUT -map +/ice40/cells_map.v"); diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 0652064cb..7dc027176 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -74,7 +74,7 @@  // (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 -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] IS_C_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] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;  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;    wire QQ, $Q;    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;  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] IS_C_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] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;  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;    wire QQ, $Q;    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;  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] IS_C_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] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;  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;    wire QQ, $Q, $QQ;    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;  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] IS_C_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] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;  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;    wire QQ, $Q, $QQ;    generate if (INIT == 1'b1) begin diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 63d00027a..77be8299c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -26,13 +26,16 @@  USING_YOSYS_NAMESPACE  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  {  	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  	{  		//   |---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";  				if (vpr)  					techmap_args += " -D _EXPLICIT_CARRY"; -				else if (abc9) +				else  					techmap_args += " -D _CLB_CARRY";  			}  			run("techmap " + techmap_args); @@ -555,7 +558,11 @@ struct SynthXilinxPass : public ScriptPass  				run("techmap " + techmap_args);  				run("read_verilog -icells -lib +/xilinx/abc9_model.v");  				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)  					abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut";  				else diff --git a/tests/arch/ecp5/bug1630.il.gz b/tests/arch/ecp5/bug1630.il.gz Binary files differnew file mode 100644 index 000000000..37bcf2be2 --- /dev/null +++ b/tests/arch/ecp5/bug1630.il.gz diff --git a/tests/arch/ecp5/bug1630.ys b/tests/arch/ecp5/bug1630.ys new file mode 100644 index 000000000..b419fb9bb --- /dev/null +++ b/tests/arch/ecp5/bug1630.ys @@ -0,0 +1,2 @@ +read_ilang bug1630.il.gz +abc9 -lut +/ecp5/abc9_5g.lut diff --git a/tests/arch/ice40/bug1626.ys b/tests/arch/ice40/bug1626.ys new file mode 100644 index 000000000..27b6fb5e8 --- /dev/null +++ b/tests/arch/ice40/bug1626.ys @@ -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 diff --git a/tests/arch/xilinx/add_sub.ys b/tests/arch/xilinx/add_sub.ys index 313948cc5..70cfe81a3 100644 --- a/tests/arch/xilinx/add_sub.ys +++ b/tests/arch/xilinx/add_sub.ys @@ -4,8 +4,8 @@ proc  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)  cd top # Constrain all select calls below inside the top module -select -assert-count 14 t:LUT2 -select -assert-count 6 t:MUXCY -select -assert-count 8 t:XORCY -select -assert-none t:LUT2 t:MUXCY t:XORCY %% t:* %D +stat +select -assert-count 16 t:LUT2 +select -assert-count 2 t:CARRY4 +select -assert-none t:LUT2 t:CARRY4 %% t:* %D diff --git a/tests/arch/xilinx/counter.ys b/tests/arch/xilinx/counter.ys index 11c29922e..064519ce7 100644 --- a/tests/arch/xilinx/counter.ys +++ b/tests/arch/xilinx/counter.ys @@ -5,10 +5,9 @@ flatten  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)  cd top # Constrain all select calls below inside the top module - +stat  select -assert-count 1 t:BUFG  select -assert-count 8 t:FDCE  select -assert-count 1 t:INV -select -assert-count 7 t:MUXCY -select -assert-count 8 t:XORCY -select -assert-none t:BUFG t:FDCE t:INV t:MUXCY t:XORCY %% t:* %D +select -assert-count 2 t:CARRY4 +select -assert-none t:BUFG t:FDCE t:INV t:CARRY4 %% t:* %D diff --git a/tests/arch/xilinx/fsm.ys b/tests/arch/xilinx/fsm.ys index 3235d5af3..a464fcfdb 100644 --- a/tests/arch/xilinx/fsm.ys +++ b/tests/arch/xilinx/fsm.ys @@ -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)  cd fsm # Constrain all select calls below inside the top module - +stat  select -assert-count 1 t:BUFG  select -assert-count 4 t:FDRE  select -assert-count 1 t:FDSE diff --git a/tests/techmap/abc9.ys b/tests/techmap/abc9.ys new file mode 100644 index 000000000..d5a63e1cb --- /dev/null +++ b/tests/techmap/abc9.ys @@ -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_ diff --git a/tests/various/autoname.ys b/tests/various/autoname.ys new file mode 100644 index 000000000..830962e81 --- /dev/null +++ b/tests/various/autoname.ys @@ -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  | 
