mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +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 | ||||
| { | ||||
| 	Design *design; | ||||
| 	Module *module; | ||||
| 	SigMap sigmap; | ||||
| 
 | ||||
| 	dict<SigBit, State> init_map; | ||||
| 	pool<SigBit> input_bits, output_bits; | ||||
| 	dict<SigBit, SigBit> not_map, alias_map; | ||||
| 	dict<SigBit, pair<SigBit, SigBit>> and_map; | ||||
|  | @ -137,7 +139,7 @@ struct XAigerWriter | |||
| 		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> unused_bits; | ||||
|  | @ -157,7 +159,8 @@ struct XAigerWriter | |||
| 			if (wire->get_bool_attribute(ID::keep)) | ||||
| 				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++) | ||||
| 			{ | ||||
| 				SigBit wirebit(wire, i); | ||||
|  | @ -174,17 +177,27 @@ struct XAigerWriter | |||
| 				undriven_bits.insert(bit); | ||||
| 				unused_bits.insert(bit); | ||||
| 
 | ||||
| 				bool scc = wire->attributes.count(ID::abc9_scc); | ||||
| 				if (wire->port_input || scc) | ||||
| 				bool keep = wire->get_bool_attribute(ID::abc9_keep); | ||||
| 				if (wire->port_input || keep) | ||||
| 					input_bits.insert(bit); | ||||
| 
 | ||||
| 				bool keep = wire->get_bool_attribute(ID::keep); | ||||
| 				if (wire->port_output || keep || scc) { | ||||
| 				keep = keep || wire->get_bool_attribute(ID::keep); | ||||
| 				if (wire->port_output || keep) { | ||||
| 					if (bit != wirebit) | ||||
| 						alias_map[wirebit] = bit; | ||||
| 					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; | ||||
| 
 | ||||
|  | @ -212,10 +225,7 @@ struct XAigerWriter | |||
| 					continue; | ||||
| 				} | ||||
| 
 | ||||
| 				if (cell->type == ID($__ABC9_FF_) && | ||||
| 						// The presence of an abc9_mergeability attribute indicates
 | ||||
| 						//   that we do want to pass this flop to ABC
 | ||||
| 						cell->attributes.count(ID::abc9_mergeability)) | ||||
| 				if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) | ||||
| 				{ | ||||
| 					SigBit D = sigmap(cell->getPort(ID::D).as_bit()); | ||||
| 					SigBit Q = sigmap(cell->getPort(ID::Q).as_bit()); | ||||
|  | @ -231,31 +241,35 @@ struct XAigerWriter | |||
| 					continue; | ||||
| 			} | ||||
| 
 | ||||
| 			RTLIL::Module* inst_module = module->design->module(cell->type); | ||||
| 			if (inst_module) { | ||||
| 				IdString derived_type = inst_module->derive(module->design, cell->parameters); | ||||
| 				inst_module = module->design->module(derived_type); | ||||
| 				log_assert(inst_module); | ||||
| 
 | ||||
| 			RTLIL::Module* inst_module = design->module(cell->type); | ||||
| 			if (inst_module && inst_module->get_blackbox_attribute()) { | ||||
| 				bool abc9_flop = false; | ||||
| 				if (!cell->has_keep_attr()) { | ||||
| 					auto it = cell->attributes.find(ID::abc9_box_seq); | ||||
| 					if (it != cell->attributes.end()) { | ||||
| 						int abc9_box_seq = it->second.as_int(); | ||||
| 						if (GetSize(box_list) <= abc9_box_seq) | ||||
| 							box_list.resize(abc9_box_seq+1); | ||||
| 						box_list[abc9_box_seq] = cell; | ||||
| 						// Only flop boxes may have arrival times
 | ||||
| 						//   (all others are combinatorial)
 | ||||
| 						abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop); | ||||
| 						if (!abc9_flop) | ||||
| 							continue; | ||||
| 					} | ||||
| 
 | ||||
| 				auto it = cell->attributes.find(ID::abc9_box_seq); | ||||
| 				if (it != cell->attributes.end()) { | ||||
| 					log_assert(!cell->has_keep_attr()); | ||||
| 					int abc9_box_seq = it->second.as_int(); | ||||
| 					if (GetSize(box_list) <= abc9_box_seq) | ||||
| 						box_list.resize(abc9_box_seq+1); | ||||
| 					box_list[abc9_box_seq] = cell; | ||||
| 					// Only flop boxes may have arrival times
 | ||||
| 					//   (all others are combinatorial)
 | ||||
| 					log_assert(cell->parameters.empty()); | ||||
| 					abc9_flop = inst_module->get_bool_attribute(ID::abc9_flop); | ||||
| 					if (!abc9_flop) | ||||
| 						continue; | ||||
| 				} | ||||
| 
 | ||||
| 				if (!timing.count(derived_type)) | ||||
| 				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(inst_module->name)) | ||||
| 					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()) { | ||||
| 					auto port_wire = inst_module->wire(conn.first); | ||||
| 					if (!port_wire->port_output) | ||||
|  | @ -269,7 +283,7 @@ struct XAigerWriter | |||
| #ifndef NDEBUG | ||||
| 						if (ys_debug(1)) { | ||||
| 							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); | ||||
| 						} | ||||
| #endif | ||||
|  | @ -280,10 +294,6 @@ struct XAigerWriter | |||
| 				if (abc9_flop) | ||||
| 					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(); | ||||
| 			for (const auto &c : cell->connections()) { | ||||
|  | @ -317,9 +327,9 @@ struct XAigerWriter | |||
| 		for (auto cell : box_list) { | ||||
| 			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->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); | ||||
| 			if (r.second) { | ||||
|  | @ -383,27 +393,6 @@ struct XAigerWriter | |||
| 						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) | ||||
|  | @ -419,16 +408,14 @@ struct XAigerWriter | |||
| 			undriven_bits.erase(bit); | ||||
| 		} | ||||
| 
 | ||||
| 		if (holes_mode) { | ||||
| 			struct sort_by_port_id { | ||||
| 				bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { | ||||
| 					return a.wire->port_id < b.wire->port_id || | ||||
| 					    (a.wire->port_id == b.wire->port_id && a.offset < b.offset); | ||||
| 				} | ||||
| 			}; | ||||
| 			input_bits.sort(sort_by_port_id()); | ||||
| 			output_bits.sort(sort_by_port_id()); | ||||
| 		} | ||||
| 		struct sort_by_port_id { | ||||
| 			bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const { | ||||
| 				return a.wire->port_id < b.wire->port_id || | ||||
| 				    (a.wire->port_id == b.wire->port_id && a.offset < b.offset); | ||||
| 			} | ||||
| 		}; | ||||
| 		input_bits.sort(sort_by_port_id()); | ||||
| 		output_bits.sort(sort_by_port_id()); | ||||
| 
 | ||||
| 		aig_map[State::S0] = 0; | ||||
| 		aig_map[State::S1] = 1; | ||||
|  | @ -589,17 +576,14 @@ struct XAigerWriter | |||
| 			int box_count = 0; | ||||
| 			for (auto cell : box_list) { | ||||
| 				log_assert(cell); | ||||
| 				log_assert(cell->parameters.empty()); | ||||
| 
 | ||||
| 				RTLIL::Module* box_module = module->design->module(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 r = cell_cache.insert(cell->type); | ||||
| 				auto &v = r.first->second; | ||||
| 				if (r.second) { | ||||
| 					RTLIL::Module* box_module = design->module(cell->type); | ||||
| 					log_assert(box_module); | ||||
| 
 | ||||
| 					int box_inputs = 0, box_outputs = 0; | ||||
| 					for (auto port_name : box_module->ports) { | ||||
| 						RTLIL::Wire *w = box_module->wire(port_name); | ||||
|  | @ -610,11 +594,6 @@ struct XAigerWriter | |||
| 							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<1>(v) = box_outputs; | ||||
| 					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); | ||||
| 			write_s_buffer(ff_bits.size()); | ||||
| 
 | ||||
| 			dict<SigSpec, int> clk_to_mergeability; | ||||
| 			for (const auto &i : ff_bits) { | ||||
| 				const SigBit &d = i.first; | ||||
| 				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); | ||||
| 				write_r_buffer(mergeability); | ||||
| 
 | ||||
| 				Const init = cell->attributes.at(ID::abc9_init, State::Sx); | ||||
| 				log_assert(GetSize(init) == 1); | ||||
| 				SigBit Q = sigmap(cell->getPort(ID::Q)); | ||||
| 				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) | ||||
| 					write_s_buffer(1); | ||||
| 				else if (init == State::S0) | ||||
| 					write_s_buffer(0); | ||||
| 				else { | ||||
| 					log_assert(init == State::Sx); | ||||
| 					write_s_buffer(0); | ||||
| 					write_s_buffer(2); | ||||
| 				} | ||||
| 
 | ||||
| 				// 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(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) { | ||||
| 				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*/); | ||||
| 
 | ||||
| 				f << "a"; | ||||
|  | @ -704,10 +693,10 @@ struct XAigerWriter | |||
| 
 | ||||
| 		f << stringf("Generated by %s\n", yosys_version_str); | ||||
| 
 | ||||
| 		module->design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); | ||||
| 		module->design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); | ||||
| 		module->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_ands", and_map.size()); | ||||
| 		design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); | ||||
| 		design->scratchpad_set_int("write_xaiger.num_inputs", input_bits.size()); | ||||
| 		design->scratchpad_set_int("write_xaiger.num_outputs", output_bits.size()); | ||||
| 	} | ||||
| 
 | ||||
| 	void write_map(std::ostream &f) | ||||
|  | @ -761,10 +750,10 @@ struct XAigerBackend : public Backend { | |||
| 		log("    write_xaiger [options] [filename]\n"); | ||||
| 		log("\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("non (* abc9_box_id *) cells will be converted into psuedo-inputs and\n"); | ||||
| 		log("pseudo-outputs. Whitebox contents will be taken from the '<module-name>$holes'\n"); | ||||
| 		log("module, if it exists.\n"); | ||||
| 		log("is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, (optionally\n"); | ||||
| 		log("$_DFF_N_, $_DFF_P_), or non (* abc9_box *) cells will be converted into psuedo-\n"); | ||||
| 		log("inputs and pseudo-outputs. Whitebox contents will be taken from the equivalent\n"); | ||||
| 		log("module in the '$abc9_holes' design, if it exists.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -ascii\n"); | ||||
| 		log("        write ASCII version of AIGER format\n"); | ||||
|  | @ -772,10 +761,13 @@ struct XAigerBackend : public Backend { | |||
| 		log("    -map <filename>\n"); | ||||
| 		log("        write an extra file with port and box symbols\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 | ||||
| 	{ | ||||
| 		bool ascii_mode = false; | ||||
| 		bool ascii_mode = false, dff_mode = false; | ||||
| 		std::string map_filename; | ||||
| 
 | ||||
| 		log_header(design, "Executing XAIGER backend.\n"); | ||||
|  | @ -791,6 +783,10 @@ struct XAigerBackend : public Backend { | |||
| 				map_filename = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-dff") { | ||||
| 				dff_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(f, filename, args, argidx, !ascii_mode); | ||||
|  | @ -808,7 +804,7 @@ struct XAigerBackend : public Backend { | |||
| 		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)); | ||||
| 
 | ||||
| 		XAigerWriter writer(top_module); | ||||
| 		XAigerWriter writer(top_module, dff_mode); | ||||
| 		writer.write_aiger(*f, ascii_mode); | ||||
| 
 | ||||
| 		if (!map_filename.empty()) { | ||||
|  |  | |||
|  | @ -454,6 +454,14 @@ void AigerReader::parse_xaiger() | |||
| 			for (unsigned i = 0; i < flopNum; i++) | ||||
| 				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') { | ||||
| 			parse_xaiger_literal(f); | ||||
| 			f >> s; | ||||
|  | @ -767,6 +775,7 @@ void AigerReader::post_process() | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	dict<int, Wire*> mergeability_to_clock; | ||||
| 	for (uint32_t i = 0; i < flopNum; i++) { | ||||
| 		RTLIL::Wire *d = outputs[outputs.size() - flopNum + i]; | ||||
| 		log_assert(d); | ||||
|  | @ -778,10 +787,9 @@ void AigerReader::post_process() | |||
| 		log_assert(q->port_input); | ||||
| 		q->port_input = false; | ||||
| 
 | ||||
| 		auto ff = module->addCell(NEW_ID, ID($__ABC9_FF_)); | ||||
| 		ff->setPort(ID::D, d); | ||||
| 		ff->setPort(ID::Q, q); | ||||
| 		Cell* ff = module->addFfGate(NEW_ID, d, q); | ||||
| 		ff->attributes[ID::abc9_mergeability] = mergeability[i]; | ||||
| 		q->attributes[ID::init] = initial_state[i]; | ||||
| 	} | ||||
| 
 | ||||
| 	dict<RTLIL::IdString, std::pair<int,int>> wideports_cache; | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ struct AigerReader | |||
|     std::vector<RTLIL::Wire*> outputs; | ||||
|     std::vector<RTLIL::Wire*> bad_properties; | ||||
|     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); | ||||
|     void parse_aiger(); | ||||
|  |  | |||
|  | @ -2,13 +2,12 @@ X(A) | |||
| X(abc9_box) | ||||
| X(abc9_box_id) | ||||
| X(abc9_box_seq) | ||||
| X(abc9_bypass) | ||||
| X(abc9_carry) | ||||
| X(abc9_flop) | ||||
| X(abc9_holes) | ||||
| X(abc9_init) | ||||
| X(abc9_keep) | ||||
| X(abc9_lut) | ||||
| X(abc9_mergeability) | ||||
| X(abc9_scc) | ||||
| X(abc9_scc_id) | ||||
| X(abcgroup) | ||||
| X(ABITS) | ||||
|  |  | |||
|  | @ -82,6 +82,9 @@ struct TimingInfo | |||
| 
 | ||||
| 		for (auto cell : module->cells()) { | ||||
| 			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 dst = cell->getPort(ID::DST); | ||||
| 				for (const auto &c : src.chunks()) | ||||
|  | @ -128,11 +131,9 @@ struct TimingInfo | |||
| 				int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); | ||||
| 				int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); | ||||
| 				int max = std::max(rise_max,fall_max); | ||||
| 				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)); | ||||
| 				if (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; | ||||
| 				if (max < 0) { | ||||
| 					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)); | ||||
| 					max = 0; | ||||
| 				} | ||||
| 				for (const auto &d : dst) { | ||||
| 					auto &v = t.arrival[NameBit(d)]; | ||||
|  | @ -152,11 +153,9 @@ struct TimingInfo | |||
| 					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)); | ||||
| 				int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); | ||||
| 				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)); | ||||
| 				if (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; | ||||
| 				if (max < 0) { | ||||
| 					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)); | ||||
| 					max = 0; | ||||
| 				} | ||||
| 				for (const auto &s : src) { | ||||
| 					auto &v = t.required[NameBit(s)]; | ||||
|  |  | |||
|  | @ -151,8 +151,8 @@ struct Abc9Pass : public ScriptPass | |||
| 		log("        specified).\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -dff\n"); | ||||
| 		log("        also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n"); | ||||
| 		log("        domains are marked as such and automatically partitioned by ABC.\n"); | ||||
| 		log("        also pass $_DFF_[NP]_ cells through to ABC. modules with many clock\n"); | ||||
| 		log("        domains are supported and automatically partitioned by ABC.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nocleanup\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 | ||||
| 	{ | ||||
| 		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")) { | ||||
| 			run("abc9_ops -check"); | ||||
| 			run("read_verilog -icells -lib -specify +/abc9_model.v"); | ||||
| 			run("scc -set_attr abc9_scc_id {}"); | ||||
| 			if (help_mode) | ||||
| 				run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); | ||||
| 			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) | ||||
| 				run("abc9_ops -prep_lut <maxlut>", "(skip if -lut or -luts)"); | ||||
| 			else if (!lut_mode) | ||||
| 				run(stringf("abc9_ops -prep_lut %d", maxlut)); | ||||
| 			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()) | ||||
| 				run(stringf("abc9_ops -prep_box %s", dff_mode ? "-dff" : "")); | ||||
| 			run("select -set abc9_holes A:abc9_holes"); | ||||
| 			run("flatten -wb @abc9_holes"); | ||||
| 			run("techmap @abc9_holes"); | ||||
| 			if (dff_mode || help_mode) | ||||
| 				run("abc9_ops -prep_dff", "(only if -dff)"); | ||||
| 			run("opt -purge @abc9_holes"); | ||||
| 			run("aigmap"); | ||||
| 			run("wbflip @abc9_holes"); | ||||
| 				run("abc9_ops -prep_box"); | ||||
| 			if (saved_designs.count("$abc9_holes") || help_mode) { | ||||
| 				run("design -stash $abc9"); | ||||
| 				run("design -load $abc9_holes"); | ||||
| 				run("techmap -wb -map %$abc9 -map +/techmap.v"); | ||||
| 				run("opt -purge"); | ||||
| 				run("aigmap"); | ||||
| 				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) { | ||||
| 				run("foreach module in selection"); | ||||
| 				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("    write_xaiger -map <abc-temp-dir>/input.sym <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_ops -write_box <abc-temp-dir>/input.box", "(skip if '-box')"); | ||||
| 				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("    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 { | ||||
| 				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)); | ||||
| 						continue; | ||||
| 					} | ||||
| 					log_assert(!mod->attributes.count(ID::abc9_box_id)); | ||||
| 
 | ||||
| 					log_push(); | ||||
| 					active_design->selection().select(mod); | ||||
|  | @ -333,8 +398,9 @@ struct Abc9Pass : public ScriptPass | |||
| 
 | ||||
| 					if (!lut_mode) | ||||
| 						run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", 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())); | ||||
| 					if (box_file.empty()) | ||||
| 						run_nocheck(stringf("abc9_ops -write_box %s/input.box", 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"); | ||||
| 
 | ||||
|  | @ -349,10 +415,13 @@ struct Abc9Pass : public ScriptPass | |||
| 						abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str()); | ||||
| 						if (!lut_mode) | ||||
| 							abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str()); | ||||
| 						abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); | ||||
| 						if (box_file.empty()) | ||||
| 							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(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 | ||||
| 						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(); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		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; | ||||
| 
 | ||||
|  |  | |||
										
											
												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/mul2dsp.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)) | ||||
|  |  | |||
							
								
								
									
										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 *) | ||||
| module \$__ABC9_DELAY (input I, output O); | ||||
| module $__ABC9_DELAY (input I, output O); | ||||
|   parameter DELAY = 0; | ||||
|   specify | ||||
|     (I => O) = DELAY; | ||||
|   endspecify | ||||
| 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/latches_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)) | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
| // --------------------------------------- | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module TRELLIS_DPR16X4 ( | ||||
| 	input  [3:0] DI, | ||||
| 	input  [3:0] WAD, | ||||
|  | @ -222,10 +223,16 @@ module TRELLIS_DPR16X4 ( | |||
| 			mem[WAD] <= DI; | ||||
| 
 | ||||
| 	assign DO = mem[RAD]; | ||||
| 
 | ||||
| 	specify | ||||
| 		// TODO | ||||
| 		(RAD *> DO) = 0; | ||||
| 	endspecify | ||||
| endmodule | ||||
| 
 | ||||
| // --------------------------------------- | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module DPR16X4C ( | ||||
| 		input [3:0] DI, | ||||
| 		input WCK, WRE, | ||||
|  | @ -281,6 +288,10 @@ module DPR16X4C ( | |||
| 
 | ||||
| 	assign DO = ram[RAD]; | ||||
| 
 | ||||
| 	specify | ||||
| 		// TODO | ||||
| 		(RAD *> DO) = 0; | ||||
| 	endspecify | ||||
| 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); | ||||
| 	parameter GSR = "ENABLED"; | ||||
| 	parameter [127:0] CEMUX = "1"; | ||||
|  | @ -340,6 +354,38 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q); | |||
| 					Q <= DI; | ||||
| 		end | ||||
| 	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 | ||||
| 
 | ||||
| // --------------------------------------- | ||||
|  |  | |||
|  | @ -66,6 +66,9 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 		log("    -noflatten\n"); | ||||
| 		log("        do not flatten design before synthesis\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -dff\n"); | ||||
| 		log("        run 'abc'/'abc9' with -dff option\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -retime\n"); | ||||
| 		log("        run 'abc' with '-dff -D 1' options\n"); | ||||
| 		log("\n"); | ||||
|  | @ -107,7 +110,7 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 	} | ||||
| 
 | ||||
| 	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 | ||||
| 	{ | ||||
|  | @ -122,6 +125,7 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 		nowidelut = false; | ||||
| 		asyncprld = false; | ||||
| 		flatten = true; | ||||
| 		dff = false; | ||||
| 		retime = false; | ||||
| 		abc2 = false; | ||||
| 		vpr = false; | ||||
|  | @ -169,6 +173,10 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 				flatten = false; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-dff") { | ||||
| 				dff = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-retime") { | ||||
| 				retime = true; | ||||
| 				continue; | ||||
|  | @ -307,6 +315,8 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 			run("opt_clean"); | ||||
| 			if (!nodffe) | ||||
| 				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("opt_expr -undriven -mux_undef"); | ||||
| 			run("simplemap"); | ||||
|  | @ -318,17 +328,13 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 
 | ||||
| 		if (check_label("map_luts")) | ||||
| 		{ | ||||
| 			if (abc2 || help_mode) { | ||||
| 			if (abc2 || help_mode) | ||||
| 				run("abc", "      (only if -abc2)"); | ||||
| 			} | ||||
| 			std::string techmap_args = asyncprld ? "" : "-map +/ecp5/latches_map.v"; | ||||
| 			if (abc9) | ||||
| 				techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1"; | ||||
| 			if (!asyncprld || abc9) | ||||
| 				run("techmap " + techmap_args); | ||||
| 			if (!asyncprld || help_mode) | ||||
| 				run("techmap -map +/ecp5/latches_map.v", "(skip if -asyncprld)"); | ||||
| 
 | ||||
| 			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; | ||||
| 				if (nowidelut) | ||||
| 					abc9_opts += " -maxlut 4"; | ||||
|  | @ -338,26 +344,29 @@ struct SynthEcp5Pass : public ScriptPass | |||
| 				else | ||||
| 					abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); | ||||
| 				if (nowidelut) | ||||
| 					run("abc9 -maxlut 4 -W 200"); | ||||
| 				else | ||||
| 					run("abc9 -W 200"); | ||||
| 				run("techmap -map +/ecp5/abc9_unmap.v"); | ||||
| 					abc9_opts += " -maxlut 4"; | ||||
| 				if (dff) | ||||
| 					abc9_opts += " -dff"; | ||||
| 				run("abc9" + abc9_opts); | ||||
| 			} else { | ||||
| 				std::string abc_args = " -dress"; | ||||
| 				if (nowidelut) | ||||
| 					run("abc -lut 4 -dress"); | ||||
| 					abc_args += " -lut 4"; | ||||
| 				else | ||||
| 					run("abc -lut 4:7 -dress"); | ||||
| 					abc_args += " -lut 4:7"; | ||||
| 				if (dff) | ||||
| 					abc_args += " -dff"; | ||||
| 				run("abc" + abc_args); | ||||
| 			} | ||||
| 			run("clean"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_cells")) | ||||
| 		{ | ||||
| 			if (vpr) | ||||
| 				run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); | ||||
| 			else | ||||
| 				run("techmap -map +/ecp5/cells_map.v", "(with -D NO_LUT in vpr mode)"); | ||||
| 
 | ||||
| 			if (help_mode) | ||||
| 				run("techmap -map +/ecp5/cells_map.v", "(skip if -vpr)"); | ||||
| 			else if (!vpr) | ||||
| 				run("techmap -map +/ecp5/cells_map.v"); | ||||
| 			run("opt_lut_ins -tech ecp5"); | ||||
| 			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/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/latches_map.v)) | ||||
| $(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); | ||||
|   parameter WIDTH = 0; | ||||
|   parameter LUT = 0; | ||||
|  | @ -59,4 +29,3 @@ module \$lut (A, Y); | |||
|     end | ||||
|   endgenerate | ||||
| endmodule | ||||
| `endif | ||||
|  |  | |||
|  | @ -245,6 +245,7 @@ endmodule | |||
| 
 | ||||
| // Positive Edge SiliconBlue FF Cells | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFF ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, D | ||||
|  | @ -280,6 +281,7 @@ module SB_DFF ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFE ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, D | ||||
|  | @ -322,6 +324,7 @@ module SB_DFFE ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFSR ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, R, D | ||||
|  | @ -369,6 +372,7 @@ module SB_DFFSR ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SB_DFFR ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, R, D | ||||
|  | @ -386,7 +390,13 @@ module SB_DFFR ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||
| 		$setup(negedge R, posedge C, 160); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!R) (posedge C => (Q : D)) = 540; | ||||
| 	endspecify | ||||
|  | @ -399,7 +409,13 @@ module SB_DFFR ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||
| 		$setup(negedge R, posedge C, 235); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!R) (posedge C => (Q : D)) = 796; | ||||
| 	endspecify | ||||
|  | @ -412,13 +428,20 @@ module SB_DFFR ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||
| 		$setup(negedge R, posedge C, 424); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!R) (posedge C => (Q : D)) = 1391; | ||||
| 	endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFSS ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, S, D | ||||
|  | @ -466,6 +489,7 @@ module SB_DFFSS ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SB_DFFS ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, S, D | ||||
|  | @ -483,7 +507,13 @@ module SB_DFFS ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||
| 		$setup(negedge S, posedge C, 160); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!S) (posedge C => (Q : D)) = 540; | ||||
| 	endspecify | ||||
|  | @ -496,7 +526,13 @@ module SB_DFFS ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||
| 		$setup(negedge S, posedge C, 235); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!S) (posedge C => (Q : D)) = 796; | ||||
| 	endspecify | ||||
|  | @ -509,13 +545,20 @@ module SB_DFFS ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||
| 		$setup(negedge S, posedge C, 424); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!S) (posedge C => (Q : D)) = 1391; | ||||
| 	endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFESR ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, R, D | ||||
|  | @ -571,6 +614,7 @@ module SB_DFFESR ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SB_DFFER ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, R, D | ||||
|  | @ -590,7 +634,13 @@ module SB_DFFER ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||
| 		$setup(negedge R, posedge C, 160); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !R) (posedge C => (Q : D)) = 540; | ||||
| 	endspecify | ||||
|  | @ -605,7 +655,13 @@ module SB_DFFER ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||
| 		$setup(negedge R, posedge C, 235); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !R) (posedge C => (Q : D)) = 796; | ||||
| 	endspecify | ||||
|  | @ -620,13 +676,20 @@ module SB_DFFER ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||
| 		$setup(negedge R, posedge C, 424); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !R) (posedge C => (Q : D)) = 1391; | ||||
| 	endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFESS ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, S, D | ||||
|  | @ -682,6 +745,7 @@ module SB_DFFESS ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SB_DFFES ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, S, D | ||||
|  | @ -701,7 +765,13 @@ module SB_DFFES ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||
| 		$setup(posedge S, posedge C, 160); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !S) (posedge C => (Q : D)) = 540; | ||||
| 	endspecify | ||||
|  | @ -716,7 +786,13 @@ module SB_DFFES ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||
| 		$setup(posedge S, posedge C, 235); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !S) (posedge C => (Q : D)) = 796; | ||||
| 	endspecify | ||||
|  | @ -731,7 +807,13 @@ module SB_DFFES ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||
| 		$setup(posedge S, posedge C, 424); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !S) (posedge C => (Q : D)) = 1391; | ||||
| 	endspecify | ||||
|  | @ -740,6 +822,7 @@ endmodule | |||
| 
 | ||||
| // Negative Edge SiliconBlue FF Cells | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFN ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, D | ||||
|  | @ -775,6 +858,7 @@ module SB_DFFN ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFNE ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, D | ||||
|  | @ -817,6 +901,7 @@ module SB_DFFNE ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFNSR ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, R, D | ||||
|  | @ -864,6 +949,7 @@ module SB_DFFNSR ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFNR ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, R, D | ||||
|  | @ -881,7 +967,13 @@ module SB_DFFNR ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||
| 		$setup(negedge R, negedge C, 160); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!R) (negedge C => (Q : D)) = 540; | ||||
| 	endspecify | ||||
|  | @ -894,7 +986,13 @@ module SB_DFFNR ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||
| 		$setup(negedge R, negedge C, 235); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!R) (negedge C => (Q : D)) = 796; | ||||
| 	endspecify | ||||
|  | @ -907,13 +1005,20 @@ module SB_DFFNR ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||
| 		$setup(negedge R, negedge C, 424); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!R) (negedge C => (Q : D)) = 1391; | ||||
| 	endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFNSS ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, S, D | ||||
|  | @ -961,6 +1066,7 @@ module SB_DFFNSS ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SB_DFFNS ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, S, D | ||||
|  | @ -978,7 +1084,13 @@ module SB_DFFNS ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||
| 		$setup(negedge S, negedge C, 160); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!S) (negedge C => (Q : D)) = 540; | ||||
| 	endspecify | ||||
|  | @ -991,7 +1103,13 @@ module SB_DFFNS ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||
| 		$setup(negedge S, negedge C, 235); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!S) (negedge C => (Q : D)) = 796; | ||||
| 	endspecify | ||||
|  | @ -1004,13 +1122,20 @@ module SB_DFFNS ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||
| 		$setup(negedge S, negedge C, 424); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (!S) (negedge C => (Q : D)) = 1391; | ||||
| 	endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFNESR ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, R, D | ||||
|  | @ -1066,6 +1191,7 @@ module SB_DFFNESR ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SB_DFFNER ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, R, D | ||||
|  | @ -1085,7 +1211,13 @@ module SB_DFFNER ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||
| 		$setup(R, negedge C, 2160); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !R) (negedge C => (Q : D)) = 540; | ||||
| 	endspecify | ||||
|  | @ -1100,7 +1232,13 @@ module SB_DFFNER ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||
| 		$setup(R, negedge C, 235); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !R) (negedge C => (Q : D)) = 796; | ||||
| 	endspecify | ||||
|  | @ -1115,13 +1253,20 @@ module SB_DFFNER ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||
| 		$setup(negedge R, negedge C, 424); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !R) (negedge C => (Q : D)) = 1391; | ||||
| 	endspecify | ||||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| module SB_DFFNESS ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, S, D | ||||
|  | @ -1177,6 +1322,7 @@ module SB_DFFNESS ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SB_DFFNES ( | ||||
| 	output `SB_DFF_REG, | ||||
| 	input C, E, S, D | ||||
|  | @ -1196,7 +1342,14 @@ module SB_DFFNES ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63 | ||||
| 		$setup(negedge S, negedge C, 160); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !S) (negedge C => (Q : D)) = 540; | ||||
| 	endspecify | ||||
|  | @ -1211,7 +1364,13 @@ module SB_DFFNES ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63 | ||||
| 		$setup(negedge S, negedge C, 235); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !S) (negedge C => (Q : D)) = 796; | ||||
| 	endspecify | ||||
|  | @ -1226,7 +1385,13 @@ module SB_DFFNES ( | |||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75 | ||||
| 		$setup(negedge S, negedge C, 424); | ||||
| 		// https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103 | ||||
| `ifndef YOSYS | ||||
| 		(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 | ||||
| 		if (E && !S) (negedge C => (Q : D)) = 1391; | ||||
| 	endspecify | ||||
|  | @ -2723,6 +2888,7 @@ module SB_IO_OD ( | |||
| `endif | ||||
| endmodule | ||||
| 
 | ||||
| //(* abc9_box, lib_whitebox *) // TODO | ||||
| module SB_MAC16 ( | ||||
| 	input CLK, CE, | ||||
| 	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("        do not flatten design before synthesis\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -dff\n"); | ||||
| 		log("        run 'abc'/'abc9' with -dff option\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -retime\n"); | ||||
| 		log("        run 'abc' with '-dff -D 1' options\n"); | ||||
| 		log("\n"); | ||||
|  | @ -113,7 +116,7 @@ struct SynthIce40Pass : public ScriptPass | |||
| 	} | ||||
| 
 | ||||
| 	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; | ||||
| 
 | ||||
| 	void clear_flags() YS_OVERRIDE | ||||
|  | @ -221,6 +224,10 @@ struct SynthIce40Pass : public ScriptPass | |||
| 				abc9 = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-dff") { | ||||
| 				dff = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-device" && argidx+1 < args.size()) { | ||||
| 				device_opt = args[++argidx]; | ||||
| 				continue; | ||||
|  | @ -354,7 +361,9 @@ struct SynthIce40Pass : public ScriptPass | |||
| 				run(stringf("dff2dffe -unmap-mince %d", min_ce_use)); | ||||
| 				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("simplemap"); | ||||
| 			run("ice40_ffinit"); | ||||
|  | @ -378,7 +387,7 @@ struct SynthIce40Pass : public ScriptPass | |||
| 			} | ||||
| 			if (!noabc) { | ||||
| 				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 k = "synth_ice40.abc9.W"; | ||||
| 					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()); | ||||
| 						abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); | ||||
| 					} | ||||
| 					if (dff) | ||||
| 						abc9_opts += " -dff"; | ||||
| 					run("abc9 " + abc9_opts); | ||||
| 				} | ||||
| 				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("techmap -D NO_LUT -map +/ice40/cells_map.v"); | ||||
| 			run("techmap -map +/ice40/ff_map.v"); | ||||
| 			run("clean"); | ||||
| 			run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_cells")) | ||||
| 		{ | ||||
| 			if (vpr) | ||||
| 				run("techmap -D NO_LUT -map +/ice40/cells_map.v"); | ||||
| 			else | ||||
| 				run("techmap -map +/ice40/cells_map.v", "(with -D NO_LUT in vpr mode)"); | ||||
| 
 | ||||
| 			if (help_mode) | ||||
| 				run("techmap -map +/ice40/cells_map.v", "(skip if -vpr)"); | ||||
| 			else if (!vpr) | ||||
| 				run("techmap -map +/ice40/cells_map.v"); | ||||
| 			run("clean"); | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -209,7 +209,6 @@ struct SynthIntelALMPass : public ScriptPass { | |||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_luts")) { | ||||
| 			run("read_verilog -icells -specify -lib +/abc9_model.v"); | ||||
| 			run("abc9 -maxlut 6 -W 200"); | ||||
| 			run("techmap -map +/intel_alm/common/alm_map.v"); | ||||
| 			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/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_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; | ||||
|   endspecify | ||||
| 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 IBUF_LOW_PWR = 0; | ||||
|   assign O = I; | ||||
|   specify | ||||
|     (I => O) = 0; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| module IBUFG( | ||||
|  | @ -57,6 +60,9 @@ module OBUF( | |||
|   parameter DRIVE = 12; | ||||
|   parameter SLEW = "SLOW"; | ||||
|   assign O = I; | ||||
|   specify | ||||
|     (I => O) = 0; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| module IOBUF ( | ||||
|  | @ -72,6 +78,10 @@ module IOBUF ( | |||
|     parameter SLEW = "SLOW"; | ||||
|     assign IO = T ? 1'bz : I; | ||||
|     assign O = IO; | ||||
|     specify | ||||
|         (I => IO) = 0; | ||||
|         (IO => O) = 0; | ||||
|     endspecify | ||||
| endmodule | ||||
| 
 | ||||
| module OBUFT ( | ||||
|  | @ -85,14 +95,20 @@ module OBUFT ( | |||
|     parameter IOSTANDARD = "DEFAULT"; | ||||
|     parameter SLEW = "SLOW"; | ||||
|     assign O = T ? 1'bz : I; | ||||
|     specify | ||||
|         (I => O) = 0; | ||||
|     endspecify | ||||
| endmodule | ||||
| 
 | ||||
| module BUFG( | ||||
|     (* clkbuf_driver *) | ||||
|     output O, | ||||
|     input 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 | ||||
| 
 | ||||
| module BUFGCTRL( | ||||
|  | @ -499,8 +515,8 @@ module FDRE ( | |||
|   endgenerate | ||||
|   specify | ||||
|     // 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 , negedge 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*/ 0); // Negative times not currently supported | ||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||
|     $setup(CE, posedge 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 , negedge C &&&  IS_C_INVERTED, 404); | ||||
|     // 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)        (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) (negedge C => (Q : D ^ IS_D_INVERTED)) = 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 && 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; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -529,7 +545,7 @@ module FDRE_1 ( | |||
|   always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D; | ||||
|   specify | ||||
|     // 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 | ||||
|     $setup(CE, negedge C, 109); | ||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 | ||||
|  | @ -564,8 +580,8 @@ module FDSE ( | |||
|   endgenerate | ||||
|   specify | ||||
|     // 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 , negedge 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*/ 0); // Negative times not currently supported | ||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||
|     $setup(CE, posedge 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 , negedge C &&&  IS_C_INVERTED, 404); | ||||
|     // 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)        (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) (negedge C => (Q : D ^ IS_D_INVERTED)) = 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 && 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; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -594,7 +610,7 @@ module FDSE_1 ( | |||
|   always @(negedge C) if (S) Q <= 1'b1; else if (CE) Q <= D; | ||||
|   specify | ||||
|     // 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 | ||||
|     $setup(CE, negedge C, 109); | ||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 | ||||
|  | @ -640,7 +656,7 @@ module FDRSE ( | |||
|       Q <= d; | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module FDCE ( | ||||
|   output reg Q, | ||||
|   (* clkbuf_sink *) | ||||
|  | @ -667,8 +683,8 @@ module FDCE ( | |||
|   endgenerate | ||||
|   specify | ||||
|     // 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 , negedge 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*/ 0); // Negative times not currently supported | ||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||
|     $setup(CE , posedge 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, negedge C &&&  IS_C_INVERTED, 404); | ||||
|     // 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 | ||||
|     //if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764; // Captured by $__ABC9_ASYNC0 | ||||
|     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; | ||||
| `ifndef YOSYS | ||||
|     if (!IS_CLR_INVERTED) (posedge CLR => (Q : 1'b0)) = 764; | ||||
|     if ( IS_CLR_INVERTED) (negedge CLR => (Q : 1'b0)) = 764; | ||||
| `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 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module FDCE_1 ( | ||||
|   output reg Q, | ||||
|   (* clkbuf_sink *) | ||||
|  | @ -697,18 +719,24 @@ module FDCE_1 ( | |||
|   always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D; | ||||
|   specify | ||||
|     // 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 | ||||
|     $setup(CE , negedge C, 109); | ||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 | ||||
|     $setup(CLR, negedge C, 404); | ||||
|     // 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; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module FDPE ( | ||||
|   output reg Q, | ||||
|   (* clkbuf_sink *) | ||||
|  | @ -734,8 +762,8 @@ module FDPE ( | |||
|   endgenerate | ||||
|   specify | ||||
|     // 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 , negedge 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*/ 0); // Negative times not currently supported | ||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L248 | ||||
|     $setup(CE , posedge 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, negedge C &&&  IS_C_INVERTED, 404); | ||||
|     // 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 | ||||
|     //if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 | ||||
|     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; | ||||
| `ifndef YOSYS | ||||
|     if (!IS_PRE_INVERTED) (posedge PRE => (Q : 1'b1)) = 764; | ||||
|     if ( IS_PRE_INVERTED) (negedge PRE => (Q : 1'b1)) = 764; | ||||
| `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 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_flop, lib_whitebox *) | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module FDPE_1 ( | ||||
|   output reg Q, | ||||
|   (* clkbuf_sink *) | ||||
|  | @ -764,14 +798,19 @@ module FDPE_1 ( | |||
|   always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D; | ||||
|   specify | ||||
|     // 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 | ||||
|     $setup(CE , negedge C, 109); | ||||
|     // https://github.com/SymbiFlow/prjxray-db/blob/23c8b0851f979f0799318eaca90174413a46b257/artix7/timings/slicel.sdf#L274 | ||||
|     $setup(PRE, negedge C, 404); | ||||
|     // 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 | ||||
|     //if (IS_PRE_INVERTED)  (negedge PRE => (Q : 1'b1)) = 764; // Captured by $__ABC9_ASYNC1 | ||||
| `ifndef YOSYS | ||||
|     (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; | ||||
|   endspecify | ||||
| endmodule | ||||
|  | @ -1383,6 +1422,7 @@ module RAM16X1D_1 ( | |||
|   always @(negedge clk) if (WE) mem[a] <= D; | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module RAM32X1D ( | ||||
|   output DPO, SPO, | ||||
|   input  D, | ||||
|  | @ -1429,15 +1469,15 @@ module RAM32X1D ( | |||
|     if (!IS_WCLK_INVERTED) (posedge WCLK => (DPO : 1'bx)) = 1153; | ||||
|     if ( IS_WCLK_INVERTED) (posedge WCLK => (SPO : D))    = 1153; | ||||
|     if ( IS_WCLK_INVERTED) (negedge WCLK => (DPO : 1'bx)) = 1153; | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //({A0,DPRA0} => {SPO,DPO}) = 642; | ||||
|     //({A1,DPRA1} => {SPO,DPO}) = 631; | ||||
|     //({A2,DPRA2} => {SPO,DPO}) = 472; | ||||
|     //({A3,DPRA3} => {SPO,DPO}) = 407; | ||||
|     //({A4,DPRA4} => {SPO,DPO}) = 238; | ||||
|     (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; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module RAM32X1D_1 ( | ||||
|   output DPO, SPO, | ||||
|   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 | ||||
|     if (WE) (negedge WCLK => (SPO : D))    = 1153; | ||||
|     if (WE) (negedge WCLK => (DPO : 1'bx)) = 1153; | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //({A0,DPRA0} => {SPO,DPO}) = 642; | ||||
|     //({A1,DPRA1} => {SPO,DPO}) = 631; | ||||
|     //({A2,DPRA2} => {SPO,DPO}) = 472; | ||||
|     //({A3,DPRA3} => {SPO,DPO}) = 407; | ||||
|     //({A4,DPRA4} => {SPO,DPO}) = 238; | ||||
|     (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; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module RAM64X1D ( | ||||
|   output DPO, SPO, | ||||
|   input  D, | ||||
|  | @ -1537,13 +1577,12 @@ module RAM64X1D ( | |||
|     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 => (DPO : 1'bx)) = 1153; | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //({A0,DPRA0} => {SPO,DPO}) = 642; | ||||
|     //({A1,DPRA1} => {SPO,DPO}) = 631; | ||||
|     //({A2,DPRA2} => {SPO,DPO}) = 472; | ||||
|     //({A3,DPRA3} => {SPO,DPO}) = 407; | ||||
|     //({A4,DPRA4} => {SPO,DPO}) = 238; | ||||
|     //({A5,DPRA5} => {SPO,DPO}) = 127; | ||||
|     (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 | ||||
| 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 | ||||
|     if (WE) (negedge WCLK => (SPO : D))    = 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 | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module RAM128X1D ( | ||||
|   output       DPO, SPO, | ||||
|   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 | ||||
|     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 */; | ||||
|     (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 | ||||
|     // 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 | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -1671,6 +1716,7 @@ endmodule | |||
| 
 | ||||
| // Multi port. | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module RAM32M ( | ||||
|   output [1:0] DOA, | ||||
|   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 | ||||
|     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD[1] : DID[1])) = 1190; | ||||
|     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD[1] : DID[1])) = 1190; | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //({{2{ADDRA[0]}},{2{ADDRB[0]}},{2{ADDRC[0]}},{2{ADDRD[0]}}} => {DOA,DOB,DOC,DOD}) = 642; | ||||
|     //({{2{ADDRA[1]}},{2{ADDRB[1]}},{2{ADDRC[1]}},{2{ADDRD[1]}}} => {DOA,DOB,DOC,DOD}) = 631; | ||||
|     //({{2{ADDRA[2]}},{2{ADDRB[2]}},{2{ADDRC[2]}},{2{ADDRD[2]}}} => {DOA,DOB,DOC,DOD}) = 472; | ||||
|     //({{2{ADDRA[3]}},{2{ADDRB[3]}},{2{ADDRC[3]}},{2{ADDRD[3]}}} => {DOA,DOB,DOC,DOD}) = 407; | ||||
|     //({{2{ADDRA[4]}},{2{ADDRB[4]}},{2{ADDRC[4]}},{2{ADDRD[4]}}} => {DOA,DOB,DOC,DOD}) = 238; | ||||
|     (ADDRA[0] *> DOA) = 642; (ADDRB[0] *> DOB) = 642; (ADDRC[0] *> DOC) = 642; (ADDRD[0] *> DOD) = 642; | ||||
|     (ADDRA[1] *> DOA) = 631; (ADDRB[1] *> DOB) = 631; (ADDRC[1] *> DOC) = 631; (ADDRD[1] *> DOD) = 631; | ||||
|     (ADDRA[2] *> DOA) = 472; (ADDRB[2] *> DOB) = 472; (ADDRC[2] *> DOC) = 472; (ADDRD[2] *> DOD) = 472; | ||||
|     (ADDRA[3] *> DOA) = 407; (ADDRB[3] *> DOB) = 407; (ADDRC[3] *> DOC) = 407; (ADDRD[3] *> DOD) = 407; | ||||
|     (ADDRA[4] *> DOA) = 238; (ADDRB[4] *> DOB) = 238; (ADDRC[4] *> DOC) = 238; (ADDRD[4] *> DOD) = 238; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -1845,6 +1890,7 @@ module RAM32M16 ( | |||
|     end | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module RAM64M ( | ||||
|   output       DOA, | ||||
|   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 | ||||
|     if (!IS_WCLK_INVERTED && WE) (posedge WCLK => (DOD : DID)) = 1163; | ||||
|     if ( IS_WCLK_INVERTED && WE) (negedge WCLK => (DOD : DID)) = 1163; | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //({ADDRA[0],ADDRB[0],ADDRC[0],ADDRD[0]} => {DOA,DOB,DOC,DOD}) = 642; | ||||
|     //({ADDRA[1],ADDRB[1],ADDRC[1],ADDRD[1]} => {DOA,DOB,DOC,DOD}) = 631; | ||||
|     //({ADDRA[2],ADDRB[2],ADDRC[2],ADDRD[2]} => {DOA,DOB,DOC,DOD}) = 472; | ||||
|     //({ADDRA[3],ADDRB[3],ADDRC[3],ADDRD[3]} => {DOA,DOB,DOC,DOD}) = 407; | ||||
|     //({ADDRA[4],ADDRB[4],ADDRC[4],ADDRD[4]} => {DOA,DOB,DOC,DOD}) = 238; | ||||
|     (ADDRA[0] => DOA) = 642; (ADDRB[0] => DOB) = 642; (ADDRC[0] => DOC) = 642; (ADDRD[0] => DOD) = 642; | ||||
|     (ADDRA[1] => DOA) = 631; (ADDRB[1] => DOB) = 631; (ADDRC[1] => DOC) = 631; (ADDRD[1] => DOD) = 631; | ||||
|     (ADDRA[2] => DOA) = 472; (ADDRB[2] => DOB) = 472; (ADDRC[2] => DOC) = 472; (ADDRD[2] => DOD) = 472; | ||||
|     (ADDRA[3] => DOA) = 407; (ADDRB[3] => DOB) = 407; (ADDRC[3] => DOC) = 407; (ADDRD[3] => DOD) = 407; | ||||
|     (ADDRA[4] => DOA) = 238; (ADDRB[4] => DOB) = 238; (ADDRC[4] => DOC) = 238; (ADDRD[4] => DOD) = 238; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -2045,6 +2090,7 @@ endmodule | |||
| 
 | ||||
| // Shift registers. | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SRL16 ( | ||||
|   output Q, | ||||
|   input A0, A1, A2, A3, | ||||
|  | @ -2063,14 +2109,14 @@ module SRL16 ( | |||
|     (posedge CLK => (Q : 1'bx)) = 1472; | ||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L912 | ||||
|     $setup(D , posedge CLK, 173); | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //(A0 => Q) = 631; | ||||
|     //(A1 => Q) = 472; | ||||
|     //(A2 => Q) = 407; | ||||
|     //(A3 => Q) = 238; | ||||
|     (A0 => Q) = 631; | ||||
|     (A1 => Q) = 472; | ||||
|     (A2 => Q) = 407; | ||||
|     (A3 => Q) = 238; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SRL16E ( | ||||
|   output Q, | ||||
|   input A0, A1, A2, A3, CE, | ||||
|  | @ -2096,16 +2142,19 @@ module SRL16E ( | |||
|     $setup(D , posedge 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 | ||||
|     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) (negedge CLK => (Q : 1'bx)) = 1472; | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //(A0 => Q) = 631; | ||||
|     //(A1 => Q) = 472; | ||||
|     //(A2 => Q) = 407; | ||||
|     //(A3 => Q) = 238; | ||||
|     (A0 => Q) = 631; | ||||
|     (A1 => Q) = 472; | ||||
|     (A2 => Q) = 407; | ||||
|     (A3 => Q) = 238; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SRLC16 ( | ||||
|   output Q, | ||||
|   output Q15, | ||||
|  | @ -2122,18 +2171,20 @@ module SRLC16 ( | |||
|   always @(posedge CLK) r <= { r[14:0], D }; | ||||
| 
 | ||||
|   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 | ||||
|     $setup(D , posedge CLK, 173); | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //(A0 => Q) = 631; | ||||
|     //(A1 => Q) = 472; | ||||
|     //(A2 => Q) = 407; | ||||
|     //(A3 => Q) = 238; | ||||
|     // 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#L904 | ||||
|     (posedge CLK => (Q15 : 1'bx)) = 1114; | ||||
|     (A0 => Q) = 631; | ||||
|     (A1 => Q) = 472; | ||||
|     (A2 => Q) = 407; | ||||
|     (A3 => Q) = 238; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SRLC16E ( | ||||
|   output Q, | ||||
|   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 | ||||
|     $setup(D , posedge 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 | ||||
|     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : D)) = 1472; | ||||
|     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : D)) = 1472; | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //(A0 => Q) = 642; | ||||
|     //(A1 => Q) = 631; | ||||
|     //(A2 => Q) = 472; | ||||
|     //(A3 => Q) = 407; | ||||
|     //(A4 => Q) = 238; | ||||
|     // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904 | ||||
|     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q15 : 1'bx)) = 1114; | ||||
|     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q15 : 1'bx)) = 1114; | ||||
|     (A0 => Q) = 631; | ||||
|     (A1 => Q) = 472; | ||||
|     (A2 => Q) = 407; | ||||
|     (A3 => Q) = 238; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, lib_whitebox *) | ||||
| module SRLC32E ( | ||||
|   output Q, | ||||
|   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 | ||||
|     $setup(D , posedge 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 | ||||
|     if (!IS_CLK_INVERTED && CE) (posedge 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 | ||||
|     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q : 1'bx)) = 1114; | ||||
|     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q : 1'bx)) = 1114; | ||||
|     // Captured by $__ABC9_RAM6 | ||||
|     //(A0 => Q) = 642; | ||||
|     //(A1 => Q) = 631; | ||||
|     //(A2 => Q) = 472; | ||||
|     //(A3 => Q) = 407; | ||||
|     //(A4 => Q) = 238; | ||||
|     if (!IS_CLK_INVERTED && CE) (posedge CLK => (Q31 : 1'bx)) = 1114; | ||||
|     if ( IS_CLK_INVERTED && CE) (negedge CLK => (Q31 : 1'bx)) = 1114; | ||||
|     (A[0] => Q) = 642; | ||||
|     (A[1] => Q) = 631; | ||||
|     (A[2] => Q) = 472; | ||||
|     (A[3] => Q) = 407; | ||||
|     (A[4] => Q) = 238; | ||||
|   endspecify | ||||
| endmodule | ||||
| 
 | ||||
|  | @ -2978,6 +3036,10 @@ endmodule | |||
| 
 | ||||
| // 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 ( | ||||
|     output [29:0] ACOUT, | ||||
|     output [17:0] BCOUT, | ||||
|  |  | |||
|  | @ -143,7 +143,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 
 | ||||
| 	std::string top_opt, edif_file, blif_file, family; | ||||
| 	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; | ||||
| 	int widemux; | ||||
| 	int lut_size; | ||||
|  | @ -170,7 +170,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 		nodsp = false; | ||||
| 		uram = false; | ||||
| 		abc9 = false; | ||||
| 		dff_mode = false; | ||||
| 		dff = false; | ||||
| 		flatten_before_abc = false; | ||||
| 		widemux = 0; | ||||
| 		lut_size = 6; | ||||
|  | @ -217,7 +217,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-retime") { | ||||
| 				dff_mode = true; | ||||
| 				dff = true; | ||||
| 				retime = true; | ||||
| 				continue; | ||||
| 			} | ||||
|  | @ -281,7 +281,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-dff") { | ||||
| 				dff_mode = true; | ||||
| 				dff = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
|  | @ -595,9 +595,11 @@ struct SynthXilinxPass : public ScriptPass | |||
| 			run("clean"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (check_label("map_ffs")) { | ||||
| 		if (check_label("map_ffs", "('-abc9' only)")) { | ||||
| 			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) | ||||
| 				run("flatten"); | ||||
| 			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) { | ||||
| 				if (lut_size != 6) | ||||
| 					log_error("'synth_xilinx -abc9' not currently supported for LUT4-based devices.\n"); | ||||
| 				if (family != "xc7") | ||||
| 					log_warning("'synth_xilinx -abc9' not currently supported for the '%s' family, " | ||||
| 							"will use timing for 'xc7' instead.\n", family.c_str()); | ||||
| 				std::string techmap_args = "-map +/xilinx/abc9_map.v -max_iter 1"; | ||||
| 				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"); | ||||
| 				run("read_verilog -icells -lib -specify +/xilinx/abc9_model.v"); | ||||
| 				std::string abc9_opts; | ||||
| 				std::string k = "synth_xilinx.abc9.W"; | ||||
| 				if (active_design && active_design->scratchpad.count(k)) | ||||
|  | @ -628,10 +626,9 @@ struct SynthXilinxPass : public ScriptPass | |||
| 				} | ||||
| 				if (nowidelut) | ||||
| 					abc9_opts += stringf(" -maxlut %d", lut_size); | ||||
| 				if (dff_mode) | ||||
| 				if (dff) | ||||
| 					abc9_opts += " -dff"; | ||||
| 				run("abc9" + abc9_opts); | ||||
| 				run("techmap -map +/xilinx/abc9_unmap.v"); | ||||
| 			} | ||||
| 			else { | ||||
| 				std::string abc_opts; | ||||
|  | @ -648,7 +645,7 @@ struct SynthXilinxPass : public ScriptPass | |||
| 					else | ||||
| 						abc_opts += " -luts 2:2,3,6:5,10,20,40"; | ||||
| 				} | ||||
| 				if (dff_mode) | ||||
| 				if (dff) | ||||
| 					abc_opts += " -dff"; | ||||
| 				if (retime) | ||||
| 					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 | ||||
| module top(input C, D, output [7:0] Q); | ||||
| FDRE   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])); | ||||
| FDCE   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])); | ||||
| FDRE_1 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])); | ||||
| FDCE_1 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])); | ||||
| FDRE   /*#(.INIT(0))*/ fd1(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[0])); | ||||
| FDSE   #(.INIT(0)) fd2(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[1])); | ||||
| FDCE   #(.INIT(0)) fd3(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[2])); | ||||
| FDPE   #(.INIT(0)) fd4(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[3])); | ||||
| FDRE_1 #(.INIT(0)) fd5(.C(C), .CE(1'b1), .D(D), .R(1'b1), .Q(Q[4])); | ||||
| FDSE_1 #(.INIT(0)) fd6(.C(C), .CE(1'b1), .D(D), .S(1'b1), .Q(Q[5])); | ||||
| FDCE_1 #(.INIT(0)) fd7(.C(C), .CE(1'b1), .D(D), .CLR(1'b1), .Q(Q[6])); | ||||
| FDPE_1 #(.INIT(0)) fd8(.C(C), .CE(1'b1), .D(D), .PRE(1'b1), .Q(Q[7])); | ||||
| endmodule | ||||
| EOT | ||||
| equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf | ||||
| 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 | ||||
| read_verilog <<EOT | ||||
| module top(input C, D, output [7:0] Q); | ||||
| FDRE   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])); | ||||
| FDCE   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])); | ||||
| FDRE_1 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])); | ||||
| FDCE_1 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])); | ||||
| FDRE   #(.INIT(0)) fd1(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[0])); | ||||
| FDSE   #(.INIT(0)) fd2(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[1])); | ||||
| FDCE   #(.INIT(0)) fd3(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[2])); | ||||
| FDPE   #(.INIT(0)) fd4(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[3])); | ||||
| FDRE_1 /*#(.INIT(0))*/ fd5(.C(C), .CE(1'b0), .D(D), .R(1'b0), .Q(Q[4])); | ||||
| FDSE_1 #(.INIT(0)) fd6(.C(C), .CE(1'b0), .D(D), .S(1'b0), .Q(Q[5])); | ||||
| FDCE_1 #(.INIT(0)) fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6])); | ||||
| FDPE_1 #(.INIT(0)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7])); | ||||
| endmodule | ||||
| EOT | ||||
| equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf | ||||
| 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; | ||||
| endmodule | ||||
| 
 | ||||
| (* abc9_box, blackbox *) | ||||
| (* abc9_box_id=1, blackbox *) | ||||
| module MUXF8(input I0, I1, S, output O); | ||||
| specify | ||||
|     (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; \ | ||||
|     opt -full; \ | ||||
|     techmap; \ | ||||
|     abc9 -lut 4; \ | ||||
|     abc9 -lut 4 -box ../abc9.box; \ | ||||
|     clean; \ | ||||
|     check -assert; \ | ||||
|     select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \ | ||||
|  |  | |||
|  | @ -45,14 +45,16 @@ sat -seq 10 -verify -prove-asserts -show-ports miter | |||
| design -reset | ||||
| read_verilog -icells <<EOT | ||||
| module abc9_test036(input clk, d, output q); | ||||
| (* keep *) reg w; | ||||
| $__ABC9_FF_ ff(.D(d), .Q(w)); | ||||
| wire \ff.clock = clk; | ||||
| wire \ff.init = 1'b0; | ||||
| (* keep, init=1'b0 *) wire w; | ||||
| $_DFF_P_ ff(.C(clk), .D(d), .Q(w)); | ||||
| assign q = w; | ||||
| endmodule | ||||
| 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 | ||||
|  | @ -67,8 +69,32 @@ specify | |||
| endspecify | ||||
| 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)); | ||||
| endmodule | ||||
| EOT | ||||
| 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