mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Various improvements regarding logic loops in "share" results
This commit is contained in:
		
							parent
							
								
									d6e2ace95b
								
							
						
					
					
						commit
						96e821dc6c
					
				
					 1 changed files with 108 additions and 37 deletions
				
			
		| 
						 | 
					@ -44,6 +44,7 @@ struct ShareWorker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CellTypes fwd_ct, cone_ct;
 | 
						CellTypes fwd_ct, cone_ct;
 | 
				
			||||||
	ModWalker modwalker;
 | 
						ModWalker modwalker;
 | 
				
			||||||
 | 
						ModIndex mi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::set<RTLIL::Cell*> cells_to_remove;
 | 
						std::set<RTLIL::Cell*> cells_to_remove;
 | 
				
			||||||
	std::set<RTLIL::Cell*> recursion_state;
 | 
						std::set<RTLIL::Cell*> recursion_state;
 | 
				
			||||||
| 
						 | 
					@ -102,7 +103,7 @@ struct ShareWorker
 | 
				
			||||||
	// Find shareable cells and compatible groups of cells
 | 
						// Find shareable cells and compatible groups of cells
 | 
				
			||||||
	// ---------------------------------------------------
 | 
						// ---------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::set<RTLIL::Cell*> shareable_cells;
 | 
						std::set<RTLIL::Cell*, RTLIL::sort_by_name_str<RTLIL::Cell>> shareable_cells;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void find_shareable_cells()
 | 
						void find_shareable_cells()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -252,7 +253,7 @@ struct ShareWorker
 | 
				
			||||||
	// Create replacement cell
 | 
						// Create replacement cell
 | 
				
			||||||
	// -----------------------
 | 
						// -----------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RTLIL::Cell *make_supercell(RTLIL::Cell *c1, RTLIL::Cell *c2, RTLIL::SigSpec act)
 | 
						RTLIL::Cell *make_supercell(RTLIL::Cell *c1, RTLIL::Cell *c2, RTLIL::SigSpec act, std::set<RTLIL::Cell*> &supercell_aux)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		log_assert(c1->type == c2->type);
 | 
							log_assert(c1->type == c2->type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,10 +284,12 @@ struct ShareWorker
 | 
				
			||||||
			int a_width = std::max(a1.size(), a2.size());
 | 
								int a_width = std::max(a1.size(), a2.size());
 | 
				
			||||||
			int y_width = std::max(y1.size(), y2.size());
 | 
								int y_width = std::max(y1.size(), y2.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (a1.size() != a_width) a1 = module->addPos(NEW_ID, a1, module->addWire(NEW_ID, a_width), a_signed)->getPort("\\Y");
 | 
								a1.extend_u0(a_width, a_signed);
 | 
				
			||||||
			if (a2.size() != a_width) a2 = module->addPos(NEW_ID, a2, module->addWire(NEW_ID, a_width), a_signed)->getPort("\\Y");
 | 
								a2.extend_u0(a_width, a_signed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								RTLIL::SigSpec a = module->addWire(NEW_ID, a_width);
 | 
				
			||||||
 | 
								supercell_aux.insert(module->addMux(NEW_ID, a2, a1, act, a));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::SigSpec a = module->Mux(NEW_ID, a2, a1, act);
 | 
					 | 
				
			||||||
			RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
 | 
								RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
 | 
								RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
 | 
				
			||||||
| 
						 | 
					@ -296,12 +299,10 @@ struct ShareWorker
 | 
				
			||||||
			supercell->setPort("\\A", a);
 | 
								supercell->setPort("\\A", a);
 | 
				
			||||||
			supercell->setPort("\\Y", y);
 | 
								supercell->setPort("\\Y", y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::SigSpec new_y1(y, 0, y1.size());
 | 
								supercell_aux.insert(module->addPos(NEW_ID, y, y1));
 | 
				
			||||||
			RTLIL::SigSpec new_y2(y, 0, y2.size());
 | 
								supercell_aux.insert(module->addPos(NEW_ID, y, y2));
 | 
				
			||||||
 | 
					 | 
				
			||||||
			module->connect(RTLIL::SigSig(y1, new_y1));
 | 
					 | 
				
			||||||
			module->connect(RTLIL::SigSig(y2, new_y2));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								supercell_aux.insert(supercell);
 | 
				
			||||||
			return supercell;
 | 
								return supercell;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -386,23 +387,27 @@ struct ShareWorker
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				a_width = std::max(y_width, a_width);
 | 
									a_width = std::max(y_width, a_width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (a1.size() < y1.size()) a1 = module->addPos(NEW_ID, a1, module->addWire(NEW_ID, y1.size()), true)->getPort("\\Y");
 | 
									if (a1.size() < y1.size()) a1.extend_u0(y1.size(), true);
 | 
				
			||||||
				if (a2.size() < y2.size()) a2 = module->addPos(NEW_ID, a2, module->addWire(NEW_ID, y2.size()), true)->getPort("\\Y");
 | 
									if (a2.size() < y2.size()) a2.extend_u0(y2.size(), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (a1.size() != a_width) a1 = module->addPos(NEW_ID, a1, module->addWire(NEW_ID, a_width), false)->getPort("\\Y");
 | 
									a1.extend_u0(a_width, false);
 | 
				
			||||||
				if (a2.size() != a_width) a2 = module->addPos(NEW_ID, a2, module->addWire(NEW_ID, a_width), false)->getPort("\\Y");
 | 
									a2.extend_u0(a_width, false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (a1.size() != a_width) a1 = module->addPos(NEW_ID, a1, module->addWire(NEW_ID, a_width), a_signed)->getPort("\\Y");
 | 
									a1.extend_u0(a_width, a_signed);
 | 
				
			||||||
				if (a2.size() != a_width) a2 = module->addPos(NEW_ID, a2, module->addWire(NEW_ID, a_width), a_signed)->getPort("\\Y");
 | 
									a2.extend_u0(a_width, a_signed);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (b1.size() != b_width) b1 = module->addPos(NEW_ID, b1, module->addWire(NEW_ID, b_width), b_signed)->getPort("\\Y");
 | 
								b1.extend_u0(b_width, b_signed);
 | 
				
			||||||
			if (b2.size() != b_width) b2 = module->addPos(NEW_ID, b2, module->addWire(NEW_ID, b_width), b_signed)->getPort("\\Y");
 | 
								b2.extend_u0(b_width, b_signed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								RTLIL::SigSpec a = module->addWire(NEW_ID, a_width);
 | 
				
			||||||
 | 
								RTLIL::SigSpec b = module->addWire(NEW_ID, b_width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								supercell_aux.insert(module->addMux(NEW_ID, a2, a1, act, a));
 | 
				
			||||||
 | 
								supercell_aux.insert(module->addMux(NEW_ID, b2, b1, act, b));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::SigSpec a = module->Mux(NEW_ID, a2, a1, act);
 | 
					 | 
				
			||||||
			RTLIL::SigSpec b = module->Mux(NEW_ID, b2, b1, act);
 | 
					 | 
				
			||||||
			RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
 | 
								RTLIL::Wire *y = module->addWire(NEW_ID, y_width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
 | 
								RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type);
 | 
				
			||||||
| 
						 | 
					@ -416,19 +421,18 @@ struct ShareWorker
 | 
				
			||||||
			supercell->setPort("\\Y", y);
 | 
								supercell->setPort("\\Y", y);
 | 
				
			||||||
			supercell->check();
 | 
								supercell->check();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::SigSpec new_y1(y, 0, y1.size());
 | 
								supercell_aux.insert(module->addPos(NEW_ID, y, y1));
 | 
				
			||||||
			RTLIL::SigSpec new_y2(y, 0, y2.size());
 | 
								supercell_aux.insert(module->addPos(NEW_ID, y, y2));
 | 
				
			||||||
 | 
					 | 
				
			||||||
			module->connect(RTLIL::SigSig(y1, new_y1));
 | 
					 | 
				
			||||||
			module->connect(RTLIL::SigSig(y2, new_y2));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								supercell_aux.insert(supercell);
 | 
				
			||||||
			return supercell;
 | 
								return supercell;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (c1->type == "$memrd")
 | 
							if (c1->type == "$memrd")
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			RTLIL::Cell *supercell = module->addCell(NEW_ID, c1);
 | 
								RTLIL::Cell *supercell = module->addCell(NEW_ID, c1);
 | 
				
			||||||
			module->connect(c2->getPort("\\DATA"), supercell->getPort("\\DATA"));
 | 
								supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort("\\DATA"), c2->getPort("\\DATA")));
 | 
				
			||||||
 | 
								supercell_aux.insert(supercell);
 | 
				
			||||||
			return supercell;
 | 
								return supercell;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -633,16 +637,21 @@ struct ShareWorker
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RTLIL::SigSpec make_cell_activation_logic(const std::set<std::pair<RTLIL::SigSpec, RTLIL::Const>> &activation_patterns)
 | 
						RTLIL::SigSpec make_cell_activation_logic(const std::set<std::pair<RTLIL::SigSpec, RTLIL::Const>> &activation_patterns, std::set<RTLIL::Cell*> &supercell_aux)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		RTLIL::Wire *all_cases_wire = module->addWire(NEW_ID, 0);
 | 
							RTLIL::Wire *all_cases_wire = module->addWire(NEW_ID, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto &p : activation_patterns) {
 | 
							for (auto &p : activation_patterns) {
 | 
				
			||||||
			all_cases_wire->width++;
 | 
								all_cases_wire->width++;
 | 
				
			||||||
			module->addEq(NEW_ID, p.first, p.second, RTLIL::SigSpec(all_cases_wire, all_cases_wire->width - 1));
 | 
								supercell_aux.insert(module->addEq(NEW_ID, p.first, p.second, RTLIL::SigSpec(all_cases_wire, all_cases_wire->width - 1)));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (all_cases_wire->width == 1)
 | 
							if (all_cases_wire->width == 1)
 | 
				
			||||||
			return all_cases_wire;
 | 
								return all_cases_wire;
 | 
				
			||||||
		return module->ReduceOr(NEW_ID, all_cases_wire);
 | 
					
 | 
				
			||||||
 | 
							RTLIL::Wire *result_wire = module->addWire(NEW_ID);
 | 
				
			||||||
 | 
							supercell_aux.insert(module->addReduceOr(NEW_ID, all_cases_wire, result_wire));
 | 
				
			||||||
 | 
							return result_wire;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -690,6 +699,13 @@ struct ShareWorker
 | 
				
			||||||
		bool found_scc = !toposort.sort();
 | 
							bool found_scc = !toposort.sort();
 | 
				
			||||||
		topo_cell_drivers = std::move(toposort.database);
 | 
							topo_cell_drivers = std::move(toposort.database);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (found_scc && toposort.analyze_loops)
 | 
				
			||||||
 | 
								for (auto &loop : toposort.loops) {
 | 
				
			||||||
 | 
									log("### loop ###\n");
 | 
				
			||||||
 | 
									for (auto &c : loop)
 | 
				
			||||||
 | 
										log("%s (%s)\n", log_id(c), log_id(c->type));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return found_scc;
 | 
							return found_scc;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -715,13 +731,52 @@ struct ShareWorker
 | 
				
			||||||
		return find_in_input_cone_worker(root, needle, stop);
 | 
							return find_in_input_cone_worker(root, needle, stop);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool is_part_of_scc(RTLIL::Cell *cell)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							CellTypes ct;
 | 
				
			||||||
 | 
							ct.setup_internals();
 | 
				
			||||||
 | 
							ct.setup_stdcells();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::set<RTLIL::Cell*> queue, covered;
 | 
				
			||||||
 | 
							queue.insert(cell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							while (!queue.empty())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::set<RTLIL::Cell*> new_queue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (auto c : queue) {
 | 
				
			||||||
 | 
									if (!ct.cell_known(c->type))
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									for (auto &conn : c->connections())
 | 
				
			||||||
 | 
										if (ct.cell_input(c->type, conn.first))
 | 
				
			||||||
 | 
											for (auto bit : conn.second)
 | 
				
			||||||
 | 
												for (auto &pi : mi.query_ports(bit))
 | 
				
			||||||
 | 
													if (ct.cell_known(pi.cell->type) && ct.cell_output(pi.cell->type, pi.port))
 | 
				
			||||||
 | 
														new_queue.insert(pi.cell);
 | 
				
			||||||
 | 
									covered.insert(c);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								queue.clear();
 | 
				
			||||||
 | 
								for (auto c : new_queue) {
 | 
				
			||||||
 | 
									if (cells_to_remove.count(c))
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									if (c == cell)
 | 
				
			||||||
 | 
										return true;
 | 
				
			||||||
 | 
									if (!covered.count(c))
 | 
				
			||||||
 | 
										queue.insert(c);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// -------------
 | 
						// -------------
 | 
				
			||||||
	// Setup and run
 | 
						// Setup and run
 | 
				
			||||||
	// -------------
 | 
						// -------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ShareWorker(ShareWorkerConfig config, RTLIL::Design *design, RTLIL::Module *module) :
 | 
						ShareWorker(ShareWorkerConfig config, RTLIL::Design *design, RTLIL::Module *module) :
 | 
				
			||||||
			config(config), design(design), module(module)
 | 
								config(config), design(design), module(module), mi(module)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		bool before_scc = module_has_scc();
 | 
							bool before_scc = module_has_scc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -934,18 +989,37 @@ struct ShareWorker
 | 
				
			||||||
					other_cell_select_score += p.first.size();
 | 
										other_cell_select_score += p.first.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				RTLIL::Cell *supercell;
 | 
									RTLIL::Cell *supercell;
 | 
				
			||||||
 | 
									std::set<RTLIL::Cell*> supercell_aux;
 | 
				
			||||||
				if (cell_select_score <= other_cell_select_score) {
 | 
									if (cell_select_score <= other_cell_select_score) {
 | 
				
			||||||
					RTLIL::SigSpec act = make_cell_activation_logic(filtered_cell_activation_patterns);
 | 
										RTLIL::SigSpec act = make_cell_activation_logic(filtered_cell_activation_patterns, supercell_aux);
 | 
				
			||||||
					supercell = make_supercell(cell, other_cell, act);
 | 
										supercell = make_supercell(cell, other_cell, act, supercell_aux);
 | 
				
			||||||
					log("      Activation signal for %s: %s\n", log_id(cell), log_signal(act));
 | 
										log("      Activation signal for %s: %s\n", log_id(cell), log_signal(act));
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					RTLIL::SigSpec act = make_cell_activation_logic(filtered_other_cell_activation_patterns);
 | 
										RTLIL::SigSpec act = make_cell_activation_logic(filtered_other_cell_activation_patterns, supercell_aux);
 | 
				
			||||||
					supercell = make_supercell(other_cell, cell, act);
 | 
										supercell = make_supercell(other_cell, cell, act, supercell_aux);
 | 
				
			||||||
					log("      Activation signal for %s: %s\n", log_id(other_cell), log_signal(act));
 | 
										log("      Activation signal for %s: %s\n", log_id(other_cell), log_signal(act));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				log("      New cell: %s (%s)\n", log_id(supercell), log_id(supercell->type));
 | 
									log("      New cell: %s (%s)\n", log_id(supercell), log_id(supercell->type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									cells_to_remove.insert(cell);
 | 
				
			||||||
 | 
									cells_to_remove.insert(other_cell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									for (auto c : supercell_aux)
 | 
				
			||||||
 | 
										if (is_part_of_scc(c))
 | 
				
			||||||
 | 
											goto do_rollback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (0) {
 | 
				
			||||||
 | 
								do_rollback:
 | 
				
			||||||
 | 
										log("      New topology contains loops! Rolling back..\n");
 | 
				
			||||||
 | 
										cells_to_remove.erase(cell);
 | 
				
			||||||
 | 
										cells_to_remove.erase(other_cell);
 | 
				
			||||||
 | 
										shareable_cells.insert(other_cell);
 | 
				
			||||||
 | 
										for (auto cc : supercell_aux)
 | 
				
			||||||
 | 
											module->remove(cc);
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				std::set<std::pair<RTLIL::SigSpec, RTLIL::Const>> supercell_activation_patterns;
 | 
									std::set<std::pair<RTLIL::SigSpec, RTLIL::Const>> supercell_activation_patterns;
 | 
				
			||||||
				supercell_activation_patterns.insert(filtered_cell_activation_patterns.begin(), filtered_cell_activation_patterns.end());
 | 
									supercell_activation_patterns.insert(filtered_cell_activation_patterns.begin(), filtered_cell_activation_patterns.end());
 | 
				
			||||||
				supercell_activation_patterns.insert(filtered_other_cell_activation_patterns.begin(), filtered_other_cell_activation_patterns.end());
 | 
									supercell_activation_patterns.insert(filtered_other_cell_activation_patterns.begin(), filtered_other_cell_activation_patterns.end());
 | 
				
			||||||
| 
						 | 
					@ -953,9 +1027,6 @@ struct ShareWorker
 | 
				
			||||||
				activation_patterns_cache[supercell] = supercell_activation_patterns;
 | 
									activation_patterns_cache[supercell] = supercell_activation_patterns;
 | 
				
			||||||
				shareable_cells.insert(supercell);
 | 
									shareable_cells.insert(supercell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				cells_to_remove.insert(cell);
 | 
					 | 
				
			||||||
				cells_to_remove.insert(other_cell);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				for (auto bit : topo_sigmap(all_ctrl_signals))
 | 
									for (auto bit : topo_sigmap(all_ctrl_signals))
 | 
				
			||||||
					for (auto c : topo_bit_drivers[bit])
 | 
										for (auto c : topo_bit_drivers[bit])
 | 
				
			||||||
						topo_cell_drivers[supercell].insert(c);
 | 
											topo_cell_drivers[supercell].insert(c);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue