mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-28 10:19:26 +00:00 
			
		
		
		
	timinginfo: arrival/required times with clocks
This commit is contained in:
		
							parent
							
								
									b96866c456
								
							
						
					
					
						commit
						ddbe81df78
					
				
					 4 changed files with 63 additions and 66 deletions
				
			
		|  | @ -255,26 +255,24 @@ struct XAigerWriter | ||||||
| 
 | 
 | ||||||
| 				if (!timing.count(derived_type)) | 				if (!timing.count(derived_type)) | ||||||
| 					timing.setup_module(inst_module); | 					timing.setup_module(inst_module); | ||||||
| 				auto &t = timing.at(derived_type).arrival; |  | ||||||
| 				for (const auto &conn : cell->connections()) { |  | ||||||
| 					auto port_wire = inst_module->wire(conn.first); |  | ||||||
| 					if (!port_wire->port_output) |  | ||||||
| 						continue; |  | ||||||
| 
 | 
 | ||||||
| 					for (int i = 0; i < GetSize(conn.second); i++) { | 				for (auto &i : timing.at(derived_type).arrival) { | ||||||
| 						auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); | 					auto port_wire = inst_module->wire(i.first.name); | ||||||
|  | 					log_assert(port_wire->port_output); | ||||||
|  | 
 | ||||||
|  | 					auto d = i.second.first; | ||||||
| 					if (d == 0) | 					if (d == 0) | ||||||
| 						continue; | 						continue; | ||||||
|  | 					auto offset = i.first.offset; | ||||||
| 
 | 
 | ||||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||||
| 					if (ys_debug(1)) { | 					if (ys_debug(1)) { | ||||||
| 							static std::set<std::tuple<IdString,IdString,int>> seen; | 						static std::set<std::pair<IdString,TimingInfo::NameBit>> seen; | ||||||
| 							if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n", | 						if (seen.emplace(derived_type, i.first).second) log("%s.%s[%d] abc9_arrival = %d\n", | ||||||
| 									log_id(cell->type), log_id(conn.first), i, d); | 								log_id(cell->type), log_id(i.first.name), offset, d); | ||||||
| 					} | 					} | ||||||
| #endif | #endif | ||||||
| 						arrival_times[conn.second[i]] = d; | 					arrival_times[cell->getPort(i.first.name)[offset]] = d; | ||||||
| 					} |  | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (abc9_flop) | 				if (abc9_flop) | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ struct TimingInfo | ||||||
| 		explicit NameBit(const RTLIL::SigBit &b) : name(b.wire->name), offset(b.offset) {} | 		explicit NameBit(const RTLIL::SigBit &b) : name(b.wire->name), offset(b.offset) {} | ||||||
| 		bool operator==(const NameBit& nb) const { return nb.name == name && nb.offset == offset; } | 		bool operator==(const NameBit& nb) const { return nb.name == name && nb.offset == offset; } | ||||||
| 		bool operator!=(const NameBit& nb) const { return !operator==(nb); } | 		bool operator!=(const NameBit& nb) const { return !operator==(nb); } | ||||||
|  | 		bool operator<(const NameBit& nb) const { return nb.name < name && nb.offset < offset; } | ||||||
| 		unsigned int hash() const { return mkhash_add(name.hash(), offset); } | 		unsigned int hash() const { return mkhash_add(name.hash(), offset); } | ||||||
| 	}; | 	}; | ||||||
| 	struct BitBit | 	struct BitBit | ||||||
|  | @ -49,9 +50,8 @@ struct TimingInfo | ||||||
| 
 | 
 | ||||||
| 	struct ModuleTiming | 	struct ModuleTiming | ||||||
| 	{ | 	{ | ||||||
| 		RTLIL::IdString type; |  | ||||||
| 		dict<BitBit, int> comb; | 		dict<BitBit, int> comb; | ||||||
| 		dict<NameBit, int> arrival, required; | 		dict<NameBit, std::pair<int,NameBit>> arrival, required; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	dict<RTLIL::IdString, ModuleTiming> data; | 	dict<RTLIL::IdString, ModuleTiming> data; | ||||||
|  | @ -117,10 +117,9 @@ struct TimingInfo | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else if (cell->type == ID($specify3)) { | 			else if (cell->type == ID($specify3)) { | ||||||
| 				auto src = cell->getPort(ID::SRC); | 				auto src = cell->getPort(ID::SRC).as_bit(); | ||||||
| 				auto dst = cell->getPort(ID::DST); | 				auto dst = cell->getPort(ID::DST); | ||||||
| 				for (const auto &c : src.chunks()) | 				if (!src.wire->port_input) | ||||||
| 					if (!c.wire->port_input) |  | ||||||
| 					log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); | 					log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); | ||||||
| 				for (const auto &c : dst.chunks()) | 				for (const auto &c : dst.chunks()) | ||||||
| 					if (!c.wire->port_output) | 					if (!c.wire->port_output) | ||||||
|  | @ -128,15 +127,16 @@ struct TimingInfo | ||||||
| 				int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); | 				int rise_max = cell->getParam(ID::T_RISE_MAX).as_int(); | ||||||
| 				int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); | 				int fall_max = cell->getParam(ID::T_FALL_MAX).as_int(); | ||||||
| 				int max = std::max(rise_max,fall_max); | 				int max = std::max(rise_max,fall_max); | ||||||
| 				if (max < 0) | 				if (max < 0) { | ||||||
| 					log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); | 					log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported; clamping to zero .\n", log_id(module), log_id(cell)); | ||||||
| 				if (max <= 0) { | 					max = 0; | ||||||
| 					log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); |  | ||||||
| 					continue; |  | ||||||
| 				} | 				} | ||||||
| 				for (const auto &d : dst) { | 				for (const auto &d : dst) { | ||||||
| 					auto &v = t.arrival[NameBit(d)]; | 					auto &v = t.arrival[NameBit(d)]; | ||||||
| 					v = std::max(v, max); | 					if (v.first < max) { | ||||||
|  | 						v.first = max; | ||||||
|  | 						v.second = NameBit(src); | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else if (cell->type == ID($specrule)) { | 			else if (cell->type == ID($specrule)) { | ||||||
|  | @ -144,23 +144,23 @@ struct TimingInfo | ||||||
| 				if (type != "$setup" && type != "$setuphold") | 				if (type != "$setup" && type != "$setuphold") | ||||||
| 					continue; | 					continue; | ||||||
| 				auto src = cell->getPort(ID::SRC); | 				auto src = cell->getPort(ID::SRC); | ||||||
| 				auto dst = cell->getPort(ID::DST); | 				auto dst = cell->getPort(ID::DST).as_bit(); | ||||||
| 				for (const auto &c : src.chunks()) | 				for (const auto &c : src.chunks()) | ||||||
| 					if (!c.wire->port_input) | 					if (!c.wire->port_input) | ||||||
| 						log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); | 						log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); | ||||||
| 				for (const auto &c : dst.chunks()) | 				if (!dst.wire->port_input) | ||||||
| 					if (!c.wire->port_input) |  | ||||||
| 					log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); | 					log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); | ||||||
| 				int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); | 				int max = cell->getParam(ID::T_LIMIT_MAX).as_int(); | ||||||
| 				if (max < 0) | 				if (max < 0) { | ||||||
| 					log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); | 					log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported; clamping to zero.\n", log_id(module), log_id(cell)); | ||||||
| 				if (max <= 0) { | 					max = 0; | ||||||
| 					log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); |  | ||||||
| 					continue; |  | ||||||
| 				} | 				} | ||||||
| 				for (const auto &s : src) { | 				for (const auto &s : src) { | ||||||
| 					auto &v = t.required[NameBit(s)]; | 					auto &v = t.required[NameBit(s)]; | ||||||
| 					v = std::max(v, max); | 					if (v.first < max) { | ||||||
|  | 						v.first = max; | ||||||
|  | 						v.second = NameBit(dst); | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ struct StaWorker | ||||||
| 						auto it = t.required.find(namebit); | 						auto it = t.required.find(namebit); | ||||||
| 						if (it == t.required.end()) | 						if (it == t.required.end()) | ||||||
| 							continue; | 							continue; | ||||||
| 						endpoints[bit] = it->second; | 						endpoints[bit] = it->second.first; | ||||||
| 					} | 					} | ||||||
| 					if (cell->output(conn.first)) { | 					if (cell->output(conn.first)) { | ||||||
| 						dst_bits.insert(std::make_pair(bit,namebit)); | 						dst_bits.insert(std::make_pair(bit,namebit)); | ||||||
|  | @ -90,14 +90,8 @@ struct StaWorker | ||||||
| 						auto it = t.arrival.find(namebit); | 						auto it = t.arrival.find(namebit); | ||||||
| 						if (it == t.arrival.end()) | 						if (it == t.arrival.end()) | ||||||
| 							continue; | 							continue; | ||||||
| 						auto arrivals = bit.wire->get_intvec_attribute(ID(sta_arrival)); | 						const auto &s = it->second.second; | ||||||
| 						if (arrivals.empty()) | 						fanouts[cell->getPort(s.name)[s.offset]].emplace_back(bit,it->second.first); | ||||||
| 							arrivals = std::vector<int>(GetSize(bit.wire), -1); |  | ||||||
| 						else |  | ||||||
| 							log_assert(GetSize(arrivals) == GetSize(bit.wire)); |  | ||||||
| 						arrivals[bit.offset] = it->second; |  | ||||||
| 						bit.wire->set_intvec_attribute(ID(sta_arrival), arrivals); |  | ||||||
| 						queue.emplace_back(bit); |  | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | @ -143,7 +137,7 @@ struct StaWorker | ||||||
| 				auto new_arrival = src_arrival + d.second + endpoints.at(d.first, 0); | 				auto new_arrival = src_arrival + d.second + endpoints.at(d.first, 0); | ||||||
| 				if (dst_arrival < new_arrival) { | 				if (dst_arrival < new_arrival) { | ||||||
| 					dst_arrival = std::max(dst_arrival, new_arrival); | 					dst_arrival = std::max(dst_arrival, new_arrival); | ||||||
| 					if (dst_arrival > maxarrival) { | 					if (endpoints.count(d.first) && dst_arrival > maxarrival) { | ||||||
| 						maxarrival = dst_arrival; | 						maxarrival = dst_arrival; | ||||||
| 						maxbit = d.first; | 						maxbit = d.first; | ||||||
| 					} | 					} | ||||||
|  | @ -169,6 +163,10 @@ struct StaWorker | ||||||
| 		std::map<int, unsigned> arrival_histogram; | 		std::map<int, unsigned> arrival_histogram; | ||||||
| 		for (const auto &i : endpoints) { | 		for (const auto &i : endpoints) { | ||||||
| 			const auto &b = i.first; | 			const auto &b = i.first; | ||||||
|  | 			if (!b.wire->attributes.count(ID(sta_arrival))) { | ||||||
|  | 				log_warning("Wire %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b)); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			auto arrival = b.wire->get_intvec_attribute(ID(sta_arrival))[b.offset]; | 			auto arrival = b.wire->get_intvec_attribute(ID(sta_arrival))[b.offset]; | ||||||
| 			arrival += i.second; | 			arrival += i.second; | ||||||
| 			arrival_histogram[arrival]++; | 			arrival_histogram[arrival]++; | ||||||
|  |  | ||||||
|  | @ -440,25 +440,26 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) | ||||||
| 			if (!port_wire->port_input) | 			if (!port_wire->port_input) | ||||||
| 				continue; | 				continue; | ||||||
| 
 | 
 | ||||||
| 			SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); | 			auto d = i.second.first; | ||||||
| 			for (int i = 0; i < GetSize(conn.second); i++) { |  | ||||||
| 				auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); |  | ||||||
| 			if (d == 0) | 			if (d == 0) | ||||||
| 				continue; | 				continue; | ||||||
|  | 			auto offset = i.first.offset; | ||||||
| 
 | 
 | ||||||
|  | 			auto O = module->addWire(NEW_ID); | ||||||
|  | 			auto rhs = cell->getPort(i.first.name); | ||||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||||
| 			if (ys_debug(1)) { | 			if (ys_debug(1)) { | ||||||
| 					static std::set<std::tuple<IdString,IdString,int>> seen; | 				static std::set<std::pair<IdString,TimingInfo::NameBit>> seen; | ||||||
| 					if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n", | 				if (seen.emplace(derived_type, i.first).second) log("%s.%s[%d] abc9_required = %d\n", | ||||||
| 							log_id(cell->type), log_id(conn.first), i, d); | 						log_id(cell->type), log_id(i.first.name), offset, d); | ||||||
| 			} | 			} | ||||||
| #endif | #endif | ||||||
| 			auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); | 			auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); | ||||||
| 				box->setPort(ID::I, conn.second[i]); | 			box->setPort(ID::I, rhs[offset]); | ||||||
| 				box->setPort(ID::O, O[i]); | 			box->setPort(ID::O, O); | ||||||
| 			box->setParam(ID::DELAY, d); | 			box->setParam(ID::DELAY, d); | ||||||
| 				conn.second[i] = O[i]; | 			rhs[offset] = O; | ||||||
| 			} | 			cell->setPort(i.first.name, rhs); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -606,13 +607,13 @@ void prep_box(RTLIL::Design *design, bool dff_mode) | ||||||
| 						// Assume that no setup time means zero
 | 						// Assume that no setup time means zero
 | ||||||
| 						ss << 0; | 						ss << 0; | ||||||
| 					else { | 					else { | ||||||
| 						ss << it->second; | 						ss << it->second.first; | ||||||
| 
 | 
 | ||||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||||
| 						if (ys_debug(1)) { | 						if (ys_debug(1)) { | ||||||
| 							static std::set<std::pair<IdString,IdString>> seen; | 							static std::set<std::pair<IdString,IdString>> seen; | ||||||
| 							if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), | 							if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), | ||||||
| 									log_id(port_name), it->second); | 									log_id(port_name), it->second.first); | ||||||
| 						} | 						} | ||||||
| #endif | #endif | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue