diff options
Diffstat (limited to 'frontends/aiger')
| -rw-r--r-- | frontends/aiger/aigerparse.cc | 88 | 
1 files changed, 70 insertions, 18 deletions
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 1ac0f7ba4..30e35da01 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -440,6 +440,7 @@ void AigerReader::parse_xaiger()  			else if (c == 'r') {  				uint32_t dataSize = parse_xaiger_literal(f);  				flopNum = parse_xaiger_literal(f); +				log_debug("flopNum: %u\n", flopNum);  				log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));  				f.ignore(flopNum * sizeof(uint32_t));  			} @@ -461,7 +462,7 @@ void AigerReader::parse_xaiger()  				uint32_t poNum = parse_xaiger_literal(f);  				log_debug("poNum = %u\n", poNum);  				uint32_t boxNum = parse_xaiger_literal(f); -				log_debug("boxNum = %u\n", poNum); +				log_debug("boxNum = %u\n", boxNum);  				for (unsigned i = 0; i < boxNum; i++) {  					f.ignore(2*sizeof(uint32_t));  					uint32_t boxUniqueId = parse_xaiger_literal(f); @@ -506,8 +507,7 @@ void AigerReader::parse_aiger_ascii()  	// Parse latches  	RTLIL::Wire *clk_wire = nullptr; -	if (L > 0) { -		log_assert(clk_name != ""); +	if (L > 0 && !clk_name.empty()) {  		clk_wire = module->wire(clk_name);  		log_assert(!clk_wire);  		log_debug2("Creating %s\n", clk_name.c_str()); @@ -523,7 +523,10 @@ void AigerReader::parse_aiger_ascii()  		RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);  		RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); -		module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); +		if (clk_wire) +			module->addDffGate(NEW_ID, clk_wire, d_wire, q_wire); +		else +			module->addFfGate(NEW_ID, d_wire, q_wire);  		// Reset logic is optional in AIGER 1.9  		if (f.peek() == ' ') { @@ -631,8 +634,7 @@ void AigerReader::parse_aiger_binary()  	// Parse latches  	RTLIL::Wire *clk_wire = nullptr; -	if (L > 0) { -		log_assert(clk_name != ""); +	if (L > 0 && !clk_name.empty()) {  		clk_wire = module->wire(clk_name);  		log_assert(!clk_wire);  		log_debug2("Creating %s\n", clk_name.c_str()); @@ -648,7 +650,10 @@ void AigerReader::parse_aiger_binary()  		RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);  		RTLIL::Wire *d_wire = createWireIfNotExists(module, l2); -		module->addDff(NEW_ID, clk_wire, d_wire, q_wire); +		if (clk_wire) +			module->addDff(NEW_ID, clk_wire, d_wire, q_wire); +		else +			module->addFf(NEW_ID, d_wire, q_wire);  		// Reset logic is optional in AIGER 1.9  		if (f.peek() == ' ') { @@ -737,13 +742,29 @@ void AigerReader::parse_aiger_binary()  void AigerReader::post_process()  {  	pool<IdString> seen_boxes; -	unsigned ci_count = 0, co_count = 0; +	dict<IdString, std::pair<RTLIL::Module*,IdString>> flop_data; +	unsigned ci_count = 0, co_count = 0, flop_count = 0;  	for (auto cell : boxes) {  		RTLIL::Module* box_module = design->module(cell->type);  		log_assert(box_module); +		RTLIL::Module* flop_module = nullptr; +		RTLIL::IdString flop_past_q;  		if (seen_boxes.insert(cell->type).second) { -			auto it = box_module->attributes.find("\\abc_carry"); +			auto it = box_module->attributes.find("\\abc_flop"); +			if (it != box_module->attributes.end()) { +				log_assert(flop_count < flopNum); +				std::string abc_flop = it->second.decode_string(); +				auto pos = abc_flop.find(','); +				log_assert(pos != std::string::npos); +				flop_module = design->module(RTLIL::escape_id(abc_flop.substr(0, pos))); +				log_assert(flop_module); +				pos = abc_flop.rfind(','); +				log_assert(pos != std::string::npos); +				flop_past_q = RTLIL::escape_id(abc_flop.substr(pos+1)); +				flop_data[cell->type] = std::make_pair(flop_module, flop_past_q); +			} +			it = box_module->attributes.find("\\abc_carry");  			if (it != box_module->attributes.end()) {  				RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr;  				auto carry_in_out = it->second.decode_string(); @@ -782,23 +803,28 @@ void AigerReader::post_process()  				carry_out->port_id = ports.size();  			}  		} +		else { +			auto it = flop_data.find(cell->type); +			if (it != flop_data.end()) +				std::tie(flop_module,flop_past_q) = it->second; +		}  		// NB: Assume box_module->ports are sorted alphabetically  		//     (as RTLIL::Module::fixup_ports() would do)  		for (auto port_name : box_module->ports) { -			RTLIL::Wire* w = box_module->wire(port_name); -			log_assert(w); +			RTLIL::Wire* port = box_module->wire(port_name); +			log_assert(port);  			RTLIL::SigSpec rhs; -			RTLIL::Wire* wire = nullptr; -			for (int i = 0; i < GetSize(w); i++) { -				if (w->port_input) { +			for (int i = 0; i < GetSize(port); i++) { +				RTLIL::Wire* wire = nullptr; +				if (port->port_input) {  					log_assert(co_count < outputs.size());  					wire = outputs[co_count++];  					log_assert(wire);  					log_assert(wire->port_output);  					wire->port_output = false;  				} -				if (w->port_output) { +				if (port->port_output) {  					log_assert((piNum + ci_count) < inputs.size());  					wire = inputs[piNum + ci_count++];  					log_assert(wire); @@ -807,7 +833,25 @@ void AigerReader::post_process()  				}  				rhs.append(wire);  			} -			cell->setPort(port_name, rhs); + +			if (!flop_module || port_name != flop_past_q) +				cell->setPort(port_name, rhs); +		} + +		if (flop_module) { +			RTLIL::Wire *d = outputs[outputs.size() - flopNum + flop_count]; +			log_assert(d); +			log_assert(d->port_output); +			d->port_output = false; + +			RTLIL::Wire *q = inputs[piNum - flopNum + flop_count]; +			log_assert(q); +			log_assert(q->port_input); +			q->port_input = false; + +			flop_count++; +			cell->type = flop_module->name; +			module->connect(q, d);  		}  	} @@ -824,6 +868,7 @@ void AigerReader::post_process()  				RTLIL::Wire* wire = inputs[variable];  				log_assert(wire);  				log_assert(wire->port_input); +				log_debug("Renaming input %s", log_id(wire));  				if (index == 0) {  					// Cope with the fact that a CI might be identical @@ -850,6 +895,7 @@ void AigerReader::post_process()  						wire->port_input = false;  					}  				} +				log_debug(" -> %s\n", log_id(wire));  			}  			else if (type == "output") {  				log_assert(static_cast<unsigned>(variable + co_count) < outputs.size()); @@ -881,6 +927,7 @@ void AigerReader::post_process()  					else {  						wire->port_output = false;  						module->connect(wire, existing); +						wire = existing;  					}  				}  				else if (index > 0) { @@ -906,6 +953,11 @@ void AigerReader::post_process()  						wire->port_output = false;  					}  				} +				log_debug(" -> %s\n", log_id(wire)); +				int init; +				mf >> init; +				if (init < 2) +					wire->attributes["\\init"] = init;  			}  			else if (type == "box") {  				RTLIL::Cell* cell = module->cell(stringf("$__box%d__", variable)); @@ -1016,8 +1068,8 @@ struct AigerFrontend : public Frontend {  		log("        Name of module to be created (default: <filename>)\n");  		log("\n");  		log("    -clk_name <wire_name>\n"); -		log("        AIGER latches to be transformed into posedge DFFs clocked by wire of"); -		log("        this name (default: clk)\n"); +		log("        If specified, AIGER latches to be transformed into $_DFF_P_ cells\n"); +		log("        clocked by wire of this name. Otherwise, $_FF_ cells will be used.\n");  		log("\n");  		log("    -map <filename>\n");  		log("        read file with port and latch symbols\n");  | 
