mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Merge https://github.com/YosysHQ/yosys into read_aiger
This commit is contained in:
		
						commit
						02e8dc7ad2
					
				
					 113 changed files with 6374 additions and 802 deletions
				
			
		| 
						 | 
				
			
			@ -214,6 +214,8 @@ namespace AST
 | 
			
		|||
			MEM2REG_FL_SET_ASYNC = 0x00000800,
 | 
			
		||||
			MEM2REG_FL_EQ2       = 0x00001000,
 | 
			
		||||
			MEM2REG_FL_CMPLX_LHS = 0x00002000,
 | 
			
		||||
			MEM2REG_FL_CONST_LHS = 0x00004000,
 | 
			
		||||
			MEM2REG_FL_VAR_LHS   = 0x00008000,
 | 
			
		||||
 | 
			
		||||
			/* proc flags */
 | 
			
		||||
			MEM2REG_FL_EQ1       = 0x01000000,
 | 
			
		||||
| 
						 | 
				
			
			@ -237,6 +239,7 @@ namespace AST
 | 
			
		|||
		bool has_const_only_constructs(bool &recommend_const_eval);
 | 
			
		||||
		void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
 | 
			
		||||
		AstNode *eval_const_function(AstNode *fcall);
 | 
			
		||||
		bool is_simple_const_expr();
 | 
			
		||||
 | 
			
		||||
		// create a human-readable text representation of the AST (for debugging)
 | 
			
		||||
		void dumpAst(FILE *f, std::string indent) const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -525,7 +525,16 @@ struct AST_INTERNAL::ProcessGenerator
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
				if (last_generated_case != NULL && ast->get_bool_attribute("\\full_case") && default_case == NULL) {
 | 
			
		||||
			#if 0
 | 
			
		||||
					// this is a valid transformation, but as optimization it is premature.
 | 
			
		||||
					// better: add a default case that assigns 'x' to everything, and let later
 | 
			
		||||
					// optimizations take care of the rest
 | 
			
		||||
					last_generated_case->compare.clear();
 | 
			
		||||
			#else
 | 
			
		||||
					default_case = new RTLIL::CaseRule;
 | 
			
		||||
					addChunkActions(default_case->actions, this_case_eq_ltemp, SigSpec(State::Sx, GetSize(this_case_eq_rvalue)));
 | 
			
		||||
					sw->cases.push_back(default_case);
 | 
			
		||||
			#endif
 | 
			
		||||
				} else {
 | 
			
		||||
					if (default_case == NULL) {
 | 
			
		||||
						default_case = new RTLIL::CaseRule;
 | 
			
		||||
| 
						 | 
				
			
			@ -544,7 +553,11 @@ struct AST_INTERNAL::ProcessGenerator
 | 
			
		|||
			break;
 | 
			
		||||
 | 
			
		||||
		case AST_WIRE:
 | 
			
		||||
			log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n");
 | 
			
		||||
			log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n");
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case AST_ASSIGN:
 | 
			
		||||
			log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n");
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case AST_PARAMETER:
 | 
			
		||||
| 
						 | 
				
			
			@ -644,7 +657,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
 | 
			
		|||
				while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
 | 
			
		||||
				if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
 | 
			
		||||
					log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
 | 
			
		||||
				this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
 | 
			
		||||
				this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
 | 
			
		||||
				delete left_at_zero_ast;
 | 
			
		||||
				delete right_at_zero_ast;
 | 
			
		||||
			} else
 | 
			
		||||
| 
						 | 
				
			
			@ -792,7 +805,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
 | 
			
		|||
	// everything should have been handled above -> print error if not.
 | 
			
		||||
	default:
 | 
			
		||||
		for (auto f : log_files)
 | 
			
		||||
			current_ast->dumpAst(f, "verilog-ast> ");
 | 
			
		||||
			current_ast_mod->dumpAst(f, "verilog-ast> ");
 | 
			
		||||
		log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1034,7 +1047,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
			
		|||
					while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
 | 
			
		||||
					if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
 | 
			
		||||
						log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
 | 
			
		||||
					int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
 | 
			
		||||
					int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
 | 
			
		||||
					AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
 | 
			
		||||
							children[0]->children[1]->clone() : children[0]->children[0]->clone());
 | 
			
		||||
					fake_ast->children[0]->delete_children();
 | 
			
		||||
| 
						 | 
				
			
			@ -1409,10 +1422,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
			
		|||
			if (GetSize(en) != 1)
 | 
			
		||||
				en = current_module->ReduceBool(NEW_ID, en);
 | 
			
		||||
 | 
			
		||||
			std::stringstream sstr;
 | 
			
		||||
			sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++);
 | 
			
		||||
			IdString cellname;
 | 
			
		||||
			if (str.empty()) {
 | 
			
		||||
				std::stringstream sstr;
 | 
			
		||||
				sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++);
 | 
			
		||||
				cellname = sstr.str();
 | 
			
		||||
			} else {
 | 
			
		||||
				cellname = str;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *cell = current_module->addCell(sstr.str(), celltype);
 | 
			
		||||
			RTLIL::Cell *cell = current_module->addCell(cellname, celltype);
 | 
			
		||||
			cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
 | 
			
		||||
 | 
			
		||||
			for (auto &attr : attributes) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1565,7 +1584,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
			
		|||
	// everything should have been handled above -> print error if not.
 | 
			
		||||
	default:
 | 
			
		||||
		for (auto f : log_files)
 | 
			
		||||
			current_ast->dumpAst(f, "verilog-ast> ");
 | 
			
		||||
			current_ast_mod->dumpAst(f, "verilog-ast> ");
 | 
			
		||||
		type_name = type2str(type);
 | 
			
		||||
		log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str());
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,6 @@ using namespace AST_INTERNAL;
 | 
			
		|||
bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
 | 
			
		||||
{
 | 
			
		||||
	static int recursion_counter = 0;
 | 
			
		||||
	static pair<string, int> last_blocking_assignment_warn;
 | 
			
		||||
	static bool deep_recursion_warning = false;
 | 
			
		||||
 | 
			
		||||
	if (recursion_counter++ == 1000 && deep_recursion_warning) {
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +71,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
	if (stage == 0)
 | 
			
		||||
	{
 | 
			
		||||
		log_assert(type == AST_MODULE || type == AST_INTERFACE);
 | 
			
		||||
		last_blocking_assignment_warn = pair<string, int>();
 | 
			
		||||
 | 
			
		||||
		deep_recursion_warning = true;
 | 
			
		||||
		while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { }
 | 
			
		||||
| 
						 | 
				
			
			@ -113,6 +111,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
				if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)
 | 
			
		||||
					goto verbose_activate;
 | 
			
		||||
 | 
			
		||||
				if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS))
 | 
			
		||||
					goto verbose_activate;
 | 
			
		||||
 | 
			
		||||
				// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -325,6 +326,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
		for (size_t i = 0; i < children.size(); i++) {
 | 
			
		||||
			AstNode *node = children[i];
 | 
			
		||||
			if (node->type == AST_WIRE) {
 | 
			
		||||
				if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
 | 
			
		||||
					for (auto c : node->children[0]->children) {
 | 
			
		||||
						if (!c->is_simple_const_expr()) {
 | 
			
		||||
							if (attributes.count("\\dynports"))
 | 
			
		||||
								delete attributes.at("\\dynports");
 | 
			
		||||
							attributes["\\dynports"] = AstNode::mkconst_int(1, true);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if (this_wire_scope.count(node->str) > 0) {
 | 
			
		||||
					AstNode *first_node = this_wire_scope[node->str];
 | 
			
		||||
					if (first_node->is_input && node->is_reg)
 | 
			
		||||
| 
						 | 
				
			
			@ -642,6 +652,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
	// (iterate by index as e.g. auto wires can add new children in the process)
 | 
			
		||||
	for (size_t i = 0; i < children.size(); i++) {
 | 
			
		||||
		bool did_something_here = true;
 | 
			
		||||
		bool backup_flag_autowire = flag_autowire;
 | 
			
		||||
		if ((type == AST_GENFOR || type == AST_FOR) && i >= 3)
 | 
			
		||||
			break;
 | 
			
		||||
		if ((type == AST_GENIF || type == AST_GENCASE) && i >= 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -652,6 +663,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
			break;
 | 
			
		||||
		if (type == AST_PREFIX && i >= 1)
 | 
			
		||||
			break;
 | 
			
		||||
		if (type == AST_DEFPARAM && i == 0)
 | 
			
		||||
			flag_autowire = true;
 | 
			
		||||
		while (did_something_here && i < children.size()) {
 | 
			
		||||
			bool const_fold_here = const_fold, in_lvalue_here = in_lvalue;
 | 
			
		||||
			int width_hint_here = width_hint;
 | 
			
		||||
| 
						 | 
				
			
			@ -686,6 +699,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
			children.erase(children.begin() + (i--));
 | 
			
		||||
			did_something = true;
 | 
			
		||||
		}
 | 
			
		||||
		flag_autowire = backup_flag_autowire;
 | 
			
		||||
	}
 | 
			
		||||
	for (auto &attr : attributes) {
 | 
			
		||||
		while (attr.second->simplify(true, false, false, stage, -1, false, true))
 | 
			
		||||
| 
						 | 
				
			
			@ -934,12 +948,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (current_scope.count(str) == 0) {
 | 
			
		||||
			// log_warning("Creating auto-wire `%s' in module `%s'.\n", str.c_str(), current_ast_mod->str.c_str());
 | 
			
		||||
			AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
 | 
			
		||||
			auto_wire->str = str;
 | 
			
		||||
			current_ast_mod->children.push_back(auto_wire);
 | 
			
		||||
			current_scope[str] = auto_wire;
 | 
			
		||||
			did_something = true;
 | 
			
		||||
			if (flag_autowire || str == "\\$global_clock") {
 | 
			
		||||
				AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
 | 
			
		||||
				auto_wire->str = str;
 | 
			
		||||
				current_ast_mod->children.push_back(auto_wire);
 | 
			
		||||
				current_scope[str] = auto_wire;
 | 
			
		||||
				did_something = true;
 | 
			
		||||
			} else {
 | 
			
		||||
				log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (id2ast != current_scope[str]) {
 | 
			
		||||
			id2ast = current_scope[str];
 | 
			
		||||
| 
						 | 
				
			
			@ -1492,6 +1509,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
		newNode->children.push_back(assign_en);
 | 
			
		||||
 | 
			
		||||
		AstNode *assertnode = new AstNode(type);
 | 
			
		||||
		assertnode->str = str;
 | 
			
		||||
		assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
 | 
			
		||||
		assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
 | 
			
		||||
		assertnode->children[0]->str = id_check;
 | 
			
		||||
| 
						 | 
				
			
			@ -1572,14 +1590,6 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
		sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
 | 
			
		||||
		std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
 | 
			
		||||
 | 
			
		||||
		if (type == AST_ASSIGN_EQ) {
 | 
			
		||||
			pair<string, int> this_blocking_assignment_warn(filename, linenum);
 | 
			
		||||
			if (this_blocking_assignment_warn != last_blocking_assignment_warn)
 | 
			
		||||
				log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n",
 | 
			
		||||
						filename.c_str(), linenum);
 | 
			
		||||
			last_blocking_assignment_warn = this_blocking_assignment_warn;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		int mem_width, mem_size, addr_bits;
 | 
			
		||||
		bool mem_signed = children[0]->id2ast->is_signed;
 | 
			
		||||
		children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
 | 
			
		||||
| 
						 | 
				
			
			@ -1689,7 +1699,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
				while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
 | 
			
		||||
				if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
 | 
			
		||||
					log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
 | 
			
		||||
				int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
 | 
			
		||||
				int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
 | 
			
		||||
 | 
			
		||||
				assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
 | 
			
		||||
						new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone()));
 | 
			
		||||
| 
						 | 
				
			
			@ -1778,7 +1788,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
 | 
			
		||||
			if (str == "\\$past")
 | 
			
		||||
			{
 | 
			
		||||
				if (width_hint <= 0)
 | 
			
		||||
				if (width_hint < 0)
 | 
			
		||||
					goto replace_fcall_later;
 | 
			
		||||
 | 
			
		||||
				int num_steps = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -2162,6 +2172,8 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
				newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init);
 | 
			
		||||
				delete node_filename;
 | 
			
		||||
				delete node_memory;
 | 
			
		||||
				goto apply_newNode;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2203,6 +2215,8 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
		std::map<std::string, std::string> replace_rules;
 | 
			
		||||
		vector<AstNode*> added_mod_children;
 | 
			
		||||
		dict<std::string, AstNode*> wire_cache;
 | 
			
		||||
		vector<AstNode*> new_stmts;
 | 
			
		||||
		vector<AstNode*> output_assignments;
 | 
			
		||||
 | 
			
		||||
		if (current_block == NULL)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -2327,8 +2341,8 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
					wire->port_id = 0;
 | 
			
		||||
					wire->is_input = false;
 | 
			
		||||
					wire->is_output = false;
 | 
			
		||||
					if (!child->is_output)
 | 
			
		||||
						wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
 | 
			
		||||
					wire->is_reg = true;
 | 
			
		||||
					wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
 | 
			
		||||
					wire_cache[child->str] = wire;
 | 
			
		||||
 | 
			
		||||
					current_ast_mod->children.push_back(wire);
 | 
			
		||||
| 
						 | 
				
			
			@ -2350,13 +2364,10 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
							new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
 | 
			
		||||
							new AstNode(AST_ASSIGN_EQ, arg, wire_id);
 | 
			
		||||
					assign->children[0]->was_checked = true;
 | 
			
		||||
 | 
			
		||||
					for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
 | 
			
		||||
						if (*it != current_block_child)
 | 
			
		||||
							continue;
 | 
			
		||||
						current_block->children.insert(it, assign);
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					if (child->is_input)
 | 
			
		||||
						new_stmts.push_back(assign);
 | 
			
		||||
					else
 | 
			
		||||
						output_assignments.push_back(assign);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2370,15 +2381,19 @@ skip_dynamic_range_lvalue_expansion:;
 | 
			
		|||
			{
 | 
			
		||||
				AstNode *stmt = child->clone();
 | 
			
		||||
				stmt->replace_ids(prefix, replace_rules);
 | 
			
		||||
 | 
			
		||||
				for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
 | 
			
		||||
					if (*it != current_block_child)
 | 
			
		||||
						continue;
 | 
			
		||||
					current_block->children.insert(it, stmt);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				new_stmts.push_back(stmt);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end());
 | 
			
		||||
 | 
			
		||||
		for (auto it = current_block->children.begin(); ; it++) {
 | 
			
		||||
			log_assert(it != current_block->children.end());
 | 
			
		||||
			if (*it == current_block_child) {
 | 
			
		||||
				current_block->children.insert(it, new_stmts.begin(), new_stmts.end());
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	replace_fcall_with_id:
 | 
			
		||||
		if (type == AST_FCALL) {
 | 
			
		||||
			delete_children();
 | 
			
		||||
| 
						 | 
				
			
			@ -2848,7 +2863,11 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
 | 
			
		|||
 | 
			
		||||
	for (size_t i = 0; i < children.size(); i++) {
 | 
			
		||||
		AstNode *child = children[i];
 | 
			
		||||
		if (child->type != AST_FUNCTION && child->type != AST_TASK && child->type != AST_PREFIX)
 | 
			
		||||
		// AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
 | 
			
		||||
		// still needs to recursed-into
 | 
			
		||||
		if (type == AST_PREFIX && i == 1 && child->type == AST_IDENTIFIER)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (child->type != AST_FUNCTION && child->type != AST_TASK)
 | 
			
		||||
			child->expand_genblock(index_var, prefix, name_map);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2903,7 +2922,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
 | 
			
		|||
		dict<AstNode*, uint32_t> &mem2reg_candidates, dict<AstNode*, uint32_t> &proc_flags, uint32_t &flags)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t children_flags = 0;
 | 
			
		||||
	int ignore_children_counter = 0;
 | 
			
		||||
	int lhs_children_counter = 0;
 | 
			
		||||
 | 
			
		||||
	if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -2929,6 +2948,16 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
 | 
			
		|||
				proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// for proper (non-init) writes: remember if this is a constant index or not
 | 
			
		||||
			if ((flags & MEM2REG_FL_INIT) == 0) {
 | 
			
		||||
				if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) {
 | 
			
		||||
					if (children[0]->children[0]->children[0]->type == AST_CONSTANT)
 | 
			
		||||
						mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS;
 | 
			
		||||
					else
 | 
			
		||||
						mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// remember where this is
 | 
			
		||||
			if (flags & MEM2REG_FL_INIT) {
 | 
			
		||||
				if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
 | 
			
		||||
| 
						 | 
				
			
			@ -2941,7 +2970,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ignore_children_counter = 1;
 | 
			
		||||
		lhs_children_counter = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY)
 | 
			
		||||
| 
						 | 
				
			
			@ -2984,12 +3013,23 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
 | 
			
		|||
	log_assert((flags & ~0x000000ff) == 0);
 | 
			
		||||
 | 
			
		||||
	for (auto child : children)
 | 
			
		||||
		if (ignore_children_counter > 0)
 | 
			
		||||
			ignore_children_counter--;
 | 
			
		||||
		else if (proc_flags_p)
 | 
			
		||||
	{
 | 
			
		||||
		if (lhs_children_counter > 0) {
 | 
			
		||||
			lhs_children_counter--;
 | 
			
		||||
			if (child->children.size() && child->children[0]->type == AST_RANGE && child->children[0]->children.size()) {
 | 
			
		||||
				for (auto c : child->children[0]->children) {
 | 
			
		||||
					if (proc_flags_p)
 | 
			
		||||
						c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
 | 
			
		||||
					else
 | 
			
		||||
						c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else
 | 
			
		||||
		if (proc_flags_p)
 | 
			
		||||
			child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
 | 
			
		||||
		else
 | 
			
		||||
			child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	flags &= ~children_flags | backup_flags;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3041,6 +3081,39 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
 | 
			
		|||
	if (type == AST_FUNCTION || type == AST_TASK)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))
 | 
			
		||||
	{
 | 
			
		||||
		log_assert(children[0]->type == AST_CONSTANT);
 | 
			
		||||
		log_assert(children[1]->type == AST_CONSTANT);
 | 
			
		||||
		log_assert(children[2]->type == AST_CONSTANT);
 | 
			
		||||
 | 
			
		||||
		int cursor = children[0]->asInt(false);
 | 
			
		||||
		Const data = children[1]->bitsAsConst();
 | 
			
		||||
		int length = children[2]->asInt(false);
 | 
			
		||||
 | 
			
		||||
		if (length != 0)
 | 
			
		||||
		{
 | 
			
		||||
			AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK));
 | 
			
		||||
			mod->children.push_back(block);
 | 
			
		||||
			block = block->children[0];
 | 
			
		||||
 | 
			
		||||
			int wordsz = GetSize(data) / length;
 | 
			
		||||
 | 
			
		||||
			for (int i = 0; i < length; i++) {
 | 
			
		||||
				block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false)));
 | 
			
		||||
				block->children.back()->children[0]->str = str;
 | 
			
		||||
				block->children.back()->children[0]->id2ast = id2ast;
 | 
			
		||||
				block->children.back()->children[0]->was_checked = true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		AstNode *newNode = new AstNode(AST_NONE);
 | 
			
		||||
		newNode->cloneInto(this);
 | 
			
		||||
		delete newNode;
 | 
			
		||||
 | 
			
		||||
		did_something = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))
 | 
			
		||||
	{
 | 
			
		||||
		if (async_block == NULL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -3270,6 +3343,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
 | 
			
		|||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool AstNode::is_simple_const_expr()
 | 
			
		||||
{
 | 
			
		||||
	if (type == AST_IDENTIFIER)
 | 
			
		||||
		return false;
 | 
			
		||||
	for (auto child : children)
 | 
			
		||||
		if (!child->is_simple_const_expr())
 | 
			
		||||
			return false;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// helper function for AstNode::eval_const_function()
 | 
			
		||||
void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ Then run in the following command in this directory:
 | 
			
		|||
 | 
			
		||||
	sby -f example.sby
 | 
			
		||||
 | 
			
		||||
This will generate approximately one page of text outpout. The last lines
 | 
			
		||||
This will generate approximately one page of text output. The last lines
 | 
			
		||||
should be something like this:
 | 
			
		||||
 | 
			
		||||
	SBY [example] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1855,6 +1855,13 @@ struct VerificPass : public Pass {
 | 
			
		|||
		log("  -autocover\n");
 | 
			
		||||
		log("    Generate automatic cover statements for all asserts\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("  -chparam name value \n");
 | 
			
		||||
		log("    Elaborate the specified top modules (all modules when -all given) using\n");
 | 
			
		||||
		log("    this parameter value. Modules on which this parameter does not exist will\n");
 | 
			
		||||
		log("    cause Verific to produce a VERI-1928 or VHDL-1676 message. This option\n");
 | 
			
		||||
		log("    can be specified multiple times to override multiple parameters.\n");
 | 
			
		||||
		log("    String values must be passed in double quotes (\").\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("  -v, -vv\n");
 | 
			
		||||
		log("    Verbose log messages. (-vv is even more verbose than -v.)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -1920,6 +1927,10 @@ struct VerificPass : public Pass {
 | 
			
		|||
			// WARNING: instantiating unknown module 'XYZ' (VERI-1063)
 | 
			
		||||
			Message::SetMessageType("VERI-1063", VERIFIC_ERROR);
 | 
			
		||||
 | 
			
		||||
#ifndef DB_PRESERVE_INITIAL_VALUE
 | 
			
		||||
#  warning Verific was built without DB_PRESERVE_INITIAL_VALUE.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			set_verific_global_flags = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2105,6 +2116,7 @@ struct VerificPass : public Pass {
 | 
			
		|||
			bool mode_autocover = false;
 | 
			
		||||
			bool flatten = false, extnets = false;
 | 
			
		||||
			string dumpfile;
 | 
			
		||||
			Map parameters(STRING_HASH);
 | 
			
		||||
 | 
			
		||||
			for (argidx++; argidx < GetSize(args); argidx++) {
 | 
			
		||||
				if (args[argidx] == "-all") {
 | 
			
		||||
| 
						 | 
				
			
			@ -2143,6 +2155,15 @@ struct VerificPass : public Pass {
 | 
			
		|||
					mode_autocover = true;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (args[argidx] == "-chparam"  && argidx+2 < GetSize(args)) {
 | 
			
		||||
                                        const std::string &key = args[++argidx];
 | 
			
		||||
                                        const std::string &value = args[++argidx];
 | 
			
		||||
					unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(),
 | 
			
		||||
									           1 /* force_overwrite */);
 | 
			
		||||
					if (!new_insertion)
 | 
			
		||||
						log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str());
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (args[argidx] == "-V") {
 | 
			
		||||
					mode_verific = true;
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -2176,7 +2197,7 @@ struct VerificPass : public Pass {
 | 
			
		|||
				if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
 | 
			
		||||
				if (veri_lib) veri_libs.InsertLast(veri_lib);
 | 
			
		||||
 | 
			
		||||
				Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs);
 | 
			
		||||
				Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, ¶meters);
 | 
			
		||||
				Netlist *nl;
 | 
			
		||||
				int i;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2213,7 +2234,7 @@ struct VerificPass : public Pass {
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
				log("Running hier_tree::Elaborate().\n");
 | 
			
		||||
				Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units);
 | 
			
		||||
				Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units, ¶meters);
 | 
			
		||||
				Netlist *nl;
 | 
			
		||||
				int i;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2312,7 +2333,7 @@ struct ReadPass : public Pass {
 | 
			
		|||
	}
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		if (args.size() < 2)
 | 
			
		||||
		if (args.size() < 2 || args[1][0] != '-')
 | 
			
		||||
			log_cmd_error("Missing mode parameter.\n");
 | 
			
		||||
 | 
			
		||||
		if (args.size() < 3)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1666,7 +1666,20 @@ struct VerificSvaImporter
 | 
			
		|||
				log("  importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(),
 | 
			
		||||
						LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile()));
 | 
			
		||||
 | 
			
		||||
			RTLIL::IdString root_name = module->uniquify(importer->mode_names || root->IsUserDeclared() ? RTLIL::escape_id(root->Name()) : NEW_ID);
 | 
			
		||||
			bool is_user_declared = root->IsUserDeclared();
 | 
			
		||||
 | 
			
		||||
			// FIXME
 | 
			
		||||
			if (!is_user_declared) {
 | 
			
		||||
				const char *name = root->Name();
 | 
			
		||||
				for (int i = 0; name[i]; i++) {
 | 
			
		||||
					if (i ? (name[i] < '0' || name[i] > '9') : (name[i] != 'i')) {
 | 
			
		||||
						is_user_declared = true;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			RTLIL::IdString root_name = module->uniquify(importer->mode_names || is_user_declared ? RTLIL::escape_id(root->Name()) : NEW_ID);
 | 
			
		||||
 | 
			
		||||
			// parse SVA sequence into trigger signal
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -189,6 +189,14 @@ YOSYS_NAMESPACE_END
 | 
			
		|||
"always_ff"    { SV_KEYWORD(TOK_ALWAYS); }
 | 
			
		||||
"always_latch" { SV_KEYWORD(TOK_ALWAYS); }
 | 
			
		||||
 | 
			
		||||
 /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex
 | 
			
		||||
    to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
 | 
			
		||||
    global state.. its a mess) */
 | 
			
		||||
[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
 | 
			
		||||
	frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
 | 
			
		||||
	return TOK_SVA_LABEL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
"assert"     { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
 | 
			
		||||
"assume"     { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
 | 
			
		||||
"cover"      { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
 | 
			
		||||
| 
						 | 
				
			
			@ -303,7 +311,7 @@ supply1 { return TOK_SUPPLY1; }
 | 
			
		|||
 | 
			
		||||
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
 | 
			
		||||
	frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
 | 
			
		||||
    return TOK_ID;
 | 
			
		||||
	return TOK_ID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,7 +105,8 @@ static void free_attr(std::map<std::string, AstNode*> *al)
 | 
			
		|||
	bool boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
 | 
			
		||||
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL
 | 
			
		||||
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER
 | 
			
		||||
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
 | 
			
		||||
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
 | 
			
		||||
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
 | 
			
		||||
| 
						 | 
				
			
			@ -119,14 +120,13 @@ static void free_attr(std::map<std::string, AstNode*> *al)
 | 
			
		|||
%token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
 | 
			
		||||
%token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
 | 
			
		||||
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
 | 
			
		||||
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME
 | 
			
		||||
%token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
 | 
			
		||||
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
 | 
			
		||||
%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
 | 
			
		||||
%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY
 | 
			
		||||
 | 
			
		||||
%type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int
 | 
			
		||||
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
 | 
			
		||||
%type <string> opt_label tok_prim_wrapper hierarchical_id
 | 
			
		||||
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id
 | 
			
		||||
%type <boolean> opt_signed opt_property unique_case_attr
 | 
			
		||||
%type <al> attr case_attr
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1329,6 +1329,14 @@ opt_label:
 | 
			
		|||
		$$ = NULL;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
opt_sva_label:
 | 
			
		||||
	TOK_SVA_LABEL ':' {
 | 
			
		||||
		$$ = $1;
 | 
			
		||||
	} |
 | 
			
		||||
	/* empty */ {
 | 
			
		||||
		$$ = NULL;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
opt_property:
 | 
			
		||||
	TOK_PROPERTY {
 | 
			
		||||
		$$ = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -1337,9 +1345,6 @@ opt_property:
 | 
			
		|||
		$$ = false;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
opt_stmt_label:
 | 
			
		||||
	TOK_ID ':' | /* empty */;
 | 
			
		||||
 | 
			
		||||
modport_stmt:
 | 
			
		||||
    TOK_MODPORT TOK_ID {
 | 
			
		||||
        AstNode *modport = new AstNode(AST_MODPORT);
 | 
			
		||||
| 
						 | 
				
			
			@ -1376,83 +1381,164 @@ modport_type_token:
 | 
			
		|||
    TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;}
 | 
			
		||||
 | 
			
		||||
assert:
 | 
			
		||||
	opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {
 | 
			
		||||
		if (noassert_mode)
 | 
			
		||||
	opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' {
 | 
			
		||||
		if (noassert_mode) {
 | 
			
		||||
			delete $5;
 | 
			
		||||
		else
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
 | 
			
		||||
		} else {
 | 
			
		||||
			AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5);
 | 
			
		||||
			if ($1 != nullptr)
 | 
			
		||||
				node->str = *$1;
 | 
			
		||||
			ast_stack.back()->children.push_back(node);
 | 
			
		||||
		}
 | 
			
		||||
		if ($1 != nullptr)
 | 
			
		||||
			delete $1;
 | 
			
		||||
	} |
 | 
			
		||||
	opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' {
 | 
			
		||||
		if (noassume_mode)
 | 
			
		||||
	opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' {
 | 
			
		||||
		if (noassume_mode) {
 | 
			
		||||
			delete $5;
 | 
			
		||||
		else
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5));
 | 
			
		||||
		} else {
 | 
			
		||||
			AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5);
 | 
			
		||||
			if ($1 != nullptr)
 | 
			
		||||
				node->str = *$1;
 | 
			
		||||
			ast_stack.back()->children.push_back(node);
 | 
			
		||||
		}
 | 
			
		||||
		if ($1 != nullptr)
 | 
			
		||||
			delete $1;
 | 
			
		||||
	} |
 | 
			
		||||
	opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		if (noassert_mode)
 | 
			
		||||
	opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		if (noassert_mode) {
 | 
			
		||||
			delete $6;
 | 
			
		||||
		else
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
 | 
			
		||||
		} else {
 | 
			
		||||
			AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6);
 | 
			
		||||
			if ($1 != nullptr)
 | 
			
		||||
				node->str = *$1;
 | 
			
		||||
			ast_stack.back()->children.push_back(node);
 | 
			
		||||
		}
 | 
			
		||||
		if ($1 != nullptr)
 | 
			
		||||
			delete $1;
 | 
			
		||||
	} |
 | 
			
		||||
	opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		if (noassume_mode)
 | 
			
		||||
	opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		if (noassume_mode) {
 | 
			
		||||
			delete $6;
 | 
			
		||||
		else
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6));
 | 
			
		||||
		} else {
 | 
			
		||||
			AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6);
 | 
			
		||||
			if ($1 != nullptr)
 | 
			
		||||
				node->str = *$1;
 | 
			
		||||
			ast_stack.back()->children.push_back(node);
 | 
			
		||||
		}
 | 
			
		||||
		if ($1 != nullptr)
 | 
			
		||||
			delete $1;
 | 
			
		||||
	} |
 | 
			
		||||
	opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
 | 
			
		||||
	opt_sva_label TOK_COVER opt_property '(' expr ')' ';' {
 | 
			
		||||
		AstNode *node = new AstNode(AST_COVER, $5);
 | 
			
		||||
		if ($1 != nullptr) {
 | 
			
		||||
			node->str = *$1;
 | 
			
		||||
			delete $1;
 | 
			
		||||
		}
 | 
			
		||||
		ast_stack.back()->children.push_back(node);
 | 
			
		||||
	} |
 | 
			
		||||
	opt_stmt_label TOK_COVER opt_property '(' ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
 | 
			
		||||
	opt_sva_label TOK_COVER opt_property '(' ')' ';' {
 | 
			
		||||
		AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
 | 
			
		||||
		if ($1 != nullptr) {
 | 
			
		||||
			node->str = *$1;
 | 
			
		||||
			delete $1;
 | 
			
		||||
		}
 | 
			
		||||
		ast_stack.back()->children.push_back(node);
 | 
			
		||||
	} |
 | 
			
		||||
	opt_stmt_label TOK_COVER ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
 | 
			
		||||
	opt_sva_label TOK_COVER ';' {
 | 
			
		||||
		AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
 | 
			
		||||
		if ($1 != nullptr) {
 | 
			
		||||
			node->str = *$1;
 | 
			
		||||
			delete $1;
 | 
			
		||||
		}
 | 
			
		||||
		ast_stack.back()->children.push_back(node);
 | 
			
		||||
	} |
 | 
			
		||||
	opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' {
 | 
			
		||||
		if (norestrict_mode)
 | 
			
		||||
	opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' {
 | 
			
		||||
		if (norestrict_mode) {
 | 
			
		||||
			delete $5;
 | 
			
		||||
		else
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
 | 
			
		||||
		} else {
 | 
			
		||||
			AstNode *node = new AstNode(AST_ASSUME, $5);
 | 
			
		||||
			if ($1 != nullptr)
 | 
			
		||||
				node->str = *$1;
 | 
			
		||||
			ast_stack.back()->children.push_back(node);
 | 
			
		||||
		}
 | 
			
		||||
		if (!$3)
 | 
			
		||||
			log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
 | 
			
		||||
		if ($1 != nullptr)
 | 
			
		||||
			delete $1;
 | 
			
		||||
	} |
 | 
			
		||||
	opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		if (norestrict_mode)
 | 
			
		||||
	opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		if (norestrict_mode) {
 | 
			
		||||
			delete $6;
 | 
			
		||||
		else
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
 | 
			
		||||
		} else {
 | 
			
		||||
			AstNode *node = new AstNode(AST_FAIR, $6);
 | 
			
		||||
			if ($1 != nullptr)
 | 
			
		||||
				node->str = *$1;
 | 
			
		||||
			ast_stack.back()->children.push_back(node);
 | 
			
		||||
		}
 | 
			
		||||
		if (!$3)
 | 
			
		||||
			log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
 | 
			
		||||
		if ($1 != nullptr)
 | 
			
		||||
			delete $1;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
assert_property:
 | 
			
		||||
	TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4));
 | 
			
		||||
	opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
 | 
			
		||||
		if ($1 != nullptr) {
 | 
			
		||||
			ast_stack.back()->children.back()->str = *$1;
 | 
			
		||||
			delete $1;
 | 
			
		||||
		}
 | 
			
		||||
	} |
 | 
			
		||||
	TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
 | 
			
		||||
	opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
 | 
			
		||||
		if ($1 != nullptr) {
 | 
			
		||||
			ast_stack.back()->children.back()->str = *$1;
 | 
			
		||||
			delete $1;
 | 
			
		||||
		}
 | 
			
		||||
	} |
 | 
			
		||||
	TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5));
 | 
			
		||||
	opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
 | 
			
		||||
		if ($1 != nullptr) {
 | 
			
		||||
			ast_stack.back()->children.back()->str = *$1;
 | 
			
		||||
			delete $1;
 | 
			
		||||
		}
 | 
			
		||||
	} |
 | 
			
		||||
	TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
 | 
			
		||||
	opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
 | 
			
		||||
		if ($1 != nullptr) {
 | 
			
		||||
			ast_stack.back()->children.back()->str = *$1;
 | 
			
		||||
			delete $1;
 | 
			
		||||
		}
 | 
			
		||||
	} |
 | 
			
		||||
	TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4));
 | 
			
		||||
	opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
 | 
			
		||||
		if ($1 != nullptr) {
 | 
			
		||||
			ast_stack.back()->children.back()->str = *$1;
 | 
			
		||||
			delete $1;
 | 
			
		||||
		}
 | 
			
		||||
	} |
 | 
			
		||||
	TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
 | 
			
		||||
		if (norestrict_mode)
 | 
			
		||||
			delete $4;
 | 
			
		||||
		else
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
 | 
			
		||||
	} |
 | 
			
		||||
	TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		if (norestrict_mode)
 | 
			
		||||
	opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
 | 
			
		||||
		if (norestrict_mode) {
 | 
			
		||||
			delete $5;
 | 
			
		||||
		else
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
 | 
			
		||||
		} else {
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
 | 
			
		||||
			if ($1 != nullptr) {
 | 
			
		||||
				ast_stack.back()->children.back()->str = *$1;
 | 
			
		||||
				delete $1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} |
 | 
			
		||||
	opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
 | 
			
		||||
		if (norestrict_mode) {
 | 
			
		||||
			delete $6;
 | 
			
		||||
		} else {
 | 
			
		||||
			ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
 | 
			
		||||
			if ($1 != nullptr) {
 | 
			
		||||
				ast_stack.back()->children.back()->str = *$1;
 | 
			
		||||
				delete $1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
simple_behavioral_stmt:
 | 
			
		||||
| 
						 | 
				
			
			@ -1670,6 +1756,11 @@ case_expr_list:
 | 
			
		|||
	TOK_DEFAULT {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT));
 | 
			
		||||
	} |
 | 
			
		||||
	TOK_SVA_LABEL {
 | 
			
		||||
		ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER));
 | 
			
		||||
		ast_stack.back()->children.back()->str = *$1;
 | 
			
		||||
		delete $1;
 | 
			
		||||
	} |
 | 
			
		||||
	expr {
 | 
			
		||||
		ast_stack.back()->children.push_back($1);
 | 
			
		||||
	} |
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue