mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	abc9_ops: use TimingInfo for -prep_{lut,box} too
This commit is contained in:
		
							parent
							
								
									cda4acb544
								
							
						
					
					
						commit
						3ea5506f81
					
				
					 3 changed files with 65 additions and 97 deletions
				
			
		| 
						 | 
					@ -148,24 +148,8 @@ struct TimingInfo
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int delay(IdString module_name, const SigBit &src, const SigBit &dst) const {
 | 
					        decltype(data)::const_iterator find (RTLIL::IdString module_name) const { return data.find(module_name); }
 | 
				
			||||||
                auto it = data.find(module_name);
 | 
					        decltype(data)::const_iterator end () const { return data.end(); }
 | 
				
			||||||
                if (it == data.end())
 | 
					 | 
				
			||||||
                        return 0;
 | 
					 | 
				
			||||||
                return it->second.comb.at(BitBit(src,dst), 0);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        int arrival(IdString module_name, const SigBit &src) const {
 | 
					 | 
				
			||||||
                auto it = data.find(module_name);
 | 
					 | 
				
			||||||
                if (it == data.end())
 | 
					 | 
				
			||||||
                        return 0;
 | 
					 | 
				
			||||||
                return it->second.arrival.at(src, 0);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        int required(IdString module_name, const SigBit &dst) const {
 | 
					 | 
				
			||||||
                auto it = data.find(module_name);
 | 
					 | 
				
			||||||
                if (it == data.end())
 | 
					 | 
				
			||||||
                        return 0;
 | 
					 | 
				
			||||||
                return it->second.required.at(dst, 0);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_NAMESPACE_END
 | 
					YOSYS_NAMESPACE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -424,8 +424,8 @@ void prep_delays(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
	std::stringstream ss;
 | 
						std::stringstream ss;
 | 
				
			||||||
	for (auto module : design->modules()) {
 | 
						for (auto module : design->modules()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                auto it = timing.data.find(module->name);
 | 
					                auto it = timing.find(module->name);
 | 
				
			||||||
                if (it == timing.data.end())
 | 
					                if (it == timing.end())
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                const auto &t = it->second;
 | 
					                const auto &t = it->second;
 | 
				
			||||||
| 
						 | 
					@ -539,35 +539,31 @@ void prep_delays(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void prep_lut(RTLIL::Design *design, int maxlut)
 | 
					void prep_lut(RTLIL::Design *design, int maxlut)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					        const TimingInfo timing(design);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::vector<std::tuple<int, IdString, int, std::vector<int>>> table;
 | 
						std::vector<std::tuple<int, IdString, int, std::vector<int>>> table;
 | 
				
			||||||
	for (auto module : design->modules()) {
 | 
						for (auto module : design->modules()) {
 | 
				
			||||||
		auto it = module->attributes.find(ID(abc9_lut));
 | 
							auto it = module->attributes.find(ID(abc9_lut));
 | 
				
			||||||
		if (it == module->attributes.end())
 | 
							if (it == module->attributes.end())
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                auto jt = timing.find(module->name);
 | 
				
			||||||
 | 
					                if (jt == timing.end())
 | 
				
			||||||
 | 
					                        continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SigBit o;
 | 
							SigBit o;
 | 
				
			||||||
		std::vector<int> specify;
 | 
							std::vector<int> specify;
 | 
				
			||||||
		for (auto cell : module->cells()) {
 | 
							auto &t = jt->second;
 | 
				
			||||||
			if (cell->type != ID($specify2))
 | 
							for (const auto &i : t.comb) {
 | 
				
			||||||
				continue;
 | 
								auto &d = i.first.second;
 | 
				
			||||||
			log_assert(cell->getParam(ID(SRC_WIDTH)) == 1);
 | 
								log_dump(o, d);
 | 
				
			||||||
			log_assert(cell->getParam(ID(DST_WIDTH)) == 1);
 | 
					 | 
				
			||||||
			SigBit s = cell->getPort(ID(SRC));
 | 
					 | 
				
			||||||
			SigBit d = cell->getPort(ID(DST));
 | 
					 | 
				
			||||||
			log_assert(s.wire->port_input);
 | 
					 | 
				
			||||||
			log_assert(d.wire->port_output);
 | 
					 | 
				
			||||||
			if (o == SigBit())
 | 
								if (o == SigBit())
 | 
				
			||||||
				o = d;
 | 
									o = d;
 | 
				
			||||||
			else
 | 
								else if (o != d)
 | 
				
			||||||
				log_assert(o == d);
 | 
									log_error("(* abc9_lut *) module '%s' with has more than one output.\n", log_id(module));
 | 
				
			||||||
			// TODO: Don't assume that each specify entry with the destination 'o'
 | 
								specify.push_back(i.second);
 | 
				
			||||||
			//       describes a unique LUT input
 | 
					 | 
				
			||||||
			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_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell));
 | 
					 | 
				
			||||||
			specify.push_back(max);
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (maxlut && GetSize(specify) > maxlut)
 | 
							if (maxlut && GetSize(specify) > maxlut)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		// ABC requires non-decreasing LUT input delays
 | 
							// ABC requires non-decreasing LUT input delays
 | 
				
			||||||
| 
						 | 
					@ -607,14 +603,27 @@ void write_lut(RTLIL::Module *module, const std::string &dst) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void prep_box(RTLIL::Design *design, bool dff_mode)
 | 
					void prep_box(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					        const TimingInfo timing(design);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::stringstream ss;
 | 
						std::stringstream ss;
 | 
				
			||||||
	int abc9_box_id = 1;
 | 
						int abc9_box_id = 1;
 | 
				
			||||||
 | 
						for (auto module : design->modules()) {
 | 
				
			||||||
 | 
							auto it = module->attributes.find(ID(abc9_box_id));
 | 
				
			||||||
 | 
							if (it == module->attributes.end())
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							abc9_box_id = std::max(abc9_box_id, it->second.as_int());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dict<IdString,std::vector<IdString>> box_ports;
 | 
						dict<IdString,std::vector<IdString>> box_ports;
 | 
				
			||||||
	for (auto module : design->modules()) {
 | 
						for (auto module : design->modules()) {
 | 
				
			||||||
		auto abc9_flop = module->get_bool_attribute(ID(abc9_flop));
 | 
							auto abc9_flop = module->get_bool_attribute(ID(abc9_flop));
 | 
				
			||||||
		if (abc9_flop) {
 | 
							if (abc9_flop) {
 | 
				
			||||||
 | 
								auto r = module->attributes.insert(ID(abc9_box_id));
 | 
				
			||||||
 | 
								if (!r.second)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								r.first->second = abc9_box_id++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (dff_mode) {
 | 
								if (dff_mode) {
 | 
				
			||||||
                                log_dump(module->name);
 | 
					 | 
				
			||||||
				int num_inputs = 0, num_outputs = 0;
 | 
									int num_inputs = 0, num_outputs = 0;
 | 
				
			||||||
				for (auto port_name : module->ports) {
 | 
									for (auto port_name : module->ports) {
 | 
				
			||||||
					auto wire = module->wire(port_name);
 | 
										auto wire = module->wire(port_name);
 | 
				
			||||||
| 
						 | 
					@ -624,10 +633,6 @@ void prep_box(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				log_assert(num_outputs == 1);
 | 
									log_assert(num_outputs == 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				auto r = module->attributes.insert(ID(abc9_box_id));
 | 
					 | 
				
			||||||
				if (r.second)
 | 
					 | 
				
			||||||
					r.first->second = abc9_box_id++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				ss << log_id(module) << " " << r.first->second.as_int();
 | 
									ss << log_id(module) << " " << r.first->second.as_int();
 | 
				
			||||||
				ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0");
 | 
									ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0");
 | 
				
			||||||
				ss << " " << num_inputs+1 << " " << num_outputs << std::endl;
 | 
									ss << " " << num_inputs+1 << " " << num_outputs << std::endl;
 | 
				
			||||||
| 
						 | 
					@ -680,12 +685,12 @@ void prep_box(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			if (!module->attributes.erase(ID(abc9_box)))
 | 
								if (!module->attributes.erase(ID(abc9_box)))
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		log_assert(!module->attributes.count(ID(abc9_box_id)));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dict<std::pair<SigBit,SigBit>, std::string> table;
 | 
								auto r = module->attributes.insert(ID(abc9_box_id));
 | 
				
			||||||
		std::vector<SigBit> inputs;
 | 
								if (!r.second)
 | 
				
			||||||
		std::vector<SigBit> outputs;
 | 
									continue;
 | 
				
			||||||
 | 
								r.first->second = abc9_box_id++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto r = box_ports.insert(module->name);
 | 
							auto r = box_ports.insert(module->name);
 | 
				
			||||||
		if (r.second) {
 | 
							if (r.second) {
 | 
				
			||||||
| 
						 | 
					@ -712,6 +717,8 @@ void prep_box(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::vector<SigBit> inputs;
 | 
				
			||||||
 | 
							std::vector<SigBit> outputs;
 | 
				
			||||||
		for (auto port_name : r.first->second) {
 | 
							for (auto port_name : r.first->second) {
 | 
				
			||||||
			auto wire = module->wire(port_name);
 | 
								auto wire = module->wire(port_name);
 | 
				
			||||||
			if (wire->port_input)
 | 
								if (wire->port_input)
 | 
				
			||||||
| 
						 | 
					@ -721,47 +728,11 @@ void prep_box(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
				for (int i = 0; i < GetSize(wire); i++)
 | 
									for (int i = 0; i < GetSize(wire); i++)
 | 
				
			||||||
					outputs.emplace_back(wire, i);
 | 
										outputs.emplace_back(wire, i);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for (auto cell : module->cells()) {
 | 
					
 | 
				
			||||||
			if (cell->type != ID($specify2))
 | 
							ss << log_id(module) << " " << module->attributes.at(ID(abc9_box_id)).as_int();
 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			auto src = cell->getPort(ID(SRC));
 | 
					 | 
				
			||||||
			auto dst = cell->getPort(ID(DST));
 | 
					 | 
				
			||||||
			for (const auto &c : src.chunks())
 | 
					 | 
				
			||||||
				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));
 | 
					 | 
				
			||||||
			for (const auto &c : dst.chunks())
 | 
					 | 
				
			||||||
				if (!c.wire->port_output)
 | 
					 | 
				
			||||||
					log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst));
 | 
					 | 
				
			||||||
			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_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell));
 | 
					 | 
				
			||||||
			if (cell->getParam(ID(FULL)).as_bool()) {
 | 
					 | 
				
			||||||
				for (auto s : src)
 | 
					 | 
				
			||||||
					for (auto d : dst) {
 | 
					 | 
				
			||||||
						auto r = table.insert(std::make_pair(s,d));
 | 
					 | 
				
			||||||
						log_assert(r.second);
 | 
					 | 
				
			||||||
						r.first->second = std::to_string(max);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else {
 | 
					 | 
				
			||||||
				log_assert(GetSize(src) == GetSize(dst));
 | 
					 | 
				
			||||||
				for (auto i = 0; i < GetSize(src); i++) {
 | 
					 | 
				
			||||||
					auto r = table.insert(std::make_pair(src[i],dst[i]));
 | 
					 | 
				
			||||||
					if (!r.second)
 | 
					 | 
				
			||||||
						log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(src[i]), log_signal(dst[i]));
 | 
					 | 
				
			||||||
					log_assert(r.second);
 | 
					 | 
				
			||||||
					r.first->second = std::to_string(max);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		auto r2 = module->attributes.insert(ID(abc9_box_id));
 | 
					 | 
				
			||||||
		log_assert(r2.second);
 | 
					 | 
				
			||||||
		ss << log_id(module) << " " << abc9_box_id;
 | 
					 | 
				
			||||||
		r2.first->second = abc9_box_id++;
 | 
					 | 
				
			||||||
		ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0");
 | 
							ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0");
 | 
				
			||||||
		ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl;
 | 
							ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool first = true;
 | 
							bool first = true;
 | 
				
			||||||
		ss << "#";
 | 
							ss << "#";
 | 
				
			||||||
		for (const auto &i : inputs) {
 | 
							for (const auto &i : inputs) {
 | 
				
			||||||
| 
						 | 
					@ -775,6 +746,12 @@ void prep_box(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
				ss << log_id(i.wire) << "[" << i.offset << "]";
 | 
									ss << log_id(i.wire) << "[" << i.offset << "]";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ss << std::endl;
 | 
							ss << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto it = timing.find(module->name);
 | 
				
			||||||
 | 
							if (it == timing.end())
 | 
				
			||||||
 | 
								log_error("(* abc9_box *) module '%s' has no timing information.\n", log_id(module));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const auto &t = it->second.comb;
 | 
				
			||||||
		for (const auto &o : outputs) {
 | 
							for (const auto &o : outputs) {
 | 
				
			||||||
			first = true;
 | 
								first = true;
 | 
				
			||||||
			for (const auto &i : inputs) {
 | 
								for (const auto &i : inputs) {
 | 
				
			||||||
| 
						 | 
					@ -782,7 +759,11 @@ void prep_box(RTLIL::Design *design, bool dff_mode)
 | 
				
			||||||
					first = false;
 | 
										first = false;
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					ss << " ";
 | 
										ss << " ";
 | 
				
			||||||
				ss << table.at(std::make_pair(i,o), "-");
 | 
									auto jt = t.find(std::make_pair(i,o));
 | 
				
			||||||
 | 
									if (jt == t.end())
 | 
				
			||||||
 | 
										ss << "-";
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										ss << jt->second;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			ss << " # ";
 | 
								ss << " # ";
 | 
				
			||||||
			if (GetSize(o.wire) == 1)
 | 
								if (GetSize(o.wire) == 1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,6 +69,7 @@ endmodule
 | 
				
			||||||
(* abc9_box *)
 | 
					(* abc9_box *)
 | 
				
			||||||
module \$__ABC9_RAM6 (input A, input [5:0] S, output Y);
 | 
					module \$__ABC9_RAM6 (input A, input [5:0] S, output Y);
 | 
				
			||||||
  specify
 | 
					  specify
 | 
				
			||||||
 | 
					    (A    => Y) =   0;
 | 
				
			||||||
    (S[0] => Y) = 642;
 | 
					    (S[0] => Y) = 642;
 | 
				
			||||||
    (S[1] => Y) = 631;
 | 
					    (S[1] => Y) = 631;
 | 
				
			||||||
    (S[2] => Y) = 472;
 | 
					    (S[2] => Y) = 472;
 | 
				
			||||||
| 
						 | 
					@ -81,13 +82,15 @@ endmodule
 | 
				
			||||||
(* abc9_box *)
 | 
					(* abc9_box *)
 | 
				
			||||||
module \$__ABC9_RAM7 (input A, input [6:0] S, output Y);
 | 
					module \$__ABC9_RAM7 (input A, input [6:0] S, output Y);
 | 
				
			||||||
  specify
 | 
					  specify
 | 
				
			||||||
    (S[0] => Y) = 1028;
 | 
					    (A    => Y) = 0;
 | 
				
			||||||
    (S[1] => Y) = 1017;
 | 
					                                                    // https://github.com/SymbiFlow/prjxray-db/blob/1c85daf1b115da4d27ca83c6b89f53a94de39748/artix7/timings/slicel.sdf#L867
 | 
				
			||||||
    (S[2] => Y) =  858;
 | 
					    (S[0] => Y) = 642 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
 | 
				
			||||||
    (S[3] => Y) =  793;
 | 
					    (S[1] => Y) = 631 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
 | 
				
			||||||
    (S[4] => Y) =  624;
 | 
					    (S[2] => Y) = 472 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
 | 
				
			||||||
    (S[5] => Y) =  513;
 | 
					    (S[3] => Y) = 407 + 223 /* to cross F7BMUX */ + 174 /* CMUX */;
 | 
				
			||||||
    (S[6] => Y) =  464;
 | 
					    (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
 | 
					  endspecify
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue