mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	Improve Verific SVA importer
This commit is contained in:
		
							parent
							
								
									649bb9374f
								
							
						
					
					
						commit
						147ff96ba3
					
				
					 1 changed files with 58 additions and 37 deletions
				
			
		| 
						 | 
					@ -1140,9 +1140,6 @@ struct VerificSvaImporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SigBit disable_iff = State::S0;
 | 
						SigBit disable_iff = State::S0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool import_sva_disable_hiactive = true;
 | 
					 | 
				
			||||||
	int import_sva_init_disable_steps = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool mode_assert = false;
 | 
						bool mode_assert = false;
 | 
				
			||||||
	bool mode_assume = false;
 | 
						bool mode_assume = false;
 | 
				
			||||||
	bool mode_cover = false;
 | 
						bool mode_cover = false;
 | 
				
			||||||
| 
						 | 
					@ -1173,18 +1170,65 @@ struct VerificSvaImporter
 | 
				
			||||||
	Instance *get_ast_input3(Instance *inst) { return net_to_ast_driver(inst->GetInput3()); }
 | 
						Instance *get_ast_input3(Instance *inst) { return net_to_ast_driver(inst->GetInput3()); }
 | 
				
			||||||
	Instance *get_ast_control(Instance *inst) { return net_to_ast_driver(inst->GetControl()); }
 | 
						Instance *get_ast_control(Instance *inst) { return net_to_ast_driver(inst->GetControl()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SigBit parse_sequence(Net *n)
 | 
						struct sequence_t {
 | 
				
			||||||
 | 
							int length = 0;
 | 
				
			||||||
 | 
							SigBit sig_a = State::S1;
 | 
				
			||||||
 | 
							SigBit sig_en = State::S1;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void sequence_cond(sequence_t &seq, SigBit cond)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							seq.sig_a = module->And(NEW_ID, seq.sig_a, cond);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void sequence_ff(sequence_t &seq)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (disable_iff != State::S0)
 | 
				
			||||||
 | 
								seq.sig_en = module->Mux(NEW_ID, seq.sig_en, State::S0, disable_iff);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Wire *sig_a_q = module->addWire(NEW_ID);
 | 
				
			||||||
 | 
							sig_a_q->attributes["\\init"] = Const(0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Wire *sig_en_q = module->addWire(NEW_ID);
 | 
				
			||||||
 | 
							sig_en_q->attributes["\\init"] = Const(0, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							module->addDff(NEW_ID, clock, seq.sig_a, sig_a_q, clock_posedge);
 | 
				
			||||||
 | 
							module->addDff(NEW_ID, clock, seq.sig_en, sig_en_q, clock_posedge);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							seq.length++;
 | 
				
			||||||
 | 
							seq.sig_a = sig_a_q;
 | 
				
			||||||
 | 
							seq.sig_en = sig_en_q;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void parse_sequence(sequence_t &seq, Net *n)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Instance *inst = net_to_ast_driver(n);
 | 
							Instance *inst = net_to_ast_driver(n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (inst == nullptr)
 | 
							if (inst == nullptr) {
 | 
				
			||||||
			return importer->net_map_at(n);
 | 
								sequence_cond(seq, importer->net_map_at(n));
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (inst->Type() == PRIM_SVA_OVERLAPPED_IMPLICATION)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								parse_sequence(seq, inst->GetInput1());
 | 
				
			||||||
 | 
								seq.sig_en = module->And(NEW_ID, seq.sig_en, seq.sig_a);
 | 
				
			||||||
 | 
								parse_sequence(seq, inst->GetInput2());
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (inst->Type() == PRIM_SVA_NON_OVERLAPPED_IMPLICATION)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								parse_sequence(seq, inst->GetInput1());
 | 
				
			||||||
 | 
								seq.sig_en = module->And(NEW_ID, seq.sig_en, seq.sig_a);
 | 
				
			||||||
 | 
								sequence_ff(seq);
 | 
				
			||||||
 | 
								parse_sequence(seq, inst->GetInput2());
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!importer->mode_keep)
 | 
							if (!importer->mode_keep)
 | 
				
			||||||
			log_error("Unsupported Verific SVA primitive %s of type %s.\n", inst->Name(), inst->View()->Owner()->Name());
 | 
								log_error("Unsupported Verific SVA primitive %s of type %s.\n", inst->Name(), inst->View()->Owner()->Name());
 | 
				
			||||||
		log_warning("Unsupported Verific SVA primitive %s of type %s.\n", inst->Name(), inst->View()->Owner()->Name());
 | 
							log_warning("Unsupported Verific SVA primitive %s of type %s.\n", inst->Name(), inst->View()->Owner()->Name());
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return importer->net_map_at(n);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void run()
 | 
						void run()
 | 
				
			||||||
| 
						 | 
					@ -1203,8 +1247,6 @@ struct VerificSvaImporter
 | 
				
			||||||
		clock = importer->net_map_at(clock_node->GetInput());
 | 
							clock = importer->net_map_at(clock_node->GetInput());
 | 
				
			||||||
		clock_posedge = (clock_node->Type() == PRIM_SVA_POSEDGE);
 | 
							clock_posedge = (clock_node->Type() == PRIM_SVA_POSEDGE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		import_sva_init_disable_steps = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// parse disable_iff expression
 | 
							// parse disable_iff expression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Net *sequence_net = at_node->GetInput2();
 | 
							Net *sequence_net = at_node->GetInput2();
 | 
				
			||||||
| 
						 | 
					@ -1217,38 +1259,17 @@ struct VerificSvaImporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// parse SVA sequence into trigger signal
 | 
							// parse SVA sequence into trigger signal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SigBit sig_a_d = parse_sequence(sequence_net);
 | 
							sequence_t seq;
 | 
				
			||||||
		Wire *sig_a_q = module->addWire(NEW_ID);
 | 
							parse_sequence(seq, sequence_net);
 | 
				
			||||||
		sig_a_q->attributes["\\init"] = Const(import_sva_disable_hiactive ? State::S1 : State::S0, 1);
 | 
							sequence_ff(seq);
 | 
				
			||||||
		module->addDff(NEW_ID, clock, sig_a_d, sig_a_q, clock_posedge);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// generate properly delayed enable signal
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		SigBit sig_en = State::S1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (disable_iff != State::S0)
 | 
					 | 
				
			||||||
			sig_en = module->Mux(NEW_ID, sig_en, State::S0, disable_iff);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (int i = 0; i < import_sva_init_disable_steps; i++)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Wire *new_en = module->addWire(NEW_ID);
 | 
					 | 
				
			||||||
			new_en->attributes["\\init"] = Const(0, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			module->addDff(NEW_ID, clock, sig_en, new_en, clock_posedge);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (disable_iff != State::S0 && i+1 < import_sva_init_disable_steps)
 | 
					 | 
				
			||||||
				sig_en = module->Mux(NEW_ID, new_en, State::S0, disable_iff);
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				sig_en = new_en;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// generate assert/assume/cover cell
 | 
							// generate assert/assume/cover cell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		RTLIL::IdString root_name = module->uniquify(root->IsUserDeclared() ? RTLIL::escape_id(root->Name()) : NEW_ID);
 | 
							RTLIL::IdString root_name = module->uniquify(root->IsUserDeclared() ? RTLIL::escape_id(root->Name()) : NEW_ID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (mode_assert) module->addAssert(root_name, sig_a_q, sig_en);
 | 
							if (mode_assert) module->addAssert(root_name, seq.sig_a, seq.sig_en);
 | 
				
			||||||
		if (mode_assume) module->addAssume(root_name, sig_a_q, sig_en);
 | 
							if (mode_assume) module->addAssume(root_name, seq.sig_a, seq.sig_en);
 | 
				
			||||||
		if (mode_cover) module->addCover(root_name, sig_a_q, sig_en);
 | 
							if (mode_cover) module->addCover(root_name, seq.sig_a, seq.sig_en);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue