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