mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	neater errors, lost in the sauce of source
This commit is contained in:
		
							parent
							
								
									88800a16ea
								
							
						
					
					
						commit
						b276fb6616
					
				
					 13 changed files with 196 additions and 245 deletions
				
			
		| 
						 | 
					@ -48,7 +48,7 @@ The lexer does little more than identifying all keywords and literals recognised
 | 
				
			||||||
by the Yosys Verilog frontend.
 | 
					by the Yosys Verilog frontend.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The lexer keeps track of the current location in the Verilog source code using
 | 
					The lexer keeps track of the current location in the Verilog source code using
 | 
				
			||||||
some global variables. These variables are used by the constructor of AST nodes
 | 
					some VerilogLexer member variables. These variables are used by the constructor of AST nodes
 | 
				
			||||||
to annotate each node with the source code location it originated from.
 | 
					to annotate each node with the source code location it originated from.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Finally the lexer identifies and handles special comments such as "``// synopsys
 | 
					Finally the lexer identifies and handles special comments such as "``// synopsys
 | 
				
			||||||
| 
						 | 
					@ -189,9 +189,10 @@ the bison code for parsing multiplications:
 | 
				
			||||||
.. code:: none
 | 
					.. code:: none
 | 
				
			||||||
   	:number-lines:
 | 
					   	:number-lines:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	basic_expr '*' attr basic_expr {
 | 
					  basic_expr TOK_ASTER attr basic_expr {
 | 
				
			||||||
		$$ = new AstNode(AST_MUL, $1, $4);
 | 
					    $$ = std::make_unique<AstNode>(AST_MUL, std::move($1), std::move($4));
 | 
				
			||||||
		append_attr($$, $3);
 | 
					    SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
				
			||||||
 | 
					    append_attr($$.get(), $3);
 | 
				
			||||||
  } |
 | 
					  } |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The generated AST data structure is then passed directly to the AST frontend
 | 
					The generated AST data structure is then passed directly to the AST frontend
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,8 +38,7 @@ using namespace AST_INTERNAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// instantiate global variables (public API)
 | 
					// instantiate global variables (public API)
 | 
				
			||||||
namespace AST {
 | 
					namespace AST {
 | 
				
			||||||
	std::string current_filename;
 | 
						bool sv_mode_but_global_and_used_for_literally_one_condition;
 | 
				
			||||||
	bool sv_mode;
 | 
					 | 
				
			||||||
	unsigned long long astnodes = 0;
 | 
						unsigned long long astnodes = 0;
 | 
				
			||||||
	unsigned long long astnode_count() { return astnodes; }
 | 
						unsigned long long astnode_count() { return astnodes; }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -200,7 +199,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// create new node (AstNode constructor)
 | 
					// create new node (AstNode constructor)
 | 
				
			||||||
// (the optional child arguments make it easier to create AST trees)
 | 
					// (the optional child arguments make it easier to create AST trees)
 | 
				
			||||||
AstNode::AstNode(AstNodeType type, std::unique_ptr<AstNode> child1, std::unique_ptr<AstNode> child2, std::unique_ptr<AstNode> child3, std::unique_ptr<AstNode> child4)
 | 
					AstNode::AstNode(AstSrcLocType loc, AstNodeType type, std::unique_ptr<AstNode> child1, std::unique_ptr<AstNode> child2, std::unique_ptr<AstNode> child3, std::unique_ptr<AstNode> child4)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static unsigned int hashidx_count = 123456789;
 | 
						static unsigned int hashidx_count = 123456789;
 | 
				
			||||||
	hashidx_count = mkhash_xorshift(hashidx_count);
 | 
						hashidx_count = mkhash_xorshift(hashidx_count);
 | 
				
			||||||
| 
						 | 
					@ -208,7 +207,7 @@ AstNode::AstNode(AstNodeType type, std::unique_ptr<AstNode> child1, std::unique_
 | 
				
			||||||
	astnodes++;
 | 
						astnodes++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->type = type;
 | 
						this->type = type;
 | 
				
			||||||
	filename = current_filename;
 | 
						loc = loc;
 | 
				
			||||||
	is_input = false;
 | 
						is_input = false;
 | 
				
			||||||
	is_output = false;
 | 
						is_output = false;
 | 
				
			||||||
	is_reg = false;
 | 
						is_reg = false;
 | 
				
			||||||
| 
						 | 
					@ -252,7 +251,7 @@ AstNode::AstNode(AstNodeType type, std::unique_ptr<AstNode> child1, std::unique_
 | 
				
			||||||
// create a (deep recursive) copy of a node
 | 
					// create a (deep recursive) copy of a node
 | 
				
			||||||
std::unique_ptr<AstNode> AstNode::clone() const
 | 
					std::unique_ptr<AstNode> AstNode::clone() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto that = std::make_unique<AstNode>(this->type);
 | 
						auto that = std::make_unique<AstNode>(this->location, this->type);
 | 
				
			||||||
	cloneInto(*that.get());
 | 
						cloneInto(*that.get());
 | 
				
			||||||
	return that;
 | 
						return that;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -287,7 +286,6 @@ void AstNode::cloneInto(AstNode &other) const
 | 
				
			||||||
	other.id2ast = id2ast;
 | 
						other.id2ast = id2ast;
 | 
				
			||||||
	other.basic_prep = basic_prep;
 | 
						other.basic_prep = basic_prep;
 | 
				
			||||||
	other.lookahead = lookahead;
 | 
						other.lookahead = lookahead;
 | 
				
			||||||
	other.filename = filename;
 | 
					 | 
				
			||||||
	other.location = location;
 | 
						other.location = location;
 | 
				
			||||||
	other.in_lvalue = in_lvalue;
 | 
						other.in_lvalue = in_lvalue;
 | 
				
			||||||
	other.in_param = in_param;
 | 
						other.in_param = in_param;
 | 
				
			||||||
| 
						 | 
					@ -842,9 +840,9 @@ bool AstNode::contains(const AstNode *other) const
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// create an AST node for a constant (using a 32 bit int as value)
 | 
					// create an AST node for a constant (using a 32 bit int as value)
 | 
				
			||||||
std::unique_ptr<AstNode> AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
 | 
					std::unique_ptr<AstNode> AstNode::mkconst_int(AstSrcLocType loc, uint32_t v, bool is_signed, int width)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto node = std::make_unique<AstNode>(AST_CONSTANT);
 | 
						auto node = std::make_unique<AstNode>(loc, AST_CONSTANT);
 | 
				
			||||||
	node->integer = v;
 | 
						node->integer = v;
 | 
				
			||||||
	node->is_signed = is_signed;
 | 
						node->is_signed = is_signed;
 | 
				
			||||||
	for (int i = 0; i < width; i++) {
 | 
						for (int i = 0; i < width; i++) {
 | 
				
			||||||
| 
						 | 
					@ -858,9 +856,9 @@ std::unique_ptr<AstNode> AstNode::mkconst_int(uint32_t v, bool is_signed, int wi
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// create an AST node for a constant (using a bit vector as value)
 | 
					// create an AST node for a constant (using a bit vector as value)
 | 
				
			||||||
std::unique_ptr<AstNode> AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
 | 
					std::unique_ptr<AstNode> AstNode::mkconst_bits(AstSrcLocType loc, const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto node = std::make_unique<AstNode>(AST_CONSTANT);
 | 
						auto node = std::make_unique<AstNode>(loc, AST_CONSTANT);
 | 
				
			||||||
	node->is_signed = is_signed;
 | 
						node->is_signed = is_signed;
 | 
				
			||||||
	node->bits = v;
 | 
						node->bits = v;
 | 
				
			||||||
	for (size_t i = 0; i < 32; i++) {
 | 
						for (size_t i = 0; i < 32; i++) {
 | 
				
			||||||
| 
						 | 
					@ -876,15 +874,15 @@ std::unique_ptr<AstNode> AstNode::mkconst_bits(const std::vector<RTLIL::State> &
 | 
				
			||||||
	return node;
 | 
						return node;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::unique_ptr<AstNode> AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
 | 
					std::unique_ptr<AstNode> AstNode::mkconst_bits(AstSrcLocType loc, const std::vector<RTLIL::State> &v, bool is_signed)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return mkconst_bits(v, is_signed, false);
 | 
						return mkconst_bits(loc, v, is_signed, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// create an AST node for a constant (using a string in bit vector form as value)
 | 
					// create an AST node for a constant (using a string in bit vector form as value)
 | 
				
			||||||
std::unique_ptr<AstNode> AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
 | 
					std::unique_ptr<AstNode> AstNode::mkconst_str(AstSrcLocType loc, const std::vector<RTLIL::State> &v)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto node = mkconst_str(RTLIL::Const(v).decode_string());
 | 
						auto node = mkconst_str(loc, RTLIL::Const(v).decode_string());
 | 
				
			||||||
	while (GetSize(node->bits) < GetSize(v))
 | 
						while (GetSize(node->bits) < GetSize(v))
 | 
				
			||||||
		node->bits.push_back(RTLIL::State::S0);
 | 
							node->bits.push_back(RTLIL::State::S0);
 | 
				
			||||||
	log_assert(node->bits == v);
 | 
						log_assert(node->bits == v);
 | 
				
			||||||
| 
						 | 
					@ -892,14 +890,14 @@ std::unique_ptr<AstNode> AstNode::mkconst_str(const std::vector<RTLIL::State> &v
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// create an AST node for a constant (using a string as value)
 | 
					// create an AST node for a constant (using a string as value)
 | 
				
			||||||
std::unique_ptr<AstNode> AstNode::mkconst_str(const std::string &str)
 | 
					std::unique_ptr<AstNode> AstNode::mkconst_str(AstSrcLocType loc, const std::string &str)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	std::unique_ptr<AstNode> node;
 | 
						std::unique_ptr<AstNode> node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// LRM 1364-2005 5.2.3.3 The empty string literal ("") shall be considered
 | 
						// LRM 1364-2005 5.2.3.3 The empty string literal ("") shall be considered
 | 
				
			||||||
	// equivalent to the ASCII NUL ("\0")
 | 
						// equivalent to the ASCII NUL ("\0")
 | 
				
			||||||
	if (str.empty()) {
 | 
						if (str.empty()) {
 | 
				
			||||||
		node = AstNode::mkconst_int(0, false, 8);
 | 
							node = AstNode::mkconst_int(loc, 0, false, 8);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		std::vector<RTLIL::State> data;
 | 
							std::vector<RTLIL::State> data;
 | 
				
			||||||
		data.reserve(str.size() * 8);
 | 
							data.reserve(str.size() * 8);
 | 
				
			||||||
| 
						 | 
					@ -910,7 +908,7 @@ std::unique_ptr<AstNode> AstNode::mkconst_str(const std::string &str)
 | 
				
			||||||
				ch = ch >> 1;
 | 
									ch = ch >> 1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		node = AstNode::mkconst_bits(data, false);
 | 
							node = AstNode::mkconst_bits(loc, data, false);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	node->is_string = true;
 | 
						node->is_string = true;
 | 
				
			||||||
| 
						 | 
					@ -919,19 +917,19 @@ std::unique_ptr<AstNode> AstNode::mkconst_str(const std::string &str)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// create a temporary register
 | 
					// create a temporary register
 | 
				
			||||||
std::unique_ptr<AstNode> AstNode::mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed)
 | 
					std::unique_ptr<AstNode> AstNode::mktemp_logic(AstSrcLocType loc, const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto wire_owned = std::make_unique<AstNode>(AST_WIRE, std::make_unique<AstNode>(AST_RANGE, mkconst_int(range_left, true), mkconst_int(range_right, true)));
 | 
						auto wire_owned = std::make_unique<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(loc, AST_RANGE, mkconst_int(loc, range_left, true), mkconst_int(loc, range_right, true)));
 | 
				
			||||||
	auto* wire = wire_owned.get();
 | 
						auto* wire = wire_owned.get();
 | 
				
			||||||
	wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++);
 | 
						wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(location.filename).c_str(), location.first_line, autoidx++);
 | 
				
			||||||
	if (nosync)
 | 
						if (nosync)
 | 
				
			||||||
		wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
 | 
							wire->set_attribute(ID::nosync, AstNode::mkconst_int(loc, 1, false));
 | 
				
			||||||
	wire->is_signed = is_signed;
 | 
						wire->is_signed = is_signed;
 | 
				
			||||||
	wire->is_logic = true;
 | 
						wire->is_logic = true;
 | 
				
			||||||
	mod->children.push_back(std::move(wire_owned));
 | 
						mod->children.push_back(std::move(wire_owned));
 | 
				
			||||||
	while (wire->simplify(true, 1, -1, false)) { }
 | 
						while (wire->simplify(true, 1, -1, false)) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto ident = std::make_unique<AstNode>(AST_IDENTIFIER);
 | 
						auto ident = std::make_unique<AstNode>(loc, AST_IDENTIFIER);
 | 
				
			||||||
	ident->str = wire->str;
 | 
						ident->str = wire->str;
 | 
				
			||||||
	ident->id2ast = wire;
 | 
						ident->id2ast = wire;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -985,7 +983,7 @@ RTLIL::Const AstNode::asParaConst() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (type == AST_REALVALUE)
 | 
						if (type == AST_REALVALUE)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto strnode = AstNode::mkconst_str(stringf("%f", realvalue));
 | 
							auto strnode = AstNode::mkconst_str(location, stringf("%f", realvalue));
 | 
				
			||||||
		RTLIL::Const val = strnode->asAttrConst();
 | 
							RTLIL::Const val = strnode->asAttrConst();
 | 
				
			||||||
		val.flags |= RTLIL::CONST_FLAG_REAL;
 | 
							val.flags |= RTLIL::CONST_FLAG_REAL;
 | 
				
			||||||
		return val;
 | 
							return val;
 | 
				
			||||||
| 
						 | 
					@ -1087,7 +1085,7 @@ RTLIL::Const AstNode::realAsConst(int width)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string AstNode::loc_string() const
 | 
					std::string AstNode::loc_string() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
 | 
						return stringf("%s:%d.%d-%d.%d", location.filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
 | 
					void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
 | 
				
			||||||
| 
						 | 
					@ -1445,7 +1443,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
 | 
				
			||||||
			if (design->has(child->str)) {
 | 
								if (design->has(child->str)) {
 | 
				
			||||||
				RTLIL::Module *existing_mod = design->module(child->str);
 | 
									RTLIL::Module *existing_mod = design->module(child->str);
 | 
				
			||||||
				if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
 | 
									if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
 | 
				
			||||||
					log_file_error(child->filename, child->location.first_line, "Re-definition of module `%s'!\n", child->str.c_str());
 | 
										log_file_error(child->location.filename, child->location.first_line, "Re-definition of module `%s'!\n", child->str.c_str());
 | 
				
			||||||
				} else if (nooverwrite) {
 | 
									} else if (nooverwrite) {
 | 
				
			||||||
					log("Ignoring re-definition of module `%s' at %s.\n",
 | 
										log("Ignoring re-definition of module `%s' at %s.\n",
 | 
				
			||||||
							child->str.c_str(), child->loc_string().c_str());
 | 
												child->str.c_str(), child->loc_string().c_str());
 | 
				
			||||||
| 
						 | 
					@ -1924,7 +1922,7 @@ void AstNode::input_error(const char *format, ...) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	va_list ap;
 | 
						va_list ap;
 | 
				
			||||||
	va_start(ap, format);
 | 
						va_start(ap, format);
 | 
				
			||||||
	logv_file_error(filename, location.first_line, format, ap);
 | 
						logv_file_error(location.filename, location.first_line, format, ap);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_NAMESPACE_END
 | 
					YOSYS_NAMESPACE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,10 +163,11 @@ namespace AST
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct AstSrcLocType {
 | 
						struct AstSrcLocType {
 | 
				
			||||||
 | 
							std::string filename;
 | 
				
			||||||
		unsigned int first_line, last_line;
 | 
							unsigned int first_line, last_line;
 | 
				
			||||||
		unsigned int first_column, last_column;
 | 
							unsigned int first_column, last_column;
 | 
				
			||||||
		AstSrcLocType() : first_line(0), last_line(0), first_column(0), last_column(0) {}
 | 
							AstSrcLocType() : filename(""), first_line(0), last_line(0), first_column(0), last_column(0) {}
 | 
				
			||||||
		AstSrcLocType(int _first_line, int _first_column, int _last_line, int _last_column) : first_line(_first_line), last_line(_last_line), first_column(_first_column), last_column(_last_column) {}
 | 
							AstSrcLocType(std::string _filename, int _first_line, int _first_column, int _last_line, int _last_column) : filename(_filename), first_line(_first_line), last_line(_last_line), first_column(_first_column), last_column(_last_column) {}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// convert an node type to a string (e.g. for debug output)
 | 
						// convert an node type to a string (e.g. for debug output)
 | 
				
			||||||
| 
						 | 
					@ -223,7 +224,6 @@ namespace AST
 | 
				
			||||||
		// this is the original sourcecode location that resulted in this AST node
 | 
							// this is the original sourcecode location that resulted in this AST node
 | 
				
			||||||
		// it is automatically set by the constructor using AST::current_filename and
 | 
							// it is automatically set by the constructor using AST::current_filename and
 | 
				
			||||||
		// the AST::get_line_num() callback function.
 | 
							// the AST::get_line_num() callback function.
 | 
				
			||||||
		std::string filename;
 | 
					 | 
				
			||||||
		AstSrcLocType location;
 | 
							AstSrcLocType location;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// are we embedded in an lvalue, param?
 | 
							// are we embedded in an lvalue, param?
 | 
				
			||||||
| 
						 | 
					@ -234,7 +234,7 @@ namespace AST
 | 
				
			||||||
		bool in_param_from_above;
 | 
							bool in_param_from_above;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// creating and deleting nodes
 | 
							// creating and deleting nodes
 | 
				
			||||||
		AstNode(AstNodeType type = AST_NONE, std::unique_ptr<AstNode> child1 = nullptr, std::unique_ptr<AstNode> child2 = nullptr, std::unique_ptr<AstNode> child3 = nullptr, std::unique_ptr<AstNode> child4 = nullptr);
 | 
							AstNode(AstSrcLocType loc, AstNodeType type = AST_NONE, std::unique_ptr<AstNode> child1 = nullptr, std::unique_ptr<AstNode> child2 = nullptr, std::unique_ptr<AstNode> child3 = nullptr, std::unique_ptr<AstNode> child4 = nullptr);
 | 
				
			||||||
		std::unique_ptr<AstNode> clone() const;
 | 
							std::unique_ptr<AstNode> clone() const;
 | 
				
			||||||
		void cloneInto(AstNode &other) const;
 | 
							void cloneInto(AstNode &other) const;
 | 
				
			||||||
		void delete_children();
 | 
							void delete_children();
 | 
				
			||||||
| 
						 | 
					@ -322,14 +322,14 @@ namespace AST
 | 
				
			||||||
		AstNode operator=(AstNode) = delete;
 | 
							AstNode operator=(AstNode) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// helper functions for creating AST nodes for constants
 | 
							// helper functions for creating AST nodes for constants
 | 
				
			||||||
		static std::unique_ptr<AstNode> mkconst_int(uint32_t v, bool is_signed, int width = 32);
 | 
							static std::unique_ptr<AstNode> mkconst_int(AstSrcLocType loc, uint32_t v, bool is_signed, int width = 32);
 | 
				
			||||||
		static std::unique_ptr<AstNode> mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
 | 
							static std::unique_ptr<AstNode> mkconst_bits(AstSrcLocType loc, const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
 | 
				
			||||||
		static std::unique_ptr<AstNode> mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
 | 
							static std::unique_ptr<AstNode> mkconst_bits(AstSrcLocType loc, const std::vector<RTLIL::State> &v, bool is_signed);
 | 
				
			||||||
		static std::unique_ptr<AstNode> mkconst_str(const std::vector<RTLIL::State> &v);
 | 
							static std::unique_ptr<AstNode> mkconst_str(AstSrcLocType loc, const std::vector<RTLIL::State> &v);
 | 
				
			||||||
		static std::unique_ptr<AstNode> mkconst_str(const std::string &str);
 | 
							static std::unique_ptr<AstNode> mkconst_str(AstSrcLocType loc, const std::string &str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// helper function to create an AST node for a temporary register
 | 
							// helper function to create an AST node for a temporary register
 | 
				
			||||||
		std::unique_ptr<AstNode> mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed);
 | 
							std::unique_ptr<AstNode> mktemp_logic(AstSrcLocType loc, const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// helper function for creating sign-extended const objects
 | 
							// helper function for creating sign-extended const objects
 | 
				
			||||||
		RTLIL::Const bitsAsConst(int width, bool is_signed);
 | 
							RTLIL::Const bitsAsConst(int width, bool is_signed);
 | 
				
			||||||
| 
						 | 
					@ -409,7 +409,7 @@ namespace AST
 | 
				
			||||||
	// to initialize the filename and linenum properties of new nodes
 | 
						// to initialize the filename and linenum properties of new nodes
 | 
				
			||||||
	extern std::string current_filename;
 | 
						extern std::string current_filename;
 | 
				
			||||||
	// also set by the language frontend to control some AST processing
 | 
						// also set by the language frontend to control some AST processing
 | 
				
			||||||
	extern bool sv_mode;
 | 
						extern bool sv_mode_but_global_and_used_for_literally_one_condition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// for stats
 | 
						// for stats
 | 
				
			||||||
	unsigned long long astnode_count();
 | 
						unsigned long long astnode_count();
 | 
				
			||||||
| 
						 | 
					@ -419,7 +419,7 @@ namespace AST
 | 
				
			||||||
	void use_internal_line_num();
 | 
						void use_internal_line_num();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// call a DPI function
 | 
						// call a DPI function
 | 
				
			||||||
	std::unique_ptr<AstNode> dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<std::unique_ptr<AstNode>> &args);
 | 
						std::unique_ptr<AstNode> dpi_call(AstSrcLocType loc, const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<std::unique_ptr<AstNode>> &args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Helper functions related to handling SystemVerilog interfaces
 | 
						// Helper functions related to handling SystemVerilog interfaces
 | 
				
			||||||
	std::pair<std::string,std::string> split_modport_from_type(std::string name_type);
 | 
						std::pair<std::string,std::string> split_modport_from_type(std::string name_type);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ static ffi_fptr resolve_fn (std::string symbol_name)
 | 
				
			||||||
	log_error("unable to resolve '%s'.\n", symbol_name.c_str());
 | 
						log_error("unable to resolve '%s'.\n", symbol_name.c_str());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::unique_ptr<AST::AstNode> AST::dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<std::unique_ptr<AST::AstNode>> &args)
 | 
					std::unique_ptr<AST::AstNode> AST::dpi_call(AstSrcLocType loc, const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<std::unique_ptr<AST::AstNode>> &args)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	std::unique_ptr<AST::AstNode> newNode = nullptr;
 | 
						std::unique_ptr<AST::AstNode> newNode = nullptr;
 | 
				
			||||||
	union value { double f64; float f32; int32_t i32; void *ptr; };
 | 
						union value { double f64; float f32; int32_t i32; void *ptr; };
 | 
				
			||||||
| 
						 | 
					@ -125,11 +125,11 @@ std::unique_ptr<AST::AstNode> AST::dpi_call(const std::string &rtype, const std:
 | 
				
			||||||
        ffi_call(&cif, resolve_fn(fname.c_str()), values[args.size()], values.data());
 | 
					        ffi_call(&cif, resolve_fn(fname.c_str()), values[args.size()], values.data());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rtype == "real") {
 | 
						if (rtype == "real") {
 | 
				
			||||||
		newNode = std::make_unique<AstNode>(AST_REALVALUE);
 | 
							newNode = std::make_unique<AstNode>(loc, AST_REALVALUE);
 | 
				
			||||||
		newNode->realvalue = value_store[args.size()].f64;
 | 
							newNode->realvalue = value_store[args.size()].f64;
 | 
				
			||||||
		log("  return realvalue: %g\n", newNode->asReal(true));
 | 
							log("  return realvalue: %g\n", newNode->asReal(true));
 | 
				
			||||||
	} else if (rtype == "shortreal") {
 | 
						} else if (rtype == "shortreal") {
 | 
				
			||||||
		newNode = std::make_unique<AstNode>(AST_REALVALUE);
 | 
							newNode = std::make_unique<AstNode>(loc, AST_REALVALUE);
 | 
				
			||||||
		newNode->realvalue = value_store[args.size()].f32;
 | 
							newNode->realvalue = value_store[args.size()].f32;
 | 
				
			||||||
		log("  return realvalue: %g\n", newNode->asReal(true));
 | 
							log("  return realvalue: %g\n", newNode->asReal(true));
 | 
				
			||||||
	} else if (rtype == "chandle") {
 | 
						} else if (rtype == "chandle") {
 | 
				
			||||||
| 
						 | 
					@ -137,10 +137,10 @@ std::unique_ptr<AST::AstNode> AST::dpi_call(const std::string &rtype, const std:
 | 
				
			||||||
		std::vector<RTLIL::State> bits(64);
 | 
							std::vector<RTLIL::State> bits(64);
 | 
				
			||||||
		for (int i = 0; i < 64; i++)
 | 
							for (int i = 0; i < 64; i++)
 | 
				
			||||||
			bits.at(i) = (rawval & (1ULL << i)) ? RTLIL::State::S1 : RTLIL::State::S0;
 | 
								bits.at(i) = (rawval & (1ULL << i)) ? RTLIL::State::S1 : RTLIL::State::S0;
 | 
				
			||||||
		newNode = AstNode::mkconst_bits(bits, false);
 | 
							newNode = AstNode::mkconst_bits(loc, bits, false);
 | 
				
			||||||
		log("  return chandle: %llx\n", (unsigned long long)newNode->asInt(false));
 | 
							log("  return chandle: %llx\n", (unsigned long long)newNode->asInt(false));
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		newNode = AstNode::mkconst_int(value_store[args.size()].i32, false);
 | 
							newNode = AstNode::mkconst_int(loc, value_store[args.size()].i32, false);
 | 
				
			||||||
		log("  return integer: %lld\n", (long long)newNode->asInt(true));
 | 
							log("  return integer: %lld\n", (long long)newNode->asInt(true));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,7 +153,7 @@ YOSYS_NAMESPACE_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_NAMESPACE_BEGIN
 | 
					YOSYS_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AST::AstNode *AST::dpi_call(const std::string&, const std::string &fname, const std::vector<std::string>&, const std::vector<AstNode*>&)
 | 
					AST::AstNode *AST::dpi_call(AstSrcLocType loc, const std::string&, const std::string &fname, const std::vector<std::string>&, const std::vector<AstNode*>&)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname.c_str());
 | 
						log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname.c_str());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ using namespace AST_INTERNAL;
 | 
				
			||||||
// helper function for creating RTLIL code for unary operations
 | 
					// helper function for creating RTLIL code for unary operations
 | 
				
			||||||
static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)
 | 
					static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++);
 | 
						IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->location.filename).c_str(), that->location.first_line, autoidx++);
 | 
				
			||||||
	RTLIL::Cell *cell = current_module->addCell(name, type);
 | 
						RTLIL::Cell *cell = current_module->addCell(name, type);
 | 
				
			||||||
	set_src_attr(cell, that);
 | 
						set_src_attr(cell, that);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	IdString name = stringf("$extend$%s:%d$%d", RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++);
 | 
						IdString name = stringf("$extend$%s:%d$%d", RTLIL::encode_filename(that->location.filename).c_str(), that->location.first_line, autoidx++);
 | 
				
			||||||
	RTLIL::Cell *cell = current_module->addCell(name, ID($pos));
 | 
						RTLIL::Cell *cell = current_module->addCell(name, ID($pos));
 | 
				
			||||||
	set_src_attr(cell, that);
 | 
						set_src_attr(cell, that);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,7 +104,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
 | 
				
			||||||
// helper function for creating RTLIL code for binary operations
 | 
					// helper function for creating RTLIL code for binary operations
 | 
				
			||||||
static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
 | 
					static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++);
 | 
						IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->location.filename).c_str(), that->location.first_line, autoidx++);
 | 
				
			||||||
	RTLIL::Cell *cell = current_module->addCell(name, type);
 | 
						RTLIL::Cell *cell = current_module->addCell(name, type);
 | 
				
			||||||
	set_src_attr(cell, that);
 | 
						set_src_attr(cell, that);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -138,7 +138,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
 | 
				
			||||||
	log_assert(cond.size() == 1);
 | 
						log_assert(cond.size() == 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std::stringstream sstr;
 | 
						std::stringstream sstr;
 | 
				
			||||||
	sstr << "$ternary$" << RTLIL::encode_filename(that->filename) << ":" << that->location.first_line << "$" << (autoidx++);
 | 
						sstr << "$ternary$" << RTLIL::encode_filename(that->location.filename) << ":" << that->location.first_line << "$" << (autoidx++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux));
 | 
						RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux));
 | 
				
			||||||
	set_src_attr(cell, that);
 | 
						set_src_attr(cell, that);
 | 
				
			||||||
| 
						 | 
					@ -347,7 +347,7 @@ struct AST_INTERNAL::ProcessGenerator
 | 
				
			||||||
		LookaheadRewriter la_rewriter(always.get());
 | 
							LookaheadRewriter la_rewriter(always.get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// generate process and simple root case
 | 
							// generate process and simple root case
 | 
				
			||||||
		proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(always->filename).c_str(), always->location.first_line, autoidx++));
 | 
							proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(always->location.filename).c_str(), always->location.first_line, autoidx++));
 | 
				
			||||||
		set_src_attr(proc, always.get());
 | 
							set_src_attr(proc, always.get());
 | 
				
			||||||
		for (auto &attr : always->attributes) {
 | 
							for (auto &attr : always->attributes) {
 | 
				
			||||||
			if (attr.second->type != AST_CONSTANT)
 | 
								if (attr.second->type != AST_CONSTANT)
 | 
				
			||||||
| 
						 | 
					@ -723,7 +723,7 @@ struct AST_INTERNAL::ProcessGenerator
 | 
				
			||||||
			if (ast->str == "$display" || ast->str == "$displayb" || ast->str == "$displayh" || ast->str == "$displayo" ||
 | 
								if (ast->str == "$display" || ast->str == "$displayb" || ast->str == "$displayh" || ast->str == "$displayo" ||
 | 
				
			||||||
		  ast->str == "$write"   || ast->str == "$writeb"   || ast->str == "$writeh"   || ast->str == "$writeo") {
 | 
							  ast->str == "$write"   || ast->str == "$writeb"   || ast->str == "$writeh"   || ast->str == "$writeo") {
 | 
				
			||||||
				std::stringstream sstr;
 | 
									std::stringstream sstr;
 | 
				
			||||||
				sstr << ast->str << "$" << ast->filename << ":" << ast->location.first_line << "$" << (autoidx++);
 | 
									sstr << ast->str << "$" << ast->location.filename << ":" << ast->location.first_line << "$" << (autoidx++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				Wire *en = current_module->addWire(sstr.str() + "_EN", 1);
 | 
									Wire *en = current_module->addWire(sstr.str() + "_EN", 1);
 | 
				
			||||||
				set_src_attr(en, ast);
 | 
									set_src_attr(en, ast);
 | 
				
			||||||
| 
						 | 
					@ -766,7 +766,7 @@ struct AST_INTERNAL::ProcessGenerator
 | 
				
			||||||
					node->detectSignWidth(width, is_signed, nullptr);
 | 
										node->detectSignWidth(width, is_signed, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					VerilogFmtArg arg = {};
 | 
										VerilogFmtArg arg = {};
 | 
				
			||||||
					arg.filename = node->filename;
 | 
										arg.filename = node->location.filename;
 | 
				
			||||||
					arg.first_line = node->location.first_line;
 | 
										arg.first_line = node->location.first_line;
 | 
				
			||||||
					if (node->type == AST_CONSTANT && node->is_string) {
 | 
										if (node->type == AST_CONSTANT && node->is_string) {
 | 
				
			||||||
						arg.type = VerilogFmtArg::STRING;
 | 
											arg.type = VerilogFmtArg::STRING;
 | 
				
			||||||
| 
						 | 
					@ -793,7 +793,7 @@ struct AST_INTERNAL::ProcessGenerator
 | 
				
			||||||
					fmt.append_literal("\n");
 | 
										fmt.append_literal("\n");
 | 
				
			||||||
				fmt.emit_rtlil(cell);
 | 
									fmt.emit_rtlil(cell);
 | 
				
			||||||
			} else if (!ast->str.empty()) {
 | 
								} else if (!ast->str.empty()) {
 | 
				
			||||||
				log_file_error(ast->filename, ast->location.first_line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str());
 | 
									log_file_error(ast->location.filename, ast->location.first_line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -813,7 +813,7 @@ struct AST_INTERNAL::ProcessGenerator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				IdString cellname;
 | 
									IdString cellname;
 | 
				
			||||||
				if (ast->str.empty())
 | 
									if (ast->str.empty())
 | 
				
			||||||
					cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(ast->filename).c_str(), ast->location.first_line, autoidx++);
 | 
										cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(ast->location.filename).c_str(), ast->location.first_line, autoidx++);
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					cellname = ast->str;
 | 
										cellname = ast->str;
 | 
				
			||||||
				check_unique_id(current_module, cellname, ast, "procedural assertion");
 | 
									check_unique_id(current_module, cellname, ast, "procedural assertion");
 | 
				
			||||||
| 
						 | 
					@ -843,7 +843,7 @@ struct AST_INTERNAL::ProcessGenerator
 | 
				
			||||||
				set_src_attr(cell, ast);
 | 
									set_src_attr(cell, ast);
 | 
				
			||||||
				for (auto &attr : ast->attributes) {
 | 
									for (auto &attr : ast->attributes) {
 | 
				
			||||||
					if (attr.second->type != AST_CONSTANT)
 | 
										if (attr.second->type != AST_CONSTANT)
 | 
				
			||||||
						log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
 | 
											log_file_error(ast->location.filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
 | 
				
			||||||
					cell->attributes[attr.first] = attr.second->asAttrConst();
 | 
										cell->attributes[attr.first] = attr.second->asAttrConst();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				cell->setParam(ID::FLAVOR, flavor);
 | 
									cell->setParam(ID::FLAVOR, flavor);
 | 
				
			||||||
| 
						 | 
					@ -1503,7 +1503,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::SigSpec sig = realAsConst(width_hint);
 | 
								RTLIL::SigSpec sig = realAsConst(width_hint);
 | 
				
			||||||
			log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
 | 
								log_file_warning(location.filename, location.first_line, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
 | 
				
			||||||
			return sig;
 | 
								return sig;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1535,7 +1535,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
				if (dynamic_cast<RTLIL::Binding*>(current_module)) {
 | 
									if (dynamic_cast<RTLIL::Binding*>(current_module)) {
 | 
				
			||||||
					/* nothing to do here */
 | 
										/* nothing to do here */
 | 
				
			||||||
				} else if (flag_autowire)
 | 
									} else if (flag_autowire)
 | 
				
			||||||
					log_file_warning(filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str());
 | 
										log_file_warning(location.filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str());
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
 | 
										input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -1640,10 +1640,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
						chunk.offset = source_width - (chunk.offset + chunk.width);
 | 
											chunk.offset = source_width - (chunk.offset + chunk.width);
 | 
				
			||||||
					if (chunk.offset > chunk_left || chunk.offset + chunk.width < chunk_right) {
 | 
										if (chunk.offset > chunk_left || chunk.offset + chunk.width < chunk_right) {
 | 
				
			||||||
						if (chunk.width == 1)
 | 
											if (chunk.width == 1)
 | 
				
			||||||
							log_file_warning(filename, location.first_line, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
 | 
												log_file_warning(location.filename, location.first_line, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
 | 
				
			||||||
									str.c_str());
 | 
														str.c_str());
 | 
				
			||||||
						else
 | 
											else
 | 
				
			||||||
							log_file_warning(filename, location.first_line, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n",
 | 
												log_file_warning(location.filename, location.first_line, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n",
 | 
				
			||||||
									children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width);
 | 
														children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width);
 | 
				
			||||||
						chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
 | 
											chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
| 
						 | 
					@ -1657,10 +1657,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
							chunk.offset += add_undef_bits_lsb;
 | 
												chunk.offset += add_undef_bits_lsb;
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						if (add_undef_bits_lsb)
 | 
											if (add_undef_bits_lsb)
 | 
				
			||||||
							log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
 | 
												log_file_warning(location.filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
 | 
				
			||||||
									children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb);
 | 
														children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb);
 | 
				
			||||||
						if (add_undef_bits_msb)
 | 
											if (add_undef_bits_msb)
 | 
				
			||||||
							log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
 | 
												log_file_warning(location.filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
 | 
				
			||||||
									children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb);
 | 
														children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -1934,7 +1934,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
	case AST_MEMRD:
 | 
						case AST_MEMRD:
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			std::stringstream sstr;
 | 
								std::stringstream sstr;
 | 
				
			||||||
			sstr << "$memrd$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
								sstr << "$memrd$" << str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd));
 | 
								RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd));
 | 
				
			||||||
			set_src_attr(cell, this);
 | 
								set_src_attr(cell, this);
 | 
				
			||||||
| 
						 | 
					@ -1972,7 +1972,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
	case AST_MEMINIT:
 | 
						case AST_MEMINIT:
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			std::stringstream sstr;
 | 
								std::stringstream sstr;
 | 
				
			||||||
			sstr << "$meminit$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
								sstr << "$meminit$" << str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			SigSpec en_sig = children[2]->genRTLIL();
 | 
								SigSpec en_sig = children[2]->genRTLIL();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2017,7 +2017,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			IdString cellname;
 | 
								IdString cellname;
 | 
				
			||||||
			if (str.empty())
 | 
								if (str.empty())
 | 
				
			||||||
				cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++);
 | 
									cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(location.filename).c_str(), location.first_line, autoidx++);
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				cellname = str;
 | 
									cellname = str;
 | 
				
			||||||
			check_unique_id(current_module, cellname, this, "procedural assertion");
 | 
								check_unique_id(current_module, cellname, this, "procedural assertion");
 | 
				
			||||||
| 
						 | 
					@ -2060,7 +2060,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
						new_left.append(left[i]);
 | 
											new_left.append(left[i]);
 | 
				
			||||||
						new_right.append(right[i]);
 | 
											new_right.append(right[i]);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				log_file_warning(filename, location.first_line, "Ignoring assignment to constant bits:\n"
 | 
									log_file_warning(location.filename, location.first_line, "Ignoring assignment to constant bits:\n"
 | 
				
			||||||
						"    old assignment: %s = %s\n    new assignment: %s = %s.\n",
 | 
											"    old assignment: %s = %s\n    new assignment: %s = %s.\n",
 | 
				
			||||||
						log_signal(left), log_signal(right),
 | 
											log_signal(left), log_signal(right),
 | 
				
			||||||
						log_signal(new_left), log_signal(new_right));
 | 
											log_signal(new_left), log_signal(new_right));
 | 
				
			||||||
| 
						 | 
					@ -2095,7 +2095,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
					IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
 | 
										IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
 | 
				
			||||||
					const AstNode *value = child->children[0].get();
 | 
										const AstNode *value = child->children[0].get();
 | 
				
			||||||
					if (value->type == AST_REALVALUE)
 | 
										if (value->type == AST_REALVALUE)
 | 
				
			||||||
						log_file_warning(filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n",
 | 
											log_file_warning(location.filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n",
 | 
				
			||||||
								log_id(cell), log_id(paraname), value->realvalue);
 | 
													log_id(cell), log_id(paraname), value->realvalue);
 | 
				
			||||||
					else if (value->type != AST_CONSTANT)
 | 
										else if (value->type != AST_CONSTANT)
 | 
				
			||||||
						input_error("Parameter %s.%s with non-constant value!\n",
 | 
											input_error("Parameter %s.%s with non-constant value!\n",
 | 
				
			||||||
| 
						 | 
					@ -2192,14 +2192,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
			int sz = children.size();
 | 
								int sz = children.size();
 | 
				
			||||||
			if (str == "$info") {
 | 
								if (str == "$info") {
 | 
				
			||||||
				if (sz > 0)
 | 
									if (sz > 0)
 | 
				
			||||||
					log_file_info(filename, location.first_line, "%s.\n", children[0]->str.c_str());
 | 
										log_file_info(location.filename, location.first_line, "%s.\n", children[0]->str.c_str());
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					log_file_info(filename, location.first_line, "\n");
 | 
										log_file_info(location.filename, location.first_line, "\n");
 | 
				
			||||||
			} else if (str == "$warning") {
 | 
								} else if (str == "$warning") {
 | 
				
			||||||
				if (sz > 0)
 | 
									if (sz > 0)
 | 
				
			||||||
					log_file_warning(filename, location.first_line, "%s.\n", children[0]->str.c_str());
 | 
										log_file_warning(location.filename, location.first_line, "%s.\n", children[0]->str.c_str());
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					log_file_warning(filename, location.first_line, "\n");
 | 
										log_file_warning(location.filename, location.first_line, "\n");
 | 
				
			||||||
			} else if (str == "$error") {
 | 
								} else if (str == "$error") {
 | 
				
			||||||
				if (sz > 0)
 | 
									if (sz > 0)
 | 
				
			||||||
					input_error("%s.\n", children[0]->str.c_str());
 | 
										input_error("%s.\n", children[0]->str.c_str());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,7 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_
 | 
				
			||||||
		while (node_arg->simplify(true, stage, -1, false)) { }
 | 
							while (node_arg->simplify(true, stage, -1, false)) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		VerilogFmtArg arg = {};
 | 
							VerilogFmtArg arg = {};
 | 
				
			||||||
		arg.filename = filename;
 | 
							arg.filename = location.filename;
 | 
				
			||||||
		arg.first_line = location.first_line;
 | 
							arg.first_line = location.first_line;
 | 
				
			||||||
		if (node_arg->type == AST_CONSTANT && node_arg->is_string) {
 | 
							if (node_arg->type == AST_CONSTANT && node_arg->is_string) {
 | 
				
			||||||
			arg.type = VerilogFmtArg::STRING;
 | 
								arg.type = VerilogFmtArg::STRING;
 | 
				
			||||||
| 
						 | 
					@ -173,10 +173,10 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_
 | 
				
			||||||
			arg.sig = node_arg->bitsAsConst();
 | 
								arg.sig = node_arg->bitsAsConst();
 | 
				
			||||||
			arg.signed_ = node_arg->is_signed;
 | 
								arg.signed_ = node_arg->is_signed;
 | 
				
			||||||
		} else if (may_fail) {
 | 
							} else if (may_fail) {
 | 
				
			||||||
			log_file_info(filename, location.first_line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1);
 | 
								log_file_info(location.filename, location.first_line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1);
 | 
				
			||||||
			return Fmt();
 | 
								return Fmt();
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			log_file_error(filename, location.first_line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1);
 | 
								log_file_error(location.filename, location.first_line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		args.push_back(arg);
 | 
							args.push_back(arg);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -240,20 +240,20 @@ void AstNode::annotateTypedEnums(AstNode *template_node)
 | 
				
			||||||
			RTLIL::Const val = enum_item->children[0]->bitsAsConst(width, is_signed);
 | 
								RTLIL::Const val = enum_item->children[0]->bitsAsConst(width, is_signed);
 | 
				
			||||||
			enum_item_str.append(val.as_string());
 | 
								enum_item_str.append(val.as_string());
 | 
				
			||||||
			//set attribute for available val to enum item name mappings
 | 
								//set attribute for available val to enum item name mappings
 | 
				
			||||||
			set_attribute(enum_item_str.c_str(), mkconst_str(enum_item->str));
 | 
								set_attribute(enum_item_str.c_str(), mkconst_str(location, enum_item->str));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::unique_ptr<AstNode> make_range(int left, int right, bool is_signed = false)
 | 
					static std::unique_ptr<AstNode> make_range(AstSrcLocType loc, int left, int right, bool is_signed = false)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// generate a pre-validated range node for a fixed signal range.
 | 
						// generate a pre-validated range node for a fixed signal range.
 | 
				
			||||||
	auto range = std::make_unique<AstNode>(AST_RANGE);
 | 
						auto range = std::make_unique<AstNode>(loc, AST_RANGE);
 | 
				
			||||||
	range->range_left = left;
 | 
						range->range_left = left;
 | 
				
			||||||
	range->range_right = right;
 | 
						range->range_right = right;
 | 
				
			||||||
	range->range_valid = true;
 | 
						range->range_valid = true;
 | 
				
			||||||
	range->children.push_back(AstNode::mkconst_int(left, true));
 | 
						range->children.push_back(AstNode::mkconst_int(loc, left, true));
 | 
				
			||||||
	range->children.push_back(AstNode::mkconst_int(right, true));
 | 
						range->children.push_back(AstNode::mkconst_int(loc, right, true));
 | 
				
			||||||
	range->is_signed = is_signed;
 | 
						range->is_signed = is_signed;
 | 
				
			||||||
	return range;
 | 
						return range;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -388,30 +388,32 @@ static int size_packed_struct(AstNode *snode, int base_offset)
 | 
				
			||||||
	return width;
 | 
						return width;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::unique_ptr<AstNode> node_int(int ival)
 | 
					static std::unique_ptr<AstNode> node_int(AstSrcLocType loc, int ival)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return AstNode::mkconst_int(ival, true);
 | 
						return AstNode::mkconst_int(loc, ival, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::unique_ptr<AstNode> multiply_by_const(std::unique_ptr<AstNode> expr_node, int stride)
 | 
					static std::unique_ptr<AstNode> multiply_by_const(std::unique_ptr<AstNode> expr_node, int stride)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return std::make_unique<AstNode>(AST_MUL, std::move(expr_node), node_int(stride));
 | 
						auto loc = expr_node->location;
 | 
				
			||||||
 | 
						return std::make_unique<AstNode>(loc, AST_MUL, std::move(expr_node), node_int(loc, stride));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static std::unique_ptr<AstNode> normalize_index(AstNode *expr, AstNode *decl_node, int dimension)
 | 
					static std::unique_ptr<AstNode> normalize_index(AstNode *expr, AstNode *decl_node, int dimension)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto new_expr = expr->clone();
 | 
						auto new_expr = expr->clone();
 | 
				
			||||||
 | 
						auto loc = expr->location;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int offset = decl_node->dimensions[dimension].range_right;
 | 
						int offset = decl_node->dimensions[dimension].range_right;
 | 
				
			||||||
	if (offset) {
 | 
						if (offset) {
 | 
				
			||||||
		new_expr = std::make_unique<AstNode>(AST_SUB, std::move(new_expr), node_int(offset));
 | 
							new_expr = std::make_unique<AstNode>(loc, AST_SUB, std::move(new_expr), node_int(loc, offset));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Packed dimensions are normally indexed by lsb, while unpacked dimensions are normally indexed by msb.
 | 
						// Packed dimensions are normally indexed by lsb, while unpacked dimensions are normally indexed by msb.
 | 
				
			||||||
	if ((dimension < decl_node->unpacked_dimensions) ^ decl_node->dimensions[dimension].range_swapped) {
 | 
						if ((dimension < decl_node->unpacked_dimensions) ^ decl_node->dimensions[dimension].range_swapped) {
 | 
				
			||||||
		// Swap the index if the dimension is declared the "wrong" way.
 | 
							// Swap the index if the dimension is declared the "wrong" way.
 | 
				
			||||||
		int left = decl_node->dimensions[dimension].range_width - 1;
 | 
							int left = decl_node->dimensions[dimension].range_width - 1;
 | 
				
			||||||
		new_expr = std::make_unique<AstNode>(AST_SUB, node_int(left), std::move(new_expr));
 | 
							new_expr = std::make_unique<AstNode>(loc, AST_SUB, node_int(loc, left), std::move(new_expr));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return new_expr;
 | 
						return new_expr;
 | 
				
			||||||
| 
						 | 
					@ -433,7 +435,7 @@ static std::unique_ptr<AstNode> index_msb_offset(std::unique_ptr<AstNode> lsb_of
 | 
				
			||||||
	std::unique_ptr<AstNode> add_offset;
 | 
						std::unique_ptr<AstNode> add_offset;
 | 
				
			||||||
	if (rnode->children.size() == 1) {
 | 
						if (rnode->children.size() == 1) {
 | 
				
			||||||
		// Index, e.g. s.a[i]
 | 
							// Index, e.g. s.a[i]
 | 
				
			||||||
		add_offset = node_int(stride - 1);
 | 
							add_offset = node_int(rnode->location, stride - 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		// rnode->children.size() == 2
 | 
							// rnode->children.size() == 2
 | 
				
			||||||
| 
						 | 
					@ -620,7 +622,7 @@ const RTLIL::Module* AstNode::lookup_cell_module()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto reprocess_after = [this] (const std::string &modname) {
 | 
						auto reprocess_after = [this] (const std::string &modname) {
 | 
				
			||||||
		if (!attributes.count(ID::reprocess_after))
 | 
							if (!attributes.count(ID::reprocess_after))
 | 
				
			||||||
			set_attribute(ID::reprocess_after, AstNode::mkconst_str(modname));
 | 
								set_attribute(ID::reprocess_after, AstNode::mkconst_str(location, modname));
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const AstNode *celltype = nullptr;
 | 
						const AstNode *celltype = nullptr;
 | 
				
			||||||
| 
						 | 
					@ -929,7 +931,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
	log("-------------\n");
 | 
						log("-------------\n");
 | 
				
			||||||
	log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, filename.c_str(), location.first_line, type2str(type).c_str(), this);
 | 
						log("AST simplify[%d] depth %d at %s:%d on %s %p:\n", stage, recursion_counter, location.filename.c_str(), location.first_line, type2str(type).c_str(), this);
 | 
				
			||||||
	log("const_fold=%d, stage=%d, width_hint=%d, sign_hint=%d\n",
 | 
						log("const_fold=%d, stage=%d, width_hint=%d, sign_hint=%d\n",
 | 
				
			||||||
			int(const_fold), int(stage), int(width_hint), int(sign_hint));
 | 
								int(const_fold), int(stage), int(width_hint), int(sign_hint));
 | 
				
			||||||
	// dumpAst(nullptr, "> ");
 | 
						// dumpAst(nullptr, "> ");
 | 
				
			||||||
| 
						 | 
					@ -1020,7 +1022,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
					for (auto &it : node->attributes)
 | 
										for (auto &it : node->attributes)
 | 
				
			||||||
						if (it.first != ID::mem2reg)
 | 
											if (it.first != ID::mem2reg)
 | 
				
			||||||
							reg->set_attribute(it.first, it.second->clone());
 | 
												reg->set_attribute(it.first, it.second->clone());
 | 
				
			||||||
					reg->filename = node->filename;
 | 
										reg->location.filename = node->location.filename;
 | 
				
			||||||
					reg->location = node->location;
 | 
										reg->location = node->location;
 | 
				
			||||||
					while (reg->simplify(true, 1, -1, false)) { }
 | 
										while (reg->simplify(true, 1, -1, false)) { }
 | 
				
			||||||
					children.push_back(std::move(reg));
 | 
										children.push_back(std::move(reg));
 | 
				
			||||||
| 
						 | 
					@ -1049,7 +1051,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
	// note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
 | 
						// note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
 | 
				
			||||||
	if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" ||
 | 
						if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" ||
 | 
				
			||||||
			str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) {
 | 
								str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) {
 | 
				
			||||||
		log_file_warning(filename, location.first_line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str());
 | 
							log_file_warning(location.filename, location.first_line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str());
 | 
				
			||||||
		delete_children();
 | 
							delete_children();
 | 
				
			||||||
		str = std::string();
 | 
							str = std::string();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1059,7 +1061,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
		 str == "$write"   || str == "$writeb"   || str == "$writeh"   || str == "$writeo"))
 | 
							 str == "$write"   || str == "$writeb"   || str == "$writeh"   || str == "$writeo"))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!current_always) {
 | 
							if (!current_always) {
 | 
				
			||||||
			log_file_warning(filename, location.first_line, "System task `%s' outside initial or always block is unsupported.\n", str.c_str());
 | 
								log_file_warning(location.filename, location.first_line, "System task `%s' outside initial or always block is unsupported.\n", str.c_str());
 | 
				
			||||||
			delete_children();
 | 
								delete_children();
 | 
				
			||||||
			str = std::string();
 | 
								str = std::string();
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
| 
						 | 
					@ -1336,7 +1338,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// create the indirection wire
 | 
									// create the indirection wire
 | 
				
			||||||
				std::stringstream sstr;
 | 
									std::stringstream sstr;
 | 
				
			||||||
				sstr << "$indirect$" << ref->name.c_str() << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
									sstr << "$indirect$" << ref->name.c_str() << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
				
			||||||
				std::string tmp_str = sstr.str();
 | 
									std::string tmp_str = sstr.str();
 | 
				
			||||||
				add_wire_for_ref(ref, tmp_str);
 | 
									add_wire_for_ref(ref, tmp_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2174,7 +2176,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
			int width = std::abs(children[1]->range_left - children[1]->range_right) + 1;
 | 
								int width = std::abs(children[1]->range_left - children[1]->range_right) + 1;
 | 
				
			||||||
			if (children[0]->type == AST_REALVALUE) {
 | 
								if (children[0]->type == AST_REALVALUE) {
 | 
				
			||||||
				RTLIL::Const constvalue = children[0]->realAsConst(width);
 | 
									RTLIL::Const constvalue = children[0]->realAsConst(width);
 | 
				
			||||||
				log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n",
 | 
									log_file_warning(location.filename, location.first_line, "converting real value %e to binary %s.\n",
 | 
				
			||||||
						children[0]->realvalue, log_signal(constvalue));
 | 
											children[0]->realvalue, log_signal(constvalue));
 | 
				
			||||||
				children[0] = mkconst_bits(constvalue.to_bits(), sign_hint);
 | 
									children[0] = mkconst_bits(constvalue.to_bits(), sign_hint);
 | 
				
			||||||
				fixup_hierarchy_flags();
 | 
									fixup_hierarchy_flags();
 | 
				
			||||||
| 
						 | 
					@ -2316,7 +2318,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
			std::swap(data_range_left, data_range_right);
 | 
								std::swap(data_range_left, data_range_right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::stringstream sstr;
 | 
							std::stringstream sstr;
 | 
				
			||||||
		sstr << "$mem2bits$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
							sstr << "$mem2bits$" << str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
				
			||||||
		std::string wire_id = sstr.str();
 | 
							std::string wire_id = sstr.str();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto wire_owned = std::make_unique<AstNode>(AST_WIRE, std::make_unique<AstNode>(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
 | 
							auto wire_owned = std::make_unique<AstNode>(AST_WIRE, std::make_unique<AstNode>(AST_RANGE, mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
 | 
				
			||||||
| 
						 | 
					@ -2536,7 +2538,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
 | 
				
			||||||
		for (size_t i = 0; i < children.size(); i++)
 | 
							for (size_t i = 0; i < children.size(); i++)
 | 
				
			||||||
			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF)
 | 
								if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				log_assert(!sv_mode);
 | 
									log_assert(!sv_mode_but_global_and_used_for_literally_one_condition);
 | 
				
			||||||
				children[i]->input_error("Local declaration in unnamed block is only supported in SystemVerilog mode!\n");
 | 
									children[i]->input_error("Local declaration in unnamed block is only supported in SystemVerilog mode!\n");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -3072,7 +3074,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto wire_tmp_owned = std::make_unique<AstNode>(AST_WIRE, std::make_unique<AstNode>(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true)));
 | 
								auto wire_tmp_owned = std::make_unique<AstNode>(AST_WIRE, std::make_unique<AstNode>(AST_RANGE, mkconst_int(width_hint-1, true), mkconst_int(0, true)));
 | 
				
			||||||
			auto wire_tmp = wire_tmp_owned.get();
 | 
								auto wire_tmp = wire_tmp_owned.get();
 | 
				
			||||||
			wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++);
 | 
								wire_tmp->str = stringf("$splitcmplxassign$%s:%d$%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line, autoidx++);
 | 
				
			||||||
			current_scope[wire_tmp->str] = wire_tmp;
 | 
								current_scope[wire_tmp->str] = wire_tmp;
 | 
				
			||||||
			current_ast_mod->children.push_back(std::move(wire_tmp_owned));
 | 
								current_ast_mod->children.push_back(std::move(wire_tmp_owned));
 | 
				
			||||||
			wire_tmp->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
 | 
								wire_tmp->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
 | 
				
			||||||
| 
						 | 
					@ -3114,7 +3116,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
				
			||||||
			input_error("Insufficient number of array indices for %s.\n", log_id(str));
 | 
								input_error("Insufficient number of array indices for %s.\n", log_id(str));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::stringstream sstr;
 | 
							std::stringstream sstr;
 | 
				
			||||||
		sstr << "$memwr$" << children[0]->str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
							sstr << "$memwr$" << children[0]->str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
				
			||||||
		std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
 | 
							std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int mem_width, mem_size, addr_bits;
 | 
							int mem_width, mem_size, addr_bits;
 | 
				
			||||||
| 
						 | 
					@ -3385,7 +3387,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
				
			||||||
					auto* reg = reg_owned.get();
 | 
										auto* reg = reg_owned.get();
 | 
				
			||||||
					current_ast_mod->children.push_back(std::move(reg_owned));
 | 
										current_ast_mod->children.push_back(std::move(reg_owned));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					reg->str = stringf("$past$%s:%d$%d$%d", RTLIL::encode_filename(filename).c_str(), location.first_line, myidx, i);
 | 
										reg->str = stringf("$past$%s:%d$%d$%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line, myidx, i);
 | 
				
			||||||
					reg->is_reg = true;
 | 
										reg->is_reg = true;
 | 
				
			||||||
					reg->is_signed = sign_hint;
 | 
										reg->is_signed = sign_hint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3761,7 +3763,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
				
			||||||
						input_error("Failed to evaluate DPI function with non-constant argument.\n");
 | 
											input_error("Failed to evaluate DPI function with non-constant argument.\n");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				newNode = dpi_call(rtype, fname, argtypes, args);
 | 
									newNode = dpi_call(dpi_decl->location, rtype, fname, argtypes, args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				goto apply_newNode;
 | 
									goto apply_newNode;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -3845,7 +3847,7 @@ skip_dynamic_range_lvalue_expansion:;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::stringstream sstr;
 | 
							std::stringstream sstr;
 | 
				
			||||||
		sstr << str << "$func$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++) << '.';
 | 
							sstr << str << "$func$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++) << '.';
 | 
				
			||||||
		std::string prefix = sstr.str();
 | 
							std::string prefix = sstr.str();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto* decl = current_scope[str];
 | 
							auto* decl = current_scope[str];
 | 
				
			||||||
| 
						 | 
					@ -4375,7 +4377,7 @@ apply_newNode:
 | 
				
			||||||
		// newNode->dumpAst(stderr, "+ ");
 | 
							// newNode->dumpAst(stderr, "+ ");
 | 
				
			||||||
		log_assert(newNode != nullptr);
 | 
							log_assert(newNode != nullptr);
 | 
				
			||||||
		// newNode->null_check();
 | 
							// newNode->null_check();
 | 
				
			||||||
		newNode->filename = filename;
 | 
							newNode->location.filename = location.filename;
 | 
				
			||||||
		newNode->location = location;
 | 
							newNode->location = location;
 | 
				
			||||||
		newNode->cloneInto(*this);
 | 
							newNode->cloneInto(*this);
 | 
				
			||||||
		fixup_hierarchy_flags();
 | 
							fixup_hierarchy_flags();
 | 
				
			||||||
| 
						 | 
					@ -4422,7 +4424,7 @@ std::unique_ptr<AstNode> AstNode::readmem(bool is_readmemh, std::string mem_file
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
		char slash = '/';
 | 
							char slash = '/';
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		std::string path = filename.substr(0, filename.find_last_of(slash)+1);
 | 
							std::string path = location.filename.substr(0, location.filename.find_last_of(slash)+1);
 | 
				
			||||||
		f.open(path + mem_filename.c_str());
 | 
							f.open(path + mem_filename.c_str());
 | 
				
			||||||
		yosys_input_files.insert(path + mem_filename);
 | 
							yosys_input_files.insert(path + mem_filename);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -4479,7 +4481,7 @@ std::unique_ptr<AstNode> AstNode::readmem(bool is_readmemh, std::string mem_file
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			VERILOG_FRONTEND::ConstParser p{mem_filename, std::nullopt};
 | 
								VERILOG_FRONTEND::ConstParser p{memory->location};
 | 
				
			||||||
			auto value = p.const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token);
 | 
								auto value = p.const2ast(stringf("%d'%c", mem_width, is_readmemh ? 'h' : 'b') + token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (unconditional_init)
 | 
								if (unconditional_init)
 | 
				
			||||||
| 
						 | 
					@ -4701,7 +4703,7 @@ static void mark_memories_assign_lhs_complex(dict<AstNode*, pool<std::string>> &
 | 
				
			||||||
	if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) {
 | 
						if (that->type == AST_IDENTIFIER && that->id2ast && that->id2ast->type == AST_MEMORY) {
 | 
				
			||||||
		AstNode *mem = that->id2ast;
 | 
							AstNode *mem = that->id2ast;
 | 
				
			||||||
		if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS))
 | 
							if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_CMPLX_LHS))
 | 
				
			||||||
			mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(that->filename).c_str(), that->location.first_line));
 | 
								mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(that->location.filename).c_str(), that->location.first_line));
 | 
				
			||||||
		mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS;
 | 
							mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CMPLX_LHS;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -4729,14 +4731,14 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
 | 
				
			||||||
			// activate mem2reg if this is assigned in an async proc
 | 
								// activate mem2reg if this is assigned in an async proc
 | 
				
			||||||
			if (flags & AstNode::MEM2REG_FL_ASYNC) {
 | 
								if (flags & AstNode::MEM2REG_FL_ASYNC) {
 | 
				
			||||||
				if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC))
 | 
									if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ASYNC))
 | 
				
			||||||
					mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line));
 | 
										mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line));
 | 
				
			||||||
				mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC;
 | 
									mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ASYNC;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// remember if this is assigned blocking (=)
 | 
								// remember if this is assigned blocking (=)
 | 
				
			||||||
			if (type == AST_ASSIGN_EQ) {
 | 
								if (type == AST_ASSIGN_EQ) {
 | 
				
			||||||
				if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1))
 | 
									if (!(proc_flags[mem] & AstNode::MEM2REG_FL_EQ1))
 | 
				
			||||||
					mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line));
 | 
										mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line));
 | 
				
			||||||
				proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
 | 
									proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4753,11 +4755,11 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
 | 
				
			||||||
			// remember where this is
 | 
								// remember where this is
 | 
				
			||||||
			if (flags & MEM2REG_FL_INIT) {
 | 
								if (flags & MEM2REG_FL_INIT) {
 | 
				
			||||||
				if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
 | 
									if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
 | 
				
			||||||
					mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line));
 | 
										mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line));
 | 
				
			||||||
				mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT;
 | 
									mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_INIT;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE))
 | 
									if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_ELSE))
 | 
				
			||||||
					mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line));
 | 
										mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line));
 | 
				
			||||||
				mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE;
 | 
									mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_SET_ELSE;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -4774,7 +4776,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// flag if used after blocking assignment (in same proc)
 | 
							// flag if used after blocking assignment (in same proc)
 | 
				
			||||||
		if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) {
 | 
							if ((proc_flags[mem] & AstNode::MEM2REG_FL_EQ1) && !(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_EQ2)) {
 | 
				
			||||||
			mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(filename).c_str(), location.first_line));
 | 
								mem2reg_places[mem].insert(stringf("%s:%d", RTLIL::encode_filename(location.filename).c_str(), location.first_line));
 | 
				
			||||||
			mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2;
 | 
								mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_EQ2;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -4960,7 +4962,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
 | 
				
			||||||
			children[0]->children[0]->children[0]->type != AST_CONSTANT)
 | 
								children[0]->children[0]->children[0]->type != AST_CONSTANT)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		std::stringstream sstr;
 | 
							std::stringstream sstr;
 | 
				
			||||||
		sstr << "$mem2reg_wr$" << children[0]->str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
							sstr << "$mem2reg_wr$" << children[0]->str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
				
			||||||
		std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
 | 
							std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int mem_width, mem_size, addr_bits;
 | 
							int mem_width, mem_size, addr_bits;
 | 
				
			||||||
| 
						 | 
					@ -5079,7 +5081,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			std::stringstream sstr;
 | 
								std::stringstream sstr;
 | 
				
			||||||
			sstr << "$mem2reg_rd$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
								sstr << "$mem2reg_rd$" << str << "$" << RTLIL::encode_filename(location.filename) << ":" << location.first_line << "$" << (autoidx++);
 | 
				
			||||||
			std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
 | 
								std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			int mem_width, mem_size, addr_bits;
 | 
								int mem_width, mem_size, addr_bits;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y
 | 
				
			||||||
 | 
					
 | 
				
			||||||
frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc
 | 
					frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc
 | 
				
			||||||
frontends/verilog/verilog_frontend.h: frontends/verilog/verilog_parser.tab.hh
 | 
					frontends/verilog/verilog_frontend.h: frontends/verilog/verilog_parser.tab.hh
 | 
				
			||||||
 | 
					frontends/verilog/verilog_error.h: frontends/verilog/verilog_parser.tab.hh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l frontends/verilog/verilog_parser.tab.cc
 | 
					frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l frontends/verilog/verilog_parser.tab.cc
 | 
				
			||||||
	$(Q) mkdir -p $(dir $@)
 | 
						$(Q) mkdir -p $(dir $@)
 | 
				
			||||||
| 
						 | 
					@ -24,5 +25,6 @@ OBJS += frontends/verilog/verilog_parser.tab.o
 | 
				
			||||||
OBJS += frontends/verilog/verilog_lexer.o
 | 
					OBJS += frontends/verilog/verilog_lexer.o
 | 
				
			||||||
OBJS += frontends/verilog/preproc.o
 | 
					OBJS += frontends/verilog/preproc.o
 | 
				
			||||||
OBJS += frontends/verilog/verilog_frontend.o
 | 
					OBJS += frontends/verilog/verilog_frontend.o
 | 
				
			||||||
 | 
					OBJS += frontends/verilog/verilog_error.o
 | 
				
			||||||
OBJS += frontends/verilog/const2ast.o
 | 
					OBJS += frontends/verilog/const2ast.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,11 +46,8 @@ using namespace VERILOG_FRONTEND;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string ConstParser::fmt_maybe_loc(std::string msg) {
 | 
					std::string ConstParser::fmt_maybe_loc(std::string msg) {
 | 
				
			||||||
	std::string s;
 | 
						std::string s;
 | 
				
			||||||
	s += filename.value_or("INTERNAL");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (loc)
 | 
						s += stringf("%s:%d:", loc.filename, loc.first_line);
 | 
				
			||||||
		s += stringf("%d", loc->first_line);
 | 
					 | 
				
			||||||
	s += ": ";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s += msg;
 | 
						s += msg;
 | 
				
			||||||
	return s;
 | 
						return s;
 | 
				
			||||||
| 
						 | 
					@ -191,7 +188,7 @@ std::unique_ptr<AstNode> ConstParser::const2ast(std::string code, char case_type
 | 
				
			||||||
				ch = ch >> 1;
 | 
									ch = ch >> 1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		auto ast = AstNode::mkconst_bits(data, false);
 | 
							auto ast = AstNode::mkconst_bits(loc, data, false);
 | 
				
			||||||
		ast->str = code;
 | 
							ast->str = code;
 | 
				
			||||||
		return ast;
 | 
							return ast;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -210,7 +207,7 @@ std::unique_ptr<AstNode> ConstParser::const2ast(std::string code, char case_type
 | 
				
			||||||
		my_strtobin(data, str, -1, 10, case_type, false);
 | 
							my_strtobin(data, str, -1, 10, case_type, false);
 | 
				
			||||||
		if (data.back() == State::S1)
 | 
							if (data.back() == State::S1)
 | 
				
			||||||
			data.push_back(State::S0);
 | 
								data.push_back(State::S0);
 | 
				
			||||||
		return AstNode::mkconst_bits(data, true);
 | 
							return AstNode::mkconst_bits(loc, data, true);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// unsized constant
 | 
						// unsized constant
 | 
				
			||||||
| 
						 | 
					@ -258,7 +255,7 @@ std::unique_ptr<AstNode> ConstParser::const2ast(std::string code, char case_type
 | 
				
			||||||
			if (is_signed && data.back() == State::S1)
 | 
								if (is_signed && data.back() == State::S1)
 | 
				
			||||||
				data.push_back(State::S0);
 | 
									data.push_back(State::S0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return AstNode::mkconst_bits(data, is_signed, is_unsized);
 | 
							return AstNode::mkconst_bits(loc, data, is_signed, is_unsized);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,10 +32,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "verilog_frontend.h"
 | 
					#include "verilog_frontend.h"
 | 
				
			||||||
#include "verilog_lexer.h"
 | 
					#include "verilog_lexer.h"
 | 
				
			||||||
 | 
					#include "verilog_error.h"
 | 
				
			||||||
#include "preproc.h"
 | 
					#include "preproc.h"
 | 
				
			||||||
#include "kernel/yosys.h"
 | 
					#include "kernel/yosys.h"
 | 
				
			||||||
#include "libs/sha1/sha1.h"
 | 
					#include "libs/sha1/sha1.h"
 | 
				
			||||||
#include <stdarg.h>
 | 
					#include <stdarg.h>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_NAMESPACE_BEGIN
 | 
					YOSYS_NAMESPACE_BEGIN
 | 
				
			||||||
using namespace VERILOG_FRONTEND;
 | 
					using namespace VERILOG_FRONTEND;
 | 
				
			||||||
| 
						 | 
					@ -48,7 +50,7 @@ static std::list<std::vector<std::string>> verilog_defaults_stack;
 | 
				
			||||||
static void error_on_dpi_function(AST::AstNode *node)
 | 
					static void error_on_dpi_function(AST::AstNode *node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (node->type == AST::AST_DPI_FUNCTION)
 | 
					    if (node->type == AST::AST_DPI_FUNCTION)
 | 
				
			||||||
		log_file_error(node->filename, node->location.first_line, "Found DPI function %s.\n", node->str.c_str());
 | 
					        err_at_ast(node->location, "Found DPI function %s.\n", node->str.c_str());
 | 
				
			||||||
    for (auto& child : node->children)
 | 
					    for (auto& child : node->children)
 | 
				
			||||||
        error_on_dpi_function(child.get());
 | 
					        error_on_dpi_function(child.get());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -69,15 +71,7 @@ static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct VerilogFrontend : public Frontend {
 | 
					struct VerilogFrontend : public Frontend {
 | 
				
			||||||
	ParseMode parse_mode;
 | 
						VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { }
 | 
				
			||||||
	ParseState parse_state;
 | 
					 | 
				
			||||||
	VerilogLexer lexer;
 | 
					 | 
				
			||||||
	frontend_verilog_yy::parser parser;
 | 
					 | 
				
			||||||
	VerilogFrontend() : Frontend("verilog", "read modules from Verilog file"),
 | 
					 | 
				
			||||||
						parse_mode(),
 | 
					 | 
				
			||||||
						parse_state(),
 | 
					 | 
				
			||||||
						lexer(&parse_state, &parse_mode),
 | 
					 | 
				
			||||||
						parser(&lexer, &parse_state, &parse_mode) { }
 | 
					 | 
				
			||||||
	void help() override
 | 
						void help() override
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
							//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
				
			||||||
| 
						 | 
					@ -259,6 +253,8 @@ struct VerilogFrontend : public Frontend {
 | 
				
			||||||
		bool flag_dump_vlog1 = false;
 | 
							bool flag_dump_vlog1 = false;
 | 
				
			||||||
		bool flag_dump_vlog2 = false;
 | 
							bool flag_dump_vlog2 = false;
 | 
				
			||||||
		bool flag_dump_rtlil = false;
 | 
							bool flag_dump_rtlil = false;
 | 
				
			||||||
 | 
							bool flag_debug_lexer = false;
 | 
				
			||||||
 | 
							bool flag_debug_parser = false;
 | 
				
			||||||
		bool flag_nolatches = false;
 | 
							bool flag_nolatches = false;
 | 
				
			||||||
		bool flag_nomeminit = false;
 | 
							bool flag_nomeminit = false;
 | 
				
			||||||
		bool flag_nomem2reg = false;
 | 
							bool flag_nomem2reg = false;
 | 
				
			||||||
| 
						 | 
					@ -281,8 +277,8 @@ struct VerilogFrontend : public Frontend {
 | 
				
			||||||
		std::list<std::string> include_dirs;
 | 
							std::list<std::string> include_dirs;
 | 
				
			||||||
		std::list<std::string> attributes;
 | 
							std::list<std::string> attributes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		lexer.set_debug(false);
 | 
							ParseMode parse_mode;
 | 
				
			||||||
		parser.set_debug_level(0);
 | 
							ParseState parse_state;
 | 
				
			||||||
		parse_mode.sv = false;
 | 
							parse_mode.sv = false;
 | 
				
			||||||
		parse_mode.formal = false;
 | 
							parse_mode.formal = false;
 | 
				
			||||||
		parse_mode.noassert = false;
 | 
							parse_mode.noassert = false;
 | 
				
			||||||
| 
						 | 
					@ -340,8 +336,8 @@ struct VerilogFrontend : public Frontend {
 | 
				
			||||||
				flag_dump_ast2 = true;
 | 
									flag_dump_ast2 = true;
 | 
				
			||||||
				flag_dump_vlog1 = true;
 | 
									flag_dump_vlog1 = true;
 | 
				
			||||||
				flag_dump_vlog2 = true;
 | 
									flag_dump_vlog2 = true;
 | 
				
			||||||
				lexer.set_debug(true);
 | 
									flag_debug_lexer = true;
 | 
				
			||||||
				parser.set_debug_level(1);
 | 
									flag_debug_parser = true;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (arg == "-dump_ast1") {
 | 
								if (arg == "-dump_ast1") {
 | 
				
			||||||
| 
						 | 
					@ -370,6 +366,8 @@ struct VerilogFrontend : public Frontend {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (arg == "-yydebug") {
 | 
								if (arg == "-yydebug") {
 | 
				
			||||||
				flag_yydebug = true;
 | 
									flag_yydebug = true;
 | 
				
			||||||
 | 
									flag_debug_lexer = true;
 | 
				
			||||||
 | 
									flag_debug_parser = true;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (arg == "-nolatches") {
 | 
								if (arg == "-nolatches") {
 | 
				
			||||||
| 
						 | 
					@ -481,6 +479,11 @@ struct VerilogFrontend : public Frontend {
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VerilogLexer lexer(&parse_state, &parse_mode, &filename);
 | 
				
			||||||
 | 
							frontend_verilog_yy::parser parser(&lexer, &parse_state, &parse_mode);
 | 
				
			||||||
 | 
							lexer.set_debug(flag_debug_lexer);
 | 
				
			||||||
 | 
							parser.set_debug_level(flag_debug_parser ? 1 : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (parse_mode.formal || !flag_nosynthesis)
 | 
							if (parse_mode.formal || !flag_nosynthesis)
 | 
				
			||||||
			defines_map.add(parse_mode.formal ? "FORMAL" : "SYNTHESIS", "1");
 | 
								defines_map.add(parse_mode.formal ? "FORMAL" : "SYNTHESIS", "1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -491,10 +494,10 @@ struct VerilogFrontend : public Frontend {
 | 
				
			||||||
		log("Parsing %s%s input from `%s' to AST representation.\n",
 | 
							log("Parsing %s%s input from `%s' to AST representation.\n",
 | 
				
			||||||
				parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str());
 | 
									parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		AST::current_filename = filename;
 | 
							AST::sv_mode_but_global_and_used_for_literally_one_condition = parse_mode.sv;
 | 
				
			||||||
		AST::sv_mode = parse_mode.sv;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		parse_state.current_ast = new AST::AstNode(AST::AST_DESIGN);
 | 
							AstSrcLocType top_loc = AstSrcLocType ( "read_verilog", 0, 0, 0, 0);
 | 
				
			||||||
 | 
							parse_state.current_ast = new AST::AstNode(top_loc, AST::AST_DESIGN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		parse_state.lexin = f;
 | 
							parse_state.lexin = f;
 | 
				
			||||||
		std::string code_after_preproc;
 | 
							std::string code_after_preproc;
 | 
				
			||||||
| 
						 | 
					@ -522,10 +525,6 @@ struct VerilogFrontend : public Frontend {
 | 
				
			||||||
		// add a new empty type map to allow overriding existing global definitions
 | 
							// add a new empty type map to allow overriding existing global definitions
 | 
				
			||||||
		parse_state.user_type_stack.push_back(UserTypeMap());
 | 
							parse_state.user_type_stack.push_back(UserTypeMap());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		parser.~parser();
 | 
					 | 
				
			||||||
		lexer.~VerilogLexer();
 | 
					 | 
				
			||||||
		new (&lexer) VerilogLexer(&parse_state, &parse_mode);
 | 
					 | 
				
			||||||
		new (&parser) frontend_verilog_yy::parser(&lexer, &parse_state, &parse_mode);
 | 
					 | 
				
			||||||
		if (flag_yydebug) {
 | 
							if (flag_yydebug) {
 | 
				
			||||||
			lexer.set_debug(true);
 | 
								lexer.set_debug(true);
 | 
				
			||||||
			parser.set_debug_level(1);
 | 
								parser.set_debug_level(1);
 | 
				
			||||||
| 
						 | 
					@ -537,7 +536,7 @@ struct VerilogFrontend : public Frontend {
 | 
				
			||||||
			if (child->type == AST::AST_MODULE)
 | 
								if (child->type == AST::AST_MODULE)
 | 
				
			||||||
				for (auto &attr : attributes)
 | 
									for (auto &attr : attributes)
 | 
				
			||||||
					if (child->attributes.count(attr) == 0)
 | 
										if (child->attributes.count(attr) == 0)
 | 
				
			||||||
						child->attributes[attr] = AST::AstNode::mkconst_int(1, false);
 | 
											child->attributes[attr] = AST::AstNode::mkconst_int(top_loc, 1, false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (flag_nodpi)
 | 
							if (flag_nodpi)
 | 
				
			||||||
| 
						 | 
					@ -776,24 +775,4 @@ struct VerilogFileList : public Pass {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[noreturn]]
 | 
					 | 
				
			||||||
void VERILOG_FRONTEND::verr_at(std::string filename, int begin_line, char const *fmt, va_list ap)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    char buffer[1024];
 | 
					 | 
				
			||||||
    char *p = buffer;
 | 
					 | 
				
			||||||
    p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
 | 
					 | 
				
			||||||
    p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
 | 
					 | 
				
			||||||
    YOSYS_NAMESPACE_PREFIX log_file_error(filename, begin_line, "%s", buffer);
 | 
					 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[noreturn]]
 | 
					 | 
				
			||||||
void VERILOG_FRONTEND::err_at_ast(AstSrcLocType loc, char const *fmt, ...)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	va_list args;
 | 
					 | 
				
			||||||
	va_start(args, fmt);
 | 
					 | 
				
			||||||
	verr_at(AST::current_filename, loc.first_line, fmt, args);
 | 
					 | 
				
			||||||
	va_end(args);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
YOSYS_NAMESPACE_END
 | 
					YOSYS_NAMESPACE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <list>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_NAMESPACE_BEGIN
 | 
					YOSYS_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,8 +46,7 @@ namespace VERILOG_FRONTEND
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Ephemeral context class */
 | 
						/* Ephemeral context class */
 | 
				
			||||||
	struct ConstParser {
 | 
						struct ConstParser {
 | 
				
			||||||
		std::optional<std::string> filename;
 | 
							AST::AstSrcLocType loc;
 | 
				
			||||||
		std::optional<AST::AstSrcLocType> loc;
 | 
					 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
		std::string fmt_maybe_loc(std::string msg);
 | 
							std::string fmt_maybe_loc(std::string msg);
 | 
				
			||||||
		void log_maybe_loc_error(std::string msg);
 | 
							void log_maybe_loc_error(std::string msg);
 | 
				
			||||||
| 
						 | 
					@ -64,8 +62,6 @@ namespace VERILOG_FRONTEND
 | 
				
			||||||
		std::unique_ptr<AST::AstNode> const2ast(std::string code, char case_type = 0, bool warn_z = false);
 | 
							std::unique_ptr<AST::AstNode> const2ast(std::string code, char case_type = 0, bool warn_z = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	[[noreturn]]
 | 
					 | 
				
			||||||
	extern void err_at_ast(AST::AstSrcLocType loc, char const *fmt, ...);
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_NAMESPACE_END
 | 
					YOSYS_NAMESPACE_END
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,18 +4,20 @@
 | 
				
			||||||
#include "kernel/yosys.h"
 | 
					#include "kernel/yosys.h"
 | 
				
			||||||
#include "frontends/ast/ast.h"
 | 
					#include "frontends/ast/ast.h"
 | 
				
			||||||
#include "frontends/verilog/verilog_parser.tab.hh"
 | 
					#include "frontends/verilog/verilog_parser.tab.hh"
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
YOSYS_NAMESPACE_BEGIN
 | 
					YOSYS_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace VERILOG_FRONTEND {
 | 
					namespace VERILOG_FRONTEND {
 | 
				
			||||||
	[[noreturn]]
 | 
					 | 
				
			||||||
	extern void verr_at(std::string filename, int begin_line, char const *fmt, va_list ap);
 | 
					 | 
				
			||||||
	using parser = frontend_verilog_yy::parser;
 | 
						using parser = frontend_verilog_yy::parser;
 | 
				
			||||||
	class VerilogLexer : public frontend_verilog_yyFlexLexer {
 | 
						class VerilogLexer : public frontend_verilog_yyFlexLexer {
 | 
				
			||||||
		ParseState* extra;
 | 
							ParseState* extra;
 | 
				
			||||||
		ParseMode* mode;
 | 
							ParseMode* mode;
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		VerilogLexer(ParseState* e, ParseMode* m) : frontend_verilog_yyFlexLexer(e->lexin), extra(e), mode(m) {}
 | 
							parser::location_type out_loc; // TODO private?
 | 
				
			||||||
 | 
							VerilogLexer(ParseState* e, ParseMode* m, std::string* filename) : frontend_verilog_yyFlexLexer(e->lexin), extra(e), mode(m) {
 | 
				
			||||||
 | 
								out_loc.begin.filename = filename;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		~VerilogLexer() override {}
 | 
							~VerilogLexer() override {}
 | 
				
			||||||
		// autogenerated body due to YY_DECL
 | 
							// autogenerated body due to YY_DECL
 | 
				
			||||||
		parser::symbol_type nextToken();
 | 
							parser::symbol_type nextToken();
 | 
				
			||||||
| 
						 | 
					@ -24,19 +26,9 @@ namespace VERILOG_FRONTEND {
 | 
				
			||||||
		parser::symbol_type terminate() {
 | 
							parser::symbol_type terminate() {
 | 
				
			||||||
			return parser::make_FRONTEND_VERILOG_YYEOF(out_loc);
 | 
								return parser::make_FRONTEND_VERILOG_YYEOF(out_loc);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		parser::location_type out_loc;
 | 
					 | 
				
			||||||
		[[noreturn]]
 | 
					 | 
				
			||||||
		void err(char const *fmt, ...)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			va_list args;
 | 
					 | 
				
			||||||
			va_start(args, fmt);
 | 
					 | 
				
			||||||
			verr_at(AST::current_filename, yylineno, fmt, args);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
		std::vector<std::string> fn_stack;
 | 
							std::vector<std::string> fn_stack;
 | 
				
			||||||
		std::vector<int> ln_stack;
 | 
							std::vector<int> ln_stack;
 | 
				
			||||||
		parser::location_type real_loc;
 | 
					 | 
				
			||||||
		parser::location_type old_loc;
 | 
					 | 
				
			||||||
		int LexerInput(char* buf, int max_size) override {
 | 
							int LexerInput(char* buf, int max_size) override {
 | 
				
			||||||
			return readsome(*extra->lexin, buf, max_size);
 | 
								return readsome(*extra->lexin, buf, max_size);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,17 +85,16 @@ YOSYS_NAMESPACE_END
 | 
				
			||||||
// 	result = readsome(*extra->lexin, buf, max_size)
 | 
					// 	result = readsome(*extra->lexin, buf, max_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define YY_USER_ACTION \
 | 
					#define YY_USER_ACTION \
 | 
				
			||||||
		real_loc.begin = real_loc.end; \
 | 
							out_loc.begin = out_loc.end; \
 | 
				
			||||||
		for(int i = 0; YYText()[i] != '\0'; ++i){ \
 | 
							for(int i = 0; YYText()[i] != '\0'; ++i){ \
 | 
				
			||||||
				if(YYText()[i] == '\n') { \
 | 
									if(YYText()[i] == '\n') { \
 | 
				
			||||||
						real_loc.end.line++; \
 | 
											out_loc.end.line++; \
 | 
				
			||||||
						real_loc.end.column = 1; \
 | 
											out_loc.end.column = 1; \
 | 
				
			||||||
				} \
 | 
									} \
 | 
				
			||||||
				else { \
 | 
									else { \
 | 
				
			||||||
						real_loc.end.column++; \
 | 
											out_loc.end.column++; \
 | 
				
			||||||
				} \
 | 
									} \
 | 
				
			||||||
		} \
 | 
							}
 | 
				
			||||||
		out_loc = real_loc;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define YY_BREAK \
 | 
					#define YY_BREAK \
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
| 
						 | 
					@ -183,7 +182,6 @@ TIME_SCALE_SUFFIX [munpf]?s
 | 
				
			||||||
		current_filename = current_filename.substr(0, current_filename.size()-1);
 | 
							current_filename = current_filename.substr(0, current_filename.size()-1);
 | 
				
			||||||
	yylineno = (0);
 | 
						yylineno = (0);
 | 
				
			||||||
	out_loc.begin.line = out_loc.end.line = 0;
 | 
						out_loc.begin.line = out_loc.end.line = 0;
 | 
				
			||||||
	real_loc.begin.line = real_loc.end.line = 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_pop"[^\n]*\n {
 | 
					<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_pop"[^\n]*\n {
 | 
				
			||||||
| 
						 | 
					@ -191,7 +189,6 @@ TIME_SCALE_SUFFIX [munpf]?s
 | 
				
			||||||
	fn_stack.pop_back();
 | 
						fn_stack.pop_back();
 | 
				
			||||||
	yylineno = (ln_stack.back());
 | 
						yylineno = (ln_stack.back());
 | 
				
			||||||
	out_loc.begin.line = out_loc.end.line = ln_stack.back();
 | 
						out_loc.begin.line = out_loc.end.line = ln_stack.back();
 | 
				
			||||||
	real_loc.begin.line = real_loc.end.line = ln_stack.back();
 | 
					 | 
				
			||||||
	ln_stack.pop_back();
 | 
						ln_stack.pop_back();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,7 +197,6 @@ TIME_SCALE_SUFFIX [munpf]?s
 | 
				
			||||||
	while (*p == ' ' || *p == '\t') p++;
 | 
						while (*p == ' ' || *p == '\t') p++;
 | 
				
			||||||
	yylineno = (atoi(p));
 | 
						yylineno = (atoi(p));
 | 
				
			||||||
	out_loc.begin.line = out_loc.end.line = atoi(p);
 | 
						out_loc.begin.line = out_loc.end.line = atoi(p);
 | 
				
			||||||
	real_loc.begin.line = real_loc.end.line = atoi(p);
 | 
					 | 
				
			||||||
	while (*p && *p != ' ' && *p != '\t') p++;
 | 
						while (*p && *p != ' ' && *p != '\t') p++;
 | 
				
			||||||
	while (*p == ' ' || *p == '\t') p++;
 | 
						while (*p == ' ' || *p == '\t') p++;
 | 
				
			||||||
	const char *q = *p ? p + 1 : p;
 | 
						const char *q = *p ? p + 1 : p;
 | 
				
			||||||
| 
						 | 
					@ -226,14 +222,14 @@ TIME_SCALE_SUFFIX [munpf]?s
 | 
				
			||||||
	else if (!strcmp(p, "wire"))
 | 
						else if (!strcmp(p, "wire"))
 | 
				
			||||||
		extra->default_nettype_wire = true;
 | 
							extra->default_nettype_wire = true;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		err("Unsupported default nettype: %s", p);
 | 
							err_at_loc(out_loc, "Unsupported default nettype: %s", p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"`protect"[^\n]* /* ignore `protect*/
 | 
					"`protect"[^\n]* /* ignore `protect*/
 | 
				
			||||||
"`endprotect"[^\n]* /* ignore `endprotect*/
 | 
					"`endprotect"[^\n]* /* ignore `endprotect*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"`"[a-zA-Z_$][a-zA-Z0-9_$]* {
 | 
					"`"[a-zA-Z_$][a-zA-Z0-9_$]* {
 | 
				
			||||||
	err("Unimplemented compiler directive or undefined macro %s.", YYText());
 | 
						err_at_loc(out_loc, "Unimplemented compiler directive or undefined macro %s.", YYText());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"module"       { return parser::make_TOK_MODULE(out_loc); }
 | 
					"module"       { return parser::make_TOK_MODULE(out_loc); }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%code requires {
 | 
					%code requires {
 | 
				
			||||||
	#include "kernel/yosys_common.h"
 | 
						#include "kernel/yosys_common.h"
 | 
				
			||||||
	// #include "frontends/verilog/verilog_lexer.h"
 | 
						#include "frontends/verilog/verilog_error.h"
 | 
				
			||||||
	// start requires
 | 
						// start requires
 | 
				
			||||||
	YOSYS_NAMESPACE_BEGIN
 | 
						YOSYS_NAMESPACE_BEGIN
 | 
				
			||||||
	namespace VERILOG_FRONTEND {
 | 
						namespace VERILOG_FRONTEND {
 | 
				
			||||||
| 
						 | 
					@ -157,8 +157,7 @@
 | 
				
			||||||
		static ConstParser make_ConstParser_here(parser::location_type flex_loc) {
 | 
							static ConstParser make_ConstParser_here(parser::location_type flex_loc) {
 | 
				
			||||||
			AstSrcLocType loc;
 | 
								AstSrcLocType loc;
 | 
				
			||||||
			SET_LOC(loc, flex_loc, flex_loc);
 | 
								SET_LOC(loc, flex_loc, flex_loc);
 | 
				
			||||||
			std::optional<std::string> filename = flex_loc.begin.filename ? std::make_optional(*(flex_loc.begin.filename)) : std::nullopt;
 | 
								ConstParser p{loc};
 | 
				
			||||||
			ConstParser p{filename, loc};
 | 
					 | 
				
			||||||
			return p;
 | 
								return p;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		static void append_attr(AstNode *ast, dict<IdString, std::unique_ptr<AstNode>> *al)
 | 
							static void append_attr(AstNode *ast, dict<IdString, std::unique_ptr<AstNode>> *al)
 | 
				
			||||||
| 
						 | 
					@ -244,17 +243,6 @@
 | 
				
			||||||
			node->children.push_back(std::move(rangeNode));
 | 
								node->children.push_back(std::move(rangeNode));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[[noreturn]]
 | 
					 | 
				
			||||||
		extern void verr_at(std::string filename, int begin_line, char const *fmt, va_list ap);
 | 
					 | 
				
			||||||
		[[noreturn]]
 | 
					 | 
				
			||||||
		static void err_at_loc(frontend_verilog_yy::parser::location_type loc, char const *fmt, ...)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			va_list args;
 | 
					 | 
				
			||||||
			va_start(args, fmt);
 | 
					 | 
				
			||||||
			verr_at(AST::current_filename, loc.begin.line, fmt, args);
 | 
					 | 
				
			||||||
			va_end(args);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		static void checkLabelsMatch(const frontend_verilog_yy::parser::location_type& loc, const char *element, const std::string* before, const std::string *after)
 | 
							static void checkLabelsMatch(const frontend_verilog_yy::parser::location_type& loc, const char *element, const std::string* before, const std::string *after)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (!before && after)
 | 
								if (!before && after)
 | 
				
			||||||
| 
						 | 
					@ -731,7 +719,7 @@ module:
 | 
				
			||||||
		append_attr(mod, $1);
 | 
							append_attr(mod, $1);
 | 
				
			||||||
	} module_para_opt module_args_opt TOK_SEMICOL module_body TOK_ENDMODULE opt_label {
 | 
						} module_para_opt module_args_opt TOK_SEMICOL module_body TOK_ENDMODULE opt_label {
 | 
				
			||||||
		if (extra->port_stubs.size() != 0)
 | 
							if (extra->port_stubs.size() != 0)
 | 
				
			||||||
			lexer->err("Missing details for module port `%s'.",
 | 
								err_at_loc(@7, "Missing details for module port `%s'.",
 | 
				
			||||||
					extra->port_stubs.begin()->first.c_str());
 | 
										extra->port_stubs.begin()->first.c_str());
 | 
				
			||||||
		SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @$);
 | 
							SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @$);
 | 
				
			||||||
		extra->ast_stack.pop_back();
 | 
							extra->ast_stack.pop_back();
 | 
				
			||||||
| 
						 | 
					@ -785,7 +773,7 @@ module_arg_opt_assignment:
 | 
				
			||||||
					extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(AST_ASSIGN, std::move(wire), std::move($2)));
 | 
										extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(AST_ASSIGN, std::move(wire), std::move($2)));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
			lexer->err("SystemVerilog interface in module port list cannot have a default value.");
 | 
								err_at_loc(@2, "SystemVerilog interface in module port list cannot have a default value.");
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	%empty;
 | 
						%empty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -799,7 +787,7 @@ module_arg:
 | 
				
			||||||
			extra->ast_stack.back()->children.push_back(std::move(node));
 | 
								extra->ast_stack.back()->children.push_back(std::move(node));
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			if (extra->port_stubs.count(*$1) != 0)
 | 
								if (extra->port_stubs.count(*$1) != 0)
 | 
				
			||||||
				lexer->err("Duplicate module port `%s'.", $1->c_str());
 | 
									err_at_loc(@1, "Duplicate module port `%s'.", $1->c_str());
 | 
				
			||||||
			extra->port_stubs[*$1] = ++extra->port_counter;
 | 
								extra->port_stubs[*$1] = ++extra->port_counter;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} module_arg_opt_assignment |
 | 
						} module_arg_opt_assignment |
 | 
				
			||||||
| 
						 | 
					@ -809,7 +797,7 @@ module_arg:
 | 
				
			||||||
		extra->astbuf1->children[0]->str = *$1;
 | 
							extra->astbuf1->children[0]->str = *$1;
 | 
				
			||||||
	} TOK_ID {  /* SV interfaces */
 | 
						} TOK_ID {  /* SV interfaces */
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str());
 | 
								err_at_loc(@3, "Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str());
 | 
				
			||||||
		extra->astbuf2 = extra->astbuf1->clone(); // really only needed if multiple instances of same type.
 | 
							extra->astbuf2 = extra->astbuf1->clone(); // really only needed if multiple instances of same type.
 | 
				
			||||||
		extra->astbuf2->str = *$3;
 | 
							extra->astbuf2->str = *$3;
 | 
				
			||||||
		extra->astbuf2->port_id = ++extra->port_counter;
 | 
							extra->astbuf2->port_id = ++extra->port_counter;
 | 
				
			||||||
| 
						 | 
					@ -824,9 +812,9 @@ module_arg:
 | 
				
			||||||
		if (range != nullptr)
 | 
							if (range != nullptr)
 | 
				
			||||||
			node->children.push_back(std::move(range));
 | 
								node->children.push_back(std::move(range));
 | 
				
			||||||
		if (!node->is_input && !node->is_output)
 | 
							if (!node->is_input && !node->is_output)
 | 
				
			||||||
			lexer->err("Module port `%s' is neither input nor output.", $4->c_str());
 | 
								err_at_loc(@4, "Module port `%s' is neither input nor output.", $4->c_str());
 | 
				
			||||||
		if (node->is_reg && node->is_input && !node->is_output && !mode->sv)
 | 
							if (node->is_reg && node->is_input && !node->is_output && !mode->sv)
 | 
				
			||||||
			lexer->err("Input port `%s' is declared as register.", $4->c_str());
 | 
								err_at_loc(@4, "Input port `%s' is declared as register.", $4->c_str());
 | 
				
			||||||
		append_attr(node.get(), $1);
 | 
							append_attr(node.get(), $1);
 | 
				
			||||||
		extra->ast_stack.back()->children.push_back(std::move(node));
 | 
							extra->ast_stack.back()->children.push_back(std::move(node));
 | 
				
			||||||
	} module_arg_opt_assignment |
 | 
						} module_arg_opt_assignment |
 | 
				
			||||||
| 
						 | 
					@ -867,7 +855,7 @@ interface:
 | 
				
			||||||
		intf->str = *$3;
 | 
							intf->str = *$3;
 | 
				
			||||||
	} module_para_opt module_args_opt TOK_SEMICOL interface_body TOK_ENDINTERFACE {
 | 
						} module_para_opt module_args_opt TOK_SEMICOL interface_body TOK_ENDINTERFACE {
 | 
				
			||||||
		if (extra->port_stubs.size() != 0)
 | 
							if (extra->port_stubs.size() != 0)
 | 
				
			||||||
			lexer->err("Missing details for module port `%s'.",
 | 
								err_at_loc(@6, "Missing details for module port `%s'.",
 | 
				
			||||||
				extra->port_stubs.begin()->first.c_str());
 | 
									extra->port_stubs.begin()->first.c_str());
 | 
				
			||||||
		extra->ast_stack.pop_back();
 | 
							extra->ast_stack.pop_back();
 | 
				
			||||||
		log_assert(extra->ast_stack.size() == 1);
 | 
							log_assert(extra->ast_stack.size() == 1);
 | 
				
			||||||
| 
						 | 
					@ -1284,7 +1272,7 @@ task_func_port:
 | 
				
			||||||
		extra->astbuf2 = checkRange(extra->astbuf1.get(), std::move($3));
 | 
							extra->astbuf2 = checkRange(extra->astbuf1.get(), std::move($3));
 | 
				
			||||||
		if (!extra->astbuf1->is_input && !extra->astbuf1->is_output) {
 | 
							if (!extra->astbuf1->is_input && !extra->astbuf1->is_output) {
 | 
				
			||||||
			if (!mode->sv)
 | 
								if (!mode->sv)
 | 
				
			||||||
				lexer->err("task/function argument direction missing");
 | 
									err_at_loc(@2, "task/function argument direction missing");
 | 
				
			||||||
			extra->astbuf1->is_input = prev_was_input;
 | 
								extra->astbuf1->is_input = prev_was_input;
 | 
				
			||||||
			extra->astbuf1->is_output = prev_was_output;
 | 
								extra->astbuf1->is_output = prev_was_output;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1292,7 +1280,7 @@ task_func_port:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!extra->astbuf1) {
 | 
							if (!extra->astbuf1) {
 | 
				
			||||||
			if (!mode->sv)
 | 
								if (!mode->sv)
 | 
				
			||||||
				lexer->err("task/function argument direction missing");
 | 
									err_at_loc(@$, "task/function argument direction missing");
 | 
				
			||||||
			extra->albuf = new dict<IdString, std::unique_ptr<AstNode>>;
 | 
								extra->albuf = new dict<IdString, std::unique_ptr<AstNode>>;
 | 
				
			||||||
			extra->astbuf1 = std::make_unique<AstNode>(AST_WIRE);
 | 
								extra->astbuf1 = std::make_unique<AstNode>(AST_WIRE);
 | 
				
			||||||
			extra->current_wire_rand = false;
 | 
								extra->current_wire_rand = false;
 | 
				
			||||||
| 
						 | 
					@ -1325,7 +1313,7 @@ specify_item:
 | 
				
			||||||
		specify_rise_fall_ptr_t timing = std::move($9);
 | 
							specify_rise_fall_ptr_t timing = std::move($9);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (specify_edge != 0 && target->dat == nullptr)
 | 
							if (specify_edge != 0 && target->dat == nullptr)
 | 
				
			||||||
			lexer->err("Found specify edge but no data spec.\n");
 | 
								err_at_loc(@3, "Found specify edge but no data spec.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto cell_owned = std::make_unique<AstNode>(AST_CELL);
 | 
							auto cell_owned = std::make_unique<AstNode>(AST_CELL);
 | 
				
			||||||
		auto cell = cell_owned.get();
 | 
							auto cell = cell_owned.get();
 | 
				
			||||||
| 
						 | 
					@ -1400,7 +1388,7 @@ specify_item:
 | 
				
			||||||
	TOK_ID TOK_LPAREN specify_edge expr specify_condition TOK_COMMA specify_edge expr specify_condition TOK_COMMA specify_triple specify_opt_triple TOK_RPAREN TOK_SEMICOL {
 | 
						TOK_ID TOK_LPAREN specify_edge expr specify_condition TOK_COMMA specify_edge expr specify_condition TOK_COMMA specify_triple specify_opt_triple TOK_RPAREN TOK_SEMICOL {
 | 
				
			||||||
		if (*$1 != "$setup" && *$1 != "$hold" && *$1 != "$setuphold" && *$1 != "$removal" && *$1 != "$recovery" &&
 | 
							if (*$1 != "$setup" && *$1 != "$hold" && *$1 != "$setuphold" && *$1 != "$removal" && *$1 != "$recovery" &&
 | 
				
			||||||
				*$1 != "$recrem" && *$1 != "$skew" && *$1 != "$timeskew" && *$1 != "$fullskew" && *$1 != "$nochange")
 | 
									*$1 != "$recrem" && *$1 != "$skew" && *$1 != "$timeskew" && *$1 != "$fullskew" && *$1 != "$nochange")
 | 
				
			||||||
			lexer->err("Unsupported specify rule type: %s\n", $1->c_str());
 | 
								err_at_loc(@1, "Unsupported specify rule type: %s\n", $1->c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto src_pen = AstNode::mkconst_int($3 != 0, false, 1);
 | 
							auto src_pen = AstNode::mkconst_int($3 != 0, false, 1);
 | 
				
			||||||
		auto src_pol = AstNode::mkconst_int($3 == 'p', false, 1);
 | 
							auto src_pol = AstNode::mkconst_int($3 == 'p', false, 1);
 | 
				
			||||||
| 
						 | 
					@ -1766,10 +1754,10 @@ single_param_decl:
 | 
				
			||||||
		AstNode *decl = extra->ast_stack.back()->children.back().get();
 | 
							AstNode *decl = extra->ast_stack.back()->children.back().get();
 | 
				
			||||||
		if (decl->type != AST_PARAMETER) {
 | 
							if (decl->type != AST_PARAMETER) {
 | 
				
			||||||
			log_assert(decl->type == AST_LOCALPARAM);
 | 
								log_assert(decl->type == AST_LOCALPARAM);
 | 
				
			||||||
			lexer->err("localparam initialization is missing!");
 | 
								err_at_loc(@1, "localparam initialization is missing!");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("Parameter defaults can only be omitted in SystemVerilog mode!");
 | 
								err_at_loc(@1, "Parameter defaults can only be omitted in SystemVerilog mode!");
 | 
				
			||||||
		decl->children.erase(decl->children.begin());
 | 
							decl->children.erase(decl->children.begin());
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1778,7 +1766,7 @@ single_param_decl_ident:
 | 
				
			||||||
		std::unique_ptr<AstNode> node_owned;
 | 
							std::unique_ptr<AstNode> node_owned;
 | 
				
			||||||
		if (extra->astbuf1 == nullptr) {
 | 
							if (extra->astbuf1 == nullptr) {
 | 
				
			||||||
			if (!mode->sv)
 | 
								if (!mode->sv)
 | 
				
			||||||
				lexer->err("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword");
 | 
									err_at_loc(@1, "In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword");
 | 
				
			||||||
			node_owned = std::make_unique<AstNode>(AST_PARAMETER);
 | 
								node_owned = std::make_unique<AstNode>(AST_PARAMETER);
 | 
				
			||||||
			node_owned->children.push_back(AstNode::mkconst_int(0, true));
 | 
								node_owned->children.push_back(AstNode::mkconst_int(0, true));
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
| 
						 | 
					@ -1929,7 +1917,7 @@ struct_body: opt_packed TOK_LCURL struct_member_list TOK_RCURL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
opt_packed:
 | 
					opt_packed:
 | 
				
			||||||
	TOK_PACKED opt_signed_struct |
 | 
						TOK_PACKED opt_signed_struct |
 | 
				
			||||||
	%empty { lexer->err("Only PACKED supported at this time"); };
 | 
						%empty { err_at_loc(@$, "Only PACKED supported at this time"); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
opt_signed_struct:
 | 
					opt_signed_struct:
 | 
				
			||||||
	  TOK_SIGNED		{ extra->astbuf2->is_signed = true; }
 | 
						  TOK_SIGNED		{ extra->astbuf2->is_signed = true; }
 | 
				
			||||||
| 
						 | 
					@ -2114,7 +2102,7 @@ wire_name_and_opt_assign:
 | 
				
			||||||
wire_name:
 | 
					wire_name:
 | 
				
			||||||
	TOK_ID range_or_multirange {
 | 
						TOK_ID range_or_multirange {
 | 
				
			||||||
		if (extra->astbuf1 == nullptr)
 | 
							if (extra->astbuf1 == nullptr)
 | 
				
			||||||
			lexer->err("Internal error - should not happen - no AST_WIRE node.");
 | 
								err_at_loc(@1, "Internal error - should not happen - no AST_WIRE node.");
 | 
				
			||||||
		auto node = extra->astbuf1->clone();
 | 
							auto node = extra->astbuf1->clone();
 | 
				
			||||||
		node->str = *$1;
 | 
							node->str = *$1;
 | 
				
			||||||
		append_attr_clone(node.get(), extra->albuf);
 | 
							append_attr_clone(node.get(), extra->albuf);
 | 
				
			||||||
| 
						 | 
					@ -2122,7 +2110,7 @@ wire_name:
 | 
				
			||||||
			node->children.push_back(extra->astbuf2->clone());
 | 
								node->children.push_back(extra->astbuf2->clone());
 | 
				
			||||||
		if ($2 != nullptr) {
 | 
							if ($2 != nullptr) {
 | 
				
			||||||
			if (node->is_input || node->is_output)
 | 
								if (node->is_input || node->is_output)
 | 
				
			||||||
				lexer->err("input/output/inout ports cannot have unpacked dimensions.");
 | 
									err_at_loc(@2, "input/output/inout ports cannot have unpacked dimensions.");
 | 
				
			||||||
			if (!extra->astbuf2 && !node->is_custom_type) {
 | 
								if (!extra->astbuf2 && !node->is_custom_type) {
 | 
				
			||||||
				addRange(node.get(), 0, 0, false);
 | 
									addRange(node.get(), 0, 0, false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -2133,21 +2121,21 @@ wire_name:
 | 
				
			||||||
				node->port_id = extra->current_function_or_task_port_id++;
 | 
									node->port_id = extra->current_function_or_task_port_id++;
 | 
				
			||||||
		} else if (extra->ast_stack.back()->type == AST_GENBLOCK) {
 | 
							} else if (extra->ast_stack.back()->type == AST_GENBLOCK) {
 | 
				
			||||||
			if (node->is_input || node->is_output)
 | 
								if (node->is_input || node->is_output)
 | 
				
			||||||
				lexer->err("Cannot declare module port `%s' within a generate block.", $1->c_str());
 | 
									err_at_loc(@1, "Cannot declare module port `%s' within a generate block.", $1->c_str());
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			if (extra->do_not_require_port_stubs && (node->is_input || node->is_output) && extra->port_stubs.count(*$1) == 0) {
 | 
								if (extra->do_not_require_port_stubs && (node->is_input || node->is_output) && extra->port_stubs.count(*$1) == 0) {
 | 
				
			||||||
				extra->port_stubs[*$1] = ++extra->port_counter;
 | 
									extra->port_stubs[*$1] = ++extra->port_counter;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (extra->port_stubs.count(*$1) != 0) {
 | 
								if (extra->port_stubs.count(*$1) != 0) {
 | 
				
			||||||
				if (!node->is_input && !node->is_output)
 | 
									if (!node->is_input && !node->is_output)
 | 
				
			||||||
					lexer->err("Module port `%s' is neither input nor output.", $1->c_str());
 | 
										err_at_loc(@1, "Module port `%s' is neither input nor output.", $1->c_str());
 | 
				
			||||||
				if (node->is_reg && node->is_input && !node->is_output && !mode->sv)
 | 
									if (node->is_reg && node->is_input && !node->is_output && !mode->sv)
 | 
				
			||||||
					lexer->err("Input port `%s' is declared as register.", $1->c_str());
 | 
										err_at_loc(@1, "Input port `%s' is declared as register.", $1->c_str());
 | 
				
			||||||
				node->port_id = extra->port_stubs[*$1];
 | 
									node->port_id = extra->port_stubs[*$1];
 | 
				
			||||||
				extra->port_stubs.erase(*$1);
 | 
									extra->port_stubs.erase(*$1);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				if (node->is_input || node->is_output)
 | 
									if (node->is_input || node->is_output)
 | 
				
			||||||
					lexer->err("Module port `%s' is not declared in module header.", $1->c_str());
 | 
										err_at_loc(@1, "Module port `%s' is not declared in module header.", $1->c_str());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		//FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column...
 | 
							//FIXME: for some reason, TOK_ID has a location which always points to one column *after* the real last column...
 | 
				
			||||||
| 
						 | 
					@ -2169,7 +2157,7 @@ assign_expr:
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type_name: TOK_ID { $$ = std::move($1); } // first time seen
 | 
					type_name: TOK_ID { $$ = std::move($1); } // first time seen
 | 
				
			||||||
	 | TOK_USER_TYPE	{ if (extra->isInLocalScope($1.get())) lexer->err("Duplicate declaration of TYPEDEF '%s'", $1->c_str()+1); $$ = std::move($1); }
 | 
						 | TOK_USER_TYPE	{ if (extra->isInLocalScope($1.get())) err_at_loc(@1, "Duplicate declaration of TYPEDEF '%s'", $1->c_str()+1); $$ = std::move($1); }
 | 
				
			||||||
	 ;
 | 
						 ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef_decl:
 | 
					typedef_decl:
 | 
				
			||||||
| 
						 | 
					@ -2347,7 +2335,7 @@ cell_port_list:
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (has_positional_args && has_named_args)
 | 
							if (has_positional_args && has_named_args)
 | 
				
			||||||
			lexer->err("Mix of positional and named cell ports.");
 | 
								err_at_loc(@1, "Mix of positional and named cell ports.");
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cell_port_list_rules:
 | 
					cell_port_list_rules:
 | 
				
			||||||
| 
						 | 
					@ -2388,7 +2376,7 @@ cell_port:
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	attr TOK_WILDCARD_CONNECT {
 | 
						attr TOK_WILDCARD_CONNECT {
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("Wildcard port connections are only supported in SystemVerilog mode.");
 | 
								err_at_loc(@2, "Wildcard port connections are only supported in SystemVerilog mode.");
 | 
				
			||||||
		extra->cell_hack->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false);
 | 
							extra->cell_hack->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false);
 | 
				
			||||||
		free_attr($1);
 | 
							free_attr($1);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
| 
						 | 
					@ -2727,11 +2715,11 @@ for_initialization:
 | 
				
			||||||
		extra->ast_stack.back()->children.push_back(std::move(node));
 | 
							extra->ast_stack.back()->children.push_back(std::move(node));
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	non_io_wire_type range TOK_ID {
 | 
						non_io_wire_type range TOK_ID {
 | 
				
			||||||
		lexer->err("For loop variable declaration is missing initialization!");
 | 
							err_at_loc(@3, "For loop variable declaration is missing initialization!");
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	non_io_wire_type range TOK_ID TOK_EQ expr {
 | 
						non_io_wire_type range TOK_ID TOK_EQ expr {
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("For loop inline variable declaration is only supported in SystemVerilog mode!");
 | 
								err_at_loc(@4, "For loop inline variable declaration is only supported in SystemVerilog mode!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// loop variable declaration
 | 
							// loop variable declaration
 | 
				
			||||||
		auto wire = std::move($1);
 | 
							auto wire = std::move($1);
 | 
				
			||||||
| 
						 | 
					@ -2915,21 +2903,21 @@ if_attr:
 | 
				
			||||||
	attr TOK_UNIQUE0 {
 | 
						attr TOK_UNIQUE0 {
 | 
				
			||||||
		AstNode *context = extra->ast_stack.back();
 | 
							AstNode *context = extra->ast_stack.back();
 | 
				
			||||||
		if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
 | 
							if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
 | 
				
			||||||
			lexer->err("unique0 keyword cannot be used for 'else if' branch.");
 | 
								err_at_loc(@2, "unique0 keyword cannot be used for 'else if' branch.");
 | 
				
			||||||
		(*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
 | 
							(*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
 | 
				
			||||||
		$$ = $1;
 | 
							$$ = $1;
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	attr TOK_PRIORITY {
 | 
						attr TOK_PRIORITY {
 | 
				
			||||||
		AstNode *context = extra->ast_stack.back();
 | 
							AstNode *context = extra->ast_stack.back();
 | 
				
			||||||
		if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
 | 
							if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
 | 
				
			||||||
			lexer->err("priority keyword cannot be used for 'else if' branch.");
 | 
								err_at_loc(@2, "priority keyword cannot be used for 'else if' branch.");
 | 
				
			||||||
		(*$1)[ID::full_case] = AstNode::mkconst_int(1, false);
 | 
							(*$1)[ID::full_case] = AstNode::mkconst_int(1, false);
 | 
				
			||||||
		$$ = $1;
 | 
							$$ = $1;
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	attr TOK_UNIQUE {
 | 
						attr TOK_UNIQUE {
 | 
				
			||||||
		AstNode *context = extra->ast_stack.back();
 | 
							AstNode *context = extra->ast_stack.back();
 | 
				
			||||||
		if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
 | 
							if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
 | 
				
			||||||
			lexer->err("unique keyword cannot be used for 'else if' branch.");
 | 
								err_at_loc(@2, "unique keyword cannot be used for 'else if' branch.");
 | 
				
			||||||
		(*$1)[ID::full_case] = AstNode::mkconst_int(1, false);
 | 
							(*$1)[ID::full_case] = AstNode::mkconst_int(1, false);
 | 
				
			||||||
		(*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
 | 
							(*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false);
 | 
				
			||||||
		$$ = $1;
 | 
							$$ = $1;
 | 
				
			||||||
| 
						 | 
					@ -3127,11 +3115,11 @@ genvar_identifier:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
genvar_initialization:
 | 
					genvar_initialization:
 | 
				
			||||||
	TOK_GENVAR genvar_identifier {
 | 
						TOK_GENVAR genvar_identifier {
 | 
				
			||||||
		lexer->err("Generate for loop variable declaration is missing initialization!");
 | 
							err_at_loc(@2, "Generate for loop variable declaration is missing initialization!");
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	TOK_GENVAR genvar_identifier TOK_EQ expr {
 | 
						TOK_GENVAR genvar_identifier TOK_EQ expr {
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("Generate for loop inline variable declaration is only supported in SystemVerilog mode!");
 | 
								err_at_loc(@3, "Generate for loop inline variable declaration is only supported in SystemVerilog mode!");
 | 
				
			||||||
		AstNode* node = extra->saveChild(std::make_unique<AstNode>(AST_GENVAR));
 | 
							AstNode* node = extra->saveChild(std::make_unique<AstNode>(AST_GENVAR));
 | 
				
			||||||
		node->is_reg = true;
 | 
							node->is_reg = true;
 | 
				
			||||||
		node->is_signed = true;
 | 
							node->is_signed = true;
 | 
				
			||||||
| 
						 | 
					@ -3233,7 +3221,7 @@ basic_expr:
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	TOK_LPAREN expr TOK_RPAREN integral_number {
 | 
						TOK_LPAREN expr TOK_RPAREN integral_number {
 | 
				
			||||||
		if ($4->compare(0, 1, "'") != 0)
 | 
							if ($4->compare(0, 1, "'") != 0)
 | 
				
			||||||
			lexer->err("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
 | 
								err_at_loc(@4, "Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
 | 
				
			||||||
		auto p = make_ConstParser_here(@4);
 | 
							auto p = make_ConstParser_here(@4);
 | 
				
			||||||
		auto val = p.const2ast(*$4, extra->case_type_stack.size() == 0 ? 0 : extra->case_type_stack.back(), !mode->lib);
 | 
							auto val = p.const2ast(*$4, extra->case_type_stack.size() == 0 ? 0 : extra->case_type_stack.back(), !mode->lib);
 | 
				
			||||||
		if (val == nullptr)
 | 
							if (val == nullptr)
 | 
				
			||||||
| 
						 | 
					@ -3242,7 +3230,7 @@ basic_expr:
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	hierarchical_id integral_number {
 | 
						hierarchical_id integral_number {
 | 
				
			||||||
		if ($2->compare(0, 1, "'") != 0)
 | 
							if ($2->compare(0, 1, "'") != 0)
 | 
				
			||||||
			lexer->err("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
 | 
								err_at_loc(@2, "Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
 | 
				
			||||||
		auto bits = std::make_unique<AstNode>(AST_IDENTIFIER);
 | 
							auto bits = std::make_unique<AstNode>(AST_IDENTIFIER);
 | 
				
			||||||
		bits->str = *$1;
 | 
							bits->str = *$1;
 | 
				
			||||||
		SET_AST_NODE_LOC(bits.get(), @1, @1);
 | 
							SET_AST_NODE_LOC(bits.get(), @1, @1);
 | 
				
			||||||
| 
						 | 
					@ -3491,25 +3479,25 @@ basic_expr:
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	TOK_SIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN {
 | 
						TOK_SIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN {
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("Static cast is only supported in SystemVerilog mode.");
 | 
								err_at_loc(@2, "Static cast is only supported in SystemVerilog mode.");
 | 
				
			||||||
		$$ = std::make_unique<AstNode>(AST_TO_SIGNED, std::move($4));
 | 
							$$ = std::make_unique<AstNode>(AST_TO_SIGNED, std::move($4));
 | 
				
			||||||
		SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
							SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	TOK_UNSIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN {
 | 
						TOK_UNSIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN {
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("Static cast is only supported in SystemVerilog mode.");
 | 
								err_at_loc(@2, "Static cast is only supported in SystemVerilog mode.");
 | 
				
			||||||
		$$ = std::make_unique<AstNode>(AST_TO_UNSIGNED, std::move($4));
 | 
							$$ = std::make_unique<AstNode>(AST_TO_UNSIGNED, std::move($4));
 | 
				
			||||||
		SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
							SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	basic_expr OP_CAST TOK_LPAREN expr TOK_RPAREN {
 | 
						basic_expr OP_CAST TOK_LPAREN expr TOK_RPAREN {
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("Static cast is only supported in SystemVerilog mode.");
 | 
								err_at_loc(@2, "Static cast is only supported in SystemVerilog mode.");
 | 
				
			||||||
		$$ = std::make_unique<AstNode>(AST_CAST_SIZE, std::move($1), std::move($4));
 | 
							$$ = std::make_unique<AstNode>(AST_CAST_SIZE, std::move($1), std::move($4));
 | 
				
			||||||
		SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
							SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
	typedef_base_type OP_CAST TOK_LPAREN expr TOK_RPAREN {
 | 
						typedef_base_type OP_CAST TOK_LPAREN expr TOK_RPAREN {
 | 
				
			||||||
		if (!mode->sv)
 | 
							if (!mode->sv)
 | 
				
			||||||
			lexer->err("Static cast is only supported in SystemVerilog mode.");
 | 
								err_at_loc(@2, "Static cast is only supported in SystemVerilog mode.");
 | 
				
			||||||
		$$ = std::make_unique<AstNode>(AST_CAST_SIZE, std::move($1), std::move($4));
 | 
							$$ = std::make_unique<AstNode>(AST_CAST_SIZE, std::move($1), std::move($4));
 | 
				
			||||||
		SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
							SET_AST_NODE_LOC($$.get(), @1, @4);
 | 
				
			||||||
	} |
 | 
						} |
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue