mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Fix "verific -extnets" for more complex situations
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
		
							parent
							
								
									ddc1a4488e
								
							
						
					
					
						commit
						c863796e9f
					
				
					 2 changed files with 93 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -1619,30 +1619,35 @@ struct VerificExtNets
 | 
			
		|||
	int portname_cnt = 0;
 | 
			
		||||
 | 
			
		||||
	// a map from Net to the same Net one level up in the design hierarchy
 | 
			
		||||
	std::map<Net*, Net*> net_level_up;
 | 
			
		||||
	std::map<Net*, Net*> net_level_up_drive_up;
 | 
			
		||||
	std::map<Net*, Net*> net_level_up_drive_down;
 | 
			
		||||
 | 
			
		||||
	Net *get_net_level_up(Net *net)
 | 
			
		||||
	Net *route_up(Net *net, bool drive_up, Net *final_net = nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		auto &net_level_up = drive_up ? net_level_up_drive_up : net_level_up_drive_down;
 | 
			
		||||
 | 
			
		||||
		if (net_level_up.count(net) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			Netlist *nl = net->Owner();
 | 
			
		||||
 | 
			
		||||
			// Simply return if Netlist is not unique
 | 
			
		||||
			if (nl->NumOfRefs() != 1)
 | 
			
		||||
				return net;
 | 
			
		||||
			log_assert(nl->NumOfRefs() == 1);
 | 
			
		||||
 | 
			
		||||
			Instance *up_inst = (Instance*)nl->GetReferences()->GetLast();
 | 
			
		||||
			Netlist *up_nl = up_inst->Owner();
 | 
			
		||||
 | 
			
		||||
			// create new Port
 | 
			
		||||
			string name = stringf("___extnets_%d", portname_cnt++);
 | 
			
		||||
			Port *new_port = new Port(name.c_str(), DIR_OUT);
 | 
			
		||||
			Port *new_port = new Port(name.c_str(), drive_up ? DIR_OUT : DIR_IN);
 | 
			
		||||
			nl->Add(new_port);
 | 
			
		||||
			net->Connect(new_port);
 | 
			
		||||
 | 
			
		||||
			// create new Net in up Netlist
 | 
			
		||||
			Net *new_net = new Net(name.c_str());
 | 
			
		||||
			up_nl->Add(new_net);
 | 
			
		||||
			Net *new_net = final_net;
 | 
			
		||||
			if (new_net == nullptr || new_net->Owner() != up_nl) {
 | 
			
		||||
				new_net = new Net(name.c_str());
 | 
			
		||||
				up_nl->Add(new_net);
 | 
			
		||||
			}
 | 
			
		||||
			up_inst->Connect(new_port, new_net);
 | 
			
		||||
 | 
			
		||||
			net_level_up[net] = new_net;
 | 
			
		||||
| 
						 | 
				
			
			@ -1651,6 +1656,39 @@ struct VerificExtNets
 | 
			
		|||
		return net_level_up.at(net);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Net *route_up(Net *net, bool drive_up, Netlist *dest, Net *final_net = nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		while (net->Owner() != dest)
 | 
			
		||||
			net = route_up(net, drive_up, final_net);
 | 
			
		||||
		if (final_net != nullptr)
 | 
			
		||||
			log_assert(net == final_net);
 | 
			
		||||
		return net;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Netlist *find_common_ancestor(Netlist *A, Netlist *B)
 | 
			
		||||
	{
 | 
			
		||||
		std::set<Netlist*> ancestors_of_A;
 | 
			
		||||
 | 
			
		||||
		Netlist *cursor = A;
 | 
			
		||||
		while (1) {
 | 
			
		||||
			ancestors_of_A.insert(cursor);
 | 
			
		||||
			if (cursor->NumOfRefs() != 1)
 | 
			
		||||
				break;
 | 
			
		||||
			cursor = ((Instance*)cursor->GetReferences()->GetLast())->Owner();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cursor = B;
 | 
			
		||||
		while (1) {
 | 
			
		||||
			if (ancestors_of_A.count(cursor))
 | 
			
		||||
				return cursor;
 | 
			
		||||
			if (cursor->NumOfRefs() != 1)
 | 
			
		||||
				break;
 | 
			
		||||
			cursor = ((Instance*)cursor->GetReferences()->GetLast())->Owner();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log_error("No common ancestor found between %s and %s.\n", get_full_netlist_name(A).c_str(), get_full_netlist_name(B).c_str());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void run(Netlist *nl)
 | 
			
		||||
	{
 | 
			
		||||
		MapIter mi, mi2;
 | 
			
		||||
| 
						 | 
				
			
			@ -1674,19 +1712,37 @@ struct VerificExtNets
 | 
			
		|||
			if (verific_verbose)
 | 
			
		||||
				log("Fixing external net reference on port %s.%s.%s:\n", get_full_netlist_name(nl).c_str(), inst->Name(), port->Name());
 | 
			
		||||
 | 
			
		||||
			while (net->IsExternalTo(nl))
 | 
			
		||||
			{
 | 
			
		||||
				Net *newnet = get_net_level_up(net);
 | 
			
		||||
				if (newnet == net) break;
 | 
			
		||||
			Netlist *ext_nl = net->Owner();
 | 
			
		||||
 | 
			
		||||
			if (verific_verbose)
 | 
			
		||||
				log(" external net owner: %s\n", get_full_netlist_name(ext_nl).c_str());
 | 
			
		||||
 | 
			
		||||
			Netlist *ca_nl = find_common_ancestor(nl, ext_nl);
 | 
			
		||||
 | 
			
		||||
			if (verific_verbose)
 | 
			
		||||
				log(" common ancestor: %s\n", get_full_netlist_name(ca_nl).c_str());
 | 
			
		||||
 | 
			
		||||
			Net *ca_net = route_up(net, !port->IsOutput(), ca_nl);
 | 
			
		||||
			Net *new_net = ca_net;
 | 
			
		||||
 | 
			
		||||
			if (ca_nl != nl)
 | 
			
		||||
			{
 | 
			
		||||
				if (verific_verbose)
 | 
			
		||||
					log("  external net: %s.%s\n", get_full_netlist_name(net->Owner()).c_str(), net->Name());
 | 
			
		||||
				net = newnet;
 | 
			
		||||
					log(" net in common ancestor: %s\n", ca_net->Name());
 | 
			
		||||
 | 
			
		||||
				string name = stringf("___extnets_%d", portname_cnt++);
 | 
			
		||||
				new_net = new Net(name.c_str());
 | 
			
		||||
				nl->Add(new_net);
 | 
			
		||||
 | 
			
		||||
				Net *n = route_up(new_net, port->IsOutput(), ca_nl, ca_net);
 | 
			
		||||
				log_assert(n == ca_net);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (verific_verbose)
 | 
			
		||||
				log("  final net: %s.%s%s\n", get_full_netlist_name(net->Owner()).c_str(), net->Name(), net->IsExternalTo(nl) ? " (external)" : "");
 | 
			
		||||
			todo_connect.push_back(tuple<Instance*, Port*, Net*>(inst, port, net));
 | 
			
		||||
				log(" new local net: %s\n", new_net->Name());
 | 
			
		||||
 | 
			
		||||
			log_assert(!new_net->IsExternalTo(nl));
 | 
			
		||||
			todo_connect.push_back(tuple<Instance*, Port*, Net*>(inst, port, new_net));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto it : todo_connect) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue