mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Merge pull request #1926 from YosysHQ/eddie/abc9_auto_dff
abc9: support seq synthesis when module has (* abc9_flop *) and bypass non-combinatorial (* abc9_box *)
This commit is contained in:
		
						commit
						2d573a0ff6
					
				
					 34 changed files with 1663 additions and 1860 deletions
				
			
		|  | @ -76,9 +76,11 @@ void aiger_encode(std::ostream &f, int x) | ||||||
| 
 | 
 | ||||||
| struct XAigerWriter | struct XAigerWriter | ||||||
| { | { | ||||||
|  | 	Design *design; | ||||||
| 	Module *module; | 	Module *module; | ||||||
| 	SigMap sigmap; | 	SigMap sigmap; | ||||||
| 
 | 
 | ||||||
|  | 	dict<SigBit, State> init_map; | ||||||
| 	pool<SigBit> input_bits, output_bits; | 	pool<SigBit> input_bits, output_bits; | ||||||
| 	dict<SigBit, SigBit> not_map, alias_map; | 	dict<SigBit, SigBit> not_map, alias_map; | ||||||
| 	dict<SigBit, pair<SigBit, SigBit>> and_map; | 	dict<SigBit, pair<SigBit, SigBit>> and_map; | ||||||
|  | @ -137,7 +139,7 @@ struct XAigerWriter | ||||||
| 		return a; | 		return a; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	XAigerWriter(Module *module, bool holes_mode=false) : module(module), sigmap(module) | 	XAigerWriter(Module *module, bool dff_mode) : design(module->design), module(module), sigmap(module) | ||||||
| 	{ | 	{ | ||||||
| 		pool<SigBit> undriven_bits; | 		pool<SigBit> undriven_bits; | ||||||
| 		pool<SigBit> unused_bits; | 		pool<SigBit> unused_bits; | ||||||
|  | @ -157,7 +159,8 @@ struct XAigerWriter | ||||||
| 			if (wire->get_bool_attribute(ID::keep)) | 			if (wire->get_bool_attribute(ID::keep)) | ||||||
| 				sigmap.add(wire); | 				sigmap.add(wire); | ||||||
| 
 | 
 | ||||||
| 		for (auto wire : module->wires()) | 		for (auto wire : module->wires()) { | ||||||
|  | 			auto it = wire->attributes.find(ID::init); | ||||||
| 			for (int i = 0; i < GetSize(wire); i++) | 			for (int i = 0; i < GetSize(wire); i++) | ||||||
| 			{ | 			{ | ||||||
| 				SigBit wirebit(wire, i); | 				SigBit wirebit(wire, i); | ||||||
|  | @ -174,16 +177,26 @@ struct XAigerWriter | ||||||
| 				undriven_bits.insert(bit); | 				undriven_bits.insert(bit); | ||||||
| 				unused_bits.insert(bit); | 				unused_bits.insert(bit); | ||||||
| 
 | 
 | ||||||
| 				bool scc = wire->attributes.count(ID::abc9_scc); | 				bool keep = wire->get_bool_attribute(ID::abc9_keep); | ||||||
| 				if (wire->port_input || scc) | 				if (wire->port_input || keep) | ||||||
| 					input_bits.insert(bit); | 					input_bits.insert(bit); | ||||||
| 
 | 
 | ||||||
| 				bool keep = wire->get_bool_attribute(ID::keep); | 				keep = keep || wire->get_bool_attribute(ID::keep); | ||||||
| 				if (wire->port_output || keep || scc) { | 				if (wire->port_output || keep) { | ||||||
| 					if (bit != wirebit) | 					if (bit != wirebit) | ||||||
| 						alias_map[wirebit] = bit; | 						alias_map[wirebit] = bit; | ||||||
| 					output_bits.insert(wirebit); | 					output_bits.insert(wirebit); | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
|  | 				if (it != wire->attributes.end()) { | ||||||
|  | 					auto s = it->second[i]; | ||||||
|  | 					if (s != State::Sx) { | ||||||
|  | 						auto r = init_map.insert(std::make_pair(bit, it->second[i])); | ||||||
|  | 						if (!r.second && r.first->second != it->second[i]) | ||||||
|  | 							log_error("Bit '%s' has a conflicting (* init *) value.\n", log_signal(bit)); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		TimingInfo timing; | 		TimingInfo timing; | ||||||
|  | @ -212,10 +225,7 @@ struct XAigerWriter | ||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (cell->type == ID($__ABC9_FF_) && | 				if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) | ||||||
| 						// The presence of an abc9_mergeability attribute indicates
 |  | ||||||
| 						//   that we do want to pass this flop to ABC
 |  | ||||||
| 						cell->attributes.count(ID::abc9_mergeability)) |  | ||||||
| 				{ | 				{ | ||||||
| 					SigBit D = sigmap(cell->getPort(ID::D).as_bit()); | 					SigBit D = sigmap(cell->getPort(ID::D).as_bit()); | ||||||
| 					SigBit Q = sigmap(cell->getPort(ID::Q).as_bit()); | 					SigBit Q = sigmap(cell->getPort(ID::Q).as_bit()); | ||||||
|  | @ -231,31 +241,35 @@ struct XAigerWriter | ||||||
| 					continue; | 					continue; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Module* inst_module = module->design->module(cell->type); | 			RTLIL::Module* inst_module = design->module(cell->type); | ||||||
| 			if (inst_module) { | 			if (inst_module && inst_module->get_blackbox_attribute()) { | ||||||
| 				IdString derived_type = inst_module->derive(module->design, cell->parameters); |  | ||||||
| 				inst_module = module->design->module(derived_type); |  | ||||||
| 				log_assert(inst_module); |  | ||||||
| 
 |  | ||||||
| 				bool abc9_flop = false; | 				bool abc9_flop = false; | ||||||
| 				if (!cell->has_keep_attr()) { | 
 | ||||||
| 				auto it = cell->attributes.find(ID::abc9_box_seq); | 				auto it = cell->attributes.find(ID::abc9_box_seq); | ||||||
| 				if (it != cell->attributes.end()) { | 				if (it != cell->attributes.end()) { | ||||||
|  | 					log_assert(!cell->has_keep_attr()); | ||||||
| 					int abc9_box_seq = it->second.as_int(); | 					int abc9_box_seq = it->second.as_int(); | ||||||
| 					if (GetSize(box_list) <= abc9_box_seq) | 					if (GetSize(box_list) <= abc9_box_seq) | ||||||
| 						box_list.resize(abc9_box_seq+1); | 						box_list.resize(abc9_box_seq+1); | ||||||
| 					box_list[abc9_box_seq] = cell; | 					box_list[abc9_box_seq] = cell; | ||||||
| 					// Only flop boxes may have arrival times
 | 					// Only flop boxes may have arrival times
 | ||||||
| 					//   (all others are combinatorial)
 | 					//   (all others are combinatorial)
 | ||||||
|  | 					log_assert(cell->parameters.empty()); | ||||||
| 					abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop); | 					abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop); | ||||||
| 					if (!abc9_flop) | 					if (!abc9_flop) | ||||||
| 						continue; | 						continue; | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
|  | 				if (!cell->parameters.empty()) { | ||||||
|  | 					auto derived_type = inst_module->derive(design, cell->parameters); | ||||||
|  | 					inst_module = design->module(derived_type); | ||||||
|  | 					log_assert(inst_module); | ||||||
|  | 					log_assert(inst_module->get_blackbox_attribute()); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (!timing.count(derived_type)) | 				if (!timing.count(inst_module->name)) | ||||||
| 					timing.setup_module(inst_module); | 					timing.setup_module(inst_module); | ||||||
| 				auto &t = timing.at(derived_type).arrival; | 				auto &t = timing.at(inst_module->name).arrival; | ||||||
| 				for (const auto &conn : cell->connections()) { | 				for (const auto &conn : cell->connections()) { | ||||||
| 					auto port_wire = inst_module->wire(conn.first); | 					auto port_wire = inst_module->wire(conn.first); | ||||||
| 					if (!port_wire->port_output) | 					if (!port_wire->port_output) | ||||||
|  | @ -269,7 +283,7 @@ struct XAigerWriter | ||||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||||
| 						if (ys_debug(1)) { | 						if (ys_debug(1)) { | ||||||
| 							static std::set<std::tuple<IdString,IdString,int>> seen; | 							static std::set<std::tuple<IdString,IdString,int>> seen; | ||||||
| 							if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n", | 							if (seen.emplace(inst_module->name, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n", | ||||||
| 									log_id(cell->type), log_id(conn.first), i, d); | 									log_id(cell->type), log_id(conn.first), i, d); | ||||||
| 						} | 						} | ||||||
| #endif | #endif | ||||||
|  | @ -280,10 +294,6 @@ struct XAigerWriter | ||||||
| 				if (abc9_flop) | 				if (abc9_flop) | ||||||
| 					continue; | 					continue; | ||||||
| 			} | 			} | ||||||
| 			else { |  | ||||||
| 				if (cell->type == ID($__ABC9_DELAY)) |  | ||||||
| 					log_error("Cell type '%s' not recognised. Check that '+/abc9_model.v' has been read.\n", cell->type.c_str()); |  | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			bool cell_known = inst_module || cell->known(); | 			bool cell_known = inst_module || cell->known(); | ||||||
| 			for (const auto &c : cell->connections()) { | 			for (const auto &c : cell->connections()) { | ||||||
|  | @ -317,9 +327,9 @@ struct XAigerWriter | ||||||
| 		for (auto cell : box_list) { | 		for (auto cell : box_list) { | ||||||
| 			log_assert(cell); | 			log_assert(cell); | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Module* box_module = module->design->module(cell->type); | 			RTLIL::Module* box_module = design->module(cell->type); | ||||||
| 			log_assert(box_module); | 			log_assert(box_module); | ||||||
| 			log_assert(box_module->attributes.count(ID::abc9_box_id) || box_module->get_bool_attribute(ID::abc9_flop)); | 			log_assert(box_module->has_attribute(ID::abc9_box_id)); | ||||||
| 
 | 
 | ||||||
| 			auto r = box_ports.insert(cell->type); | 			auto r = box_ports.insert(cell->type); | ||||||
| 			if (r.second) { | 			if (r.second) { | ||||||
|  | @ -383,27 +393,6 @@ struct XAigerWriter | ||||||
| 						undriven_bits.erase(O); | 						undriven_bits.erase(O); | ||||||
| 					} | 					} | ||||||
| 			} | 			} | ||||||
| 
 |  | ||||||
| 			// Connect <cell>.abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box
 |  | ||||||
| 			if (box_module->get_bool_attribute(ID::abc9_flop)) { |  | ||||||
| 				SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str())); |  | ||||||
| 				if (rhs.empty()) |  | ||||||
| 					log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); |  | ||||||
| 
 |  | ||||||
| 				for (auto b : rhs) { |  | ||||||
| 					SigBit I = sigmap(b); |  | ||||||
| 					if (b == RTLIL::Sx) |  | ||||||
| 						b = State::S0; |  | ||||||
| 					else if (I != b) { |  | ||||||
| 						if (I == RTLIL::Sx) |  | ||||||
| 							alias_map[b] = State::S0; |  | ||||||
| 						else |  | ||||||
| 							alias_map[b] = I; |  | ||||||
| 					} |  | ||||||
| 					co_bits.emplace_back(b); |  | ||||||
| 					unused_bits.erase(I); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (auto bit : input_bits) | 		for (auto bit : input_bits) | ||||||
|  | @ -419,7 +408,6 @@ struct XAigerWriter | ||||||
| 			undriven_bits.erase(bit); | 			undriven_bits.erase(bit); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (holes_mode) { |  | ||||||
| 		struct sort_by_port_id { | 		struct sort_by_port_id { | ||||||
| 			bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { | 			bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { | ||||||
| 				return a.wire->port_id < b.wire->port_id || | 				return a.wire->port_id < b.wire->port_id || | ||||||
|  | @ -428,7 +416,6 @@ struct XAigerWriter | ||||||
| 		}; | 		}; | ||||||
| 		input_bits.sort(sort_by_port_id()); | 		input_bits.sort(sort_by_port_id()); | ||||||
| 		output_bits.sort(sort_by_port_id()); | 		output_bits.sort(sort_by_port_id()); | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		aig_map[State::S0] = 0; | 		aig_map[State::S0] = 0; | ||||||
| 		aig_map[State::S1] = 1; | 		aig_map[State::S1] = 1; | ||||||
|  | @ -589,17 +576,14 @@ struct XAigerWriter | ||||||
| 			int box_count = 0; | 			int box_count = 0; | ||||||
| 			for (auto cell : box_list) { | 			for (auto cell : box_list) { | ||||||
| 				log_assert(cell); | 				log_assert(cell); | ||||||
|  | 				log_assert(cell->parameters.empty()); | ||||||
| 
 | 
 | ||||||
| 				RTLIL::Module* box_module = module->design->module(cell->type); | 				auto r = cell_cache.insert(cell->type); | ||||||
| 				log_assert(box_module); |  | ||||||
| 
 |  | ||||||
| 				IdString derived_type = box_module->derive(box_module->design, cell->parameters); |  | ||||||
| 				box_module = box_module->design->module(derived_type); |  | ||||||
| 				log_assert(box_module); |  | ||||||
| 
 |  | ||||||
| 				auto r = cell_cache.insert(derived_type); |  | ||||||
| 				auto &v = r.first->second; | 				auto &v = r.first->second; | ||||||
| 				if (r.second) { | 				if (r.second) { | ||||||
|  | 					RTLIL::Module* box_module = design->module(cell->type); | ||||||
|  | 					log_assert(box_module); | ||||||
|  | 
 | ||||||
| 					int box_inputs = 0, box_outputs = 0; | 					int box_inputs = 0, box_outputs = 0; | ||||||
| 					for (auto port_name : box_module->ports) { | 					for (auto port_name : box_module->ports) { | ||||||
| 						RTLIL::Wire *w = box_module->wire(port_name); | 						RTLIL::Wire *w = box_module->wire(port_name); | ||||||
|  | @ -610,11 +594,6 @@ struct XAigerWriter | ||||||
| 							box_outputs += GetSize(w); | 							box_outputs += GetSize(w); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					// For flops only, create an extra 1-bit input that drives a new wire
 |  | ||||||
| 					//   called "<cell>.abc9_ff.Q" that is used below
 |  | ||||||
| 					if (box_module->get_bool_attribute(ID::abc9_flop)) |  | ||||||
| 						box_inputs++; |  | ||||||
| 
 |  | ||||||
| 					std::get<0>(v) = box_inputs; | 					std::get<0>(v) = box_inputs; | ||||||
| 					std::get<1>(v) = box_outputs; | 					std::get<1>(v) = box_outputs; | ||||||
| 					std::get<2>(v) = box_module->attributes.at(ID::abc9_box_id).as_int(); | 					std::get<2>(v) = box_module->attributes.at(ID::abc9_box_id).as_int(); | ||||||
|  | @ -635,23 +614,27 @@ struct XAigerWriter | ||||||
| 			auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); | 			auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); | ||||||
| 			write_s_buffer(ff_bits.size()); | 			write_s_buffer(ff_bits.size()); | ||||||
| 
 | 
 | ||||||
|  | 			dict<SigSpec, int> clk_to_mergeability; | ||||||
| 			for (const auto &i : ff_bits) { | 			for (const auto &i : ff_bits) { | ||||||
| 				const SigBit &d = i.first; | 				const SigBit &d = i.first; | ||||||
| 				const Cell *cell = i.second; | 				const Cell *cell = i.second; | ||||||
| 
 | 
 | ||||||
| 				int mergeability = cell->attributes.at(ID::abc9_mergeability).as_int(); | 				SigSpec clk_and_pol{sigmap(cell->getPort(ID::C)), cell->type[6] == 'P' ? State::S1 : State::S0}; | ||||||
|  | 				auto r = clk_to_mergeability.insert(std::make_pair(clk_and_pol, clk_to_mergeability.size()+1)); | ||||||
|  | 				int mergeability = r.first->second; | ||||||
| 				log_assert(mergeability > 0); | 				log_assert(mergeability > 0); | ||||||
| 				write_r_buffer(mergeability); | 				write_r_buffer(mergeability); | ||||||
| 
 | 
 | ||||||
| 				Const init = cell->attributes.at(ID::abc9_init, State::Sx); | 				SigBit Q = sigmap(cell->getPort(ID::Q)); | ||||||
| 				log_assert(GetSize(init) == 1); | 				State init = init_map.at(Q, State::Sx); | ||||||
|  | 				log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init)); | ||||||
| 				if (init == State::S1) | 				if (init == State::S1) | ||||||
| 					write_s_buffer(1); | 					write_s_buffer(1); | ||||||
| 				else if (init == State::S0) | 				else if (init == State::S0) | ||||||
| 					write_s_buffer(0); | 					write_s_buffer(0); | ||||||
| 				else { | 				else { | ||||||
| 					log_assert(init == State::Sx); | 					log_assert(init == State::Sx); | ||||||
| 					write_s_buffer(0); | 					write_s_buffer(2); | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				// Use arrival time from output of flop box
 | 				// Use arrival time from output of flop box
 | ||||||
|  | @ -671,10 +654,16 @@ struct XAigerWriter | ||||||
| 			f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be)); | 			f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be)); | ||||||
| 			f.write(buffer_str.data(), buffer_str.size()); | 			f.write(buffer_str.data(), buffer_str.size()); | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str())); | 			RTLIL::Design *holes_design; | ||||||
|  | 			auto it = saved_designs.find("$abc9_holes"); | ||||||
|  | 			if (it != saved_designs.end()) | ||||||
|  | 				holes_design = it->second; | ||||||
|  | 			else | ||||||
|  | 				holes_design = nullptr; | ||||||
|  | 			RTLIL::Module *holes_module = holes_design ? holes_design->module(module->name) : nullptr; | ||||||
| 			if (holes_module) { | 			if (holes_module) { | ||||||
| 				std::stringstream a_buffer; | 				std::stringstream a_buffer; | ||||||
| 				XAigerWriter writer(holes_module, true /* holes_mode */); | 				XAigerWriter writer(holes_module, false /* dff_mode */); | ||||||
| 				writer.write_aiger(a_buffer, false /*ascii_mode*/); | 				writer.write_aiger(a_buffer, false /*ascii_mode*/); | ||||||
| 
 | 
 | ||||||
| 				f << "a"; | 				f << "a"; | ||||||
|  | @ -704,10 +693,10 @@ struct XAigerWriter | ||||||
| 
 | 
 | ||||||
| 		f << stringf("Generated by %s\n", yosys_version_str); | 		f << stringf("Generated by %s\n", yosys_version_str); | ||||||
| 
 | 
 | ||||||
| 		module->design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); | 		design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); | ||||||
| 		module->design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); | 		design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); | ||||||
| 		module->design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size()); | 		design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size()); | ||||||
| 		module->design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); | 		design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void write_map(std::ostream &f) | 	void write_map(std::ostream &f) | ||||||
|  | @ -761,10 +750,10 @@ struct XAigerBackend : public Backend { | ||||||
| 		log("    write_xaiger [options] [filename]\n"); | 		log("    write_xaiger [options] [filename]\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Write the top module (according to the (* top *) attribute or if only one module\n"); | 		log("Write the top module (according to the (* top *) attribute or if only one module\n"); | ||||||
| 		log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, or"); | 		log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, (optionally\n"); | ||||||
| 		log("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n"); | 		log("$_DFF_N_, $_DFF_P_), or non (* abc9_box *) cells will be converted into psuedo-\n"); | ||||||
| 		log("pseudo-outputs. Whitebox contents will be taken from the '<module-name>$holes'\n"); | 		log("inputs and pseudo-outputs. Whitebox contents will be taken from the equivalent\n"); | ||||||
| 		log("module, if it exists.\n"); | 		log("module in the '$abc9_holes' design, if it exists.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -ascii\n"); | 		log("    -ascii\n"); | ||||||
| 		log("        write ASCII version of AIGER format\n"); | 		log("        write ASCII version of AIGER format\n"); | ||||||
|  | @ -772,10 +761,13 @@ struct XAigerBackend : public Backend { | ||||||
| 		log("    -map <filename>\n"); | 		log("    -map <filename>\n"); | ||||||
| 		log("        write an extra file with port and box symbols\n"); | 		log("        write an extra file with port and box symbols\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -dff\n"); | ||||||
|  | 		log("        write $_DFF_[NP]_ cells\n"); | ||||||
|  | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		bool ascii_mode = false; | 		bool ascii_mode = false, dff_mode = false; | ||||||
| 		std::string map_filename; | 		std::string map_filename; | ||||||
| 
 | 
 | ||||||
| 		log_header(design, "Executing XAIGER backend.\n"); | 		log_header(design, "Executing XAIGER backend.\n"); | ||||||
|  | @ -791,6 +783,10 @@ struct XAigerBackend : public Backend { | ||||||
| 				map_filename = args[++argidx]; | 				map_filename = args[++argidx]; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-dff") { | ||||||
|  | 				dff_mode = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		extra_args(f, filename, args, argidx, !ascii_mode); | 		extra_args(f, filename, args, argidx, !ascii_mode); | ||||||
|  | @ -808,7 +804,7 @@ struct XAigerBackend : public Backend { | ||||||
| 		if (!top_module->memories.empty()) | 		if (!top_module->memories.empty()) | ||||||
| 			log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module)); | 			log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module)); | ||||||
| 
 | 
 | ||||||
| 		XAigerWriter writer(top_module); | 		XAigerWriter writer(top_module, dff_mode); | ||||||
| 		writer.write_aiger(*f, ascii_mode); | 		writer.write_aiger(*f, ascii_mode); | ||||||
| 
 | 
 | ||||||
| 		if (!map_filename.empty()) { | 		if (!map_filename.empty()) { | ||||||
|  |  | ||||||
|  | @ -454,6 +454,14 @@ void AigerReader::parse_xaiger() | ||||||
| 			for (unsigned i = 0; i < flopNum; i++) | 			for (unsigned i = 0; i < flopNum; i++) | ||||||
| 				mergeability.emplace_back(parse_xaiger_literal(f)); | 				mergeability.emplace_back(parse_xaiger_literal(f)); | ||||||
| 		} | 		} | ||||||
|  | 		else if (c == 's') { | ||||||
|  | 			uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f); | ||||||
|  | 			flopNum = parse_xaiger_literal(f); | ||||||
|  | 			log_assert(dataSize == (flopNum+1) * sizeof(uint32_t)); | ||||||
|  | 			initial_state.reserve(flopNum); | ||||||
|  | 			for (unsigned i = 0; i < flopNum; i++) | ||||||
|  | 				initial_state.emplace_back(parse_xaiger_literal(f)); | ||||||
|  | 		} | ||||||
| 		else if (c == 'n') { | 		else if (c == 'n') { | ||||||
| 			parse_xaiger_literal(f); | 			parse_xaiger_literal(f); | ||||||
| 			f >> s; | 			f >> s; | ||||||
|  | @ -767,6 +775,7 @@ void AigerReader::post_process() | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	dict<int, Wire*> mergeability_to_clock; | ||||||
| 	for (uint32_t i = 0; i < flopNum; i++) { | 	for (uint32_t i = 0; i < flopNum; i++) { | ||||||
| 		RTLIL::Wire *d = outputs[outputs.size() - flopNum + i]; | 		RTLIL::Wire *d = outputs[outputs.size() - flopNum + i]; | ||||||
| 		log_assert(d); | 		log_assert(d); | ||||||
|  | @ -778,10 +787,9 @@ void AigerReader::post_process() | ||||||
| 		log_assert(q->port_input); | 		log_assert(q->port_input); | ||||||
| 		q->port_input = false; | 		q->port_input = false; | ||||||
| 
 | 
 | ||||||
| 		auto ff = module->addCell(NEW_ID, ID($__ABC9_FF_)); | 		Cell* ff = module->addFfGate(NEW_ID, d, q); | ||||||
| 		ff->setPort(ID::D, d); |  | ||||||
| 		ff->setPort(ID::Q, q); |  | ||||||
| 		ff->attributes[ID::abc9_mergeability] = mergeability[i]; | 		ff->attributes[ID::abc9_mergeability] = mergeability[i]; | ||||||
|  | 		q->attributes[ID::init] = initial_state[i]; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dict<RTLIL::IdString, std::pair<int,int>> wideports_cache; | 	dict<RTLIL::IdString, std::pair<int,int>> wideports_cache; | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ struct AigerReader | ||||||
|     std::vector<RTLIL::Wire*> outputs; |     std::vector<RTLIL::Wire*> outputs; | ||||||
|     std::vector<RTLIL::Wire*> bad_properties; |     std::vector<RTLIL::Wire*> bad_properties; | ||||||
|     std::vector<RTLIL::Cell*> boxes; |     std::vector<RTLIL::Cell*> boxes; | ||||||
|     std::vector<int> mergeability; |     std::vector<int> mergeability, initial_state; | ||||||
| 
 | 
 | ||||||
|     AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); |     AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); | ||||||
|     void parse_aiger(); |     void parse_aiger(); | ||||||
|  |  | ||||||
|  | @ -2,13 +2,12 @@ X(A) | ||||||
| X(abc9_box) | X(abc9_box) | ||||||
| X(abc9_box_id) | X(abc9_box_id) | ||||||
| X(abc9_box_seq) | X(abc9_box_seq) | ||||||
|  | X(abc9_bypass) | ||||||
| X(abc9_carry) | X(abc9_carry) | ||||||
| X(abc9_flop) | X(abc9_flop) | ||||||
| X(abc9_holes) | X(abc9_keep) | ||||||
| X(abc9_init) |  | ||||||
| X(abc9_lut) | X(abc9_lut) | ||||||
| X(abc9_mergeability) | X(abc9_mergeability) | ||||||
| X(abc9_scc) |  | ||||||
| X(abc9_scc_id) | X(abc9_scc_id) | ||||||
| X(abcgroup) | X(abcgroup) | ||||||
| X(ABITS) | X(ABITS) | ||||||
|  |  | ||||||
|  | @ -82,6 +82,9 @@ struct TimingInfo | ||||||
| 
 | 
 | ||||||
| 		for (auto cell : module->cells()) { | 		for (auto cell : module->cells()) { | ||||||
| 			if (cell->type == ID($specify2)) { | 			if (cell->type == ID($specify2)) { | ||||||
|  | 				auto en = cell->getPort(ID::EN); | ||||||
|  | 				if (en.is_fully_const() && !en.as_bool()) | ||||||
|  | 					continue; | ||||||
| 				auto src = cell->getPort(ID::SRC); | 				auto src = cell->getPort(ID::SRC); | ||||||
| 				auto dst = cell->getPort(ID::DST); | 				auto dst = cell->getPort(ID::DST); | ||||||
| 				for (const auto &c : src.chunks()) | 				for (const auto &c : src.chunks()) | ||||||
|  | @ -128,11 +131,9 @@ struct TimingInfo | ||||||
| 				int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); | 				int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); | ||||||
| 				int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); | 				int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); | ||||||
| 				int max = std::max(rise_max,fall_max); | 				int max = std::max(rise_max,fall_max); | ||||||
| 				if (max < 0) | 				if (max < 0) { | ||||||
| 					log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); | 					log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); | ||||||
| 				if (max <= 0) { | 					max = 0; | ||||||
| 					log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); |  | ||||||
| 					continue; |  | ||||||
| 				} | 				} | ||||||
| 				for (const auto &d : dst) { | 				for (const auto &d : dst) { | ||||||
| 					auto &v = t.arrival[NameBit(d)]; | 					auto &v = t.arrival[NameBit(d)]; | ||||||
|  | @ -152,11 +153,9 @@ struct TimingInfo | ||||||
| 					if (!c.wire->port_input) | 					if (!c.wire->port_input) | ||||||
| 						log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); | 						log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); | ||||||
| 				int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); | 				int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); | ||||||
| 				if (max < 0) | 				if (max < 0) { | ||||||
| 					log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); | 					log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell)); | ||||||
| 				if (max <= 0) { | 					max = 0; | ||||||
| 					log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); |  | ||||||
| 					continue; |  | ||||||
| 				} | 				} | ||||||
| 				for (const auto &s : src) { | 				for (const auto &s : src) { | ||||||
| 					auto &v = t.required[NameBit(s)]; | 					auto &v = t.required[NameBit(s)]; | ||||||
|  |  | ||||||
|  | @ -151,8 +151,8 @@ struct Abc9Pass : public ScriptPass | ||||||
| 		log("        specified).\n"); | 		log("        specified).\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -dff\n"); | 		log("    -dff\n"); | ||||||
| 		log("        also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n"); | 		log("        also pass $_DFF_[NP]_ cells through to ABC. modules with many clock\n"); | ||||||
| 		log("        domains are marked as such and automatically partitioned by ABC.\n"); | 		log("        domains are supported and automatically partitioned by ABC.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -nocleanup\n"); | 		log("    -nocleanup\n"); | ||||||
| 		log("        when this option is used, the temporary files created by this pass\n"); | 		log("        when this option is used, the temporary files created by this pass\n"); | ||||||
|  | @ -274,40 +274,106 @@ struct Abc9Pass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 	void script() YS_OVERRIDE | 	void script() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
|  | 		if (check_label("check")) { | ||||||
|  | 			if (help_mode) | ||||||
|  | 				run("abc9_ops -check [-dff]", "(option if -dff)"); | ||||||
|  | 			else | ||||||
|  | 				run(stringf("abc9_ops -check %s", dff_mode ? "-dff" : "")); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (check_label("map")) { | ||||||
|  | 			if (help_mode) | ||||||
|  | 				run("abc9_ops -prep_hier -prep_bypass [-prep_dff -dff]", "(option if -dff)"); | ||||||
|  | 			else | ||||||
|  | 				run(stringf("abc9_ops -prep_hier -prep_bypass %s", dff_mode ? "-prep_dff -dff" : "")); | ||||||
|  | 			if (dff_mode) { | ||||||
|  | 				run("design -copy-to $abc9_map @$abc9_flops", "(only if -dff)"); | ||||||
|  | 				run("select -unset $abc9_flops", "             (only if -dff)"); | ||||||
|  | 			} | ||||||
|  | 			run("design -stash $abc9"); | ||||||
|  | 			run("design -load $abc9_map"); | ||||||
|  | 			run("proc"); | ||||||
|  | 			run("wbflip"); | ||||||
|  | 			run("techmap"); | ||||||
|  | 			run("opt"); | ||||||
|  | 			if (dff_mode || help_mode) { | ||||||
|  | 				if (!help_mode) | ||||||
|  | 					active_design->scratchpad_unset("abc9_ops.prep_dff_submod.did_something"); | ||||||
|  | 				run("abc9_ops -prep_dff_submod", "                                                 (only if -dff)"); // rewrite specify
 | ||||||
|  | 				bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_submod.did_something"); | ||||||
|  | 				if (did_something) { | ||||||
|  | 										// select all $_DFF_[NP]_
 | ||||||
|  | 										// then select all its fanins
 | ||||||
|  | 										// then select all fanouts of all that
 | ||||||
|  | 										// lastly remove $_DFF_[NP]_ cells
 | ||||||
|  | 					run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d", "       (only if -dff)"); | ||||||
|  | 					run("submod", "                                                                    (only if -dff)"); | ||||||
|  | 					run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop", "(only if -dff)"); | ||||||
|  | 					if (help_mode) { | ||||||
|  | 						run("foreach module in design"); | ||||||
|  | 						run("    rename <module-name>_$abc9_flop _TECHMAP_REPLACE_", "                     (only if -dff)"); | ||||||
|  | 					} | ||||||
|  | 					else { | ||||||
|  | 						// Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs
 | ||||||
|  | 						for (auto module : active_design->selected_modules()) { | ||||||
|  | 							active_design->selected_active_module = module->name.str(); | ||||||
|  | 							if (module->cell(stringf("%s_$abc9_flop", module->name.c_str()))) | ||||||
|  | 								run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str())); | ||||||
|  | 						} | ||||||
|  | 						active_design->selected_active_module.clear(); | ||||||
|  | 					} | ||||||
|  | 					run("abc9_ops -prep_dff_unmap", "                                                  (only if -dff)"); | ||||||
|  | 					run("design -copy-to $abc9 =*_$abc9_flop", "                                       (only if -dff)"); // copy submod out
 | ||||||
|  | 					run("delete =*_$abc9_flop", "                                                      (only if -dff)"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			run("design -stash $abc9_map"); | ||||||
|  | 			run("design -load $abc9"); | ||||||
|  | 			run("design -delete $abc9"); | ||||||
|  | 			if (help_mode) | ||||||
|  | 				run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF]", "(option if -dff)"); | ||||||
|  | 			else | ||||||
|  | 				run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : "")); | ||||||
|  | 			run("design -delete $abc9_map"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if (check_label("pre")) { | 		if (check_label("pre")) { | ||||||
| 			run("abc9_ops -check"); | 			run("read_verilog -icells -lib -specify +/abc9_model.v"); | ||||||
| 			run("scc -set_attr abc9_scc_id {}"); | 			run("scc -set_attr abc9_scc_id {}"); | ||||||
| 			if (help_mode) | 			if (help_mode) | ||||||
| 				run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); | 				run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); | ||||||
| 			else | 			else | ||||||
| 				run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); | 				run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : "")); | ||||||
| 			if (help_mode) | 			if (help_mode) | ||||||
| 				run("abc9_ops -prep_lut <maxlut>", "(skip if -lut or -luts)"); | 				run("abc9_ops -prep_lut <maxlut>", "(skip if -lut or -luts)"); | ||||||
| 			else if (!lut_mode) | 			else if (!lut_mode) | ||||||
| 				run(stringf("abc9_ops -prep_lut %d", maxlut)); | 				run(stringf("abc9_ops -prep_lut %d", maxlut)); | ||||||
| 			if (help_mode) | 			if (help_mode) | ||||||
| 				run("abc9_ops -prep_box [-dff]", "(skip if -box)"); | 				run("abc9_ops -prep_box", "(skip if -box)"); | ||||||
| 			else if (box_file.empty()) | 			else if (box_file.empty()) | ||||||
| 				run(stringf("abc9_ops -prep_box %s", dff_mode ? "-dff" : "")); | 				run("abc9_ops -prep_box"); | ||||||
| 			run("select -set abc9_holes A:abc9_holes"); | 			if (saved_designs.count("$abc9_holes") || help_mode) { | ||||||
| 			run("flatten -wb @abc9_holes"); | 				run("design -stash $abc9"); | ||||||
| 			run("techmap @abc9_holes"); | 				run("design -load $abc9_holes"); | ||||||
| 			if (dff_mode || help_mode) | 				run("techmap -wb -map %$abc9 -map +/techmap.v"); | ||||||
| 				run("abc9_ops -prep_dff", "(only if -dff)"); | 				run("opt -purge"); | ||||||
| 			run("opt -purge @abc9_holes"); |  | ||||||
| 				run("aigmap"); | 				run("aigmap"); | ||||||
| 			run("wbflip @abc9_holes"); | 				run("design -stash $abc9_holes"); | ||||||
|  | 				run("design -load $abc9"); | ||||||
|  | 				run("design -delete $abc9"); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map")) { | 		if (check_label("exe")) { | ||||||
|  | 			run("aigmap"); | ||||||
| 			if (help_mode) { | 			if (help_mode) { | ||||||
| 				run("foreach module in selection"); | 				run("foreach module in selection"); | ||||||
| 				run("    abc9_ops -write_lut <abc-temp-dir>/input.lut", "(skip if '-lut' or '-luts')"); | 				run("    abc9_ops -write_lut <abc-temp-dir>/input.lut", "(skip if '-lut' or '-luts')"); | ||||||
| 				run("    abc9_ops -write_box <abc-temp-dir>/input.box"); | 				run("    abc9_ops -write_box <abc-temp-dir>/input.box", "(skip if '-box')"); | ||||||
| 				run("    write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig"); | 				run("    write_xaiger -map <abc-temp-dir>/input.sym [-dff] <abc-temp-dir>/input.xaig"); | ||||||
| 				run("    abc9_exe [options] -cwd <abc-temp-dir> [-lut <abc-temp-dir>/input.lut] -box <abc-temp-dir>/input.box"); | 				run("    abc9_exe [options] -cwd <abc-temp-dir> -lut [<abc-temp-dir>/input.lut] -box [<abc-temp-dir>/input.box]"); | ||||||
| 				run("    read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig"); | 				run("    read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig"); | ||||||
| 				run("    abc9_ops -reintegrate"); | 				run("    abc9_ops -reintegrate [-dff]"); | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
| 				auto selected_modules = active_design->selected_modules(); | 				auto selected_modules = active_design->selected_modules(); | ||||||
|  | @ -318,7 +384,6 @@ struct Abc9Pass : public ScriptPass | ||||||
| 						log("Skipping module %s as it contains processes.\n", log_id(mod)); | 						log("Skipping module %s as it contains processes.\n", log_id(mod)); | ||||||
| 						continue; | 						continue; | ||||||
| 					} | 					} | ||||||
| 					log_assert(!mod->attributes.count(ID::abc9_box_id)); |  | ||||||
| 
 | 
 | ||||||
| 					log_push(); | 					log_push(); | ||||||
| 					active_design->selection().select(mod); | 					active_design->selection().select(mod); | ||||||
|  | @ -333,8 +398,9 @@ struct Abc9Pass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 					if (!lut_mode) | 					if (!lut_mode) | ||||||
| 						run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); | 						run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); | ||||||
|  | 					if (box_file.empty()) | ||||||
| 						run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); | 						run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); | ||||||
| 					run_nocheck(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); | 					run_nocheck(stringf("write_xaiger -map %s/input.sym %s %s/input.xaig", tempdir_name.c_str(), dff_mode ? "-dff" : "", tempdir_name.c_str())); | ||||||
| 
 | 
 | ||||||
| 					int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); | 					int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); | ||||||
| 
 | 
 | ||||||
|  | @ -349,10 +415,13 @@ struct Abc9Pass : public ScriptPass | ||||||
| 						abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str()); | 						abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str()); | ||||||
| 						if (!lut_mode) | 						if (!lut_mode) | ||||||
| 							abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str()); | 							abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str()); | ||||||
|  | 						if (box_file.empty()) | ||||||
| 							abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); | 							abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); | ||||||
|  | 						else | ||||||
|  | 							abc9_exe_cmd += stringf(" -box %s", box_file.c_str()); | ||||||
| 						run_nocheck(abc9_exe_cmd); | 						run_nocheck(abc9_exe_cmd); | ||||||
| 						run_nocheck(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_nocheck(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_nocheck("abc9_ops -reintegrate"); | 						run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : "")); | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
| 						log("Don't call ABC as there is nothing to map.\n"); | 						log("Don't call ABC as there is nothing to map.\n"); | ||||||
|  | @ -369,6 +438,14 @@ struct Abc9Pass : public ScriptPass | ||||||
| 				active_design->selection_stack.pop_back(); | 				active_design->selection_stack.pop_back(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		if (check_label("unmap")) { | ||||||
|  | 			run("techmap -wb -map %$abc9_unmap -map +/abc9_unmap.v"); 	// techmap user design from submod back to original cell
 | ||||||
|  | 											//   ($_DFF_[NP]_ already shorted by -reintegrate)
 | ||||||
|  | 			run("design -delete $abc9_unmap"); | ||||||
|  | 			if (saved_designs.count("$abc9_holes") || help_mode) | ||||||
|  | 				run("design -delete $abc9_holes"); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } Abc9Pass; | } Abc9Pass; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -30,4 +30,6 @@ $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) | ||||||
| $(eval $(call add_share_file,share,techlibs/common/cells.lib)) | $(eval $(call add_share_file,share,techlibs/common/cells.lib)) | ||||||
| $(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) | $(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) | ||||||
| $(eval $(call add_share_file,share,techlibs/common/abc9_model.v)) | $(eval $(call add_share_file,share,techlibs/common/abc9_model.v)) | ||||||
|  | $(eval $(call add_share_file,share,techlibs/common/abc9_map.v)) | ||||||
|  | $(eval $(call add_share_file,share,techlibs/common/abc9_unmap.v)) | ||||||
| $(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v)) | $(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v)) | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								techlibs/common/abc9_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								techlibs/common/abc9_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | `ifdef DFF | ||||||
|  | (* techmap_celltype = "$_DFF_N_ $_DFF_P_" *) | ||||||
|  | module $_DFF_x_(input C, D, output Q); | ||||||
|  |   parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx; | ||||||
|  |   parameter _TECHMAP_CELLTYPE_ = ""; | ||||||
|  |   wire D_; | ||||||
|  |   generate if (_TECHMAP_CELLTYPE_ == "$_DFF_N_") begin | ||||||
|  |     if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin | ||||||
|  |       $__DFF_N__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); | ||||||
|  |       $_DFF_N_ ff (.C(C), .D(D_), .Q(Q)); | ||||||
|  |     end | ||||||
|  |     else | ||||||
|  |       (* abc9_keep *) $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); | ||||||
|  |   end | ||||||
|  |   else if (_TECHMAP_CELLTYPE_ == "$_DFF_P_") begin | ||||||
|  |     if (_TECHMAP_WIREINIT_Q_ === 1'b0) begin | ||||||
|  |       $__DFF_P__$abc9_flop _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q), .n1(D_)); | ||||||
|  |       $_DFF_P_ ff (.C(C), .D(D_), .Q(Q)); | ||||||
|  |     end | ||||||
|  |     else | ||||||
|  |       (* abc9_keep *) $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); | ||||||
|  |   end | ||||||
|  |   else if (_TECHMAP_CELLTYPE_ != "") | ||||||
|  |     $error("Unrecognised _TECHMAP_CELLTYPE_"); | ||||||
|  |   endgenerate | ||||||
|  | endmodule | ||||||
|  | `endif | ||||||
|  | @ -1,10 +1,25 @@ | ||||||
| module \$__ABC9_FF_ (input D, output Q); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| (* abc9_box *) | (* abc9_box *) | ||||||
| module \$__ABC9_DELAY (input I, output O); | module $__ABC9_DELAY (input I, output O); | ||||||
|   parameter DELAY = 0; |   parameter DELAY = 0; | ||||||
|   specify |   specify | ||||||
|     (I => O) = DELAY; |     (I => O) = DELAY; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
|  | 
 | ||||||
|  | (* abc9_flop, abc9_box, lib_whitebox *) | ||||||
|  | module $__DFF_N__$abc9_flop (input C, D, Q, output n1); | ||||||
|  |   assign n1 = D; | ||||||
|  |   specify | ||||||
|  |     $setup(D, posedge C, 0); | ||||||
|  |     (posedge C => (n1:D)) = 0; | ||||||
|  |   endspecify | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* abc9_flop, abc9_box, lib_whitebox *) | ||||||
|  | module $__DFF_P__$abc9_flop (input C, D, Q, output n1); | ||||||
|  |   assign n1 = D; | ||||||
|  |   specify | ||||||
|  |     $setup(D, posedge C, 0); | ||||||
|  |     (posedge C => (n1:D)) = 0; | ||||||
|  |   endspecify | ||||||
|  | endmodule | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								techlibs/common/abc9_unmap.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								techlibs/common/abc9_unmap.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | (* techmap_celltype = "$__DFF_N__$abc9_flop $__DFF_P__$abc9_flop" *) | ||||||
|  | module $__DFF_x__$abc9_flop (input C, D, Q, output n1); | ||||||
|  |   parameter _TECHMAP_CELLTYPE_ = ""; | ||||||
|  |   generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N__$abc9_flop") | ||||||
|  |     $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); | ||||||
|  |   else if (_TECHMAP_CELLTYPE_ == "$__DFF_P__$abc9_flop") | ||||||
|  |     $_DFF_P_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); | ||||||
|  |   else if (_TECHMAP_CELLTYPE_ != "") | ||||||
|  |     $error("Unrecognised _TECHMAP_CELLTYPE_"); | ||||||
|  |   endgenerate | ||||||
|  | endmodule | ||||||
|  | @ -23,9 +23,6 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams.txt)) | ||||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) | $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v)) | ||||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v)) | $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v)) | ||||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v)) | $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v)) | ||||||
| 
 |  | ||||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_map.v)) |  | ||||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_unmap.v)) |  | ||||||
| $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_model.v)) | $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc9_model.v)) | ||||||
| 
 | 
 | ||||||
| EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk | EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk | ||||||
|  |  | ||||||
|  | @ -1,27 +0,0 @@ | ||||||
| // --------------------------------------- |  | ||||||
| 
 |  | ||||||
| // Attach a (combinatorial) black-box onto the output |  | ||||||
| //   of this LUTRAM primitive to capture its |  | ||||||
| //   asynchronous read behaviour |  | ||||||
| module TRELLIS_DPR16X4 ( |  | ||||||
| 	(* techmap_autopurge *) input  [3:0] DI, |  | ||||||
| 	(* techmap_autopurge *) input  [3:0] WAD, |  | ||||||
| 	(* techmap_autopurge *) input        WRE, |  | ||||||
| 	(* techmap_autopurge *) input        WCK, |  | ||||||
| 	(* techmap_autopurge *) input  [3:0] RAD, |  | ||||||
| 	output [3:0] DO |  | ||||||
| ); |  | ||||||
| 	parameter WCKMUX = "WCK"; |  | ||||||
| 	parameter WREMUX = "WRE"; |  | ||||||
| 	parameter [63:0] INITVAL = 64'h0000000000000000; |  | ||||||
|     wire [3:0] $DO; |  | ||||||
| 
 |  | ||||||
|     TRELLIS_DPR16X4 #( |  | ||||||
|       .WCKMUX(WCKMUX), .WREMUX(WREMUX), .INITVAL(INITVAL) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .DI(DI), .WAD(WAD), .WRE(WRE), .WCK(WCK), |  | ||||||
|       .RAD(RAD), .DO($DO) |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     $__ABC9_DPR16X4_COMB do (.$DO($DO), .RAD(RAD), .DO(DO)); |  | ||||||
| endmodule |  | ||||||
|  | @ -1,5 +0,0 @@ | ||||||
| // --------------------------------------- |  | ||||||
| 
 |  | ||||||
| module \$__ABC9_DPR16X4_COMB (input [3:0] $DO, RAD, output [3:0] DO); |  | ||||||
|     assign DO = $DO; |  | ||||||
| endmodule |  | ||||||
|  | @ -186,6 +186,7 @@ module PFUMX (input ALUT, BLUT, C0, output Z); | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------- | // --------------------------------------- | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module TRELLIS_DPR16X4 ( | module TRELLIS_DPR16X4 ( | ||||||
| 	input  [3:0] DI, | 	input  [3:0] DI, | ||||||
| 	input  [3:0] WAD, | 	input  [3:0] WAD, | ||||||
|  | @ -222,10 +223,16 @@ module TRELLIS_DPR16X4 ( | ||||||
| 			mem[WAD] <= DI; | 			mem[WAD] <= DI; | ||||||
| 
 | 
 | ||||||
| 	assign DO = mem[RAD]; | 	assign DO = mem[RAD]; | ||||||
|  | 
 | ||||||
|  | 	specify | ||||||
|  | 		// TODO | ||||||
|  | 		(RAD *> DO) = 0; | ||||||
|  | 	endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------- | // --------------------------------------- | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module DPR16X4C ( | module DPR16X4C ( | ||||||
| 		input [3:0] DI, | 		input [3:0] DI, | ||||||
| 		input WCK, WRE, | 		input WCK, WRE, | ||||||
|  | @ -281,6 +288,10 @@ module DPR16X4C ( | ||||||
| 
 | 
 | ||||||
| 	assign DO = ram[RAD]; | 	assign DO = ram[RAD]; | ||||||
| 
 | 
 | ||||||
|  | 	specify | ||||||
|  | 		// TODO | ||||||
|  | 		(RAD *> DO) = 0; | ||||||
|  | 	endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------- | // --------------------------------------- | ||||||
|  | @ -294,6 +305,9 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------- | // --------------------------------------- | ||||||
| 
 | 
 | ||||||
|  | `ifdef YOSYS | ||||||
|  | (* abc9_flop=(SRMODE != "ASYNC"), abc9_box=(SRMODE == "ASYNC"), lib_whitebox *) | ||||||
|  | `endif | ||||||
| module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); | module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); | ||||||
| 	parameter GSR = "ENABLED"; | 	parameter GSR = "ENABLED"; | ||||||
| 	parameter [127:0] CEMUX = "1"; | 	parameter [127:0] CEMUX = "1"; | ||||||
|  | @ -340,6 +354,38 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); | ||||||
| 					Q <= DI; | 					Q <= DI; | ||||||
| 		end | 		end | ||||||
| 	endgenerate | 	endgenerate | ||||||
|  | 
 | ||||||
|  | 	generate | ||||||
|  | 		// TODO | ||||||
|  | 		if (CLKMUX == "INV") | ||||||
|  | 			specify | ||||||
|  | 				$setup(DI, negedge CLK, 0); | ||||||
|  | 				$setup(CE, negedge CLK, 0); | ||||||
|  | 				$setup(LSR, negedge CLK, 0); | ||||||
|  | `ifndef YOSYS | ||||||
|  | 				if (SRMODE == "ASYNC" && muxlsr) (negedge CLK => (Q : srval)) = 0; | ||||||
|  | `else | ||||||
|  | 				if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; 	// Technically, this should be an edge sensitive path | ||||||
|  | 											// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 											// a simple path | ||||||
|  | `endif | ||||||
|  | 				if (!muxlsr && muxce) (negedge CLK => (Q : DI)) = 0; | ||||||
|  | 			endspecify | ||||||
|  | 		else | ||||||
|  | 			specify | ||||||
|  | 				$setup(DI, posedge CLK, 0); | ||||||
|  | 				$setup(CE, posedge CLK, 0); | ||||||
|  | 				$setup(LSR, posedge CLK, 0); | ||||||
|  | `ifndef YOSYS | ||||||
|  | 				if (SRMODE == "ASYNC" && muxlsr) (posedge CLK => (Q : srval)) = 0; | ||||||
|  | `else | ||||||
|  | 				if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; 	// Technically, this should be an edge sensitive path | ||||||
|  | 											// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 											// a simple path | ||||||
|  | `endif | ||||||
|  | 				if (!muxlsr && muxce) (posedge CLK => (Q : DI)) = 0; | ||||||
|  | 			endspecify | ||||||
|  | 	endgenerate | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| // --------------------------------------- | // --------------------------------------- | ||||||
|  |  | ||||||
|  | @ -66,6 +66,9 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 		log("    -noflatten\n"); | 		log("    -noflatten\n"); | ||||||
| 		log("        do not flatten design before synthesis\n"); | 		log("        do not flatten design before synthesis\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -dff\n"); | ||||||
|  | 		log("        run 'abc'/'abc9' with -dff option\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("    -retime\n"); | 		log("    -retime\n"); | ||||||
| 		log("        run 'abc' with '-dff -D 1' options\n"); | 		log("        run 'abc' with '-dff -D 1' options\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | @ -107,7 +110,7 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	string top_opt, blif_file, edif_file, json_file; | 	string top_opt, blif_file, edif_file, json_file; | ||||||
| 	bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, retime, abc2, abc9, nodsp, vpr; | 	bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, nodsp, vpr; | ||||||
| 
 | 
 | ||||||
| 	void clear_flags() YS_OVERRIDE | 	void clear_flags() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
|  | @ -122,6 +125,7 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 		nowidelut = false; | 		nowidelut = false; | ||||||
| 		asyncprld = false; | 		asyncprld = false; | ||||||
| 		flatten = true; | 		flatten = true; | ||||||
|  | 		dff = false; | ||||||
| 		retime = false; | 		retime = false; | ||||||
| 		abc2 = false; | 		abc2 = false; | ||||||
| 		vpr = false; | 		vpr = false; | ||||||
|  | @ -169,6 +173,10 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 				flatten = false; | 				flatten = false; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-dff") { | ||||||
|  | 				dff = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			if (args[argidx] == "-retime") { | 			if (args[argidx] == "-retime") { | ||||||
| 				retime = true; | 				retime = true; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -307,6 +315,8 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 			run("opt_clean"); | 			run("opt_clean"); | ||||||
| 			if (!nodffe) | 			if (!nodffe) | ||||||
| 				run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); | 				run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); | ||||||
|  | 			if ((abc9 && dff) || help_mode) | ||||||
|  | 				run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff"); | ||||||
| 			run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : ""))); | 			run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : ""))); | ||||||
| 			run("opt_expr -undriven -mux_undef"); | 			run("opt_expr -undriven -mux_undef"); | ||||||
| 			run("simplemap"); | 			run("simplemap"); | ||||||
|  | @ -318,17 +328,13 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map_luts")) | 		if (check_label("map_luts")) | ||||||
| 		{ | 		{ | ||||||
| 			if (abc2 || help_mode) { | 			if (abc2 || help_mode) | ||||||
| 				run("abc", "      (only if -abc2)"); | 				run("abc", "      (only if -abc2)"); | ||||||
| 			} | 			if (!asyncprld || help_mode) | ||||||
| 			std::string techmap_args = asyncprld ? "" : "-map +/ecp5/latches_map.v"; | 				run("techmap -map +/ecp5/latches_map.v", "(skip if -asyncprld)"); | ||||||
| 			if (abc9) |  | ||||||
| 				techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1"; |  | ||||||
| 			if (!asyncprld || abc9) |  | ||||||
| 				run("techmap " + techmap_args); |  | ||||||
| 
 | 
 | ||||||
| 			if (abc9) { | 			if (abc9) { | ||||||
| 				run("read_verilog -icells -lib -specify +/abc9_model.v +/ecp5/abc9_model.v"); | 				run("read_verilog -icells -lib -specify +/ecp5/abc9_model.v"); | ||||||
| 				std::string abc9_opts; | 				std::string abc9_opts; | ||||||
| 				if (nowidelut) | 				if (nowidelut) | ||||||
| 					abc9_opts += " -maxlut 4"; | 					abc9_opts += " -maxlut 4"; | ||||||
|  | @ -338,26 +344,29 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 				else | 				else | ||||||
| 					abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); | 					abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); | ||||||
| 				if (nowidelut) | 				if (nowidelut) | ||||||
| 					run("abc9 -maxlut 4 -W 200"); | 					abc9_opts += " -maxlut 4"; | ||||||
| 				else | 				if (dff) | ||||||
| 					run("abc9 -W 200"); | 					abc9_opts += " -dff"; | ||||||
| 				run("techmap -map +/ecp5/abc9_unmap.v"); | 				run("abc9" + abc9_opts); | ||||||
| 			} else { | 			} else { | ||||||
|  | 				std::string abc_args = " -dress"; | ||||||
| 				if (nowidelut) | 				if (nowidelut) | ||||||
| 					run("abc -lut 4 -dress"); | 					abc_args += " -lut 4"; | ||||||
| 				else | 				else | ||||||
| 					run("abc -lut 4:7 -dress"); | 					abc_args += " -lut 4:7"; | ||||||
|  | 				if (dff) | ||||||
|  | 					abc_args += " -dff"; | ||||||
|  | 				run("abc" + abc_args); | ||||||
| 			} | 			} | ||||||
| 			run("clean"); | 			run("clean"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map_cells")) | 		if (check_label("map_cells")) | ||||||
| 		{ | 		{ | ||||||
| 			if (vpr) | 			if (help_mode) | ||||||
| 				run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); | 				run("techmap -map +/ecp5/cells_map.v", "(skip if -vpr)"); | ||||||
| 			else | 			else if (!vpr) | ||||||
| 				run("techmap -map +/ecp5/cells_map.v", "(with -D NO_LUT in vpr mode)"); | 				run("techmap -map +/ecp5/cells_map.v"); | ||||||
| 
 |  | ||||||
| 			run("opt_lut_ins -tech ecp5"); | 			run("opt_lut_ins -tech ecp5"); | ||||||
| 			run("clean"); | 			run("clean"); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ techlibs/ice40/brams_init3.vh: techlibs/ice40/brams_init.mk | ||||||
| 
 | 
 | ||||||
| $(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v)) | $(eval $(call add_share_file,share/ice40,techlibs/ice40/arith_map.v)) | ||||||
| $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v)) | $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_map.v)) | ||||||
|  | $(eval $(call add_share_file,share/ice40,techlibs/ice40/ff_map.v)) | ||||||
| $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) | $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v)) | ||||||
| $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) | $(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v)) | ||||||
| $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) | $(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt)) | ||||||
|  |  | ||||||
|  | @ -1,33 +1,3 @@ | ||||||
| module  \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule |  | ||||||
| module  \$_DFF_P_ (input D, C, output Q); SB_DFF  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule |  | ||||||
| 
 |  | ||||||
| module  \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule |  | ||||||
| module  \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule |  | ||||||
| 
 |  | ||||||
| module  \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule |  | ||||||
| module  \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule |  | ||||||
| 
 |  | ||||||
| module  \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule |  | ||||||
| module  \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule |  | ||||||
| module  \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule |  | ||||||
| module  \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule |  | ||||||
| 
 |  | ||||||
| module  \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule |  | ||||||
| module  \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule |  | ||||||
| module  \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule |  | ||||||
| module  \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule |  | ||||||
| 
 |  | ||||||
| module  \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule |  | ||||||
| module  \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule |  | ||||||
| module  \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule |  | ||||||
| module  \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule |  | ||||||
| 
 |  | ||||||
| module  \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule |  | ||||||
| module  \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule |  | ||||||
| module  \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule |  | ||||||
| module  \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule |  | ||||||
| 
 |  | ||||||
| `ifndef NO_LUT |  | ||||||
| module \$lut (A, Y); | module \$lut (A, Y); | ||||||
|   parameter WIDTH = 0; |   parameter WIDTH = 0; | ||||||
|   parameter LUT = 0; |   parameter LUT = 0; | ||||||
|  | @ -59,4 +29,3 @@ module \$lut (A, Y); | ||||||
|     end |     end | ||||||
|   endgenerate |   endgenerate | ||||||
| endmodule | endmodule | ||||||
| `endif |  | ||||||
|  |  | ||||||
|  | @ -245,6 +245,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // Positive Edge SiliconBlue FF Cells | // Positive Edge SiliconBlue FF Cells | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFF ( | module SB_DFF ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, D | 	input C, D | ||||||
|  | @ -280,6 +281,7 @@ module SB_DFF ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFE ( | module SB_DFFE ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, D | 	input C, E, D | ||||||
|  | @ -322,6 +324,7 @@ module SB_DFFE ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFSR ( | module SB_DFFSR ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, R, D | 	input C, R, D | ||||||
|  | @ -369,6 +372,7 @@ module SB_DFFSR ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SB_DFFR ( | module SB_DFFR ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, R, D | 	input C, R, D | ||||||
|  | @ -386,7 +390,13 @@ module SB_DFFR ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||||
| 		$setup(negedge R, posedge C, 160); | 		$setup(negedge R, posedge C, 160); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 599; | 		(posedge R => (Q : 1'b0)) = 599; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 599;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | ||||||
| 		if (!R) (posedge C => (Q : D)) = 540; | 		if (!R) (posedge C => (Q : D)) = 540; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -399,7 +409,13 @@ module SB_DFFR ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||||
| 		$setup(negedge R, posedge C, 235); | 		$setup(negedge R, posedge C, 235); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 883; | 		(posedge R => (Q : 1'b0)) = 883; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 883;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | ||||||
| 		if (!R) (posedge C => (Q : D)) = 796; | 		if (!R) (posedge C => (Q : D)) = 796; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -412,13 +428,20 @@ module SB_DFFR ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||||
| 		$setup(negedge R, posedge C, 424); | 		$setup(negedge R, posedge C, 424); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 1589; | 		(posedge R => (Q : 1'b0)) = 1589; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 1589;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | ||||||
| 		if (!R) (posedge C => (Q : D)) = 1391; | 		if (!R) (posedge C => (Q : D)) = 1391; | ||||||
| 	endspecify | 	endspecify | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFSS ( | module SB_DFFSS ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, S, D | 	input C, S, D | ||||||
|  | @ -466,6 +489,7 @@ module SB_DFFSS ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SB_DFFS ( | module SB_DFFS ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, S, D | 	input C, S, D | ||||||
|  | @ -483,7 +507,13 @@ module SB_DFFS ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||||
| 		$setup(negedge S, posedge C, 160); | 		$setup(negedge S, posedge C, 160); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 599; | 		(posedge S => (Q : 1'b1)) = 599; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 599;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | ||||||
| 		if (!S) (posedge C => (Q : D)) = 540; | 		if (!S) (posedge C => (Q : D)) = 540; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -496,7 +526,13 @@ module SB_DFFS ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||||
| 		$setup(negedge S, posedge C, 235); | 		$setup(negedge S, posedge C, 235); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 883; | 		(posedge S => (Q : 1'b1)) = 883; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 883;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | ||||||
| 		if (!S) (posedge C => (Q : D)) = 796; | 		if (!S) (posedge C => (Q : D)) = 796; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -509,13 +545,20 @@ module SB_DFFS ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||||
| 		$setup(negedge S, posedge C, 424); | 		$setup(negedge S, posedge C, 424); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 1589; | 		(posedge S => (Q : 1'b1)) = 1589; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | ||||||
| 		if (!S) (posedge C => (Q : D)) = 1391; | 		if (!S) (posedge C => (Q : D)) = 1391; | ||||||
| 	endspecify | 	endspecify | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFESR ( | module SB_DFFESR ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, R, D | 	input C, E, R, D | ||||||
|  | @ -571,6 +614,7 @@ module SB_DFFESR ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SB_DFFER ( | module SB_DFFER ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, R, D | 	input C, E, R, D | ||||||
|  | @ -590,7 +634,13 @@ module SB_DFFER ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||||
| 		$setup(negedge R, posedge C, 160); | 		$setup(negedge R, posedge C, 160); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 599; | 		(posedge R => (Q : 1'b0)) = 599; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 599;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | ||||||
| 		if (E && !R) (posedge C => (Q : D)) = 540; | 		if (E && !R) (posedge C => (Q : D)) = 540; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -605,7 +655,13 @@ module SB_DFFER ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||||
| 		$setup(negedge R, posedge C, 235); | 		$setup(negedge R, posedge C, 235); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 883; | 		(posedge R => (Q : 1'b0)) = 883; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 883; 	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | ||||||
| 		if (E && !R) (posedge C => (Q : D)) = 796; | 		if (E && !R) (posedge C => (Q : D)) = 796; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -620,13 +676,20 @@ module SB_DFFER ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||||
| 		$setup(negedge R, posedge C, 424); | 		$setup(negedge R, posedge C, 424); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 1589; | 		(posedge R => (Q : 1'b0)) = 1589; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 1589;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | ||||||
| 		if (E && !R) (posedge C => (Q : D)) = 1391; | 		if (E && !R) (posedge C => (Q : D)) = 1391; | ||||||
| 	endspecify | 	endspecify | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFESS ( | module SB_DFFESS ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, S, D | 	input C, E, S, D | ||||||
|  | @ -682,6 +745,7 @@ module SB_DFFESS ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SB_DFFES ( | module SB_DFFES ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, S, D | 	input C, E, S, D | ||||||
|  | @ -701,7 +765,13 @@ module SB_DFFES ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||||
| 		$setup(posedge S, posedge C, 160); | 		$setup(posedge S, posedge C, 160); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 599; | 		(posedge S => (Q : 1'b1)) = 599; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 599;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | ||||||
| 		if (E && !S) (posedge C => (Q : D)) = 540; | 		if (E && !S) (posedge C => (Q : D)) = 540; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -716,7 +786,13 @@ module SB_DFFES ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||||
| 		$setup(posedge S, posedge C, 235); | 		$setup(posedge S, posedge C, 235); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 883; | 		(posedge S => (Q : 1'b1)) = 883; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path | ||||||
|  | 							   // but for facilitating a bypass box, let's pretend it's | ||||||
|  | 							   // a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | ||||||
| 		if (E && !S) (posedge C => (Q : D)) = 796; | 		if (E && !S) (posedge C => (Q : D)) = 796; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -731,7 +807,13 @@ module SB_DFFES ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||||
| 		$setup(posedge S, posedge C, 424); | 		$setup(posedge S, posedge C, 424); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 1589; | 		(posedge S => (Q : 1'b1)) = 1589; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path | ||||||
|  | 							   // but for facilitating a bypass box, let's pretend it's | ||||||
|  | 							   // a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | ||||||
| 		if (E && !S) (posedge C => (Q : D)) = 1391; | 		if (E && !S) (posedge C => (Q : D)) = 1391; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -740,6 +822,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // Negative Edge SiliconBlue FF Cells | // Negative Edge SiliconBlue FF Cells | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFN ( | module SB_DFFN ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, D | 	input C, D | ||||||
|  | @ -775,6 +858,7 @@ module SB_DFFN ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFNE ( | module SB_DFFNE ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, D | 	input C, E, D | ||||||
|  | @ -817,6 +901,7 @@ module SB_DFFNE ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFNSR ( | module SB_DFFNSR ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, R, D | 	input C, R, D | ||||||
|  | @ -864,6 +949,7 @@ module SB_DFFNSR ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFNR ( | module SB_DFFNR ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, R, D | 	input C, R, D | ||||||
|  | @ -881,7 +967,13 @@ module SB_DFFNR ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||||
| 		$setup(negedge R, negedge C, 160); | 		$setup(negedge R, negedge C, 160); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 599; | 		(posedge R => (Q : 1'b0)) = 599; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 599;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | ||||||
| 		if (!R) (negedge C => (Q : D)) = 540; | 		if (!R) (negedge C => (Q : D)) = 540; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -894,7 +986,13 @@ module SB_DFFNR ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||||
| 		$setup(negedge R, negedge C, 235); | 		$setup(negedge R, negedge C, 235); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 883; | 		(posedge R => (Q : 1'b0)) = 883; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 883;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | ||||||
| 		if (!R) (negedge C => (Q : D)) = 796; | 		if (!R) (negedge C => (Q : D)) = 796; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -907,13 +1005,20 @@ module SB_DFFNR ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||||
| 		$setup(negedge R, negedge C, 424); | 		$setup(negedge R, negedge C, 424); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 1589; | 		(posedge R => (Q : 1'b0)) = 1589; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 1589;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | ||||||
| 		if (!R) (negedge C => (Q : D)) = 1391; | 		if (!R) (negedge C => (Q : D)) = 1391; | ||||||
| 	endspecify | 	endspecify | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFNSS ( | module SB_DFFNSS ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, S, D | 	input C, S, D | ||||||
|  | @ -961,6 +1066,7 @@ module SB_DFFNSS ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SB_DFFNS ( | module SB_DFFNS ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, S, D | 	input C, S, D | ||||||
|  | @ -978,7 +1084,13 @@ module SB_DFFNS ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||||
| 		$setup(negedge S, negedge C, 160); | 		$setup(negedge S, negedge C, 160); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 599; | 		(posedge S => (Q : 1'b1)) = 599; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 599;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | ||||||
| 		if (!S) (negedge C => (Q : D)) = 540; | 		if (!S) (negedge C => (Q : D)) = 540; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -991,7 +1103,13 @@ module SB_DFFNS ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||||
| 		$setup(negedge S, negedge C, 235); | 		$setup(negedge S, negedge C, 235); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 883; | 		(posedge S => (Q : 1'b1)) = 883; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 883;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | ||||||
| 		if (!S) (negedge C => (Q : D)) = 796; | 		if (!S) (negedge C => (Q : D)) = 796; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -1004,13 +1122,20 @@ module SB_DFFNS ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||||
| 		$setup(negedge S, negedge C, 424); | 		$setup(negedge S, negedge C, 424); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 1589; | 		(posedge S => (Q : 1'b1)) = 1589; | ||||||
|  | `else | ||||||
|  | 		if (S) (S => Q) = 1589;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | ||||||
| 		if (!S) (negedge C => (Q : D)) = 1391; | 		if (!S) (negedge C => (Q : D)) = 1391; | ||||||
| 	endspecify | 	endspecify | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFNESR ( | module SB_DFFNESR ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, R, D | 	input C, E, R, D | ||||||
|  | @ -1066,6 +1191,7 @@ module SB_DFFNESR ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SB_DFFNER ( | module SB_DFFNER ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, R, D | 	input C, E, R, D | ||||||
|  | @ -1085,7 +1211,13 @@ module SB_DFFNER ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||||
| 		$setup(R, negedge C, 2160); | 		$setup(R, negedge C, 2160); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 599; | 		(posedge R => (Q : 1'b0)) = 599; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 599;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | ||||||
| 		if (E && !R) (negedge C => (Q : D)) = 540; | 		if (E && !R) (negedge C => (Q : D)) = 540; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -1100,7 +1232,13 @@ module SB_DFFNER ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||||
| 		$setup(R, negedge C, 235); | 		$setup(R, negedge C, 235); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 883; | 		(posedge R => (Q : 1'b0)) = 883; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 883;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | ||||||
| 		if (E && !R) (negedge C => (Q : D)) = 796; | 		if (E && !R) (negedge C => (Q : D)) = 796; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -1115,13 +1253,20 @@ module SB_DFFNER ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||||
| 		$setup(negedge R, negedge C, 424); | 		$setup(negedge R, negedge C, 424); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge R => (Q : 1'b0)) = 1589; | 		(posedge R => (Q : 1'b0)) = 1589; | ||||||
|  | `else | ||||||
|  | 		if (R) (R => Q) = 1589;	// Technically, this should be an edge sensitive path | ||||||
|  | 					// but for facilitating a bypass box, let's pretend it's | ||||||
|  | 					// a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | ||||||
| 		if (E && !R) (negedge C => (Q : D)) = 1391; | 		if (E && !R) (negedge C => (Q : D)) = 1391; | ||||||
| 	endspecify | 	endspecify | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_flop, lib_whitebox *) | ||||||
| module SB_DFFNESS ( | module SB_DFFNESS ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, S, D | 	input C, E, S, D | ||||||
|  | @ -1177,6 +1322,7 @@ module SB_DFFNESS ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SB_DFFNES ( | module SB_DFFNES ( | ||||||
| 	output `SB_DFF_REG, | 	output `SB_DFF_REG, | ||||||
| 	input C, E, S, D | 	input C, E, S, D | ||||||
|  | @ -1196,7 +1342,14 @@ module SB_DFFNES ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||||
| 		$setup(negedge S, negedge C, 160); | 		$setup(negedge S, negedge C, 160); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 599; | 		(posedge S => (Q : 1'b1)) = 599; | ||||||
|  | `else | ||||||
|  |         if (S) (S => Q) = 599; // Technically, this should be an edge sensitive path | ||||||
|  |                                // but for facilitating a bypass box, let's pretend it's | ||||||
|  |                                // a simple path | ||||||
|  | `endif | ||||||
|  | 
 | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90 | ||||||
| 		if (E && !S) (negedge C => (Q : D)) = 540; | 		if (E && !S) (negedge C => (Q : D)) = 540; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -1211,7 +1364,13 @@ module SB_DFFNES ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||||
| 		$setup(negedge S, negedge C, 235); | 		$setup(negedge S, negedge C, 235); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 883; | 		(posedge S => (Q : 1'b1)) = 883; | ||||||
|  | `else | ||||||
|  |         if (S) (S => Q) = 883; // Technically, this should be an edge sensitive path | ||||||
|  |                                // but for facilitating a bypass box, let's pretend it's | ||||||
|  |                                // a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90 | ||||||
| 		if (E && !S) (negedge C => (Q : D)) = 796; | 		if (E && !S) (negedge C => (Q : D)) = 796; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -1226,7 +1385,13 @@ module SB_DFFNES ( | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||||
| 		$setup(negedge S, negedge C, 424); | 		$setup(negedge S, negedge C, 424); | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||||
|  | `ifndef YOSYS | ||||||
| 		(posedge S => (Q : 1'b1)) = 1589; | 		(posedge S => (Q : 1'b1)) = 1589; | ||||||
|  | `else | ||||||
|  |         if (S) (S => Q) = 1589; // Technically, this should be an edge sensitive path | ||||||
|  |                                // but for facilitating a bypass box, let's pretend it's | ||||||
|  |                                // a simple path | ||||||
|  | `endif | ||||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102 | ||||||
| 		if (E && !S) (negedge C => (Q : D)) = 1391; | 		if (E && !S) (negedge C => (Q : D)) = 1391; | ||||||
| 	endspecify | 	endspecify | ||||||
|  | @ -2723,6 +2888,7 @@ module SB_IO_OD ( | ||||||
| `endif | `endif | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | //(* abc9_box, lib_whitebox *) // TODO | ||||||
| module SB_MAC16 ( | module SB_MAC16 ( | ||||||
| 	input CLK, CE, | 	input CLK, CE, | ||||||
| 	input [15:0] C, A, B, D, | 	input [15:0] C, A, B, D, | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								techlibs/ice40/ff_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								techlibs/ice40/ff_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | module  \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule | ||||||
|  | module  \$_DFF_P_ (input D, C, output Q); SB_DFF  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule | ||||||
|  | module  \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule | ||||||
|  | module  \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule | ||||||
|  | module  \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule | ||||||
|  | module  \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule | ||||||
|  | module  \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule | ||||||
|  | module  \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule | ||||||
|  | module  \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule | ||||||
|  | module  \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule | ||||||
|  | module  \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule | ||||||
|  | module  \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule | ||||||
|  | module  \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule | ||||||
|  | 
 | ||||||
|  | module  \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule | ||||||
|  | module  \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule | ||||||
|  | module  \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule | ||||||
|  | module  \$__DFFE_PP1 (input D, C, E, R, output Q); SB_DFFES  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule | ||||||
|  | @ -71,6 +71,9 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 		log("    -noflatten\n"); | 		log("    -noflatten\n"); | ||||||
| 		log("        do not flatten design before synthesis\n"); | 		log("        do not flatten design before synthesis\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -dff\n"); | ||||||
|  | 		log("        run 'abc'/'abc9' with -dff option\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("    -retime\n"); | 		log("    -retime\n"); | ||||||
| 		log("        run 'abc' with '-dff -D 1' options\n"); | 		log("        run 'abc' with '-dff -D 1' options\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | @ -113,7 +116,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	string top_opt, blif_file, edif_file, json_file, device_opt; | 	string top_opt, blif_file, edif_file, json_file, device_opt; | ||||||
| 	bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, flowmap; | 	bool nocarry, nodffe, nobram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap; | ||||||
| 	int min_ce_use; | 	int min_ce_use; | ||||||
| 
 | 
 | ||||||
| 	void clear_flags() YS_OVERRIDE | 	void clear_flags() YS_OVERRIDE | ||||||
|  | @ -221,6 +224,10 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 				abc9 = true; | 				abc9 = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-dff") { | ||||||
|  | 				dff = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			if (args[argidx] == "-device" && argidx+1 < args.size()) { | 			if (args[argidx] == "-device" && argidx+1 < args.size()) { | ||||||
| 				device_opt = args[++argidx]; | 				device_opt = args[++argidx]; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -354,7 +361,9 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 				run(stringf("dff2dffe -unmap-mince %d", min_ce_use)); | 				run(stringf("dff2dffe -unmap-mince %d", min_ce_use)); | ||||||
| 				run("simplemap t:$dff"); | 				run("simplemap t:$dff"); | ||||||
| 			} | 			} | ||||||
| 			run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v"); | 			if ((abc9 && dff) || help_mode) | ||||||
|  | 				run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "(only if -abc9 and -dff"); | ||||||
|  | 			run("techmap -map +/ice40/ff_map.v"); | ||||||
| 			run("opt_expr -mux_undef"); | 			run("opt_expr -mux_undef"); | ||||||
| 			run("simplemap"); | 			run("simplemap"); | ||||||
| 			run("ice40_ffinit"); | 			run("ice40_ffinit"); | ||||||
|  | @ -378,7 +387,7 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 			} | 			} | ||||||
| 			if (!noabc) { | 			if (!noabc) { | ||||||
| 				if (abc9) { | 				if (abc9) { | ||||||
| 					run("read_verilog " + define + " -icells -lib -specify +/abc9_model.v +/ice40/abc9_model.v"); | 					run("read_verilog " + define + " -icells -lib -specify +/ice40/abc9_model.v"); | ||||||
| 					std::string abc9_opts; | 					std::string abc9_opts; | ||||||
| 					std::string k = "synth_ice40.abc9.W"; | 					std::string k = "synth_ice40.abc9.W"; | ||||||
| 					if (active_design && active_design->scratchpad.count(k)) | 					if (active_design && active_design->scratchpad.count(k)) | ||||||
|  | @ -387,24 +396,25 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 						k = stringf("synth_ice40.abc9.%s.W", device_opt.c_str()); | 						k = stringf("synth_ice40.abc9.%s.W", device_opt.c_str()); | ||||||
| 						abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); | 						abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); | ||||||
| 					} | 					} | ||||||
|  | 					if (dff) | ||||||
|  | 						abc9_opts += " -dff"; | ||||||
| 					run("abc9 " + abc9_opts); | 					run("abc9 " + abc9_opts); | ||||||
| 				} | 				} | ||||||
| 				else | 				else | ||||||
| 					run("abc -dress -lut 4", "(skip if -noabc)"); | 					run(stringf("abc -dress -lut 4 %s", dff ? "-dff" : ""), "(skip if -noabc)"); | ||||||
| 			} | 			} | ||||||
| 			run("ice40_wrapcarry -unwrap"); | 			run("ice40_wrapcarry -unwrap"); | ||||||
| 			run("techmap -D NO_LUT -map +/ice40/cells_map.v"); | 			run("techmap -map +/ice40/ff_map.v"); | ||||||
| 			run("clean"); | 			run("clean"); | ||||||
| 			run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); | 			run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map_cells")) | 		if (check_label("map_cells")) | ||||||
| 		{ | 		{ | ||||||
| 			if (vpr) | 			if (help_mode) | ||||||
| 				run("techmap -D NO_LUT -map +/ice40/cells_map.v"); | 				run("techmap -map +/ice40/cells_map.v", "(skip if -vpr)"); | ||||||
| 			else | 			else if (!vpr) | ||||||
| 				run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)"); | 				run("techmap -map +/ice40/cells_map.v"); | ||||||
| 
 |  | ||||||
| 			run("clean"); | 			run("clean"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -209,7 +209,6 @@ struct SynthIntelALMPass : public ScriptPass { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map_luts")) { | 		if (check_label("map_luts")) { | ||||||
| 			run("read_verilog -icells -specify -lib +/abc9_model.v"); |  | ||||||
| 			run("abc9 -maxlut 6 -W 200"); | 			run("abc9 -maxlut 6 -W 200"); | ||||||
| 			run("techmap -map +/intel_alm/common/alm_map.v"); | 			run("techmap -map +/intel_alm/common/alm_map.v"); | ||||||
| 			run("opt -fast"); | 			run("opt -fast"); | ||||||
|  |  | ||||||
|  | @ -54,8 +54,6 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc5v_dsp_map.v)) | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v)) | $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_dsp_map.v)) | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v)) | $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xcu_dsp_map.v)) | ||||||
| 
 | 
 | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_map.v)) |  | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_unmap.v)) |  | ||||||
| $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_model.v)) | $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc9_model.v)) | ||||||
| 
 | 
 | ||||||
| $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) | $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh)) | ||||||
|  |  | ||||||
|  | @ -1,786 +0,0 @@ | ||||||
| /* |  | ||||||
|  *  yosys -- Yosys Open SYnthesis Suite |  | ||||||
|  * |  | ||||||
|  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> |  | ||||||
|  *                2019  Eddie Hung    <eddie@fpgeh.com> |  | ||||||
|  * |  | ||||||
|  *  Permission to use, copy, modify, and/or distribute this software for any |  | ||||||
|  *  purpose with or without fee is hereby granted, provided that the above |  | ||||||
|  *  copyright notice and this permission notice appear in all copies. |  | ||||||
|  * |  | ||||||
|  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |  | ||||||
|  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |  | ||||||
|  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |  | ||||||
|  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |  | ||||||
|  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |  | ||||||
|  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |  | ||||||
|  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| // The following techmapping rules are intended to be run (with -max_iter 1) |  | ||||||
| //   before invoking the `abc9` pass in order to transform the design into |  | ||||||
| //   a format that it understands. |  | ||||||
| 
 |  | ||||||
| `ifdef DFF_MODE |  | ||||||
| // For example, (complex) flip-flops are expected to be described as an |  | ||||||
| //   combinatorial box (containing all control logic such as clock enable |  | ||||||
| //   or synchronous resets) followed by a basic D-Q flop. |  | ||||||
| // Yosys will automatically analyse the simulation model (described in |  | ||||||
| //   cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in |  | ||||||
| //   order to extract the combinatorial control logic left behind. |  | ||||||
| //   Specifically, a simulation model similar to the one below: |  | ||||||
| // |  | ||||||
| //                ++===================================++ |  | ||||||
| //                ||                        Sim model  || |  | ||||||
| //                ||      /\/\/\/\                     || |  | ||||||
| //            D -->>-----<        >     +------+       || |  | ||||||
| //            R -->>-----<  Comb. >     |$_DFF_|       || |  | ||||||
| //           CE -->>-----<  logic >-----| [NP]_|---+---->>-- Q |  | ||||||
| //                ||  +--<        >     +------+   |   || |  | ||||||
| //                ||  |   \/\/\/\/                 |   || |  | ||||||
| //                ||  |                            |   || |  | ||||||
| //                ||  +----------------------------+   || |  | ||||||
| //                ||                                   || |  | ||||||
| //                ++===================================++ |  | ||||||
| // |  | ||||||
| //   is transformed into: |  | ||||||
| // |  | ||||||
| //                ++==================++ |  | ||||||
| //                ||         Comb box || |  | ||||||
| //                ||                  || |  | ||||||
| //                ||      /\/\/\/\    || |  | ||||||
| //           D  -->>-----<        >   || |  | ||||||
| //           R  -->>-----<  Comb. >   ||        +-----------+ |  | ||||||
| //          CE  -->>-----<  logic >--->>-- $Q --|$__ABC9_FF_|--+-->> Q |  | ||||||
| //   abc9_ff.Q +-->>-----<        >   ||        +-----------+  | |  | ||||||
| //             |  ||      \/\/\/\/    ||                       | |  | ||||||
| //             |  ||                  ||                       | |  | ||||||
| //             |  ++==================++                       | |  | ||||||
| //             |                                               | |  | ||||||
| //             +-----------------------------------------------+ |  | ||||||
| // |  | ||||||
| // The purpose of the following FD* rules are to wrap the flop with: |  | ||||||
| // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9 |  | ||||||
| //     the connectivity of its basic D-Q flop |  | ||||||
| // (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to |  | ||||||
| //     capture asynchronous behaviour |  | ||||||
| // (c) a special abc9_ff.clock wire to capture its clock domain and polarity |  | ||||||
| //     (indicated to `abc9' so that it only performs sequential synthesis |  | ||||||
| //     (with reachability analysis) correctly on one domain at a time) |  | ||||||
| // (d) an (* abc9_init *) attribute on the $__ABC9_FF_ cell capturing its |  | ||||||
| //     initial state |  | ||||||
| //     NOTE: in order to perform sequential synthesis, `abc9' requires that |  | ||||||
| //     the initial value of all flops be zero |  | ||||||
| // (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, (* 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; |  | ||||||
|   parameter [0:0] IS_R_INVERTED = 1'b0; |  | ||||||
|   wire QQ, $Q; |  | ||||||
|   generate if (INIT == 1'b1) begin |  | ||||||
|     assign Q = ~QQ; |  | ||||||
|     FDSE #( |  | ||||||
|       .INIT(1'b0), |  | ||||||
|       .IS_C_INVERTED(IS_C_INVERTED), |  | ||||||
|       .IS_D_INVERTED(IS_D_INVERTED), |  | ||||||
|       .IS_S_INVERTED(IS_R_INVERTED) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) |  | ||||||
|     ); |  | ||||||
|   end |  | ||||||
|   else begin |  | ||||||
|     assign Q = QQ; |  | ||||||
|     FDRE #( |  | ||||||
|       .INIT(1'b0), |  | ||||||
|       .IS_C_INVERTED(IS_C_INVERTED), |  | ||||||
|       .IS_D_INVERTED(IS_D_INVERTED), |  | ||||||
|       .IS_R_INVERTED(IS_R_INVERTED) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .R(R) |  | ||||||
|     ); |  | ||||||
|   end |  | ||||||
|   endgenerate |  | ||||||
|   (* abc9_init = 1'b0 *) |  | ||||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); |  | ||||||
| 
 |  | ||||||
|   // Special signals |  | ||||||
|   wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; |  | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; |  | ||||||
| endmodule |  | ||||||
| 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 |  | ||||||
|     assign Q = ~QQ; |  | ||||||
|     FDSE_1 #( |  | ||||||
|       .INIT(1'b0) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .S(R) |  | ||||||
|     ); |  | ||||||
|   end |  | ||||||
|   else begin |  | ||||||
|     assign Q = QQ; |  | ||||||
|     FDRE_1 #( |  | ||||||
|       .INIT(1'b0) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .R(R) |  | ||||||
|     ); |  | ||||||
|   end |  | ||||||
|   endgenerate |  | ||||||
|   (* abc9_init = 1'b0 *) |  | ||||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); |  | ||||||
| 
 |  | ||||||
|   // Special signals |  | ||||||
|   wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; |  | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| 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; |  | ||||||
|   parameter [0:0] IS_S_INVERTED = 1'b0; |  | ||||||
|   wire QQ, $Q; |  | ||||||
|   generate if (INIT == 1'b1) begin |  | ||||||
|     assign Q = ~QQ; |  | ||||||
|     FDRE #( |  | ||||||
|       .INIT(1'b0), |  | ||||||
|       .IS_C_INVERTED(IS_C_INVERTED), |  | ||||||
|       .IS_D_INVERTED(IS_D_INVERTED), |  | ||||||
|       .IS_R_INVERTED(IS_S_INVERTED) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) |  | ||||||
|     ); |  | ||||||
|   end |  | ||||||
|   else begin |  | ||||||
|     assign Q = QQ; |  | ||||||
|     FDSE #( |  | ||||||
|       .INIT(1'b0), |  | ||||||
|       .IS_C_INVERTED(IS_C_INVERTED), |  | ||||||
|       .IS_D_INVERTED(IS_D_INVERTED), |  | ||||||
|       .IS_S_INVERTED(IS_S_INVERTED) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .S(S) |  | ||||||
|     ); |  | ||||||
|   end endgenerate |  | ||||||
|   (* abc9_init = 1'b0 *) |  | ||||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); |  | ||||||
| 
 |  | ||||||
|   // Special signals |  | ||||||
|   wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; |  | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; |  | ||||||
| endmodule |  | ||||||
| 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 |  | ||||||
|     assign Q = ~QQ; |  | ||||||
|     FDRE_1 #( |  | ||||||
|       .INIT(1'b0) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .R(S) |  | ||||||
|     ); |  | ||||||
|   end |  | ||||||
|   else begin |  | ||||||
|     assign Q = QQ; |  | ||||||
|     FDSE_1 #( |  | ||||||
|       .INIT(1'b0) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .S(S) |  | ||||||
|     ); |  | ||||||
|   end endgenerate |  | ||||||
|   (* abc9_init = 1'b0 *) |  | ||||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ)); |  | ||||||
| 
 |  | ||||||
|   // Special signals |  | ||||||
|   wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; |  | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ; |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| 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; |  | ||||||
|   parameter [0:0] IS_CLR_INVERTED = 1'b0; |  | ||||||
|   wire QQ, $Q, $QQ; |  | ||||||
|   generate if (INIT == 1'b1) begin |  | ||||||
|     assign Q = ~QQ; |  | ||||||
|     FDPE #( |  | ||||||
|       .INIT(1'b0), |  | ||||||
|       .IS_C_INVERTED(IS_C_INVERTED), |  | ||||||
|       .IS_D_INVERTED(IS_D_INVERTED), |  | ||||||
|       .IS_PRE_INVERTED(IS_CLR_INVERTED) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) |  | ||||||
|                                         // ^^^ Note that async |  | ||||||
|                                         //     control is not directly |  | ||||||
|                                         //     supported by abc9 but its |  | ||||||
|                                         //     behaviour is captured by |  | ||||||
|                                         //     $__ABC9_ASYNC1 below |  | ||||||
|     ); |  | ||||||
|     // Since this is an async flop, async behaviour is dealt with here |  | ||||||
|     $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); |  | ||||||
|   end |  | ||||||
|   else begin |  | ||||||
|     assign Q = QQ; |  | ||||||
|     FDCE #( |  | ||||||
|       .INIT(1'b0), |  | ||||||
|       .IS_C_INVERTED(IS_C_INVERTED), |  | ||||||
|       .IS_D_INVERTED(IS_D_INVERTED), |  | ||||||
|       .IS_CLR_INVERTED(IS_CLR_INVERTED) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) |  | ||||||
|                                        // ^^^ Note that async |  | ||||||
|                                        //     control is not directly |  | ||||||
|                                        //     supported by abc9 but its |  | ||||||
|                                        //     behaviour is captured by |  | ||||||
|                                        //     $__ABC9_ASYNC0 below |  | ||||||
|     ); |  | ||||||
|     // Since this is an async flop, async behaviour is dealt with here |  | ||||||
|     $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); |  | ||||||
|   end endgenerate |  | ||||||
|   (* abc9_init = 1'b0 *) |  | ||||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); |  | ||||||
| 
 |  | ||||||
|   // Special signals |  | ||||||
|   wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; |  | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; |  | ||||||
| endmodule |  | ||||||
| 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 |  | ||||||
|     assign Q = ~QQ; |  | ||||||
|     FDPE_1 #( |  | ||||||
|       .INIT(1'b0) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) |  | ||||||
|                                         // ^^^ Note that async |  | ||||||
|                                         //     control is not directly |  | ||||||
|                                         //     supported by abc9 but its |  | ||||||
|                                         //     behaviour is captured by |  | ||||||
|                                         //     $__ABC9_ASYNC1 below |  | ||||||
|     ); |  | ||||||
|     $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR), .Y(QQ)); |  | ||||||
|   end |  | ||||||
|   else begin |  | ||||||
|     assign Q = QQ; |  | ||||||
|     FDCE_1 #( |  | ||||||
|       .INIT(1'b0) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) |  | ||||||
|                                        // ^^^ Note that async |  | ||||||
|                                        //     control is not directly |  | ||||||
|                                        //     supported by abc9 but its |  | ||||||
|                                        //     behaviour is captured by |  | ||||||
|                                        //     $__ABC9_ASYNC0 below |  | ||||||
|     ); |  | ||||||
|     $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR), .Y(QQ)); |  | ||||||
|   end endgenerate |  | ||||||
|   (* abc9_init = 1'b0 *) |  | ||||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); |  | ||||||
| 
 |  | ||||||
|   // Special signals |  | ||||||
|   wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; |  | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| 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; |  | ||||||
|   parameter [0:0] IS_PRE_INVERTED = 1'b0; |  | ||||||
|   wire QQ, $Q, $QQ; |  | ||||||
|   generate if (INIT == 1'b1) begin |  | ||||||
|     assign Q = ~QQ; |  | ||||||
|     FDCE #( |  | ||||||
|       .INIT(1'b0), |  | ||||||
|       .IS_C_INVERTED(IS_C_INVERTED), |  | ||||||
|       .IS_D_INVERTED(IS_D_INVERTED), |  | ||||||
|       .IS_CLR_INVERTED(IS_PRE_INVERTED), |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) |  | ||||||
|                                         // ^^^ Note that async |  | ||||||
|                                         //     control is not directly |  | ||||||
|                                         //     supported by abc9 but its |  | ||||||
|                                         //     behaviour is captured by |  | ||||||
|                                         //     $__ABC9_ASYNC0 below |  | ||||||
|     ); |  | ||||||
|     $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); |  | ||||||
|   end |  | ||||||
|   else begin |  | ||||||
|     assign Q = QQ; |  | ||||||
|     FDPE #( |  | ||||||
|       .INIT(1'b0), |  | ||||||
|       .IS_C_INVERTED(IS_C_INVERTED), |  | ||||||
|       .IS_D_INVERTED(IS_D_INVERTED), |  | ||||||
|       .IS_PRE_INVERTED(IS_PRE_INVERTED), |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) |  | ||||||
|                                        // ^^^ Note that async |  | ||||||
|                                        //     control is not directly |  | ||||||
|                                        //     supported by abc9 but its |  | ||||||
|                                        //     behaviour is captured by |  | ||||||
|                                        //     $__ABC9_ASYNC1 below |  | ||||||
|     ); |  | ||||||
|     $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); |  | ||||||
|   end endgenerate |  | ||||||
|   (* abc9_init = 1'b0 *) |  | ||||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); |  | ||||||
| 
 |  | ||||||
|   // Special signals |  | ||||||
|   wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED}; |  | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; |  | ||||||
| endmodule |  | ||||||
| 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 |  | ||||||
|     assign Q = ~QQ; |  | ||||||
|     FDCE_1 #( |  | ||||||
|       .INIT(1'b0) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) |  | ||||||
|                                         // ^^^ Note that async |  | ||||||
|                                         //     control is not directly |  | ||||||
|                                         //     supported by abc9 but its |  | ||||||
|                                         //     behaviour is captured by |  | ||||||
|                                         //     $__ABC9_ASYNC0 below |  | ||||||
|     ); |  | ||||||
|     $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE), .Y(QQ)); |  | ||||||
|   end |  | ||||||
|   else begin |  | ||||||
|     assign Q = QQ; |  | ||||||
|     FDPE_1 #( |  | ||||||
|       .INIT(1'b0) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|       .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) |  | ||||||
|                                        // ^^^ Note that async |  | ||||||
|                                        //     control is not directly |  | ||||||
|                                        //     supported by abc9 but its |  | ||||||
|                                        //     behaviour is captured by |  | ||||||
|                                        //     $__ABC9_ASYNC1 below |  | ||||||
|     ); |  | ||||||
|     $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE), .Y(QQ)); |  | ||||||
|   end endgenerate |  | ||||||
|   (* abc9_init = 1'b0 *) |  | ||||||
|   $__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ)); |  | ||||||
| 
 |  | ||||||
|   // Special signals |  | ||||||
|   wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */}; |  | ||||||
|   wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ; |  | ||||||
| endmodule |  | ||||||
| `endif |  | ||||||
| 
 |  | ||||||
| // Attach a (combinatorial) black-box onto the output |  | ||||||
| //   of thes LUTRAM primitives to capture their |  | ||||||
| //   asynchronous read behaviour |  | ||||||
| module RAM32X1D ( |  | ||||||
|   output DPO, SPO, |  | ||||||
|   (* techmap_autopurge *) input  D, |  | ||||||
|   (* techmap_autopurge *) input  WCLK, |  | ||||||
|   (* techmap_autopurge *) input  WE, |  | ||||||
|   (* techmap_autopurge *) input  A0, A1, A2, A3, A4, |  | ||||||
|   (* techmap_autopurge *) input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4 |  | ||||||
| ); |  | ||||||
|   parameter INIT = 32'h0; |  | ||||||
|   parameter IS_WCLK_INVERTED = 1'b0; |  | ||||||
|   wire $DPO, $SPO; |  | ||||||
|   RAM32X1D #( |  | ||||||
|     .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .DPO($DPO), .SPO($SPO), |  | ||||||
|     .D(D), .WCLK(WCLK), .WE(WE), |  | ||||||
|     .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), |  | ||||||
|     .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 spo (.A($SPO), .S({1'b1, A4, A3, A2, A1, A0}), .Y(SPO)); |  | ||||||
|   $__ABC9_RAM6 dpo (.A($DPO), .S({1'b1, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module RAM64X1D ( |  | ||||||
|   output DPO, SPO, |  | ||||||
|   (* techmap_autopurge *) input  D, |  | ||||||
|   (* techmap_autopurge *) input  WCLK, |  | ||||||
|   (* techmap_autopurge *) input  WE, |  | ||||||
|   (* techmap_autopurge *) input  A0, A1, A2, A3, A4, A5, |  | ||||||
|   (* techmap_autopurge *) input  DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5 |  | ||||||
| ); |  | ||||||
|   parameter INIT = 64'h0; |  | ||||||
|   parameter IS_WCLK_INVERTED = 1'b0; |  | ||||||
|   wire $DPO, $SPO; |  | ||||||
|   RAM64X1D #( |  | ||||||
|     .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .DPO($DPO), .SPO($SPO), |  | ||||||
|     .D(D), .WCLK(WCLK), .WE(WE), |  | ||||||
|     .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5), |  | ||||||
|     .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 spo (.A($SPO), .S({A5, A4, A3, A2, A1, A0}), .Y(SPO)); |  | ||||||
|   $__ABC9_RAM6 dpo (.A($DPO), .S({DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module RAM128X1D ( |  | ||||||
|   output       DPO, SPO, |  | ||||||
|   (* techmap_autopurge *) input        D, |  | ||||||
|   (* techmap_autopurge *) input        WCLK, |  | ||||||
|   (* techmap_autopurge *) input        WE, |  | ||||||
|   (* techmap_autopurge *) input  [6:0] A, DPRA |  | ||||||
| ); |  | ||||||
|   parameter INIT = 128'h0; |  | ||||||
|   parameter IS_WCLK_INVERTED = 1'b0; |  | ||||||
|   wire $DPO, $SPO; |  | ||||||
|   RAM128X1D #( |  | ||||||
|     .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .DPO($DPO), .SPO($SPO), |  | ||||||
|     .D(D), .WCLK(WCLK), .WE(WE), |  | ||||||
|     .A(A), |  | ||||||
|     .DPRA(DPRA) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM7 spo (.A($SPO), .S(A), .Y(SPO)); |  | ||||||
|   $__ABC9_RAM7 dpo (.A($DPO), .S(DPRA), .Y(DPO)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module RAM32M ( |  | ||||||
|   output [1:0] DOA, |  | ||||||
|   output [1:0] DOB, |  | ||||||
|   output [1:0] DOC, |  | ||||||
|   output [1:0] DOD, |  | ||||||
|   (* techmap_autopurge *) input [4:0] ADDRA, |  | ||||||
|   (* techmap_autopurge *) input [4:0] ADDRB, |  | ||||||
|   (* techmap_autopurge *) input [4:0] ADDRC, |  | ||||||
|   (* techmap_autopurge *) input [4:0] ADDRD, |  | ||||||
|   (* techmap_autopurge *) input [1:0] DIA, |  | ||||||
|   (* techmap_autopurge *) input [1:0] DIB, |  | ||||||
|   (* techmap_autopurge *) input [1:0] DIC, |  | ||||||
|   (* techmap_autopurge *) input [1:0] DID, |  | ||||||
|   (* techmap_autopurge *) input WCLK, |  | ||||||
|   (* techmap_autopurge *) input WE |  | ||||||
| ); |  | ||||||
|   parameter [63:0] INIT_A = 64'h0000000000000000; |  | ||||||
|   parameter [63:0] INIT_B = 64'h0000000000000000; |  | ||||||
|   parameter [63:0] INIT_C = 64'h0000000000000000; |  | ||||||
|   parameter [63:0] INIT_D = 64'h0000000000000000; |  | ||||||
|   parameter [0:0] IS_WCLK_INVERTED = 1'b0; |  | ||||||
|   wire [1:0] $DOA, $DOB, $DOC, $DOD; |  | ||||||
|   RAM32M #( |  | ||||||
|     .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), |  | ||||||
|     .IS_WCLK_INVERTED(IS_WCLK_INVERTED) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD), |  | ||||||
|     .WCLK(WCLK), .WE(WE), |  | ||||||
|     .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), |  | ||||||
|     .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 doa0 (.A($DOA[0]), .S({1'b1, ADDRA}), .Y(DOA[0])); |  | ||||||
|   $__ABC9_RAM6 doa1 (.A($DOA[1]), .S({1'b1, ADDRA}), .Y(DOA[1])); |  | ||||||
|   $__ABC9_RAM6 dob0 (.A($DOB[0]), .S({1'b1, ADDRB}), .Y(DOB[0])); |  | ||||||
|   $__ABC9_RAM6 dob1 (.A($DOB[1]), .S({1'b1, ADDRB}), .Y(DOB[1])); |  | ||||||
|   $__ABC9_RAM6 doc0 (.A($DOC[0]), .S({1'b1, ADDRC}), .Y(DOC[0])); |  | ||||||
|   $__ABC9_RAM6 doc1 (.A($DOC[1]), .S({1'b1, ADDRC}), .Y(DOC[1])); |  | ||||||
|   $__ABC9_RAM6 dod0 (.A($DOD[0]), .S({1'b1, ADDRD}), .Y(DOD[0])); |  | ||||||
|   $__ABC9_RAM6 dod1 (.A($DOD[1]), .S({1'b1, ADDRD}), .Y(DOD[1])); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module RAM64M ( |  | ||||||
|   output DOA, |  | ||||||
|   output DOB, |  | ||||||
|   output DOC, |  | ||||||
|   output DOD, |  | ||||||
|   (* techmap_autopurge *) input [5:0] ADDRA, |  | ||||||
|   (* techmap_autopurge *) input [5:0] ADDRB, |  | ||||||
|   (* techmap_autopurge *) input [5:0] ADDRC, |  | ||||||
|   (* techmap_autopurge *) input [5:0] ADDRD, |  | ||||||
|   (* techmap_autopurge *) input DIA, |  | ||||||
|   (* techmap_autopurge *) input DIB, |  | ||||||
|   (* techmap_autopurge *) input DIC, |  | ||||||
|   (* techmap_autopurge *) input DID, |  | ||||||
|   (* techmap_autopurge *) input WCLK, |  | ||||||
|   (* techmap_autopurge *) input WE |  | ||||||
| ); |  | ||||||
|   parameter [63:0] INIT_A = 64'h0000000000000000; |  | ||||||
|   parameter [63:0] INIT_B = 64'h0000000000000000; |  | ||||||
|   parameter [63:0] INIT_C = 64'h0000000000000000; |  | ||||||
|   parameter [63:0] INIT_D = 64'h0000000000000000; |  | ||||||
|   parameter [0:0] IS_WCLK_INVERTED = 1'b0; |  | ||||||
|   wire $DOA, $DOB, $DOC, $DOD; |  | ||||||
|   RAM64M #( |  | ||||||
|     .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), |  | ||||||
|     .IS_WCLK_INVERTED(IS_WCLK_INVERTED) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD), |  | ||||||
|     .WCLK(WCLK), .WE(WE), |  | ||||||
|     .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), |  | ||||||
|     .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 doa (.A($DOA), .S(ADDRA), .Y(DOA)); |  | ||||||
|   $__ABC9_RAM6 dob (.A($DOB), .S(ADDRB), .Y(DOB)); |  | ||||||
|   $__ABC9_RAM6 doc (.A($DOC), .S(ADDRC), .Y(DOC)); |  | ||||||
|   $__ABC9_RAM6 dod (.A($DOD), .S(ADDRD), .Y(DOD)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module SRL16 ( |  | ||||||
|   output Q, |  | ||||||
|   (* techmap_autopurge *) input A0, A1, A2, A3, CLK, D |  | ||||||
| ); |  | ||||||
|   parameter [15:0] INIT = 16'h0000; |  | ||||||
|   wire $Q; |  | ||||||
|   SRL16 #( |  | ||||||
|     .INIT(INIT), |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .Q($Q), |  | ||||||
|     .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CLK(CLK), .D(D) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module SRL16E ( |  | ||||||
|   output Q, |  | ||||||
|   (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D |  | ||||||
| ); |  | ||||||
|   parameter [15:0] INIT = 16'h0000; |  | ||||||
|   parameter [0:0] IS_CLK_INVERTED = 1'b0; |  | ||||||
|   wire $Q; |  | ||||||
|   SRL16E #( |  | ||||||
|     .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .Q($Q), |  | ||||||
|     .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module SRLC16 ( |  | ||||||
|   output Q, Q15, |  | ||||||
|   (* techmap_autopurge *) input A0, A1, A2, A3, CLK, D |  | ||||||
| ); |  | ||||||
|   parameter [15:0] INIT = 16'h0000; |  | ||||||
|   wire $Q; |  | ||||||
|   SRLC16 #( |  | ||||||
|     .INIT(INIT), |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .Q($Q), .Q(Q15), |  | ||||||
|     .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CLK(CLK), .D(D) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module SRLC16E ( |  | ||||||
|   output Q, Q15, |  | ||||||
|   (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D |  | ||||||
| ); |  | ||||||
|   parameter [15:0] INIT = 16'h0000; |  | ||||||
|   parameter [0:0] IS_CLK_INVERTED = 1'b0; |  | ||||||
|   wire $Q; |  | ||||||
|   SRLC16E #( |  | ||||||
|     .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .Q($Q), .Q(Q15), |  | ||||||
|     .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module SRLC32E ( |  | ||||||
|   output Q, |  | ||||||
|   output Q31, |  | ||||||
|   (* techmap_autopurge *) input [4:0] A, |  | ||||||
|   (* techmap_autopurge *) input CE, CLK, D |  | ||||||
| ); |  | ||||||
|   parameter [31:0] INIT = 32'h00000000; |  | ||||||
|   parameter [0:0] IS_CLK_INVERTED = 1'b0; |  | ||||||
|   wire $Q; |  | ||||||
|   SRLC32E #( |  | ||||||
|     .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED) |  | ||||||
|   ) _TECHMAP_REPLACE_ ( |  | ||||||
|     .Q($Q), .Q31(Q31), |  | ||||||
|     .A(A), .CE(CE), .CLK(CLK), .D(D) |  | ||||||
|   ); |  | ||||||
|   $__ABC9_RAM6 q (.A($Q), .S({1'b1, A}), .Y(Q)); |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module DSP48E1 ( |  | ||||||
|     (* techmap_autopurge *) output [29:0] ACOUT, |  | ||||||
|     (* techmap_autopurge *) output [17:0] BCOUT, |  | ||||||
|     (* techmap_autopurge *) output reg CARRYCASCOUT, |  | ||||||
|     (* techmap_autopurge *) output reg [3:0] CARRYOUT, |  | ||||||
|     (* techmap_autopurge *) output reg MULTSIGNOUT, |  | ||||||
|     (* techmap_autopurge *) output OVERFLOW, |  | ||||||
|     (* techmap_autopurge *) output reg signed [47:0] P, |  | ||||||
|     (* techmap_autopurge *) output PATTERNBDETECT, |  | ||||||
|     (* techmap_autopurge *) output PATTERNDETECT, |  | ||||||
|     (* techmap_autopurge *) output [47:0] PCOUT, |  | ||||||
|     (* techmap_autopurge *) output UNDERFLOW, |  | ||||||
|     (* techmap_autopurge *) input signed [29:0] A, |  | ||||||
|     (* techmap_autopurge *) input [29:0] ACIN, |  | ||||||
|     (* techmap_autopurge *) input [3:0] ALUMODE, |  | ||||||
|     (* techmap_autopurge *) input signed [17:0] B, |  | ||||||
|     (* techmap_autopurge *) input [17:0] BCIN, |  | ||||||
|     (* techmap_autopurge *) input [47:0] C, |  | ||||||
|     (* techmap_autopurge *) input CARRYCASCIN, |  | ||||||
|     (* techmap_autopurge *) input CARRYIN, |  | ||||||
|     (* techmap_autopurge *) input [2:0] CARRYINSEL, |  | ||||||
|     (* techmap_autopurge *) input CEA1, |  | ||||||
|     (* techmap_autopurge *) input CEA2, |  | ||||||
|     (* techmap_autopurge *) input CEAD, |  | ||||||
|     (* techmap_autopurge *) input CEALUMODE, |  | ||||||
|     (* techmap_autopurge *) input CEB1, |  | ||||||
|     (* techmap_autopurge *) input CEB2, |  | ||||||
|     (* techmap_autopurge *) input CEC, |  | ||||||
|     (* techmap_autopurge *) input CECARRYIN, |  | ||||||
|     (* techmap_autopurge *) input CECTRL, |  | ||||||
|     (* techmap_autopurge *) input CED, |  | ||||||
|     (* techmap_autopurge *) input CEINMODE, |  | ||||||
|     (* techmap_autopurge *) input CEM, |  | ||||||
|     (* techmap_autopurge *) input CEP, |  | ||||||
|     (* techmap_autopurge *) input CLK, |  | ||||||
|     (* techmap_autopurge *) input [24:0] D, |  | ||||||
|     (* techmap_autopurge *) input [4:0] INMODE, |  | ||||||
|     (* techmap_autopurge *) input MULTSIGNIN, |  | ||||||
|     (* techmap_autopurge *) input [6:0] OPMODE, |  | ||||||
|     (* techmap_autopurge *) input [47:0] PCIN, |  | ||||||
|     (* techmap_autopurge *) input RSTA, |  | ||||||
|     (* techmap_autopurge *) input RSTALLCARRYIN, |  | ||||||
|     (* techmap_autopurge *) input RSTALUMODE, |  | ||||||
|     (* techmap_autopurge *) input RSTB, |  | ||||||
|     (* techmap_autopurge *) input RSTC, |  | ||||||
|     (* techmap_autopurge *) input RSTCTRL, |  | ||||||
|     (* techmap_autopurge *) input RSTD, |  | ||||||
|     (* techmap_autopurge *) input RSTINMODE, |  | ||||||
|     (* techmap_autopurge *) input RSTM, |  | ||||||
|     (* techmap_autopurge *) input RSTP |  | ||||||
| ); |  | ||||||
|     parameter integer ACASCREG = 1; |  | ||||||
|     parameter integer ADREG = 1; |  | ||||||
|     parameter integer ALUMODEREG = 1; |  | ||||||
|     parameter integer AREG = 1; |  | ||||||
|     parameter AUTORESET_PATDET = "NO_RESET"; |  | ||||||
|     parameter A_INPUT = "DIRECT"; |  | ||||||
|     parameter integer BCASCREG = 1; |  | ||||||
|     parameter integer BREG = 1; |  | ||||||
|     parameter B_INPUT = "DIRECT"; |  | ||||||
|     parameter integer CARRYINREG = 1; |  | ||||||
|     parameter integer CARRYINSELREG = 1; |  | ||||||
|     parameter integer CREG = 1; |  | ||||||
|     parameter integer DREG = 1; |  | ||||||
|     parameter integer INMODEREG = 1; |  | ||||||
|     parameter integer MREG = 1; |  | ||||||
|     parameter integer OPMODEREG = 1; |  | ||||||
|     parameter integer PREG = 1; |  | ||||||
|     parameter SEL_MASK = "MASK"; |  | ||||||
|     parameter SEL_PATTERN = "PATTERN"; |  | ||||||
|     parameter USE_DPORT = "FALSE"; |  | ||||||
|     parameter USE_MULT = "MULTIPLY"; |  | ||||||
|     parameter USE_PATTERN_DETECT = "NO_PATDET"; |  | ||||||
|     parameter USE_SIMD = "ONE48"; |  | ||||||
|     parameter [47:0] MASK = 48'h3FFFFFFFFFFF; |  | ||||||
|     parameter [47:0] PATTERN = 48'h000000000000; |  | ||||||
|     parameter [3:0] IS_ALUMODE_INVERTED = 4'b0; |  | ||||||
|     parameter [0:0] IS_CARRYIN_INVERTED = 1'b0; |  | ||||||
|     parameter [0:0] IS_CLK_INVERTED = 1'b0; |  | ||||||
|     parameter [4:0] IS_INMODE_INVERTED = 5'b0; |  | ||||||
|     parameter [6:0] IS_OPMODE_INVERTED = 7'b0; |  | ||||||
| 
 |  | ||||||
|     wire [47:0] $P, $PCOUT; |  | ||||||
| 
 |  | ||||||
|     DSP48E1 #( |  | ||||||
|         .ACASCREG(ACASCREG), |  | ||||||
|         .ADREG(ADREG), |  | ||||||
|         .ALUMODEREG(ALUMODEREG), |  | ||||||
|         .AREG(AREG), |  | ||||||
|         .AUTORESET_PATDET(AUTORESET_PATDET), |  | ||||||
|         .A_INPUT(A_INPUT), |  | ||||||
|         .BCASCREG(BCASCREG), |  | ||||||
|         .BREG(BREG), |  | ||||||
|         .B_INPUT(B_INPUT), |  | ||||||
|         .CARRYINREG(CARRYINREG), |  | ||||||
|         .CARRYINSELREG(CARRYINSELREG), |  | ||||||
|         .CREG(CREG), |  | ||||||
|         .DREG(DREG), |  | ||||||
|         .INMODEREG(INMODEREG), |  | ||||||
|         .MREG(MREG), |  | ||||||
|         .OPMODEREG(OPMODEREG), |  | ||||||
|         .PREG(PREG), |  | ||||||
|         .SEL_MASK(SEL_MASK), |  | ||||||
|         .SEL_PATTERN(SEL_PATTERN), |  | ||||||
|         .USE_DPORT(USE_DPORT), |  | ||||||
|         .USE_MULT(USE_MULT), |  | ||||||
|         .USE_PATTERN_DETECT(USE_PATTERN_DETECT), |  | ||||||
|         .USE_SIMD(USE_SIMD), |  | ||||||
|         .MASK(MASK), |  | ||||||
|         .PATTERN(PATTERN), |  | ||||||
|         .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED), |  | ||||||
|         .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED), |  | ||||||
|         .IS_CLK_INVERTED(IS_CLK_INVERTED), |  | ||||||
|         .IS_INMODE_INVERTED(IS_INMODE_INVERTED), |  | ||||||
|         .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED) |  | ||||||
|     ) _TECHMAP_REPLACE_ ( |  | ||||||
|         .ACOUT(ACOUT), |  | ||||||
|         .BCOUT(BCOUT), |  | ||||||
|         .CARRYCASCOUT(CARRYCASCOUT), |  | ||||||
|         .CARRYOUT(CARRYOUT), |  | ||||||
|         .MULTSIGNOUT(MULTSIGNOUT), |  | ||||||
|         .OVERFLOW(OVERFLOW), |  | ||||||
|         .P($P), |  | ||||||
|         .PATTERNBDETECT(PATTERNBDETECT), |  | ||||||
|         .PATTERNDETECT(PATTERNDETECT), |  | ||||||
|         .PCOUT($PCOUT), |  | ||||||
|         .UNDERFLOW(UNDERFLOW), |  | ||||||
|         .A(A), |  | ||||||
|         .ACIN(ACIN), |  | ||||||
|         .ALUMODE(ALUMODE), |  | ||||||
|         .B(B), |  | ||||||
|         .BCIN(BCIN), |  | ||||||
|         .C(C), |  | ||||||
|         .CARRYCASCIN(CARRYCASCIN), |  | ||||||
|         .CARRYIN(CARRYIN), |  | ||||||
|         .CARRYINSEL(CARRYINSEL), |  | ||||||
|         .CEA1(CEA1), |  | ||||||
|         .CEA2(CEA2), |  | ||||||
|         .CEAD(CEAD), |  | ||||||
|         .CEALUMODE(CEALUMODE), |  | ||||||
|         .CEB1(CEB1), |  | ||||||
|         .CEB2(CEB2), |  | ||||||
|         .CEC(CEC), |  | ||||||
|         .CECARRYIN(CECARRYIN), |  | ||||||
|         .CECTRL(CECTRL), |  | ||||||
|         .CED(CED), |  | ||||||
|         .CEINMODE(CEINMODE), |  | ||||||
|         .CEM(CEM), |  | ||||||
|         .CEP(CEP), |  | ||||||
|         .CLK(CLK), |  | ||||||
|         .D(D), |  | ||||||
|         .INMODE(INMODE), |  | ||||||
|         .MULTSIGNIN(MULTSIGNIN), |  | ||||||
|         .OPMODE(OPMODE), |  | ||||||
|         .PCIN(PCIN), |  | ||||||
|         .RSTA(RSTA), |  | ||||||
|         .RSTALLCARRYIN(RSTALLCARRYIN), |  | ||||||
|         .RSTALUMODE(RSTALUMODE), |  | ||||||
|         .RSTB(RSTB), |  | ||||||
|         .RSTC(RSTC), |  | ||||||
|         .RSTCTRL(RSTCTRL), |  | ||||||
|         .RSTD(RSTD), |  | ||||||
|         .RSTINMODE(RSTINMODE), |  | ||||||
|         .RSTM(RSTM), |  | ||||||
|         .RSTP(RSTP) |  | ||||||
|     ); |  | ||||||
|     $__ABC9_DSP48E1 #( |  | ||||||
|         .ADREG(ADREG), |  | ||||||
|         .AREG(AREG), |  | ||||||
|         .BREG(BREG), |  | ||||||
|         .CREG(CREG), |  | ||||||
|         .DREG(DREG), |  | ||||||
|         .MREG(MREG), |  | ||||||
|         .PREG(PREG), |  | ||||||
|         .USE_DPORT(USE_DPORT), |  | ||||||
|         .USE_MULT(USE_MULT) |  | ||||||
|     ) dsp_comb ( |  | ||||||
|         .$A(A), .$B(B), .$C(C), .$D(D), .$P($P), .$PCIN(PCIN), .$PCOUT($PCOUT), .P(P), .PCOUT(PCOUT)); |  | ||||||
| endmodule |  | ||||||
|  | @ -37,174 +37,3 @@ module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1); | ||||||
|     (S1 => O) = 273; |     (S1 => O) = 273; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 |  | ||||||
| // Box to emulate async behaviour of FDC* |  | ||||||
| (* abc9_box, lib_whitebox *) |  | ||||||
| module \$__ABC9_ASYNC0 (input A, S, output Y); |  | ||||||
|   assign Y = S ? 1'b0 : A; |  | ||||||
|   specify |  | ||||||
|     (A => Y) = 0; |  | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 |  | ||||||
|     (S => Y) = 764; |  | ||||||
|   endspecify |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| // Box to emulate async behaviour of FDP* |  | ||||||
| (* abc9_box, lib_whitebox *) |  | ||||||
| module \$__ABC9_ASYNC1 (input A, S, output Y); |  | ||||||
|   assign Y = S ? 1'b1 : A; |  | ||||||
|   specify |  | ||||||
|     (A => Y) = 0; |  | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 |  | ||||||
|     (S => Y) = 764; |  | ||||||
|   endspecify |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| // Box to emulate comb/seq behaviour of RAM{32,64} and SRL{16,32} |  | ||||||
| //   Necessary since RAMD* and SRL* have both combinatorial (i.e. |  | ||||||
| //   same-cycle read operation) and sequential (write operation |  | ||||||
| //   is only committed on the next clock edge). |  | ||||||
| //   To model the combinatorial path, such cells have to be split |  | ||||||
| //   into comb and seq parts, with this box modelling only the former. |  | ||||||
| (* abc9_box *) |  | ||||||
| module \$__ABC9_RAM6 (input A, input [5:0] S, output Y); |  | ||||||
|   specify |  | ||||||
|     (A    => Y) =   0; |  | ||||||
|     (S[0] => Y) = 642; |  | ||||||
|     (S[1] => Y) = 631; |  | ||||||
|     (S[2] => Y) = 472; |  | ||||||
|     (S[3] => Y) = 407; |  | ||||||
|     (S[4] => Y) = 238; |  | ||||||
|     (S[5] => Y) = 127; |  | ||||||
|   endspecify |  | ||||||
| endmodule |  | ||||||
| // Box to emulate comb/seq behaviour of RAM128 |  | ||||||
| (* abc9_box *) |  | ||||||
| module \$__ABC9_RAM7 (input A, input [6:0] S, output Y); |  | ||||||
|   specify |  | ||||||
|     (A    => Y) = 0; |  | ||||||
|                                                     // https://github.com/SymbiFlow/prjxray-db/blob/1c85daf1b115da4d27ca83c6b89f53a94de39748/artix7/timings/slicel.sdf#L867 |  | ||||||
|     (S[0] => Y) = 642 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; |  | ||||||
|     (S[1] => Y) = 631 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; |  | ||||||
|     (S[2] => Y) = 472 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; |  | ||||||
|     (S[3] => Y) = 407 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; |  | ||||||
|     (S[4] => Y) = 238 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; |  | ||||||
|     (S[5] => Y) = 127 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; |  | ||||||
|     (S[6] => Y) = 0 + 296 /* to select F7BMUX */ + 174 /* CMUX */; |  | ||||||
|   endspecify |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| // Boxes used to represent the comb behaviour of DSP48E1 |  | ||||||
| (* abc9_box *) |  | ||||||
| module $__ABC9_DSP48E1 ( |  | ||||||
|     input [29:0] $A, |  | ||||||
|     input [17:0] $B, |  | ||||||
|     input [47:0] $C, |  | ||||||
|     input [24:0] $D, |  | ||||||
|     input [47:0] $P, |  | ||||||
|     input [47:0] $PCIN, |  | ||||||
|     input [47:0] $PCOUT, |  | ||||||
|     output [47:0] P, |  | ||||||
|     output [47:0] PCOUT |  | ||||||
| ); |  | ||||||
|     parameter integer ADREG = 1; |  | ||||||
|     parameter integer AREG = 1; |  | ||||||
|     parameter integer BREG = 1; |  | ||||||
|     parameter integer CREG = 1; |  | ||||||
|     parameter integer DREG = 1; |  | ||||||
|     parameter integer MREG = 1; |  | ||||||
|     parameter integer PREG = 1; |  | ||||||
|     parameter USE_DPORT = "FALSE"; |  | ||||||
|     parameter USE_MULT = "MULTIPLY"; |  | ||||||
| 
 |  | ||||||
|     function integer \A.P.comb ; |  | ||||||
|     begin |  | ||||||
|         if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE")     \A.P.comb = 2823; |  | ||||||
|         else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \A.P.comb = 3806; |  | ||||||
|         else if (USE_MULT == "NONE" && USE_DPORT == "FALSE")    \A.P.comb = 1523; |  | ||||||
|     end |  | ||||||
|     endfunction |  | ||||||
|     function integer \A.PCOUT.comb ; |  | ||||||
|     begin |  | ||||||
|         if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE")     \A.PCOUT.comb = 2970; |  | ||||||
|         else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \A.PCOUT.comb = 3954; |  | ||||||
|         else if (USE_MULT == "NONE" && USE_DPORT == "FALSE")    \A.PCOUT.comb = 1671; |  | ||||||
|     end |  | ||||||
|     endfunction |  | ||||||
|     function integer \B.P.comb ; |  | ||||||
|     begin |  | ||||||
|         if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE")     \B.P.comb = 2690; |  | ||||||
|         else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \B.P.comb = 2690; |  | ||||||
|         else if (USE_MULT == "NONE" && USE_DPORT == "FALSE")    \B.P.comb = 1509; |  | ||||||
|     end |  | ||||||
|     endfunction |  | ||||||
|     function integer \B.PCOUT.comb ; |  | ||||||
|     begin |  | ||||||
|         if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE")     \B.PCOUT.comb = 2838; |  | ||||||
|         else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \B.PCOUT.comb = 2838; |  | ||||||
|         else if (USE_MULT == "NONE" && USE_DPORT == "FALSE")    \B.PCOUT.comb = 1658; |  | ||||||
|     end |  | ||||||
|     endfunction |  | ||||||
|     function integer \C.P.comb ; |  | ||||||
|     begin |  | ||||||
|         if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE")     \C.P.comb = 1325; |  | ||||||
|         else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \C.P.comb = 1325; |  | ||||||
|         else if (USE_MULT == "NONE" && USE_DPORT == "FALSE")    \C.P.comb = 1325; |  | ||||||
|     end |  | ||||||
|     endfunction |  | ||||||
|     function integer \C.PCOUT.comb ; |  | ||||||
|     begin |  | ||||||
|         if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE")     \C.PCOUT.comb = 1474; |  | ||||||
|         else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") \C.PCOUT.comb = 1474; |  | ||||||
|         else if (USE_MULT == "NONE" && USE_DPORT == "FALSE")    \C.PCOUT.comb = 1474; |  | ||||||
|     end |  | ||||||
|     endfunction |  | ||||||
|     function integer \D.P.comb ; |  | ||||||
|     begin |  | ||||||
|         if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE")      \D.P.comb = 3717; |  | ||||||
|     end |  | ||||||
|     endfunction |  | ||||||
|     function integer \D.PCOUT.comb ; |  | ||||||
|     begin |  | ||||||
|         if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE")      \D.PCOUT.comb = 3700; |  | ||||||
|     end |  | ||||||
|     endfunction |  | ||||||
| 
 |  | ||||||
| 	specify |  | ||||||
| 		($P *> P) 			= 0; |  | ||||||
| 		($PCOUT *> PCOUT)	= 0; |  | ||||||
| 	endspecify |  | ||||||
| 
 |  | ||||||
|     // Identical comb delays to DSP48E1 in cells_sim.v |  | ||||||
|     generate |  | ||||||
|         if (PREG == 0 && MREG == 0 && AREG == 0 && ADREG == 0) |  | ||||||
|             specify |  | ||||||
|                 ($A *> P) =      \A.P.comb (); |  | ||||||
|                 ($A *> PCOUT) =  \A.PCOUT.comb (); |  | ||||||
|             endspecify |  | ||||||
| 
 |  | ||||||
|         if (PREG == 0 && MREG == 0 && BREG == 0) |  | ||||||
|             specify |  | ||||||
|                 ($B *> P) =      \B.P.comb (); |  | ||||||
|                 ($B *> PCOUT) =  \B.PCOUT.comb (); |  | ||||||
|             endspecify |  | ||||||
| 
 |  | ||||||
|         if (PREG == 0 && CREG == 0) |  | ||||||
|             specify |  | ||||||
|                 ($C *> P) =      \C.P.comb (); |  | ||||||
|                 ($C *> PCOUT) =  \C.PCOUT.comb (); |  | ||||||
|             endspecify |  | ||||||
| 
 |  | ||||||
|         if (PREG == 0 && MREG == 0 && ADREG == 0 && DREG == 0) |  | ||||||
|             specify |  | ||||||
|                 ($D *> P) =      \D.P.comb (); |  | ||||||
|                 ($D *> PCOUT) =  \D.PCOUT.comb (); |  | ||||||
|             endspecify |  | ||||||
| 
 |  | ||||||
|         if (PREG == 0) |  | ||||||
|             specify |  | ||||||
|                 ($PCIN *> P) =       1107; |  | ||||||
|                 ($PCIN *> PCOUT) =   1255; |  | ||||||
|             endspecify |  | ||||||
|     endgenerate |  | ||||||
| endmodule |  | ||||||
|  |  | ||||||
|  | @ -1,61 +0,0 @@ | ||||||
| /* |  | ||||||
|  *  yosys -- Yosys Open SYnthesis Suite |  | ||||||
|  * |  | ||||||
|  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> |  | ||||||
|  *                2019  Eddie Hung    <eddie@fpgeh.com> |  | ||||||
|  * |  | ||||||
|  *  Permission to use, copy, modify, and/or distribute this software for any |  | ||||||
|  *  purpose with or without fee is hereby granted, provided that the above |  | ||||||
|  *  copyright notice and this permission notice appear in all copies. |  | ||||||
|  * |  | ||||||
|  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |  | ||||||
|  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |  | ||||||
|  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |  | ||||||
|  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |  | ||||||
|  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |  | ||||||
|  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |  | ||||||
|  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| // ============================================================================ |  | ||||||
| 
 |  | ||||||
| (* techmap_celltype = "$__ABC9_ASYNC0 $__ABC9_ASYNC1" *) |  | ||||||
| module $__ABC9_ASYNC01(input A, S, output Y); |  | ||||||
|   assign Y = A; |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module $__ABC9_FF_(input D, output Q); |  | ||||||
|   assign Q = D; |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module $__ABC9_RAM6(input A, input [5:0] S, output Y); |  | ||||||
|   assign Y = A; |  | ||||||
| endmodule |  | ||||||
| module $__ABC9_RAM7(input A, input [6:0] S, output Y); |  | ||||||
|   assign Y = A; |  | ||||||
| endmodule |  | ||||||
| 
 |  | ||||||
| module $__ABC9_DSP48E1( |  | ||||||
|     input [29:0] $A, |  | ||||||
|     input [17:0] $B, |  | ||||||
|     input [47:0] $C, |  | ||||||
|     input [24:0] $D, |  | ||||||
|     input [47:0] $P, |  | ||||||
|     input [47:0] $PCIN, |  | ||||||
|     input [47:0] $PCOUT, |  | ||||||
|     output [47:0] P, |  | ||||||
|     output [47:0] PCOUT |  | ||||||
| ); |  | ||||||
|     parameter integer ADREG = 1; |  | ||||||
|     parameter integer AREG = 1; |  | ||||||
|     parameter integer BREG = 1; |  | ||||||
|     parameter integer CREG = 1; |  | ||||||
|     parameter integer DREG = 1; |  | ||||||
|     parameter integer MREG = 1; |  | ||||||
|     parameter integer PREG = 1; |  | ||||||
|     parameter USE_DPORT = "FALSE"; |  | ||||||
|     parameter USE_MULT = "MULTIPLY"; |  | ||||||
| 
 |  | ||||||
|     assign P = $P, PCOUT = $PCOUT; |  | ||||||
| endmodule |  | ||||||
|  | @ -36,6 +36,9 @@ module IBUF( | ||||||
|   parameter IOSTANDARD = "default"; |   parameter IOSTANDARD = "default"; | ||||||
|   parameter IBUF_LOW_PWR = 0; |   parameter IBUF_LOW_PWR = 0; | ||||||
|   assign O = I; |   assign O = I; | ||||||
|  |   specify | ||||||
|  |     (I => O) = 0; | ||||||
|  |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module IBUFG( | module IBUFG( | ||||||
|  | @ -57,6 +60,9 @@ module OBUF( | ||||||
|   parameter DRIVE = 12; |   parameter DRIVE = 12; | ||||||
|   parameter SLEW = "SLOW"; |   parameter SLEW = "SLOW"; | ||||||
|   assign O = I; |   assign O = I; | ||||||
|  |   specify | ||||||
|  |     (I => O) = 0; | ||||||
|  |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module IOBUF ( | module IOBUF ( | ||||||
|  | @ -72,6 +78,10 @@ module IOBUF ( | ||||||
|     parameter SLEW = "SLOW"; |     parameter SLEW = "SLOW"; | ||||||
|     assign IO = T ? 1'bz : I; |     assign IO = T ? 1'bz : I; | ||||||
|     assign O = IO; |     assign O = IO; | ||||||
|  |     specify | ||||||
|  |         (I => IO) = 0; | ||||||
|  |         (IO => O) = 0; | ||||||
|  |     endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module OBUFT ( | module OBUFT ( | ||||||
|  | @ -85,14 +95,20 @@ module OBUFT ( | ||||||
|     parameter IOSTANDARD = "DEFAULT"; |     parameter IOSTANDARD = "DEFAULT"; | ||||||
|     parameter SLEW = "SLOW"; |     parameter SLEW = "SLOW"; | ||||||
|     assign O = T ? 1'bz : I; |     assign O = T ? 1'bz : I; | ||||||
|  |     specify | ||||||
|  |         (I => O) = 0; | ||||||
|  |     endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module BUFG( | module BUFG( | ||||||
|     (* clkbuf_driver *) |     (* clkbuf_driver *) | ||||||
|     output O, |     output O, | ||||||
|     input I); |     input I); | ||||||
| 
 |  | ||||||
|   assign O = I; |   assign O = I; | ||||||
|  |   specify | ||||||
|  |     // https://github.com/SymbiFlow/prjxray-db/blob/4bc6385ab300b1819848371f508185f57b649a0e/artix7/timings/CLK_BUFG_TOP_R.sdf#L11 | ||||||
|  |     (I => O) = 96; | ||||||
|  |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module BUFGCTRL( | module BUFGCTRL( | ||||||
|  | @ -499,8 +515,8 @@ module FDRE ( | ||||||
|   endgenerate |   endgenerate | ||||||
|   specify |   specify | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 | ||||||
|     //$setup(D , posedge C &&& CE && !IS_C_INVERTED , -46); // Negative times not currently supported |     $setup(D , posedge C &&& CE && !IS_C_INVERTED , /*-46*/ 0); // Negative times not currently supported | ||||||
|     //$setup(D , negedge C &&& CE &&  IS_C_INVERTED , -46); // Negative times not currently supported |     $setup(D , negedge C &&& CE &&  IS_C_INVERTED , /*-46*/ 0); // Negative times not currently supported | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|     $setup(CE, posedge C &&& !IS_C_INVERTED, 109); |     $setup(CE, posedge C &&& !IS_C_INVERTED, 109); | ||||||
|     $setup(CE, negedge C &&&  IS_C_INVERTED, 109); |     $setup(CE, negedge C &&&  IS_C_INVERTED, 109); | ||||||
|  | @ -508,10 +524,10 @@ module FDRE ( | ||||||
|     $setup(R , posedge C &&& !IS_C_INVERTED, 404); |     $setup(R , posedge C &&& !IS_C_INVERTED, 404); | ||||||
|     $setup(R , negedge C &&&  IS_C_INVERTED, 404); |     $setup(R , negedge C &&&  IS_C_INVERTED, 404); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 |     // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 | ||||||
|     if (!IS_C_INVERTED && R ^ IS_R_INVERTED)        (posedge C => (Q : 1'b0)) = 303; |     if (!IS_C_INVERTED && R != IS_R_INVERTED)        (posedge C => (Q : 1'b0)) = 303; | ||||||
|     if ( IS_C_INVERTED && R ^ IS_R_INVERTED)        (negedge C => (Q : 1'b0)) = 303; |     if ( IS_C_INVERTED && R != IS_R_INVERTED)        (negedge C => (Q : 1'b0)) = 303; | ||||||
|     if (!IS_C_INVERTED && R ~^ IS_R_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; |     if (!IS_C_INVERTED && R == IS_R_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; | ||||||
|     if ( IS_C_INVERTED && R ~^ IS_R_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; |     if ( IS_C_INVERTED && R == IS_R_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | @ -529,7 +545,7 @@ module FDRE_1 ( | ||||||
|   always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; |   always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; | ||||||
|   specify |   specify | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 | ||||||
|     //$setup(D , negedge C &&& CE, -46); // Negative times not currently supported |     $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|     $setup(CE, negedge C, 109); |     $setup(CE, negedge C, 109); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 | ||||||
|  | @ -564,8 +580,8 @@ module FDSE ( | ||||||
|   endgenerate |   endgenerate | ||||||
|   specify |   specify | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 | ||||||
|     //$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported |     $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     //$setup(D , negedge C &&&  IS_C_INVERTED && CE, -46); // Negative times not currently supported |     $setup(D , negedge C &&&  IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|     $setup(CE, posedge C &&& !IS_C_INVERTED, 109); |     $setup(CE, posedge C &&& !IS_C_INVERTED, 109); | ||||||
|     $setup(CE, negedge C &&&  IS_C_INVERTED, 109); |     $setup(CE, negedge C &&&  IS_C_INVERTED, 109); | ||||||
|  | @ -573,10 +589,10 @@ module FDSE ( | ||||||
|     $setup(S , posedge C &&& !IS_C_INVERTED, 404); |     $setup(S , posedge C &&& !IS_C_INVERTED, 404); | ||||||
|     $setup(S , negedge C &&&  IS_C_INVERTED, 404); |     $setup(S , negedge C &&&  IS_C_INVERTED, 404); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 |     // https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L243 | ||||||
|     if (!IS_C_INVERTED && S ^ IS_S_INVERTED)        (posedge C => (Q : 1'b1)) = 303; |     if (!IS_C_INVERTED && S != IS_S_INVERTED)       (posedge C => (Q : 1'b1)) = 303; | ||||||
|     if ( IS_C_INVERTED && S ^ IS_S_INVERTED)        (negedge C => (Q : 1'b1)) = 303; |     if ( IS_C_INVERTED && S != IS_S_INVERTED)       (negedge C => (Q : 1'b1)) = 303; | ||||||
|     if (!IS_C_INVERTED && S ~^ IS_S_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; |     if (!IS_C_INVERTED && S == IS_S_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; | ||||||
|     if ( IS_C_INVERTED && S ~^ IS_S_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; |     if ( IS_C_INVERTED && S == IS_S_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | @ -594,7 +610,7 @@ module FDSE_1 ( | ||||||
|   always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; |   always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; | ||||||
|   specify |   specify | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 | ||||||
|     //$setup(D , negedge C &&& CE, -46); // Negative times not currently supported |     $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|     $setup(CE, negedge C, 109); |     $setup(CE, negedge C, 109); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 | ||||||
|  | @ -640,7 +656,7 @@ module FDRSE ( | ||||||
|       Q <= d; |       Q <= d; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| (* abc9_flop, lib_whitebox *) | (* abc9_box, lib_whitebox *) | ||||||
| module FDCE ( | module FDCE ( | ||||||
|   output reg Q, |   output reg Q, | ||||||
|   (* clkbuf_sink *) |   (* clkbuf_sink *) | ||||||
|  | @ -667,8 +683,8 @@ module FDCE ( | ||||||
|   endgenerate |   endgenerate | ||||||
|   specify |   specify | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 | ||||||
|     //$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported |     $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     //$setup(D , negedge C &&&  IS_C_INVERTED && CE, -46); // Negative times not currently supported |     $setup(D , negedge C &&&  IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|     $setup(CE , posedge C &&& !IS_C_INVERTED, 109); |     $setup(CE , posedge C &&& !IS_C_INVERTED, 109); | ||||||
|     $setup(CE , negedge C &&&  IS_C_INVERTED, 109); |     $setup(CE , negedge C &&&  IS_C_INVERTED, 109); | ||||||
|  | @ -676,14 +692,20 @@ module FDCE ( | ||||||
|     $setup(CLR, posedge C &&& !IS_C_INVERTED, 404); |     $setup(CLR, posedge C &&& !IS_C_INVERTED, 404); | ||||||
|     $setup(CLR, negedge C &&&  IS_C_INVERTED, 404); |     $setup(CLR, negedge C &&&  IS_C_INVERTED, 404); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 | ||||||
|     //if (!IS_CLR_INVERTED) (posedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0 | `ifndef YOSYS | ||||||
|     //if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0 |     if (!IS_CLR_INVERTED) (posedge CLR => (Q : 1'b0)) = 764; | ||||||
|     if (!IS_C_INVERTED && CLR ~^ IS_CLR_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; |     if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764; | ||||||
|     if ( IS_C_INVERTED && CLR ~^ IS_CLR_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; | `else | ||||||
|  |     if (IS_CLR_INVERTED != CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path | ||||||
|  |                                                   // but for facilitating a bypass box, let's pretend it's | ||||||
|  |                                                   // a simple path | ||||||
|  | `endif | ||||||
|  |     if (!IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; | ||||||
|  |     if ( IS_C_INVERTED && CLR == IS_CLR_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| (* abc9_flop, lib_whitebox *) | (* abc9_box, lib_whitebox *) | ||||||
| module FDCE_1 ( | module FDCE_1 ( | ||||||
|   output reg Q, |   output reg Q, | ||||||
|   (* clkbuf_sink *) |   (* clkbuf_sink *) | ||||||
|  | @ -697,18 +719,24 @@ module FDCE_1 ( | ||||||
|   always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; |   always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; | ||||||
|   specify |   specify | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 | ||||||
|     //$setup(D , negedge C &&& CE, -46); // Negative times not currently supported |     $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|     $setup(CE , negedge C, 109); |     $setup(CE , negedge C, 109); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 | ||||||
|     $setup(CLR, negedge C, 404); |     $setup(CLR, negedge C, 404); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 | ||||||
|     //(posedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0 | `ifndef YOSYS | ||||||
|  |     (posedge CLR => (Q : 1'b0)) = 764; | ||||||
|  | `else | ||||||
|  |     if (CLR) (CLR => Q) = 764; // Technically, this should be an edge sensitive path | ||||||
|  |                                // but for facilitating a bypass box, let's pretend it's | ||||||
|  |                                // a simple path | ||||||
|  | `endif | ||||||
|     if (!CLR && CE) (negedge C => (Q : D)) = 303; |     if (!CLR && CE) (negedge C => (Q : D)) = 303; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| (* abc9_flop, lib_whitebox *) | (* abc9_box, lib_whitebox *) | ||||||
| module FDPE ( | module FDPE ( | ||||||
|   output reg Q, |   output reg Q, | ||||||
|   (* clkbuf_sink *) |   (* clkbuf_sink *) | ||||||
|  | @ -734,8 +762,8 @@ module FDPE ( | ||||||
|   endgenerate |   endgenerate | ||||||
|   specify |   specify | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 | ||||||
|     //$setup(D , posedge C &&& !IS_C_INVERTED && CE, -46); // Negative times not currently supported |     $setup(D , posedge C &&& !IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     //$setup(D , negedge C &&&  IS_C_INVERTED && CE, -46); // Negative times not currently supported |     $setup(D , negedge C &&&  IS_C_INVERTED && CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|     $setup(CE , posedge C &&& !IS_C_INVERTED, 109); |     $setup(CE , posedge C &&& !IS_C_INVERTED, 109); | ||||||
|     $setup(CE , negedge C &&&  IS_C_INVERTED, 109); |     $setup(CE , negedge C &&&  IS_C_INVERTED, 109); | ||||||
|  | @ -743,14 +771,20 @@ module FDPE ( | ||||||
|     $setup(PRE, posedge C &&& !IS_C_INVERTED, 404); |     $setup(PRE, posedge C &&& !IS_C_INVERTED, 404); | ||||||
|     $setup(PRE, negedge C &&&  IS_C_INVERTED, 404); |     $setup(PRE, negedge C &&&  IS_C_INVERTED, 404); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 | ||||||
|     //if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 | `ifndef YOSYS | ||||||
|     //if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 |     if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; | ||||||
|     if (!IS_C_INVERTED && PRE ~^ IS_PRE_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; |     if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; | ||||||
|     if ( IS_C_INVERTED && PRE ~^ IS_PRE_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; | `else | ||||||
|  |     if (IS_PRE_INVERTED != PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path | ||||||
|  |                                                   // but for facilitating a bypass box, let's pretend it's | ||||||
|  |                                                   // a simple path | ||||||
|  | `endif | ||||||
|  |     if (!IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (posedge C => (Q : D ^ IS_D_INVERTED)) = 303; | ||||||
|  |     if ( IS_C_INVERTED && PRE == IS_PRE_INVERTED && CE) (negedge C => (Q : D ^ IS_D_INVERTED)) = 303; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| (* abc9_flop, lib_whitebox *) | (* abc9_box, lib_whitebox *) | ||||||
| module FDPE_1 ( | module FDPE_1 ( | ||||||
|   output reg Q, |   output reg Q, | ||||||
|   (* clkbuf_sink *) |   (* clkbuf_sink *) | ||||||
|  | @ -764,14 +798,19 @@ module FDPE_1 ( | ||||||
|   always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; |   always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; | ||||||
|   specify |   specify | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L249 | ||||||
|     //$setup(D , negedge C &&& CE, -46); // Negative times not currently supported |     $setup(D , negedge C &&& CE, /*-46*/ 0); // Negative times not currently supported | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|     $setup(CE , negedge C, 109); |     $setup(CE , negedge C, 109); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 | ||||||
|     $setup(PRE, negedge C, 404); |     $setup(PRE, negedge C, 404); | ||||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L270 | ||||||
|     //if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 | `ifndef YOSYS | ||||||
|     //if (IS_PRE_INVERTED)  (negedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 |     (posedge PRE => (Q : 1'b1)) = 764; | ||||||
|  | `else | ||||||
|  |     if (PRE) (PRE => Q) = 764; // Technically, this should be an edge sensitive path | ||||||
|  |                                // but for facilitating a bypass box, let's pretend it's | ||||||
|  |                                // a simple path | ||||||
|  | `endif | ||||||
|     if (!PRE && CE) (negedge C => (Q : D)) = 303; |     if (!PRE && CE) (negedge C => (Q : D)) = 303; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
|  | @ -1383,6 +1422,7 @@ module RAM16X1D_1 ( | ||||||
|   always @(negedge clk) if (WE) mem[a] <= D; |   always @(negedge clk) if (WE) mem[a] <= D; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module RAM32X1D ( | module RAM32X1D ( | ||||||
|   output DPO, SPO, |   output DPO, SPO, | ||||||
|   input  D, |   input  D, | ||||||
|  | @ -1429,15 +1469,15 @@ module RAM32X1D ( | ||||||
|     if (!IS_WCLK_INVERTED) (posedge WCLK => (DPO : 1'bx)) = 1153; |     if (!IS_WCLK_INVERTED) (posedge WCLK => (DPO : 1'bx)) = 1153; | ||||||
|     if ( IS_WCLK_INVERTED) (posedge WCLK => (SPO : D))    = 1153; |     if ( IS_WCLK_INVERTED) (posedge WCLK => (SPO : D))    = 1153; | ||||||
|     if ( IS_WCLK_INVERTED) (negedge WCLK => (DPO : 1'bx)) = 1153; |     if ( IS_WCLK_INVERTED) (negedge WCLK => (DPO : 1'bx)) = 1153; | ||||||
|     // Captured by $__ABC9_RAM6 |     (A0 => SPO) = 642; (DPRA0 => DPO) = 642; | ||||||
|     //({A0,DPRA0} => {SPO,DPO}) = 642; |     (A1 => SPO) = 632; (DPRA1 => DPO) = 631; | ||||||
|     //({A1,DPRA1} => {SPO,DPO}) = 631; |     (A2 => SPO) = 472; (DPRA2 => DPO) = 472; | ||||||
|     //({A2,DPRA2} => {SPO,DPO}) = 472; |     (A3 => SPO) = 407; (DPRA3 => DPO) = 407; | ||||||
|     //({A3,DPRA3} => {SPO,DPO}) = 407; |     (A4 => SPO) = 238; (DPRA4 => DPO) = 238; | ||||||
|     //({A4,DPRA4} => {SPO,DPO}) = 238; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module RAM32X1D_1 ( | module RAM32X1D_1 ( | ||||||
|   output DPO, SPO, |   output DPO, SPO, | ||||||
|   input  D, |   input  D, | ||||||
|  | @ -1479,15 +1519,15 @@ module RAM32X1D_1 ( | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 | ||||||
|     if (WE) (negedge WCLK => (SPO : D))    = 1153; |     if (WE) (negedge WCLK => (SPO : D))    = 1153; | ||||||
|     if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; |     if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; | ||||||
|     // Captured by $__ABC9_RAM6 |     (A0 => SPO) = 642; (DPRA0 => DPO) = 642; | ||||||
|     //({A0,DPRA0} => {SPO,DPO}) = 642; |     (A1 => SPO) = 632; (DPRA1 => DPO) = 631; | ||||||
|     //({A1,DPRA1} => {SPO,DPO}) = 631; |     (A2 => SPO) = 472; (DPRA2 => DPO) = 472; | ||||||
|     //({A2,DPRA2} => {SPO,DPO}) = 472; |     (A3 => SPO) = 407; (DPRA3 => DPO) = 407; | ||||||
|     //({A3,DPRA3} => {SPO,DPO}) = 407; |     (A4 => SPO) = 238; (DPRA4 => DPO) = 238; | ||||||
|     //({A4,DPRA4} => {SPO,DPO}) = 238; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module RAM64X1D ( | module RAM64X1D ( | ||||||
|   output DPO, SPO, |   output DPO, SPO, | ||||||
|   input  D, |   input  D, | ||||||
|  | @ -1537,13 +1577,12 @@ module RAM64X1D ( | ||||||
|     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DPO : 1'bx)) = 1153; |     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DPO : 1'bx)) = 1153; | ||||||
|     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (SPO : D))    = 1153; |     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (SPO : D))    = 1153; | ||||||
|     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153; |     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153; | ||||||
|     // Captured by $__ABC9_RAM6 |     (A0 => SPO) = 642; (DPRA0 => DPO) = 642; | ||||||
|     //({A0,DPRA0} => {SPO,DPO}) = 642; |     (A1 => SPO) = 632; (DPRA1 => DPO) = 631; | ||||||
|     //({A1,DPRA1} => {SPO,DPO}) = 631; |     (A2 => SPO) = 472; (DPRA2 => DPO) = 472; | ||||||
|     //({A2,DPRA2} => {SPO,DPO}) = 472; |     (A3 => SPO) = 407; (DPRA3 => DPO) = 407; | ||||||
|     //({A3,DPRA3} => {SPO,DPO}) = 407; |     (A4 => SPO) = 238; (DPRA4 => DPO) = 238; | ||||||
|     //({A4,DPRA4} => {SPO,DPO}) = 238; |     (A5 => SPO) = 127; (DPRA5 => DPO) = 127; | ||||||
|     //({A5,DPRA5} => {SPO,DPO}) = 127; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | @ -1586,9 +1625,16 @@ module RAM64X1D_1 ( | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 | ||||||
|     if (WE) (negedge WCLK => (SPO : D))    = 1153; |     if (WE) (negedge WCLK => (SPO : D))    = 1153; | ||||||
|     if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; |     if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; | ||||||
|  |     (A0 => SPO) = 642; (DPRA0 => DPO) = 642; | ||||||
|  |     (A1 => SPO) = 632; (DPRA1 => DPO) = 631; | ||||||
|  |     (A2 => SPO) = 472; (DPRA2 => DPO) = 472; | ||||||
|  |     (A3 => SPO) = 407; (DPRA3 => DPO) = 407; | ||||||
|  |     (A4 => SPO) = 238; (DPRA4 => DPO) = 238; | ||||||
|  |     (A5 => SPO) = 127; (DPRA5 => DPO) = 127; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module RAM128X1D ( | module RAM128X1D ( | ||||||
|   output       DPO, SPO, |   output       DPO, SPO, | ||||||
|   input        D, |   input        D, | ||||||
|  | @ -1632,22 +1678,21 @@ module RAM128X1D ( | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/31f51ac5ec7448dd6f79a8267f147123e4413c21/artix7/timings/CLBLM_R.sdf#L981 | ||||||
|     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (SPO : D))    = 1153 + 217 /* to cross F7AMUX */ + 175 /* AMUX */; |     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (SPO : D))    = 1153 + 217 /* to cross F7AMUX */ + 175 /* AMUX */; | ||||||
|     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; |     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DPO : 1'bx)) = 1153 + 223 /* to cross F7BMUX */ + 174 /* CMUX */; | ||||||
|  |     (A[0] => SPO) = 642 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; | ||||||
|  |     (A[1] => SPO) = 631 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; | ||||||
|  |     (A[2] => SPO) = 472 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; | ||||||
|  |     (A[3] => SPO) = 407 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; | ||||||
|  |     (A[4] => SPO) = 238 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; | ||||||
|  |     (A[5] => SPO) = 127 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; | ||||||
|  |     (A[6] => SPO) = 0 + 276 /* to select F7AMUX */ + 175 /* AMUX */; | ||||||
|  |     (DPRA[0] => DPO) = 642 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; | ||||||
|  |     (DPRA[1] => DPO) = 631 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; | ||||||
|  |     (DPRA[2] => DPO) = 472 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; | ||||||
|  |     (DPRA[3] => DPO) = 407 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; | ||||||
|  |     (DPRA[4] => DPO) = 238 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; | ||||||
|  |     (DPRA[5] => DPO) = 127 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; | ||||||
|  |     (DPRA[6] => DPO) = 0 + 296 /* to select MUXF7 */ + 174 /* CMUX */; | ||||||
| `endif | `endif | ||||||
|     // Captured by $__ABC9_RAM7 |  | ||||||
|     //(A[0] => SPO) = 642 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; |  | ||||||
|     //(A[1] => SPO) = 631 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; |  | ||||||
|     //(A[2] => SPO) = 472 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; |  | ||||||
|     //(A[3] => SPO) = 407 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; |  | ||||||
|     //(A[4] => SPO) = 238 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; |  | ||||||
|     //(A[5] => SPO) = 127 + 193 /* to cross F7AMUX */ + 175 /* AMUX */; |  | ||||||
|     //(A[6] => SPO) = 0 + 276 /* to select F7AMUX */ + 175 /* AMUX */; |  | ||||||
|     //(DPRA[0] => DPO) = 642 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; |  | ||||||
|     //(DPRA[1] => DPO) = 631 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; |  | ||||||
|     //(DPRA[2] => DPO) = 472 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; |  | ||||||
|     //(DPRA[3] => DPO) = 407 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; |  | ||||||
|     //(DPRA[4] => DPO) = 238 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; |  | ||||||
|     //(DPRA[5] => DPO) = 127 + 223 /* to cross MUXF7 */ + 174 /* CMUX */; |  | ||||||
|     //(DPRA[6] => DPO) = 0 + 296 /* to select MUXF7 */ + 174 /* CMUX */; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | @ -1671,6 +1716,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // Multi port. | // Multi port. | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module RAM32M ( | module RAM32M ( | ||||||
|   output [1:0] DOA, |   output [1:0] DOA, | ||||||
|   output [1:0] DOB, |   output [1:0] DOB, | ||||||
|  | @ -1767,12 +1813,11 @@ module RAM32M ( | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1061 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1061 | ||||||
|     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD[1] : DID[1])) = 1190; |     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD[1] : DID[1])) = 1190; | ||||||
|     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD[1] : DID[1])) = 1190; |     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD[1] : DID[1])) = 1190; | ||||||
|     // Captured by $__ABC9_RAM6 |     (ADDRA[0] *> DOA) = 642; (ADDRB[0] *> DOB) = 642; (ADDRC[0] *> DOC) = 642; (ADDRD[0] *> DOD) = 642; | ||||||
|     //({{2{ADDRA[0]}},{2{ADDRB[0]}},{2{ADDRC[0]}},{2{ADDRD[0]}}} => {DOA,DOB,DOC,DOD}) = 642; |     (ADDRA[1] *> DOA) = 631; (ADDRB[1] *> DOB) = 631; (ADDRC[1] *> DOC) = 631; (ADDRD[1] *> DOD) = 631; | ||||||
|     //({{2{ADDRA[1]}},{2{ADDRB[1]}},{2{ADDRC[1]}},{2{ADDRD[1]}}} => {DOA,DOB,DOC,DOD}) = 631; |     (ADDRA[2] *> DOA) = 472; (ADDRB[2] *> DOB) = 472; (ADDRC[2] *> DOC) = 472; (ADDRD[2] *> DOD) = 472; | ||||||
|     //({{2{ADDRA[2]}},{2{ADDRB[2]}},{2{ADDRC[2]}},{2{ADDRD[2]}}} => {DOA,DOB,DOC,DOD}) = 472; |     (ADDRA[3] *> DOA) = 407; (ADDRB[3] *> DOB) = 407; (ADDRC[3] *> DOC) = 407; (ADDRD[3] *> DOD) = 407; | ||||||
|     //({{2{ADDRA[3]}},{2{ADDRB[3]}},{2{ADDRC[3]}},{2{ADDRD[3]}}} => {DOA,DOB,DOC,DOD}) = 407; |     (ADDRA[4] *> DOA) = 238; (ADDRB[4] *> DOB) = 238; (ADDRC[4] *> DOC) = 238; (ADDRD[4] *> DOD) = 238; | ||||||
|     //({{2{ADDRA[4]}},{2{ADDRB[4]}},{2{ADDRC[4]}},{2{ADDRD[4]}}} => {DOA,DOB,DOC,DOD}) = 238; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | @ -1845,6 +1890,7 @@ module RAM32M16 ( | ||||||
|     end |     end | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module RAM64M ( | module RAM64M ( | ||||||
|   output       DOA, |   output       DOA, | ||||||
|   output       DOB, |   output       DOB, | ||||||
|  | @ -1923,12 +1969,11 @@ module RAM64M ( | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L1093 | ||||||
|     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD : DID)) = 1163; |     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD : DID)) = 1163; | ||||||
|     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD : DID)) = 1163; |     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD : DID)) = 1163; | ||||||
|     // Captured by $__ABC9_RAM6 |     (ADDRA[0] => DOA) = 642; (ADDRB[0] => DOB) = 642; (ADDRC[0] => DOC) = 642; (ADDRD[0] => DOD) = 642; | ||||||
|     //({ADDRA[0],ADDRB[0],ADDRC[0],ADDRD[0]} => {DOA,DOB,DOC,DOD}) = 642; |     (ADDRA[1] => DOA) = 631; (ADDRB[1] => DOB) = 631; (ADDRC[1] => DOC) = 631; (ADDRD[1] => DOD) = 631; | ||||||
|     //({ADDRA[1],ADDRB[1],ADDRC[1],ADDRD[1]} => {DOA,DOB,DOC,DOD}) = 631; |     (ADDRA[2] => DOA) = 472; (ADDRB[2] => DOB) = 472; (ADDRC[2] => DOC) = 472; (ADDRD[2] => DOD) = 472; | ||||||
|     //({ADDRA[2],ADDRB[2],ADDRC[2],ADDRD[2]} => {DOA,DOB,DOC,DOD}) = 472; |     (ADDRA[3] => DOA) = 407; (ADDRB[3] => DOB) = 407; (ADDRC[3] => DOC) = 407; (ADDRD[3] => DOD) = 407; | ||||||
|     //({ADDRA[3],ADDRB[3],ADDRC[3],ADDRD[3]} => {DOA,DOB,DOC,DOD}) = 407; |     (ADDRA[4] => DOA) = 238; (ADDRB[4] => DOB) = 238; (ADDRC[4] => DOC) = 238; (ADDRD[4] => DOD) = 238; | ||||||
|     //({ADDRA[4],ADDRB[4],ADDRC[4],ADDRD[4]} => {DOA,DOB,DOC,DOD}) = 238; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | @ -2045,6 +2090,7 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // Shift registers. | // Shift registers. | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SRL16 ( | module SRL16 ( | ||||||
|   output Q, |   output Q, | ||||||
|   input A0, A1, A2, A3, |   input A0, A1, A2, A3, | ||||||
|  | @ -2063,14 +2109,14 @@ module SRL16 ( | ||||||
|     (posedge CLK => (Q : 1'bx)) = 1472; |     (posedge CLK => (Q : 1'bx)) = 1472; | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 | ||||||
|     $setup(D , posedge CLK, 173); |     $setup(D , posedge CLK, 173); | ||||||
|     // Captured by $__ABC9_RAM6 |     (A0 => Q) = 631; | ||||||
|     //(A0 => Q) = 631; |     (A1 => Q) = 472; | ||||||
|     //(A1 => Q) = 472; |     (A2 => Q) = 407; | ||||||
|     //(A2 => Q) = 407; |     (A3 => Q) = 238; | ||||||
|     //(A3 => Q) = 238; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SRL16E ( | module SRL16E ( | ||||||
|   output Q, |   output Q, | ||||||
|   input A0, A1, A2, A3, CE, |   input A0, A1, A2, A3, CE, | ||||||
|  | @ -2096,16 +2142,19 @@ module SRL16E ( | ||||||
|     $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); |     $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); | ||||||
|     $setup(D , negedge CLK &&&  IS_CLK_INVERTED, 173); |     $setup(D , negedge CLK &&&  IS_CLK_INVERTED, 173); | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 | ||||||
|  |     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472; | ||||||
|  |     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472; | ||||||
|  |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 | ||||||
|     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472; |     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472; | ||||||
|     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472; |     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472; | ||||||
|     // Captured by $__ABC9_RAM6 |     (A0 => Q) = 631; | ||||||
|     //(A0 => Q) = 631; |     (A1 => Q) = 472; | ||||||
|     //(A1 => Q) = 472; |     (A2 => Q) = 407; | ||||||
|     //(A2 => Q) = 407; |     (A3 => Q) = 238; | ||||||
|     //(A3 => Q) = 238; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SRLC16 ( | module SRLC16 ( | ||||||
|   output Q, |   output Q, | ||||||
|   output Q15, |   output Q15, | ||||||
|  | @ -2122,18 +2171,20 @@ module SRLC16 ( | ||||||
|   always @(posedge CLK) r <= { r[14:0], D }; |   always @(posedge CLK) r <= { r[14:0], D }; | ||||||
| 
 | 
 | ||||||
|   specify |   specify | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 |  | ||||||
|     (posedge CLK => (Q : 1'bx)) = 1472; |  | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 | ||||||
|     $setup(D , posedge CLK, 173); |     $setup(D , posedge CLK, 173); | ||||||
|     // Captured by $__ABC9_RAM6 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 | ||||||
|     //(A0 => Q) = 631; |     (posedge CLK => (Q : 1'bx)) = 1472; | ||||||
|     //(A1 => Q) = 472; |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 | ||||||
|     //(A2 => Q) = 407; |     (posedge CLK => (Q15 : 1'bx)) = 1114; | ||||||
|     //(A3 => Q) = 238; |     (A0 => Q) = 631; | ||||||
|  |     (A1 => Q) = 472; | ||||||
|  |     (A2 => Q) = 407; | ||||||
|  |     (A3 => Q) = 238; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SRLC16E ( | module SRLC16E ( | ||||||
|   output Q, |   output Q, | ||||||
|   output Q15, |   output Q15, | ||||||
|  | @ -2160,18 +2211,23 @@ module SRLC16E ( | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 | ||||||
|     $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); |     $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); | ||||||
|     $setup(D , negedge CLK &&&  IS_CLK_INVERTED, 173); |     $setup(D , negedge CLK &&&  IS_CLK_INVERTED, 173); | ||||||
|  |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|  |     $setup(CE, posedge CLK &&& !IS_CLK_INVERTED, 109); | ||||||
|  |     $setup(CE, negedge CLK &&&  IS_CLK_INVERTED, 109); | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 | ||||||
|     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472; |     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472; | ||||||
|     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472; |     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472; | ||||||
|     // Captured by $__ABC9_RAM6 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 | ||||||
|     //(A0 => Q) = 642; |     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q15 : 1'bx)) = 1114; | ||||||
|     //(A1 => Q) = 631; |     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q15 : 1'bx)) = 1114; | ||||||
|     //(A2 => Q) = 472; |     (A0 => Q) = 631; | ||||||
|     //(A3 => Q) = 407; |     (A1 => Q) = 472; | ||||||
|     //(A4 => Q) = 238; |     (A2 => Q) = 407; | ||||||
|  |     (A3 => Q) = 238; | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | (* abc9_box, lib_whitebox *) | ||||||
| module SRLC32E ( | module SRLC32E ( | ||||||
|   output Q, |   output Q, | ||||||
|   output Q31, |   output Q31, | ||||||
|  | @ -2199,18 +2255,20 @@ module SRLC32E ( | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 | ||||||
|     $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); |     $setup(D , posedge CLK &&& !IS_CLK_INVERTED, 173); | ||||||
|     $setup(D , negedge CLK &&&  IS_CLK_INVERTED, 173); |     $setup(D , negedge CLK &&&  IS_CLK_INVERTED, 173); | ||||||
|  |     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||||
|  |     $setup(CE, posedge CLK &&& !IS_CLK_INVERTED, 109); | ||||||
|  |     $setup(CE, negedge CLK &&&  IS_CLK_INVERTED, 109); | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L905 | ||||||
|     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472; |     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1472; | ||||||
|     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472; |     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1472; | ||||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 |     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 | ||||||
|     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1114; |     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q31 : 1'bx)) = 1114; | ||||||
|     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1114; |     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q31 : 1'bx)) = 1114; | ||||||
|     // Captured by $__ABC9_RAM6 |     (A[0] => Q) = 642; | ||||||
|     //(A0 => Q) = 642; |     (A[1] => Q) = 631; | ||||||
|     //(A1 => Q) = 631; |     (A[2] => Q) = 472; | ||||||
|     //(A2 => Q) = 472; |     (A[3] => Q) = 407; | ||||||
|     //(A3 => Q) = 407; |     (A[4] => Q) = 238; | ||||||
|     //(A4 => Q) = 238; |  | ||||||
|   endspecify |   endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | @ -2978,6 +3036,10 @@ endmodule | ||||||
| 
 | 
 | ||||||
| // Virtex 6, Series 7. | // Virtex 6, Series 7. | ||||||
| 
 | 
 | ||||||
|  | `ifdef YOSYS | ||||||
|  | (* abc9_box=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG), | ||||||
|  |    lib_whitebox=!(PREG || AREG || ADREG || BREG || CREG || DREG || MREG) *) | ||||||
|  | `endif | ||||||
| module DSP48E1 ( | module DSP48E1 ( | ||||||
|     output [29:0] ACOUT, |     output [29:0] ACOUT, | ||||||
|     output [17:0] BCOUT, |     output [17:0] BCOUT, | ||||||
|  |  | ||||||
|  | @ -143,7 +143,7 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 
 | 
 | ||||||
| 	std::string top_opt, edif_file, blif_file, family; | 	std::string top_opt, edif_file, blif_file, family; | ||||||
| 	bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; | 	bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; | ||||||
| 	bool abc9, dff_mode; | 	bool abc9, dff; | ||||||
| 	bool flatten_before_abc; | 	bool flatten_before_abc; | ||||||
| 	int widemux; | 	int widemux; | ||||||
| 	int lut_size; | 	int lut_size; | ||||||
|  | @ -170,7 +170,7 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 		nodsp = false; | 		nodsp = false; | ||||||
| 		uram = false; | 		uram = false; | ||||||
| 		abc9 = false; | 		abc9 = false; | ||||||
| 		dff_mode = false; | 		dff = false; | ||||||
| 		flatten_before_abc = false; | 		flatten_before_abc = false; | ||||||
| 		widemux = 0; | 		widemux = 0; | ||||||
| 		lut_size = 6; | 		lut_size = 6; | ||||||
|  | @ -217,7 +217,7 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-retime") { | 			if (args[argidx] == "-retime") { | ||||||
| 				dff_mode = true; | 				dff = true; | ||||||
| 				retime = true; | 				retime = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | @ -281,7 +281,7 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-dff") { | 			if (args[argidx] == "-dff") { | ||||||
| 				dff_mode = true; | 				dff = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
|  | @ -595,9 +595,11 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 			run("clean"); | 			run("clean"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("map_ffs")) { | 		if (check_label("map_ffs", "('-abc9' only)")) { | ||||||
| 			if (abc9 || help_mode) { | 			if (abc9 || help_mode) { | ||||||
| 				run("techmap -map " + ff_map_file, "('-abc9' only)"); | 				if (dff || help_mode) | ||||||
|  | 					run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$__DFFS*", "('-dff' only)"); | ||||||
|  | 				run("techmap -map " + ff_map_file); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -606,18 +608,14 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 			if (flatten_before_abc) | 			if (flatten_before_abc) | ||||||
| 				run("flatten"); | 				run("flatten"); | ||||||
| 			if (help_mode) | 			if (help_mode) | ||||||
| 				run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for 'nowidelut', '-dff', '-retime')"); | 				run("abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1]", "(option for '-nowidelut', '-dff', '-retime')"); | ||||||
| 			else if (abc9) { | 			else if (abc9) { | ||||||
| 				if (lut_size != 6) | 				if (lut_size != 6) | ||||||
| 					log_error("'synth_xilinx -abc9' not currently supported for LUT4-based devices.\n"); | 					log_error("'synth_xilinx -abc9' not currently supported for LUT4-based devices.\n"); | ||||||
| 				if (family != "xc7") | 				if (family != "xc7") | ||||||
| 					log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " | 					log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " | ||||||
| 							"will use timing for 'xc7' instead.\n", family.c_str()); | 							"will use timing for 'xc7' instead.\n", family.c_str()); | ||||||
| 				std::string techmap_args = "-map +/xilinx/abc9_map.v -max_iter 1"; | 				run("read_verilog -icells -lib -specify +/xilinx/abc9_model.v"); | ||||||
| 				if (dff_mode) |  | ||||||
| 					techmap_args += " -D DFF_MODE"; |  | ||||||
| 				run("techmap " + techmap_args); |  | ||||||
| 				run("read_verilog -icells -lib -specify +/abc9_model.v +/xilinx/abc9_model.v"); |  | ||||||
| 				std::string abc9_opts; | 				std::string abc9_opts; | ||||||
| 				std::string k = "synth_xilinx.abc9.W"; | 				std::string k = "synth_xilinx.abc9.W"; | ||||||
| 				if (active_design && active_design->scratchpad.count(k)) | 				if (active_design && active_design->scratchpad.count(k)) | ||||||
|  | @ -628,10 +626,9 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 				} | 				} | ||||||
| 				if (nowidelut) | 				if (nowidelut) | ||||||
| 					abc9_opts += stringf(" -maxlut %d", lut_size); | 					abc9_opts += stringf(" -maxlut %d", lut_size); | ||||||
| 				if (dff_mode) | 				if (dff) | ||||||
| 					abc9_opts += " -dff"; | 					abc9_opts += " -dff"; | ||||||
| 				run("abc9" + abc9_opts); | 				run("abc9" + abc9_opts); | ||||||
| 				run("techmap -map +/xilinx/abc9_unmap.v"); |  | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
| 				std::string abc_opts; | 				std::string abc_opts; | ||||||
|  | @ -648,7 +645,7 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 					else | 					else | ||||||
| 						abc_opts += " -luts 2:2,3,6:5,10,20,40"; | 						abc_opts += " -luts 2:2,3,6:5,10,20,40"; | ||||||
| 				} | 				} | ||||||
| 				if (dff_mode) | 				if (dff) | ||||||
| 					abc_opts += " -dff"; | 					abc_opts += " -dff"; | ||||||
| 				if (retime) | 				if (retime) | ||||||
| 					abc_opts += " -D 1"; | 					abc_opts += " -D 1"; | ||||||
|  |  | ||||||
|  | @ -1,32 +1,85 @@ | ||||||
|  | logger -nowarn "Yosys has only limited support for tri-state logic at the moment\. .*" | ||||||
|  | 
 | ||||||
| read_verilog <<EOT | read_verilog <<EOT | ||||||
| module top(input C, D, output [7:0] Q); | module top(input C, D, output [7:0] Q); | ||||||
| FDRE   fd1(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[0])); | FDRE   /*#(.INIT(0))*/ fd1(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[0])); | ||||||
| FDSE   fd2(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[1])); | FDSE   #(.INIT(0)) fd2(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[1])); | ||||||
| FDCE   fd3(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[2])); | FDCE   #(.INIT(0)) fd3(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[2])); | ||||||
| FDPE   fd4(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[3])); | FDPE   #(.INIT(0)) fd4(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[3])); | ||||||
| FDRE_1 fd5(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[4])); | FDRE_1 #(.INIT(0)) fd5(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[4])); | ||||||
| FDSE_1 fd6(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[5])); | FDSE_1 #(.INIT(0)) fd6(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[5])); | ||||||
| FDCE_1 fd7(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[6])); | FDCE_1 #(.INIT(0)) fd7(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[6])); | ||||||
| FDPE_1 fd8(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[7])); | FDPE_1 #(.INIT(0)) fd8(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[7])); | ||||||
| endmodule | endmodule | ||||||
| EOT | EOT | ||||||
| equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf | equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf | ||||||
| design -load postopt | design -load postopt | ||||||
| select -assert-none t:FD* | select -assert-count 6 t:FD* | ||||||
|  | select -assert-count 6 c:fd2 c:fd3 c:fd4 c:fd6 c:fd7 c:fd8 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| design -reset | design -reset | ||||||
| read_verilog <<EOT | read_verilog <<EOT | ||||||
| module top(input C, D, output [7:0] Q); | module top(input C, D, output [7:0] Q); | ||||||
| FDRE   fd1(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[0])); | FDRE   #(.INIT(0)) fd1(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[0])); | ||||||
| FDSE   fd2(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[1])); | FDSE   #(.INIT(0)) fd2(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[1])); | ||||||
| FDCE   fd3(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[2])); | FDCE   #(.INIT(0)) fd3(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[2])); | ||||||
| FDPE   fd4(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[3])); | FDPE   #(.INIT(0)) fd4(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[3])); | ||||||
| FDRE_1 fd5(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[4])); | FDRE_1 /*#(.INIT(0))*/ fd5(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[4])); | ||||||
| FDSE_1 fd6(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[5])); | FDSE_1 #(.INIT(0)) fd6(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[5])); | ||||||
| FDCE_1 fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6])); | FDCE_1 #(.INIT(0)) fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6])); | ||||||
| FDPE_1 fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7])); | FDPE_1 #(.INIT(0)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7])); | ||||||
| endmodule | endmodule | ||||||
| EOT | EOT | ||||||
| equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf | equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf | ||||||
| design -load postopt | design -load postopt | ||||||
| select -assert-none t:FD* | select -assert-count 4 t:FD* | ||||||
|  | select -assert-count 4 c:fd3 c:fd4 c:fd7 c:fd8 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | design -reset | ||||||
|  | read_verilog <<EOT | ||||||
|  | module top(input C, D, output [7:0] Q); | ||||||
|  | FDRE   #(.INIT(1)) fd1(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[0])); | ||||||
|  | FDSE   /*#(.INIT(1))*/ fd2(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[1])); | ||||||
|  | FDCE   #(.INIT(1)) fd3(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[2])); | ||||||
|  | FDPE   #(.INIT(1)) fd4(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[3])); | ||||||
|  | FDRE_1 #(.INIT(1)) fd5(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[4])); | ||||||
|  | FDSE_1 #(.INIT(1)) fd6(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[5])); | ||||||
|  | FDCE_1 /*#(.INIT(1))*/ fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6])); | ||||||
|  | FDPE_1 #(.INIT(1)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7])); | ||||||
|  | endmodule | ||||||
|  | EOT | ||||||
|  | logger -expect warning "Module '\$paramod\\FDRE\\INIT=1' contains a \$dff cell .*" 1 | ||||||
|  | logger -expect warning "Module '\$paramod\\FDRE_1\\INIT=1' contains a \$dff cell .*" 1 | ||||||
|  | logger -expect warning "Module 'FDSE' contains a \$dff cell .*" 1 | ||||||
|  | logger -expect warning "Module '\$paramod\\FDSE_1\\INIT=1' contains a \$dff cell .*" 1 | ||||||
|  | equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf | ||||||
|  | design -load postopt | ||||||
|  | select -assert-count 8 t:FD* | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | design -reset | ||||||
|  | read_verilog <<EOT | ||||||
|  | module top(input clk, clr, pre, output reg q0 = 1'b0, output reg q1 = 1'b1); | ||||||
|  | always @(posedge clk or posedge clr) | ||||||
|  |     if (clr) | ||||||
|  |         q0 <= 1'b0; | ||||||
|  |     else | ||||||
|  |         q0 <= ~q0; | ||||||
|  | always @(posedge clk or posedge pre) | ||||||
|  |     if (pre) | ||||||
|  |         q1 <= 1'b1; | ||||||
|  |     else | ||||||
|  |         q1 <= ~q1; | ||||||
|  | endmodule | ||||||
|  | EOT | ||||||
|  | proc | ||||||
|  | equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf | ||||||
|  | design -load postopt | ||||||
|  | select -assert-count 1 t:FDCE | ||||||
|  | select -assert-count 1 t:FDPE | ||||||
|  | select -assert-count 2 t:INV | ||||||
|  | select -assert-count 0 t:FD* t:INV %% t:* %D | ||||||
|  | 
 | ||||||
|  | logger -expect-no-warnings | ||||||
|  |  | ||||||
|  | @ -1,91 +0,0 @@ | ||||||
| read_verilog <<EOT |  | ||||||
| module top(input C, CE, D, R, output [1:0] Q); |  | ||||||
| FDRE   #(.INIT(1'b1)) ff1 (.C(C), .CE(CE), .D(D), .R(R), .Q(Q[0])); |  | ||||||
| FDRE_1 #(.INIT(1'b1)) ff2 (.C(C), .CE(CE), .D(D), .R(R), .Q(Q[1])); |  | ||||||
| endmodule |  | ||||||
| EOT |  | ||||||
| design -save gold |  | ||||||
| 
 |  | ||||||
| techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE |  | ||||||
| techmap -map +/xilinx/abc9_unmap.v |  | ||||||
| select -assert-count 1 t:FDSE |  | ||||||
| select -assert-count 1 t:FDSE_1 |  | ||||||
| techmap -autoproc -map +/xilinx/cells_sim.v |  | ||||||
| design -stash gate |  | ||||||
| 
 |  | ||||||
| design -import gold -as gold |  | ||||||
| design -import gate -as gate |  | ||||||
| techmap -autoproc -map +/xilinx/cells_sim.v |  | ||||||
| 
 |  | ||||||
| miter -equiv -flatten -make_assert -make_outputs gold gate miter |  | ||||||
| sat -seq 2 -verify -prove-asserts -show-ports miter |  | ||||||
| 
 |  | ||||||
| design -reset |  | ||||||
| read_verilog <<EOT |  | ||||||
| module top(input C, CE, D, S, output [1:0] Q); |  | ||||||
| FDSE   #(.INIT(1'b1)) ff1 (.C(C), .CE(CE), .D(D), .S(S), .Q(Q[0])); |  | ||||||
| FDSE_1 #(.INIT(1'b1)) ff2 (.C(C), .CE(CE), .D(D), .S(S), .Q(Q[1])); |  | ||||||
| endmodule |  | ||||||
| EOT |  | ||||||
| design -save gold |  | ||||||
| 
 |  | ||||||
| techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE |  | ||||||
| techmap -map +/xilinx/abc9_unmap.v |  | ||||||
| select -assert-count 1 t:FDRE |  | ||||||
| select -assert-count 1 t:FDRE_1 |  | ||||||
| techmap -autoproc -map +/xilinx/cells_sim.v |  | ||||||
| design -stash gate |  | ||||||
| 
 |  | ||||||
| design -import gold -as gold |  | ||||||
| design -import gate -as gate |  | ||||||
| techmap -autoproc -map +/xilinx/cells_sim.v |  | ||||||
| 
 |  | ||||||
| miter -equiv -flatten -make_assert -make_outputs gold gate miter |  | ||||||
| sat -seq 2 -set-init-zero -verify -prove-asserts -show-ports miter |  | ||||||
| 
 |  | ||||||
| design -reset |  | ||||||
| read_verilog <<EOT |  | ||||||
| module top(input C, CE, D, PRE, output [1:0] Q); |  | ||||||
| FDPE   #(.INIT(1'b1)) ff1 (.C(C), .CE(CE), .D(D), .PRE(PRE), .Q(Q[0])); |  | ||||||
| FDPE_1 #(.INIT(1'b1)) ff2 (.C(C), .CE(CE), .D(D), .PRE(PRE), .Q(Q[1])); |  | ||||||
| endmodule |  | ||||||
| EOT |  | ||||||
| design -save gold |  | ||||||
| 
 |  | ||||||
| techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE |  | ||||||
| techmap -map +/xilinx/abc9_unmap.v |  | ||||||
| select -assert-count 1 t:FDCE |  | ||||||
| select -assert-count 1 t:FDCE_1 |  | ||||||
| techmap -autoproc -map +/xilinx/cells_sim.v |  | ||||||
| design -stash gate |  | ||||||
| 
 |  | ||||||
| design -import gold -as gold |  | ||||||
| design -import gate -as gate |  | ||||||
| techmap -autoproc -map +/xilinx/cells_sim.v |  | ||||||
| clk2fflogic |  | ||||||
| 
 |  | ||||||
| miter -equiv -flatten -make_assert -make_outputs gold gate miter |  | ||||||
| sat -seq 2 -set-init-zero -verify -prove-asserts -show-ports miter |  | ||||||
| 
 |  | ||||||
| design -reset |  | ||||||
| read_verilog <<EOT |  | ||||||
| module top(input C, CE, D, CLR, output [1:0] Q); |  | ||||||
| FDCE   #(.INIT(1'b1)) ff1 (.C(C), .CE(CE), .D(D), .CLR(CLR), .Q(Q[0])); |  | ||||||
| FDCE_1 #(.INIT(1'b1)) ff2 (.C(C), .CE(CE), .D(D), .CLR(CLR), .Q(Q[1])); |  | ||||||
| endmodule |  | ||||||
| EOT |  | ||||||
| design -save gold |  | ||||||
| 
 |  | ||||||
| techmap -map +/xilinx/abc9_map.v -max_iter 1 -D DFF_MODE |  | ||||||
| techmap -map +/xilinx/abc9_unmap.v |  | ||||||
| select -assert-count 1 t:FDPE |  | ||||||
| techmap -autoproc -map +/xilinx/cells_sim.v |  | ||||||
| design -stash gate |  | ||||||
| 
 |  | ||||||
| design -import gold -as gold |  | ||||||
| design -import gate -as gate |  | ||||||
| techmap -autoproc -map +/xilinx/cells_sim.v |  | ||||||
| clk2fflogic |  | ||||||
| 
 |  | ||||||
| miter -equiv -flatten -make_assert -make_outputs gold gate miter |  | ||||||
| sat -seq 2 -set-init-zero -verify -prove-asserts -show-ports miter |  | ||||||
							
								
								
									
										3
									
								
								tests/simple_abc9/abc9.box
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tests/simple_abc9/abc9.box
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | MUXF8 1 0 3 1 | ||||||
|  | #I0 I1 S | ||||||
|  | 0 0 0 # O | ||||||
|  | @ -213,7 +213,7 @@ module arbiter (clk, rst, request, acknowledge, grant, grant_valid, grant_encode | ||||||
|   input rst; |   input rst; | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| (* abc9_box, blackbox *) | (* abc9_box_id=1, blackbox *) | ||||||
| module MUXF8(input I0, I1, S, output O); | module MUXF8(input I0, I1, S, output O); | ||||||
| specify | specify | ||||||
|     (I0 => O) = 0; |     (I0 => O) = 0; | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-n 300 -p | ||||||
|     synth -run coarse; \ |     synth -run coarse; \ | ||||||
|     opt -full; \ |     opt -full; \ | ||||||
|     techmap; \ |     techmap; \ | ||||||
|     abc9 -lut 4; \ |     abc9 -lut 4 -box ../abc9.box; \ | ||||||
|     clean; \ |     clean; \ | ||||||
|     check -assert; \ |     check -assert; \ | ||||||
|     select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ |     select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ | ||||||
|  |  | ||||||
|  | @ -45,14 +45,16 @@ sat -seq 10 -verify -prove-asserts -show-ports miter | ||||||
| design -reset | design -reset | ||||||
| read_verilog -icells <<EOT | read_verilog -icells <<EOT | ||||||
| module abc9_test036(input clk, d, output q); | module abc9_test036(input clk, d, output q); | ||||||
| (* keep *) reg w; | (* keep, init=1'b0 *) wire w; | ||||||
| $__ABC9_FF_ ff(.D(d), .Q(w)); | $_DFF_P_ ff(.C(clk), .D(d), .Q(w)); | ||||||
| wire \ff.clock = clk; |  | ||||||
| wire \ff.init = 1'b0; |  | ||||||
| assign q = w; | assign q = w; | ||||||
| endmodule | endmodule | ||||||
| EOT | EOT | ||||||
| abc9 -lut 4 -dff | equiv_opt -assert abc9 -lut 4 -dff | ||||||
|  | design -load postopt | ||||||
|  | cd abc9_test036 | ||||||
|  | select -assert-count 1 t:$_DFF_P_ | ||||||
|  | select -assert-none t:* t:$_DFF_P_ %d | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| design -reset | design -reset | ||||||
|  | @ -67,8 +69,32 @@ specify | ||||||
| endspecify | endspecify | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
| module top(input [1:0] i, output o); | module abc9_test037(input [1:0] i, output o); | ||||||
| LUT2 #(.mask(4'b0)) lut (.i(i), .o(o)); | LUT2 #(.mask(4'b0)) lut (.i(i), .o(o)); | ||||||
| endmodule | endmodule | ||||||
| EOT | EOT | ||||||
| abc9 | abc9 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | design -reset | ||||||
|  | read_verilog -icells <<EOT | ||||||
|  | module abc9_test038(input clk, output w, x, y, z); | ||||||
|  | (* init=1'b1 *) wire w; | ||||||
|  | $_DFF_N_ ff1(.C(clk), .D(1'b1), .Q(w)); | ||||||
|  | (* init=1'bx *) wire x; | ||||||
|  | $_DFF_N_ ff2(.C(clk), .D(1'b0), .Q(x)); | ||||||
|  | (* init=1'b0 *) wire y; | ||||||
|  | $_DFF_N_ ff3(.C(clk), .D(1'b0), .Q(y)); | ||||||
|  | (* init=1'b0 *) wire z; | ||||||
|  | $_DFF_N_ ff4(.C(clk), .D(1'b1), .Q(z)); | ||||||
|  | endmodule | ||||||
|  | EOT | ||||||
|  | simplemap | ||||||
|  | equiv_opt abc9 -lut 4 -dff | ||||||
|  | design -load postopt | ||||||
|  | cd abc9_test038 | ||||||
|  | select -assert-count 3 t:$_DFF_N_ | ||||||
|  | select -assert-none c:ff1 c:ff2 c:ff4 %% c:* %D | ||||||
|  | clean | ||||||
|  | select -assert-count 2 a:init | ||||||
|  | select -assert-none w:w w:z %% a:init %D | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue